kubernetes 核心技术-controller

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 最小的单元。

kubernetes 核心技术-controller

使用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的匹配关系:

kubernetes 核心技术-controller

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

 

上一篇:flowable实战(二)flowable流程模型管理接口


下一篇:kubernetes创建Pod