CKS认证
CKS 指的是 Certified Kubernetes Security Specialist,是 Kubernetes 安全认证考试,由云原生计算基金会 (CNCF) 管理和推出。CKS 考试旨在评估个人在 Kubernetes 安全方面的知识和技能,包括设计和构建安全的容器化应用程序、保护 Kubernetes 平台和主机安全、防范网络攻击和数据泄露等方面。
通过 CKS 认证可以证明您具备 Kubernetes 安全方面的专业知识和技能,并为企业提供 Kubernetes 安全方面的专家和顾问。CKS 认证需要先取得 CKA (Certified Kubernetes Administrator) 认证,在此基础上进一步考核 Kubernetes 安全方面的能力。
为了准备 CKS 考试,您可以参加官方组织的培训课程,也可以通过自学来获得相关知识。考试内容涵盖 Kubernetes 安全的各个方面,例如身份验证和授权、网络安全、加密、漏洞管理等等。
CKS题库
CKS考试概要:
考试模式:线上考试
考试时间:2小时
题目数量:16题
分数:总100分,66分及格
题目变化:每次考题会对里面涉及的命名空间、资源名称个别微调,还有题目顺序。
1、kube-bench 修复不安全项
https://kubernetes.io/zh/docs/reference/config-api/kubelet-config.v1beta1/
1
2
3
4
5
6
7
8
9
10
11
12
13
|
Context 针对 kubeadm 创建的 cluster 运行 CIS 基准测试工具时, 发现了多个必须立即解决的问题。 Task
通过配置修复所有问题并重新启动受影响的组件以确保新的设置生效。 修复针对 API 服务器发现的所有以下违规行为: 1.2.7 Ensure
that the --authorization-mode argument is not set to AlwaysAllow 1.2.8
Ensure that the --authorization-mode argument includes Node 1.2.9
Ensure that the --authorization-mode argument includes RBAC 1.2.18
Ensure that the --insecure-bind-address argument is not set 1.2.19
Ensure that the --insecure-port argument is set to 0 FAIL FAIL FAIL
FAIL FAIL 修复针对 kubelet 发现的所有以下违规行为: Fix all of the following
violations that were found against the kubelet: 4.2.1 Ensure that the
anonymous-auth argument is set to false 4.2.2 Ensure that the
–authorization-mode argument is not set to AlwaysAllow FAIL FAIL 注意:尽可能使用 Webhook 身份验证/授权。 修复针对 etcd 发现的所有以下违规行为: Fix all of the
following violations that were found against etcd: 2.2 Ensure that the
–client-cert-auth argument is set to true FAIL
|
解读:使用kube-bench工具检查集群组件配置文件存在的问题与修复,并重启对应组件确保新配置生效。
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
#切换环境
kubectl config use-context KSCS00201
#
ssh master01
sudo -i
修改api-server
kube-bench master
mkdir bak1
cp /etc/kubernetes/manifests/kube-apiserver.yaml bak1/
vim /etc/kubernetes/manifests/kube-apiserver.yaml
#修改、添加、删除相关内容
#修改authorization-mode,注意Node和RBAC之间的符号是英文状态的逗号,而不是点。
- --authorization-mode=Node,RBAC
#删除insecure-bind-address,考试中,有可能本来就没写这行。
- --insecure-bind-address=0.0.0.0
修改kubelet
#可以使用这条命令查,要记住
kube-bench node
修改 /var/lib/kubelet/config.yaml
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
anonymous: #修改anonymous下的,将true改为false
enabled: false #改为false
webhook:
cacheTTL: 0s
enabled: true
x509:
clientCAFile: /etc/kubernetes/pki/ca.crt
authorization: #修改authorization下的
mode: Webhook #改为Webhook
webhook:
……
修改etcd
#可以使用这条命令查,要记住
kube-bench
修改之前,备份一下配置文件。
mkdir bak1
cp /etc/kubernetes/manifests/etcd.yaml bak1/
vim /etc/kubernetes/manifests/etcd.yaml
修改
- --client-cert-auth=true #修改为true
|
1
2
3
4
5
6
7
|
修改完成后,等待2分钟,再检查一下所有pod,确保模拟环境里的所有pod都正常。
kubectl get pod -A
# 退出root,退回到candidate@master01
exit
# 退出master01,退回到candidate@node01
exit
|
2、Pod指定ServiceAccount
1
2
3
4
5
|
Task
1. 在现有 namespace qa 中创建一个名为 backend-sa 的新 ServiceAccount, 确保此
ServiceAccount 不自动挂载 API 凭据。
2. 使用 /cks/sa/pod1.yaml 中的清单文件来创建一个 Pod。
3. 最后,清理 namespace qa 中任何未使用的 ServiceAccount。
|
https://kubernetes.io/zh/docs/tasks/configure-pod-container/configure-service-account/#%E4%BD%BF%E7%94%A8%E9%BB%98%E8%AE%A4%E7%9A%84%E6%9C%8D%E5%8A%A1%E8%B4%A6%E6%88%B7%E8%AE%BF%E9%97%AE-api-%E6%9C%8D%E5%8A%A1%E5%99%A8

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
# kubectl config use-context KSCH0030
1 创建ServiceAccount
vi qa-ns.yaml
根据官网修改如下内容
apiVersion: v1
kind: ServiceAccount
metadata:
name: backend-sa #修改name
namespace: qa #注意添加namespace
automountServiceAccountToken: false #修改为false,表示不自动挂载 secret
kubectl apply -f qa-ns.yaml
kubectl get sa -n qa
2 创建Pod使用该ServiceAccount
vi /cks/sa/pod1.yaml
修改如下内容
……
metadata:
name: backend
namespace: qa #注意命名空间是否对
spec:
serviceAccountName: backend-sa # 没有则添加一行,有则修改这一行为刚才创建ServiceAccount(考试时,默认已有这一行,需要修改。)
containers:
……
kubectl apply -f /cks/sa/pod1.yaml
kubectl get pod -n qa
3. 删除没有使用的ServiceAccount
查看所有sa
kubectl get sa -n qa
查看已经在用的sa
kubectl get pod -n qa -o yaml | grep -i serviceAccountName
删除不用的sa
kubectl delete sa test01 -n qa
|
3、默认网络策略
1
2
3
4
5
6
7
8
|
Context
一个默认拒绝(default-deny)的NetworkPolicy可避免在未定义任何其他NetworkPolicy的namespace中意外公开Pod。
Task
为所有类型为Ingress+Egress 的流量在namespace testing中创建一个名为denypolicy的新默认拒绝NetworkPolicy。
此新的NetworkPolicy必须拒绝namespace testing中的所有的Ingress + Egress 流量。
将新创建的默认拒绝NetworkPolicy应用与在namespace testing中运行的所有Pod。
你可以在 /cks/net/p1.yaml找到一个模板清单文件。
|
https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/#%E9%BB%98%E8%AE%A4%E6%8B%92%E7%BB%9D%E6%89%80%E6%9C%89%E5%85%A5%E5%8F%A3%E5%92%8C%E6%89%80%E6%9C%89%E5%87%BA%E7%AB%99%E6%B5%81%E9%87%8F
解读:在testing命名空间创建一个名为denypolicy的网络策略。拒绝所有Ingress和
Egress流量。将网络策略应用到testing命名空间中的所有pod。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
# kubectl config use-context KSCS00101
创建名为 denypolicy的 NetworkPolicy,拒绝testing命名空间内所有Ingress + Egress 流量
(这里可能是ingress 或egress或ingress+egress,根据题目要求写。)
vi /cks/net/p1.yaml
……
metadata:
name: denypolicy #修改name
namespace: testing #注意添加namespace
spec:
podSelector: {}
policyTypes:
- Ingress #注意看题,是Ingress + Egress(入口+出口),还是只是Ingress 或只是Egress。
- Egress #在1.23的考试中,只要求拒绝所有Egress流量,那就只写这这个- Egress即可,这种情况就不要写- Ingress 了。
创建
kubectl apply -f /cks/net/p1.yaml
检查
kubectl describe networkpolicy denypolicy -n testing
|
4、RBAC - RoleBinding
1
2
3
4
5
6
7
8
9
|
Context
绑定到 Pod 的 ServiceAccount 的 Role 授予过度宽松的权限。完成以下项目以减少权限集。
Task
一个名为web-pod的现有Pod已在 namespace db中运行。
编辑绑定到 Pod 的 ServiceAccount service-account-web的现有Role,仅允许只对 services类型的资源执行 get操作。
在namespace db中创建一个名为role-2 ,并仅允许只对 namespaces类型的资源执行delete操作的新 Role。
创建一个名为role-2-binding的新 RoleBinding,将新创建的 Role 绑定到 Pod 的ServiceAccount。
注意:请勿删除现有的 RoleBinding。
|
两个都要看
https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/#role-and-clusterole
https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/#%E4%B8%80%E4%BA%9B%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%B7%A5%E5%85%B7

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
|
# kubectl config use-context KSCH00201
查看ServiceAccount service-account-web对应的rolebindings role-1-binding
查看rolebindings role-1-binding对应的role为role-1
kubectl describe rolebindings -n db
编辑role-1权限:
kubectl edit role role-1 -n db
修改如下内容
……
resourceVersion: "30867"
uid: 22e3c185-f7f5-4542-b86a-6ce153aa1c5a
rules: #模拟环境里要删除掉null,然后添加以下内容。考试时,要根据实际情况修改。
- apiGroups: [""]
resources: ["services"] #只允许对 services资源类型执行 get 操作。还有可能会考只允许对endpoints资源list 的操作
verbs: ["get"]
检查
kubectl describe role role-1 -n db
在db命名空间,创建名为role-2的role,并且通过rolebinding绑定service-account-web,只允许对namespaces做delete操作。
记住 --verb是权限,可能考delete或者update等 --resource是对象,可能考namespaces或者persistentvolumeclaims等。
kubectl create role role-2 --verb=delete --resource=namespaces -n db
kubectl create rolebinding role-2-binding --role=role-2 --serviceaccount=db:service-account-web -n db
检查
kubectl describe rolebindings -n db
|
方法二:
1
2
3
4
|
确认web-pod的pod是否指定service-account-web,再看下对应role是否有对services资源的get操作。
kubectl create role web-role-2 --verb=delete --resource=namespaces -n monitoring
kubectl create rolebinding web-role-2-binding --role=web-role-2 --serviceaccount=monitoring:service-account-web -n monitoring
|
5、日志审计 log audit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
Task
在cluster中启用审计日志。为此,请启用日志后端,并确保:
⚫ 日志存储在 /var/log/kubernetes/audit-logs.txt
⚫ 日志文件能保留 10 天
⚫ 最多保留 2 个旧审计日志文件
/etc/kubernetes/logpolicy/sample-policy.yaml 提供了基本策略。它仅指定不记录的内容。
注意:基本策略位于cluster的master节点上。
编辑和扩展基本策略以记录:
⚫ RequestResponse 级别的 persistentvolumes更改
⚫ namespace front-apps中 configmaps更改的请求体
⚫ Metadata 级别的所有 namespace 中的 ConfigMap 和 Secret 的更改
此外,添加一个全方位的规则以在 Metadata 级别记录所有其他请求。
注意:不要忘记应用修改后的策略。
|
https://kubernetes.io/zh/docs/tasks/debug/debug-cluster/audit/
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
# kubectl config use-context KSCH00601
本题分数比较多,占12%。
日志审计这一题需要自己调整的内容还是挺多的,因此要非常仔细,建议修改前备份一下原始的环境,要不然修改错了就会导致集群崩溃。
启用 RequestResponse 级别的审计记录来跟踪 persistentvolumes 更改的请求。
启用 namespace front-apps 中 configmaps 更改请求体的审计记录。
启用 Metadata 级别的审计记录来跟踪所有 namespace 中 ConfigMap 和 Secret 的更改。
添加一个全方位的规则以记录所有其他请求的 Metadata 级别的审计记录。
1 切换到Master的root下
ssh master01
sudo -i
2 配置审计策略
先备份配置文件
mkdir bak5
cp /etc/kubernetes/logpolicy/sample-policy.yaml bak5/
vim /etc/kubernetes/logpolicy/sample-policy.yaml
参考官方网址内容
……
rules:
# namespaces changes at RequestResponse level
- level: RequestResponse
resources:
- group: ""
resources: ["persistentvolumes"] #根据题目要求修改,比如题目要求的是namespaces。
#the request body of persistentvolumes/pods changes in the namespace front-apps
- level: Request
resources:
- group: ""
resources: ["configmaps"] #根据题目要求修改,比如题目要求的是persistentvolumes或者pods。
namespaces: ["front-apps"]
# Log configmap and secret changes in all other namespaces at the Metadata level.
- level: Metadata
resources:
- group: ""
resources: ["secrets", "configmaps"]
# Also, add a catch-all rule to log all other requests at the Metadata level.
- level: Metadata
omitStages:
- "RequestReceived"
3 配置 master 节点的kube-apiserver.yaml
先备份配置文件
mkdir bak5
cp /etc/kubernetes/manifests/kube-apiserver.yaml bak5/
vi /etc/kubernetes/manifests/kube-apiserver.yaml
添加以下参数:注意空格要对齐
#定义审计策略yaml文件位置,通过hostpath挂载
- --audit-policy-file=/etc/kubernetes/logpolicy/sample-policy.yaml #主意检查,如果考试中已经存在了,则不要重复添加。
#定义审计日志位置,通过hostpath挂载
- --audit-log-path=/var/log/kubernetes/audit-logs.txt #主意检查,如果考试中已经存在了,则不要重复添加。
#定义保留旧审计日志文件的最大天数为10天
- --audit-log-maxage=10 #主意检查,如果考试中已经存在了,则不要重复添加。
#定义要保留的审计日志文件的最大数量为2个
- --audit-log-maxbackup=2 #主意检查,如果考试中已经存在了,则不要重复添加。
#在kube-apiserver.yaml 文件的volumeMounts 标签下增加
volumeMounts: #找到这个字段,添加下面内容
- mountPath: /etc/kubernetes/logpolicy/sample-policy.yaml #这里也可以写到目录/etc/kubernetes/logpolicy/
name: audit #注意,在1.23考试中,蓝色的内容已经默认有了,你只需要添加绿色字体的内容。可以通过红色字,在文件中定位。但模拟环境没有加,
需要你全部手动添加。这样是为了练习,万一考试中没有,你也会加。但是如果考试中已添加,你再添加一遍,则会报错,导致api-server启不起来。
readOnly: true #这个为true
- mountPath: /var/log/kubernetes/
name: audit-log #注意,在1.23考试中,蓝色的内容已经有了,你只需要添加绿色字体的内容。可以通过红色字,在文件中定位。但模拟环境没有加,
需要你全部手动添加。这样是为了练习,万一考试中没有,你也会加。
readOnly: false #这个为false
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#在kube-apiserver.yaml 文件的volumes标签下增加
volumes: #找到这个字段,添加下面内容 #注意,在1.23考试中,蓝色的内容已经有了,volumes这段无需修改,但是为了以防万一,模拟环境中没有
加,需要你手动添加。这样是为了练习,万一考试中没有,你也会加。
- name: audit
hostPath:
path: /etc/kubernetes/logpolicy/sample-policy.yaml #这里如果写到目录/etc/kubernetes/logpolicy/,则下面的type:应为type: DirectoryOrCreate
type: File
- name: audit-log
hostPath:
path: /var/log/kubernetes/
type: DirectoryOrCreate
4 重启kubelet服务
systemctl restart kubelet
等待2分钟后,再检查
kubectl get pod -A
tail /var/log/kubernetes/audit-logs.txt
# 退出root,退回到candidate@master01
exit
# 退出master01,退回到candidate@node01
exit
|
6、创建 Secret
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
Task
在namespace istio-system中获取名为db1-test的现有secret的内容
将username字段存储在名为 /cks/sec/user.txt 的文件中,并将password字段存储在名为 /cks/sec/pass.txt的文件中。
注意:你必须创建以上两个文件,他们还不存在。
注意:不要在以下步骤中使用/修改先前创建的文件,如果需要,可以创建新的临时文件。
在istio-system namespace中创建一个名为db2-test的新secret,内容如下:
username : production-instance
password : KvLftKgs4aVH
最后,创建一个新的Pod,它可以通过卷访问secret db2-test :
Pod 名称 secret-pod
Namespace istio-system
容器名 dev-container
镜像 nginx
卷名 secret-volume
挂载路径 /etc/secret
|
三个网址都要看
https://kubernetes.io/zh/docs/tasks/configmap-secret/managing-secret-using-kubectl/#decoding-secret
https://kubernetes.io/zh/docs/tasks/configmap-secret/managing-secret-using-kubectl/#create-a-secret
https://kubernetes.io/zh/docs/concepts/configuration/secret/#using-secrets
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
# kubectl config use-context KSCH00701
1 将db1-test的username和password,通过base64解码保存到题目指定文件:
方法1:
kubectl get secrets db1-test -n istio-system -o jsonpath={.data}
会反馈结果为:{"password":"aGVsbG8=","username":"ZGIx"}
echo 'ZGIx'|base64 -d > /cks/sec/user.txt
echo 'aGVsbG8='|base64 -d > /cks/sec/pass.txt
方法2:
kubectl get secrets -n istio-system db1-test -o jsonpath={.data.username} | base64 -d > /cks/sec/user.txt
kubectl get secrets -n istio-system db1-test -o jsonpath={.data.password} | base64 -d > /cks/sec/pass.txt
检查
cat /cks/sec/user.txt
cat /cks/sec/pass.txt
2 创建名为 db2-test 的 secret 使用题目要求的用户名和密码作为键值。注意要加命名空间。
注意,如果密码中有特殊字符(例如:$,\,*,= 和 !),需要加单引号来转义--from-literal=password='G!Y\*d$zDsb'这样。
kubectl create secret generic db2-test -n istio-system --from-literal=username=production-instance --from-literal=password=KvLftKgs4aVH
3 根据题目要求,参考官网,创建Pod使用该secret
vim k8s-secret.yaml
添加如下内容
apiVersion: v1
kind: Pod
metadata:
name: secret-pod #pod名字
namespace: istio-system #命名空间
spec:
containers:
- name: dev-container #容器名字
image: nginx #镜像名字
volumeMounts: #挂载路径
- name: secret-volume #卷名
mountPath: /etc/secret
volumes:
- name: secret-volume #卷名
secret:
secretName: db2-test #名为 db2-test 的 secret
创建
kubectl apply -f k8s-secret.yaml
|
7、Dockerfile检测
1
2
3
4
5
6
7
8
9
10
11
12
|
Task
分析和编辑给定的Dockerfile /cks/docker/Dockerfile(基于ubuntu:16.04 镜像),
并修复在文件中拥有的突出的安全/最佳实践问题的两个指令。
分析和编辑给定的清单文件 /cks/docker/deployment.yaml ,
并修复在文件中拥有突出的安全/最佳实践问题的两个字段。
注意:请勿添加或删除配置设置;只需修改现有的配置设置让以上两个配置设置都不再有安全/最佳实践问题。
注意:如果您需要非特权用户来执行任何项目,请使用用户ID 65535 的用户 nobody 。
只修改即可,不需要创建。
|
https://kubernetes.io/zh/docs/concepts/security/pod-security-standards/#restricted

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
|
# kubectl config use-context KSSC00301
注意,本次的Dockerfile和deployment.yaml仅修改即可,无需部署。
<1> 修改Dockerfile
vi /cks/docker/Dockerfile
1、仅将CMD上面的USER root修改为USER nobody,不要改其他的USER root。
USER nobody
2、修改基础镜像为题目要求的 ubuntu:16.04
FROM ubuntu:16.04
<2> 修改deployment.yaml
vi /cks/docker/deployment.yaml
1、template 里标签跟上面的内容不一致,所以需要将原先的run: couchdb 修改为app: couchdb
app: couchdb
(注意,这里具体要改成app: couchdb还是其他的标签,要以考试给你的yaml文件的上下文其他标签为准,要与另外两个标签一致,具体见下方截图。)
感谢网友Tse和adams的反馈和纠正。
2、删除 'SYS_ADMIN' 字段,确保 'privileged': 为False 。(CKS考试是有多套类似考试环境的,所以有时是删SYS_ADMIN,有时是改'privileged': False)
注意 注意,如果考试时,本来就没有'SYS_ADMIN' 字段,且'privileged':也默认就为False,则直接将下面绿色的这两行注释掉,就是前面加#。
securityContext:
{'Capabilities': {'add': ['NET_BIND_SERVICE'], 'drop': ['all']}, 'privileged': False, 'readonlyRootFilesystem': False, 'runAsUser': 65535}
修改后
|


8、沙箱运行容器 gVisor
1
2
3
4
5
6
7
8
9
|
Context
该 cluster使用 containerd作为CRI运行时。containerd的默认运行时处理程序是runc。
containerd已准备好支持额外的运行时处理程序runsc (gVisor)。
Task
使用名为runsc的现有运行时处理程序,创建一个名为untrusted 的RuntimeClass。
更新 namespace server中的所有Pod以在gVisor上运行。
您可以在 /cks/gVisor/rc.yaml中找到一个模版清单
|
参考资料:
https://kubernetes.io/zh/docs/concepts/containers/runtime-class/#2-%E5%88%9B%E5%BB%BA%E7%9B%B8%E5%BA%94%E7%9A%84-runtimeclass-%E8%B5%84%E6%BA%90

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
34
|
# kubectl config use-context KSMV00301
1 创建RuntimeClass
vi /cks/gVisor/rc.yaml
添加如下内容
……
metadata:
name: untrusted # 用来引用 RuntimeClass 的名字,RuntimeClass 是一个集群层面的资源
handler: runsc # 对应的 CRI 配置的名称
创建
kubectl apply -f /cks/gVisor/rc.yaml
检查
kubectl get RuntimeClass
2 将命名空间为server下的Pod引用RuntimeClass。
考试时,3个Deployment下有3个Pod,修改3个deployment即可。
kubectl -n server get deployment
编辑deployment
kubectl -n server edit deployments busybox-run
kubectl -n server edit deployments nginx-host
kubectl -n server edit deployments run-test
修改如下内容
spec: #找到这个spec,注意在deployment里是有两个单独行的spec的,要找第二个,也就是下面有containers这个字段的spec。
runtimeClassName: untrusted #添加这一行,注意空格对齐,保存会报错,忽略即可。
containers:
- image: nginx:1.9
imagePullPolicy: IfNotPresent
name: run-test
|
因为模拟环境没有安装runsc运行环境,所以改完后,新Pod是ContainerCreating状态。考试时,改完后Pod会重建并Running的。
9、容器安全,删除特权Pod
1
2
3
4
5
6
7
8
9
10
11
|
Context
最佳实践是将容器设计为无状态和不可变的。
Task
检查在 namespace production中运行的Pod,并删除任何非无状态或非不可变的 Pod。
使用以下对无状态和不可变的严格解释:
⚫ 能够在容器内存储数据的 Pod 的容器必须被视为非无状态的。
注意:你不必担心数据是否实际上已经存储在容器中。
⚫ 被配置为任何形式的特权 Pod 必须被视为可能是非无状态和非不可变的。
|
https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# kubectl config use-context KSRS00501
查看此命名空间下的所有 pod,删除有特权 Privileged 或者挂载 volume 的 pod
kubectl get pod -n production
kubectl get pods XXXX -n production -o yaml | grep -i "privileged: true" #注意冒号后面有一个空格,XXXX换成production命名空间下的pod名。
将上面查出来的有特权的pod删除
kubectl delete pod XXXX -n production
上面只是将特权的pod查出来了,根据题目要求,还应该查挂载volume的pod,命令为
kubectl get pods XXXX -n production -o jsonpath={.spec.volumes} | jq
模拟环境里的3个pod,都没有挂载volume,所以无需删除了。考试中也是这样的,都没有挂载volume。
|

什么样的是挂载了volume的pod呢?
比如kube-system命名空间下的etcd-master01是挂载了volume的。
具体是否挂载,可以依据是否有hostPath或路径

10、网络策略 NetworkPolicy
1
2
3
4
5
6
7
8
9
10
|
Task
创建一个名为pod-restriction 的NetworkPolicy来限制对在namespace dev-team 中运行的Pod products-service的访问。
只允许以下Pod连接到Pod products-service
⚫ namespace qaqa中的Pod
⚫ 位于任何namespace,带有标签environment: testing的Pod
注意:确保应用NetworkPolicy。
你可以在/cks/net/po.yaml找到一个模板清单文件。
|
https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/#networkpolicy-resource

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
# kubectl config use-context KSSH00301
1 检查namespace标签
模拟环境已提前打好标签了,所以你只需要检查标签即可。但为了防止考试时,没有给你打标签,所以还是需要你将下面打标签的命令记住。
# 查看 qaqa 命名空间标签(name: qaqa)
kubectl get ns --show-labels
# 查看 pod 标签(environment: testing)
kubectl get pod -n dev-team --show-labels
如果 Pod 或者 Namespace 没有标签,则需要打上标签。
注意:我这里将pod products-service的标签打成了environment: testing,下面会有解释,不要和题目里要求的“位于任何 namespace,带有标签environment:
testing的Pod”这句话里的标签混淆了。
# kubectl label ns qaqa name=qaqa
# kubectl label pod products-service environment=testing -n dev-team
创建NetworkPolicy
vi /cks/net/po.yaml
根据官网,修改为如下内容:
……
metadata:
name: pod-restriction #修改
namespace: dev-team #修改
spec:
podSelector:
matchLabels:
environment: testing #根据题目要求的标签修改,这个写的是Pod products-service的标签,也就是使用kubectl get pod -n dev-team --show-labels 查出来的pod的标签,这个标签不要和题目里要求的“位于任何namespace,带有标签environment: testing的Pod”这句话里的标签混淆了,两个没有关系,所以可不一样。比如你考试时查出来的POD products-service的标签是name: products,那这里的environment: testing就要换成name: products。
policyTypes:
- Ingress #注意,这里只写 - Ingress,不要将 - Egress也复制进来!
ingress:
- from: #第一个from
- namespaceSelector:
matchLabels:
name: qaqa #命名空间有name: qaqa标签的
- from: #第二个from
- namespaceSelector: {} #修改为这样,所有命名空间
podSelector: #注意,这个podSelector前面的“-” 要删除,换成空格,空格对齐要对。
matchLabels:
environment: testing #有environment: testing标签的Pod,这个地方是根据题目要求“Pods with label environment: testing , in any namespace”,这句话里的pod标签写的。不要和上面spec里的混淆。
创建
kubectl apply -f /cks/net/po.yaml
检查
kubectl get networkpolicy -n dev-team
|
11、Trivy 扫描镜像安全漏洞
1
2
3
4
5
6
7
8
9
|
Task
使用Trivy开源容器扫描器检测namespace kamino中 Pod 使用的具有严重漏洞的镜像。
查找具有High或Critical严重性漏洞的镜像,并删除使用这些镜像的Pod。
注意:Trivy仅安装在cluster的master节点上,
在工作节点上不可使用。
你必须切换到cluster的master节点才能使用Trivy。
|
https://kubernetes.io/zh/docs/reference/kubectl/cheatsheet/#%E6%A0%BC%E5%BC%8F%E5%8C%96%E8%BE%93%E5%87%BA
1
2
|
# 列举 default 名字空间中运行的所有镜像,按 Pod 分组
kubectl get pods --namespace default --output=custom-columns="NAME:.metadata.name,IMAGE:.spec.containers[*].image"
|
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
34
35
36
37
|
# kubectl config use-context KSSC00401
注意:这个题非常耗费时间,考试时关注一下剩余时间。如果时间剩余不多,可以放到最后做这道题。
1 切换到Master的candidate下
ssh master01
2 获取命名空间kamino 下的所有pod的image
kubectl get pods --namespace kamino --output=custom-columns="NAME:.metadata.name,IMAGE:.spec.containers[*].image"
# 获取每一个pod的image
kubect get pod XXXX -n kamino -o yaml | grep image
trivy image -s HIGH,CRITICAL nginx:1.19 # HIGH,CRITICAL,这里的nginx:1.19 换成你上一步查出来的镜像名字
或者也可以使用这条命令查询trivy image nginx:1.19 | grep -iE 'High|Critical'
注意tri222和tri333的2个pod里各有2个image,都需要扫描。
trivy image -s HIGH,CRITICAL amazonlinux:1
trivy image -s HIGH,CRITICAL amazonlinux:2
trivy image -s HIGH,CRITICAL nginx:1.19
trivy image -s HIGH,CRITICAL vicuu/nginx:host
4 删除有问题的pod
kubectl delete pod XXXX -n kamino
5 退出master01,退回到candidate@node01
exit
请注意,考试时有5个pod,每个pod里有多个image 镜像,都需要扫描。扫描出有漏洞的镜像,则删除有这个镜像的pod。
|
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
|
# 切换到Master的root下
(写while脚本有点麻烦)
(对于pod数量多的情况,可以使用下面方法)
ssh master01
检查所有pod
kubectl get po -n kamino
kubectl get po -n kamino | grep -v "NAME" | awk '{print $1}' > podlist.txt
cat podlist.txt
循环检查pod里的image
while read line;do
echo $line
kubectl get pod -n kamino $line -o yaml | grep "image:"
done < podlist.txt
对查出来的image 逐一扫描
trivy image -s HIGH,CRITICAL nginx:1.19 #注意HIGH,CRITICAL为大写
删除扫描的镜像带有高危或严重漏洞的 Pod
kubectl delete pod XXXX -n kamino
# 退出master01,退回到candidate@node01
exit
|
12、AppArmor
1
2
3
4
5
6
|
Context
APPArmor 已在 cluster 的工作节点node02上被启用。一个 APPArmor 配置文件已存在,但尚未被实施。
Task
在 cluster 的工作节点node02上,实施位于 /etc/apparmor.d/nginx_apparmor的现有APPArmor 配置文件。
编辑位于 /cks/KSSH00401/nginx-deploy.yaml 的现有清单文件以应用 AppArmor 配置文件。
最后,应用清单文件并创建其中指定的 Pod 。
|
https://kubernetes.io/zh/docs/tutorials/security/apparmor/#example

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
# kubectl config use-context KSSH00401
1 切换到node02的root下
ssh node02
sudo -i
2 切换到apparmor的目录,并检查配置文件
cd /etc/apparmor.d/
vi /etc/apparmor.d/nginx_apparmor
注意,nginx-profile-3这一行要注释掉,但要确保profile nginx-profile-3这一行没有注释。
#include <tunables/global>
# nginx-profile-3 #注释掉 模拟环境里多写了一行的,会导致apparmor_parser -q的时候会报错。1.21里,这个文件是有一个这样的操作的,但在新的1.23
的考试中,这个/etc/apparmor.d/nginx_apparmor又变成正确的了。所以你在考试时,可以先cat /etc/apparmor.d/nginx_apparmor,有错误则改,没错误,则
不要再改了。
profile nginx-profile-3 flags=(attach_disconnected) { #这句是正确的配置,不要修改。profile后面的nginx-profile-3为apparmor策略模块的名字。
#include <abstractions/base>
file,
……
3 执行apparmor策略模块
没有grep到,说明没有启动。
apparmor_status | grep nginx-profile-3
加载启用这个配置文件
apparmor_parser -q /etc/apparmor.d/nginx_apparmor
# 再次检查有结果了
apparmor_status | grep nginx
显示如下内容
nginx-profile-3
4 修改pod文件
vi /cks/KSSH00401/nginx-deploy.yaml
修改如下内容
……
metadata:
name: podx
#添加annotations,kubernetes.io/podx名字和containers下的名字一样即可,nginx-profile-3为前面在worker node01上执行的apparmor策略模块的名
字。
annotations:
container.apparmor.security.beta.kubernetes.io/podx: localhost/nginx-profile-3
spec:
containers:
- image: busybox
imagePullPolicy: IfNotPresent
name: podx #这个就是containers下的名字,为podx
command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
……
创建
kubectl apply -f /cks/KSSH00401/nginx-deploy.yaml
# 退出root,退回到candidate@node02
exit
# 退出node02,退回到candidate@node01
exit
|
13、Sysdig & falco
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
Task:
使用运行时检测工具来检测 Pod tomcat123单个容器中频发生成和执行的异常进程。
有两种工具可供使用:
⚫ sysdig
⚫ falco
注: 这些工具只预装在cluster的工作节点node02上,不在 master 节点。
使用工具至少分析30秒 ,使用过滤器检查生成和执行的进程,将事件写到 /opt/KSR00101/incidents/summary文件中,
其中包含检测的事件, 格式如下:
timestamp,uid/username,processName
保持工具的原始时间戳格式不变。
注: 确保事件文件存储在集群的工作节点上。
请注意,考试时,考题里已表明sysdig在工作节点上,所以你需要ssh到开头写的工作节点上。但在模拟环境,你需要ssh到node02这个工作节点。
# kubectl config use-context KSSC00401
1 切换到node02的root下
ssh node02
sudo -i
2、先找到containerd的socket
crictl info | grep sock
3、crontainerd要使用crictl命令找到容器,题目要求的是tomcat123,则grep tomcat123。
crictl ps | grep tomcat123
4、
通过 sysdig 扫描容器30s并输出到指定文件:
sysdig -h 和-l 查看帮助
注:可以使用 sysdig -l |grep time 过滤,确认输出格式字段
sysdig -l | grep time
sysdig -l | grep uid
sysdig -l | grep proc
开始扫描 (我目前想不到别的方法,只能将命令分成2条了,谁有更好的方法,可以分享一下。)
sysdig -M 30 -p "%evt.time,%user.uid,%proc.name" --cri /run/containerd/containerd.sock container.name=tomcat123 >> /opt/KSR00101/incidents/summary
sysdig -M 30 -p "%evt.time,%user.name,%proc.name" --cri /run/containerd/containerd.sock container.name=tomcat123 >> /opt/KSR00101/incidents/summary
提示:如果考试时执行sysdig报错“Unable to load the driver”,则执行下面一条命令:(模拟环境里不需要执行)
#启用模块
sysdig-probe-loader
然后再次执行sysdig -M 30 ……
如果还是报错,就重装一下sysdig,命令为apt install sysdig
查看保存的文件
cat /opt/KSR00101/incidents/summary |head
# 退出root,退回到candidate@node02
exit
# 退出node02,退回到candidate@node01
exit
|
14、Pod 安全策略-PSP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
Context
PodSecurityPolicy应防在特定namespace中特权Pod的创建。
Task
创建一个名为restrict-policy的新的PodSecurityPolicy,以防止特权Pod的创建。
创建一个名为restrict-access-role并使用新创建的PodSecurityPolicy restrict-policy的ClusterRole。
在现有的namespace staging中创建一个名为psp-denial-sa的新ServiceAccount
。
最后,创建一个名为dany-access-bind的ClusterRoleBinding ,
将新创建的ClusterRole restrict-access-role绑定到新创建的ServiceAccount psp-denial-sa。
你可以在一下位置找到模版清单文件:
/cks/psp/psp.yaml
|
四个都要看
https://kubernetes.io/zh/docs/reference/command-line-tools-reference/kube-apiserver/#%E9%80%89%E9%A1%B9
https://kubernetes.io/docs/concepts/security/pod-security-policy/#create-a-policy-and-a-pod
https://kubernetes.io/docs/concepts/security/pod-security-policy/#via-rbac
如果使用命令不会创建clusterrole和clusterrolebinding,则可以参考官网的yaml文件,修改并使用kubectl apply -f来创建。
https://kubernetes.io/docs/concepts/security/pod-security-policy/#example
使用命令创建clusterrole和clusterrolebinding的参考方法
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
# kubectl config use-context KSMV00102
1 切换到Master的root下
ssh master01
sudo -i
2 检查确认apiserver支持PodSecurityPolicy
启用PSP准入控制器(考试中默认已经启用,但以防万一,还是要检查一下的。)
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep PodSecurityPolicy
确保有下面这行,在1.23的考试中,这一行已经提前给你加上了,但还是需要检查确认一下。
- --enable-admission-plugins=NodeRestriction,PodSecurityPolicy
如果kube-apiserver.yam配置文件需要修改
则先备份配置文件,再添加这行。
mkdir bak14
cp /etc/kubernetes/manifests/kube-apiserver.yaml bak14
vi /etc/kubernetes/manifests/kube-apiserver.yaml
修改或添加如下内容
- --enable-admission-plugins=NodeRestriction,PodSecurityPolicy
编辑完后重新加载配置文件,并重启kubelet
systemctl daemon-reload
systemctl restart kubelet.service
# 退出root,退回到candidate@master01
exit
# 退出master01,退回到candidate@node01
exit
3 创建PSP
官方网址里复制PSP的内容,并修改拒绝特权。(考试中会给出参考的yaml文件,可以修改这个文件。)
创建名为prevent-psp-policy的PodSecurityPolicy,阻止创建Privileged Pod。
vi /cks/psp/psp.yaml #如果这个文件考试时,在node01找不到,就回上面的master里找。
修改如下内容
……
metadata:
name: restrict-policy #检查一下name,如果不对则修改。
spec:
privileged: false # 修改为false,阻止创建Privileged Pod(特权pod)
seLinux: #下面这些信息,根据官网拷贝。
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
volumes:
- '*'
创建
kubectl apply -f /cks/psp/psp.yaml
检查
kubectl get podsecuritypolicy
4 创建CluserRole和ServiceAccount,并通过ClusterRoleBinding绑定。
方法1:
使用命令创建
kubectl create clusterrole restrict-access-role --verb=use --resource=psp --resource-name=restrict-policy
kubectl create sa psp-denial-sa -n staging
kubectl create clusterrolebinding dany-access-bind --clusterrole=restrict-access-role --serviceaccount=staging:psp-denial-sa
方法2:
1.23考试中,已经给你3个空的yaml文件了,所以可以使用方法2来做,先修改yaml文件,再apply。
参考官网,通过yaml文件来创建,CluserRole和ServiceAccount,以及ClusterRoleBinding绑定
https://kubernetes.io/zh/docs/concepts/policy/pod-security-policy/#via-rbac
检查
kubectl describe clusterrolebinding dany-access-bind
|
15、启用API server认证
1
2
3
4
5
6
7
8
9
10
11
12
|
Context
由 kubeadm 创建的 cluster 的 Kubernetes API 服务器,出于测试目的,
临时配置允许未经身份验证和未经授权的访问,授予匿名用户 cluster-admin 的访问权限.
Task
重新配置cluster 的Kubernetes APl 服务器,以确保只允许经过身份验证和授权的 REST请求。
使用授权模式 Node,RBAC 和准入控制器 NodeRestriction。
删除用户 system:anonymous 的 ClusterRoleBinding来进行清理。
注意:所有kubectl 配置环境/文件也被配置使用未经身份验证和未经授权的访问。
你不必更改它,但请注意,一旦完成 cluster 的安全加固, kubectl 的配置将无法工作。
您可以使用位于 cluster 的 master 节点上,cluster 原本的 kubectl 配置文件
/etc/kubernetes/admin.conf ,以确保经过身份验证的授权的请求仍然被允许。
|
https://kubernetes.io/zh/docs/reference/command-line-tools-reference/kube-apiserver/
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
34
35
36
37
38
|
# kubectl config use-context KSCF00301
1 切换到Master的root下
ssh master01
sudo -i
2 确保只有认证并且授权过的REST请求才被允许
编辑/etc/kubernetes/manifests/kube-apiserver.yaml,修改下面内容
- --authorization-mode=AlwaysAllow
- --enable-admission-plugins=AlwaysAdmit
vi /etc/kubernetes/manifests/kube-apiserver.yaml
修改为
- --authorization-mode=Node,RBAC #注意,只保留Node,RBAC这两个,中间是英文状态下的逗号。在1.23考试中,这一条可能默认已经有
了,但还是要检查确认一下。
- --enable-admission-plugins=NodeRestriction #在1.23考试中,这一个原先为AlwaysAdmit,需要修改为NodeRestriction。
- --client-ca-file=/etc/kubernetes/pki/ca.crt #这一条也要检查一下,是否存在配置文件中,如果没有,也需要添加。在1.23考试中,这一条默认已经有了。
- --enable-bootstrap-token-auth=true #这一条也要检查一下,是否存在配置文件中,如果没有,也需要添加。在1.23考试中,这一条默认已经有
了。
重启kubelet
systemctl daemon-reload
systemctl restart kubelet
修改完成后,等待3分钟,集群才会恢复正常。
kubectl get pod -A
3 删除题目要求的角色绑定
查
kubectl get clusterrolebinding system:anonymous
删
kubectl delete clusterrolebinding system:anonymous
再检查
kubectl get clusterrolebinding system:anonymous
|
16、ImagePolicyWebhook容器镜像扫描
1
2
3
4
5
6
7
8
9
10
11
12
|
cluster上设置了容器镜像扫描器,但尚未完全集成到 cluster 的配置中。
完成后,容器镜像扫描器应扫描并拒绝易受攻击的镜像的使用。
Task
注意:你必须在 cluster 的 master 节点上完成整个考题,所有服务和文件都已被准备好并放置在该节点上。
给定一个目录 /etc/kubernetes/epconfig中不完整的配置,
以及具有 HTTPS 端点https://image-bouncer-webhook.default.svc:1323/image_policy 的功能性容器镜像扫描器:
1. 启用必要的插件来创建镜像策略
2. 校验控制配置并将其更改为隐式拒绝(implicit deny)
3. 编辑配置以正确指向提供的 HTTPS 端点
最后,通过尝试部署易受攻击的资源 /cks/img/web1.yaml来测试配置是否有效。
|
三个网址都要看
https://kubernetes.io/zh/docs/reference/access-authn-authz/admission-
controllers/#%E5%A6%82%E4%BD%95%E5%90%AF%E7%94%A8%E4%B8%80%E4%B8%AA%E5%87%86%E5%85%A5%E6%8E%A7%E5%88%B6%E5%99%A8
https://kubernetes.io/zh/docs/reference/access-authn-authz/admission-controllers/#imagepolicywebhook
https://kubernetes.io/zh/docs/tasks/debug/debug-cluster/audit/#log-%E5%90%8E%E7%AB%AF
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
# kubectl config use-context KSSH00901
本题分数比较多,占10%
第1步 切换到Master的root下
ssh master01
sudo -i
第2步,编辑admission_configuration.json(题目会给这个目录),修改defaultAllow为false:
vi /etc/kubernetes/epconfig/admission_configuration.json
……
"denyTTL": 50,
"retryBackoff": 500,
"defaultAllow": false #将true改为false
……
第3步,编辑/etc/kubernetes/epconfig/kubeconfig.yml,添加 webhook server 地址:
操作前,先备份配置文件
mkdir bak16
cp /etc/kubernetes/epconfig/kubeconfig.yml bak16/
vi /etc/kubernetes/epconfig/kubeconfig.yml
修改如下内容
……
certificate-authority: /etc/kubernetes/epconfig/server.crt
server: https://image-bouncer-webhook.default.svc:1323/image_policy #添加webhook server地址
name: bouncer_webhook
……
第4步,编辑kube-apiserver.yaml,从官网中引用 ImagePolicyWebhook 的配置信息:
操作前,先备份配置文件
mkdir bak16
cp /etc/kubernetes/manifests/kube-apiserver.yaml bak16/
vi /etc/kubernetes/manifests/kube-apiserver.yaml
在- command:下添加如下内容,注意空格要对齐
- --enable-admission-plugins=NodeRestriction,ImagePolicyWebhook
- --admission-control-config-file=/etc/kubernetes/epconfig/admission_configuration.json #在1.23的考试中,默认这行已经添加了,但为了以防万一,
模拟环境,没有添加,需要你手动添加。考试时,你先检查,有的话,就不要再重复添加了。重复添加反而会报错!
# 在kube-apiserver.yaml的 volumeMounts 增加
volumeMounts: #在volumeMounts下面增加 #注意,在1.23考试中,蓝色的内容可能已经有了,你只需要添加绿色字体的内容。可以通过红色字,在文件中定位。但模拟环境没有加,需要你全部手动添加。这样是为了练习,万一考试中没有,你也会加。但是如果考试中已添加,你再添加一遍,则会报错,导致api-server启不起来。
- mountPath: /etc/kubernetes/epconfig
name: epconfig
readOnly: true
# 在kube-apiserver.yaml的volumes 增加
volumes: #在volumes下面增加 #注意,在1.23考试中,蓝色的内容可能已经有了,你只需要检查确认一下是否准确。可以通过红色字,在文件中定位。但模拟环境没有加,需要你全部手动添加。这样是为了练习,万一考试中没有,你也会加。但是如果考试中已添加,你再添加一遍,则会报错,导致api-server启不起来。
- name: epconfig
hostPath:
path: /etc/kubernetes/epconfig
type: DirectoryOrCreate
#如果你写的是目录,则是DirectoryOrCreate,如果你写的是文件,则是File
第5步,重启kubelet。
systemctl restart kubelet
通过尝试部署易受攻击的资源 /cks/img/web1.yaml来测试配置是否有效
无法创建pod,如下报错,表示成功。
因为模拟环境里的image_policy 策略是镜像tag是latest 的不允许创建。
kubectl apply -f /cks/img/web1.yaml
第6步 退回到原ssh终端
# 退出root,退回到candidate@master01
exit
# 退出master01,退回到candidate@node01
exit
|