Deployment 简述

DeploymentPodReplicaSet 提供了一个声明式定义 (declarative) 方法,用来替代以前的 ReplicationController 更方便的管理应用。

作为最常用的 Kubernetes 对象,Deployment 经常会用来创建 ReplicaSetPod,我们往往不会直接在集群中使用 ReplicaSet 部署一个新的微服务,一方面是因为 ReplicaSet 的功能其实不够强大,一些常见的更新、扩容和缩容运维操作都不支持,Deployment 的引入就是为了支持这些复杂的操作。

我的实践:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: django-cmdb-mysql
  namespace: it
  labels:
     name: django-cmdb-mysql
spec:
  replicas: 2
  selector: 
    matchLabels:
      name: django-cmdb-mysql
  template:
    metadata:
      labels:
        name: django-cmdb-mysql
    spec:
      containers:
      - name: django-pod
        image: prod-image-warehouse.tencentcloudcr.com/it/cmdb-mysql:v8
        ports:
          - containerPort: 8000
            protocol: TCP
        imagePullPolicy: IfNotPresent
        resources:
          requests:
            cpu: 1
            memory: 1000Mi
          limits:
            cpu: 2
            memory: 2000Mi
        volumeMounts:
        - name: it-django-config
          mountPath: /usr/src/app/mysite/settings.py
      volumes:
      - name: it-django-config
        configMap:
          name: it-django-configmap

Deployment API 版本对照表

Kubernetes 版本Deployment 版本
v1.5-v1.15extensions/v1beta1
v1.7-v1.15apps/v1beta1
v1.8-v1.15apps/v1beta2
v1.9+apps/v1

Deployment 一个典型的用例

一个典型的用例如下:

  • 使用 Deployment 来创建 ReplicaSet。ReplicaSet 在后台创建 pod。检查启动状态,看它是成功还是失败。
  • 然后,通过更新 Deployment 的 PodTemplateSpec 字段来声明 Pod 的新状态。这会创建一个新的 ReplicaSet,Deployment 会按照控制的速率将 pod 从旧的 ReplicaSet 移动到新的 ReplicaSet 中。
  • 如果当前状态不稳定,回滚到之前的 Deployment revision。每次回滚都会更新 Deployment 的 revision。
  • 扩容 Deployment 以满足更高的负载。
  • 暂停 Deployment 来应用 PodTemplateSpec 的多个修复,然后恢复上线。
  • 根据 Deployment 的状态判断上线是否 hang 住了。
  • 清除旧的不必要的 ReplicaSet。

创建 Deployment

Deployment yaml文件包含四个部分:

  • apiVersion: 表示版本
  • kind: 表示资源
  • metadata: 表示元信息
  • spec: 资源规范字段

Deployment yaml 名词解释:

apiVersion: apps/v1  # 指定api版本,此值必须在kubectl api-versions中  
kind: Deployment  # 指定创建资源的角色/类型   
metadata:  # 资源的元数据/属性 
  name: demo  # 资源的名字,在同一个namespace中必须唯一
  namespace: default # 部署在哪个namespace中
  labels:  # 设定资源的标签
    app: demo
    version: stable
spec: # 资源规范字段
  replicas: 1 # 声明副本数目
  revisionHistoryLimit: 3 # 保留历史版本
  selector: # 选择器
    matchLabels: # 匹配标签
      app: demo
      version: stable
  strategy: # 策略
    rollingUpdate: # 滚动更新
      maxSurge: 30% # 最大额外可以存在的副本数,可以为百分比,也可以为整数
      maxUnavailable: 30% # 示在更新过程中能够进入不可用状态的 Pod 的最大值,可以为百分比,也可以为整数
    type: RollingUpdate # 滚动更新策略
  template: # 模版
    metadata: # 资源的元数据/属性 
      annotations: # 自定义注解列表
        sidecar.istio.io/inject: "false" # 自定义注解名字
      labels: # 设定资源的标签
        app: demo
        version: stable
    spec: # 资源规范字段
      containers:
      - name: demo # 容器的名字 
        # nodeName: 10.71.8.31 # 强制调度到 某个node节点ip 或 hostname
        dnsPolicy: Default	 # 使用宿主机dns  ; None 无任何策略 ;ClusterFirst 集群DNS优先;ClusterFirstWithHostNet 集群 DNS 优先,并伴随着使用宿主机网络
        image: demo:v1 # 容器使用的镜像地址   
        imagePullPolicy: IfNotPresent # 每次Pod启动拉取镜像策略,三个选择 Always、Never、IfNotPresent
                                      # Always,每次都检查;Never,每次都不检查(不管本地是否有);IfNotPresent,如果本地有就不检查,如果没有就拉取 
        resources: # 资源管理
          limits: # 最大使用
            cpu: 300m # CPU,1核心 = 1000m
            memory: 500Mi # 内存,1G = 1000Mi
          requests:  # 容器运行时,最低资源需求,也就是说最少需要多少资源容器才能正常运行
            cpu: 100m
            memory: 100Mi
        livenessProbe: # pod 内部健康检查的设置
          httpGet: # 通过httpget检查健康,返回200-399之间,则认为容器正常
            path: /healthCheck # URI地址
            port: 8080 # 端口
            scheme: HTTP # 协议
            # host: 127.0.0.1 # 主机地址
          initialDelaySeconds: 30 # 表明第一次检测在容器启动后多长时间后开始
          timeoutSeconds: 5 # 检测的超时时间
          periodSeconds: 30 # 检查间隔时间
          successThreshold: 1 # 成功门槛
          failureThreshold: 5 # 失败门槛,连接失败5次,pod杀掉,重启一个新的pod
        readinessProbe: # Pod 准备服务健康检查设置
          httpGet:
            path: /healthCheck
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 30
          timeoutSeconds: 5
          periodSeconds: 10
          successThreshold: 1
          failureThreshold: 5
        #也可以用这种方法   
        #exec: 执行命令的方法进行监测,如果其退出码不为0,则认为容器正常   
        #  command:   
        #    - cat   
        #    - /tmp/health   
        #也可以用这种方法   
        #tcpSocket: # 通过tcpSocket检查健康  
        #  port: number 
        ports:
          - name: http # 名称
            containerPort: 8080 # 容器开发对外的端口 
            protocol: TCP # 协议
      imagePullSecrets: # 镜像仓库拉取密钥
        - name: harbor-certification
      affinity: # 亲和性调试
        nodeAffinity: # 节点亲和力
          requiredDuringSchedulingIgnoredDuringExecution: # pod 必须部署到满足条件的节点上
            nodeSelectorTerms: # 节点满足任何一个条件就可以
            - matchExpressions: # 有多个选项,则只有同时满足这些逻辑选项的节点才能运行 pod
              - key: beta.kubernetes.io/arch
                operator: In
                values:
                - amd64

Service yaml 名词解释:

apiVersion: v1 # 指定api版本,此值必须在kubectl api-versions中 
kind: Service # 指定创建资源的角色/类型 
metadata: # 资源的元数据/属性
  name: demo # 资源的名字,在同一个namespace中必须唯一
  namespace: default # 部署在哪个namespace中
  labels: # 设定资源的标签
    app: demo
spec: # 资源规范字段
  type: ClusterIP # ClusterIP 类型
  ports:
    - port: 8080 # service 端口
      targetPort: http # 容器暴露的端口
      protocol: TCP # 协议
      name: http # 端口名称
  selector: # 选择器
    app: demo



作者:YP小站
链接:https://www.jianshu.com/p/99800eb305bf
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

更加详细版本

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ops-nginx-api  # Deployment 对象的名称,与应用名称保持一致
  namespace: default    #命名空间
  labels:
    appName: ops-nginx-api  # 应用名称
spec:
  selector:
    matchLabels:
      app: ops-nginx-api  #app 标签名称
  replicas: 5 #Pod
  strategy: #部署策略更多策略 1.https://www.qikqiak.com/post/k8s-deployment-strategies/
    type: RollingUpdate #其他类型如下 1.重建(Recreate) 开发环境使用 2.RollingUpdate(滚动更新)
    rollingUpdate:
       maxSurge: 25%        #一次可以添加多少个Pod
       maxUnavailable: 25%  #滚动更新期间最大多少个Pod不可用
  template:
    metadata:
      labels:
        app: 'ops-nginx-api'
    spec:
      terminationGracePeriodSeconds: 120 #优雅关闭时间,这个时间内优雅关闭未结束,k8s 强制 kill
      affinity:
        podAntiAffinity:  # pod反亲和性,尽量避免同一个应用调度到相同node
          preferredDuringSchedulingIgnoredDuringExecution: #硬需求 1.preferredDuringSchedulingIgnoredDuringExecution 软需求
            - weight: 100
              #weight 字段值的 范围是 1-100。 对于每个符合所有调度要求(资源请求、RequiredDuringScheduling 亲和性表达式等) 的节点,调度器将遍历该字段的元素来计算总和,并且如果节点匹配对应的 MatchExpressions,则添加“权重”到总和。 然后将这个评分与该节点的其他优先级函数的评分进行组合。 总分最高的节点是最优选的。
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                    - key: app
                      operator: In
                      values:
                        - ops-nginx-api
                topologyKey: "kubernetes.io/hostname"

      initContainers:  #初始化容器
        - name: sidecar-sre #init 容器名称
          image: breaklinux/sidecar-sre:201210129  #docker hup仓库镜像
          imagePullPolicy: IfNotPresent  #镜像拉取策略 1.IfNotPresent如果本地存在镜像就优先使用本地镜像。2.Never直接不再去拉取镜像了,使用本地的.如果本地不存在就报异常了。
          #3.imagePullPolicy 未被定义为特定的值,默认值设置为 Always 本地是否存在都会去仓库拉取镜像.
          env:
            #Downward API官网示例 https://kubernetes.io/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information/
            - name: CHJ_NODE_IP
              valueFrom:
                fieldRef:  #这两种呈现 Pod 和 Container 字段的方式统称为 Downward API。
                  fieldPath: status.hostIP #获取pod 所在node IP地址设置为CHJ_NODE_IP

            - name: CHJ_POD_IP  #变量名称
              valueFrom:
                fieldRef:
                  fieldPath: status.podIP #获取pod自身ip地址设置为CHJ_POD_IP变量名称

            - name: CHJ_APP_NAME   #应用名称EVN
              value: 'ops-nginx-api' #环境变量值

          command: ["/bin/sh","-c"]  #shell 执行
          args: ["mkdir -p /scratch/.sidecar-sre && cp /sidecar/post-start.sh /scratch/.sidecar-sre/post-start.sh && /scratch/.sidecar-sre/post-start.sh"]

          volumeMounts: #挂载日志卷和存在的空镜像
            - name: log-volume
              mountPath: /tmp/data/log/ops-nginx-api  #容器内挂载镜像路径
            - name: sidecar-sre
              mountPath: /scratch  #空镜像

          resources:  #qos 设置
            limits:
              cpu: 100m #pod 占单核cpu 1/10
              memory: 100Mi #内存100M
        #hostPath 卷能将主机节点文件系统上的文件或目录挂载到你的 Pod 中。 虽然这不是大多数 Pod 需要的,但是它为一些应用程序提供了强大的逃生舱。
        volumes:
          - name: log-volume  #卷名称
            hostPath:         #卷类型详细见:https://kubernetes.io/zh/docs/concepts/storage/volumes/
              path: /data/logs/prod/ops-nginx-api  #宿主机存在的目录路径
              type: DirectoryOrCreate #如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息
          - name: sidecar-sre  #
            emptyDir: {} #emptyDir 卷的存储介质(磁盘、SSD 等)是由保存 kubelet 数据的根目录 (通常是 /var/lib/kubelet)的文件系统的介质确定。

      containers:
        - name: ops-nginx-api # 容器名称,与应用名称保持一致
          image: breaklinux/op-flask-api:v1 #遵守镜像命名规范
          imagePullPolicy: Always  #镜像拉取策略 1.IfNotPresent如果本地存在镜像就优先使用本地镜像。2.Never直接不再去拉取镜像了,使用本地的.如果本地不存在就报异常了。
          #3.imagePullPolicy 未被定义为特定的值,默认值设置为 Always 本地是否存在都会去仓库拉取镜像.
          lifecycle: #Kubernetes 支持 postStart 和 preStop 事件。 当一个容器启动后,Kubernetes 将立即发送 postStart 事件;在容器被终结之前, Kubernetes 将发送一个 preStop 事件。
            postStart: #容器创建成功后,运行前的任务,用于资源部署、环境准备等。
              exec:
                command:
                  - /bin/sh
                  - -c
                  - echo 'Hello from the postStart handler' >> /var/log/nginx/message
            preStop: #在容器被终止前的任务,用于优雅关闭应用程序、通知其他系统等等
              exec:
                command:
                  - sh
                  - -c
                  - sleep 30

          livenessProbe:  #存活探针器配置
            failureThreshold: 3 #处于成功时状态时,探测操作至少连续多少次的失败才被视为检测不通过,显示为#failure属性.默认值为3,最小值为 1,存活探测情况下的放弃就意味着重新启动容器。
            httpGet: #1.存活探针器三种方式 1.cmd命令方式进行探测 2.http 状态码方式 3.基于tcp端口探测
              path: /healthy #k8s源码中healthz 实现 https://github.com/kubernetes/kubernetes/blob/master/test/images/agnhost/liveness/server.go
              port: 8080    #应用程序监听端口
            initialDelaySeconds: 600 #存活性探测延迟时长,即容器启动多久之后再开始第一次探测操作,显示为delay属性.默认值为0,即容器启动后立刻便开始进行探测.
            periodSeconds: 10  #执行探测的时间间隔(单位是秒)。默认是 10 秒。最小值是 1秒,过高的频率会对Pod对象带来较大的额外开销,而过低的频率又会使得对错误的反应不及时.
            successThreshold: 1 #处于失败状态时,探测操作至少连续多少次的成功才被人为是通过检测,显示为#success属性,默认值为1,最小值也是1
            timeoutSeconds: 3 #存活性探测的超时时长,显示为timeout属性,默认值1s,最小值也是1s

          readinessProbe:  #定义就绪探测器
            failureThreshold: 3 #处于成功时状态时,探测操作至少连续多少次的失败才被视为检测不通过,显示为#failure属性.默认值为3,最小值为  就绪探测情况下的放弃 Pod 会被打上未就绪的标签.

            tcpSocket: # 1.就绪探针三种方式 1.cmd命令方式进行探测 2.http 状态码方式 3.基于tcp端口探测
              port: 8080 #应用程序监听端口
            initialDelaySeconds: 10 #执行探测的时间间隔(单位是秒)。默认是 10 秒。最小值是 1秒,过高的频率会对Pod对象带来较大的额外开销,而过低的频率又会使得对错误的反应不及时.
            periodSeconds: 10  #执行探测的时间间隔(单位是秒)。默认是 10 秒。最小值是 1秒,过高的频率会对Pod对象带来较大的额外开销,而过低的频率又会使得对错误的反应不及时
            successThreshold: 1 #处于失败状态时,探测操作至少连续多少次的成功才被人为是通过检测,显示为#success属性,默认值为1,最小值也是1
            timeoutSeconds: 3  #存活性探测的超时时长,显示为timeout属性,默认值1s,最小值也是1s

          ports:
            - containerPort: 19201 #应用监听的端口
              protocol: TCP #协议 tcp和 udp

          env:  #应用配置中心环境变量
            - name: ENV
              value: test
            - name: apollo.meta
              value: http://saos-apollo-config-service:8080
            - name: CHJ_APP_NAME
              value: 'ops-nginx-api'
            - name: LOG_BASE
              value: '/chj/data/log'
            - name: RUNTIME_CLUSTER
              value: 'default'

          #Request: 容器使用的最小资源需求,作为容器调度时资源分配的判断依赖。只有当节点上可分配资源量>=容器资源请求数时才允许将容器调度到该节点。但Request参数不限制容器的最大可使用资源。
          #Limit: 容器能使用资源的资源的最大值,设置为0表示使用资源无上限。
          resources:  #qos限制 1.QoS 主要分为Guaranteed、Burstable 和 Best-Effort三类,优先级从高到低
            requests:
              memory: 4096Mi #内存4G
              cpu: 500m #cpu 0.5
            limits:
              memory: 4096Mi
              cpu: 500m

          volumeMounts: #挂载苏宿主机目录到制定
            - name: log-volume  # sidecar-sre
              mountPath: /tmp/data/log/ops-nginx-api #该目录作为程序日志sidecar路径收集
            - name: sidecar-sre
              mountPath: /chj/data  #苏主机挂载目录

      imagePullSecrets:  #在 Pod 中设置 ImagePullSecrets 只有提供自己密钥的 Pod 才能访问私有仓库
        - name: lixiang-images-pull  #镜像Secrets需要在集群中手动创建

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐