• ReplicationController和ReplicaSet
  • Deployment                                             无状态负载
  • DaemonSet                                              守护进程集
  • StateFulSet                                              有状态负载
  • Job/cronJob                                              普通任务/计划任务
  • Horizontal  Pod Autoscaling                     自动扩展
  • ReplicationController和ReplicaSet

    ReplicationController(RC)是用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会创建新的pod来代替,如果异常多出来的容器也会回收;

    在新版本的kubernetes中建议使用ReplicaSet来代替ReplicationController,ReplicaSet 跟ReplicationController没有本质的不同,只是ReplicaSet支持集合式的selector(通过标签来选择);而ReplicationController不支持。

    Deployment

    Deployment为Pod和ReplicaSet提供了一个声明式定义(declarative)方法,用来替代以前的ReplicationController来方便管理应用,典型的场景包括:

  • 定义deployment来创建pod和replicaset
  • 扩容和缩容
  • 部署无状态应用,只关心数量,不论角色等,称无状态
  • 具有上线部署、副本设定、滚动升级、回滚等功能
  • 提供声明式更新,例如只更新一个新的image
  • 例: 部署一个nginx应用

    创建一个rs.ymal的文件,定义deployment来创建pod和replicaset

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx
            ports:
             - containerPort: 80
    
    [root@master ~]# kubectl apply -f rs.yaml            #创建一个pod
    deployment.apps/nginx-deployment created
    [root@master ~]# kubectl get pods                    # 查看pod信息
    NAME                                READY   STATUS              RESTARTS   AGE
    nginx-6799fc88d8-d9p6h              1/1     Running             0          27m
    nginx-deployment-7848d4b86f-bnvdg   0/1     ContainerCreating   0          13s
    nginx-deployment-7848d4b86f-xwn6c   0/1     ContainerCreating   0          13s
    nginx-deployment-7848d4b86f-zf4bh   1/1     Running             0          13s
    [root@master ~]# vim rs.yaml              
    [root@master ~]# kubectl get pods --show-labels        #查看pod的标签
    NAME                                READY   STATUS    RESTARTS   AGE     LABELS
    nginx-6799fc88d8-d9p6h              1/1     Running   0          30m     app=nginx,pod-template-hash=6799fc88d8
    nginx-deployment-7848d4b86f-bnvdg   1/1     Running   0          3m42s   app=nginx,pod-template-hash=7848d4b86f
    nginx-deployment-7848d4b86f-xwn6c   1/1     Running   0          3m42s   app=nginx,pod-template-hash=7848d4b86f
    nginx-deployment-7848d4b86f-zf4bh   1/1     Running   0          3m42s   app=nginx,pod-template-hash=7848d4b86f
    [root@master ~]# kubectl get deployment                                          
    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx              1/1     1            1           56d
    nginx-deployment   3/3     3            3           6m53s
    [root@master ~]# kubectl get rs     #查看pod的rs信息
    NAME                          DESIRED   CURRENT   READY   AGE
    nginx-6799fc88d8              1         1         1       35m
    nginx-deployment-7848d4b86f   3         3         3       8m40s
    [root@master ~]# kubectl get pods -o wide            #查看pod的详细信息
    NAME                                READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
    nginx-6799fc88d8-d9p6h              1/1     Running   0          39m   10.101.11.5    node2   <none>           <none>
    nginx-deployment-7848d4b86f-bnvdg   1/1     Running   0          11m   10.101.149.5   node1   <none>           <none>
    nginx-deployment-7848d4b86f-xwn6c   1/1     Running   0          11m   10.101.149.4   node1   <none>           <none>
    nginx-deployment-7848d4b86f-zf4bh   1/1     Running   0          11m   10.101.11.6    node2   <none>           <none>

    扩容或者缩容,比如我们把pod数目扩容到10个

    [root@master ~]# kubectl scale deployment nginx-deployment --replicas 10
    deployment.apps/nginx-deployment scaled
    [root@master ~]# kubectl get pods 
    NAME                                READY   STATUS    RESTARTS   AGE
    nginx-6799fc88d8-d9p6h              1/1     Running   0          50m
    nginx-deployment-7848d4b86f-bnvdg   1/1     Running   0          22m
    nginx-deployment-7848d4b86f-fjhld   1/1     Running   0          92s
    nginx-deployment-7848d4b86f-nld5c   1/1     Running   0          92s
    nginx-deployment-7848d4b86f-nmxlf   1/1     Running   0          92s
    nginx-deployment-7848d4b86f-vmjgl   1/1     Running   0          92s
    nginx-deployment-7848d4b86f-wbfbq   1/1     Running   0          92s
    nginx-deployment-7848d4b86f-x86hq   1/1     Running   0          92s
    nginx-deployment-7848d4b86f-xngl5   1/1     Running   0          92s
    nginx-deployment-7848d4b86f-xwn6c   1/1     Running   0          22m
    nginx-deployment-7848d4b86f-zf4bh   1/1     Running   0          22m

    查看当前pod中的镜像(以nginx为例)

    [root@master ~]# kubectl get pod -o wide 
    NAME                   READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
    web1-9d68ffd75-bnvdg   1/1     Running   0          9h    10.101.11.7    node2   <none>           <none>
    web1-9d68ffd75-x86hq   1/1     Running   0          9h    10.101.149.4   node1   <none>           <none>
    web1-9d68ffd75-zf4bh   1/1     Running   0          9h    10.101.149.5   node1   <none>           <none>
    [root@master ~]# kubectl describe pod web1-9d68ffd75-bnvdg | grep image
      Normal  Pulled     9h    kubelet            Container image "nginx:1.21.4" already present on machine
    [root@master ~]# 

    查看当前镜像的nginx为1.21.4版本 升级1.21.5版本命令为

    kubectl set image deployment  web1(需要更新镜像的deployment名称)   nginx=nginx:1.21.5 (新版本镜像名称) --rcode   #可以记录镜像更新信息。

    [root@master ~]# kubectl set image deployment web1 nginx=nginx:1.21.5 
    deployment.apps/web1 image updated
    [root@master ~]# kubectl get pod
    NAME                   READY   STATUS             RESTARTS   AGE
    web1-594b7b7c6-xngl5   0/1     ImagePullBackOff   0          20s
    web1-9d68ffd75-bnvdg   1/1     Running            0          9h
    web1-9d68ffd75-x86hq   1/1     Running            0          9h
    web1-9d68ffd75-zf4bh   1/1     Running            0          9h
    [root@master ~]# 

    等待片刻再次检查镜像版本,发现镜像已经变为1.21.5版本。

    [root@master ~]# kubectl describe pod web1-594b7b7c6-fkqt9 | grep image
      Normal  Pulled     2m49s  kubelet            Container image "nginx:1.21.5" already present on machine

    kubectl rollout undo deployment  web1

    [root@master ~]# kubectl rollout undo deployment web1
    deployment.apps/web1 rolled back
    [root@master ~]# kubectl get pod -o wide                               
    NAME                   READY   STATUS        RESTARTS   AGE     IP             NODE    NOMINATED NODE   READINESS GATES
    web1-594b7b7c6-fkqt9   0/1     Terminating   0          4m58s   10.101.149.6   node1   <none>           <none>
    web1-594b7b7c6-nmxlf   0/1     Terminating   0          4m59s   10.101.11.10   node2   <none>           <none>
    web1-594b7b7c6-xngl5   0/1     Terminating   0          40m     10.101.11.9    node2   <none>           <none>
    web1-9d68ffd75-fjhld   1/1     Running       0          5s      10.101.11.11   node2   <none>           <none>
    web1-9d68ffd75-vmjgl   1/1     Running       0          6s      10.101.149.7   node1   <none>           <none>
    web1-9d68ffd75-wbfbq   1/1     Running       0          3s      10.101.149.8   node1   <none>           <none>
    [root@master ~]# 

    Deployment更新策略 

    滚动更新(rollingUpdate)和重建更新(Recreate)。这两种更新策略差异如下:

    重建更新(Recreate)
    重建更新指的是先全部删除已有的Pod对象,然后创建新版本的Pod对象。这种更新方式,最大的弊端是在更新过程中,运行的服务要有一定时间的中断。但是有点在于这种方式的更新,没有出现新、老版本的Pod共存,并且共同提供服务的阶段。但是,相比于其有点,其缺点尤为明显。

    spec:
      replicas: 1
      strategy:            #更新策略
        type: Recreate     #重建更新,默认是rollingUpdate

    滚动更新(rollingUpdate)
    在删除一部分老旧版本的Pod的同时,创建新版本的Pod资源。这种更新方式的好处在于,可以维持服务的正常提供,服务运行不会中断。但是这样做的问题在于,会存在一段时间,新版本的Pod和旧版本的Pod同时提供服务,客户端接收的服务可能来源于老版本的Pod,也可能来源于新版本的Pod,这将会导致服务上的差异性。事实上,相对比与其缺点,滚动更新策略的优点更加明显,即业务连续不中断,并且新老版本Pod并存可以使得提前检验新版本Pod的可用性,如果发现更新后服务出现问题,更是可以提前发现,提前处理。同时,滚动更新的缺点也可以通过分区域更新等方式来进行解决。因此,我们最常用的更新策略就是滚动更新,并且滚动更新也是Deployment控制器的默认更新策略。

    Deployment可以保证在升级时只有一定数量的pod是down的,默认的,他会确保至少比期望的pod数量少一个是up状态

    DaemonSet

    Daemonset确保全部(或者一些)Node上运行一个pod的副本。 当有Node加入集群时,也会为它新增一个pod。当有Node从集群中删除时,这些pod也会被回收。删除Daemonset时会删除它创建的所有pod。

    使用Daemonset的一些典型用法:

  • 运行集群存储daemon,例如在每个Node上运行ceph、glusterd
  • 在每个Node上运行日志收集daemon,例如logstash、fluentd
  • 在每个Node上运行监控daemon,例如Prometheus Node Exporter
  • 文档:https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/daemonset/

    job负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或者多个pod成功结束

    特殊说明:

  • spec.template格式同pod一样
  • restartpolicy仅支持never或 onfailure
  • 单个pod时,默认pod成功运行job即 结束
  • cronjob

    cronjob管理基于时间的job,即:

    在给定时间点运行一次

    周期性的在给定时间点运行

    典型用法是:

    在给定的时间点运行job

    创建周期性的运行job,比如发送邮件,数据库备份等等。

    StateFulSet

    StateFulSet作为controller为pod提供唯一的标识,它可以保证部署和scale的顺序。

    StateFulSet是为了解决有状态服务的问题(对应的deployment和Replicaset是为无状态服务而设计),应用场景包括:

  • 稳定的持久化存储,即pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
  • 稳定的网络标识,即pod重新调度后其PodName和HostName不变,基于headless  service(即没有cluster IP 的service)来实现
  • 有序部署,有序扩展,即pod是有顺序的,在部署或者扩展时要依据定义的顺序依次进行(即从0到N-1,在下一个pod运行之前所有之前的pod都是running或者ready状态),基于init container来实现。
  • 有序收缩,有序删除
  • vim statefuset.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      ports:
      - port: 80
        name: web
      clusterIP: None
      selector:
        app: nginx
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: web
    spec:
      selector:
        matchLabels:
          app: nginx # 必须匹配 .spec.template.metadata.labels
      serviceName: "nginx"
      replicas: 3 # 默认值是 1
      template:
        metadata:
          labels:
            app: nginx # 必须匹配 .spec.selector.matchLabels
        spec:
          containers:
          - name: nginx
            image: nginx:1.21.4
            ports:
            - containerPort: 80
              name: web
    [root@master ~]# kubectl create -f statefuset.yaml 
    service/nginx created
    statefulset.apps/web created

    [root@master ~]# kubectl get pod
    NAME READY STATUS RESTARTS AGE
    web-0 1/1 Running 0 2m24s
    web-1 1/1 Running 0 2m23s
    web-2 1/1 Running 0 2m22s
    [root@master ~]#

    StatefulSet Pod 具有唯一的标识,该标识包括顺序标识、稳定的网络标识和稳定的存储。 该标识和 Pod 是绑定的,与该 Pod 调度到哪个节点上无关。

    对于具有 N 个副本的 StatefulSet,该 StatefulSet 中的每个 Pod 将被分配一个从 0 到 N-1 的整数序号,该序号在此 StatefulSet 上是唯一的。

    创建一个busybox的pod来测试一下,可以直接访问到statufulset集群内部

    [root@master ~]# kubectl run  busybox --image=busybox 
    pod/busybox created
    [root@master ~]# kubectl get pods -o wide                  
    NAME                   READY   STATUS    RESTARTS   AGE     IP              NODE    NOMINATED NODE   READINESS GATES
    busybox                1/1     Running   0          4s      10.101.11.20    node2   <none>           <none>
    web-0  (唯一标识符)     1/1     Running   0          49m     10.101.11.14    node2   <none>           <none>
    web-1                  1/1     Running   0          49m     10.101.11.15    node2   <none>           <none>
    web-2                  1/1     Running   0          49m     10.101.149.10   node1   <none>           <none>
    [root@master ~]# kubectl exec -it busybox -- sh
    / # ping web-0.nginx     # $(服务名称).$(名字空间)
    PING web-0.nginx (10.101.11.22): 56 data bytes
    64 bytes from 10.101.11.22: seq=0 ttl=63 time=0.133 ms
    64 bytes from 10.101.11.22: seq=1 ttl=63 time=0.108 ms
    64 bytes from 10.101.11.22: seq=2 ttl=63 time=0.097 ms
    64 bytes from 10.101.11.22: seq=3 ttl=63 time=0.097 ms

    statefulset更新策略

    StatefulSet 的 .spec.updateStrategy 字段让 你可以配置和禁用掉自动滚动更新 Pod 的容器、标签、资源请求或限制、以及注解。 有两个允许的值:
    OnDelet
    当 StatefulSet 的 .spec.updateStrategy.type 设置为 OnDelete 时, 它的控制器将不会自动更新 StatefulSet 中的 Pod。 用户必须手动删除 Pod 以便让控制器创建新的 Pod,以此来对 StatefulSet 的 .spec.template 的变动作出反应。
    RollingUpdate
    RollingUpdate 更新策略对 StatefulSet 中的 Pod 执行自动的滚动更新。这是默认的更新策略。

    当 StatefulSet 的 .spec.updateStrategy.type 被设置为 RollingUpdate 时, StatefulSet 控制器会删除和重建 StatefulSet 中的每个 Pod。 它将按照与 Pod 终止相同的顺序(从最大序号到最小序号)进行,每次更新一个 Pod。

    Kubernetes 控制平面会等到被更新的 Pod 进入 Running 和 Ready 状态,然后再更新其前身。 如果你设置了 .spec.minReadySeconds(查看最短就绪秒数), 控制平面在 Pod 就绪后会额外等待一定的时间再执行下一步。

    分区滚动更新(灰度发布)

     通过声明 .spec.updateStrategy.rollingUpdate.partition 的方式,RollingUpdate 更新策略可以实现分区。 如果声明了一个分区,当 StatefulSet 的 .spec.template 被更新时, 所有序号大于等于该分区序号的 Pod 都会被更新。 所有序号小于该分区序号的 Pod 都不会被更新,并且,即使它们被删除也会依据之前的版本进行重建。

    [root@master ~]# kubectl edit sts web
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      annotations:
        kubectl.kubernetes.io/last-applied-configuration: |
          {"apiVersion":"apps/v1","kind":"StatefulSet","metadata":{"annotations":{},"name":"web","namespace":"default"},"spec":{"replicas":3,"selector":{"matchLabels":{"app":"nginx"}},"serviceName":"nginx","template":{"metadata":{"labels":{"app":"nginx"}},"spec":{"containers":[{"image":"nginx:1.21.4","name":"nginx","ports":[{"containerPort":80,"name":"web"}]}]}}}}
      creationTimestamp: "2022-07-26T07:51:51Z"
      generation: 1
      name: web
      namespace: default
      resourceVersion: "57225"
      uid: 4b527fd0-6b5d-4bae-8312-d0cabb523ae3
    spec:
      podManagementPolicy: OrderedReady
      replicas: 3
      revisionHistoryLimit: 10
      selector:
        matchLabels:
          app: nginx
      serviceName: nginx
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: nginx
        spec:
          containers:
          - image: nginx:1.21.4
            imagePullPolicy: IfNotPresent
            name: nginx
            ports:
            - containerPort: 80
              name: web
              protocol: TCP
            resources: {}
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
          dnsPolicy: ClusterFirst
          restartPolicy: Always
          schedulerName: default-scheduler
          securityContext: {}
          terminationGracePeriodSeconds: 30
      updateStrategy:
        rollingUpdate:
          partition: 0  比如当replicas数目为3时,把这里的0改为3的话,当更新版本时,只有web-2才会更新。
        type: RollingUpdate
    status:
      collisionCount: 0
      currentReplicas: 3
      currentRevision: web-6cf5dbfdf7
      observedGeneration: 1
      readyReplicas: 3
      replicas: 3
      updateRevision: web-6cf5dbfdf7
      updatedReplicas: 3

     Horizontal  Pod Autoscaling 

    应用的资源使用率通常有高峰和低谷的时候,如何肖峰填谷,提高集群的整体资源使用率,让service中的pod数量自动调整呢? 这就需要Horizontal  Pod Autoscaling ,顾名思义,使pod水平缩放。