Kubernetes工作负载资源之Deployment

ProjectDaedalus

共 10382字,需浏览 21分钟

 · 2022-08-25

这里将介绍Kubernetes工作负载资源中的Deployment

abstract.png

创建Deployment

Deployment是一种更高阶的工作负载资源。其可以视作为对RS的再一次升级。其不仅可以部署应用还可以通过声明的方式升级应用。具体地,Deployment被创建后,其内部先创建相应的RS资源。再利用该RS资源创建相应的Pod。下面即是一个创建Deployment资源的示例

# 创建Deployment资源

apiVersion: apps/v1
# 资源类型
kind: Deployment
metadata:
  # Deployment名称
  name: my-kubia-deployment
spec:
  # Pod副本数量
  replicas: 3
  # 标签选择器
  selector:
    matchLabels:
      app: my-kubia-app
  # Pod模板    
  template:
    metadata:
      # 标签信息
      labels:
        app: my-kubia-app
    spec:
      # 容器信息
      containers:
        - name: my-kubia
          image: luksa/kubia:v1
          # 仅用于展示容器所使用的端口
          ports:
            - containerPort: 8080
              protocol: TCP

---

# 创建Service资源

# API组、版本
apiVersion: v1
# 资源类型
kind: Service
metadata:
  # 资源名称
  name: my-kubia-svc
spec:
  # Service类型
  type: NodePort
  selector:
    app: my-kubia-app
  ports:
  - port: 80 # 服务监听端口
    targetPort: 8080  # 服务将请求转发到Pod的目标端口
    # 在集群各节点所打开的端口, 使得可以通过集群中任一节点IP、nodePort端口号访问该服务
    nodePort: 30123

--- 

# 创建一个Pod用于访问、测试Service提供的服务

apiVersion: v1
kind: Pod
metadata:
  name: my-bootcamp-pod
spec:
  containers:  
  - name: my-bootcamp
    image: jocatalin/kubernetes-bootcamp:v1
    ports:
      - containerPort: 8080
        protocol: TCP

效果如下所示。可以看到该Deployment会自行创建一个RS资源。同时再由该RS资源创建相应的Pod。同时这些Pod的名称前缀和RS名称完全一样。然后还可以通过Service进行访问

figure 1.jpeg

特别地,对于Deployment而言,还可以通过下述命令查看部署状态

# 查看指定名称的Deployment的部署结果
kubectl rollout status deployment <Deployment的名称>

# 查看名为my-kubia-deployment的Deployment的部署结果
kubectl rollout status deployment my-kubia-deployment

效果如下所示

figure 2.jpeg

应用升级

创建应用的V1版本

现在来演示下如何利用Deployment升级应用,先创建一个应用的V1版本

apiVersion: apps/v1
# 资源类型
kind: Deployment
metadata:
  # Deployment名称
  name: my-kubia-deployment-2
spec:
  # Pod副本数量
  replicas: 3
  # Pod就绪后需要等待多长时间, 才会将该Pod视为可用
  minReadySeconds: 10
  # 升级策略
  strategy:
    # 默认策略类型为滚动升级
    type: RollingUpdate
    # 控制滚动升级速率
    rollingUpdate:      
      # 升级期间, 相对于Deployment中指定的Pod期望副本数而言, 允许多出的Pod数量
      maxSurge: 1
      # 升级期间, 相对于Deployment中指定的Pod期望副本数而言, 允许有多少个Pod处于不可用状态
      # 例如: 当replicas=3、maxUnavailable=1, 则此时要求可用的Pod数量至少为 replicas - maxUnavailable = 3-1 = 2
      maxUnavailable: 0      
  # 标签选择器
  selector:
    matchLabels:
      app: my-kubia-app-2
  # Pod模板    
  template:
    metadata:
      # 标签信息
      labels:
        app: my-kubia-app-2
    spec:
      # 容器信息
      containers:
        - name: my-kubia-2
          image: luksa/kubia:v1
          # 仅用于展示容器所使用的端口
          ports:
            - containerPort: 8080
              protocol: TCP
          # 就绪探针
          readinessProbe:
            periodSeconds: 1
            httpGet:
              path: /
              port: 8080

---

# 创建Service资源

# API组、版本
apiVersion: v1
# 资源类型
kind: Service
metadata:
  # 资源名称
  name: my-kubia-svc-2
spec:
  # Service类型
  type: NodePort
  selector:
    app: my-kubia-app-2
  ports:
  - port: 80 # 服务监听端口
    targetPort: 8080  # 服务将请求转发到Pod的目标端口
    # 在集群各节点所打开的端口, 使得可以通过集群中任一节点IP、nodePort端口号访问该服务
    nodePort: 30123

--- 

# 创建一个Pod用于访问、测试Service提供的服务

apiVersion: v1
kind: Pod
metadata:
  name: my-bootcamp-pod-2
spec:
  containers:
  - name: my-bootcamp
    image: jocatalin/kubernetes-bootcamp:v1
    ports:
      - containerPort: 8080
        protocol: TCP

效果如下所示

figure 3.jpeg

在Deployment升级应用时,支持两种策略

  • 「RollingUpdate」:其是Deployment的默认升级策略。其会渐进的删除旧版本的Pod,与此同时创建新版本的Pod。这样应用在整个升级过程中都处于可用的状态,即通过旧版本、新版本的Pod同时对外提供服务
  • 「Recreate」:该策略下,其会一次性删除所有旧版本的Pod。再创建新版本的Pod。这样应用在整个升级过程中会有短暂的时间不可用。如果应用不支持同时使用多个不同版本对外提供服务,则可以选择该策略

应用升级

对于Deployment升级应用来说,非常简单。只需设置该Deployment中容器的新镜像信息即可

# 对于指定名称的Deployment,设置其中指定名称容器的镜像信息
kubectl set image deployment <Deployment的名称> <容器的名称>=<镜像名称>:<镜像版本>

# 对于名为my-kubia-deployment-2的Deployment,设置名为my-kubia-2容器的镜像为luksa/kubia:v2
kubectl set image deployment my-kubia-deployment-2 my-kubia-2=luksa/kubia:v2

与此同时,通过my-bootcamp-pod-2这个Pod来访问my-kubia-svc-2服务,命令如下所示

# 进入名为my-bootcamp-pod-2的Pod
kubectl exec my-bootcamp-pod-2 -it -- bash

# 不停的访问my-kubia-svc-2的Service
while truedo curl 10.96.247.140:80 ; done

效果如下所示,右侧显示在RollingUpdate策略下V2版本的新Pod不断被创建,与此同时V1版本的旧Pod逐渐被删除

figure 4.jpeg

当升级完成后,可以看到Deployment实际上是先创建了一个新RS。然后对新RS不断扩容、对旧RS不断缩容。而且旧RS实际上依然保留在其中并未删除

figure 5.jpeg

此外每次利用kubectl edit、kubectl apply命令修改、应用Deployment中Pod模板相关字段值时,同样也会自动触发升级更新。为此可先通过kubectl rollout pause命令暂停该Deployment的升级更新,在完成所有对Deployment的更改后,再通过kubectl rollout resume命令恢复该Deployment的升级更新。对于回滚操作而言,不可以对处于暂停状态的Deployment执行 kubectl rollout undo命令,需要先恢复再回滚

# 暂停指定Deployment的升级更新
kubectl rollout pause deployment <Deployment的名称>

# 恢复指定Deployment的升级更新
kubectl rollout resume deployment <Deployment的名称>

应用回滚

对于Deployment回滚应用也很简单,可以先通过下述命令查看某Deployment的滚动升级历史

# 查看指定名称的Deployment的滚动升级历史
kubectl rollout history deployment <Deployment的名称>

# 查看名为my-kubia-deployment-2的Deployment的滚动升级历史
kubectl rollout history deployment my-kubia-deployment-2

然后通过指定版本号查看该版本的具体信息

# 查看指定名称Deployment的指定版本的信息
kubectl rollout history deployment <Deployment的名称> --revision=<版本号>

# 查看名为my-kubia-deployment-2的Deployment的版本号为1的信息
kubectl rollout history deployment my-kubia-deployment-2 --revision=1

效果如下所示

figure 6.jpeg

故如果我们想将应用回滚到V1版本,只需使用kubectl rollout undo子命令即可。如果使用--to-revision选项指定版本号则会回滚到指定版本,如果不使用--to-revision选项则会直接回滚到上一个版本

# 将指定名称的Deployment回滚到上一个版本
kubectl rollout undo deployment <Deployment的名称>

# 将指定名称的Deployment回滚到指定版本
kubectl rollout undo deployment <Deployment的名称> --to-revision=<版本号> 

# 将名为 my-kubia-deployment-2的Deployment 回滚到1号版本
kubectl rollout undo deployment my-kubia-deployment-2 --to-revision=1

效果如下所示。通过curl命令的结果不难看出Deployment已经回滚到V1版本了。由于此前升级后V1版本所对应的旧RS并没有被删除。所以可以直接利用旧RS进行回滚。而一旦将旧RS删除掉,就无法进行回滚了

figure 7.jpeg

控制升级速率

在RollingUpdate策略下,可以通过maxSurge、maxUnavailable参数控制滚动升级的速率。具体地:

「maxSurge参数」

升级期间, 相对于Deployment中指定的Pod期望副本数而言, 允许多出的Pod数量。同时该值可以是绝对数字也可以是一个百分比。例如: 当Deployment中指定的Pod期望副本数replicas为4时,如果maxSurge值为2,则表明不会运行超过4+2=6个Pod实例;如果maxSurge值为25%,则表明不会运行超过4+4*25% = 4+1 =5 个Pod实例

「maxUnavailable参数」

升级期间, 相对于Deployment中指定的Pod期望副本数而言, 允许有多少个Pod处于不可用状态。同时该值可以是绝对数字也可以是一个百分比。当Deployment中指定的Pod期望副本数replicas为4时,如果maxUnavailable值为1。则表明此时要求可用的Pod数量至少为 replicas - maxUnavailable = 4-1 = 3个;如果maxUnavailable值为50%。则表明此时要求可用的Pod数量至少为 replicas - maxUnavailable = 4-4*50% = 4-2 =2个。换言之,该参数不是限制不可用Pod的数量,而是通过replicas值计算出可用Pod的最少数量

此外,还可以使用minReadySeconds参数来避免升级缺陷版本的应用时,造成大范围的影响。在RollingUpdate滚动升级策略条件下,可以实现自动阻止升级过程。具体地:

「minReadySeconds参数」

该参数指定Pod就绪后需要等待多少秒, 才会将该Pod视为可用。由于maxUnavailable参数的存在,会导致Pod可用之前,滚动升级过程不会再继续。minReadySeconds参数通过搭配就绪探针共同使用,可以实现将只有少量Pod升级到缺陷版本。由于滚动升级过程自动被阻止,故可以避免将所有Pod全部升级到缺陷版本。默认值为0意为Pod一旦就绪后,会立即将该Pod视为可用状态

在之前的Deployment中我们定义minReadySeconds参数为10秒,同时还定义了一个就绪探针。现在我们将应用升级到V3版本,该版本有一个缺陷。即其只能正确处理前四个请求,后续所有HTTP请求都将会失败。效果如下所示,可以看到由于V3版本的Pod处于未就绪,自然其也是不可用的状态。现在滚动升级已经被自动阻止了,避免了更大范围的影响。我们只需将Deployment回滚到历史版本即可

figure 8.jpeg

参考文献

  1. Kubernetes in Action中文版 Marko Luksa著
  2. 深入剖析Kubernetes 张磊著
浏览 25
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报