5、Kubernetes核心技术 - Controller控制器工作负载

目录

[一、Deployments - 控制器应用](#一、Deployments - 控制器应用)

二、Deployment升级回滚和弹性收缩

[2.1、创建一个 1.14 版本的 pod](#2.1、创建一个 1.14 版本的 pod)

2.2、应用升级

2.3、查看升级状态

2.4、查看历史版本

2.5、应用回滚

2.6、弹性伸缩

[三、StatefulSet - 有状态应用](#三、StatefulSet - 有状态应用)

[四、DaemonSet - 守护进程](#四、DaemonSet - 守护进程)

[五、Job - 单次任务](#五、Job - 单次任务)

[六、Cronjob - 定时任务](#六、Cronjob - 定时任务)


一、Deployments - 控制器应用

Deployment 表示用户对 K8S 集群的一次更新操作。Deployment 控制器可以部署无状态应用,管理 Pod 和 ReplicaSet、部署,滚动升级等功能。

下面是一个 Deployment 示例。

其中创建了一个 ReplicaSet,负责启动三个 nginx Pod:

vim simple-deployment.yam

bash 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment	 # 后续创建 ReplicaSet 和 Pod 的命名基础
  labels:
    app: nginx
spec:
  replicas: 3		# pod的副本数量
  selector:
    matchLabels:
      app: nginx  # 定义所创建的 ReplicaSet 如何查找要管理的 Pod
  template:
    metadata:
      labels:
        app: nginx		# pod模板标签
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

创建Deployment:

bash 复制代码
$ kubectl create -f simple-deployment.yaml 
deployment.apps/nginx-deployment created

# 查看deployment是否创建
$ kubectl get deployments
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           13s

注意 Deployment 已创建全部三个副本,并且所有副本都是最新的(它们包含最新的 Pod 模板) 并且可用。字段说明:

  • NAME 列出了名字空间中 Deployment 的名称。
  • READY 显示应用程序的可用的"副本"数。显示的模式是"就绪个数/期望个数"。
  • UP-TO-DATE 显示为了达到期望状态已经更新的副本数。
  • AVAILABLE 显示应用可供用户使用的副本数。
  • AGE 显示应用程序运行的时间。

我们可以通过**kubectl describe [deployment-name]**查看deployment的相关事件:

bash 复制代码
$ kubectl describe deploy nginx-deployment
Name:                   nginx-deployment
Namespace:              default
CreationTimestamp:      Mon, 06 Feb 2023 06:58:59 +0000
Labels:                 app=nginx
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=nginx
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:  app=nginx
  Containers:
   nginx:
    Image:        nginx:1.14.2
    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:   nginx-deployment-85996f8dbd (3/3 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  101s  deployment-controller  Scaled up replica set nginx-deployment-85996f8dbd to 3

我们看到,最下面的Scaled up replica set nginx-deployment-85996f8dbd to 3,其实就是运行三个副本的Pod,在k8s中deployment是通过ReplicaSet(副本集)来实现的,当我们创建一个deployment的时候,会自动创建一个ReplicaSet来管理pod的副本数量。

查看 Deployment 创建的 ReplicaSet(rs):

bash 复制代码
$ kubectl get rs         
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-85996f8dbd   3         3         3       3m13s

ReplicaSet 输出中包含以下字段:

  • NAME 列出名字空间中 ReplicaSet 的名称;
  • DESIRED 显示应用的期望副本个数,即在创建 Deployment 时所定义的值。 此为期望状态;
  • CURRENT 显示当前运行状态中的副本个数;
  • READY 显示应用中有多少副本可以为用户提供服务;
  • AGE 显示应用已经运行的时间长度。

注意 ReplicaSet 的名称格式始终为 [Deployment 名称]-[哈希]。 该名称将成为所创建的 Pod 的命名基础。 其中的哈希字符串与 ReplicaSet 上的 pod-template-hash 标签一致。

查看ReplicaSet相关事件:

bash 复制代码
$ kubectl describe rs nginx-deployment-85996f8dbd
Name:           nginx-deployment-85996f8dbd
Namespace:      default
Selector:       app=nginx,pod-template-hash=85996f8dbd
Labels:         app=nginx
                pod-template-hash=85996f8dbd
Annotations:    deployment.kubernetes.io/desired-replicas: 3
                deployment.kubernetes.io/max-replicas: 4
                deployment.kubernetes.io/revision: 1
Controlled By:  Deployment/nginx-deployment
Replicas:       3 current / 3 desired
Pods Status:    3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:  app=nginx
           pod-template-hash=85996f8dbd
  Containers:
   nginx:
    Image:        nginx:1.14.2
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Events:
  Type    Reason            Age    From                   Message
  ----    ------            ----   ----                   -------
  Normal  SuccessfulCreate  3m24s  replicaset-controller  Created pod: nginx-deployment-85996f8dbd-q9plt
  Normal  SuccessfulCreate  3m24s  replicaset-controller  Created pod: nginx-deployment-85996f8dbd-knwkv
  Normal  SuccessfulCreate  3m24s  replicaset-controller  Created pod: nginx-deployment-85996f8dbd-vcs8d

可以看到,replicaset-controller负责创建三个nginx的Pod。

二、Deployment升级回滚和弹性收缩

  • 升级: 假设从版本为 1.14 升级到 1.15 ,这就叫应用的升级【升级可以保证服务不中断】;
  • 回滚:从版本 1.15 变成 1.14,这就叫应用的回滚;
  • 弹性伸缩:我们根据不同的业务场景,来改变 Pod 的数量对外提供服务,这就是弹性伸缩;

2.1、创建一个 1.14 版本的 pod

bash 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: web
  name: web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: web
    spec:
      containers:
      # 修改 nginx 版本 1.14
      - image: nginx:1.14
        name: nginx
        resources: {}
status: {}

创建pod:

bash 复制代码
$ kubectl apply -f nginx.yaml

如上图,可以看到, 当前运行的nginx容器的镜像版本是1.14。

2.2、应用升级

bash 复制代码
$ kubectl set image deployment web nginx=nginx:1.15

升级过程:

java 复制代码
$ kubectl set image deployment web nginx=nginx:1.15
deployment.apps/web image updated

# 首先是开始的 nginx 1.14 版本的 Pod 在运行,然后 1.15 版本的在创建
$ kubectl get pod
NAME                   READY   STATUS              RESTARTS   AGE
web-66bf4959f5-qhzsd   1/1     Running             0          52s
web-bbcf684cb-bbmqv    0/1     ContainerCreating   0          3s

# 然后在 1.15 版本创建完成后,就会暂停 1.14 版本
$ kubectl get pod
NAME                   READY   STATUS        RESTARTS   AGE
web-66bf4959f5-qhzsd   1/1     Terminating   0          67s
web-bbcf684cb-bbmqv    1/1     Running       0          18s

# 最后把 1.14 版本的 Pod 移除,完成我们的升级
$ kubectl get pod
NAME                  READY   STATUS    RESTARTS   AGE
web-bbcf684cb-bbmqv   1/1     Running   0          33s

我们在下载 1.15 版本,容器就处于 ContainerCreating 状态,然后下载完成后,就用 1.15 版本去替换 1.14 版本了,这么做的好处就是:升级可以保证服务不中断。

2.3、查看升级状态

bash 复制代码
$ kubectl rollout status deployment web
deployment "web" successfully rolled out

2.4、查看历史版本

bash 复制代码
$ kubectl rollout history deployment web
deployment.apps/web 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

2.5、应用回滚

bash 复制代码
# 回滚到上一版本
$ kubectl rollout undo deployment web

# 回滚到指定版本
$ kubectl rollout undo deployment web --to-revision=2

如上图,可以看到,通过kubectl rollout undo成功回滚到上一个版本,镜像版本又变成1.14了。当然还可以指定--to-revision回滚到指定的版本。

2.6、弹性伸缩

bash 复制代码
# 创建5个pod副本
$ kubectl scale deployment web --replicas=5
deployment.apps/web scaled

# 输出结果,等一会就会全部 Running
$ kubectl get pod
NAME                   READY   STATUS    RESTARTS   AGE
web-5b9d46fdff-2v2rt   1/1     Running   0          24s
web-5b9d46fdff-4lz7w   1/1     Running   0          24s
web-5b9d46fdff-7tq9x   1/1     Running   0          3m42s
web-5b9d46fdff-mfqhb   1/1     Running   0          24s
web-5b9d46fdff-sfx6q   1/1     Running   0          24s

三、StatefulSet - 有状态应用

Deployment控制器设计原则:管理的所有Pod一模一样,提供同一个服务,也不考虑在哪台Node 运行,可随意扩容和缩容。这种应用称为"无状态",例如Web服务。

在实际的场景中,并不能满足所有应用,尤其是分布式应用,会部署多个实例,这些实例之间往往有依赖关系,例如主从关系、主备关系,这种应用称为"有状态",例如MySQL主从、Etcd集群。

这时候就需要有状态部署了,有状态部署有以下几个特点:

  • 1、每个pod角色不同(不对等)
  • 2、pod之间有连接关系
  • 3、每个pod都有独立的存储

StatefulSet控制器用于部署有状态应用,满足一些有状态应用的需求:

• Pod有序的部署、扩容、删除和停止;

• Pod分配一个稳定的且唯一的网络标识;

• Pod分配一个独享的存储;

稳定的Pod网络标识:使用Headless Service(相比普通Service只是将spec.clusterIP定义为None)。

维护Pod网络身份,会为每个Pod分配一个数字编号并且按照编号顺序部署。

稳定主要体现在主机名和Pod A记录:

• 主机名:<statefulset名称>-<编号>

• Pod DNS A记录:<statefulset名称-编号>.<service-name> .<namespace>.svc.cluster.local

通过一个StatefulSet有状态应用的例子来说明:

准备sta.yaml文件:

bash 复制代码
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: default
  labels: 
     app: nginx
spec:
  clusterIP: None
  ports:
  - port: 80
    name: nginx
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: ClusterIP

---

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx-statefulset
  namespace: default
spec:
  serviceName: nginx
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx

创建并查看pod:

bash 复制代码
$ kubectl apply -f sta.yaml 
service/nginx created
statefulset.apps/nginx-statefulset created

$ kubectl get pods
NAME                  READY   STATUS    RESTARTS   AGE
nginx-statefulset-0   1/1     Running   0          62s
nginx-statefulset-1   1/1     Running   0          43s
nginx-statefulset-2   1/1     Running   0          39s

可以看到,每个pod都有一个唯一的名称。

bash 复制代码
[root@localhost ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   13m
nginx        ClusterIP   None         <none>        80/TCP    110s

可以看到,CULSTER-IP为None,说明这是一个Headless Service。

四、DaemonSet - 守护进程

DaemonSet 确保全部节点上都运行一个 Pod 的副本。 当有节点加入集群时, 也会为他们新增一个 Pod 。 当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。

DaemonSet 的一些典型用法:

  • 在每个节点上运行集群守护进程
  • 在每个节点上运行日志收集守护进程
  • 在每个节点上运行监控守护进程

一种简单的用法是为每种类型的守护进程在所有的节点上都启动一个 DaemonSet。 一个稍微复杂的用法是为同一种守护进程部署多个 DaemonSet;每个具有不同的标志, 并且对不同硬件类型具有不同的内存、CPU 要求。

DaemonSet示例:

vim daemonset.yaml

bash 复制代码
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx

创建并查看pod:

bash 复制代码
# 当前集群中存在两个节点
$ kubectl get nodes
NAME           STATUS   ROLES           AGE     VERSION
controlplane   Ready    control-plane   2d17h   v1.26.0
node01         Ready    <none>          2d16h   v1.26.0

$ kubectl apply -f daemonset.yaml 
daemonset.apps/nginx created

# nginx pod在两个节点都处于运行状态
$ kubectl get pod -o wide
NAME          READY   STATUS    RESTARTS   AGE   IP            NODE           NOMINATED NODE   READINESS GATES
nginx-frmjc   1/1     Running   0          6s    192.168.1.4   node01         <none>           <none>
nginx-qdb7s   1/1     Running   0          6s    192.168.0.8   controlplane   <none>           <none>

五、Job - 单次任务

Job 会创建一个或者多个 Pod,并将继续重试 Pod 的执行,直到指定数量的 Pod 成功终止。 随着 Pod 成功结束,Job 跟踪记录成功完成的 Pod 个数。 当数量达到指定的成功个数阈值时,任务(即 Job)结束。 删除 Job 的操作会清除所创建的全部 Pod。 挂起 Job 的操作会删除 Job 的所有活跃 Pod,直到 Job 被再次恢复执行。

示例 Job:下面是一个 Job 配置示例。它负责计算 π 到小数点后 2000 位,并将结果打印出来。 此计算大约需要 10 秒钟完成。

vim job.yaml

java 复制代码
apiVersion: batch/v1
kind: Job
metadata:
  name: pi-job
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl:5.34.0
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4

创建并查看job:

bash 复制代码
$ kubectl apply -f job.yaml 
job.batch/pi-job created

$ kubectl get job
NAME     COMPLETIONS   DURATION   AGE
pi-job   1/1           30s        82s

$ kubectl describe job pi-job
Name:             pi-job
Namespace:        default
Selector:         controller-uid=63b08866-0f04-4326-98ac-08118ec419d7
Labels:           controller-uid=63b08866-0f04-4326-98ac-08118ec419d7
                  job-name=pi-job
Annotations:      batch.kubernetes.io/job-tracking: 
Parallelism:      1
Completions:      1
Completion Mode:  NonIndexed
Start Time:       Sun, 29 Jan 2023 07:48:01 +0000
Completed At:     Sun, 29 Jan 2023 07:48:31 +0000
Duration:         30s
Pods Statuses:    0 Active (0 Ready) / 1 Succeeded / 0 Failed
Pod Template:
  Labels:  controller-uid=63b08866-0f04-4326-98ac-08118ec419d7
           job-name=pi-job
  Containers:
   pi:
    Image:      perl:5.34.0
    Port:       <none>
    Host Port:  <none>
    Command:
      perl
      -Mbignum=bpi
      -wle
      print bpi(2000)
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Events:
  Type    Reason            Age   From            Message
  ----    ------            ----  ----            -------
  Normal  SuccessfulCreate  84s   job-controller  Created pod: pi-job-q7h7c
  Normal  Completed         54s   job-controller  Job completed

要查看 Job 对应的已完成的 Pod,可以执行 kubectl get pod:

bash 复制代码
$ kubectl get pod
NAME           READY   STATUS      RESTARTS   AGE
pi-job-q7h7c   0/1     Completed   0          117s

# 查看Pod的标准输出
$ kubectl logs pi-job-q7h7c
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275901

六、Cronjob - 定时任务

CronJob 创建基于时隔重复调度的 Job。

CronJob 用于执行排期操作,例如备份、生成报告等。 一个 CronJob 对象就像 Unix 系统上的 crontab(cron table)文件中的一行。 它用 Cron 格式进行编写, 并周期性地在给定的调度时间执行 Job。

CronJob示例:下面的 CronJob 示例清单会在每分钟打印出当前时间和问候消息

vim cronjob.yaml

bash 复制代码
apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello-cronjob
spec:
  schedule: "* * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: busybox
            image: busybox:1.28
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

创建并查看cronjob:

bash 复制代码
$ kubectl create -f cronjob.yaml 
cronjob.batch/hello-cronjob created

$ kubectl get cronjob
NAME            SCHEDULE    SUSPEND   ACTIVE   LAST SCHEDULE   AGE
hello-cronjob   * * * * *   False     0        <none>          6s

$ kubectl describe cronjob hello-cronjob
Name:                          hello-cronjob
Namespace:                     default
Labels:                        <none>
Annotations:                   <none>
Schedule:                      * * * * *
Concurrency Policy:            Allow
Suspend:                       False
Successful Job History Limit:  3
Failed Job History Limit:      1
Starting Deadline Seconds:     <unset>
Selector:                      <unset>
Parallelism:                   <unset>
Completions:                   <unset>
Pod Template:
  Labels:  <none>
  Containers:
   busybox:
    Image:      busybox:1.28
    Port:       <none>
    Host Port:  <none>
    Command:
      /bin/sh
      -c
      date; echo Hello from the Kubernetes cluster
    Environment:     <none>
    Mounts:          <none>
  Volumes:           <none>
Last Schedule Time:  Sun, 29 Jan 2023 07:57:00 +0000
Active Jobs:         hello-cronjob-27916317
Events:
  Type    Reason            Age   From                Message
  ----    ------            ----  ----                -------
  Normal  SuccessfulCreate  1s    cronjob-controller  Created job hello-cronjob-27916317

查看cronjob生成的pod:

bash 复制代码
$ kubectl get pod
NAME                           READY   STATUS      RESTARTS   AGE
hello-cronjob-27916317-zdc9d   0/1     Completed   0          100s
hello-cronjob-27916318-nx65t   0/1     Completed   0          40s

$ kubectl logs hello-cronjob-27916317-zdc9d
Sun Jan 29 07:57:02 UTC 2023
Hello from the Kubernetes cluster

$ kubectl logs hello-cronjob-27916318-nx65t
Sun Jan 29 07:58:00 UTC 2023
Hello from the Kubernetes cluster

可以看到,cronjob每分钟就会生成一个对应的pod,然后日志输出当前时间和对应的提示消息。

相关推荐
西西小飞龙30 分钟前
Docker 基础使用
docker·容器·eureka
再ZzZ1 小时前
Docker安装PaddleOCR并提供接口服务(CPU)
运维·docker·容器
国际云,接待2 小时前
微软云注册被阻止怎么解决?
服务器·网络·microsoft·云原生·微软·云计算
IguoChan3 小时前
8. Redis Operator (1) —— 单机部署
kubernetes
老实巴交的麻匪4 小时前
可观测性 | Grafana Loki 日志聚合方案快速体验
运维·云原生·容器
weixin_428498494 小时前
Docker run 子命令与运行优化相关的参数
docker·容器
dsd23335 小时前
K8S 专栏 —— Pod 篇
docker·容器·kubernetes
虚妄狼6 小时前
【Docker】docker 常用命令
运维·docker·容器
风清再凯7 小时前
k8s的开篇学习和安装
学习·容器·kubernetes
炎码工坊7 小时前
DevSecOps实践:CI/CD流水线集成动态安全测试(DAST)工具
安全·网络安全·微服务·云原生·安全架构