Kubernetes 通常不会直接创建 Pod,而是通过 Controller 来管理 Pod 。Controller 中定义了 Pod 的部署特性,比如有几个副本,在什么样的 Node 上运行等,pod和controller之间通过yaml文件中的selector与label标签建立关系。
为了满足不同的业务场景,Kubernetes 提供了多种 Controller,包括 Deployment、ReplicaSet、DaemonSet、StatefuleSet、Job 等。
ReplicaSet
实现了 Pod 的多副本管理,目的是在任何时候都维持一组稳定的pod副本,常用来确保指定数量的pod副本可用。
使用 Deployment 时会自动创建 ReplicaSet,也就是说 Deployment 是通过 ReplicaSet 来管理 Pod 的多个副本,我们通常不需要直接使用 ReplicaSet,而是通过Deployment去使用ReplicaSet,这样的话我们就不需要担心和其他机制的冲突(如:ReplicaSet不支持滚动更新,但是Deployment支持)。
一个ReplicaSet的示例:
apiVersion: apps/v1 kind: ReplicaSet metadata: name: frontend labels: app: guestbook tier: frontend spec: # modify replicas according to your case replicas: 3 selector: matchLabels: tier: frontend template: metadata: labels: tier: frontend spec: containers: - name: php-redis image: gcr.io/google_samples/gb-frontend:v3
ReplicaSet中.spec.template.metadata.labels必须跟spec.selector
相同,不然会被API拒绝。
使用kubectl delete可以删除ReplicaSet及其pod,Garbage collection默认会删除所有相关pod。若只想删除ReplicaSet而不删除pod,需要指定--cascade=false。删除ReplicaSet后,可以创建具有相同selector的ReplicaSet来管理原先的pod,但不会使用新ReplicaSet的podTemplate来更新原先的pod。若想自动更新pod,使用Deployment。
总之,不建议直接使用 ReplicaSet,而是通过Deployment去使用ReplicaSet。
Deployment(详细)
这是在使用kubernetes时候,大家部署系统或者是服务经常使用的一种controller类型。因为我们可以通过它来使用ReplicaSet来为我们部署的应用进行副本的创建。
一般在实际的运用中,大家用 Deployment 做应用的真正的管理,而 Pod 是组成 Deployment 最小的单元。
使用deployment部署应用(基于yaml方式)
1.编写或生成yaml文件:kubectl create deployment nginx --image=nginx:1.8 --dry-run -o yaml > nginx.yaml
[root@master ~]# kubectl create deployment nginx --image=nginx:1.8 --dry-run -o yaml > nginx.yaml W0413 03:47:05.133957 72422 helpers.go:535] --dry-run is deprecated and can be replaced with --dry-run=client. [root@master ~]# ll -rw-r--r-- 1 root root 388 Apr 13 03:47 nginx.yaml
注意,上一步的目的是快速的生成一个yaml模板,方便修改后使用,当然也可以自己直接写yaml文件。
在生成的yaml文件中,可以看到selector与label的匹配关系:
2.使用已生成的yaml文件部署应用:kubectl apply -f nginx.yaml
[root@master ~]# kubectl apply -f nginx.yaml deployment.apps/nginx created [root@master ~]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-7c96855774-7h7bq 0/1 ContainerCreating 0 9s
3.对外发布(暴露对外端口),并重新生成yaml文件:kubectl expose deployment nginx --port=80 --type=NodePort --target-port=80 --name=nginx-server -o yaml > nginx-server.yaml
[root@master ~]# kubectl expose deployment nginx --port=80 --type=NodePort --target-port=80 --name=nginx-server -o yaml > nginx-server.yaml [root@master ~]# kubectl get pod,svc NAME READY STATUS RESTARTS AGE pod/nginx-7c96855774-7h7bq 1/1 Running 0 10m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 27d service/nginx-server NodePort 10.111.125.48 <none> 80:31491/TCP 26s [root@master ~]# ll total 32 -rw-r--r-- 1 root root 1074 Apr 14 00:39 nginx-server.yaml -rw-r--r-- 1 root root 388 Apr 13 03:47 nginx.yaml
这里两个yaml文件,nginx.yaml是pod的,nginx-server.yaml是service的(真实服务)。
应用升级与回滚(以nginx的pod为例)
1.新建版本为1.8 nginx的pod
yaml文件为:其中副本数为2
apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: nginx name: nginx spec: replicas: 2 selector: matchLabels: app: nginx strategy: {} template: metadata: creationTimestamp: null labels: app: nginx spec: containers: - image: nginx:1.8 name: nginx resources: {} status: {}
使用yaml文件部署应用:由于yaml文件中副本数为2,会有2个pod
[root@master ~]# kubectl apply -f nginx.yaml deployment.apps/nginx created [root@master ~]# kubectl get pods NAME READY STATUS RESTARTS AGE nginx-7c96855774-jg8hm 1/1 Running 0 36s nginx-7c96855774-ntwlw 1/1 Running 0 36s
2.升级nginx版本1.8至1.9:kubectl set image deployment nginx nginx=nginx:1.9
[root@master ~]# kubectl set image deployment nginx nginx=nginx:1.9 deployment.apps/nginx image updated [root@master ~]# kubectl get pods NAME READY STATUS RESTARTS AGE nginx-77766dd89-fcm9r 0/1 ContainerCreating 0 16s nginx-7c96855774-jg8hm 1/1 Running 0 16m nginx-7c96855774-ntwlw 1/1 Running 0 16m
在这个过程中,可以使用命令来查看升级的状态:kubectl rollout status deployment nginx
[root@master ~]# kubectl rollout status deployment nginx Waiting for deployment "nginx" rollout to finish: 1 out of 2 new replicas have been updated... Waiting for deployment "nginx" rollout to finish: 1 out of 2 new replicas have been updated... Waiting for deployment "nginx" rollout to finish: 1 out of 2 new replicas have been updated... Waiting for deployment "nginx" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "nginx" rollout to finish: 1 old replicas are pending termination... deployment "nginx" successfully rolled out
等到升级成功完毕后,再去查看pods:
[root@master ~]# kubectl get pods NAME READY STATUS RESTARTS AGE nginx-77766dd89-fcm9r 1/1 Running 0 5m20s nginx-77766dd89-rld2x 1/1 Running 0 4m51s
可以发现,在升级的过程中,并不是直接kill掉原来的两个pod,而是启动玩新版本的pod后,再去kill掉老的,这种替换的机制保证了服务提供不间断。
另一方面,在node节点上也会发现已经有新版本的nginx镜像被下载:
[root@node1 ~]# docker images nginx* REPOSITORY TAG IMAGE ID CREATED SIZE nginx 1.9 c8c29d842c09 4 years ago 183MB nginx 1.8 0d493297b409 5 years ago 133MB
3.回滚版本
每次rollout都会创建revision,默认系统会保存deployment的rollout,可通过指定revision来rollback deployment。
首先可以查看历史升级的版本: kubectl rollout history deployment nginx
[root@master ~]# kubectl rollout history deployment nginx deployment.apps/nginx REVISION CHANGE-CAUSE 1 <none> 2 <none>
其中第一个版本就是1.8,第二个版本都是1.9
如果是回滚到上一个版本:kubectl rollout undo deployment nginx
[root@master ~]# kubectl rollout undo deployment nginx deployment.apps/nginx rolled back
如果是回滚到指定版本:kubectl rollout undo deployment nginx --to-revision=2,其中--to-revision就是上述通过rollout history查询出来的版本号
[root@master ~]# kubectl rollout undo deployment nginx --to-revision=2 deployment.apps/nginx rolled back
最后可以通过查看deployment的详细信息来验证当前的版本:kubectl describe deployment nginx
[root@master ~]# kubectl describe deployment nginx Name: nginx Namespace: default CreationTimestamp: Wed, 14 Apr 2021 05:50:54 +0800 Labels: app=nginx Annotations: deployment.kubernetes.io/revision: 4 Selector: app=nginx Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx:1.9 。。。。。。。。
应用弹性伸缩
当前只有2个pod,复制为10个:kubectl scale deployment nginx --replicas=10
[root@master ~]# kubectl get pods NAME READY STATUS RESTARTS AGE nginx-7c96855774-8m6q9 1/1 Running 0 7m31s nginx-7c96855774-nzvld 1/1 Running 0 7m30s [root@master ~]# kubectl scale deployment nginx --replicas=10 deployment.apps/nginx scaled [root@master ~]# kubectl get pods NAME READY STATUS RESTARTS AGE nginx-7c96855774-2dk89 1/1 Running 0 9s nginx-7c96855774-2ttfw 1/1 Running 0 9s nginx-7c96855774-8m6q9 1/1 Running 0 8m41s nginx-7c96855774-cn6vr 1/1 Running 0 9s nginx-7c96855774-gfzrq 1/1 Running 0 9s nginx-7c96855774-nzvld 1/1 Running 0 8m40s nginx-7c96855774-r4sdt 1/1 Running 0 9s nginx-7c96855774-rtdrb 1/1 Running 0 9s nginx-7c96855774-vjzg2 1/1 Running 0 9s nginx-7c96855774-vrqck 1/1 Running 0 9s
若cluster启动HPA(horizontal Pod autoscaling),还可以设置deployment的autoscaler:
kubectl autoscale deployment nginx --min=10 --max=15 --cpu-percent=80
表示数量在10-15之间,cpu使用率为80%。
DaemonSet
用于每个 Node 最多只运行一个 Pod 副本的场景。正如其名称所揭示的,DaemonSet 通常用于运行 daemon(守护程序)。当有Node加入集群时,也会为他们新增一个Pod,当有Node从集群中移除时,这个Pod同时也会回收。在删除DaemonSet的时候,会删除他创建的所有Pod。
使用DaemonSet的一些例子:
1.运行在集群存储的daemon,例如在每个node上运行的ceph(分布式文件系统);
2.在每个node上运行日志收集daemon,例如fluentd、logstash;
3.在每个node上运行的监控daemon,例如Prometheus Node Exporter。
StatefulSets
StatefulSets主要用来管理有状态的app。跟Deployment一样,StatefulSet用来管理Pod,但不同的是,StatefulSets中的每个pod都维护一个严格的identifier(识别号)并在reschedule时不变。
StatefulSets是为了解决有状态服务的问题(对应Deployment和ReplicaSet是为无状态服务而设计的)。能够保证 Pod 的每个副本在整个生命周期中名称是不变的。而其他 Controller 不提供这个功能,当某个 Pod 发生故障需要删除并重新启动时,Pod 的名称会发生变化。同时 StatefuleSet 会保证副本按照固定的顺序启动、更新或者删除。
应用的场景:
1.需要稳定的持久化存储;
2.需要稳定的网络标志(即Pod被重新调度时网络访问不变);
3.有序部署和有序扩展;
4.有序收缩和删除。
使用的服务有:MySQL集群、MongoDB集群、Akka集群、ZooKeeper集群等。
Job
批处理任务通常并行(或者串行)启动多个pod去处理一批工作项(work item),当指定数量的pod处理完任务并成功终止后,整个批处理任务结束。适用于运行结束就删除的应用。而其他 Controller 中的 Pod 通常是长期持续运行。
CronJob
相应的,kubernetes提供了定时进行的批处理任务,解决了某些批处理任务需要定时反复执行的问题。
参考:
https://www.pianshen.com/article/80111234551/
https://zhuanlan.zhihu.com/p/88202304