【Kubernetes资源篇】Deployment控制器入门实战详解

一、Deployment 高级控制器理论

官方中文参考文档:

1、Deployment控制器介绍

Deployment是ReplicaSet的高级别抽象,ReplicaSet控制器有的功能Deployment全部具备,ReplicaSet没有的Deployment也具备比如,它提供了滚动升级和回滚的功能。Deployment是控制多个ReplicaSet,从而可以实现无缝升级和回滚。

Deployment控制器特点:

  • 选择器:ReplicaSet使用标签选择器来选择要管理的Pod副本。
  • 伸缩性:Deployment高级控制器可以根据负载自动伸缩容器数量,以满足应用程序的需求。
  • 自我修复:Deployment高级控制器可以监控容器的健康状况,并在容器出现故障时自动重启或替换容器。
  • 负载均衡:Deployment高级控制器可以通过负载均衡算法,将请求分发到不同的容器实例上,以提高应用程序的性能和可用性。
  • 版本控制:Deployment可以指定多个ReplicaSet,每个ReplicaSet可以控制不同版本的Pod,从而实现灰度发布和回滚。
  • 声明式:指直接修改资源清单yaml文件,然后通过 apply ,就可以更改资源。

2、Deployment工作原理

Deployment控制器建立在ReplicaSet控制器之上,管理多个ReplicaSet,每次更新镜像版本,都会生成一个新的ReplicaSet,把旧的ReplicaSet替换掉,多个ReplicaSet同时存在,但只运行一个ReplicaSet。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oihJ8ed8-1685790124572)(D:\MD归档文档\IMG\image-20230602095346882.png)]

如上图所示:ReplicaSet V1版本控制了三个Pod,ReplicaSet V1版本删除一个Pod,会在ReplicaSet V2版本新建一个Pod,以此类推,直到ReplicaSet V2版本完全替换完。

如果ReplicaSet V2版本更新上去存在问题,还可以回滚,Deployment建立在ReplicaSet之上,多个ReplicaSet组成一个Deployment,但只有一个ReplicaSet处于活跃状态。

二、Deployment YAML编写及参数解释

使用explain命令查看定义 可以查看 deployment控制器字段说明:

kubectl explain deployment

1、整体Deployment YAML资源清单内容:

cat demo-deployment.yaml 

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-deployment-1
  labels:
    env: uat
spec:
  replicas: 3
  minReadySeconds: 10  # 更新场景,等待时间,如果没有设置K8S会假设该容器启动起来后就提供服务了
  paused:  # 暂停,当更新Pod时,先暂停,而不是立马更新
  progressDeadlineSeconds: 60 # 更新场景,等待时间超过此值,状态标记False,并说明原因,但是它并不会阻止 Deployment 继续进行卡住后面的操作 
  strategy:
    rollingUpdate:        # 滚动更新,定义滚动更新方式,也就是pod能多几个,少几个
      maxSurge: 20%       # 允许更新中,最多超过Pod数值
      maxUnavailable: 20% # 允许更新中,最多允许几个不可用
  selector:
    matchLabels:
      app: demo-nginx
  template:
    metadata: 
      labels:
        app: demo-nginx
    spec:
      containers:
      - name: demo-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        startupProbe:      # 启动探测
          tcpSocket:
            port: 80
        livenessProbe:     # 存活探测 
          httpGet:
            port: 80
            path: /index.html
        readinessProbe:    # 就绪探测
          httpGet:
            port: 80
            path: "/index.html"

2、核心参数解释:

  • spec.minReadySeconds:更新场景,等待时间,如果没有设置K8S会假设该容器启动起来后就提供服务了。
  • spec.paused: 暂停,当更新Pod时,先暂停,而不是立马更新,后面金丝雀发布要用到
  • spec.progressDeadlineSeconds:更新场景,等待时间超过此值,状态标记False,并说明原因,但是它并不会阻止 Deployment 继续进行卡住后面的操作
  • spec.strategy.rollingUpdate:滚动更新,定义滚动更新方式,也就是pod能多几个,少几个
  • spec.strategy.rollingUpdate.maxSurge:指定在更新期间可以创建的新Pod的最大数量。例如,如果maxSurge设置为1,而Deployment中有3个Pod,则在更新期间可以创建4个Pod,其中3个是旧的Pod,1个是新的Pod。
  • spec.strategy.rollingUpdate.maxUnavailable:指定在更新期间可以同时停止的旧Pod的最大数量。例如,如果maxUnavailable设置为1,而Deployment中有3个Pod,则在更新期间可以停止2个Pod,其中1个是旧的Pod,1个是新的Pod。

3、Deployment更新策略:

Deployment目前支持两种更新策略

  • Recreate:重建式更新,把Pod全部删除,在重新创建,风险很大,不建议使用

  • rollingUpdate:滚动式更新,批量替换更新,平滑升级,用户无感知

4、Deployment更新策略百分比方式计算公式:

假设有5个副本,最多一个不可用,就表示最少有4个可用

  • maxSurge: 25% 5*25%=1.25(~=2) 5+2=7个可用
  • maxUnavailable: 25% 5%25%=1.25(~=1) 5-1=4个不可用

三、实战案例:

1、Deployment部署WEB站点

WEB站点镜像下载:

导入镜像:

ctr -n=k8s.io images import  k8s_web.tar.gz

资源清单如下:

cat web-deployment.yaml 

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
  labels:
    env: uat
spec:
  replicas: 5
  minReadySeconds: 10  
  progressDeadlineSeconds: 60 
  strategy:
    rollingUpdate:
      maxSurge: 20%       
      maxUnavailable: 20% 
  selector:
    matchLabels:
      app: web-nginx
  template:
    metadata: 
      labels:
        app: web-nginx
    spec:
      containers:
      - name: web-nginx
        image: web:v1
        imagePullPolicy: IfNotPresent
        startupProbe:
          tcpSocket:
            port: 80
        livenessProbe:
          httpGet:
            port: 80
            path: /index.html
        readinessProbe:
          httpGet:
            port: 80
            path: "/index.html"

执行YAML清单文件:

kubectl apply -f web-deployment.yaml

查看创建出来的资源:

kubectl get pod,rs -l app=web-nginx

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dy1yG9Tx-1685790124573)(D:\MD归档文档\IMG\image-20230602113208393.png)]

访问WEB网站:

podIp=$(kubectl get pod -l app=web-nginx|awk NR==2|awk '{print $1}')
kubectl describe pod  ${podIp}|grep -w IP:|awk NR==1|awk '{print $NF}'

curl 10.244.235.214
web version = V1

2、Deployment针对WEB站点扩缩容

扩容,将副本扩容至 7,根据上面YAML修改spec.replicas=7

修改完成后重新执行apply:

kubectl apply -f web-deployment.yaml

查看Pod数量:

kubectl get pods -l app=web-nginx|tail -n +2|wc -l

缩容,将副本缩容至 3,根据上面YAML修改spec.replicas=3

修改完成后重新执行apply:

kubectl apply -f web-deployment.yaml

查看Pod数量:

kubectl get pods -l app=web-nginx|tail -n +2|wc -l

3、Deployment针对WEB站点滚动更新

滚动更新是一种自动化较高的更新方式,即一批一批的更新Pod资源,用户体验比较平滑。滚动更新使用 spec.strategy.rollingUpdate 字段来定义。

基于上面YAML资源清单进行滚动更新,更换镜像版本为V2 YAML如下:

cat web-deployment.yaml 
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
  labels:
    env: uat
spec:
  replicas: 5
  minReadySeconds: 10  
  progressDeadlineSeconds: 60 
  strategy:
    rollingUpdate:
      maxSurge: 30%         # 5*30%=1.5(~=2), 2+5=7,更新期间最多创建7个Pod 
      maxUnavailable: 20%   # 5*20%=1, 1-5=4,更新期间最多停止4个Pod
  selector:
    matchLabels:
      app: web-nginx
  template:
    metadata: 
      labels:
        app: web-nginx
    spec:
      containers:
      - name: web-nginx
        image: web:v2    # 版本更新
        imagePullPolicy: IfNotPresent
        startupProbe:
          tcpSocket:
            port: 80
        livenessProbe:
          httpGet:
            port: 80
            path: /index.html
        readinessProbe:
          httpGet:
            port: 80
            path: "/index.html"

执行YAML文件:

kubectl apply -f web-deployment.yaml

访问WEB网站:

podIp=$(kubectl get pod -l app=web-nginx|awk NR==2|awk '{print $1}')
kubectl describe pod  ${podIp}|grep -w IP:|awk NR==1|awk '{print $NF}'

curl 10.244.235.236
web version = V2

可以看到WEB网站内容更新至V2版本了

4、Deployment针对WEB站点回滚版本

查看历史版本:

kubectl rollout history deployment web-deployment

回滚版本:回滚到V1 版本

kubectl rollout undo deployment web-deployment --to-revision=1

访问WEB网站:

podIp=$(kubectl get pod -l app=web-nginx|awk NR==2|awk '{print $1}')
kubectl describe pod  ${podIp}|grep -w IP:|awk NR==1|awk '{print $NF}'

curl 10.244.235.231
web version = V1

可以看到WEB网站内容更新至V1版本了

四、蓝绿部署发布

1、蓝绿部署介绍

蓝绿部署中,需要有两套系统,一套是正在提供服务系统,标记为 绿色,另一套是准备发布的系统,标记为 蓝色,两套系统功能完善,只有 绿色 对外提供服务、蓝色用来发布前测试,测试无问题直接可以系统更新为 蓝色。

切换后一段时间内,蓝绿两套系统并存,观察蓝色系统确实无问题之后,将其进行删除,将资源回收。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7dooZhRI-1685790124573)(D:\MD归档文档\IMG\image-20230603152442649.png)]

  • 优点:两套系统指只需要更改路由或者切换DNS服务器,风险小,效率高。
  • 缺点:两套系统并存,占用资源大。

2、案例:实现蓝绿部署

K8S不支持蓝绿部署,需要我们来进行规划,创建不同的Deployment、不同的Service来实现不同流量的切换!

  • 创建绿色系统(第一版)YAML如下:
cat green-demo.yaml 

---
apiVersion: v1
kind: Namespace
metadata:
  name: blue-green-demo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: green-app
  namespace: blue-green-demo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: green-app
  template:
    metadata:
      name: green-app
      labels: 
        app: green-app
    spec:
      containers:
      - name: green-app
        image: web:v1
        imagePullPolicy: IfNotPresent
        startupProbe:
          tcpSocket:
            port: 80
        livenessProbe:
          httpGet:
            port: 80
            path: "/index.html"
        readinessProbe:
          httpGet:
            port: 80
            path: "/index.html"

创建Service 代理绿色(第一版)系统:

cat blue-green-svc.yaml

---
apiVersion: v1
kind: Service
metadata:
  name: blue-green-svc
  namespace: blue-green-demo
spec:
  type: NodePort
  ports:
  - port: 80
    nodePort: 30010
    name: http
  selector:
    app: green-app

执行YAML文件:

kubectl apply -f green-demo.yaml 
kubectl apply -f blue-green-svc.yaml

查看创建资源:

kubectl get pod,svc -n blue-green-demo

浏览器访问 IP:30010

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u0DHEjbW-1685790124574)(D:\MD归档文档\IMG\image-20230603155422091.png)]

  • 创建蓝色系统(第二版)YAML如下
cat blue-deom.yaml 
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: blue-app
  namespace: blue-green-demo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: blue-app
  template:
    metadata:
      name: blue-app
      labels: 
        app: blue-app
    spec:
      containers:
      - name: blue-app
        image: web:v2
        imagePullPolicy: IfNotPresent
        startupProbe:
          tcpSocket:
            port: 80
        livenessProbe:
          httpGet:
            port: 80
            path: "/index.html"
        readinessProbe:
          httpGet:
            port: 80
            path: "/index.html"

执行YAML资源清单文件:

kubectl apply -f  blue-deom.yaml
  • 进行切换

只需要修改 Service 中选择标签即可。Service修改如下:

cat blue-green-svc.yaml 
---
apiVersion: v1
kind: Service
metadata:
  name: blue-green-svc
  namespace: blue-green-demo
spec:
  type: NodePort
  ports:
  - port: 80
    nodePort: 30010
    name: http
  selector:
    app: blue-app  # 关联蓝色系统Pod标签

执行YAML文件:

kubectl apply -f  blue-green-svc.yaml

浏览器刷新访问页面:

链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6vHwXIlj-1685790124574)(D:\MD归档文档\IMG\image-20230603163353356.png)]

回滚也是一样,只需要修改Service更改代理Pod标签即可了!

五、金丝雀(灰度)部署

2、金丝雀部署介绍

金丝雀部署又称为灰度部署,它允许在生产环境中逐步推出新版本,以确保新版本的稳定性和可靠性。在金丝雀发布中,新版本应用程序只会在一小部分用户中进行测试,如果没有问题,就会逐步扩大范围,直到所有用户都在使用新版本。这种方法可以减少新版本应用程序出现问题的风险,同时也可以确保用户的体验不会受到太大影响。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J76TQuiy-1685790124574)(D:\MD归档文档\IMG\image-20230603180036402.png)]

  • 优点:灵活、自定义策略,可以根据流量或内容进行金丝雀部署,出现问题不会影响全网用户。

  • 缺点:没有覆盖全网用户,出现问题不好排查。

3、案例:实现金丝雀部署

首先创建Deployment资源,使用web:V1 镜像

cat deploy-demo.yaml 
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-demo
spec:
  replicas: 5
  selector:
    matchLabels:
      app: web-nginx
  template:
    metadata:
      name: nginx
      labels: 
        app: web-nginx
    spec:
      containers:
      - name: web-nginx
        image: web:v1
        imagePullPolicy: IfNotPresent
        startupProbe:
          tcpSocket:
            port: 80
        livenessProbe:
          httpGet:
            port: 80
            path: "/index.html"
        readinessProbe:
          httpGet:
            port: 80
            path: "/index.html"

---
apiVersion: v1
kind: Service
metadata:
  name: deploy-demo-svc
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30011
    name: http
  selector:
    app: web-nginx

执行YAML文件:

kubectl apply -f deploy-demo.yaml 

版本更新,进行金丝雀发布 版本更新为V2,更新的时候使用 pause 暂停更新

kubectl set image deployment deploy-demo web-nginx=web:v2 && kubectl rollout pause deployment deploy-demo

上面命令语法解释:

# 更新镜像为web:v2
kubectl set image deployment {
    
    deploy控制器名称} {
    
    容器名称}=web:v2 

浏览器访问:刷新页面会出现不同的页面,因为只更新了一部分

如果经过测试新版本无问题,可以使用 解除暂停,使其所有都更新为web:v2 版本

kubectl rollout resume deployment deploy-demo

五、总结

  • Deployment高级控制器建立在ReplicaSet之上,每次更新镜像版本,都会生成一个新的ReplicaSet,把旧的ReplicaSet替换掉,多个ReplicaSet同时存在,但只运行一个ReplicaSet。

  • Deployment扩缩容:直接修改replicas字段值,重新apply

  • Deployment滚动升级:使用字spec.strategy段定义升级策略,目前支持两种升级策略:

    • rollingUpdate滚动更新:批量替换更新,平滑升级,用户无感知。
    • Recreate重建试更新:把Pod全部删除,在重新创建,风险很大,不建议使用。
  • Deployment版本回滚:使用rollout history 查看历史版本,使用rollout undo .... --to-revision=x指定回滚版本。

  • 蓝绿发布:创建两套系统,利用修改Service关联Pod标签负载到对应系统。

  • 金丝雀发布:只更新一小部分Pod,如果没问题,在进行全部更新,如果有问题不会影响全部用户。

猜你喜欢

转载自blog.csdn.net/weixin_45310323/article/details/131024507