管理工作负载

你已经部署了应用程序并通过 Service 公开它。接下来该怎么办?Kubernetes 提供了许多工具来帮助你管理应用程序的部署,包括伸缩和更新。

组织资源配置

许多应用程序需要创建多个资源,例如 Deployment 和 Service。 通过将它们分组到同一个文件中(在 YAML 中使用 --- 分隔),可以简化多个资源的管理。例如

apiVersion: v1
kind: Service
metadata:
  name: my-nginx-svc
  labels:
    app: nginx
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

可以像创建单个资源一样创建多个资源

kubectl apply -f https://k8s.io/examples/application/nginx-app.yaml
service/my-nginx-svc created
deployment.apps/my-nginx created

资源将按照它们在清单中出现的顺序创建。因此,最好先指定 Service,因为这将确保调度器可以在控制器(例如 Deployment)创建 Pod 时将其与 Service 关联的 Pod 分散开来。

kubectl apply 也接受多个 -f 参数

kubectl apply -f https://k8s.io/examples/application/nginx/nginx-svc.yaml \
  -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml

建议将与同一微服务或应用层相关的资源放入同一文件中,并将与你的应用程序相关的所有文件分组到同一目录中。如果应用程序的层级使用 DNS 互相绑定,则可以将堆栈的所有组件一起部署。

也可以将 URL 指定为配置源,这对于直接从源代码管理系统中的清单进行部署非常方便

kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
deployment.apps/my-nginx created

如果你需要定义更多清单,例如添加 ConfigMap,你也可以这样做。

外部工具

本节仅列出用于管理 Kubernetes 工作负载的最常用工具。要查看更大的列表,请查看 应用程序定义和镜像构建,位于 CNCF Landscape 中。

Helm

Helm 是一种用于管理预配置的 Kubernetes 资源包的工具。这些软件包被称为 *Helm 图表*。

Kustomize

Kustomize 遍历 Kubernetes 清单以添加、删除或更新配置选项。它既可以作为独立的二进制文件使用,也可以作为 kubectl 的 原生功能 使用。

kubectl 中的批量操作

资源创建并不是 kubectl 可以批量执行的唯一操作。它还可以从配置文件中提取资源名称,以便执行其他操作,特别是删除你创建的相同资源

kubectl delete -f https://k8s.io/examples/application/nginx-app.yaml
deployment.apps "my-nginx" deleted
service "my-nginx-svc" deleted

对于两个资源,可以使用资源/名称语法在命令行上指定这两个资源

kubectl delete deployments/my-nginx services/my-nginx-svc

对于大量的资源,你会发现使用 -l--selector 指定的选择器(标签查询)来按标签过滤资源会更容易

kubectl delete deployment,services -l app=nginx
deployment.apps "my-nginx" deleted
service "my-nginx-svc" deleted

链接和过滤

由于 kubectl 输出的资源名称与其接受的语法相同,因此可以使用 $()xargs 链接操作

kubectl get $(kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service/ )
kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service/ | xargs -i kubectl get '{}'

输出可能类似于

NAME           TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)      AGE
my-nginx-svc   LoadBalancer   10.0.0.208   <pending>     80/TCP       0s

使用上述命令,首先你在 examples/application/nginx/ 下创建资源,并使用 -o name 输出格式打印创建的资源(将每个资源打印为 resource/name)。然后,你 grep 仅获取 Service,然后使用 kubectl get 打印它。

本地文件上的递归操作

如果你碰巧将资源组织到特定目录中的几个子目录中,你也可以通过指定 --recursive-R 以及 --filename/-f 参数来对子目录递归执行操作。

例如,假设有一个目录 project/k8s/development,其中包含开发环境所需的所有清单,按资源类型组织

project/k8s/development
├── configmap
│   └── my-configmap.yaml
├── deployment
│   └── my-deployment.yaml
└── pvc
    └── my-pvc.yaml

默认情况下,在 project/k8s/development 上执行批量操作将停止在目录的第一级,而不处理任何子目录。如果你尝试使用以下命令在此目录中创建资源,则会遇到错误

kubectl apply -f project/k8s/development
error: you must provide one or more resources by argument or filename (.json|.yaml|.yml|stdin)

相反,请指定 --recursive-R 命令行参数以及 --filename/-f 参数

kubectl apply -f project/k8s/development --recursive
configmap/my-config created
deployment.apps/my-deployment created
persistentvolumeclaim/my-pvc created

--recursive 参数适用于接受 --filename/-f 参数的任何操作,例如:kubectl createkubectl getkubectl deletekubectl describe 甚至 kubectl rollout

当提供多个 -f 参数时,--recursive 参数也适用

kubectl apply -f project/k8s/namespaces -f project/k8s/development --recursive
namespace/development created
namespace/staging created
configmap/my-config created
deployment.apps/my-deployment created
persistentvolumeclaim/my-pvc created

如果你有兴趣了解更多关于 kubectl 的信息,请继续阅读 命令行工具 (kubectl)

在不停机的情况下更新你的应用程序

在某些时候,你最终需要更新已部署的应用程序,通常是通过指定新的镜像或镜像标签。 kubectl 支持几种更新操作,每种操作都适用于不同的场景。

你可以运行应用程序的多个副本,并使用 _滚动更新_ 逐步将流量转移到新的健康 Pod。最终,所有正在运行的 Pod 都将拥有新软件。

页面的这一部分将指导你如何使用 Deployment 创建和更新应用程序。

假设你正在运行 nginx 的 1.14.2 版本

kubectl create deployment my-nginx --image=nginx:1.14.2
deployment.apps/my-nginx created

确保有 1 个副本

kubectl scale --replicas 1 deployments/my-nginx --subresource='scale' --type='merge' -p '{"spec":{"replicas": 1}}'
deployment.apps/my-nginx scaled

并通过设置 100% 的 _最大激增_ 来允许 Kubernetes 在滚动更新期间添加更多临时副本

kubectl patch --type='merge' -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge": "100%" }}}}'
deployment.apps/my-nginx patched

要更新到 1.16.1 版本,请使用 kubectl edit.spec.template.spec.containers[0].imagenginx:1.14.2 更改为 nginx:1.16.1

kubectl edit deployment/my-nginx
# Change the manifest to use the newer container image, then save your changes

就是这样!Deployment 将在后台以声明的方式逐步更新部署的 nginx 应用程序。它确保在更新时只有一定数量的旧副本可能会停机,并且在期望的 Pod 数量之上只能创建一定数量的新副本。要了解有关此过程如何发生的更多详细信息,请访问 Deployment

你可以将滚动更新与 DaemonSet、Deployment 或 StatefulSet 一起使用。

管理滚动更新

你可以使用 kubectl rollout 来管理现有应用程序的渐进式更新。

例如

kubectl apply -f my-deployment.yaml

# wait for rollout to finish
kubectl rollout status deployment/my-deployment --timeout 10m # 10 minute timeout

kubectl apply -f backing-stateful-component.yaml

# don't wait for rollout to finish, just check the status
kubectl rollout status statefulsets/backing-stateful-component --watch=false

你还可以暂停、恢复或取消滚动更新。访问 kubectl rollout 以了解更多信息。

金丝雀部署

需要多个标签的另一种情况是区分同一组件的不同版本或配置的部署。常见的做法是将新应用程序版本的 _金丝雀_ 版本(通过 Pod 模板中的镜像标签指定)与以前的版本并排部署,以便新版本可以在完全推出之前接收实时生产流量。

例如,你可以使用 track 标签来区分不同的版本。

主要的稳定版本将具有一个值为 stabletrack 标签

name: frontend
replicas: 3
...
labels:
   app: guestbook
   tier: frontend
   track: stable
...
image: gb-frontend:v3

然后,你可以创建带有不同值(即 canary)的 track 标签的 Guestbook 前端的新版本,以便两组 Pod 不会重叠

name: frontend-canary
replicas: 1
...
labels:
   app: guestbook
   tier: frontend
   track: canary
...
image: gb-frontend:v4

前端服务将通过选择其标签的公共子集(即省略 track 标签)来跨越两组副本,以便流量将被重定向到两个应用程序

selector:
   app: guestbook
   tier: frontend

你可以调整稳定版本和金丝雀版本的副本数量,以确定每个版本将接收实时生产流量的比例(在本例中为 3:1)。一旦你确信,就可以将稳定版本更新为新的应用程序版本并删除金丝雀版本。

更新注解

有时你可能希望将注解附加到资源。 注解是任意的非标识元数据,供诸如工具或库之类的 API 客户端检索。 可以使用 kubectl annotate 完成此操作。 例如

kubectl annotate pods my-nginx-v4-9gw19 description='my frontend running nginx'
kubectl get pods my-nginx-v4-9gw19 -o yaml
apiVersion: v1
kind: pod
metadata:
  annotations:
    description: my frontend running nginx
...

有关更多信息,请参阅 注解kubectl annotate

伸缩你的应用程序

当你的应用程序上的负载增加或减少时,请使用 kubectl 伸缩你的应用程序。例如,要将 nginx 副本数从 3 减少到 1,请执行

kubectl scale deployment/my-nginx --replicas=1
deployment.apps/my-nginx scaled

现在你只有一个由 Deployment 管理的 Pod。

kubectl get pods -l app=nginx
NAME                        READY     STATUS    RESTARTS   AGE
my-nginx-2035384211-j5fhi   1/1       Running   0          30m

要使系统根据需要自动选择 nginx 副本的数量,范围从 1 到 3,请执行

# This requires an existing source of container and Pod metrics
kubectl autoscale deployment/my-nginx --min=1 --max=3
horizontalpodautoscaler.autoscaling/my-nginx autoscaled

现在,你的 nginx 副本将根据需要自动向上和向下伸缩。

有关更多信息,请参阅 kubectl scalekubectl autoscale水平 Pod 自动伸缩 文档。

资源的就地更新

有时需要对已创建的资源进行细微的、非破坏性的更新。

kubectl apply

建议在源代码管理中维护一组配置文件(请参阅 配置即代码),以便可以维护它们并与配置资源的 code 一起进行版本控制。然后,你可以使用 kubectl apply 将配置更改推送到集群。

此命令会将你正在推送的配置版本与之前的版本进行比较,并应用你所做的更改,而不会覆盖你未指定的属性的任何自动更改。

kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
deployment.apps/my-nginx configured

要了解有关底层机制的更多信息,请阅读 服务器端应用

kubectl edit

或者,你也可以使用 kubectl edit 更新资源

kubectl edit deployment/my-nginx

这相当于先 get 获取资源,在文本编辑器中编辑它,然后使用更新后的版本 apply 应用资源。

kubectl get deployment my-nginx -o yaml > /tmp/nginx.yaml
vi /tmp/nginx.yaml
# do some edit, and then save the file

kubectl apply -f /tmp/nginx.yaml
deployment.apps/my-nginx configured

rm /tmp/nginx.yaml

这使您可以更轻松地进行更重要的更改。请注意,您可以使用 EDITORKUBE_EDITOR 环境变量指定编辑器。

有关更多信息,请参阅 kubectl edit

kubectl patch

您可以使用 kubectl patch 就地更新 API 对象。此子命令支持 JSON 补丁、JSON 合并补丁和策略合并补丁。

有关更多详细信息,请参阅 使用 kubectl patch 就地更新 API 对象

破坏性更新

在某些情况下,您可能需要更新一旦初始化后就无法更新的资源字段,或者您可能希望立即进行递归更改,例如修复由 Deployment 创建的损坏的 Pod。要更改此类字段,请使用 replace --force,它会删除并重新创建资源。在这种情况下,您可以修改原始配置文件。

kubectl replace -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml --force
deployment.apps/my-nginx deleted
deployment.apps/my-nginx replaced

下一步

此页面上的项目引用了第三方产品或项目,这些产品或项目提供了 Kubernetes 所需的功能。Kubernetes 项目作者不对这些第三方产品或项目负责。有关更多详细信息,请参阅 CNCF 网站指南

在提出添加额外的第三方链接的更改之前,您应该阅读内容指南

上次修改时间:2024 年 2 月 19 日下午 4:54 PST:修订工作负载管理概念 (5639b8bb45)