原文链接:Practice Enough With These 150 Questions for the CKAD Exam。
看了 Medium 上的一篇文章记录了 150 个 Kubernetes 的练习,自己练习了一遍,在原文基础上根据自己的练习过程加了一些补充提示,希望对需要熟悉 K8S 操作的同学有所帮助。
练习之前需要自行搭建好一个 K8S 集群,可以参考我之前的一篇文章 利用 Kubeadm 搭建 Kubenetes 集群。
一. 核心概念篇
这部分主要的练习目的是:
- 了解 Kubernetes API 的基本操作
- 创建、查看配置 Pod 的基本操作
1. 查看集群中的所有命名空间
kubectl get namespaces
kubectl get ns
2. 查看所有命名空间的 Pod
kubectl get po --all-namespaces
3. 查看指定命名空间里的所有 pod
- 使用
-n
参数指定命名空间
kubectl get po -n <namespace name>
- 示例
$ kubectl get po -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-585f5478d8-wq2v2 1/1 Running 0 10d
4. 查看指定命名空间的 Service
$ kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.104.62.77 <none> 80:30372/TCP,443:31465/TCP 19d
5.列出所有的 Pod,基于 json path 表达式只展示 name 和 namseapce
kubectl get pods -o=jsonpath="{.items[*]['metadata.name', 'metadata.namespace']}"
补充
我自己练习时展示内容如下,可读性不是特别好
# ubuntu @ VM-0-4-ubuntu in ~ [13:37:55]
$ kubectl get pods -o=jsonpath="{.items[*]['metadata.name', 'metadata.namespace']}\n"
example-pv-pod kubia-59d857b444-6z596 kubia-59d857b444-pmm5z kubia-59d857b444-w2r27 kubia-manual my-app-v1-c9b7f9985-xnwkt my-app-v2-77fc8c9499-9nxv2 default default default default default default default\n%
比起用 json-path
的输出格式,另外一种格式 custom-columns
的输出效果更好,如下:
NAME NAMESPACE
example-pv-pod default
kubia-59d857b444-6z596 default
kubia-59d857b444-pmm5z default
kubia-59d857b444-w2r27 default
kubia-manual default
my-app-v1-c9b7f9985-xnwkt default
my-app-v2-77fc8c9499-9nxv2 default
关于 -o
参数输出选项的设置,可以参考官方文档 Output options。
6. 在 default 命名空间创建并查看运行 Nginx 的 Pod
// 创建 Pod
kubectl run nginx --image=nginx --restart=Never
// 列出 Pod
kubectl get po
7. 使用 yaml 文件创建运行 Nginx 的 Pod
// run 运行一个 Nginx Pod,然后通过 --dry-run=client 参数指定参数 -o 将 Pod 的定义描述写入文件
kubectl run nginx --image=nginx --restart=Never --dry-run=client -o yaml > nginx-pod.yaml
-
注:原文中的参数是
--dry-run
,在新的 K8S 版本中已经过时,被--dry-run=client
替换了。 -
yaml 文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
// 通过 yaml 文件创建 Pod
kubectl create -f nginx-pod.yaml
8. 输出 Pod 的 yaml 文件描述
kubectl get po nginx -o yaml
补充
和第 5 题有所重复,-o
的输出选项有下面这些
具体查看官方文档 Output options。
9. 输出 Pod 的 yaml 文件描述,但不包含 集群特定信息
kubectl get po nginx -o yaml --export
补充
--export
选项已经被废弃了,截至 v1.18.0 版本虽然还能用,但未来可能会移除。实际运行会有下面提示:
$ kubectl get po nginx -o yaml --export
Flag --export has been deprecated, This flag is deprecated and will be removed in future.
10. 获取 Pod 的详细信息
kubectl describe pod nginx
11. 删除刚创建的 Nginx Pod
kubectl delete po nginx
kubectl delete -f nginx-pod.yaml
12. 强制删除 Pod
$ kubectl delete po nginx --grace-period=0 --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "nginx" force deleted
备注
--grace-period
表示删除 Pod 前可以有几秒的处理时间,设置为负数时会被忽略,设置为 1 说明要立即删除。只有加上--force
参数时才可以设置为 0,表示立刻强制删除。
13. 创建 Nginx Pod,并指定 Nginx 的版本和开放端口
kubectl run nginx --image=nginx:1.17.4 --restart=Never --port=80
14. 修改 Pod 的镜像版本并验证
# 通过命令的方式修改
$ kubectl set image pod/nginx nginx=nginx:1.15-alpine
pod/nginx image updated
#
# 通过 edit 方式,会使用 vim 打开 Pod 的yaml 文件,修改后保存,K8S 会基于修改后的文件修改 Pod。
$ kubectl edit po nginx
# 修改保存后提示 edited
pod/nginx edited
# 修改后查看 Pod
$ kubectl describe pod nginx
15. 将 Nginx 的镜像版本改回 1.17.1
kubectl set image pod/nginx nginx=nginx:1.17.1
kubectl describe po nginx
kubectl get po nginx -w # watch it
16. 不使用 describe 查看 Pod 的容器镜像版本
$ kubectl get po nginx -o jsonpath='{.spec.containers[].image}{"\n"}'
nginx:1.17.1
17. 创建 Nginx Pod 并执行 shell 命令
// 创建 Pod
$ kubectl run nginx --image=nginx --restart=Never
pod/nginx created
// exec 执行 命令进入 Pod 容器
$ kubectl exec -it nginx /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
# ls # 进入 Pod 容器后查看文件列表
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
#
补充
上面是我实际执行的命令和输出,可以看到 K8S 提示 kubectl exec [POD] [COMMAND]
已经过时不推荐使用了,现在推荐的使用是下面格式:
kubectl exec [POD] – [COMMAND]
加了 --
间隔符,表示在 --
间隔符后执行的都是在容器中执行命令,这样命令区分起来更清晰一些,示例如下:
$ kubectl exec -it nginx -- /bin/sh
# ls
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
18. 查看 Pod 列表,并展示 IP 地址
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
example-pv-pod 1/1 Running 0 28h 192.168.171.172 vm-0-2-ubuntu <none> <none>
nginx 1/1 Running 0 8m15s 192.168.171.175 vm-0-2-ubuntu <none> <none>
- 依然是
-o
命令输出选项的使用
19. 创建运行 busybox 容器的 Pod 并执行 ls 命令,查看其日志
# 创建 Pod 并执行命令
$ kubectl run busybox --image=busybox --restart=Never -- ls
pod/busybox created
# 查看日志
$ kubectl logs busybox
bin
dev
etc
home
proc
root
sys
tmp
usr
var
20. 查看 Pod 中上一个容器实例的日志
kubectl logs busybox -p
21. 创建运行 busybox 容器的 Pod 并执行 命令 sleep 3600
kubectl run busybox --image=busybox --restart=Never -- /bin/sh -c "sleep 3600"
22. 从 busybox 容器的 Pod 访问 Nginx Pod
# 查看 Nginx Pod 的 IP 地址
$ kubectl get po nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 19m 192.168.171.175 vm-0-2-ubuntu <none> <none>
# 在 busybox 中执行命令,请求 Nginx Pod
$ kubectl exec -it busybox -- wget -o- 192.168.171.175
Connecting to 192.168.171.175 (192.168.171.175:80)
saving to 'index.html'
index.html 100% |********************************| 612 0:00:00 ETA
'index.html' saved
23. 创建运行 busybox 容器的 Pod 并打印信息 ,然后手动删除
# 创建 Pod,打印详细
$ kubectl run busybox --image=busybox --restart=Never -it -- echo "How are you"
How are you
# 手动删除
$ kubectl delete po busybox
pod "busybox" deleted
24. 创建运行 busybox 容器的 Pod 并打印信息后自动删除
- 执行的命令中添加了
--rm
参数
$ kubectl run busybox --image=busybox --restart=Never -it --rm -- echo "How are you"
How are you
pod "busybox" deleted
25. 基于不同的等级查看 Pod
# 创建容器
kubectl run nginx --image=nginx --restart=Never --port=80
# 通过 --v 指定查看的等级
kubectl get po nginx --v=7
kubectl get po nginx --v=8
kubectl get po nginx --v=9
不同的等级有不同的展示内容,下面是 --v=7
时命令展示的内容。
$ kubectl get po nginx --v=7
I0425 14:48:51.332674 7424 loader.go:375] Config loaded from file: /home/ubuntu/.kube/config
I0425 14:48:51.353559 7424 round_trippers.go:420] GET https://172.19.0.4:6443/api/v1/namespaces/default/pods/nginx
I0425 14:48:51.353586 7424 round_trippers.go:427] Request Headers:
I0425 14:48:51.354807 7424 round_trippers.go:431] Accept: application/json;as=Table;v=v1;g=meta.k8s.io,application/json;as=Table;v=v1beta1;g=meta.k8s.io,application/json
I0425 14:48:51.354835 7424 round_trippers.go:431] User-Agent: kubectl/v1.18.0 (linux/amd64) kubernetes/9e99141
I0425 14:48:51.363918 7424 round_trippers.go:446] Response Status: 200 OK in 9 milliseconds
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 2m8s
26.查看 Pod 列表,使用自定义的 POA_NAME 和 POD_STATUS 展示名称和状态
kubectl get po -o=custom-columns="POD_NAME:.metadata.name, POD_STATUS:.status.containerStatuses[].state"
- 还是
-o
输出选项的使用
27. 查看所有的 Pod,根据名称排序
kubectl get pods --sort-by=.metadata.name
28. 查看所有的 Pod,根据创建时间排序
kubectl get pods --sort-by=.metadata.creationTimestamp
二. 多容器 Pod 篇
这部分练习的主要目的是:
- 理解 Pod 的多容器设计模式
29. 创建运行三个 busybox 容器的 Pod 并执行命令
- yaml 文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: busybox
name: busybox
spec:
containers:
- args:
- bin/sh
- -c
- ls; sleep 3600
image: busybox
name: busybox1
resources: {}
- args:
- bin/sh
- -c
- echo Hello world; sleep 3600
image: busybox
name: busybox2
resources: {}
- args:
- bin/sh
- -c
- echo this is third container; sleep 3600
image: busybox
name: busybox3
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 创建 Pod 并查看日志
# 创建 Pod
kubectl create -f multi-container.yaml
30. 查看上面 Pod 中三个容器的日志
-c
参数指定容器
$ kubectl logs busybox -c busybox1
bin
dev
etc
home
proc
root
sys
tmp
usr
var
$ kubectl logs busybox -c busybox2
Hello world
$ kubectl logs busybox -c busybox3
this is third container
31. 查看 Pod 中 busybox2 先前的容器日志
kubectl logs busybox -c busybox2 --previous
--previous
参数展示的上一个容器实例的日志,如果我们的 busybox2 容器没有重建过,那就是第一个实例,这时候是没法查看日志的,运行命令会报错:
$ kubectl logs busybox -c busybox2 --previous
Error from server (BadRequest): previous terminated container "busybox2" in pod "busybox" not found
32. 在 Pod 中的指定容器中运行命令
# 在 busybox Pod 中的 busybox3 容器中执行 ls 命令
kubectl exec busybox -c busybox3 -- ls
33. 查看 Pod 里容器的指标并存入文件中查看
$ kubectl top pod busybox --containers
POD NAME CPU(cores) MEMORY(bytes)
busybox busybox2 0m 0Mi
busybox busybox3 0m 0Mi
busybox busybox1 0m 0Mi
// putting them into file
kubectl top pod busybox --containers > file.log
cat file.log
补充
- 【1】 通过 top 命令可以查看 node 和 pod 的 CPU 与内存使用,如下
$ kubectl top nodes
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
vm-0-2-ubuntu 126m 6% 2142Mi 58%
vm-0-4-ubuntu 138m 6% 2252Mi 61%
# ubuntu @ VM-0-4-ubuntu in ~ [16:32:47]
$ kubectl top pods
NAME CPU(cores) MEMORY(bytes)
busybox 0m 1Mi
my-app-v1-c9b7f9985-xnwkt 1m 2Mi
my-app-v2-77fc8c9499-9nxv2 1m 2Mi
nginx
-
【2】 top 命令的使用需要安装 metric-server 并修改 TLS 相关的配置,否则会报错,可以参考下面几篇文章
34. 创建一个多容器 Pod
该 Pod 要求如下:
- 主容器:运行 busybox 容器,不断写入文本到 index.html 文件
- sideCar 容器:运行 Nginx,读取主容器写入的文件 index.html,对外提供访问
- 两个容器通过 Volume 实现文件的共享
下面是 Pod 的 yaml 文件,
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: multi-cont-pod
name: multi-cont-pod
spec:
volumes:
- name: var-logs
emptyDir: {}
containers:
- image: busybox
command: ["/bin/sh"]
args: ["-c", "while true; do echo 'Hi I am from Main container' >> /var/log/index.html; sleep 5;done"]
name: main-container
resources: {}
volumeMounts:
- name: var-logs
mountPath: /var/log
- image: nginx
name: sidecar-container
resources: {}
ports:
- containerPort: 80
volumeMounts:
- name: var-logs
mountPath: /usr/share/nginx/html
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 创建 Pod
kubectl create -f multi-container.yaml
35. 查看 Pod 中主副容器的文件内容
在上面创建的 Pod 中可以看到,
- 主容器中将 ‘Hi I am from Main container’ 写入了
/var/log/index.html;
,并挂载到了var-logs
卷 - 副容器 Nginx 将目录
/usr/share/nginx/html
挂载到了var-logs
卷,以为着在该目录下我们可以读到主容器写入的 index.html 内容,并且可以通过请求访问。
# 查看主容器的文件
$ kubectl exec -it multi-cont-pod -c main-container -- sh
/ # cat /var/log/index.html
Hi I am from Main container
# 查看副容器的内容
$ kubectl exec -it multi-cont-pod -c sidecar-container -- sh
# cat /usr/share/nginx/html/index.html
Hi I am from Main container
Hi I am from Main container
Hi I am from Main container
# 在副容器中通过请求访问
# 安装 curl
# apt-get update && apt-get install -y curl
# 请求访问
# curl localhost
Hi I am from Main container
Hi I am from Main container
Hi I am from Main container
Hi I am from Main container
以上就是前两部分的练习,只有 35 个不算多,花两个小时练习下就熟悉了,下一篇主介绍 Pod 设计的练习。