【K8S认证】CKA考题汇总(解析+答案)
需要身份证购买购买完成后在我的考试中查看考试券,去国外站点进行报名将考试码粘贴到如下进行注册。
报名
中国区报名地址:https://training.linuxfoundation.cn 需要身份证购买
购买完成后在我的考试
中查看考试券,去国外站点进行报名https://trainingportal.linuxfoundation.org
将考试码粘贴到如下进行注册
预约
访问https://trainingportal.linuxfoundation.org/learn/dashboard
考试界面讲解
提交试卷后24小时左右会出成绩,会发邮件让你下载证书,去官网可以查看分数。
CKA
CKA认证考试是由Linux基金会和云原生计算基金会(CNCF)创建的,以促进Kubernetes生态系统的持续发展。该考试是一种远程在线、有监考、基于实操的认证考试,需要在运行Kubernetes的命令行中解决多个任务。CKA认证考试是专为Kubernetes管理员、云管理员和其他管理Kubernetes实例的IT专业人员而设的。
CKA这个证书基本是个入门级的考试,有些同学听到通过考取证书,可以得到更多的工作机会,实际上技术好的同学有一张证书可以是锦上添花,如果是技术差的用一张证书去撑场面到最后跨的一定是自己。在国内大部分证书随着时间的推移,含金量都会变低,比如思科的CCIE等。因为很多证书都是批量生产的状态,背题就能过,所以通过证书并不能代表自己的实力。
1 RBAC
Context
为部署流水线创建一个新的 ClusterRole 并将其绑定到范围为特定的 namespace 的特定ServiceAccount。
Task
创建一个名为 deployment-clusterrole 的 clusterrole,该 clusterrole 只允许对 Deployment、Daemonset、Statefulset 具有 create 权限,在现有的 namespace app-team1 中创建一个名为 cicd-token 的新 ServiceAccount。
限于 namespace app-team1 中,将新的 ClusterRole deployment-clusterrole 绑定到新的 ServiceAccount cicd-token。
官方文档搜索关键字:使用 RBAC 鉴权
切换集群
kubectl config use-context k8s
创建一个名为 deployment-clusterrole 的 ClusterRole 对象,允许对 Deployment、Daemonset、Statefulset 具有 create 权限
kubectl create clusterrole deployment-clusterrole --verb=create --resource=Deployment,StatefulSet,DaemonSet
创建sa
kubectl create serviceaccount cicd-token -n app-team1
绑定sa,题目中写了限于app-team1名称空间,所以用rolebinding。如果不限制名称空间则创建clusterrolebinding
kubectl create rolebinding rb-cicd-token(relebinding名字,随便起的,因为题目中没有要求) --clusterrole=deployment-clusterrole --serviceaccout=app-team1:cicd-token --namespace=app-team1
检查验证
root@cka-master1:~# kubectl describe rolebindings rb-cicd-token -n app-team1
Name: rb-cicd-token
Labels: <none>
Annotations: <none>
Role:
Kind: ClusterRole
Name: deployment-clusterrole
Subjects:
Kind Name Namespace
---- ---- ---------
ServiceAccount cicd-token app-team1
2 节点维护
将 ek8s-node-1
节点设置为不可用,然后重新调度该节点上的所有 Pod
官方文档搜索关键字:安全地清空一个节点
切换到指定集群
kubectl config use-context ek8s
将节点设置为不可调度
kubectl cordon ek8s-node-1
将该节点上的pod进行驱逐,重新调度
kubectl drain ek8s-node-1 --delete-emptydir-data --ignore-daemonsets --force
查看节点状态
kubectl get node
查看pod所在节点
kubectl get pod -owide
3 版本升级
Task
现有的 Kubernetes 集群正在运行版本 1.23.1。仅将 master 节点上的所有 Kubernetes 控制平面和节点组件升级到版本 1.23.2。(注意,考试时的集群可能为 1.23.0,会让你从 1.23.0 升级为 1.23.1。甚至是 1.22.1 升级为 1.22.2。所以敲命令时,具体要升级的版本,根据题目要求更改。)
确保在升级之前 drain master 节点,并在升级后 uncordon master 节点。
可以使用以下命令,通过 ssh 连接到 master 节点:ssh master01
可以使用以下命令,在该 master 节点上获取更高权限:sudo -i
另外,在主节点上升级 kubelet 和 kubectl。请不要升级工作节点,etcd,container 管理器,CNI 插件, DNS 服务或任何其他插件。
官方文档搜索关键字:upgrade
考试时执行,切换集群
kubectl config use-context mk8s
查看节点信息
root@cka-master1:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
cka-master Ready control-plane,master 3h v1.23.1
cka-node1 Ready <none> 175m v1.23.1
将节点标记为不可调度并驱逐所有负载,准备节点的维护
kubectl cordon k8s-master-1
kubectl drain k8s-master-1 --delete-emptydir-data --ignore-daemonsets --force
在考试环境中 ssh 到 master 节点,并切换到 root 下
ssh master
sudo -i
升级 kubeadm
$ apt-get update
# 找到题目要求升级到的指定版本
$ apt-cache madison kubeadm | grep 1.23.2
kubeadm | 1.23.2-00 | http://mirrors.ustc.edu.cn/kubernetes/apt kubernetes-xenial/main amd64 Packages
$ apt-get install kubeadm=1.23.2-00
验证下载操作正常,并且 kubeadm 版本正确
$ kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.2", GitCommit:"9d142434e3af351a628bffee3939e64c681afa4d", GitTreeState:"clean", BuildDate:"2022-01-19T17:34:34Z", GoVersion:"go1.17.5", Compiler:"gc", Platform:"linux/amd64"}
验证升级计划:此命令检查你的集群是否可被升级,并取回你要升级的目标版本。 命令也会显示一个包含组件配置版本状态的表格
kubeadm upgrade plan
# 排除 etcd,升级其他的
kubeadm upgrade apply v1.23.2 --etcd-upgrade=false
# 升级 kubelet 和 kubectl
apt-mark unhold kubelet kubectl
apt-get install kubelet=1.23.2-00 kubectl=1.23.2-00
apt-mark hold kubelet kubectl
systemctl daemon-reload
systemctl restart kubelet
# 考试环境中退出 root,退回到 student@master01
[root @master 01 ] # exit
# 考试环境中退出 master01,退回到 student@node-1
[student @master 01 ] $ exit
# 不要输入 exit 多了,否则会退出考试环境的。
# 解除节点的保护
root@cka-master1:~# kubectl uncordon cka-master1
# 检查 master1 是否为 Ready
root@cka-master1:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
cka-master1 Ready control-plane,master 3h40m v1.23.2
cka-node1 Ready <none> 3h36m v1.23.1
如果报错如下:
root@cka-master1:~# rm /var/lib/apt/lists/lock
root@cka-master1:~# rm /var/cache/apt/archives/lock
root@cka-master1:~# rm /var/lib/dpkg/lock*
root@cka-master1:~# dpkg --configure -a
4 ETCD 备份恢复
注意:真实考试时,第 3 题是升级集群那道题。建议真正考试时,前 4 道题按照顺序做,特别是第 4 题,且做完后不要再修改,做完第 3 道题,如果没有 exit 退出到 student@node-1,则无法执行 etcdctl 命令,另外这道题没有切换集群,用的是第 3 道题的集群,所以,这道题做完就不要在回来检查或者操作了。etcd 不建议放到最后做,如果最后做,etcd 备份还原可能把所有 pod 都清空了,这个问题有可能会出现,所以前 4 道题按照顺寻做。
此项目无需更改配置环境,但是,在执行此项目之前,请确保您已返回初始节点。etcd 这道题真实考试为第 4 题,用的集群是真实考试时的上一题的集群,即真题第 3 题 mk8s,所以无需再切换集群了。
Task
首先,为运行在 https://127.0.0.1:2379 上的现有 etcd 实例创建快照并将快照保存到 /srv/data/etcd-snapshot.db 文件。
为给定实例创建快照预计能在几秒钟内完成。 如果该操作似乎挂起,则命令可能有问题。用 CTRL + C 来取消操作然后重试。
然后还原位于 /var/lib/backup/etcd-snapshot-previous.db 的现有先前快照。
提供了以下 TLS 证书和密钥,以通过 etcdctl 连接到服务器:
CA证书: /opt/KUIN00601/ca.crt
客户端证书: /opt/KUIN00601/etcd-client.crt
客户端密钥: /opt/KUIN00601/etcd-client.key
考试时确认一下 ssh 终端,是在 [student@node-1] $ 下
# 备份
# 如果不使用 export ETCDCTL_API=3,而使用 ETCDCTL_API=3,则下面每条 etcdctl 命令前都要加ETCDCTL_API=3
# 如果执行时,提示 permission denied,则是权限不够,命令最前面加 sudo 即可。
export ETCDCTL_API=3
# 先检查考试环境有没有题目说的目录 /srv/data/,没有的话则需要自己创建
root@cka-master1:~# mkdir -pv /srv/data/
# 下面的证书是模拟环境中的位置,考试时用题目给的三个证书
root@cka-master1:~# sudo ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key snapshot save /srv/data/etcd-snapshot.db
# 还原题目指定的 /var/lib/backup/etcd-snapshot-previous.db 文件
root@cka-master1:~# sudo ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key snapshot restore /var/lib/backup/etcd-snapshot-previous.db
5 NetworkPolicy
Task
在现有的 namespace my-app 中创建一个名为 allow-port-from-namespace 的新 NetworkPolicy。确保新的 NetworkPolicy 允许 namespace echo 中的 Pods 连接到 namespace my-app 中的Pods 的 9000 端口。
进一步确保新的NetworkPolicy:
不允许对没有在监听端口 9000 的 Pods 的访问
不允许非来自 namespace echo 中的 Pods 的访问
官方文档搜索关键字:网络策略
切换集群
kubectl config use-context hk8s
查看所有 ns 的标签 label
kubectl get ns --show-labels
如果访问者的 namespace 没有标签 label,则需要手动打一个。如果有一个独特的标签 label,则也可以直接使用。
kubectl label ns my-app project=my-app
参考官方文档,拷贝 yaml 文件内容,并修改。注意先输入 “:set paste”,防止复制时 yaml 文件空格错序。
root@cka-master1:~# vim networkpolicy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-port-from-namespace
namespace: my-app # 被访问着的名称空间
spec:
podSelector: # 这两行必须要写,或者也可以写成一行为 podSelector: {}
matchLabels: {}
policyTypes:
- Ingress # 策略影响入栈流量
ingress:
- from: # 允许流量的来源
- namespaceSelector:
matchLabels:
project: my-app # 访问者的命名空间的标签 label
ports:
- protocol: TCP
port: 9000 # 被访问者公开的端口
创建网络策略资源
kubectl apply -f networkpolicy.yaml
检查
root@cka-master1:~# kubectl get networkpolicy -n my-app
NAME POD-SELECTOR AGE
allow-port-from-namespace <none> 4m37s
root@cka-master1:~# kubectl describe networkpolicy allow-port-from-namespace -n my-app
Name: allow-port-from-namespace
Namespace: my-app
Created on: 2023-01-03 19:44:38 -0800 PST
Labels: <none>
Annotations: <none>
Spec:
PodSelector: <none> (Allowing the specific traffic to all pods in this namespace)
Allowing ingress traffic:
To Port: 9000/TCP
From:
NamespaceSelector: project=echo
Not affecting egress traffic
Policy Types: Ingress
6 service
重新配置一个已经存在的 front-end 的 deployment,在名字为 nginx 的容器里面添加一个端口配置,名字为 http,暴露端口号为 80,然后创建一个 service,名字为 front-end-svc,暴露该deployment 的 http 端,并且 service 的类型为 NodePort。
官方文档搜索关键字:服务
切换集群
kubectl config use-context k8s
参考官方文档,按照需要 edit deployment
,添加端口信息
root@cka-master1:~# kubectl edit deployments front-end
······
imagePullPolicy: Always
name: nginx
ports:
- containerPort: 80
name: http
······
创建 service,以下两种方法二选一即可
# 命令行形式
root@cka-master1:~# kubectl expose deployment front-end --name=front-end-svc --port=80 --target-port=http --type=NodePort
# 编写 yaml 文件形式,复制官方文档的内容进行修改
root@cka-master1:~# vim service.yaml
apiVersion: v1
kind: Service
metadata:
name: front-end-svc # 题目指定的名称
spec:
type: NodePort # 题目指定的 service 类型
selector:
app: nginx # deployment 中 pod 的标签
ports:
- port: 80 # 题目指定暴露的端口
targetPort: http # 题目指定暴露的 http 端
root@cka-master1:~# kubectl apply -f service.yaml
查看 service 资源
root@cka-master1:~# kubectl get svc front-end-svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
front-end-svc NodePort 10.98.31.4 <none> 80:30737/TCP 16s
7 ingress
在 ing-internal 名称空间下创建一个ingress,名字为pong,代理server hi,端口为5678,配置路径/hi
可以使用以下命令检查服务 hi 的可用性:curl -kL <INTERNAL_IP>/hi
会返回hi
官方文档搜索关键字:ingress
切换集群
kubectl config use-context k8s
创建 ingress 资源。拷贝官网的 yaml 案例,修改相关参数即可。先输入 ":set paste",防止 yaml 文件空格错序
root@cka-master1:~# vim ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: pong # 题目指定名称
namespace: ing-internal # 题目指定的名称空间
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /hi # 题目指定的 url
pathType: Prefix
backend:
service:
name: hi
port:
number: 5678 # 题目指定的端口
root@cka-master1:~# kubectl apply -f ingress.yaml
root@cka-master1:~# kubectl get ingress -n ing-internal
NAME CLASS HOSTS ADDRESS PORTS AGE
pong nginx * 80 10s
8 Deployment扩缩容
将名字为 loadbalancer 的 deployment 副本数扩容为 6
$ kubectl config use-context k8s
$ kubectl scale deployment loadbalancer --replicas=6
查看是否扩容成功,不用管pod的状态
kubectl get deployment loadbalancer
9 指定节点部署
创建一个 Pod,名字为 nginx-kusc00401,镜像地址是 nginx,调度到具有 disk=spinning
标签的节点上
官方文档搜索关键字:将 Pod 分配给节点
查看 node 节点标签
kubectl get nodes --show-labels
# 创建 pod
root@cka-master1:~# vim nodeselector.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-kusc00401 # 题目指定的 pod 名称
spec:
containers:
- name: nginx # 题目指定的镜像
image: nginx
#imagePullPolicy: IfNotPresent
nodeSelector:
disk: spinning # 题目指定的被分配的节点标签
root@cka-master1:~# kubectl apply -f nodeselector.yaml
检查是否调度到对应的节点
root@cka-master1:~# kubectl get pods -o wide nginx-kusc00401
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-kusc00401 1/1 Running 0 13s 10.244.115.73 cka-node1 <none> <none>
10 检查Node节点的健康状态
检查集群中有多少节点为 Ready 状态,并且去除包含 NoSchedule 污点的节点。之后将数字写到/opt/KUSC00402/kusc00402.txt
切换 k8s 集群环境:
$ kubectl config use-context k8s
记录Ready的总数A
kubectl get node | grep -i ready
记录所有节点状态为Ready并且包含 NoSchedule 污点的总数B
kubectl describe node node名 | grep NoSchedule
将 A 减 B 的值 x 导入到/opt/KUSC00402/kusc00402.txt
echo x >> /opt/KUSC00402/kusc00402.txt
kubectl describe node $(kubectl get node | grep Ready | awk ‘{print $1}’) | grep Taint | grep -vc NoSchedule > /opt/402.txt
查看结果
cat /opt/KUSC00402/kusc00402.txt
11 一个pod封装多个容器
创建一个 Pod名字为 kucc1,这个 Pod 包含 4 个容器: nginx、redis、memcached、consul
切换集群
kubectl config use-context k8s
编写 yaml 文件
root@cka-master1:~# vim kucc1.yaml
apiVersion: v1
kind: Pod
metadata:
name: kucc1
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
- name: redis
image: redis
imagePullPolicy: IfNotPresent
- name: memcached
image: memcached
imagePullPolicy: IfNotPresent
- name: consul
image: consul
imagePullPolicy: IfNotPresent
创建pod
kubectl apply -f kucc1.yaml
查看pod,题目没有要求该pod必须启动,只需创建即可
root@cka-master1:~# kubectl get pods kucc1
NAME READY STATUS RESTARTS AGE
kucc1 4/4 Running 0 3s
12 PV
创建一个 pv,名字为app-config
,大小为 2Gi,访问权限为 ReadWriteMany。Volume 的类型为 hostPath,路径为/srv/app-config
官方文档搜索关键字:PersistentVolume
切换集群
kubectl config use-context hk8s
考试环境路径已存在
ls /srv/app-config
编写yaml文件
root@cka-master1:~# vim pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: app-config # 题目中指定的 pv 名称
spec:
capacity:
storage: 2Gi # 题目指定的 pv 大小
accessModes:
- ReadWriteMany # 题目指定的访问模式
hostPath:
path: "/srv/app-config" # 题目指定的路径
创建 pv
kubectl apply -f pv.yaml
查看pv
root@cka-master1:~# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
app-config 2Gi RWX Retain Available 6s
13 pvc
创建一个名字为 pv-volume 的 pvc,指定 storageClass 为 csi-hostpath-sc,大小为 10Mi。然后创建一个 Pod,名字为 web-server,镜像为 nginx,并且挂载该 PVC 至 /usr/share/nginx/html,挂载的权限为 RedWriteOnce。之后通过 kubectl edit 或者 kubectl path 将 pvc 改成 70Mi,并且记录修改记录。
官方文档搜索关键字:PersistentVolume
1、考试时执行,切换集群
kubectl config use-context ok8s
2、编写yaml文件
root@cka-master1:~# vim pvc-pod.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv-volume # 题目指定的 pvc 名称
spec:
storageClassName: csi-hostpath-sc # 题目指定的存储类名称
accessModes:
- ReadWriteOnce # 题目指定的访问模式
resources:
requests:
storage: 10Mi # 题目指定的 pvc 大小
---
apiVersion: v1
kind: Pod
metadata:
name: web-server # 题目指定的 pod 名称
spec:
volumes:
- name: pv-volume # 与 volumeMounts.name 一致
persistentVolumeClaim:
claimName: pv-volume # 使用的 pvc 名称
containers:
- name: nginx
image: nginx # 题目指定的镜像
volumeMounts:
- mountPath: "/usr/share/nginx/html" # 题目指定的挂载目录
name: pv-volume
3、创建
kubectl apply -f pvc-pod.yaml
4、查看是否创建成功。之所以是 pending 状态是模拟环境中没有存储类 storageClassName: csi-hostpath-sc,考试环境中存在,无需担心
root@cka-master1:~# kubectl get pvc pv-volume
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pv-volume Pending csi-hostpath-sc 21s
root@cka-master1:~# kubectl get pods web-server
NAME READY STATUS RESTARTS AGE
web-server 0/1 Pending 0 31s
5、pvc 扩容。将 storage: 10Mi 修改为 70Mi
root@cka-master1:~# kubectl edit pvc pv-volume
······
resources:
requests:
storage: 70Mi
storageClassName: csi-hostpath-sc
······
14 监控pod日志
监控 Pod 名为 foobar 的日志,并过滤出具有 unable-access-website 信息的行,然后将写入到 /opt/KUTR00101/foobar
$ kubectl config use-context k8s
$ kubectl logs foobar | grep unable-access-website > /opt/KUTR00101/foobar
如果这个pod中有两个容器的话
$ kubectl logs pod名 -c 容器名
检查是否写入到对应的文件
cat /opt/KUTR00101/foobar
15 sidecar
添加一个名为 busybox 且镜像为 busybox 的 sidecar 到一个已经存在的名为 legacy-app 的 Pod上,这个 sidecar 的启动命令为 /bin/sh -c tail -n+1 -f /var/log/legacy-app.log
。并且这个sidecar 和原有的镜像挂载一个名为logs的volume,挂载的目录为/var/log/
1、切换答题环境(考试环境有多个,每道题要在对应的环境中作答)
kubectl config use-context k8s
2、将legacy-app的pod的yaml导出
kubectl get pod legacy-app -oyaml > c-sidecar.yaml
再此yaml中添加sidecar和volume
vi c-sidecar.yaml
apiVersion: v1
kind: Pod
metadata:
name: 11-factor-app
spec:
containers:
- name: count
image: busybox
args:
- /bin/sh
- -c
- >
i=0;
while true;
do
echo "$i: $(date)" >> /var/log/11-factor-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/11-factor-app.log']
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
emptyDir: {}
3、删除原pod,创建新pod
kubectl delete pod 11-factor-app
kubectl apply -f factor-app.yaml
4、查看日志是否输出到控制台
16 查看cpu使用率最高的pod
找出具有 name=cpu-user
的 Pod,并过滤出使用 CPU 最高的 Pod,然后把它的名字写在已经存在的/opt/KUTR00401/KUTR00401.txt
文件里。注意:他没有说指定 namespace,所以需要使用-A
指定所有 namespace
$ kubectl config use-context k8s
$ kubectl top pod -A -l name=cpu-user --sort-by="cpu"
NAMESPACE NAME CPU(cores) MEMORY(bytes)
kube-system coredns-54d67798b7-hl8xc 7m 8Mi
kube-system coredns-54d67798b7-m4m2q 6m 8Mi
注意这里的 pod 名字以实际名字为准,按照 CPU 那一列进行选择一个最大的 Pod。如果CPU的数值是 1
2
3
不带m,不带m的数值是大于带 m的,因为 1 颗CPU等于 1000m
注意要用>>而不是>
$ echo "coredns-54d67798b7-hl8xc" >> /opt/KUTR00401/KUTR00401.txt
17 集群故障排查 – kubelet 故障
一个名为 wk8s-node-0 的节点状态为 NotReady,检查发生这种情况的原因,并采取相应措施将node 恢复为Ready 状态,确保所做的任何更改永久生效。
1、切换答题环境(考试环境有多个,每道题要在对应的环境中作答)
kubectl config use-context ek8s
2、查看节点状态
kubectl get node
3、切换到故障节点
ssh wk8s-node-0
sudo -i
4、检查节点状态并加入开机自启动
systemctl status kubelet
systemctl start kubelet
systemctl enable kubelet
5、退出故障节点
exit
更多推荐
所有评论(0)