CKA考后总结
Table of Contents
前
在经过两周的集中备考后,我以95分通过了CKA认证考试。这篇文章不是应试技巧的堆砌,而是我在备考过程中对Kubernetes设计理念的一些深层思考,以及实战中踩过的坑。
在深入学习Kubernetes的过程中,我逐渐理解了它的核心设计哲学:
Kubernetes是一个按照Linux “一切皆文件"理念设计的宏观系统,实现了"一切皆资源"的抽象。
这个理解对我后续的学习和实践产生了深远影响。所有的操作本质上都是对API资源的CRUD,理解了这一点,很多概念就能融会贯通。
基础通识
考试内容概览
CKA考试是纯实操的performance-based exam,时长2小时,需要在真实的Kubernetes集群环境中完成15-20道题目。考试涉及的核心知识点如下:
- Service与Ingress:创建Service暴露应用,配置Ingress规则实现路由
- 存储管理:PV/PVC的创建与绑定,StorageClass的使用
- RBAC权限控制:ServiceAccount、ClusterRole、RoleBinding的配置
- 集群故障排查:Node健康检查、Pod状态诊断、日志排查
- 集群升级:使用kubeadm进行集群版本升级
- 数据备份恢复:etcd的backup与restore操作
- 工作负载管理:Deployment、Pod的创建与配置
- 多容器Pod:Sidecar模式、Init Container的实现
- 日志查询:使用kubectl logs过滤容器日志
这里需要强调的是,CKA考试允许查阅Kubernetes官方文档,所以关键不是死记硬背,而是要熟悉文档结构和快速定位能力。
实战技巧与命令速查
在考试中,时间就是分数。这里分享一些我实战中总结的提效技巧。
环境切换
每道题目都会指定特定的集群context,这一步必须做对,否则所有操作都是无效的:
# 切换集群上下文(每道题的第一步)
kubectl config use-context k8s-cluster1
# 验证当前上下文
kubectl config current-context
快速查询与操作
# 获取带标签的资源
kubectl get ns --show-labels
kubectl get pod -o wide --show-labels
# 多资源类型同时查看
kubectl get pod,svc,deploy -n production
# 快速创建Service暴露Pod
kubectl expose pod curl --port=80 --target-port=8000 --name=curl-service
# 导出YAML模板后编辑(避免从零编写)
kubectl create deployment nginx --image=nginx --dry-run=client -o yaml > deploy.yaml
资源类型缩写
熟练使用资源缩写可以大幅提升命令输入速度,这些是考试中最常用的:
| 缩写 | 完整名称 | 缩写 | 完整名称 |
|---|---|---|---|
| po | pods | svc | services |
| deploy | deployments | rs | replicasets |
| sts | statefulsets | ds | daemonsets |
| cm | configmaps | secret | secrets |
| ns | namespaces | no | nodes |
| pv | persistentvolumes | pvc | persistentvolumeclaims |
| sa | serviceaccounts | ing | ingresses |
| hpa | horizontalpodautoscalers | ep | endpoints |
使用示例:
kubectl get po,svc -n kube-system
kubectl describe deploy nginx
kubectl edit cm nginx-config
关键工具配置
使用 kubectl top 查看资源使用率时,需要预先部署Metrics Server:
# 部署Metrics Server
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# 验证部署
kubectl top nodes
kubectl top pods -A
这一步在考试环境中通常已经配置好,但在自己的练习环境中需要手动安装。
API资源的本质
前面提到,Kubernetes的核心理念是"一切皆资源”。所有的操作本质上都是通过API Server对资源进行增删改查。
理解这一点很重要:当你执行 kubectl create deployment 时,实际上是在向API Server提交一个Deployment资源对象的JSON/YAML定义,API Server将其持久化到etcd,然后由各个Controller监听这个资源变化并执行相应的操作。
在编写复杂的资源配置时,Kubernetes API Reference是最权威的文档:
- API Reference: https://kubernetes.io/docs/reference/kubernetes-api/
- 特定版本API: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/
这里可以查到每个资源的完整字段定义、类型、默认值和描述。比如在配置Job的时候,你需要知道 spec.backoffLimit 的默认值是6,这些信息在API文档中都能找到。
Pod的网络与存储共享机制
每个Pod内部都有一个Infra容器(也叫pause容器),这个容器非常小,只有几百KB,但它的作用至关重要:
- 网络共享:Infra容器负责创建Network Namespace,Pod内的所有业务容器共享这个网络命名空间,因此它们可以通过localhost互相访问
- 存储共享:在Pod级别声明的Volume会挂载到Infra容器,业务容器通过volumeMounts引用这些Volume即可实现文件共享
这种设计使得多容器协作变得自然而优雅,也是Sidecar模式的基础。
RBAC权限控制
RBAC(Role-Based Access Control)是Kubernetes中最重要的安全机制之一,也是CKA考试的必考点。在我备考过程中,RBAC是最容易混淆的部分,需要理清楚几个核心概念。
RBAC的四大对象
Kubernetes的RBAC由四种资源对象组成:
- Role:定义命名空间级别的权限规则
- ClusterRole:定义集群级别的权限规则
- RoleBinding:将Role绑定到用户/组/ServiceAccount(命名空间级别)
- ClusterRoleBinding:将ClusterRole绑定到用户/组/ServiceAccount(集群级别)
关键理解:
- Role和RoleBinding都是命名空间级别的资源
- ClusterRole和ClusterRoleBinding是集群级别的资源
- 但是,RoleBinding也可以引用ClusterRole,这时ClusterRole的权限会被限制在RoleBinding所在的命名空间
权限绑定的四种组合
| 角色类型 | 绑定类型 | 作用范围 | 使用场景 |
|---|---|---|---|
| Role | RoleBinding | 单个命名空间 | 授予命名空间内的资源权限 |
| ClusterRole | ClusterRoleBinding | 整个集群 | 授予集群级别的资源权限 |
| ClusterRole | RoleBinding | RoleBinding所在的命名空间 | 复用集群角色但限制在某命名空间 |
| ClusterRole | 多个RoleBinding | 多个命名空间(每个RoleBinding一个) | 在多个命名空间授予相同权限 |
ServiceAccount vs User Account
在实际使用中,需要区分两种账号类型:
- User Account:真实用户的账号,由外部认证系统管理(如证书、OIDC等)
- ServiceAccount:Pod内应用程序的身份标识,由Kubernetes管理
考试中几乎都是在配置ServiceAccount的权限。每个Pod默认会使用所在命名空间的default ServiceAccount,但在实际生产环境中,应该为不同的应用创建专用的ServiceAccount并授予最小权限。
实战示例
创建一个只能读取Pod信息的ServiceAccount:
# 创建ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: pod-reader
namespace: default
---
# 创建Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader-role
namespace: default
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
# 创建RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
- kind: ServiceAccount
name: pod-reader
namespace: default
roleRef:
kind: Role
name: pod-reader-role
apiGroup: rbac.authorization.k8s.io
在Pod中使用这个ServiceAccount:
apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
serviceAccountName: pod-reader
containers:
- name: app
image: nginx
这里需要注意的是,roleRef字段在创建后不能修改,如果需要更换角色,必须删除RoleBinding重新创建。
Service网络暴露
Service是Kubernetes中实现服务发现和负载均衡的核心抽象。在我的理解中,Service本质上是一个稳定的网络端点,它通过label selector动态关联一组Pod,并为这组Pod提供统一的访问入口。
Service的四种类型
- ClusterIP(默认):在集群内部分配一个虚拟IP,只能在集群内部访问
- NodePort:在每个Node上开放一个端口(30000-32767),可以从集群外部访问
- LoadBalancer:在云环境中创建外部负载均衡器
- ExternalName:通过CNAME记录映射到外部服务
快速创建Service
在考试中,使用命令行快速创建Service比手写YAML效率更高:
# 为Deployment创建ClusterIP Service
kubectl expose deployment nginx --port=80 --target-port=8080
# 创建NodePort Service
kubectl expose deployment nginx --type=NodePort --port=80
# 为已存在的Pod创建Service
kubectl expose pod nginx --port=80 --name=nginx-service
Service与Endpoints的关系
Service通过label selector找到匹配的Pod后,会自动创建对应的Endpoints对象。可以通过以下命令查看:
kubectl get endpoints nginx-service
如果Service没有正常工作,检查Endpoints是否为空是一个重要的排查步骤。
Ingress路由规则
Ingress是Kubernetes提供的HTTP/HTTPS路由规则,它工作在七层(应用层),可以根据域名和路径将流量分发到不同的Service。
Ingress的工作原理
Ingress资源本身只是一组路由规则的定义,真正执行路由的是Ingress Controller(如Nginx Ingress Controller、Traefik等)。这是很多初学者容易混淆的地方。
部署流程:
- 首先在集群中安装Ingress Controller
- 创建Ingress资源定义路由规则
- Ingress Controller监听Ingress资源变化并更新配置
Ingress配置示例
基于域名和路径的路由:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- path: /web
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 3000
配置TLS证书:
spec:
tls:
- hosts:
- app.example.com
secretName: app-tls-secret
rules:
- host: app.example.com
# ...
这里需要注意pathType字段,Kubernetes 1.18+引入了三种类型:
- Prefix:前缀匹配
- Exact:精确匹配
- ImplementationSpecific:由Ingress Controller决定
Deployment工作负载管理
Deployment是Kubernetes中最常用的工作负载资源,它提供了声明式的Pod更新和回滚能力。在我的实践中,几乎所有的无状态应用都应该使用Deployment来管理。
核心功能
- 副本管理:维护指定数量的Pod副本
- 滚动更新:零停机更新应用版本
- 版本回滚:快速回退到之前的版本
- 扩缩容:动态调整Pod数量
常用操作命令
# 创建Deployment
kubectl create deployment nginx --image=nginx:1.21 --replicas=3
# 扩缩容
kubectl scale deployment nginx --replicas=5
# 查看滚动更新状态
kubectl rollout status deployment nginx
# 更新镜像(触发滚动更新)
kubectl set image deployment nginx nginx=nginx:1.22
# 查看历史版本
kubectl rollout history deployment nginx
# 回滚到上一个版本
kubectl rollout undo deployment nginx
# 回滚到指定版本
kubectl rollout undo deployment nginx --to-revision=2
# 暂停/恢复滚动更新
kubectl rollout pause deployment nginx
kubectl rollout resume deployment nginx
更新策略配置
Deployment支持两种更新策略,考试中经常需要配置这些参数:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 滚动更新时最多可以超出replicas的Pod数量
maxUnavailable: 0 # 滚动更新时最多允许多少个Pod不可用
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
这里的maxSurge和maxUnavailable是控制滚动更新速度的关键参数,在生产环境中需要根据实际情况调优。
Pod调度与配置
Pod是Kubernetes中最小的调度单元。在备考过程中,我发现Pod调度是一个既实用又容易出题的知识点,需要掌握三种主要的调度方式。
Pod调度的三种机制
1. NodeSelector(标签选择)
最简单的调度方式,通过Node标签来指定Pod运行的节点:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
nodeSelector:
disktype: ssd
env: production
containers:
- name: nginx
image: nginx
Node标签管理命令:
# 添加标签
kubectl label nodes k8s-node01 disktype=ssd
# 查看所有节点标签
kubectl get nodes --show-labels
# 查看指定节点标签
kubectl get node k8s-node01 --show-labels
# 删除标签(注意label key后面的减号)
kubectl label nodes k8s-node01 disktype-
# 修改标签(需要--overwrite参数)
kubectl label nodes k8s-node01 disktype=hdd --overwrite
2. Taint与Toleration(污点与容忍)
Taint是给Node打上"污点",只有能容忍这个污点的Pod才能被调度到该Node上。这是一种"排斥"机制:
# 给Node添加污点
kubectl taint nodes k8s-node01 key=value:NoSchedule
# 查看Node的污点
kubectl describe node k8s-node01 | grep Taint
# 删除污点
kubectl taint nodes k8s-node01 key:NoSchedule-
污点的三种效果:
- NoSchedule:不会调度新Pod到该Node
- PreferNoSchedule:尽量不调度,但不是强制
- NoExecute:不仅不调度新Pod,还会驱逐已有的Pod
在Pod中容忍污点:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
containers:
- name: nginx
image: nginx
3. Affinity(亲和性)
Affinity提供了更灵活的调度规则,支持硬性要求(required)和软性偏好(preferred):
NodeAffinity示例:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
- nvme
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: zone
operator: In
values:
- zone-a
containers:
- name: nginx
image: nginx
PodAffinity示例(将相关Pod调度到同一节点):
apiVersion: v1
kind: Pod
metadata:
name: web
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- cache
topologyKey: kubernetes.io/hostname
containers:
- name: web
image: nginx
这个配置会将web Pod调度到已经运行了app=cache标签的Pod所在的节点上。
Pod配置要点
在考试中经常需要快速编写Pod YAML,这些是关键字段:
apiVersion: v1
kind: Pod
metadata:
name: my-app
namespace: default
labels:
app: my-app
tier: frontend
spec:
# 调度相关
nodeSelector:
disktype: ssd
# 资源限制
containers:
- name: app
image: nginx:1.21
ports:
- containerPort: 80
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
# 环境变量
env:
- name: ENV_VAR
value: "production"
# 存储挂载
volumeMounts:
- name: data
mountPath: /data
# 存储卷定义
volumes:
- name: data
emptyDir: {}
# 重启策略
restartPolicy: Always
持久化存储PV/PVC
存储管理是Kubernetes中相对复杂的部分,涉及PV、PVC、StorageClass三个层次的抽象。在我的理解中,这是一个典型的"解耦"设计。
存储抽象层次
- PV(PersistentVolume):集群级别的存储资源,由管理员创建或通过StorageClass动态创建
- PVC(PersistentVolumeClaim):用户对存储的请求,描述需要的容量和访问模式
- StorageClass:存储类,用于动态创建PV的模板
静态PV创建流程
创建PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-data
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: manual
hostPath:
path: /data/pv-data
访问模式说明:
- ReadWriteOnce (RWO):单节点读写
- ReadOnlyMany (ROX):多节点只读
- ReadWriteMany (RWX):多节点读写
回收策略:
- Retain:保留数据,需要手动清理
- Delete:删除PVC时自动删除PV和底层存储
- Recycle:已废弃,不推荐使用
创建PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-data
namespace: default
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: manual
在Pod中使用PVC
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
volumes:
- name: data
persistentVolumeClaim:
claimName: pvc-data
动态存储配置
在生产环境中,更常用的是通过StorageClass动态创建PV:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-storage
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp3
iopsPerGB: "10"
用户创建PVC时指定storageClassName,系统会自动创建对应的PV。
容量扩展
Kubernetes 1.11+支持在线扩容PVC(前提是StorageClass的allowVolumeExpansion设置为true):
# 编辑PVC,修改storage容量
kubectl edit pvc pvc-data
# 查看扩容状态
kubectl describe pvc pvc-data
这里需要注意的是,不是所有存储后端都支持在线扩容,hostPath类型就不支持。
多容器Pod与Sidecar模式
Sidecar模式是Kubernetes中一种常见的设计模式,通过在Pod中运行辅助容器来增强主容器的功能。考试中经常会考察多容器Pod的配置。
Sidecar典型应用场景
- 日志收集:Sidecar容器收集主容器的日志并发送到日志系统
- 代理网关:如Service Mesh中的Envoy Sidecar
- 配置热更新:监听配置变化并通知主容器
- 数据同步:定期同步外部数据到共享存储
多容器Pod示例
一个带日志收集Sidecar的Pod配置:
apiVersion: v1
kind: Pod
metadata:
name: app-with-sidecar
spec:
containers:
# 主应用容器
- name: app
image: nginx
volumeMounts:
- name: logs
mountPath: /var/log/nginx
# Sidecar日志收集容器
- name: log-collector
image: busybox
command: ['sh', '-c', 'tail -f /var/log/nginx/access.log']
volumeMounts:
- name: logs
mountPath: /var/log/nginx
# 共享存储卷
volumes:
- name: logs
emptyDir: {}
从运行中的Pod提取配置
在考试中,如果需要基于已有Pod创建Sidecar配置,可以先导出YAML再编辑:
# 导出Pod配置
kubectl get pod app -o yaml > app.yaml
# 编辑文件,添加Sidecar容器
vim app.yaml
# 删除旧Pod并创建新Pod
kubectl delete pod app
kubectl apply -f app.yaml
这里需要注意删除导出YAML中的status、resourceVersion等运行时字段。
后
经过CKA考试的备考和实战,我对Kubernetes的理解上了一个台阶。考试本身不难,但它确实是一个很好的学习驱动力,强迫你系统化地掌握Kubernetes的核心概念。
备考建议
- 动手实践优先:理论知识要通过实操来巩固,搭建一个本地集群(kubeadm、k3s或minikube都可以)反复练习
- 熟悉文档结构:考试允许查文档,但你需要知道去哪里查,提前整理好常用页面的书签
- 时间管理:2小时15-20道题,平均每题6-8分钟,遇到难题先跳过,确保简单题不失分
- 验证结果:每做完一题都要验证,检查Pod状态、Service Endpoints、日志输出等
核心收获
通过这次学习,我最大的收获不是通过了考试,而是真正理解了Kubernetes的设计哲学:
通过声明式API和控制器模式,实现了复杂分布式系统的自动化管理。
这种理念可以应用到很多其他系统的设计中。在后续的Homelab实践中,我会继续深入Kubernetes的网络、存储、安全等高级主题。
就这样!希望这篇文章能够帮助到正在备考CKA或学习Kubernetes的朋友。