CKA考题讲解
0.考试101
0.1 kubectl命令⾃动补全
在 bash 中设置当前 shell 的⾃动补全,要先安装 bash-completion 包。
echo "source <(kubectl completion bash)" >> ~/.bashrc
还可以在补全时为 kubectl 使⽤⼀个速记别名:
alias k=kubectl
complete -o default -F __start_kubectl k
0.2 切换cluster环境
kubectl config use-context hk8s
kubectl config use-context CONTEXT_NAME [options]
0.3 关于–all-namespace
使⽤ -A 参数来简写完整参数内容 --all-namespaces
0.4 查看资源作⽤域
## 列出所⽀持的全部资源类型和它们的简称、API组, 是否是名字空间作⽤域 和 Kind。
kubectl api-resources
kubectl api-resources --namespaced=true # 所有命名空间作⽤域的资源
kubectl api-resources --namespaced=false # 所有⾮命名空间作⽤域的资源
kubectl api-resources -o name # ⽤简单格式列举所有资源(仅显示资源名称)
kubectl api-resources -o wide # ⽤扩展格式列举所有资源(⼜称 "wide" 格式)
kubectl api-resources --verbs=list,get # ⽀持 "list" 和 "get" 请求动词的所有资源
kubectl api-resources --api-group=extensions # "extensions" API 组中的所有资源
0.5 关于–dry-run
kubectl create deploy nginx --image=nginx --dry-run=client -o yaml > deploynginx.yml
1.权限控制RBAC
Context:为流⽔线创建⼀个新的 ClusterRole 并为其绑定到范围为指定 namespace 的 特定ServiceAccount 。
Task:创建⼀个名为 deployment-clusterrole 且 仅允许创建 以下资源类型的新 ClusterRole
Deployment
StatefulSet
DaemonSet
在现有的 namespace app-team1 创建⼀个名为 cicd-token 的新 ServiceAccount 。
限于 namespace app-team1 中,将新的 ClusterRole deployment-clusterrole 绑定到新的 ServiceAccount
cicd-token 。
#在现有的 namespace **app-team1** 创建⼀个名为 cicd-token 的新 ServiceAccount 。
kubectl create sa cicd-token -n app-team1
#创建⼀个名为 deployment-clusterrole 且 仅允许创建 以下资源类型的新 ClusterRole
Deployment
StatefulSet
DaemonSet
kubectl create clusterrole deployment-clusterrole --verb=create --resource=deployment,daemonsets,statefulsets
#限于 namespace app-team1 中,将新的 ClusterRole deployment-clusterrole 绑定到新的 ServiceAccount cicd-token
kubectl create rolebinding cicd --clusterrole=deployment-clusterrole --serviceaccount=app-team1:cicd-token -n app-team1
2.查看pod的CPU
Task
通过 pod label name=cpu-loader ,并找到运⾏时占⽤⼤量CPU的pod。
并将占⽤CPU最⾼的 pod名称写⼊⽂件 /opt/KUTR000401/KUTR00401.txt(已存在)。
#环境如果异常,kubectl top 命令⽆法执⾏,那么⾸先 kubectl describe pod/metrics-server-pod -n kube-system 并尝试删除 kubectl delete pod/metrics-server-pod -n kube-system,等待pod重建后 READY状态恢复为1/1。
#如果执行 kubectl top pod -A
error: Metrics API not available #要在 Kubernetes 集群中安装 Metrics Server
kubectl top pods -A -l name=cpu-loader --sort-by='cpu'
echo pod-name >> /opt/KUTR00401/KUTR00401.txt
3.配置⽹络策略NetworkPolicy
Task
在现有的 namespace corp-net 中创建⼀个名为 allow-port-from-namespace 的新 NetworkPolicy。
确保新的 NetworkPolicy 允许 namespace echo 中的 Pods 连接到 namespace corp-net 中的 Pods 的 80 端
⼝
进⼀步确保新的 NetworkPolicy:
不允许对没有在监听 端⼝ 80 的Pods的访问
不允许⾮来⾃ namespace echo 中的 Pods的访问
https://kubernetes.io/zh-cn/docs/concepts/services-networking/network-policies/
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-port-from-namespace
namespace: corp-net
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: echo
ports:
- protocol: TCP
port: 80
####################################################################################
apiVersion: networking.k8s.io/v1 # 指定使用的 Kubernetes 网络策略 API 版本
kind: NetworkPolicy # 定义这是一个网络策略资源
metadata:
name: allow-port-from-namespace # 网络策略的名称
namespace: corp-net # 指定网络策略应用的命名空间
spec:
podSelector: {} # 选择当前命名空间内的所有 Pod(因为没有指定任何标签选择器)
policyTypes:
- Ingress # 指定策略类型为 Ingress,即控制进入 Pod 的流量
ingress: # 定义 Ingress 规则
- from: # 指定允许的流量来源
- namespaceSelector: # 使用命名空间选择器来选择允许的命名空间
matchLabels: # 定义要匹配的标签
name: echo # 只有标签为 name=echo 的命名空间中的 Pod 可以访问
ports: # 指定允许访问的端口
- protocol: TCP # 使用 TCP 协议
port: 80 # 目标端口为 80
kubectl get pod -n corp-net -o wide
kubectl exec -it pod/echo-pod -n echo --sh
curl pod-ip #容器内验证策略是否⽣效
telnet pod-ip 6379
4.暴露服务service
Task
请重新配置现有的deployment front-end 以及添加名为 http 的端⼝规范来公开现有容器 nginx 的端⼝
80/tcp 。
创建⼀个名为 front-end-svc 的 service,以暴露容器端⼝ http。
配置此 service,以通过各个pod所在节点上的 NodePort 来公开他们。
https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/#type-nodeport
kubectl explain deployment.spec.template.spec.containers.ports #查看语法
kubectl edit deploy/front-end -n default #编辑deployment
编辑 front-end-svc.yml
apiVersion: v1
kind: Service
metadata:
name: front-end-svc
namespace: default
spec:
type: NodePort
selector:
app: front-end
ports:
# 默认情况下,为了⽅便起⻅,`targetPort` 被设置为与 `port` 字段相同的值。
- port: 80
targetPort: http
# 可选字段
# 默认情况下,为了⽅便起⻅,Kubernetes 控制平⾯会从某个范围内分配⼀个端⼝号(默认:30000-32767)
nodePort: 30007
应⽤yaml⽂件,并验证
kubectl apply -f front-end-svc.yml
kubectl get svc
curl localhost:30007
5.创建Ingress
Task:
创建⼀个新的 nginx Ingress 资源
名称 ping
Namespace: ing-internal
使⽤端⼝ 5678 在路径 /hello 上公开service hello
可⽤以下命令检查服务 hello 的可⽤性,该命令应返回 hello
curl -kL <INTERNAL_IP>/hello
https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/
kubectl get ingressclasses -A #获取ingressclass名称
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
namespace:ing-internal
annotations:
kubernetes.io/ingress.class: "nginx" #此段在官⽅⽂档中没有提供。考试时先加上这⼀句,在apply之后,等5分钟,如果ingress⼀直没有IP,则删除此段,再apply⼀下,等5分钟。如果还是没有,也找不到错误。建议继续往下做题,不要纠结于此处。
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx-example #官⽅⽂档中提供了此段,1.25的考试中,ingressclass 查询不到。因此这⾏不写。
rules:
- http:
paths:
- path: /he;lo
pathType: Prefix
backend:
service:
name: hello
port:
number: 5678
6.扩容deployment副本
Task:
将 deployment guestbook 扩展⾄ 4 个 pods
kubectl get deploy/guestbook -o wide
kubectl scale deploy/guestbook --replicas 4
kubectl get deploy/guestbook -o wide
7.调度pod到指定节点
Task:
按如下要求调度⼀个 Pod
名称: nginx-kusc00401
Image:nginx
Node selector: disk=ssd
空间名称 default
https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/
apiVersion: v1
kind: Pod
metadata:
name: nginx-kusc00401
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disk: ssd
8.查看可⽤节点数量
Task:
检查有多少 nodes 已经就绪 (不包括被打上 Taint: NoSchedule 的节点),并将数量写⼊
/opt/KUSC00402/kusc00402.txt chown magedu: /opt/KUSC00402/kusc00402.txt
kubectl describe nodes | grep -i Taint | grep -vci NoSchedule
echo node-num >> /opt/KUSC00402/kusc00402.txt
9.创建多容器的pod
Task:
按如下要求调度⼀个Pod:名称 kucc8
app containers:2
container名称/image
-
nginx
-
consul
空间名称 default
apiVersion: v1
kind: Pod
metadata:
name: kucc8
spec:
containers:
- name: nginx
image: nginx
- name: consul
image: consul
10.创建PV
Task
创建名为 app-data 的 persistent volume ,容量为 1Gi ,访问模式为 ReadWriteOnce 。
volume 类型为 hostPath ,位于 /srv/app-data
apiVersion: v1
kind: PersistentVolume
metadata:
name: app-data
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/srv/app-data"
11.创建PVC
Task
创建⼀个新的 PersistentVolumeClaim :
-
名称 pv-volume
-
Class csi-hostpath-sc managed-nfs-storage
-
容量 10Mi
创建⼀个新的 Pod,将 PersistentVolumeClaim 作为 volume 进⾏挂载:
-
名称 web-server
-
image nginx
-
挂载路径 /usr/share/nginx/html
配置新的Pod,使得对上述 volume 具有 ReadWriteOnce 权限。
最后,使⽤ kubectl edit 或 kubectl patch 将 PersistentVolumeClaim 的容量扩展为 70Mi,并记录此更改。
https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/#create-a-persistentvolumeclaim
pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv-volume
spec:
storageClassName: csi-hostpath-sc
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Mi
pvc-pod.yml
apiVersion: v1
kind: Pod
metadata:
name: web-server
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: pv-volume
containers:
- name: web-server
image: nginx
ports:
- containerPort: 80
name: "http"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storage
kubectl apply -f pvc.yml
kubectl apply -f pvc-pod.yml
kubectl get pvc
kubectl edit pvc/pv-volume --record #调整PVC的容量⼤⼩
12.查看pod⽇志
Task
监控 pod foo 的⽇志并 提取与错误 file-not-found 相对应的⽇志⾏
将这些⽇志⾏写⼊ /opt/KUTR00101/foo
kubectl get pods -A
kubectl logs pod/foo | grep 'file-not-found' > /opt/KUTR00101/foo
cat !!:$
13.使⽤sidecar代理容器⽇志
Context
将⼀个现有的 Pod 集成到 Kubernetes 的内置⽇志记录体系结构中(例如 kubectl logs)。
添加 streaming sidecar 容器是实现此要求的⼀种好⽅法。
Task
使⽤ busybox Image 来将名为 sidecar 的 sidecar 容器添加到现有的 Pod big-corp-app 中。
新的 sidecar 容器必须运⾏以下命令:
/bin/sh -c tail -n+1 -f /var/log/big-corp-app.log
使⽤挂载在 /var/log 的 Volume,使⽇志⽂件 big-corp-app.log 可⽤于 sidecar 容器。
除了添加所需要的 volume mount 以外,请勿更改现有容器的规格。
kubectl get pod/big-corp-app -n default -o yaml > big-corp-app-origin.yml
cp big-corp-app-origin.yml big-corp-app.yml
https://kubernetes.io/zh-cn/docs/concepts/cluster-administration/logging/#sidecar-container-with-logging-agent
编辑 big-corp-app.yml
apiVersion: v1
kind: Pod
metadata:
name: big-corp-app
namespace: default
spec:
containers:
- name: count
image: busybox
args:
- /bin/sh
- -c
- >
i=0;
while true;
do
echo "$(date) INFO $i" >> /var/log/big-corp-app.log;
i=$((i+1));
sleep 1;
done
volumeMounts:
- name: varlog
mountPath: /var/log
- name: sidecar
image: busybox
args:
- /bin/sh
- -c
- >
tail -n+1 -F /var/log/big-corp-app.log
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
emptyDir: {}
14.升级集群
Task
现有的 Kubernetes 集群正在运⾏版本 1.24.2。仅将 master 节点上的所有 Kubernetes 控制平⾯和节点组件升级
到版本 1.24.3。
确保在升级之前 drain master 节点,并在升级后 uncordon master 节点。
可以使⽤以下命令,通过 ssh 连接到 master 节点:
ssh master01
可以使⽤以下命令,在该 master 节点上获取更⾼权限:
sudo -i
另外,在主节点上升级 kubelet 和 kubectl。
请不要升级⼯作节点,etcd,container 管理器,CNI 插件, DNS 服务或任何其他插件。
https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/#upgrading-control-plane-nodes
#考试节点上去保护并排空升级节点的pod
kubectl cordon master01
kubectl drain master01 --ignore-daemonsets=true --delete-emptydir-data=true
ssh master01
sudo -i
###升级管理⼯具
apt-mark unhold kubeadm && \
apt-get update && apt-get install -y kubeadm=1.24.3-00 && \
apt-mark hold kubeadm
#验证版本
kubeadm version
#验证集群升级计划
kubeadm upgrade plan
#升级集群版本,包含 kube-apiserver、kube-controller-manager、kube-scheduler、kubeproxy,排除etcd
kubeadm upgrade apply v1.24.3 --etcd-upgrade=false
#多个master节点,使⽤kubeadm upgrade node升级其他控制平⾯节点
###升级master节点的 kubelet 和 kubectl
apt-mark unhold kubelet kubectl && \
apt-get update && apt-get install -y kubelet=1.24.3-00 kubectl=1.24.3-00 && \
apt-mark hold kubelet kubectl
#解除节点保护
exit
exit
kubectl uncordon master01
15.备份还原etcd
Task
⾸先,为运⾏在 https://127.0.0.1:2379 上的现有 etcd 实例创建快照并将快照保存到 /var/lib/backup/etcdsnapshot.db
为给定实例创建快照预计能在⼏秒钟内完成。 如果该操作似乎挂起,则命令可能有问题。⽤ CTRL + C 来取消操
作,然后重试。
然后还原位于/data/backup/etcd-snapshot-previous.db 的现有先前快照。
提供了以下 TLS 证书和密钥,以通过 etcdctl 连接到服务器。
CA 证书: /opt/KUIN00601/ca.crt
客户端证书: /opt/KUIN00601/etcd-client.crt
客户端密钥: /opt/KUIN00601/etcd-client.key
https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/
##1.25的考试中,etcd的备份还原是在操作机上进⾏操作
export ETCDCTL_API=3
#备份
etcdctl --endpoints=https://10.100.0.100:2379 --cacert="/opt/KUIN00601/ca.crt" --
cert="/opt/KUIN00601/etcd-client.crt" --key="/opt/KUIN00601/etcd-client.key"
snapshot save /var/lib/backup/etcd-snapshot.db
#查看
etcdctl snapshot status /var/lib/backup/etcd-snapshot -w table
#查看
ll /data/backup/etcd-snapshot-previous.db
#还原
etcdctl --endpoints=https://10.100.0.100:2379 --cacert="/opt/KUIN00601/ca.crt" --
cert="/opt/KUIN00601/etcd-client.crt" --key="/opt/KUIN00601/etcd-client.key"
snapshot restore /data/backup/etcd-snapshot-previous.db --data-dir=/var/lib/etcd
16.排查集群中故障节点
Task
名为 node02 的 Kubernetes worker node 处于 NotReady 状态。
调查发⽣这种情况的原因,并采取相应的措施将 node 恢复为 Ready 状态,确保所做的任何更改永久⽣效。
可以使⽤以下命令,通过 ssh 连接到 node02 节点:
ssh node02
可以使⽤以下命令,在该节点上获取更⾼权限:
sudo -i
ssh node02
sudo -i
systemctl status kubelet.service
systemctl enable --now kubelet.service
systemctl status kubelet.service
exit
exit
kubectl get nodes
17.节点维护
Task:
将名为 node02 的node 设置为不可⽤,并重新调度该 node上所有运⾏的 pods。
kubectl cordon node02
kubectl drain node02 --ignore-daemonsets --delete-emptydir-data --force