管理工作负载

你已经部署了你的应用程序并通过 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 Charts

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

对于两个资源的情况,你可以在命令行上使用 resource/name 语法指定这两个资源

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 打印它。

对本地文件进行递归操作

如果你将资源组织在特定目录下的多个子目录中,通过在 --filename/-f 参数旁边指定 --recursive-R,也可以对子目录递归执行操作。

例如,假设有一个目录 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)

相反,请在 --filename/-f 参数旁边指定 --recursive-R 命令行参数。

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% 的“最大激增数”(surge maximum)来允许 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 标签来区分不同的发布版本。

主要的稳定版本将具有一个 track 标签,其值为 stable

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

然后你可以创建一个新的 guestbook 前端版本,它带有一个不同值(即 canary)的 track 标签,这样两组 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 autoscalehorizontal pod autoscaler 文档。

资源的就地更新

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

kubectl apply

建议在源代码管理中维护一套配置文件(参见 基础设施即代码),以便它们可以与配置资源的对应代码一起维护和版本化。然后,你可以使用 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:修订工作负载管理概念 (5639b8bb45)