目录
部署并发布简单的应用
1.创建deployment
[root@master ~]# kubectl create deployment test-nginx --image=nginx
deployment.apps/test-nginx created
2.查看创建后的deployment
[root@master ~]# kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
test-nginx 1/1 1 1 38s
3.查看pod状态
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
test-nginx-59ffd87f5-mqvjq 1/1 Running 0 58s
testpod 1/1 Running 12 (24m ago) 24h
[root@master ~]# kubectl describe pod test-nginx-59ffd87f5-mqvjq
Name: test-nginx-59ffd87f5-mqvjq
Namespace: default
Priority: 0
Node: worker1/192.168.200.12
Start Time: Tue, 15 Nov 2022 22:08:29 -0500
Labels: app=test-nginx
pod-template-hash=59ffd87f5
Annotations: <none>
Status: Running
IP: 10.244.1.7
IPs:
IP: 10.244.1.7
Controlled By: ReplicaSet/test-nginx-59ffd87f5
Containers:
nginx:
Container ID: docker://9f66b66ff9cfe9511b8c248346f62ae872c16aca53d54003f345ab7df09e13a8
Image: nginx
Image ID: docker-pullable://nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Port: <none>
Host Port: <none>
State: Running
Started: Tue, 15 Nov 2022 22:08:53 -0500
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-l29hm (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-l29hm:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 103s default-scheduler Successfully assigned default/test-nginx-59ffd87f5-mqvjq to worker1
Normal Pulling 101s kubelet Pulling image "nginx"
Normal Pulled 79s kubelet Successfully pulled image "nginx" in 22.047909579s
Normal Created 79s kubelet Created container nginx
Normal Started 79s kubelet Started container nginx
[root@master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-nginx-59ffd87f5-mqvjq 1/1 Running 0 3m18s 10.244.1.7 worker1 <none> <none>
4.发布服务
K8S暴露服务的方式有三种:loadblancer nodeport ingress
[root@master ~]# kubectl expose deployment test-nginx --port=80 --type=NodePort
service/test-nginx exposed
[root@master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 6d
test-nginx NodePort 10.1.31.72 <none> 80:32465/TCP 14s
暴露服务之后可以使用“任意节点IP+暴露的端口进行访问”,:
5.Pod动态伸缩
[root@master ~]# kubectl scale deployment test-nginx --replicas=5 //增加pod副本数
deployment.apps/test-nginx scaled
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-nginx-59ffd87f5-7pjwk 1/1 Running 0 56s
test-nginx-59ffd87f5-8d229 1/1 Running 0 56s
test-nginx-59ffd87f5-ff4gg 1/1 Running 0 56s
test-nginx-59ffd87f5-mqvjq 1/1 Running 0 10m
test-nginx-59ffd87f5-nzft5 1/1 Running 0 56s
testpod 1/1 Running 12 (34m ago) 24h
[root@master ~]# kubectl scale deployment test-nginx --replicas=2 //设置副本的缩容
deployment.apps/test-nginx scaled
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-nginx-59ffd87f5-7pjwk 1/1 Running 0 117s
test-nginx-59ffd87f5-mqvjq 1/1 Running 0 11m
testpod 1/1 Running 12 (35m ago) 24h
[root@master ~]# kubectl autoscale deployment test-nginx --min=1 --max=10 //设置pod自动伸缩
horizontalpodautoscaler.autoscaling/test-nginx autoscaled
1.调度master节点
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready control-plane,master 6d21h v1.22.2
worker1 Ready <none> 6d20h v1.22.2
[root@master ~]# kubectl describe node master
......
Taints: node-role.kubernetes.io/master:NoSchedule
//处于安全性考虑,默认配置下的k8s集群不会将pod调度在master节点上
[root@master ~]# kubectl taint node master node-role.kubernetes.io/master- //将master作为调度节点使用
node/master untainted
[root@master ~]# kubectl describe node master //再次查看已经恢复master节点的调度角色
......
Taints: <none>
2.node节点的隔离与恢复
(1)隔离Node
为什么要隔离node?在硬件升级、维护的情况下,需要将某些node隔离。使用kubectl cordon <node_name>可以禁止pod调度在此节点上,在他上面运行的Pod不会去自动的停止,管理员需要手动的停止在该node上运行pod。
[root@master ~]# kubectl cordon worker1
node/worker1 cordoned
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready control-plane,master 6d21h v1.22.2
worker1 Ready,SchedulingDisabled <none> 6d20h v1.22.2
//查看node状态可以观察到在node状态中增加了一项SchedulingDisabled,对于后续创建的pod,系统将不会再向这个worker1节点进行调度
(2)恢复node
[root@master ~]# kubectl uncordon worker1
node/worker1 uncordoned
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready control-plane,master 6d21h v1.22.2
worker1 Ready <none> 6d20h v1.22.2
//可以看出node节点已经恢复调度,允许pod调度到该节点上
(3)驱逐node
通过kubectl drain <node_name>可以实现对node节点的驱逐,这条命令会删除该节点上的所有pod,并且在其他的node节点上重新启动。
3.node节点的扩容
为什么要进行node扩容?
在实际的生产系统中会经常遇到服务器容量不足的情况,这个时候就需要加入新的服务器,然后将应用系统进行水平扩展来完成对系统的扩容。
在k8s集群中对于新的node加入集群是非常简单的,可以在Node节点上安装docker、Kubelet和kube-proxy服务,然后将这两个启动参数中的master URL指定为当前k8s集群masyter地址,最后启动。Master节点在接受到了新的node注册之后,会自动地将它纳入当前的集群调度范围。
(1)准备新的节点,并且安装k8s所需的所有服务
安装过程省略,可以结合前面的文档进行操作
(2)启动k8s组件
[root@worker2 ~]# systemctl enable kubelet
[root@worker2 ~]# systemctl start kubelet
//此时启动不成功,后面加入集群后可以成功
(3)生成token
[root@master ~]# kubeadm token create --ttl 0
fphus0.pmi8894iwf30i202
//k8s默认的token有效期为24h,过期之后,该token不可用,登录到master节点获取一条永久有效的token
(4)获取hash值
[root@master ~]# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
9f59f022a74578f9803f875add7c2b4f7995888528ef376c49f9593e2bc9369e
(5)worker2加入集群
[root@worker2 ~]# kubeadm join 192.168.200.11:6443 --token fphus0.pmi8894iwf30i202 --discovery-token-ca-cert-hash sha256:9f59f022a74578f9803f875add7c2b4f7995888528ef376c49f9593e2bc9369e
//将上面获取到的token值和hash值使用命令加入到集群
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
(6)查看集群节点
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready control-plane,master 6d22h v1.22.2
worker1 Ready <none> 6d21h v1.22.2
worker2 Ready <none> 6m43s v1.22.2
控制器-pod管理
2.创建deployment
[root@master ~]# vi testdeployment.yaml
apiVersion: apps/v1 //k8s API稳定版本
kind: Deployment //创建的资源对象
metadata: //资源对象的元数据
name: testdeployment //资源的名称
spec: //具体资源的设置
replicas: 3 //表示在控制器下托管的pod需要保持的副本数量
selector: //用于定义一个或者多个标签,其形式为键值对。它对pod起筛选作用,会选择与标签定义相匹配的pod
matchLabels:
example: deploymentnginx
template: //pod模板
metadata:
labels:
example: deploymentnginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
[root@master ~]# kubectl apply -f testdeployment.yaml --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/testdeployment created
//--record参数,会把每次修改控制器时所使用的命令记录到备注字段中,以便在查看deployment控制器变更历史或进行回滚时可以辨别每次修改的内容
[root@master ~]# kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
testdeployment 3/3 3 3 116s
[root@master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
testdeployment-58779f7cd8-jwwtm 1/1 Running 0 3m9s 10.244.1.30 worker1 <none> <none>
testdeployment-58779f7cd8-m6q5g 1/1 Running 0 3m9s 10.244.1.31 worker1 <none> <none>
testdeployment-58779f7cd8-ssdrx 1/1 Running 0 3m9s 10.244.0.22 master <none> <none>
//在上面的案例中deployment会创建三个pod,每个pod后面都有两个有两个随机生成的字符串,用于表示各自的身份(例如58779f7cd8是replicaset随机生成的标识字符串,后面的jwwtm是pod随机表示字符串)
[root@master ~]# kubectl describe deployments testdeployment
Name: testdeployment
Namespace: default
CreationTimestamp: Sun, 20 Nov 2022 20:10:19 -0500
Labels: <none>
Annotations: deployment.kubernetes.io/revision: 1
kubernetes.io/change-cause: kubectl apply --filename=testdeployment.yaml --record=true
Selector: example=deploymentnginx
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: example=deploymentnginx
Containers:
nginx:
Image: nginx:1.7.9
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: testdeployment-58779f7cd8 (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 8m36s deployment-controller Scaled up replica set testdeployment-58779f7cd8 to 3
测试删除pod和node关机
[root@master ~]# kubectl delete pod testdeployment-58779f7cd8-jwwtm
pod "testdeployment-58779f7cd8-jwwtm" deleted
[root@master ~]# kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
test-nginx 2/2 2 2 4d22h
testdeployment 3/3 3 3 11m
//删除完毕之后等待一段时间之后会发现reay数量仍为3/3,这是因为deployment控制器启用了新的pod来维持replicas中设置的数量
//下面关闭worker1节点
[root@master ~]# kubectl get deployments //关闭机器之后,会发现控制器的ready数量已经变为1/3
NAME READY UP-TO-DATE AVAILABLE AGE
test-nginx 0/2 2 0 4d22h
testdeployment 1/3 3 1 17m
[root@master ~]# kubectl get pod //调度在worker1节点上的pod已经变为Terminating,但是过一段时间之后会发现有两个pod正在重新创建
NAME READY STATUS RESTARTS AGE
test-nginx-59ffd87f5-2g86v 0/1 ContainerCreating 0 4s
test-nginx-59ffd87f5-7pjwk 1/1 Terminating 2 (2d17h ago) 4d22h
test-nginx-59ffd87f5-mqvjq 1/1 Terminating 2 (2d17h ago) 4d22h
test-nginx-59ffd87f5-wzmt4 0/1 ContainerCreating 0 4s
testdeployment-58779f7cd8-m6q5g 1/1 Terminating 0 20m
testdeployment-58779f7cd8-qx2td 1/1 Terminating 0 9m25s
testdeployment-58779f7cd8-ssdrx 1/1 Running 0 20m
testdeployment-58779f7cd8-v7xbz 1/1 Running 0 4s
testdeployment-58779f7cd8-zddrr 1/1 Running 0 4s
testpod 1/1 Terminating 52 (2d17h ago) 5d22h
testpodforliveness 1/1 Terminating 16 (2d17h ago) 3d22h
testpodforreadiness 1/1 Terminating 3 (2d17h ago) 3d
[root@master ~]# kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
test-nginx 2/2 2 2 4d22h
testdeployment 3/3 3 3 22m
//deployment控制器保证在集群中部署的pod数量与配置中的pod数量保持一致,如果主机出现故障会自动的进行启动新的pod进行补充
Deployment控制器伸缩
1.Deployment控制器伸缩
假设现有的业务需求变更,需要将pod副本数设置为5。
[root@master ~]# vi testdeployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: testdeployment
spec:
replicas: 5 //将副本数量设置为5
......
[root@master ~]# kubectl apply -f testdeployment.yaml --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/testdeployment configured
//上面命令执行完毕后,会进入到pod创建的过程,等待pod创建完毕后,可以通过下面的命令查看状态
[root@master ~]# kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
testdeployment 5/5 5 5 47h
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
testdeployment-58779f7cd8-c492j 1/1 Running 0 116s
testdeployment-58779f7cd8-mt65r 1/1 Running 0 116s
testdeployment-58779f7cd8-ssdrx 1/1 Running 1 (21h ago) 47h
testdeployment-58779f7cd8-v7xbz 1/1 Running 1 (21h ago) 47h
testdeployment-58779f7cd8-zddrr 1/1 Running 1 (21h ago) 47h
//从以上结果可以发现pod数量也变成了5个,通过相同的方法,也可以减少pod副本的数量
2.Deployment控制器更新
Deployment控制器的更新有两种方法:
Recreate:所有现有的pod都会创建在新的pod之前被终止
RollingUpdate:表示以滚动更新的方式更新pod,并且可以设置maxUnavailable和maxSurge参数来控制滚动更新的过程
(1)Recreate方式
[root@master ~]# vi testdeployment2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: testdeployment
spec:
replicas: 5
selector:
matchLabels:
example: deploymentnginx
template:
metadata:
labels:
example: deploymentnginx
spec:
containers:
- name: nginx
image: nginx:1.8.1
ports:
- containerPort: 80
strategy:
type: Recreate
~
"testdeployment2.yaml" [New] 21L, 372C written
[root@master ~]# kubectl apply -f testdeployment2.yaml --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/testdeployment configured
[root@master ~]# kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
test-nginx 2/2 2 2 6d22h
testdeployment 5/5 5 5 2d
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
chinaskill-mall 5/5 Running 5 (21h ago) 46h
test-nginx-59ffd87f5-2g86v 1/1 Running 1 (21h ago) 47h
test-nginx-59ffd87f5-wzmt4 1/1 Running 1 (21h ago) 47h
testdeployment-5c4b8d64df-7z49v 1/1 Running 0 2m25s
testdeployment-5c4b8d64df-9mh7q 1/1 Running 0 2m25s
testdeployment-5c4b8d64df-mrptg 1/1 Running 0 2m25s
testdeployment-5c4b8d64df-nnkwl 1/1 Running 0 2m25s
testdeployment-5c4b8d64df-xnwkd 1/1 Running 0 2m25s
//在使用Recreate执行更新时,我们应用了新的模板文件后最开始会看到READY数量时0/5,AVAILABLE数量为0,UP-TO-DATE为0,表示没有一个pod执行更新,如果此时再去查询pod状态会发现之前的pod状态为Terminating,,稍等一段时间之后,我们会发现所有的pod都是可用的状态,并且deployment ready数量为5/5,UP-TO-DATE数量为5,表示更新了5个pod
[root@master ~]# kubectl describe pod testdeployment-5c4b8d64df-7z49v //随便找一个pod查看详细信息会发现我们的nginx镜像已经变为1.8.1版本
Name: testdeployment-5c4b8d64df-7z49v
Namespace: default
Priority: 0
Node: master/192.168.200.11
Start Time: Tue, 22 Nov 2022 20:17:21 -0500
Labels: example=deploymentnginx
pod-template-hash=5c4b8d64df
Annotations: <none>
Status: Running
IP: 10.244.0.40
IPs:
IP: 10.244.0.40
Controlled By: ReplicaSet/testdeployment-5c4b8d64df
Containers:
nginx:
Container ID: docker://611a648c2e7f8939ab62d291d7d6f334ac59e0e98e496a2f2c1b19384eb4ec77
Image: nginx:1.8.1
[root@master ~]# kubectl get rs -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
testdeployment-58779f7cd8 0 0 0 2d nginx nginx:1.7.9 example=deploymentnginx,pod-template-hash=58779f7cd8
testdeployment-5c4b8d64df 5 5 5 9m48s nginx nginx:1.8.1 example=deploymentnginx,pod-template-hash=5c4b8d64df
//此时再查看ReplicaSet控制器的变化情况,可以看到之前的1.7.9的版本已经停用,新的版本已经创建
(2)RollingUpdate(滚动更新)
这种更新方式会比较实用,是一种平滑的升级方式,不会中断整个pod集群提供的服务。
maxUnavailable:表示再更新的过程中能够进入不可用状态的pod的最大值或相对于总副本数的最大百分比
maxSurge:表示能够额外创建的pod数或相对于总副本数的百分比
[root@master ~]# vi testdeployment3.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: testdeployment
spec:
replicas: 3
selector:
matchLabels:
example: deploymentnginx
template:
metadata:
labels:
example: deploymentnginx
spec:
containers:
- name: nginx
image: nginx:1.9.0
ports:
- containerPort: 80
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1 //表示最多只允许一个pod不可用,所以会先终止掉一个pod,使另外两个pod处于运行状态
maxSurge: 0 //表示最多创建0个额外的副本,再更新的过程中有1个正在创建更新的pod和两个正在运行的旧pod,符合副本的数量为3和零个额外的副本
[root@master ~]# kubectl apply -f testdeployment3.yaml --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/testdeployment configured
[root@master ~]# kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
test-nginx 2/2 2 2 6d22h
testdeployment 3/3 3 3 2d
//在不同的时间段去执行上方的命令会发现Ready数量和UP-TO-DATE数量都会有变化,但是更新的时间不会过长
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
testdeployment-5c5458b87c-22hnc 1/1 Running 0 2m18s
testdeployment-5c5458b87c-45js4 1/1 Running 0 2m20s
testdeployment-5c5458b87c-fhlcw 1/1 Running 0 2m49s
//此时再执行查询pod命令会发现,拥有了新的三个pod
3.更新的暂停与恢复
假设现有的业务需要变动更新升级,计划将所有的副本nginx镜像都要升级到1.9.1的版本,此次升级不仅要平滑的过度,还要进行金丝雀发布,也就是说先确认其中的一个pod没有问题之后在进行剩余的更新。
完成上述内容可以以yaml文件的方式实现,但是比较复杂,我们可以采用简单的命令进行实现。
# kubectl rollout pause deploy [deployment name]
# kubectl rollout resume deploy [deployment name]
[root@master ~]# kubectl set image deploy testdeployment nginx=nginx:1.9.1 --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/testdeployment image updated
[root@master ~]# kubectl rollout pause deploy testdeployment
deployment.apps/testdeployment paused
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
testdeployment-5c5458b87c-22hnc 1/1 Running 0 61m
testdeployment-5c5458b87c-45js4 1/1 Running 0 61m
testdeployment-8587689fb6-bfcnp 1/1 Running 0 68s
//上面的两条命令会升级deployment中的nginx版本,但是紧接着执行暂停命令会使更新第一个pod时就停止了后续的操作
[root@master ~]# kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
testdeployment 3/3 1 3 2d1h
//上述可以发现ready和 AVAILABLE都为3,但是UP-TO-DATE为1,此时可以对新更新的pod进行验证,没有问题就可以继续让其他的pod更新
[root@master ~]# kubectl rollout resume deploy testdeployment //结束暂停
deployment.apps/testdeployment resumed
[root@master ~]# kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
test-nginx 2/2 2 2 6d23h
testdeployment 3/3 3 3 2d1h
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
testdeployment-8587689fb6-bfcnp 1/1 Running 0 8m
testdeployment-8587689fb6-hm8td 1/1 Running 0 41s
testdeployment-8587689fb6-rxsth 1/1 Running 0 42s
//上述命令可以发现所有的pod均更新完毕
Deployment控制器回滚
如果更新之后,发现pod有严重的问题,需要回滚到之前的版本,可以使用命令查看历史变更记录
[root@master ~]# kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
testdeployment 3/3 3 3 2d23h
[root@master ~]# kubectl rollout history deployment testdeployment
deployment.apps/testdeployment
REVISION CHANGE-CAUSE
1 kubectl apply --filename=testdeployment.yaml --record=true
2 kubectl apply --filename=testdeployment2.yaml --record=true
3 kubectl apply --filename=testdeployment3.yaml --record=true
4 kubectl set image deploy testdeployment nginx=nginx:1.9.1 --record=true
[root@master ~]# kubectl get rs -o wide //查看Deployment控制器下所有的ReplicaSet控制器
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
test-nginx-59ffd87f5 2 2 2 7d21h nginx nginx app=test-nginx,pod-template-hash=59ffd87f5
testdeployment-58779f7cd8 0 0 0 2d23h nginx nginx:1.7.9 example=deploymentnginx,pod-template-hash=58779f7cd8
testdeployment-5c4b8d64df 0 0 0 23h nginx nginx:1.8.1 example=deploymentnginx,pod-template-hash=5c4b8d64df
testdeployment-5c5458b87c 0 0 0 23h nginx nginx:1.9.0 example=deploymentnginx,pod-template-hash=5c5458b87c
testdeployment-8587689fb6 3 3 3 22h nginx nginx:1.9.1 example=deploymentnginx,pod-template-hash=8587689fb6
如何进行回滚?
语法:# kubectl rollout undo deployment [deployment名称] --to-revision=[REVERSION编号]
[root@master ~]# kubectl rollout undo deployment testdeployment --to-revision=2 //将控制器回滚到1.8.1版本
deployment.apps/testdeployment rolled back
[root@master ~]# kubectl rollout history deployment testdeployment //再次查看更新历史记录
deployment.apps/testdeployment
REVISION CHANGE-CAUSE
1 kubectl apply --filename=testdeployment.yaml --record=true
3 kubectl apply --filename=testdeployment3.yaml --record=true
4 kubectl set image deploy testdeployment nginx=nginx:1.9.1 --record=true
5 kubectl apply --filename=testdeployment2.yaml --record=true
[root@master ~]# kubectl get rs -o wide //再次查看replicaset控制器的状态,发现已回滚到1.8.1的版本
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
test-nginx-59ffd87f5 2 2 2 7d21h nginx nginx app=test-nginx,pod-template-hash=59ffd87f5
testdeployment-58779f7cd8 0 0 0 2d23h nginx nginx:1.7.9 example=deploymentnginx,pod-template-hash=58779f7cd8
testdeployment-5c4b8d64df 3 3 3 23h nginx nginx:1.8.1 example=deploymentnginx,pod-template-hash=5c4b8d64df
testdeployment-5c5458b87c 0 0 0 23h nginx nginx:1.9.0 example=deploymentnginx,pod-template-hash=5c5458b87c
testdeployment-8587689fb6 0 0 0 22h nginx nginx:1.9.1 example=deploymentnginx,pod-template-hash=8587689fb6
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
chinaskill-mall 5/5 Running 5 (45h ago) 2d21h
test-nginx-59ffd87f5-2g86v 1/1 Running 1 (45h ago) 2d23h
test-nginx-59ffd87f5-wzmt4 1/1 Running 1 (45h ago) 2d23h
testdeployment-5c4b8d64df-9xsnb 1/1 Running 0 4m26s
testdeployment-5c4b8d64df-jbt42 1/1 Running 0 4m20s
testdeployment-5c4b8d64df-npgsl 1/1 Running 0 4m22s
[root@master ~]# kubectl describe pod testdeployment-5c4b8d64df-9xsnb
Name: testdeployment-5c4b8d64df-9xsnb
Namespace: default
Priority: 0
Node: worker1/192.168.200.12
Start Time: Wed, 23 Nov 2022 19:57:46 -0500
Labels: example=deploymentnginx
pod-template-hash=5c4b8d64df
Annotations: <none>
Status: Running
IP: 10.244.1.48
IPs:
IP: 10.244.1.48
Controlled By: ReplicaSet/testdeployment-5c4b8d64df
Containers:
nginx:
Container ID: docker://21ca5ee96ae37b1ad5ed0b7ef4bf8e1d9a85092881dc67a682cf53c2c9e3c344
Image: nginx:1.8.1
Image ID: docker-pullable://nginx@sha256:9b3e9f189890ef9d6713c3384da3809731bdb0bff84e7b68da330ebadf533085
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Wed, 23 Nov 2022 19:57:49 -0500
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-khlqr (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-khlqr:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 4m39s default-scheduler Successfully assigned default/testdeployment-5c4b8d64df-9xsnb to worker1
Normal Pulled 4m36s kubelet Container image "nginx:1.8.1" already present on machine
Normal Created 4m36s kubelet Created container nginx
Normal Started 4m36s kubelet Started container nginx
DaemonSet控制器
它会在集群中的各个节点上运行单一的Pod副本,比较适合部署那些为节点本身提供服务或者执行维护的pod。
DaemonSet控制器的一些典型用法包括但不限于以下几个方面:
- 运行集群存储Daemon控制器,比如在每个node上运行ceph等
- 在每个node上运行日志收集Daemon控制器,比如logstash
- 在每个node上运行监控Daemon控制器,比如Prometheus Node Exporter。
在每一台节点上都启动http服务,并将它作为DaaemonSet控制器进行部署。
1.创建daemonset控制器
[root@master ~]# vi testdaemonset.yaml
[root@master ~]# vi testdaemonset.yaml
apiVersion: apps/v1 #表示使用的API版本,此处用的是K8s的稳定版
kind: DaemonSet #表示创建的资源对象,此处创建的是DaemonSet
metadata: #资源对象的元数据,一个资源对象可以包含多个元数据,此处采用的元数据为name
name: testdaemonset #表示当前资源的名称
spec: #表示资源对象的具体设置
selector: #自定义一个或多个标签,对Pod起到筛选作用,会选择与标签定义相匹配的Pod
matchLabels:
example: deploymenthttp
template: #Pod模板
metadata:
labels:
example: deploymenthttp
spec:
containers:
- name: httpd
image: httpd:2.2
ports:
- containerPort: 80 #通过Container的属性将80端口进行暴露
hostPort: 8081 #映射到宿主机的8081端口
protocol: TCP
[root@master ~]# kubectl apply -f testdaemonset.yaml
daemonset.apps/testdaemonset created
[root@master ~]# kubectl get daemonset
NAME(控制器名称) DESIRED(预期pod数) CURRENT(当前的pod数) READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
testdaemonset 2 2 2 2 2 <none> 56s
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
testdaemonset-4crzq 1/1 Running 0 2m29s 10.244.0.42 master <none> <none>
testdaemonset-7vs2l 1/1 Running 0 2m29s 10.244.1.50 worker1 <none> <none>
//在前的结果中可以看到pod数量为2,但是我们并没有指定pod副本数,因为我们的node节点数量是两个,Daemonset会为每一台node分配一个pod,此时通过两个节点访问http发现均可以访问
[root@master ~]# kubectl get daemonset --namespace=kube-system //查看k8s系统本身的命名空间
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
kube-proxy 3 3 3 3 3 kubernetes.io/os=linux 13d
[root@master ~]# kubectl get daemonset kube-proxy --namespace=kube-system -o yaml //获取运行pod的配置,查看k8s系统级的daemonset控制器需要加上--namespace=kube-system
apiVersion: apps/v1
kind: DaemonSet
metadata:
annotations:
deprecated.daemonset.template.generation: "1"
creationTimestamp: "2022-11-10T03:05:02Z"
generation: 1
labels:
k8s-app: kube-proxy
name: kube-proxy
namespace: kube-system
resourceVersion: "332127"
uid: c41a1d6c-5248-42c5-97f8-bbc9bb50a678
spec:
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: kube-proxy
template:
metadata:
creationTimestamp: null
labels:
k8s-app: kube-proxy
spec:
containers:
- command:
- /usr/local/bin/kube-proxy
- --config=/var/lib/kube-proxy/config.conf
- --hostname-override=$(NODE_NAME)
env:
- name: NODE_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
image: registry.aliyuncs.com/google_containers/kube-proxy:v1.22.2
imagePullPolicy: IfNotPresent
name: kube-proxy
resources: {}
securityContext:
privileged: true
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/lib/kube-proxy
name: kube-proxy
- mountPath: /run/xtables.lock
name: xtables-lock
- mountPath: /lib/modules
name: lib-modules
readOnly: true
dnsPolicy: ClusterFirst
hostNetwork: true
nodeSelector:
kubernetes.io/os: linux
priorityClassName: system-node-critical
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: kube-proxy
serviceAccountName: kube-proxy
terminationGracePeriodSeconds: 30
tolerations:
- operator: Exists
volumes:
- configMap:
defaultMode: 420
name: kube-proxy
name: kube-proxy
- hostPath:
path: /run/xtables.lock
type: FileOrCreate
name: xtables-lock
- hostPath:
path: /lib/modules
type: ""
name: lib-modules
updateStrategy:
rollingUpdate:
maxSurge: 0
maxUnavailable: 1
type: RollingUpdate
status:
currentNumberScheduled: 3
desiredNumberScheduled: 3
numberAvailable: 3
numberMisscheduled: 0
numberReady: 3
observedGeneration: 1
updatedNumberScheduled: 3
2.daemonset控制器的更新
它的更新方式也有两种:
(1)RollingUpdate:当使用这种方式进行更新时,在更新Daemonset控制器模板后,旧的daemonset pod将被终止,并且将以受控方式自动创建DaemonSet pod,只支持maxUnavailable
(2)OnDelete:这是向后兼容的默认更新方式。当使用这种方式更新时,在更新DaemonSet控制器模板后,只有手动删除旧的控制器POD后,才会创建新的pod.
以OnDelete的方式进行更新,将http的版本更新至2.4
[root@master ~]# vi testdaemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: testdaemonset
spec:
selector:
matchLabels:
example: deploymenthttp
template:
metadata:
labels:
example: deploymenthttp
spec:
containers:
- name: httpd
image: httpd:2.4
ports:
- containerPort: 80
hostPort: 8081
protocol: TCP
updateStrategy:
type: OnDelete
[root@master ~]# kubectl apply -f testdaemonset.yaml
daemonset.apps/testdaemonset configured
[root@master ~]# kubectl get daemonset //可以发现目前的更新还是为0,依旧是旧版本
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
testdaemonset 2 2 2 0 2 <none> 50m
[root@master ~]# kubectl get pods -o wide //会发现此时的pod也依旧为旧版
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
testdaemonset-4crzq 1/1 Running 0 52m 10.244.0.42 master <none> <none>
testdaemonset-7vs2l 1/1 Running 0 52m 10.244.1.50 worker1 <none> <none>
[root@master ~]# kubectl delete pod testdaemonset-7vs2l //删除pod触发更新
pod "testdaemonset-7vs2l" deleted
[root@master ~]# kubectl get pods -o wide //删除完毕之后,会发现有一个新的pod正在创建
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
testdaemonset-4crzq 1/1 Running 0 54m 10.244.0.42 master <none> <none>
testdaemonset-5887h 1/1 Running 0 28s 10.244.1.51 worker1 <none> <none>
[root@master ~]# kubectl get daemonset //再次查看控制器发现已经更新的了一个pod
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
testdaemonset 2 2 2 1 2 <none> 55m
//我们可以重复上述的操作继续更新剩下的pod
[root@master ~]# kubectl delete pod testdaemonset-4crzq
pod "testdaemonset-4crzq" deleted
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
testdaemonset-5887h 1/1 Running 0 2m51s 10.244.1.51 worker1 <none> <none>
testdaemonset-wnkkb 1/1 Running 0 24s 10.244.0.43 master <none> <none>
[root@master ~]# kubectl get daemonset
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
testdaemonset 2 2 2 2 2 <none> 57m
//由上可以看出所有的pod均已被更新
(3)并发式任务:同一时间并发多次执行任务,可以通过spec.parallelism指定并发数量,也可以配合spec.completions属性来指定总任务的执行次数。
1.一次性任务执行
[root@master ~]# vi testjobv1.yaml
apiVersion: batch/v1 #表示API的使用版本,Job位于batch/v1中,v1表示K8S API的稳定版本
kind: Job #创建的资源对象类型
metadata: #资源对象的元数据
name: testjobv1 #当前的资源对象名称
spec:
ttlSecondsAfterFinished: 30 #执行job任务后,等待30s中将执行玩的pod删除
template: #pod模板,需要创建一个pod,pod在启动之后,要执行一串命令
spec:
restartPolicy: Never #容器的重启策略
containers:
- name: testjobcontainer
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh','-c']
args: ['echo "start Job!"; sleep 30; echo "Job Done!"']
[root@master ~]# kubectl apply -f testjobv1.yaml //创建pod
job.batch/testjobv1 created
[root@master ~]# kubectl get job //获取任务列表
NAME COMPLETIONS DURATION AGE
testjobv1 1/1 33s 53s
[root@master ~]# kubectl get pod -o wide //获取pod状态
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
testjobv1--1-hf5bk 0/1 Completed 0 71s 10.244.1.66 worker2 <none> <none>
[root@master ~]# kubectl logs testjobv1--1-hf5bk
start Job!
Job Done!
注意:Job执行完毕后,不会被自动删除,保留pod的好处是方便后期查看日志,或者在出现问题的时候及时了解pod所处的状态。但是缺点在于,如果执行的次数越来越多,并且不删除,这种垃圾式的job会越来越多,人工删除会越来越麻烦,我们可以采取修改yaml文件增加参数信息的方式来将job执行完毕后,等待一段时间进行删除。增加参数:ttlSecondsAfterFinished
在k8s中这个功能默认是关闭的状态,需要我们手动的开启,修改的组件包括 apiserver、controller和scheduler。我们需要直接修改/etc/kubernetes/manifests/kube-apiserver.yaml,加入- --feature-gates=TTLAfterFinished=true参数即可。
2.串行式任务
[root@master ~]# vi testjobv2.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: testjobv2
spec:
completions: 5
template:
spec:
restartPolicy: Never
containers:
- name: testjobv2
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh','-c']
args: ['echo "start Job!"; sleep 30; echo "Job Done!"']
[root@master ~]# kubectl get pod -o wide //从结果可知现在增加completions参数后任务已经执行了5次
testjobv2--1-8lrqv 0/1 Completed 0 96s 10.244.1.70 worker2 <none> <none>
testjobv2--1-cm4px 0/1 Completed 0 2m40s 10.244.1.68 worker2 <none> <none>
testjobv2--1-hcbdh 0/1 Completed 0 65s 10.244.1.71 worker2 <none> <none>
testjobv2--1-lgtgd 0/1 Completed 0 34s 10.244.1.72 worker2 <none> <none>
testjobv2--1-whsf7 0/1 Completed 0 2m7s 10.244.1.69 worker2 <none> <none>
[root@master ~]# kubectl get job
NAME COMPLETIONS DURATION AGE
testjobv2 5/5 2m38s 3m39s
3.并行式任务
[root@master ~]# vi testjobv3.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: testjobv3
spec:
completions: 10
parallelism: 5
template:
spec:
restartPolicy: Never
containers:
- name: testjobv3
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh','-c']
args: ['echo "start Job!"; sleep 30; echo "Job Done!"']
[root@master ~]# kubectl get pod -o wide |grep testjobv3
testjobv3--1-4dcpb 0/1 Completed 0 2m24s 10.244.2.57 worker1 <none> <none>
......
注意:一开始会同时创建5个pod同时运行,然后等待某一个pod运行结束之后,继续创建后续的pod,保持5个pod同时处于running的状态,直到达到设置的执行总数10次为止。
4.Job的异常处理
在job任务中,只能定义restartPolicy的值为Never或OnFailure其中一种。
(1)设置OnFailure时的状态
[root@master ~]# vi testjobv4.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: testjobv4
spec:
backoffLimit: 6 #重启次数的上限,默认次数就是6次
template:
spec:
restartPolicy: OnFailure
containers:
- name: testjobv4
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh','-c']
args: ['This is erro command!!!']
[root@master ~]# kubectl apply -f testjobv4.yaml
job.batch/testjobv4 created
[root@master ~]# kubectl get pod -o wide |grep testjobv4
testjobv4--1-xnh2g 0/1 CrashLoopBackOff 4 (67s ago) 2m44s 10.244.1.78 worker2 <none> <none>
//执行完毕创建后,Pod的创建状态一直处于error或者是CrashLoopBackOff,在此期间Pod会不断的重启,RESTART的值一直在不断地增加,
Pod会以递增延迟的方式尝试重新启动(10s,20s,40s...)上限时间为6分钟,当延迟的时间增加到6分钟后,要再次等待6分钟才会重启,在我们的模板文件中设定了重启的次数上限,默认为6次,如果6次以内没有出现失败,则会重新计数,但是如果达到了重启次数的上限,则这个job对应的容器将会被终止删除。
[root@master ~]# kubectl get pod -o wide |grep testjobv4
*这个结果什么也没有了,pod到达重启上限后被删除*
(2)设置Never时的状态
[root@master ~]# vi testjobv5.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: testjobv5
spec:
backoffLimit: 6 #重启次数的上限,默认次数就是6次
template:
spec:
restartPolicy: Never
containers:
- name: testjobv5
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh','-c']
args: ['This is erro command!!!']
[root@master ~]# kubectl apply -f testjobv5.yaml
job.batch/testjobv5 created
[root@master ~]# kubectl get pod
testjobv5--1-5m7pj 0/1 Error 0 2s
testjobv5--1-dcwnp 0/1 Error 0 52s
testjobv5--1-kf2hn 0/1 Error 0 42s
testjobv5--1-t22f7 0/1 Error 0 53s
//从以上结果可知,pod不会重新启动,因为设置了never并且job任务并没有执行成功,所以job会不停的新建pod,直到pod执行成功。
在这个过程中和onfailure相同的是,Never也会增加启动延迟的时间,同样也是由backoffLimit来控制重启的上限次数,在经过6次重启之后(等于7次启动),pod还是失败的状态那么此时就不会在启新的pod了。
(3)不明显异常处理
除了可以发现的异常现象之外,job在执行的过程中,还一种难以发觉的异常情况,比如任务陷入了死循环卡死不动,看起来是正常状态但是执行任务没有任何结果。
对于这类异常情况job也提供了spec.activeDeadlineSeconds属性,指定任务的上限时间(以秒为单位),如果超过上限时间,任务将被强制终止并删除。
[root@master ~]# vi testjobv6.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: testjobv6
spec:
activeDeadlineSeconds: 10
template:
spec:
restartPolicy: Never
containers:
- name: testjobv6
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh','-c']
args: ['echo "Hello weizhihua"; sleep 3600']
[root@master ~]# kubectl apply -f testjobv6.yaml
job.batch/testjobv6 created
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
testjobv6--1-frrm7 1/1 Terminating 0 23s
//我们因为由运行时间限制10秒钟,所以在最开始的十秒钟内,Pod是处于运行的状态,10秒钟后Pod就被终止掉了,直到后面被删除(不管重启策略设置的值是OnFailure还是Never)
[root@master ~]# kubectl get pod |grep testjov6
*此处以为空*
-
在K8S集群中还有一种叫做job工作负载的对象,基于某一特定的任务运行,当运行任务的容器完成工作后,就会成功退出。
Cronjob的任务就是在job的基础上增加了时间调度,可以在给定的时间点运行一个任务,并且也可以定期的运行。
Job控制器可以执行三种类型的操作:
- 一次性任务:通常只会去启动一个pod(除非pod失败),一旦pod成功终止,job任务就完成了。
- 串行式任务:连续的、多次执行某一任务。当上一次任务执行完毕,接着执行下一个任务,直至所有的任务执行完毕,可以通过spec.completions属性指定执行次数。