四、Kubernetes 调度资源

四、Kubernetes 调度资源

1、无状态应用管理 Deployment

1.1 Deployment基础概念及使用场景

Deployment是k8s的无状态资源调度器,可以使用声明式的方式描述应用的期望状态,之后由Deployment控制器自动将当前状态改变为期望状态。

  • Deployment通过RS管理Pod,同时提供了如下的能力:
    • 声明式创建和更新
    • 自动化部署和回滚
    • 一键式缩容
    • 自动灾难修复
    • 更高级的更新方式

Deployment一般用于部署公司的无状态服务,这个也是最常用的控制器,因为企业内部限制都是以微服务为主,而微服务实现无状态化也是最佳实践,可以利用Deployment的高级功能做到无缝迁移、自动扩容缩容、自动灾难恢复、一键回滚等功能。

  • Java
  • Go
  • Vue
  • PHP等业务容器
  • 其它任何无状态服务

1.2 创建 Deployment

# 生成一个 Deployment 的 Yaml:
kubectl create deploy nginx --replicas=3 --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable --dry-run=client -oyaml > deploy.yaml

[root@k8s-master01 ~]# cat deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable
        name: nginx
        resources: {}
status: {}

示例解析:

  • nginx:Deployment的名称;
  • replicas: 创建Pod的副本数;
  • selector:定义Deployment如何找到要管理的Pod,与template的label(标签)对应,apiVersion为apps/v1必须指定该字段;
  • template字段包含以下字段:
    • app: nginx使用label(标签)标记Pod;
    • spec:表示Pod运行一个名字为nginx的容器;
    • image:运行此Pod使用的镜像;
    • Port:容器用于发送和接收流量的端口
# 使用 kubectl create 创建此 Deployment:
[root@k8s-master01 ~]# kubectl create -f deploy.yaml

# 使用 kubectl get 或者 kubectl describe 查看此 Deployment 的状态:
[root@k8s-master01 ~]# kubectl get po 
NAME                     READY   STATUS    RESTARTS   AGE
nginx-67bfb68c7d-85dg2   1/1     Running   0          18s
nginx-67bfb68c7d-fqzp4   1/1     Running   0          18s
nginx-67bfb68c7d-t6zcc   1/1     Running   0          18s
  • NAME:集群中Deployment的名称;
    • READY:Pod就绪个数和总副本数;
    • UP-TO-DATE:显示已达到期望状态的被更新的副本数;
    • AVAILABLE:显示用户可以使用的应用程序副本数,当前为0,说明目前还没有达到期望的Pod;
    • AGE:显示应用程序运行的时间。
# 可以使用 rollout 命令查看整个 Deployment 创建的状态:
[root@k8s-master01 ~]# kubectl rollout status deploy nginx
deployment "nginx" successfully rolled out

# 当 rollout 结束时,再次查看此 Deployment,可以看到 AVAILABLE 的数量和 yaml 文件中定义的 replicas 相同:
[root@k8s-master01 ~]# kubectl get deploy
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   3/3     3            3           46s

# 查看此 Deployment 当前对应的 ReplicaSet:
[root@k8s-master01 ~]# kubectl get rs -l app=nginx
NAME               DESIRED   CURRENT   READY   AGE
nginx-67bfb68c7d   3         3         3       71s
  • DESIRED:应用程序副本数;
  • CURRENT:当前正在运行的副本数;
  • READY:有多少副本是正常的

当 Deployment 有过更新,对应的 RS 可能不止一个,可以通过-o yaml 获取当前对应的 RS
是哪个,其余的 RS 为保留的历史版本,用于回滚等操作。

查看此 Deployment 创建的 Pod,可以看到 Pod 的 hash 值 5c689d88bb 和上述 Deployment 对
应的 ReplicaSet 的 hash 值一致:

[root@k8s-master01 ~]# kubectl get po --show-labels
NAME                     READY   STATUS    RESTARTS   AGE   LABELS
nginx-67bfb68c7d-85dg2   1/1     Running   0          87s   app=nginx,pod-template-hash=67bfb68c7d
nginx-67bfb68c7d-fqzp4   1/1     Running   0          87s   app=nginx,pod-template-hash=67bfb68c7d
nginx-67bfb68c7d-t6zcc   1/1     Running   0          87s   app=nginx,pod-template-hash=67bfb68c7d

1.3 更新 Deployment

注意:当且仅当 Deployment 的 Pod 模板(即.spec.template)更改时,才会触发 Deployment 更新,例如更改内存、CPU 配置或者容器的 image。

# 假如更新 Nginx Pod 的 image 使用 nginx:latest,并使用--record 记录当前更改的参数,后期回滚时可以查看到对应的信息:
[root@k8s-master01 ~]# kubectl set image deployment nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15 --record


# 同样可以使用 kubectl rollout status 查看更新过程:
[root@k8s-master01 ~]# kubectl rollout status deploy nginx
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


# 可以看出更新过程为新旧交替更新,首先新建一个 Pod,当 Pod 状态为 Running 时,删除一个旧的 Pod,同时再创建一个新的 Pod。当触发一个更新后,会有新的 ReplicaSet 产生,旧的 ReplicaSet 会被保存,查看此时 ReplicaSet,可以从 AGE 或 READY 看出来新旧 ReplicaSet:
[root@k8s-master01 ~]# kubectl get rs
NAME               DESIRED   CURRENT   READY   AGE
nginx-5f58c9c676   3         3         3       74s
nginx-67bfb68c7d   0         0         0       3m38s


# 通过 describe 查看 Deployment 的详细信息:
[root@k8s-master01 ~]# kubectl describe deploy nginx
....
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  4m5s  deployment-controller  Scaled up replica set nginx-67bfb68c7d from 0 to 3
  Normal  ScalingReplicaSet  101s  deployment-controller  Scaled up replica set nginx-5f58c9c676 from 0 to 1
  Normal  ScalingReplicaSet  99s   deployment-controller  Scaled down replica set nginx-67bfb68c7d from 3 to 2
  Normal  ScalingReplicaSet  99s   deployment-controller  Scaled up replica set nginx-5f58c9c676 from 1 to 2
  Normal  ScalingReplicaSet  97s   deployment-controller  Scaled down replica set nginx-67bfb68c7d from 2 to 1
  Normal  ScalingReplicaSet  97s   deployment-controller  Scaled up replica set nginx-5f58c9c676 from 2 to 3
  Normal  ScalingReplicaSet  95s   deployment-controller  Scaled down replica set nginx-67bfb68c7d from 1 to 0
# 当然也可以使用 edit 命令直接编辑 Deployment,效果相同:
[root@k8s-master01 ~]# kubectl edit deployment nginx

# 修改成2个pod
[root@k8s-master01 ~]# kubectl get po
NAME                     READY   STATUS    RESTARTS   AGE
nginx-5f58c9c676-n7hzm   1/1     Running   0          4m34s
nginx-5f58c9c676-qd2ks   1/1     Running   0          4m32s

1.4 回滚 Deployment

# 当更新了版本不稳定或配置不合理时,可以对其进行回滚操作,假设我们又进行了几次更新
(此处以更新镜像版本触发更新,更改配置效果类似):
[root@k8s-master01 ~]# kubectl set image deployment nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/slow:latest --record

[root@k8s-master01 ~]# kubectl set image deployment nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/redis:7.2.5 --record
# 使用 kubectl rollout history 查看更新历史:
[root@k8s-master01 ~]# kubectl rollout history deploy nginx
deployment.apps/nginx 
REVISION  CHANGE-CAUSE
1         <none>
2         kubectl set image deployment nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15 --record=true
3         kubectl set image deployment nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/slow:latest --record=true
4         kubectl set image deployment nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/redis:7.2.5 --record=true

# 查看 Deployment 某次更新的详细信息,使用--revision 指定某次更新版本号:
# kubectl rollout history deploy nginx --revision=2
# 如果只需要回滚到上一个稳定版本,使用 kubectl rollout undo 即可:
[root@k8s-master01 ~]# kubectl rollout undo deploy nginx
deployment.apps/nginx rolled back

# 查看更新历史
[root@k8s-master01 ~]# kubectl rollout history deploy nginx
deployment.apps/nginx 
REVISION  CHANGE-CAUSE
1         <none>
2         kubectl set image deployment nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15 --record=true
4         kubectl set image deployment nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/redis:7.2.5 --record=true
5         kubectl set image deployment nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/slow:latest --record=true

# 回滚到了上一个版本(回滚之前是版本四)生成了一个版本五,上一个版本三消失了
# 回滚到指定版本
[root@k8s-master01 ~]# kubectl rollout undo deploy nginx --to-revision=2
deployment.apps/nginx rolled back

[root@k8s-master01 ~]# kubectl rollout history deploy nginx
deployment.apps/nginx 
REVISION  CHANGE-CAUSE
1         <none>
4         kubectl set image deployment nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/redis:7.2.5 --record=true
5         kubectl set image deployment nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/slow:latest --record=true
6         kubectl set image deployment nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15 --record=true

# 版本二消失了,生成了版本六

1.5 暂停和恢复 Deployment 更新

上述演示的均为更改某一处的配置,更改后立即触发更新,大多数情况下可能需要针对一个资源文件更改多处地方,而并不需要多次触发更新,此时可以使用 Deployment 暂停功能,临时禁用更新操作,对 Deployment 进行多次修改后在进行更新。

# 使用 kubectl rollout pause 命令即可暂停 Deployment 更新:
[root@k8s-master01 ~]# kubectl rollout pause deploy nginx

# 然后对 Deployment 进行相关更新操作,比如先更新镜像,然后对其资源进行限制(如果使用的是 kubectl edit 命令,可以直接进行多次修改,无需暂停更新,kubectl set 命令一般会集成在CICD 流水线中):
[root@k8s-master01 ~]# kubectl set image deploy nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable --record=true

[root@k8s-master01 ~]# kubectl set resources deployment nginx -c=nginx --limits=cpu=200m,memory=512Mi
# 通过 rollout history 可以看到没有新的更新
[root@k8s-master01 ~]# kubectl rollout history deploy nginx
deployment.apps/nginx 
REVISION  CHANGE-CAUSE
4         kubectl set image deployment nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/redis:7.2.5 --record=true
5         kubectl set image deployment nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/slow:latest --record=true
6         kubectl set image deployment nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15 --record=true
7         kubectl set image deploy nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable --record=true

# 检查pod是否有更新
[root@k8s-master01 ~]# kubectl get po
NAME                     READY   STATUS    RESTARTS   AGE
nginx-5f58c9c676-w6dt7   1/1     Running   0          41m
nginx-5f58c9c676-wxzjv   1/1     Running   0          41m

# 检查rs是否有更新
[root@k8s-master01 ~]# kubectl get rs
NAME               DESIRED   CURRENT   READY   AGE
nginx-5f58c9c676   2         2         2       51m
....
# 进行完最后一处配置更改后,使用 kubectl rollout resume 恢复 Deployment 更新:
[root@k8s-master01 ~]# kubectl rollout resume deploy nginx

# 可以查看到恢复更新的 Deployment 创建了一个新的 RS(ReplicaSet 缩写):
[root@k8s-master01 ~]# kubectl get po
NAME                    READY   STATUS    RESTARTS   AGE
nginx-588b94db6-62465   1/1     Running   0          6s
nginx-588b94db6-bq84w   1/1     Running   0          8s

[root@k8s-master01 ~]# kubectl get rs
NAME               DESIRED   CURRENT   READY   AGE
nginx-588b94db6    2         2         2       11s

1.6 历史版本清理策略

在默认情况下,revision 保留 10 个旧的 ReplicaSet,其余的将在后台进行垃圾回收,可以在.spec.revisionHistoryLimit 设置保留 ReplicaSet 的个数。当设置为 0 时,不保留历史记录。

1.7 扩容 Deployment

# 使用 kubectl scale 动态调整 Pod 的副本数,比如增加 Pod 为 5 个
[root@k8s-master01 ~]# kubectl scale deploy nginx --replicas=5

# 查看 Pod,此时 Pod 已经变成了 5 个:
[root@k8s-master01 ~]# kubectl get po
NAME                    READY   STATUS    RESTARTS   AGE
nginx-588b94db6-62465   1/1     Running   0          111s
nginx-588b94db6-bq84w   1/1     Running   0          113s
nginx-588b94db6-f2fql   1/1     Running   0          3s
nginx-588b94db6-fw6sh   1/1     Running   0          3s
nginx-588b94db6-nzt5m   1/1     Running   0          3s
# 如果缩容也是这个命令,把数量改小就行
[root@k8s-master01 ~]# kubectl scale deploy nginx --replicas=3

# 查看 Pod,此时 Pod 已经变成了 3 个:
[root@k8s-master01 ~]# kubectl get po
NAME                    READY   STATUS    RESTARTS   AGE
nginx-588b94db6-62465   1/1     Running   0          4m11s
nginx-588b94db6-bq84w   1/1     Running   0          4m13s
nginx-588b94db6-nzt5m   1/1     Running   0          2m23s

1.8 Deployment 更新策略

  • Recreate:重建,先删掉所有旧的 Pod 再创建新的 Pod(不推荐使用)
  • RollingUpdate:滚动更新,先创建新的 Pod,在删除旧的 Pod,RollingUpdate 可以指定 maxUnavailable 和 maxSurge 定制化更新策略
    • .spec.strategy.rollingUpdate.maxUnavailable:指定在回滚更新时最大不可用的Pod 数量,可选字段,默认为 25%,可以设置为数字或百分比,如果 maxSurge 为0,则该值不能为 0;
    • .spec.strategy.rollingUpdate.maxSurge 可以超过期望值的最大Pod数,可选字段,默认为 25%,可以设置成数字或百分比,如果 maxUnavailable 为 0,则该值不能为 0。
# 为了更好的演示把pod扩容到10个
[root@k8s-master01 ~]# kubectl scale deploy nginx --replicas=10

# 把deploy倒成yaml文件
[root@k8s-master01 ~]# kubectl get deploy nginx -o yaml > deploy.yaml 

# 删除一些不必要到配置以及加入检查方式
[root@k8s-master01 ~]# vim deploy.yaml 
[root@k8s-master01 ~]# cat deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "8"
    kubernetes.io/change-cause: kubectl set image deploy nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable
      --record=true
  creationTimestamp: "2025-06-11T00:46:20Z"
  generation: 14
  labels:
    app: nginx
  name: nginx
  namespace: default
  resourceVersion: "101030"
  uid: c983eb96-ac4b-4f72-9af7-5feabd972598
spec:
  progressDeadlineSeconds: 600
  replicas: 10
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: nginx
  strategy:
    rollingUpdate:
      maxSurge: 20%             # 最大期望值20%(增加20%)
      maxUnavailable: 20%       # 最大不可用20%(删除20%)
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable
        imagePullPolicy: IfNotPresent
        name: nginx
        readinessProbe:
          tcpSocket:
            port: 80
          initialDelaySeconds: 10
          timeoutSeconds: 2
          periodSeconds: 5
          successThreshold: 1
          failureThreshold: 2
        livenessProbe:
          tcpSocket:
            port: 80
          initialDelaySeconds: 10
          timeoutSeconds: 2
          periodSeconds: 5
          successThreshold: 1
          failureThreshold: 2
        resources:
          limits:
            cpu: 200m
            memory: 512Mi
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
# 更新配置
[root@k8s-master01 ~]# kubectl replace -f deploy.yaml 
deployment.apps/nginx replaced

# 查看pod更新情况
[root@k8s-master01 ~]# kubectl get po
NAME                    READY   STATUS              RESTARTS   AGE
nginx-588b94db6-28vcv   1/1     Running             0          9m6s
nginx-588b94db6-62465   1/1     Running             0          46m
nginx-588b94db6-bq84w   1/1     Running             0          46m
nginx-588b94db6-l6hpm   1/1     Running             0          9m6s
nginx-588b94db6-nzt5m   1/1     Running             0          44m
nginx-588b94db6-pwcj6   1/1     Running             0          9m6s
nginx-588b94db6-r8nnc   1/1     Running             0          9m6s
nginx-588b94db6-rpdtz   1/1     Running             0          9m6s
nginx-7f4cfbf7d-dvbdt   0/1     ContainerCreating   0          2s
nginx-7f4cfbf7d-fm5r7   0/1     Pending             0          1s
nginx-7f4cfbf7d-mdv7n   0/1     Pending             0          1s
nginx-7f4cfbf7d-x5928   0/1     ContainerCreating   0          2s

# 解析
    rollingUpdate:
      maxSurge: 20%             # 最大期望值20%(增加20%)
      maxUnavailable: 20%       # 最大不可用20%(删除20%)
      
# 1、目前一共10个pod
# 2、maxUnavailable: 20%,就是说我一次性可以删除 10*20%=2 个pod
# 3、maxSurge: 20%,就是说我一次性可以建立 10*20% + (maxUnavailable删除的)10*20% = 4个pod
# 4、所以第一次更新就是8个旧pod(删除2个),最大可建立 + 最大不可用 = 目前更新的pod

1.9 使用 Deployment 部署前端服务

# Docker 启动命令:
docker run -d -p 10080:80 crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/vue:v1
# 生成一个yaml文件
[root@k8s-master01 ~]# vim vue.yaml 
[root@k8s-master01 ~]# cat vue.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: vue
  name: vue
spec:
  replicas: 2
  selector:
    matchLabels:
      app: vue
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: vue
    spec:
      containers:
      - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/vue:v1
        name: vue
        readinessProbe:
          tcpSocket:
            port: 80
          initialDelaySeconds: 10
          timeoutSeconds: 2
          periodSeconds: 5
          successThreshold: 1
          failureThreshold: 2
        livenessProbe:
          tcpSocket:
            port: 80
          initialDelaySeconds: 10
          timeoutSeconds: 2
          periodSeconds: 5
          successThreshold: 1
          failureThreshold: 2
        resources:
          limits:
            cpu: 200m
            memory: 512Mi
        resources: {}
status: {}

# 创建前端服务
[root@k8s-master01 ~]# kubectl create -f vue.yaml 

# 查看pod
[root@k8s-master01 ~]# kubectl get po
NAME                   READY   STATUS    RESTARTS   AGE
vue-75769f4d64-f8zz2   1/1     Running   0          29s
vue-75769f4d64-s94mn   1/1     Running   0          29s

# 查看部署节点IP
[root@k8s-master01 ~]# kubectl get po vue-75769f4d64-f8zz2 -owide
NAME                   READY   STATUS    RESTARTS   AGE     IP               NODE         NOMINATED NODE   READINESS GATES
vue-75769f4d64-f8zz2   1/1     Running   0          7m51s   192.168.58.255   k8s-node02   <none>           <none>

# 验证服务是否成功启动
[root@k8s-master01 ~]# curl 192.168.58.255:80
<!DOCTYPE html><html><head><meta charset=utf-8><title>vue-project</title><link href=/static/css/app.30790115300ab27614ce176899523b62.css rel=stylesheet></head><body><h1>Vue Project For DevOps</h1><a href=https://edu.51cto.com/lecturer/11062970.html>人生苦短,我学k8s</h2><script type=text/javascript src=/static/js/manifest.2ae2e69a05c33dfc65f8.js></script><script type=text/javascript src=/static/js/vendor.b38abd1e8f82054d7d19.js></script><script type=text/javascript src=/static/js/app.b22ce679862c47a75225.js></script></body></html>

1.10 使用 Deployment 部署 Go 语言服务

# Docker 启动命令:
docker run -d -p 18080:8080 crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/go:v1
# 生成一个yaml文件
[root@k8s-master01 ~]# vim go.yaml 
[root@k8s-master01 ~]# cat go.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: go
  name: go
spec:
  replicas: 2
  selector:
    matchLabels:
      app: go
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: go
    spec:
      containers:
      - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/go:v1
        name: go
        readinessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 10
          timeoutSeconds: 2
          periodSeconds: 5
          successThreshold: 1
          failureThreshold: 2
        livenessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 10
          timeoutSeconds: 2
          periodSeconds: 5
          successThreshold: 1
          failureThreshold: 2
        resources:
          limits:
            cpu: 200m
            memory: 512Mi
        resources: {}
status: {}

# 创建前端服务
[root@k8s-master01 ~]# kubectl create -f go.yaml 

# 查看pod
[root@k8s-master01 ~]# kubectl get po
NAME                  READY   STATUS    RESTARTS   AGE
go-595c968884-whk86   1/1     Running   0          21s
go-595c968884-wnhzn   1/1     Running   0          21s

# 查看部署节点IP
[root@k8s-master01 ~]# kubectl get po go-595c968884-whk86 -owide
NAME                  READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
go-595c968884-whk86   1/1     Running   0          65s   192.168.85.226   k8s-node01   <none>           <none>

# 验证服务是否成功启动
[root@k8s-master01 ~]# curl 192.168.85.226:8080
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<title>Not Found</title>
		<style type="text/css">
....

1.11 使用 Deployment 部署 Java 服务

# Docker 启动命令:
docker run -d -p 18761:8761 crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/java:v1

# 可选环境变量:
JAVA_TOOL_OPTIONS:-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -Xms512m -Xmx512m -Xss256K -Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF-8 
SPRING_PROFILES_ACTIVE:prod
# 生成一个yaml文件
[root@k8s-master01 ~]# vim java.yaml 
[root@k8s-master01 ~]# cat java.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: java
  name: java
spec:
  replicas: 2
  selector:
    matchLabels:
      app: java
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: java
    spec:
      containers:
      - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/java:v1
        name: java
        env:
          - name: JAVA_TOOL_OPTIONS
            value: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -Xms512m -Xmx512m -Xss256K -Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF-8
          - name: SPRING_PROFILES_ACTIVE
            value: prod
        startupProbe:
          tcpSocket:
            port: 8761
          initialDelaySeconds: 10
          timeoutSeconds: 2
          periodSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        readinessProbe:
          tcpSocket:
            port: 8761
          initialDelaySeconds: 10
          timeoutSeconds: 2
          periodSeconds: 5
          successThreshold: 1
          failureThreshold: 2
        livenessProbe:
          tcpSocket:
            port: 8761
          initialDelaySeconds: 10
          timeoutSeconds: 2
          periodSeconds: 5
          successThreshold: 1
          failureThreshold: 2
        resources:
          limits:
            cpu: 200m
            memory: 512Mi
        resources: {}
status: {}

# 创建前端服务
[root@k8s-master01 ~]# kubectl create -f java.yaml 

# 查看pod
[root@k8s-master01 ~]# kubectl get po
NAME                    READY   STATUS    RESTARTS   AGE
java-695d6857b8-tq9pd   1/1     Running   0          27s
java-695d6857b8-wpzmp   1/1     Running   0          27s

# 查看部署节点IP
[root@k8s-master01 ~]# kubectl get po java-695d6857b8-tq9pd -owide
NAME                    READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
java-695d6857b8-tq9pd   1/1     Running   0          46s   192.168.85.239   k8s-node01   <none>           <none>

# 验证服务是否成功启动
[root@k8s-master01 ~]# curl 192.168.85.239:8761
<!doctype html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
  <head>
    <base href="/">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
....

2、有状态应用管理 StatefulSet

2.1 StatefulSet基础概念及使用场景

StatefulSet(有状态集,缩写为sts)是k8s的有状态资源调度器,可以使用声明式的方式描述应用的期望状态,之后由 StatefulSet 控制器自动且有序的将当前状态改编为期望状态,常用于部署有状态的且需要有序启动的应用程序,比如MySQL、ZooKeeper集群等。

StatefulSet 基于 Headless Service给每个实例创建一个唯一且固定的标识,之后各实例之间可以通过该标识符进行通信。

StatefulSet常用于有如下需求的场景

  • 需要稳定的独一无二的网络标识符;
  • 需要稳定的持久化数据;
  • 需要有序的、优雅的部署和扩展;
  • 需要有序的自动滚动更新

2.2 定义一个 StatefulSet 资源文件

# 创建一个模版
[root@k8s-master01 ~]# kubectl create service clusterip nginx --tcp=80:80 --clusterip="None" --dry-run=client -oyaml > sts.yaml

[root@k8s-master01 ~]# kubectl create deploy nginx --replicas=2 --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable --dry-run=client -oyaml >> sts.yaml 

# 定义一个 StatefulSet 资源文件
[root@k8s-master01 ~]# vim sts.yaml 
[root@k8s-master01 ~]# cat sts.yaml 
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  clusterIP: None
  ports:
  - name: web
    port: 80
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable
        name: nginx
        ports:
        - containerPort: 80
          name: web

其中:
kind: Service定义了一个名字为Nginx的Headless Service,创建的Service格式为nginx0.nginx.default.svc.cluster.local,其他的类似,因为没有指定Namespace(命名空间),所以默认部署在default;

当 StatefulSet 控制器创建 Pod 时,它会添加一个标签statefulset.kubernetes.io/pod-name,该标签的值为 Pod 的名称,用于匹配 Service。

# 创建 StatefulSet
[root@k8s-master01 ~]# kubectl create -f sts.yaml 

# 查看pod创建过程(一个创建完毕才会创建下一个)
[root@k8s-master01 ~]# kubectl get po
NAME    READY   STATUS              RESTARTS   AGE
web-0   0/1     ContainerCreating   0          1s
[root@k8s-master01 ~]# kubectl get po
NAME    READY   STATUS              RESTARTS   AGE
web-0   1/1     Running             0          2s
web-1   0/1     ContainerCreating   0          1s
[root@k8s-master01 ~]# kubectl get po
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          3s
web-1   1/1     Running   0          2s

[root@k8s-master01 ~]# kubectl get sts
NAME   READY   AGE
web    2/2     12s

[root@k8s-master01 ~]# kubectl get svc nginx
NAME    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   None         <none>        80/TCP    40s

2.3 StatefulSet 扩容和缩容

和 Deployment 类似,可以通过更新 replicas 字段扩容/缩容 StatefulSet,也可以使用 kubectl scalekubectl editkubectl patch 来扩容/缩容一个 StatefulSet。

# 扩容,将上述创建的 sts 副本增加到 5 个:
[root@k8s-master01 ~]# kubectl scale sts web --replicas=5

# 可使用以下命令动态查看(同样一个创建完毕才会创建下一个)
[root@k8s-master01 ~]# kubectl get po -w -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          6m14s
web-1   1/1     Running   0          6m12s
web-2   0/1     Pending   0          0s
web-2   0/1     Pending   0          0s
web-2   0/1     ContainerCreating   0          0s
web-2   0/1     ContainerCreating   0          1s
web-2   1/1     Running             0          2s
web-3   0/1     Pending             0          0s
web-3   0/1     Pending             0          0s
web-3   0/1     ContainerCreating   0          0s
web-3   0/1     ContainerCreating   0          1s
web-3   1/1     Running             0          2s
web-4   0/1     Pending             0          0s
web-4   0/1     Pending             0          0s
web-4   0/1     Pending             0          1s
web-4   0/1     ContainerCreating   0          2s
web-4   1/1     Running             0          2s

# 查看扩容后 Pod 的状态:
[root@k8s-master01 ~]# kubectl get po
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          7m1s
web-1   1/1     Running   0          6m59s
web-2   1/1     Running   0          43s
web-3   1/1     Running   0          41s
web-4   1/1     Running   0          39s
# 缩容,将上述创建的 sts 副本缩容到 3 个:
[root@k8s-master01 ~]# kubectl scale sts web --replicas=3

# 可使用以下命令动态查看(是从编号最大的开始,同样是删除完一个才会删除下一个。但是平时我们并不建议缩容)
[root@k8s-master01 ~]# kubectl get po -w -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          9m29s
web-1   1/1     Running   0          9m27s
web-2   1/1     Running   0          3m11s
web-3   1/1     Running   0          3m9s
web-4   1/1     Running   0          3m7s
web-4   1/1     Terminating   0          3m33s
web-4   1/1     Terminating   0          3m33s
web-4   0/1     Completed     0          3m34s
web-4   0/1     Completed     0          3m34s
web-4   0/1     Completed     0          3m34s
web-3   1/1     Terminating   0          3m36s
web-3   1/1     Terminating   0          3m37s
web-3   0/1     Completed     0          3m37s
web-3   0/1     Completed     0          3m38s
web-3   0/1     Completed     0          3m38s

# 查看扩容后 Pod 的状态:
[root@k8s-master01 ~]# kubectl get po
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          11m
web-1   1/1     Running   0          11m
web-2   1/1     Running   0          4m47s

2.4 StatefulSet 更新策略

  • On Delete 策略:(手动删除后重建,1.7 之前的版本的默认策略)更新策略当我们选修改 StatefulSet的.spec.template 字段时,StatefulSet 控制器不会自动更新 Pod,必须手动删除 Pod 才能使控制器创建新的 Pod。
  • RollingUpdate 策略:(滚动更新,默认)更新策略会自动更新一个 StatefulSet 中所有的 Pod,采用与序号索引相反(倒序)的顺序进行滚动更新。
# 查看更新策略:
[root@k8s-master01 ~]# kubectl get sts web -o yaml | grep "updateStrategy" -A1
  updateStrategy:
    rollingUpdate:

# 然后改变容器的镜像触发滚动更新:
[root@k8s-master01 ~]# kubectl set image sts web nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15

# 在更新过程中可以使用 kubectl rollout status sts/<name> 来查看滚动更新的状态:
[root@k8s-master01 ~]# kubectl rollout status sts/web
Waiting for 1 pods to be ready...
Waiting for partitioned roll out to finish: 1 out of 3 new pods have been updated...
Waiting for 1 pods to be ready...
Waiting for 1 pods to be ready...
Waiting for 1 pods to be ready...
Waiting for partitioned roll out to finish: 2 out of 3 new pods have been updated...
Waiting for 1 pods to be ready...
Waiting for 1 pods to be ready...
Waiting for 1 pods to be ready...
partitioned roll out complete: 3 new pods have been updated...

# 查看更新后的image
[root@k8s-master01 ~]# kubectl get po -l app=nginx -oyaml|grep image:
    - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15
      image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15
    - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15
      image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15
    - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15
      image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15

2.5 StatefulSet 分段更新

比如我们定义一个分区"partition":2(定义为代表只有序号大于等于 2 的才会更新),可以使
用 patch 或 edit 直接对 StatefulSet 进行设置:

# 修改partition
[root@k8s-master01 ~]# kubectl edit sts/web
[root@k8s-master01 ~]# kubectl get sts/web -oyaml|grep partition
      partition: 2

# 然后再次使用 patch 改变容器的镜像:
[root@k8s-master01 ~]# kubectl set image sts web nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable

# 查看更新后的image(将分区改为 2,此时会自动更新 web-2,但是不会更新 web-0 和 web-1)
[root@k8s-master01 ~]# kubectl get po -l app=nginx -oyaml|grep image:
    - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15
      image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15
    - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15
      image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15
    - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable
      image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable

2.6 StatefulSet 回滚

# 列出所有修订版本
[root@k8s-master01 ~]# kubectl rollout history sts/web
statefulset.apps/web 
REVISION  CHANGE-CAUSE
2         <none>
3         <none>

# 回滚到指定 revision
[root@k8s-master01 ~]# kubectl rollout undo sts/web --to-revision=2

# 查看
[root@k8s-master01 ~]# kubectl rollout history sts/web --revision=2
statefulset.apps/web with revision #2
Pod Template:
  Labels:	app=nginx
  Containers:
   nginx:
    Image:	crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable
    Port:	80/TCP
    Host Port:	0/TCP
    Environment:	<none>
    Mounts:	<none>
  Volumes:	<none>
  Node-Selectors:	<none>
  Tolerations:	<none>
# StatefulSet 的更新和回滚与 Deployment 类似,唯一的区别是历史版本在 ControllerRevision 中保存。
[root@k8s-master01 ~]# kubectl get ControllerRevision
NAME             CONTROLLER             REVISION   AGE
web-769f8cc94d   statefulset.apps/web   2          57m
web-f568844cd    statefulset.apps/web   3          30m

2.7 删除 StatefulSet

删除StatefulSet有两种方式,即级联删除和非级联删除。使用非级联方式删除 StatefulSet时,StatefulSet 的 Pod 不会被删除;使用级联删除时,StatefulSet 和它的 Pod 都会被删除。

# 非级联删除(了解):使用 kubectl delete sts xxx 删除 StatefulSet 时,只需提供--cascade=false 参数,就会采用非级联删除,此时删除 StatefulSet 不会删除它的 Pod:

# kubectl delete statefulset web --cascade=false


# 级联删除
# 省略--cascade=false 参数即为级联删除:

# kubectl delete statefulset web

# 也可以使用-f 指定创建 StatefulSet 和 Service 的 yaml 文件,直接删除 StatefulSet 和 Service(此文件将 StatefulSet 和 Service 写在了一起):

# kubectl delete -f sts-web.yaml

2.8 StatefulSet 并发 Pod 管理

  • StatefulSet 可以通过.spec.podManagementPolicy 字段配置 Pod 的管理策略,目前支持如下的两种方式:
    • OrderdReady:有序管理,默认方式。Pod 创建和更新按照正序和倒序进行操作,删除是同时删除。
    • Parallel:并发管理,Pod 创建和删除同时并行启动和删除。
[root@k8s-master01 ~]# vim sts.yaml 
[root@k8s-master01 ~]# cat sts.yaml 
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  clusterIP: None
  ports:
  - name: web
    port: 80
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  podManagementPolicy: Parallel     # 并发管理,Pod 创建和删除同时并行启动和删除
  serviceName: "nginx"
  replicas: 5                       # 为测试设置5个pod
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable
        name: nginx
        ports:
        - containerPort: 80
          name: web
# 创建pod
[root@k8s-master01 ~]# kubectl create -f sts.yaml

# 检查pod建立情况
[root@k8s-master01 ~]# kubectl get po
NAME    READY   STATUS              RESTARTS   AGE
web-0   0/1     ContainerCreating   0          3s
web-1   0/1     ContainerCreating   0          3s
web-2   1/1     Running             0          3s
web-3   0/1     ContainerCreating   0          3s
web-4   0/1     ContainerCreating   0          3s
[root@k8s-master01 ~]# kubectl get po
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          5s
web-1   1/1     Running   0          5s
web-2   1/1     Running   0          5s
web-3   1/1     Running   0          5s
web-4   1/1     Running   0          5s
# 删除pod
[root@k8s-master01 ~]# kubectl delete -f sts.yaml 

# 查看也是同时删除的
[root@k8s-master01 ~]# kubectl get po
NAME    READY   STATUS        RESTARTS   AGE
web-0   1/1     Terminating   0          2m45s
web-1   1/1     Terminating   0          2m45s
web-2   1/1     Terminating   0          2m45s
web-3   1/1     Terminating   0          2m45s
web-4   1/1     Terminating   0          2m45s

[root@k8s-master01 ~]# kubectl get po
No resources found in default namespace.

2.9 StatefulSet 内部通信

  • StatefulSet 创建的 Pod 一般使用 Headless Service(无头服务)进行 Pod 之前的通信,和普
    通的 Service 的区别在于 Headless Service 没有 ClusterIP,它使用的是 Endpoint 进行互相通信,Headless 一般的格式为:statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local
    • serviceName 为 Headless Service 的名字,创建 StatefulSet 时,必须指定 Headless Service名称;
    • 0..N-1 为 Pod 所在的序号,从 0 开始到 N-1;
    • statefulSetName 为 StatefulSet 的名字;
    • namespace 为服务所在的命名空间;
    • .cluster.local 为 Cluster Domain(集群域)
# 使用任意一个 Pod 即可通过唯一的网络标识符访问 StatefulSet 的节点
# 同一个 namespace 可以省略.namespace.svc.cluster.local
# kubectl exec -ti web-4 -- curl web-2.nginx

# 不同 Namespace 的访问,需要加上 Pod 所在的 Namespace
# ping web-2.nginx.default

2.10 使用 StatefulSet 部署 Eureka 集群

# 创建 Headless Service:
[root@k8s-master01 ~]# vim demo-eureka-sts.yaml
[root@k8s-master01 ~]# cat demo-eureka-sts.yaml 
apiVersion: v1
kind: Service
metadata:
  labels:
    app: demo-eureka
  name: demo-eureka
spec:
  clusterIP: None
  ports:
  - name: eureka
    port: 8761
  selector:
    app: demo-eureka
# 创建 Eureka 的 StatefulSet:
[root@k8s-master01 ~]# vim demo-eureka.yaml 
[root@k8s-master01 ~]# cat demo-eureka.yaml 
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: eureka
spec:
  serviceName: "demo-eureka"
  replicas: 3
  selector:
    matchLabels:
      app: demo-eureka
  template:
    metadata:
      labels:
        app: demo-eureka
    spec:
      containers:
      - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/demo-eureka:latest
        name: demo-eureka
        env:
         - name: SPRING_PROFILES_ACTIVE
           value: k8s
         - name: SERVER_PORT
           value: '8761'
         - name: EUREKA_SERVER_ADDRESS
           value: http://demo-eureka-0.demo-eureka:8761/eureka/,http://demo-eureka-1.demo-eureka:8761/eureka/,http://demo-eureka-2.demo-eureka:8761/eureka/
        ports:
        - containerPort: 8761
          name: eureka
# 创建 Headless Service(无法外网访问)
[root@k8s-master01 ~]# kubectl create -f demo-eureka-sts.yaml 
[root@k8s-master01 ~]# kubectl get svc demo-eureka
NAME          TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
demo-eureka   ClusterIP   None         <none>        8761/TCP   36s

# 创建 Eureka 的 StatefulSet
[root@k8s-master01 ~]# kubectl create -f demo-eureka.yaml
[root@k8s-master01 ~]# kubectl get po
NAME       READY   STATUS    RESTARTS   AGE
eureka-0   1/1     Running   0          15s
eureka-1   1/1     Running   0          12s
eureka-2   1/1     Running   0          10s

如果想我们的服务可以通过外部访问

# 创建对外访问的 Service:
[root@k8s-master01 ~]# vim demo-eureka-np.yaml 
[root@k8s-master01 ~]# cat demo-eureka-np.yaml 
apiVersion: v1
kind: Service
metadata:
  labels:
    app: demo-eureka-np
  name: demo-eureka-np
spec:
  ports:
  - name: eureka
    port: 8761
  selector:
    app: demo-eureka
  type: NodePort
    
# 创建并查看 NodePort:
[root@k8s-master01 ~]# kubectl create -f demo-eureka-np.yaml 

[root@k8s-master01 ~]# kubectl get svc demo-eureka-np
NAME             TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
demo-eureka-np   NodePort   10.105.245.86   <none>        8761:32024/TCP

之后通过浏览器打开任意节点+32024 即可访问 Eureka 的集群:

image.png-126.6kB

3、守护进程集 DaemonSet

3.1 DaemonSet基础概念及使用场景

  • DaemonSet(守护进程集)是k8s的守护进程集,与Deployment和StatefulSet区别是:前者会根据算法选择最优的节点去运行Pod,而DaemonSet会在符合匹配条件的节点上都部署一个Pod,如果没有其他限制条件,会在所有的节点上都会运行一个Pod。
  • 同时当有新节点加入集群时,也会为它们新增一个Pod,当节点从集群中移除时,这些Pod也会被回收,删除DaemonSet将会删除它创建的所有Pod。

  • DaemonSet通常会用于以下需求:
    • 运行集群存储的进程,例如在每个节点上运行Glusterd、Geph等
    • 在每个节点运行日志收集进程,例如Fluentd、Filebeat
    • 在每个节点运行监控进程,比如Prometheus Node Exportter
    • 其他任何需要在每个节点运行一个服务的需求

3.2 创建 DaemonSet

# 创建一个副本
[root@k8s-master01 ~]# kubectl create deploy nginx --image=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable --dry-run=client -oyaml > nginx-ds.yaml

[root@k8s-master01 ~]# vim nginx-ds.yaml 
[root@k8s-master01 ~]# cat nginx-ds.yaml 
apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable
        name: nginx
        imagePullPolicy: IfNotPresent
  • 必需字段
    • 和其他所有 Kubernetes 配置一样,DaemonSet 需要 apiVersion、kind 和 metadata 字段,同时也需要一个.spec 配置段。
  • Pod 模板
    • .spec 唯一需要的字段是.spec.template。.spec.template 是一个 Pod 模板,它与 Pod 具有相同的配置方式,但它不具有 apiVersion 和 kind 字段。
    • 除了 Pod 必需的字段外,在 DaemonSet 中的 Pod 模板必须指定合理的标签。
  • Pod Selector
    • .spec.selector 字段表示 Pod Selector,它与其他资源的.spec.selector 的作用相同。
    • .spec.selector 表示一个对象,它由如下两个字段组成:
# 创建 DaemonSet
[root@k8s-master01 ~]# kubectl create -f nginx-ds.yaml

# 查看pod
[root@k8s-master01 ~]# kubectl get po
NAME          READY   STATUS    RESTARTS   AGE
nginx-n7mlr   1/1     Running   0          2m15s
nginx-vfx7k   1/1     Running   0          2m15s

# 查看节点(master没有是因为有污点)
[root@k8s-master01 ~]# kubectl get po -owide
NAME          READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
nginx-n7mlr   1/1     Running   0          2m20s   172.16.58.236   k8s-node02   <none>           <none>
nginx-vfx7k   1/1     Running   0          2m20s   172.16.85.215   k8s-node01   <none>           <none>

3.3 DaemonSet 更新策略

[root@k8s-master01 ~]# kubectl set image ds/nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15 --record
 
[root@k8s-master01 ~]# kubectl get po
NAME          READY   STATUS    RESTARTS   AGE
nginx-6wmfp   1/1     Running   0          5s
nginx-b4xqq   1/1     Running   0          3s

# 查看更新的镜像版本
[root@k8s-master01 ~]# kubectl get po -l app=nginx -oyaml | grep image:
    - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15
      image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15
    - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15
      image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15

3.4 DaemonSet 回滚

# 列出所有修订版本
[root@k8s-master01 ~]# kubectl rollout history ds/nginx
daemonset.apps/nginx 
REVISION  CHANGE-CAUSE
1         <none>
2         kubectl set image ds/nginx nginx=crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:1.15 --record=true

# 回退到指定版本
[root@k8s-master01 ~]# kubectl rollout undo ds/nginx --to-revision=1

# 查看pod
[root@k8s-master01 ~]# kubectl get po
NAME          READY   STATUS    RESTARTS   AGE
nginx-gx7pg   1/1     Running   0          7s
nginx-kq28x   1/1     Running   0          8s

# 查看更新的镜像版本
[root@k8s-master01 ~]# kubectl get po -l app=nginx -oyaml | grep image:
    - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable
      image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable
    - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable
      image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable

3.5 指定节点部署 Pod

如果指定了.spec.template.spec.nodeSelector,DaemonSet Controller 将在与 Node Selector(节点选择器)匹配的节点上创建 Pod,比如部署在磁盘类型为 ssd的节点上(需要提前给节点定义标签 Label):

[root@k8s-master01 ~]# cat nginx-ds.yaml 
apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      nodeSelector:
        gpu: "true"     # 添加一个gpu标签
      containers:
      - image: crpi-q1nb2n896zwtcdts.cn-beijing.personal.cr.aliyuncs.com/ywb01/nginx:stable
        name: nginx
        imagePullPolicy: IfNotPresent
        
# 更新yaml文件
[root@k8s-master01 ~]# kubectl replace -f nginx-ds.yaml 

# 检查pod,发现所有的pod都被删除了,因为所有节点都不具备GPU
[root@k8s-master01 ~]# kubectl get po
No resources found in default namespace.
# 如果手动给node01加一个node01的标签会发生什么呢
# 如果想去掉标签:kubectl label node k8s-node01 gpu-
[root@k8s-master01 ~]# kubectl label node k8s-node01 gpu=true

# 检查pod,发现node01节点重新起了一个pod
[root@k8s-master01 ~]# kubectl get po
NAME          READY   STATUS    RESTARTS   AGE
nginx-fnbfg   1/1     Running   0          3s

此博客来源于:https://edu.51cto.com/lecturer/11062970.html