原文链接: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
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 设计的练习。

Logo

开源、云原生的融合云平台

更多推荐