【Kubernetes】K8s笔记(八):Deployment 发布无状态的应用

1. Deployment API 对象

我们之前学习了 API 对象 Job 和 CronJob,它们代表了生产环境中的离线业务,通过对 Pod 的包装,向 Pod 添加控制字段,实现了基于 Pod 运行临时任务和定时任务的功能。

这次要学习的 API 对象名字叫 Deployment,顾名思义,它是专门用来部署应用程序的,能够让应用永不宕机,多用来发布无状态的应用,是 Kubernetes 里最常用也是最有用的一个对象。它也是由 Pod 衍生出来的 API 对象。

部署应用如果只使用 Pod 这个 API 对象,会有下列的问题:

  • 虽然 Pod 可以在 YAML 文件里指定 containers 中的 restartPolicy 字段在容器发生问题的时候自动重启容器,但是它无法处理手动删除 Pod 或者节点宕机导致的应用故障,这时候 Pod 就会从集群里彻底消失

  • 在线业务还有很多复杂操作,比如多实例、高可用、更新等;如果只使用 Pod 这个 API 对象,就会回到手工管理容器的老路上,无法发挥 Kubernetes 自动化运维的优势

Deployment 就是一个新的用来管理 Pod,实现在线业务应用的 API 对象。

2. 使用 YAML 描述 Deployment

使用 kubectl api-resources 查看 Deployment 对象的基本信息:

NAME         SHORTNAMES   APIVERSION   NAMESPACED   KIND
deployments  deploy       apps/v1      true        Deployment

Deployment 的简称是 deploy,它的 apiVersionapps/v1kindDeployment

使用命令创建 Deployment 的 YAML 模板:名字叫 ngx-dep,使用的镜像是 nginx:alpine

$ export out="--dry-run=client -o yaml"
$ kubectl create deploy ngx-dep --image=nginx:alpine $out

删除一些无用的配置项得到 YAML 模板如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: ngx-dep
  name: ngx-dep

spec:
  replicas: 2
  selector:
    matchLabels:
      app: ngx-dep

  template:
    metadata:
      labels:
        app: ngx-dep
    spec:
      containers:
      - image: nginx:alpine
        name: nginx

可以看到,Deployment 的 spec 多了 replicas selector 这两个新字段。

关键字段 replicas

字段 replicas 用来设定副本数量,指定要在 Kubernetes 集群中运行多少个 Pod 实例。这个字段为 Kubernetes 明确提供了一个应用部署的期望状态,Deployment 对象可以根据这个字段自动地调整集群内的 Pod 数量。

比如,在 Deployment 对象刚创建出来的时候,Pod 数量肯定是 0,那么它就会根据 YAML 文件里的 Pod 模板,逐个创建出要求数量的 Pod。再比如,万一有 Pod 发生意外消失了,数量不满足“期望状态”,它就会通过 apiserver、scheduler 等核心组件去选择新的节点,创建出新的 Pod,直至数量与“期望状态”一致。

关键字段 selector

spec:
  replicas: 2
  selector:
    matchLabels:
      app: ngx-dep

  template:
    metadata:
      labels:
        app: ngx-dep
  • selector 的作用是筛选出被 Deployment 管理的 Pod 对象

  • selector 的下属字段 matchLabels 定义了被管理的 Pod 对象应该携带的 labelmatchLabels 必须和 template 里 Pod 定义的labels完全相同,否则 Deployment 就会找不到要控制的 Pod 对象,apiserver 也会告诉你 YAML 格式校验错误无法创建。

selector 字段的用法初看起来好像是有点多余,为了保证 Deployment 成功创建,我们必须在 YAML 里把 label 重复写两次:一次是在selector.matchLabels ,另一次是在 template.matadata

Deployment 和 Pod 实际上是一种松散的组合关系,Deployment 实际上并不“持有”Pod 对象,它只是帮助 Pod 对象能够有足够的副本数量运行。复杂的在线业务使得 Pod 除了要在 Deployment 里部署运行,还可能会被其他的 API 对象引用来管理,比如负责负载均衡的 Service 对象。

Kubernetes 采用“贴标签”的方式,通过在 API 对象的 metadata 里加各种标签(labels),让配置人员使用类似关系数据库里查询语句的方式,筛选出具有特定标识的那些对象。通过标签这种设计,Kubernetes 就解除了 Deployment 和模板里 Pod 的强绑定,把组合关系变成了“弱引用”

3. 操作 Deployment

使用下面的命令创建 Deployment 对象:

$ kubectl apply -f deploy.yml

查看 Deployment 的状态:

$ kubectl get deploy -o wide 
NAME      READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES         SELECTOR
ngx-dep   2/2     2            2           54s   nginx        nginx:alpine   app=ngx-dep
  • READY 表示运行的 Pod 数量,前面的数字是当前数量,后面的数字是期望数量,所以“2/2”的意思就是要求有两个 Pod 运行,现在已经启动了两个 Pod。

  • UP-TO-DATE 指的是当前已经更新到最新状态的 Pod 数量。因为如果要部署的 Pod 数量很多或者 Pod 启动比较慢,Deployment 完全生效需要一个过程,UP-TO-DATE 就表示现在有多少个 Pod 已经完成了部署,达成了模板里的“期望状态”。

  • AVAILABLE 要比 READY UP-TO-DATE 更进一步,不仅要求已经运行,还必须是健康状态,能够正常对外提供服务,它才是我们最关心的 Deployment 指标。最后一个 AGE 就简单了,表示 Deployment 从创建到现在所经过的时间,也就是运行的时间。

查看 pod 的状态:

$ kubectl get pod -o wide 
NAME                       READY   STATUS    RESTARTS        AGE     IP           NODE      NOMINATED NODE   READINESS GATES
ngx-dep-6b9d9dd879-qbtks   1/1     Running   1 (2m27s ago)   3m39s   10.10.1.12   worker1   <none>           <none>
ngx-dep-6b9d9dd879-rc2th   1/1     Running   0               3m39s   10.10.1.10   worker1   <none>           <none>

被 Deployment 管理的 Pod 自动带上了名字,命名的规则是 Deployment 的名字加上两串随机数(其实是 Pod 模板的 Hash 值)。

接下来我们手动删除 Pod 模拟 Pod 故障,然后查看 Pod:

$ kubectl delete pod ngx-dep-6b9d9dd879-qbtks
pod "ngx-dep-6b9d9dd879-qbtks" deleted
$ kubectl get pod -o wide 
NAME                       READY   STATUS    RESTARTS      AGE   IP           NODE      NOMINATED NODE   READINESS GATES
ngx-dep-6b9d9dd879-8n2lx   1/1     Running   0             4s    10.10.1.23   worker1   <none>           <none>
ngx-dep-6b9d9dd879-rc2th   1/1     Running   7 (15m ago)   33m   10.10.1.22   worker1   <none>           <none>

可以看到新的 Pod 生成了。

在 Deployment 部署成功之后,我们还可以随时调整 Pod 的数量,实现所谓的“应用伸缩”。这项工作在 Kubernetes 出现之前对于运维来说是一件很困难的事情,而现在由于有了 Deployment 就变得轻而易举了。

比如下面的这条命令,就把 Nginx 应用扩容到了 5 个:

$ kubectl scale --replicas=5 deploy ngx-dep

但要注意, kubectl scale 是命令式操作,扩容和缩容只是临时的措施,如果应用需要长时间保持一个确定的 Pod 数量,最好还是编辑 Deployment 的 YAML 文件,改动 replicas,再以声明式的 kubectl apply 修改对象的状态。

4. labels 字段的使用方法

之前我们通过 labels 为对象“贴”了各种“标签”,在使用 kubectl get 命令的时候,加上参数 -l,使用 == != in notin 的表达式,就能够很容易地用“标签”筛选、过滤出所要查找的对象(有点类似社交媒体的 #tag 功能),效果和 Deployment 里的 selector 字段是一样的。

看两个例子,第一条命令找出 app 标签是 nginx 的所有 Pod,第二条命令找出 app 标签是 ngxnginxngx-dep 的所有 Pod:

$ kubectl get pod -l app=nginx
$ kubectl get pod -l 'app in (ngx, nginx, ngx-dep)'
posted @ 2022-10-18 11:01  joexu01  阅读(336)  评论(0编辑  收藏  举报