【译文】Kubernetes 150 个操作练习 (上)

一入K8S深似海,从此红尘是路人

原文链接:Practice Enough With These 150 Questions for the CKAD Exam

看了 Medium 上的一篇文章记录了 150 个 Kubernetes 的练习,自己练习了一遍,在原文基础上根据自己的练习过程加了一些补充提示,希望对需要熟悉 K8S 操作的同学有所帮助。

练习之前需要自行搭建好一个 K8S 集群,可以参考我之前的一篇文章 利用 Kubeadm 搭建 Kubenetes 集群

一. 核心概念篇

这部分主要的练习目的是:

  • 了解 Kubernetes API 的基本操作
  • 创建、查看配置 Pod 的基本操作

1. 查看集群中的所有命名空间

1
2
kubectl get namespaces
kubectl get ns

2. 查看所有命名空间的 Pod

1
kubectl get po --all-namespaces

3. 查看指定命名空间里的所有 pod

  • 使用 -n 参数指定命名空间
1
kubectl get po -n <namespace name>
  • 示例
1
2
3
$ kubectl get po -n ingress-nginx
NAME                                        READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-585f5478d8-wq2v2   1/1     Running   0          10d

4. 查看指定命名空间的 Service

1
2
3
$ 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

1
kubectl get pods -o=jsonpath="{.items[*]['metadata.name', 'metadata.namespace']}"

补充

我自己练习时展示内容如下,可读性不是特别好

1
2
3
# 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 的输出效果更好,如下:

1
2
3
4
5
6
7
8
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

1
2
3
4
// 创建 Pod
kubectl run nginx --image=nginx --restart=Never
// 列出 Pod
kubectl get po

7. 使用 yaml 文件创建运行 Nginx 的 Pod

1
2
3

// 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 文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Never
status: {}
1
2
// 通过 yaml 文件创建 Pod
kubectl create -f nginx-pod.yaml

8. 输出 Pod 的 yaml 文件描述

1
kubectl get po nginx -o yaml

补充

和第 5 题有所重复,-o 的输出选项有下面这些 在这里插入图片描述

具体查看官方文档 Output options

9. 输出 Pod 的 yaml 文件描述,但不包含 集群特定信息

1
kubectl get po nginx -o yaml --export

补充

--export 选项已经被废弃了,截至 v1.18.0 版本虽然还能用,但未来可能会移除。实际运行会有下面提示:

1
2
$ kubectl get po nginx  -o yaml --export
Flag --export has been deprecated, This flag is deprecated and will be removed in future.

10. 获取 Pod 的详细信息

1
kubectl describe pod nginx

11. 删除刚创建的 Nginx Pod

1
2
3
kubectl delete po nginx

kubectl delete -f nginx-pod.yaml

12. 强制删除 Pod

1
2
3
$ 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 的版本和开放端口

1
kubectl run nginx --image=nginx:1.17.4 --restart=Never --port=80

14. 修改 Pod 的镜像版本并验证

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 通过命令的方式修改
$ 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

1
2
3
kubectl set image pod/nginx nginx=nginx:1.17.1
kubectl describe po nginx
kubectl get po nginx -w # watch it

16. 不使用 describe 查看 Pod 的容器镜像版本

1
2
$ kubectl get po nginx -o jsonpath='{.spec.containers[].image}{"\n"}'
nginx:1.17.1

17. 创建 Nginx Pod 并执行 shell 命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 创建 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]

加了 -- 间隔符,表示在 -- 间隔符后执行的都是在容器中执行命令,这样命令区分起来更清晰一些,示例如下:

1
2
3
4
$ 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 地址

1
2
3
4
$ 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 命令,查看其日志

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 创建 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 中上一个容器实例的日志

1
kubectl logs busybox -p

21. 创建运行 busybox 容器的 Pod 并执行 命令 sleep 3600

1
kubectl run busybox --image=busybox --restart=Never -- /bin/sh -c "sleep 3600"

22. 从 busybox 容器的 Pod 访问 Nginx Pod

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13

# 查看 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 并打印信息 ,然后手动删除

1
2
3
4
5
6
7
# 创建 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 参数
1
2
3
$ kubectl run busybox --image=busybox  --restart=Never -it --rm -- echo "How are you"
How are you
pod "busybox" deleted

25. 基于不同的等级查看 Pod

1
2
3
4
5
6
7
# 创建容器
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 时命令展示的内容。

1
2
3
4
5
6
7
8
9
$ 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 展示名称和状态

1
kubectl get po -o=custom-columns="POD_NAME:.metadata.name, POD_STATUS:.status.containerStatuses[].state"
  • 还是 -o 输出选项的使用

27. 查看所有的 Pod,根据名称排序

1
kubectl get pods --sort-by=.metadata.name

28. 查看所有的 Pod,根据创建时间排序

1
kubectl get pods --sort-by=.metadata.creationTimestamp

二. 多容器 Pod 篇

这部分练习的主要目的是:

  • 理解 Pod 的多容器设计模式

29. 创建运行三个 busybox 容器的 Pod 并执行命令

  • yaml 文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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 并查看日志
1
2
# 创建 Pod
kubectl create -f multi-container.yaml

30. 查看上面 Pod 中三个容器的日志

  • -c 参数指定容器
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
$ 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 先前的容器日志

1
kubectl logs busybox -c busybox2 --previous
  • --previous 参数展示的上一个容器实例的日志,如果我们的 busybox2 容器没有重建过,那就是第一个实例,这时候是没法查看日志的,运行命令会报错:
1
2
$ kubectl logs busybox -c busybox2 --previous
Error from server (BadRequest): previous terminated container "busybox2" in pod "busybox" not found

32. 在 Pod 中的指定容器中运行命令

1
2
# 在 busybox Pod 中的 busybox3 容器中执行 ls  命令
kubectl exec busybox -c busybox3 -- ls

33. 查看 Pod 里容器的指标并存入文件中查看

1
2
3
4
5
6
7
8
$ 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 与内存使用,如下
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ 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 文件,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
1
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 内容,并且可以通过请求访问。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 查看主容器的文件
$ 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 设计的练习。

Built with Hugo
Theme Stack designed by Jimmy