在这篇 CKAD 考试实操指南文章中将为你介绍如何使用知十平台并结合开源项目 CKAD Exercises 中提供的练习题来练习 CKAD 考试中 Pod Design 部分的考试内容。在这个过程中你将熟悉如何通过 kubectl 命令行工具去操作「Label」、「Annotation」、「Pod」、「Deployment」、「Job」、「CronJob」,并在实践中加深对知识的理解。
实操平台介绍
访问实验平台
在浏览器中输入此网址 https://www.knows10.com
或点击此处进入知十平台。进入后你将看到如下界面:
进入实验环境
点击 「Kubernetes 基础环境」 图标即可进入实验环境,点击后你将看到如下界面:
官方参考资料
kubectl 命令行工具基础
- 文档路径:kubernetes.io > Documentation > Reference > Command line tool (kubectl) > kubectl Cheat Sheet
- 文档链接:[https: //kubernetes.io/docs/reference/kubectl/cheatsheet]
kubectl 命令行工具进阶
- 文档路径:kubernetes.io > Documentation > Reference > Command line tool (kubectl) > kubectl Cheat Sheet
- 文档链接:[https: //kubernetes.io/docs/reference/kubectl/cheatsheet]
工作负载相关概念介绍
- 文档路径:kubernetes.io > Documentation > Concepts > Workloads
- 文档链接:[https: //kubernetes.io/docs/concepts/workloads]
标签和选择器
- 文档路径:kubernetes.io > Documentation > Concepts > Overview > Working with Kubernetes Objects > Labels and Selectors
- 文档链接: [https: //kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors]
实操练习
Labels And Annotations(标签和注解)
Create 3 pods with names nginx1,nginx2,nginx3. All of them should have the label app=v1
译:创建三个 Pod,名称分别为 nginx1、nginx2、nginx3。且每一个 Pod 都需要有 app=v1 标签。
- 方法一:分别执行三次 kubectl 命令,每次创建一个 Pod。
kubectl run nginx1 --image=nginx --restart=Never --labels=app=v1
kubectl run nginx2 --image=nginx --restart=Never --labels=app=v1
kubectl run nginx3 --image=nginx --restart=Never --labels=app=v1
- 方法二:使用 bash 的 for 循环语句,一次性创建三个 Pod。
# for i in `seq 1 3` 表示先执行 seq 1 3 命令生成一个 1-3 的序列,然后使用 for 循环语句遍历这个序列。
for i in `seq 1 3`; do kubectl run nginx$i --image=nginx -l app=v1 ; done
Show all labels of the pods
译:查看所有 Pod 的标签。
# 增加 --show-labels 参数后,会在输出结果的最后一列显示 Pod 的标签。
kubectl get po --show-labels
Change the labels of pod 'nginx2' to be app=v2
译:将 Pod nginx2 的标签修改为 app=v2。
kubectl label po nginx2 app=v2 --overwrite
知识点:
label
命令用于更新资源的标签,它的格式为kubectl label <resource-type> <resource-name> <key>=<value>
。此处我们是修改 Pod 的标签,所以<resource-type>
为po
。如果想更新其他资源的标签,只需要将<resource-type>
替换为对应的资源类型(资源类型可使用全拼也可以使用缩写)即可。如:svc
、deploy
、rs
等。--overwrite
参数的作用是覆盖已有的标签。比如 Pod nginx2 已经有了一个标签 app=v1,如果不加--overwrite
参数直接执行kubectl label po nginx2 app=v2
命令则会报错。此时必须加上--overwrite
参数,才能将标签 app=v1 修改为 app=v2。
Get the label 'app' for the pods (show a column with APP labels)
译:查看所有 Pod 的 app 标签。
- 方法一:
kubectl get po -L app
- 方法二:
kubectl get po --label-columns=app
知识点:
-L
是--label-columns
的简写,它们的作用是一样的。用于指定要显示的标签的名称。如果要显示多个标签,可以使用逗号分隔。如:-L app,env
、--label-columns=app,env
、--label-columns=app -L env
、-L app -L env
、-L=app,env
都表示显示 app 和 env 两个标签,只是语法格式不同而已。
Get only the 'app=v2' pods
译:查看所有带有 app=v2 标签的 Pod。
- 方法一:
kubectl get po -l app=v2
- 方法二:
kubectl get po -l 'app in (v2)'
- 方法三:
kubectl get po --selector=app=v2
知识点:
-l
是--selector
的简写。app in(v2)
语法用于匹配多个标签的值。如:app in (v1,v2)
表示匹配 app=v1 或 app=v2 的 Pod。-l app=v2,app=v1
语法用于匹配多个标签的值。如:-l app=v2,env=prod
表示匹配 app=v2 且 env=prod 的 Pod。
Add a new label tier=web to all pods having 'app=v2' or 'app=v1' labels
译:给所有 app=v2 或 app=v1 的 Pod 添加一个新的标签 tier=web。
kubectl label po -l "app in(v1,v2)" tier=web
Add an annotation 'owner:marketing' to all pods having 'app=v2' label
译:给所有 app=v2 的 Pod 添加一个注解 owner: marketing。
kubectl annotate po -l app=v2 owner=marketing
知识点:
Annotation 有什么作用?它和 Label 有什么区别?
- Label 是一组键值对,用于标识和选择 Kubernetes 资源。它们可以附加到 Pod、Service、Deployment 等对象上。Label 可以根据需要自定义,用于对资源进行分类、分组和筛选。例如,可以为一组 Pod 添加相同的 Label,以便将它们作为一个逻辑单元进行管理。Label 还可以用于定义服务发现和负载均衡规则。
- Annotation 是一种用于向 Kubernetes 对象添加任意键值对的方式。与 Label 不同,Annotation 的目的是提供关于资源的附加信息,而不是用于选择和筛选资源。Annotation 可以用于存储与资源相关的元数据,如版本信息、构建号、配置信息等。它们通常用于记录和共享关于资源的额外细节,以便于监控、调试和审计等。
Remove the 'app' label from the pods we created before
译:删除之前创建的 Pod 的 app 标签。
- 方法一:
# 通过直接指定所有 Pod 的名称来选中 Pod 并删除标签。
kubectl label po nginx1 nginx2 nginx3 app-
- 方法二:
# 和方法一类似,只不过这里使用了 bash 生成序列的语法。
kubectl label po nginx{1..3} app-
- 方法三:
# 通过标签选择器选中 Pod 并删除标签。
kubectl label po -l app app-
知识点:
app-
语法中的app
表示期望被删除的标签名,-
表示删除。
Annotate pods nginx1, nginx2, nginx3 with "description='my description'" value
译:给之前创建的 Pod 添加一个注解 description=my description。
- 方法一:
kubectl annotate po nginx1 nginx2 nginx3 description='my description'
- 方法二:
kubectl annotate po nginx{1..3} description='my description'
Check the annotations for pod nginx1
译:查看 Pod nginx1 的注解。
- 方法一:
kubectl annotate pod nginx1 --list
- 方法二:
kubectl describe po nginx1 | grep -i 'annotations'
- 方法三:
kubectl get po nginx1 -o custom-columns=Name:metadata.name,ANNOTATIONS:metadata.annotations.description
知识点:
custom-columns
语法用于自定义输出列的名称。如:kubectl get po -o custom-columns=Name:metadata.name,Labels:metadata.labels
表示输出 Pod 的名称和标签。
Remove the annotations for these three pods
译:删除之前添加的 description 注解。
kubectl annotate po nginx{1..3} description-
Remove these pods to have a clean state in your cluster
译:删除之前创建的所有 Pod,使集群处于干净的状态。
kubectl delete po nginx{1..3}
Pod Placement(Pod 的调度)
Create a pod that will be deployed to a Node that has the label 'accelerator=nvidia-tesla-p100'
译:创建一个 Pod,让它被调度到带有标签 accelerator=nvidia-tesla-p100 的节点上。
第一步:为节点添加标签。
当前实验环境为单节点环境,无法测试出 nodeSelector
的效果,所以此处只需要掌握如何操作即可。
# 获取集群中所有节点。
kubectl get nodes
# 为节点添加标签。此命令的格式为:kubectl label <resource-type> <reource-name> key=value。
# 下面这条命令表示为名为 kubernetes 的节点添加标签。
kubectl label nodes kubernetes accelerator=nvidia-tesla-p100
# 查看节点标签。
kubectl get nodes --show-labels
第二步:创建一个名为 cuda-test.yaml 的文件,在 spec
下添加 nodeSelector
配置。
当前实验环境没有 GPU,所以此处使用 Nginx 镜像。防止因为使用 cuda-vector-add 镜像而导致 Pod 无法启动问题。完整 YAML 文件如下所示。
apiVersion: v1
kind: Pod
metadata:
name: cuda-test
spec:
containers:
- name: cuda-test
image: "nginx"
nodeSelector:
accelerator: nvidia-tesla-p100
第三步:使用 kubectl 的 apply
命令创建 Pod。
kubectl apply -f cuda-test.yaml
Taint a node with key tier and value frontend with the effect NoSchedule. Then, create a pod that tolerates this taint
译:给节点添加一个 key 为 tier,value 为 frontend,效果为 NoSchedule 的污点。然后创建一个 Pod,让它能够容忍这个污点。
因为当前实验环境为单节点环境,无法测试出 tolerations
的效果,所以此处只需要掌握如何操作即可。
第一步:为节点添加污点。
# 为名为 kubernetes 的节点添加污点。
kubectl taint node kubernetes tier=frontend:NoSchedule
kubectl describe node kubernetes
第二步:创建一个名为 pom.yaml 的文件,在 spec
下添加 tolerations
配置,让 Pod 能够容忍这个污点。
apiVersion: v1
kind: Pod
metadata:
name: frontend
spec:
containers:
- name: nginx
image: nginx
tolerations: # Pod 容忍度
- key: "tier" # 容忍度的键为 tier
operator: "Equal" # 操作符为 Equal,表示键的值必须等于指定的值。
value: "frontend" # 值为 frontend,表示键的值必须等于 frontend。
effect: "NoSchedule" # 效果为 NoSchedule,表示不会在节点上调度其他 Pod。
第三步:使用 kubectl 的 apply
命令创建 Pod。
kubectl apply -f pod.yaml
知识点:
- 什么是 Taint?它的作用是什么?
Taint 可以被视为节点上的特殊属性,表示该节点有一些限制或要求。当节点上存在 Taint 时,只有具有相应容忍度(tolerations)的 Pod 才能在该节点上调度和运行。
通过使用 Taint 和容忍度,可以实现一些有用的场景。例如,当节点出现故障或需要维护时,可以给节点添加一个Taint,阻止新的 Pod 调度到该节点上。另外,可以使用 Taint 来限制某些特殊任务只能运行在特定类型的节点上,例如高性能计算或存储密集型任务。
Taint 和容忍度的组合允许 Kubernetes 在节点级别实现细粒度的调度策略和资源管理。通过灵活使用 Taint 和容忍度,可以根据集群的需求和资源状况来优化 Pod 的调度和分配,提高集群的可用性和性能。
Create a pod that will be placed on node controlplane. Use nodeSelector and tolerations
译:创建一个 Pod,让它被调度到 controlplane 节点上。使用 nodeSelector 和 tolerations。
因为当前实验环境为单节点环境(节点本身就是 controlplane 节点),无法测试出 nodeSelector
和 tolerations
的效果,所以此处只需要掌握如何操作即可。
第一步:编辑上一步生成的 pom.yaml 文件,在 spec
下添加 nodeSelector
和 tolerations
配置。
apiVersion: v1
kind: Pod
metadata:
name: frontend
spec:
containers:
- name: nginx
image: nginx
nodeSelector:
kubernetes.io/hostname: controlplane
tolerations:
# node-role.kubernetes.io/control-plane 表示角色为 control-plane 的节点。
# 此 key 可以通过执行 kubectl get nodes --show-labels 命令查看。
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
第二步:删除之前创建的 Pod,否则在后续执行 apply 命令时会出错。
kubectl delete po frontend
第三步:删除之前为节点添加的 tier=frontend 污点,否则会出现无法调度的情况。
kubctl taint node kubernetes tier-
第四步:创建 Pod。
kubectl apply -f pod.yaml
Deployments(工作负载)
Create a deployment with image nginx:1.18.0, called nginx, having 2 replicas, defining port 80 as the port that this container exposes (don't create a service for this deployment)
译:创建一个名为 nginx 的 Deployment,使用镜像 nginx:1.18.0,副本数为 2,定义容器暴露的端口为 80(不要为这个 Deployment 创建 Service)。
- 方法一:直接使用 kubectl 的
create
命令创建。
kubectl create deploy nginx --image=nginx:1.18.0 --replicas=2 --port=80
- 方法二:使用 YAML 文件创建。
第一步:使用 kubectl 的 --dry-run
参数,生成 YAML 文件。
kubectl create deployment nginx --image=nginx:1.18.0 --dry-run=client -o yaml > deploy.yaml
第二步:编辑 YAML 文件,修改 replicas
字段为 2,然后在 container 下添加 containerPort
字段。完整 YAML 文件如下所示。
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
spec:
replicas: 2 # 指定副本数量为 2
selector:
matchLabels:
app: nginx # 选中标签为 app=nginx 的所有 Pods。
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.18.0
name: nginx
ports:
- containerPort: 80 # 指定暴露 80 端口。
第三步:使用 kubectl 的 apply
命令创建 Deployment。
kubectl apply -f deploy.yaml
View the YAML of this deployment
译:以 YAML 格式查看 Deployment 配置。
kubectl get deploy nginx -o yaml
View the YAML of the replica set that was created by this deployment
译:以 YAML 格式查看 Deployment 自动创建的 ReplicaSet 配置。
- 方法一:通过 ReplicaSet 名字查看。
第一步:查询 ReplicaSet 名称。
使用 kubectl 的 describe 命令查看 Deployment 的 ReplicaSet 名称。在查询结果中有一个名为 NewReplicaSet
的字段,它的值就是 Deployment 的 ReplicaSet 名称。
kubectl describe deploy nginx
第二步:使用 kubectl 的 get
命令查看 Deployment 的 ReplicaSet。
# 此处需要将 <replicaset-name> 替换为第一步中获取到的 ReplicaSet 名称。如:nginx-5c7588df4d。
kubectl get rs <replicaset-name> -o yaml
- 方法二:直接使用 kubectl 的
get
命令查看。
kubectl get rs -l app=nginx -o yaml
Get the YAML for one of the pods
译:以 YAML 格式查看 Pod 的配置。
第一步:获取 Pod 名称。
- 方法一:使用 kubectl
get
命令获取所有 Pod 的名称,然后选择以nginx
开头的 Pod 名称。
kubectl get po | grep nginx
- 方法二:通过标签直接获取 Pod 名称。
kubectl get po -l app=nginx
第二步:使用 kubectl 的 get
命令查看 Pod。
# 此处需要将 <pod-name> 替换为第一步中获取到的 Pod 名称。如:nginx-5c7588df4d-4q8q2。
kubectl get po <pod-name> -o yaml
Check how the deployment rollout is going
译:查看 Deployment 的滚动升级状态。
kubectl rollout status deploy nginx
知识点:
- 滚动升级的作用是什么?
Kubernetes的滚动升级是一种更新应用程序的方法,它允许无需中断地逐步替换旧版本的Pod,以确保应用程序的持续可用性。滚动升级的作用在于以下几个方面:
高可用性:滚动升级允许在升级过程中保持应用程序的连续运行,通过逐个替换Pod,确保应用程序不会因为升级而中断或停止对用户提供服务。
容错能力:如果新版本的Pod出现问题,滚动升级可以快速回滚到旧版本,以避免对应用程序的影响。这种容错能力可以减少由于升级引入的潜在问题对系统的影响。
无缝更新:滚动升级可以平滑地将应用程序从旧版本迁移到新版本,避免了大规模的中断或停机时间。通过逐步替换Pod,用户可以无感知地接收到新版本的功能和修复。
灵活性:滚动升级可以根据需要进行配置,例如逐个替换Pod的速率、并行替换的数量等。这种灵活性使得可以根据实际情况和需求进行升级,以最小化对系统的影响。
- 滚动升级的作用是什么?
Update the nginx image to nginx:1.19.8
译:将 Deployment 的镜像更新为 nginx:1.19.8。
- 方法一:直接使用 kubectl 的
set
命令更新镜像。
kubectl set image deploy nginx nginx=nginx:1.19.8
- 方法二:使用 edit 命令编辑 YAML。
将 .spec.template.spec.containers[0].image
的值改为 nginx:1.19.8。
kubectl edit deploy nginx
修改后的 YAML 文件如下所示:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.19.8 # 修改此处
name: nginx
ports:
- containerPort: 80
Check the rollout history and confirm that the replicas are OK
译:查看 Deployment 的滚动升级历史,并确认副本数正常。
# 查看滚动升级历史。
kubectl rollout history deploy nginx
kubectl get deploy nginx
# 查看是否创建了新的 ReplicaSet。
kubectl get rs
kubectl get po
Undo the latest rollout and verify that new pods have the old image (nginx:1.18.0)
译:回滚 Deployment 的最新滚动升级,并确认新的 Pod 使用的是旧镜像(nginx:1.18.0)。
kubectl rollout undo deploy nginx
kubectl get po
# 使用 jsonpath 语法直接获取 Deployment 的镜像信息。
kubectl get deploy nginx -o=jsonpath="{.spec.template.spec.containers[0].image}"
Do an on purpose update of the deployment with a wrong image nginx:1.91
译:故意将 Deployment 的镜像更新为错误的镜像 nginx:1.91。
- 方法一:直接使用 kubectl 的
set
命令更新镜像。
kubectl set image deploy nginx nginx=nginx:1.91
- 方法二:通过
edit
命令编辑 Deployment。
将 .spec.template.spec.containers[0].image
的值改为 nginx:1.91。
kubectl edit deploy nginx
Verify that something's wrong with the rollout
译:确认 Deployment 的滚动升级出现了问题。
kubectl rollout status deploy nginx
# 执行此命令后会发现 Pod 的状态为 ErrImagePull 或 ImagePullBackOff
kubectl get po
Return the deployment to the second revision (number 2) and verify the image is nginx:1.19.8
译:将 Deployment 回滚到第二个版本(版本号为 2),并确认镜像为 nginx:1.19.8。
# undo 命令用于做回滚。--to-revision 参数用于指定需要回滚到的版本号。
kubectl rollout undo deploy nginx --to-revision=2
kubectl describe deploy nginx | grep Image:
kubectl rollout status deploy nginx
kubectl get po
Check the details of the fourth revision (number 4)
译:查看 Deployment 的第四个版本(版本号为 4)的详细信息。
kubectl rollout history deploy nginx --revision=4
Scale the deployment to 5 replicas
译:将 Deployment 的副本数扩展为 5。
kubectl scale deploy nginx --replicas=5
kubectl get po
kubectl describe deploy nginx
Autoscale the deployment, pods between 5 and 10, targetting CPU utilization at 80%
译:为 Deployment 设置自动拓展策略,当 CPU 利用率达到 80% 的时候执行拓展,Pod 数在 5 - 10 之间。
# autoscale 命令用于创建 HPA 策略。
# --min 参数用于指定最小副本数。
# --max 参加用于指定最大副本数。
# --cpu-percent 用于指定 CPU 利用率,让利用率超过此值时执行拓展操作,低于此值时执行收缩操作。通过 --memory-percent 可以指定内存利用率。
kubectl autoscale deploy nginx --min=5 --max=10 --cpu-percent=80
kubectl get hpa nginx
知识点:
- HPA 的应用场景。
Kubernetes 的 HPA(Horizontal Pod Autoscaler)可以自动调整应用程序的副本数量,以根据负载需求进行扩展或收缩。它适用于应用程序负载波动较大的场景。HPA 可以根据 CPU 利用率、内存使用率等指标自动调整 Pod 的副本数量,以确保应用程序始终具有足够的资源来满足需求。当负载增加时,HPA会自动扩展 Pod 的副本数量,以提供更多的处理能力。当负载减少时,HPA会自动收缩Pod的副本数量,以节省资源并降低成本。这种自动水平扩展和收缩的能力使得应用程序可以根据实际需求动态地调整资源使用,提高了应用程序的可伸缩性和效率。无需手动干预,HPA可以帮助确保应用程序始终具有适当的资源配置,从而提供更好的性能和可靠性。
- HPA 的应用场景。
Pause the rollout of the deployment
译:暂停 Deployment 的滚动升级。
kubectl rollout pause deploy nginx
知识点:
- 暂停滚动升级有什么应用场景?
在滚动升级服务的过程中如果发现此次更新的版本有问题。此时可以先暂停滚动更新,等问题修复后再恢复滚动更新。防止因为一次性把所有副本都更新导致业务受到严重影响。
- 暂停滚动升级有什么应用场景?
Update the image to nginx:1.19.9 and check that there's nothing going on, since we paused the rollout
译:将 Deployment 的镜像更新为 nginx:1.19.9,并确认滚动升级已经暂停。
kubectl set image deploy nginx nginx=nginx:1.19.9
kubectl rollout history deploy nginx
kubectl rollout status deploy nginx
Resume the rollout and check that the nginx:1.19.9 image has been applied
译:恢复 Deployment 的滚动升级,并确认镜像已经更新为 nginx:1.19.9。
# 恢复滚动升级
kubectl rollout resume deploy nginx
kubectl rollout history deploy nginx
kubectl rollout history deploy nginx --revision=6
kubectl rollout status deploy nginx
kubectl describe deploy nginx | grep Image:
kubctl get po
Delete the deployment and the horizontal pod autoscaler you created
译:删除 Deployment 和 HorizontalPodAutoscaler。
- 方法一:使用两条命令分别删除 Deployment 和 HorizontalPodAutoscaler。
kubectl delete deploy nginx
kubectl delete hpa nginx
- 方法二:使用一条命令删除 Deployment 和 HorizontalPodAutoscaler。
kubectl delete deploy/nginx hpa/nginx
Implement canary deployment by running two instances of nginx marked as version=v1 and version=v2 so that the load is balanced at 75%-25% ratio
实现金丝雀部署,创建两个版本的 nginx,分别标记为 version=v1 和 version=v2,让它们的负载比例为 75%-25%。
第一步:创建三个 v1 版本的 Pod。
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-v1
labels:
app: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
version: v1
template:
metadata:
labels:
app: my-app
version: v1
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: workdir
mountPath: /usr/share/nginx/html
# 通过 initContainer 为 Pod 生成 html 文件,文件中的内容为 version-1
initContainers:
- name: install
image: busybox:1.28
command:
- /bin/sh
- -c
- "echo version-1 > /work-dir/index.html"
volumeMounts:
- name: workdir
mountPath: "/work-dir"
volumes:
- name: workdir
emptyDir: {}
第二步:创建一个 v2 版本的 Pod。
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-v2
labels:
app: my-app
spec:
replicas: 1
selector:
matchLabels:
app: my-app
version: v2
template:
metadata:
labels:
app: my-app
version: v2
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: workdir
mountPath: /usr/share/nginx/html
# 通过 initContainer 为 Pod 生成 html 文件,文件中的内容为 version-2
initContainers:
- name: install
image: busybox:1.28
command:
- /bin/sh
- -c
- "echo version-2 > /work-dir/index.html"
volumeMounts:
- name: workdir
mountPath: "/work-dir"
volumes:
- name: workdir
emptyDir: {}
第三步:创建 Service。
apiVersion: v1
kind: Service
metadata:
name: my-app-svc
labels:
app: my-app
spec:
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 80
selector:
app: my-app
第四步:结果验证。
# 循环执行 wget 命令访问 my-app-svc 服务,观察是否将小部分流量路由到了新版本。
kubectl run -it --rm --restart=Never busybox --image=busybox -- /bin/sh -c 'while sleep 1; do wget -qO- my-app-svc; done'
知识点:
- 什么是金丝雀部署?
金丝雀部署是一种软件发布策略,先小规模部署新版本服务,然后将少部分用户请求引流到新的服务,观察其运行情况。如果出现问题,可以快速回滚。若无问题,逐步扩大范围,直到覆盖整个生产环境。优势是可以快速发现和解决问题,降低发布风险,提高软件发布的质量和可靠性。
Jobs(普通任务)
Create a job named pi with image perl:5.34 that runs the command with arguments "perl -Mbignum=bpi -wle 'print bpi(2000)'"
译:创建一个名为 pi 的 Job,使用镜像 perl:5.34,执行命令 perl -Mbignum=bpi -wle 'print bpi(2000)'。
kubectl create job pi --image=perl:5.34 -- perl -Mbignum=bpi -wle 'print bpi(2000)'
Wait till it's done, get the output
译:等待 Job 执行完成,然后查看输出。
- 方法一:
# -w 参数可以一直监视 Job。
kubectl get jobs -w
kubectl get po
# 此处需要将 <pod-name> 替换为真实的 Pod 名称。
kubectl logs <pod-name>
kubectl delete job pi
- 方法二:
kubectl get jobs -w
kubectl logs job/pi
kubectl delete job pi
- 方法三:
# wait:这是 kubectl 的一个子命令,用于等待 Kubernetes 资源的特定条件。
# --for=condition=complete:这是 wait 命令的一个选项,指定要等待的条件。它要求作业的状态为 "complete",也就是作业的所有任务都已成功完成。
# --timeout=300s:这是 wait 命令的另一个选项,指定等待的超时时间。它设置超时时间为 300 秒(5 分钟)。
kubectl wait --for=condition=complete --timeout=300s job pi
kubectl logs job/pi
kubectl delete job pi
Create a job with the image busybox that executes the command 'echo hello;sleep 30;echo world'
译:创建一个名为 busybox 的 Job,使用镜像 busybox,执行命令 'echo hello;sleep 30;echo world'。
kubectl create job busybox --image=busybox -- /bin/sh -c 'echo hello;sleep 30;echo world'
Follow the logs for the pod (you'll wait for 30 seconds)
译:查看 Pod 的日志(你需要等待 30 秒)。
kubectl get po
# 此处需要将 <pod-name> 替换为真实的 Pod 名称。
# -f 参数的作用持续输出日志。
kubectl logs <pod-name> -f
See the status of the job, describe it and see the logs
译:查看 Job 的状态,然后查看 Pod 的日志。
kubectl get jobs
kubectl describe jobs busybox
kubectl logs job/busybox
Delete the job
译:删除 Job。
kubectl delete job busybox
Create a job but ensure that it will be automatically terminated by kubernetes if it takes more than 30 seconds to execute
译:创建一个 Job,如果它执行超过 30 秒,就让 Kubernetes 自动终止它。
第一步:生成 Yaml 文件。
kubectl create job busybox --image=busybox --dry-run=client -o yaml -- /bin/sh -c 'while true; do echo hello; sleep 10;done' > job.yaml
第二步:编辑 YAML 文件,在 spec
下添加 activeDeadlineSeconds
字段。
apiVersion: batch/v1
kind: Job
metadata:
creationTimestamp: null
name: busybox
spec:
activeDeadlineSeconds: 30 # 在此处添加
template:
metadata:
creationTimestamp: null
spec:
containers:
- command:
- /bin/sh
- -c
- while true; do echo hello; sleep 10;done
image: busybox
name: busybox
resources: {}
restartPolicy: Never
status: {}
第三步:使用 kubectl 的 apply
命令创建 Job。
kubectl apply -f job.yaml
第四步:删除 Job。
kubectl delete jobs busybox
知识点:
activeDeadlineSeconds
用于设置 Job 的最长执行时间,单位为秒。如果 Job 的执行时间超过此值,Kubernetes 会自动终止它。
Create the same job, make it run 5 times, one after the other. Verify its status and delete it
译:创建一个 Job,让它连续执行 5 次,然后再查看 Job 的状态,最后删除它。
第一步:生成 Yaml 文件。
kubectl create job busybox --image=busybox --dry-run=client -o yaml -- /bin/sh -c 'echo hello;sleep 30;echo world' > job.yaml
第二步:编辑 YAML 文件,在 spec
下添加 completions
字段。
apiVersion: batch/v1
kind: Job
metadata:
creationTimestamp: null
name: busybox
spec:
completions: 5 # 在此处添加
template:
metadata:
creationTimestamp: null
spec:
containers:
- command:
- /bin/sh
- -c
- echo hello;sleep 30;echo world
image: busybox
name: busybox
resources: {}
restartPolicy: Never
status: {}
第三步:使用 kubectl 的 apply
命令创建 Job。
kubectl apply -f job.yaml
第四步:查看 Job 的状态。
kubectl get job busybox -w
第五步:删除 Job。
kubectl delete jobs busybox
知识点:
completions
用于设定我们希望一个 Job 被成功执行的次数,就像我们预期的目标一样。默认情况下,这个值是 1。这就好比我们在玩一个篮球投篮游戏,目标是投进一次篮。如果我们没能一次投进,游戏就会让我们再试一次,直到我们成功投进,或者我们已经尝试了太多次(这个尝试的次数上限是backoffLimit
的值,默认为6次)都没投进则游戏结束。同样的,如果 Job 的成功执行次数小于 1,Kubernetes 就会像这个游戏一样,自动产生新的 Pod 继续执行,直到成功执行了一次,或者执行错误的次数达到了backoffLimit
指定的次数则自动停止。
Create the same job, but make it run 5 parallel times
译:创建一个 Job,让它同时执行 5 次。
第一步:编辑上一题中的 YAML 文件,在 spec
下添加 parallelism
字段。
apiVersion: batch/v1
kind: Job
metadata:
creationTimestamp: null
name: busybox
spec:
parallelism: 5 # 在此处添加
template:
metadata:
creationTimestamp: null
spec:
containers:
- command:
- /bin/sh
- -c
- echo hello;sleep 30;echo world
image: busybox
name: busybox
resources: {}
restartPolicy: Never
status: {}
第二步:使用 kubectl 的 apply
命令创建 Job。
kubectl apply -f job.yaml
第三步:查看 Job 的状态。
kubectl get jobs
第四步:删除 Job。
kubectl delete jobs busybox
知识点:
parallelism
用于配置在执行 Job 时允许并行创建 Pod 的个数。此值默认为 1,也就是说默认情况下是串行的逐个创建 Pod 并执行。如果我们希望可以同时创建多个 Pod 一起执行,此时可以通过parallelism
来配置。
此配置可以和
completions
搭配使用,在搭配时可能存在下面几种情况:parallelism
大于completions
:这种情况下,Job 会立即启动parallelism
数量的 Pod,但只要有completions
数量的 Pod 成功完成,Job 就会标记为完成。超出completions
数量的 Pod,如果已经在运行,会被允许继续运行,但不会再启动新的 Pod。parallelism
小于completions
:在这种情况下,Job 会启动parallelism
数量的 Pod,然后等待它们完成后再启动新的 Pod,直到达到completions
数量的 Pod 成功完成,Job 才会标记为完成。parallelism
等于completions
:这种情况下,Job 会同时启动completions
数量的 Pod,所有的 Pod 都需要成功完成,Job 才会标记为完成。这种模式通常被用于需要大量并行处理的任务。
Cron Jobs(定时任务)
Create a cron job with image busybox that runs on a schedule of "/1 *" and writes 'date; echo Hello from the Kubernetes cluster' to standard output
译:创建一个名为 busybox 的 CronJob,使用镜像 busybox,执行命令 'date; echo Hello from the Kubernetes cluster',并且每分钟执行一次。
kubectl create cronjob busybox --image=busybox --schedule="*/1 * * * *" -- /bin/sh -c 'date; echo Hello from the Kubernetes cluster'
See its logs and delete it
译:查看 CronJob 的日志,并删除它。
kubectl get po
# 此处需要将 <pod-name> 替换为真实的 Pod 名称。
kubectl logs <pod-name>
# --force 参数表示强制删除 CronJob。
kubectl delete cj busybox --force
知识点:
*/1 * * * *
是一个 Cron 表达式,表示每分钟执行一次。如果对 Cron 表达式不熟悉可通过一些在线工具生成。
Create the same cron job again, and watch the status. Once it ran, check which job ran by the created cron job. Check the log, and delete the cron job
译:再次创建相同的 CronJob,查看它的状态。一旦它执行完成,查看它创建的 Job。查看 Job 的日志,并删除 CronJob。
kubectl get cj
# --watch 和之前使用过的 -w 参数的作用一样。
kubectl get jobs --watch
kubectl get po --show-labels
# 此处需要将 <pod-name> 替换为真实的 Pod 名称。
kubectl logs <pod-name>
kubectl delete cj busybox
Create a cron job with image busybox that runs every minute and writes 'date; echo Hello from the Kubernetes cluster' to standard output. The cron job should be terminated if it takes more than 17 seconds to start execution after its scheduled time (i.e. the job missed its scheduled time)
译:创建一个名为 busybox 的 CronJob,使用镜像 busybox,执行命令 'date; echo Hello from the Kubernetes cluster',并且每分钟执行一次。如果 CronJob 在计划执行时间后 17 秒内没有开始执行,就终止它。
第一步:生成 Yaml 文件。
kubectl create cronjob time-limited-job --image=busybox --restart=Never --dry-run=client --schedule="* * * * *" -o yaml -- /bin/sh -c 'date; echo Hello from the Kubernetes cluster' > time-limited-job.yaml
第二步:编辑 YAML 文件,在 spec
下添加 startingDeadlineSeconds
字段。
apiVersion: batch/v1
kind: CronJob
metadata:
creationTimestamp: null
name: time-limited-job
spec:
startingDeadlineSeconds: 17 # 在此处添加
jobTemplate:
metadata:
creationTimestamp: null
name: time-limited-job
spec:
template:
metadata:
creationTimestamp: null
spec:
containers:
- command:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
image: busybox
name: time-limited-job
resources: {}
restartPolicy: Never
schedule: '* * * * *'
status: {}
第三步:使用 kubectl 的 apply
命令创建 CronJob。
kubectl apply -f time-limited-job.yaml
第四步:删除 CronJob。
kubectl delete cj time-limited-job
知识点:
startingDeadlineSeconds
参数指定了作业启动的截止时间,即作业的第一个实例开始执行的最大等待时间。如果在这个时间内作业没有成功启动,则 CronJob 不会再尝试启动该作业的实例,而是将其视为失败。- 如果
startingDeadlineSeconds
没有设置,或者设置为 0,则表示作业启动的截止时间为无限大,即 CronJob 会一直尝试启动作业实例,直到成功为止。 - 如果
startingDeadlineSeconds
设置为一个正整数,则表示作业启动的截止时间为该整数所表示的秒数。如果在这个时间内作业没有成功启动,则 CronJob 将不再尝试启动该作业的实例,并将其标记为失败。 - 如果作业的启动截止时间已过,但 CronJob 的时间计划仍然满足条件,则 CronJob 会尝试启动下一个作业实例,而不会等待上一个实例的完成。
Create a cron job with image busybox that runs every minute and writes 'date; echo Hello from the Kubernetes cluster' to standard output. The cron job should be terminated if it successfully starts but takes more than 12 seconds to complete execution
译:创建一个名为 busybox 的 CronJob,使用镜像 busybox,执行命令 'date; echo Hello from the Kubernetes cluster',并且每分钟执行一次。如果 CronJob 成功开始执行,但是执行时间超过 12 秒,就终止它。
第一步:编辑上一题中的 YAML 文件,删除 spec
下的 startingDeadlineSeconds
字段,然后添加 activeDeadlineSeconds
字段。
apiVersion: batch/v1
kind: CronJob
metadata:
creationTimestamp: null
name: time-limited-job
spec:
jobTemplate:
metadata:
creationTimestamp: null
name: time-limited-job
spec:
activeDeadlineSeconds: 12 # 在此处添加
template:
metadata:
creationTimestamp: null
spec:
containers:
- command:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
image: busybox
name: time-limited-job
resources: {}
restartPolicy: Never
schedule: '* * * * *'
status: {}
第二步:使用 kubectl 的 apply
命令创建 CronJob。
kubectl apply -f time-limited-job.yaml
Create a job from cronjob
译:从 CronJob 创建一个 Job。
kubectl create job --from=cronjob/sample-cron-job sample-job
系列文章
CKAD考试实操指南(一)--- 登顶CKAD:征服考试的完美蓝图
[CKAD考试实操指南(二)---深入核心:探秘Kubernetes核心实操秘技]
[CKAD考试实操指南(三)---舞动容器:多容器Pod实践指南]