工作负载管理
你已经部署了应用程序并通过 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)创建与 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 Chart。
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
打印它。
对本地文件的递归操作
如果你碰巧将资源组织在特定目录的多个子目录中,你也可以通过指定 --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 create
、kubectl get
、kubectl delete
、kubectl 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
支持多种更新操作,每种操作适用于不同的场景。
你可以运行应用程序的多个副本,并使用*滚动更新 (rollout)* 将流量逐渐转移到新的健康 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].image
从 nginx: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 使用滚动更新 (rollout)。
管理滚动更新
你可以使用 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 模板中的镜像标签指定)的*金丝雀 (canary)* 版本与之前版本并行部署,以便新版本在完全推出之前可以接收实际生产流量。
例如,你可以使用 track
标签来区分不同的版本。
主要稳定版本会有一个 track
标签,其值为 stable
name: frontend
replicas: 3
...
labels:
app: guestbook
tier: frontend
track: stable
...
image: gb-frontend:v3
然后你可以创建一个新的 guestbook 前端版本,该版本带有值不同的 track
标签(即 canary
),这样两组 Pod 就不会重叠
name: frontend-canary
replicas: 1
...
labels:
app: guestbook
tier: frontend
track: canary
...
image: gb-frontend:v4
前端 Service 将通过选择其标签的共同子集(即省略 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 scale、kubectl autoscale 和Horizontal Pod Autoscaler 文档。
资源的就地更新
有时需要对你创建的资源进行细微的、非破坏性的更新。
kubectl apply
建议在源代码控制中维护一组配置文件(参见配置即代码),以便可以与配置这些资源的代码一起维护和版本化。然后,你可以使用 kubectl apply
将配置更改推送到集群。
此命令将比较你推送的配置版本与之前版本,并应用你所做的更改,而不会覆盖对你未指定的属性进行的任何自动更改。
kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
deployment.apps/my-nginx configured
要了解有关底层机制的更多信息,请阅读服务器端应用 (server-side apply)。
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
这使你可以更轻松地进行更重要的更改。请注意,你可以使用 EDITOR
或 KUBE_EDITOR
环境变量指定编辑器。
更多信息,请参阅kubectl edit。
kubectl patch
你可以使用 kubectl patch
对 API 对象进行就地更新。此子命令支持 JSON Patch、JSON Merge Patch 和 Strategic Merge Patch。
有关更多详细信息,请参阅使用 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 网站指南。
在提议添加额外的第三方链接的更改之前,你应该阅读内容指南。