按照图示部署好了K8s集群,一个Master,两个worker nodes。
docker容器是不稳定,当一个容器出现故障后或误删除后,管理员需要去排查并重启。在K8s中,最小的单位是Pod,本质上是对容器的包装,也是不稳定的。为了避免这种缺点,K8s里设置了Deployment来帮助我们解决这些问题。
Deployment可以帮我们做什么?
Deployment原理:
在Kubernetes架构中,有一个叫做kube-controller-manager的组件。这个组件,是一系列控制器的集合。其中每一个控制器,都以独有的方式负责某种编排功能。而Deployment正是这些控制器中的一种。
在具体实现中,实际状态往往来自于Kubernetes集群本身。比如Kubelet通过心跳汇报的容器状态和节点状态,或者监控系统中保存的应用监控数据,或者控制器主动收集的它感兴趣的信息,这些都是常见的实际状态的来源;期望状态一般来自用户提交的YAML文件,这些信息都保存在Etcd中。
对于Deployment,它的控制器简单实现如下:
可以用命令行或者yaml文件的方式创建deployment。但是推荐使用yaml文件的方式来完成,功能能丰富。
步骤1:获取deployment的yaml文件:
在master上:导出deployment的yaml文件模板:
kubectl create deployment web1 --image=nginx --dry-run=client -o yaml > web1.yaml
查看并分析其yaml文件:
[root@vms201 deployment_practise]# cat web1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web1
name: web1
spec:
replicas: 1
selector:
matchLabels:
app: web1
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: web1
spec:
containers:
- image: nginx
name: nginx
resources: {}
status: {}
template数据表示pod的模板, replicas则表示根据此模板需要创建几个副本数。matchLabels属性会去匹配template中指定的labels,来控制pod的数量,所以务必保证这两个地方labels的值是相同的。
步骤2:编辑模板文件,创建deploy:
编辑模板文件:
[root@vms201 deployment_practise]# cat web1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web1
name: web1
spec:
replicas: 3
selector:
matchLabels:
app1: web1
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app1: web1
app2: web1
spec:
containers:
- image: nginx
name: nginx
imagePullPolicy: IfNotPresent
resources: {}
status: {}
创建并查看deployment:
[root@vms201 deployment_practise]# kubectl apply -f web1.yaml
deployment.apps/web1 created
[root@vms201 deployment_practise]# kubectl get deployments.apps -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
web1 3/3 3 3 57s nginx nginx app=web1
可以看到,目前已经运行了3个副本;注意容器的labels可以由多个,matchLabels属性至少要match其中的一个。
注意:当当前pod无法无法满足实际环境的中的流量时,可以为当前pod创建多个副本,后续流量则会被分配到各个pod上去,减少了每个pod的负载。
删除其中的一个pod:
[root@vms201 deployment_practise]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web1-5bfb6d8dcc-5vv2p 1/1 Running 0 23m
web1-5bfb6d8dcc-hgt8v 1/1 Running 0 23m
web1-5bfb6d8dcc-js546 1/1 Running 0 23m
[root@vms201 deployment_practise]# kubectl delete pod web1-5bfb6d8dcc-5vv2p
pod "web1-5bfb6d8dcc-5vv2p" deleted
然后在重新查看副本数和pod:
[root@vms201 deployment_practise]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
web1 3/3 3 3 24m
[root@vms201 deployment_practise]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web1-5bfb6d8dcc-hgt8v 1/1 Running 0 27m
web1-5bfb6d8dcc-js546 1/1 Running 0 27m
web1-5bfb6d8dcc-wfjbn 1/1 Running 0 3m2s
可以发现,deployment重新装机了一个pod,保证了副本数量依旧为3。
当一个worker node出现故障,deployment会将在其上运行的pod安排到其他node上运行,当故障node重启后,pod并不会返回到重启的node上运行。
pod的yaml文件在线修改并应用是有问题的,但是deployment却可以。例如我们通过如下命令将deployment的值修改为2,然后再查看修改后的结果:
[root@vms201 deployment_practise]# kubectl edit deployments.apps
deployment.apps/web1 edited
[root@vms201 deployment_practise]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
web1 2/2 2 2 34m
通过如上的操作,deployment已经被在线修改并应用了。但如果不是使用edit的方式修改,而是直接修改其的yaml文件,修改完成后需要重新apply才会生效。
使用scale的方式设置副本的数量:
[root@vms201 deployment_practise]# kubectl scale deployment web1 --replicas=4
deployment.apps/web1 scaled
[root@vms201 deployment_practise]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
web1 4/4 4 4 51m
[root@vms201 deployment_practise]# kubectl get pod
NAME READY STATUS RESTARTS AGE
web1-5bfb6d8dcc-2djjm 1/1 Running 0 33s
web1-5bfb6d8dcc-9mj2v 1/1 Running 0 33s
web1-5bfb6d8dcc-hgt8v 1/1 Running 0 51m
web1-5bfb6d8dcc-js546 1/1 Running 0 51m
HPA(horizontal pod autoscalers)水平自动伸缩。通过检测pod CPU的负载,解决deployment里某pod负载太重,动态伸缩pod的数量来负载均衡。
HPA可以检测pod cpu的使用情况,通知deployment增加或者减少所管理pod副本的数量。
步骤1:配置HPA
设置web1的pod数量最小为2,最大为10:
[root@vms201 deployment_practise]# kubectl autoscale deployment web1 --min=2 --max=10
horizontalpodautoscaler.autoscaling/web1 autoscaled
当我们强行设置pod数为1时,查看副本数:
[root@vms201 deployment_practise]# kubectl scale deployment web1 --replicas=1
deployment.apps/web1 scaled
[root@vms201 deployment_practise]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web1-5bfb6d8dcc-2w8dd 1/1 Running 0 6s
web1-5bfb6d8dcc-js546 1/1 Running 0 62m
可以看到,有一个pod的AGE是6s,表示的是我们手工让pod从4个变为1个,由于设置了HPA的最小数量为2,所以又重新创建了一个新的pod。
步骤2:查看负载的情况和设置阈值
在当前的hpa中,我们可以看到当前的CPU的使用情况为unknown,可以通过设置让其显示
[root@vms201 deployment_practise]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web1 Deployment/web1 <unknown>/80% 2 10 2 6m30s
删除掉原来的HPA和deployment:
[root@vms201 deployment_practise]# kubectl delete -f web1.yaml
deployment.apps "web1" deleted
[root@vms201 deployment_practise]# kubectl delete hpa web1
horizontalpodautoscaler.autoscaling "web1" deleted
修改web1.yaml文件:设置资源限制,cpu为400m
[root@vms201 deployment_practise]# cat web1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web1
name: web1
spec:
replicas: 3
selector:
matchLabels:
app: web1
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: web1
spec:
containers:
- image: nginx
name: nginx
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 400m
status: {}
创建deployment和hpa
[root@vms201 deployment_practise]# kubectl apply -f web1.yaml
deployment.apps/web1 created
[root@vms201 deployment_practise]# kubectl autoscale deployment web1 --min=2 --max=10 --cpu-percent=80
horizontalpodautoscaler.autoscaling/web1 autoscaled
可以看到,这里设置了cpu-percent=80,表示pod的cpu利用率超过了百分之80会自动扩容:
[root@vms201 deployment_practise]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web1 Deployment/web1 0%/80% 2 10 3 70s
步骤3:创建SVC,做负载均衡
关于SVC的部分,后续笔记会补充。
[root@vms201 deployment_practise]# kubectl expose --name=svc1 deployment web1 --port=80
service/svc1 exposed
[root@vms201 deployment_practise]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc1 ClusterIP 10.109.167.135 <none> 80/TCP 8s
如上,SVC已经关联到了deployment上,其地址为10.109.167.135。
步骤4:测试deployment的环境
安装压力测试包:
yum install httpd-tools -y
向SVC地址发送数据做压力测试:
ab -t 600 -n 1000000 -c 1000 http://10.109.167.135/index.html
其中,各个参数的含义:
-n在测试会话中所执行的请求个数。默认时,仅执行一个请求。
-c一次产生的请求个数。默认是一次一个。
-t测试所进行的最大秒数
查看hpa状况:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web1 Deployment/web1 64%/80% 2 10 6 14m
可以看到目前已经自动拓展到了6个副本,每个副本的CPU使用率平均为64%。当压力测试完成,CPU利用率下降后,pod数会减少,但是不会立即减少,为了防止流量再次增大,默认是5分钟。5分钟后进行查看:
[root@vms201 ~]# kubectl top pods --use-protocol-buffers
NAME CPU(cores) MEMORY(bytes)
web1-65bd67cbf8-594pf 0m 5Mi
web1-65bd67cbf8-6pskt 0m 5Mi
对镜像进行升级,可以保证deployment中的部分副本进行进行升级,等升级完成后剩下的副本才继续升级,保证稳定性。(升级的过程本质是删除掉现有的pod,然后用新镜像创建新的pod)
方式1:直接修改deployment的文件:
首先将镜像拓展为6个,方便做测试:
[root@vms201 ~]# kubectl edit hpa web1
horizontalpodautoscaler.autoscaling/web1 edited
[root@vms201 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web1-65bd67cbf8-2t4m5 1/1 Running 0 13s
web1-65bd67cbf8-594pf 1/1 Running 1 39m
web1-65bd67cbf8-6pskt 1/1 Running 1 28m
web1-65bd67cbf8-9l2lw 1/1 Running 0 13s
web1-65bd67cbf8-h4jql 1/1 Running 0 13s
web1-65bd67cbf8-shchn 1/1 Running 0 13s
修改deployment的yaml文件,找到其中的镜像名称修改为nginx:1.9,并且将maxSurge设置为2,maxUnavailable设置为2。
[root@vms201 ~]# kubectl edit deployments.apps web1
deployment.apps/web1 edited
maxSurge:在升级过程中一次升级几个(可以是数字或百分比)
maxUnavailable:在升级过程中,一次性删除多少个pod(可以是数字或者百分比)
可以看到,已经升级完成,升级的时间不同:
[root@vms201 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web1-d845d59bb-64zx7 1/1 Running 0 35s
web1-d845d59bb-79vrp 1/1 Running 0 48s
web1-d845d59bb-gzlkq 1/1 Running 0 65s
web1-d845d59bb-hbnzk 1/1 Running 0 65s
web1-d845d59bb-jcf5r 1/1 Running 0 65s
web1-d845d59bb-pdmns 1/1 Running 0 65s
利用describe查看是否更新成功:
[root@vms201 ~]# kubectl describe pod web1-d845d59bb-64zx7 | grep image
Normal Pulled 3m58s kubelet Container image "nginx:1.9" already present on machine
方式2: 使用命令行方式
kubectl set image deploy deploy名 容器名=镜像名 --record
重新将nginx镜像替换为latest版本:
[root@vms201 ~]# kubectl set image deploy web1 nginx=nginx:latest --record
deployment.apps/web1 image updated
查看deployment的历史记录:
[root@vms201 ~]# kubectl rollout history deployment web1
deployment.apps/web1
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3 kubectl set image deploy web1 nginx=nginx:latest --record=true
可以看到revision3上由于我们加上了–record参数,记录了所做的操作。
恢复到指定的版本:
[root@vms201 ~]# kubectl rollout undo deployment web1 --to-revision=2
deployment.apps/web1 rolled back
恢复到版本2,也就是nginx:1.9的版本。
参考资料:
1.《老段CKA课程》
2. https://blog.csdn.net/lixinkuan328/article/details/103993274