2020年五一CKA/CKAD双证考试心得
背景
前段时间趁着比特币价格大涨把namebase白嫖送的4246HNS(约0.9个BTC)卖了换钱,正好可以支付两个CKA/CAKD认证考试费用,因此趁着五一出不去宅在家同时考了CKA和CKAD双证,1号考CKA,4号考CKAD。
其中CKA共24题3个小时考试时间,我基本在两个小时多点做完了,检查了40分钟,提前了约15分钟交卷,结果97分,有一道关于tolerations的题目痛失3分。
而CKAD共19道题2个小时考试时间,不要小看只有19道题比CKA少了5道,工作量还是很大的,时间非常紧张,我的经验教训就是不要在考试中磨磨唧唧导致后面有一道题根本没有时间,最后剩下一道关于Ambassador的一道题没做,还有一道关于sidecar的题目应该是少了个环境变量导致Pod状态为Crash没来得及修,最后分数不是很满意只有88分。
这里多说一句,还没有免费领取比特币并且Github账号在2019年2月4日followers人数大于15的可以到这个网站领取Claim your Handshake Airdrop[1],操作指南可以参考知乎Handshake Namebase“送给开源程序员每人几千元”是怎么回事?[2]。
考试前准备
CKA和CKAD报名费都是300刀,使用优惠券(Coupons)ANYWHERE30
可以享受7折优惠只需要210刀,官方显示到4月30号截止,但我在5月1号13点左右报名使用仍然有效。

今天发现官方改成截止日期到5月31日了:

由于众所周知的原因,首先需要解决的就是科学上网问题,不得不说如何配置科学上网是学习Kubernetes第一步,否则可能连自己部署Kubernetes时连镜像都拉不下来。
另外考虑共享带宽问题,建议选择在早上6点左右考试,因为9点之后大家都起来上网看视频抢带宽了,可能会导致终端卡顿。
辩证地使用网上的资料,尽信书不如无书,Google或者百度搜CKA/CKAD考试会有各种所谓的考试真题,但需要注意题目可能不是最新的,并且可能会有多套题目,应该是真正掌握Kubernetes技能,而不是依赖于背诵题目,看了网上的解析题目有时反而限制了自己的思维。
比如网上说的Bootstrap TLS题目我就没有遇到,但出现了从零开始创建一个Kubernetes集群的题目。
另外一个问题是题目答案很多就是错的,注意辨别。比如网上说有使用kubectl run --image image1 --image image2
创建多容器Pod的,这个语法我是没有见过。
还有网上几乎所有题目解析都说通过Service的labels去找关联的Pod,这是很明显的错误,Service本身的label和Pod没有任何关系,关联Pod Label使用的是selector,最简单的方式查看Service与Pod关联的label应该是kubectl get svc -o wide
而不是kubectl get svc --show-labels
。
除了这些,其他还有很多处错误,并且好多不同的所谓原创博客但错误却都是一样的,估计是相互参考了。
考试环境
考试环境使用的是Ubuntu 16.04,Kubernetes是目前最新版本v1.18,kubectl命令自动补全已经配好了,直接就可以用,不需要手动再操心去配了,这个还是很人性化的。
据说Windows不能使用ctrl+c/ctrl+v
复制粘贴,幸好我使用的是MacOS,MacOS复制粘贴很方便,和平常一样使用Cmd+c/Cmd+v
就可以,题目中的一些关键字,比如Deployment Name、Namespace、ssh命令等都会高亮显示并且单击就可以直接复制,很人性化,很方便。
需要注意的是考试环境的Web终端节点是一个跳板机,可以通过kubectl config use-context
切换不同的集群以及ssh到任意节点,但它本身并不属于任何一个集群的Node,因此如果创建了一个Service,直接访问ClusterIP是不通的,如果要检查创建的Service通不通,需要手动ssh到任意一个Master Node节点上去curl
。
另外特别需要注意的是老版本我们习惯使用kubectl run
子命令快速创建资源,通过--restart
参数决定创建的是Deployment
还是Pod
,甚至很多资料也推荐使用这种方式快速创建Deployment以及Pod。
但考试环境使用的是新版本,新版本kubectl run
子命令只能创建Pod了,不能创建Deployment、Job等其他资源了。
主要有两个原因,参考kubectl run is deprecated looking for alternative[3]:
run
命令参数太多了,不利于新手学习。即使是Kubernetes老手,也不一定能完全记住这么多的参数,不同的参数行为还不一样。代码维护越来越困难。
因此从两年前社区就开始着手去掉通过run
命令去创建除Pod之外的资源,参考Start deprecating all generators in run except for run-pod/v1,并于今年1月正式代码合并彻底废弃run
创建除Pod之外的资源Remove kubectl run generators[4]。
所以建议大家还是使用官方推荐的kubectl create
命令快速创建除Pod之外的其他资源,比如创建Deployment
:
kubectl create deployment nginx --image=nginx --dry-run -o yaml
创建Secret:
kubectl create secret generic super-secret \
--from-literal="password=123456" --dry-run -o yaml
其他资源比如job、cronjob、namespace、quota、configmap、service、serviceaccount等都可以通过create
命令很方便地快速创建,毕竟yaml文件真不是让人写的,应该让机器去自动生成。
另外新版本的metadata多了很多字段,比如managedFields
、ownerReferences
等,使用kubectl get xxx -o yaml
或者kubectl edit xxx xxx
时yaml文件会特别长,注意使用文本搜索快速查找关键字。
因为考试环境通常会使用最新的Kubernetes版本,因此自己在练习时也建议安装最新版本的Kubernetes版本。很多人偷懒使用某些培训机构做好的虚拟机镜像部署Kubernetes集群,可能就会遇到kubectl
版本太老的兼容问题。
考试时很有帮助的三个文档
Kubernetes官方文档
考试时是可以浏览kubernetes.io官方文档的,注意仅限Kubernetes官网,其他外部资源包括引用的外链都是不允许访问的,建议考试前把一些常用的链接做成书签,书签多了查找麻烦?
推荐chrome插件Holmes[5],支持根据书签关键字模糊查询。

help文档
命令参数全部记住肯定是不可能的也完全没必要,kubectl的help文档真是做得非常好,不仅有命令用法,还提供多个demo样例,很多直接复制就可以用。
如果忘了run
命令用法,只需要在命令行上输入kubectl run -h
就可以了。

注意新版本是--dryrun=client
,老版本没有client
参数,新版本不写会警告,建议加上。
另外需要学会kubectl help文档的语法,这个和其他Linux命令是相同的,比如<xxx>
表示必选参数,[xxx]
表示可选参数,-x
表示短参数,主要为了简写,一般会对应一个--xxx
长参数,如果后面还有值比如---xxx=a
则后面的值为默认值,如果是bool类型,后面的默认值为false
,则可以直接使用该参数--xxx
代替---xxx=true
,效果是一样的。
对于多值参数,如果后面的值为[]
,比如--env=[]
,则表示该参数可以指定多次,如果后面不是[]
,则通常不可以指定多次,如何表示多值需要看参数描述,通常是逗号,
隔开,比如-l
或者--labels
就是通过,
隔开指定多个值。
还有很多人不知道--
的意思,这个参数表示命令行参数终止解析标志,后面的参数即使包含-x
或者--xxx
也不会再解析成这个命令的参数。
比如使用grep命令过滤iptables-save
中包含的-A KUBE-POSTROUTING
,如果写成:
iptables-save | grep '-A KUBE-POSTROUTING'
则后面的-A
会解析成grep的参数-A
,即--after-context=NUM
。
为了阻止grep过度解析,可以加上--
标识:
iptables-save | grep -- '-A KUBE-POSTROUTING'
建议kubectl run命令的--command
参数总是放到最后,并且一定要使用--
隔开,避免kubectl过度解析。
命令参考:
kubectl run nginx --image nginx \
--env='USERNAME=alice' \
--env 'PASSWORD=123456' \
-l 'app=web,env=test' \
-o yaml --dry-run=client \
--command -- sleep 3600
当然还有很多人会直接在--
后面加命令,比如
kubectl run busybox --image=busybox -- sleep 3600
但需要注意以上命令并不是指定运行的Command
而是Args
,Command
与Args
的区别需要特别注意,简单地说Args
只是替换原来Docker image的默认命令参数,而Command
替换的是整个命令,如果不确定Docker image的默认命令是什么,建议使用Command
而不是Args
。
| ImageEntrypoint | ImageCmd | ContainerCommand | ContainerArgs | CommandRun |
|---|---|---|---|---|
| [/ep-1] | [foo bar] | <not set> | <not set> | [ep-1 foo bar] |
| [/ep-1] | [foo bar] | [/ep-2] | <not set> | [ep-2] |
| [/ep-1] | [foo bar] | <not set> | [zoo boo] | [ep-1 zoo boo] |
| [/ep-1] | [foo bar] | [/ep-2] | [zoo boo] | [ep-2 zoo boo] |
更多关于Pod的Command
以及Args
区别可以参考官方文档Define a Command and Arguments for a Container[6]。
explain命令
如果忘了Kubernetes资源的声明方式或者参数,除了可以官网搜索,还可以使用explain查看。
比如忘了hostPath
参数:
kubectl explain Pod.spec.volumes.hostPath
可以使用--recursive
递归式列出所有参数,比如忘记了Pod的metadata怎么定义:
kubectl explain Pod.metadata --recursive

关于考点
考试大纲可以从官方直接下载cncf-certification-candidate-resources[7]或者Open Source Curriculum for CNCF Certification Courses[8]。
由于考试前签了保密协议,这里不会直接把考到的题目放到这里,仅对考点进行简单的描述并总结下经验。
CKA
总体来说考的内容还是比较基础的,题目不是很难,工作量适中。
前面部分基本就是对Kubernetes常见资源的常规CURD操作,包括Pod、Deployment、Service、PV等,注意看清题目要求使用的Kubernetes Context环境、Namespace以及Image,Context环境题目在最开始就会告诉你,但Namespace可能藏在题目后面,很容易被忽视导致创建的资源放错了Namespace。
其中考的比较集中的是Deployment和Pod,get
查询时可能考到过滤字段、排序等,创建Pod可能会涉及使用nodeSlector调度、initContainer、静态Pod等,Deployment则包含扩缩容、升级等常规操作,其他的比如如何使用ConfigMap、Secret、Volume等常规操作。
建议使用kubectl run
创建Pod以及使用kubectl create
命令创建Deployment、Secret、Namespace等资源,并且使用--dry-run=client -o yaml
返回yaml文件保存到Home目录,并对部分字段进行调整后再apply
。
前面的都比较简单,而且就算忘了,还可以查阅文档,基本问题不大。
后面的部分则主要是排错以及集群部署,个人感觉这部分比较难,尤其是使用惯了kubeadm类似的工具一键部署,可能对Kubernetes的组件运行的参数以及配置不熟悉,比如--pod-manifest-path
或者staticPodPath
参数。
集群排错会给你一个集群,根据考纲会涉及Worker Node故障以及控制平台故障。
10% - Troubleshooting
• Troubleshoot application failure.
• Troubleshoot control plane failure.
• Troubleshoot worker node failure.
• Troubleshoot networking.
如果是work node故障通常就是说Node的状态为NotReady
,需要你手动去修好,个人感觉不难发现问题,算是送分题。
如果是控制平面故障则连API都访问不了,使用kubectl
命令直接报错,发现apiserver、controller-manager、scheduler没有起来,这一题我确实花了不少时间。
我以为需要手动部署剩下的这些组件,不过幸好我先检查了下Kubernetes的常见配置目录,发现某个配置路径有问题导致这些服务启动失败,修改后重启集群就恢复了,实际工作量并不大。
集群部署的话,根据官方的考纲基本掌握kubeadm就够了,我个人认为其他非官方的工具应该不会考。
12% - Installation, Configuration & Validation
• Design a Kubernetes cluster.
• Install Kubernetes masters and nodes.
• Configure secure cluster communications.
• Configure a Highly-Available Kubernetes cluster.
• Provision underlying infrastructure to deploy a Kubernetes cluster.
• Choose a network solution.
• Choose your Kubernetes infrastructure configuration.
• Install and use kubeadm to install, configure, and manage Kubernetes clusters
集群部署主要问题就是在于工作量会稍微比较大,关于部署方法官方文档足够,反正开卷考试,考试参考一步步操作即可,我做的时候基本就是文档命令拷贝执行,没有太多思考。
另外kubeadm init/join
建议加上--ignore-preflight-errors=all
参数,否则会可能会由于cloud provider问题报错。
当然除了对Kubernetes熟悉,还需要掌握Kubernetes最重要的存储系统etcd,会考到一些基本操作,这个个人认为现场直接使用etcdctl -h
查就够了。
CKAD
CKAD总体上看内容比CKA要少,其中Pod Design是大头,其他内容个人感觉和CKA内容很大部分是重叠的,不过二者考察的方向不一样。

Github上关于CKAD练习题可以参考CKAD Exercises[9]以及ckad-prep-notes[10]。
CKAD的题目个人感觉不是很难,比CKA要直接,就是一个一个Task照做就行了,基本模式就是先叫你创建一个ConfigMap,然后创建一个Secret,然后创建PV,最后创建Pod,最后可能还要你来个Service。
但最大的问题就是每一道题的工作量都很大导致时间很明显不够,和CKA题目不一样,很少有单纯创建一个Pod或者一个命令就可以搞定的题目,CKAD的题目可能涉及同时创建多种Resource,比如Secret、ConfigMap、PV、PVC、Volume、Service等,Pod还要配置各种env、args、command等。
虽然这些使用方法都可以在文档中搜索,但由于使用太频繁建议还是记住,这样可以节省很多时间,我就是在这一块吃亏了导致时间不够。说来惭愧,ConfigMap、Secret、PV、PVC我全部是考试时临时照抄文档的,没记住。
还有一个问题是CKA基本都是在default namespace完成,而CKAD基本都需要指定不同的namespace,这其实也会多花费一点时间,毕竟每个命令需要多输入一次-n xxx
。
前面的都是各种资源的CURD操作,比较基础,考过了CKA的基本问题不大,但不要花太多时间,多留点时间在12道以后的题目,建议至少预留一半的时间在后面7道题。
Understand Multi-Container Pod design patterns
(e .g. ambassador, adapter, sidecar)
后面关于Pod设计模式题目本身并不难,就是Task太多,题目还很长,我的MacOS甚至需要滚好几屏,任务包括创建一个Pod包含多个容器,每个容器挂载volume,创建并引用Configmap,配置env变量,配置command以及args等,如果不熟悉spec yaml,搜索文档会浪费很多时间,毕竟只能打开一个浏览器Tab,网络慢的话每次打开还得等。
建议熟悉Pod设计模式的Sidecar、Adaper、Ambassador三种主流模式,每一个模式在考试总都会被涉及到,并且任务的工作量很大,关于Pod设计模式建议阅读这个论文Design patterns for container-based distributed systems[11]。
参考资料
Claim your Handshake Airdrop: https://www.namebase.io/airdrop
[2]Handshake Namebase“送给开源程序员每人几千元”是怎么回事?: https://www.zhihu.com/question/373148501/answer/1114183939
[3]kubectl run is deprecated looking for alternative: https://stackoverflow.com/questions/52890718/kubectl-run-is-deprecated-looking-for-alternative
[4]Remove kubectl run generators: https://github.com/kubernetes/kubernetes/pull/87077
[5]Holmes: https://chrome.google.com/webstore/detail/holmes/gokficnebmomagijbakglkcmhdbchbhn
[6]Define a Command and Arguments for a Container: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell
[7]cncf-certification-candidate-resources: https://training.linuxfoundation.org/cncf-certification-candidate-resources/
[8]Open Source Curriculum for CNCF Certification Courses: https://github.com/cncf/curriculum
[9]CKAD Exercises: https://github.com/dgkanatsios/CKAD-exercises
[10]ckad-prep-notes: https://github.com/twajr/ckad-prep-notes
[11]Design patterns for container-based distributed systems: https://www.usenix.org/system/files/conference/hotcloud16/hotcloud16_burns.pdf




