cks

# 沙箱运行容器 gVisor ![image.png](https://cos.easydoc.net/97954506/files/l42f83dp.png) **Context** 该 cluster使用 `containerd`作为CRI运行时。`containerd`的默认运行时处理程序是runc。`containerd`已准备好支持额外的运行时处理程序`runsc`(gVisor)。 **Task** 使用名为`runsc`的现有运行时处理程序,创建一个名为`untrusted` 的RuntimeClass。更新 namespace `server`中的所有Pod以在gVisor上运行。 您可以在 `/cks/gVisor/rc.yaml`中找到一个模版清单。 **答题:** 考试时执行,切换集群。模拟环境中不需要执行。 `# kubectl config use-context KSMV00301` 1 创建RuntimeClass ``` vi /cks/gVisor/rc.yaml 添加如下内容 apiVersion: node.k8s.io/v1beta1 kind: RuntimeClass metadata: name: untrusted # 用来引用 RuntimeClass 的名字,RuntimeClass 是一个集群层面的资源 handler: runsc # 对应的 CRI 配置的名称 ``` 创建 `kubectl apply -f /cks/gVisor/rc.yaml` 检查 `kubectl get RuntimeClass` ![image.png](https://cos.easydoc.net/97954506/files/l42fdprd.png) 2 将命名空间为server下的Pod引用RuntimeClass。 考试时Pod是创建好的,直接使用kubectl edit直接修改即可。 模拟环境里,有1个deployment和3个pod。其中1个pod是deployment的,只需要修改这个deployment和另外2个pod即可。 `kubectl get all -n server` ![image.png](https://cos.easydoc.net/97954506/files/l42ffbsf.png) 编辑deployment (这里环境有点问题,没有安装runsc,所以改完后保存会报错,忽略吧,先模拟一下命令即可。) `kubectl edit deployments nginx-host -n server` 修改如下内容 ``` spec: #找到这个spec,注意在deployment里是有两个单独行的spec的,要找第二个,也就是下面有containers这个字段的。 runtimeClassName: untrusted #添加这一行,注意空格对齐,保存会报错,忽略即可。 containers: - image: vicuu/nginx:host imagePullPolicy: IfNotPresent name: nginx-host ``` 编辑pod `kubectl edit pod nginx-gvisor -n server` ``` spec: #在pod里,只有一个定单独行的spec,选择这个spec下面添加。 runtimeClassName: untrusted #添加这一行,注意空格对齐,保存会报错,忽略即可。 containers: - image: nginx imagePullPolicy: IfNotPresent name: nginx-gvisor ``` 编辑pod `kubectl edit pod busybox -n server` ``` spec: runtimeClassName: untrusted #添加这一行,注意空格对齐,保存会报错,忽略即可。 containers: - args: - /bin/sh - -c - | i=0; while true; do echo "$(date) INFO $i" >> /var/log/11-factor-app.log; i=$((i+1)); sleep 1; done image: busybox imagePullPolicy: IfNotPresent name: busybox ``` # 创建 Secret(真题第8题) ![image.png](https://cos.easydoc.net/97954506/files/l42cljx1.png) **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` ** 答题:** 考试时执行,切换集群。模拟环境中不需要执行。 `# 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 ``` ![image.png](https://cos.easydoc.net/97954506/files/l42dfoum.png) 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` 检查 kubectl get secret -n istio-system ![image.png](https://cos.easydoc.net/97954506/files/l42elz2e.png) 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 ![image.png](https://cos.easydoc.net/97954506/files/l42eodfj.png) 检查 kubectl get pod -n istio-system ![image.png](https://cos.easydoc.net/97954506/files/l42epj1r.png) # Dockerfile检测 ![image.png](https://cos.easydoc.net/97954506/files/l42evck4.png) **Task** 分析和编辑给定的Dockerfile `/cks/docker/Dockerfile`(基于`ubuntu:16.04` 镜像),并修复在文件中拥有的突出的安全/最佳实践问题的两个指令。 分析和编辑给定的清单文件 `/cks/docker/deployment.yaml` ,并修复在文件中拥有突出的安全/最佳实践问题的两个字段。 注意:请勿添加或删除配置设置;只需修改现有的配置设置让以上两个配置设置都不再有安全/最佳实践问题。 注意:如果您需要非特权用户来执行任何项目,请使用用户ID `65535` 的用户 `nobody` 。 参考资料: `https://kubernetes.io/zh/docs/tasks/configure-pod-container/security-context/#set-capabilities-for-a-container` **答题:** 考试时执行,切换集群。模拟环境中不需要执行。 `# 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 ``` ![image.png](https://cos.easydoc.net/97954506/files/l42f1j57.png) ![image.png](https://cos.easydoc.net/97954506/files/l42f2dhf.png) 2 修改deployment.yaml ``` vi /cks/docker/deployment.yaml 1、修改如下两行,将'privileged': True 修改为'privileged': False,检查确保‘runAsUser’: 65535为65535。 securityContext: {"Capabilities": {'add':{NET_BIND_SERVICE}, 'drop: []'}, 'privileged': False, ‘readonlyRootFilesystem’: False, ‘runAsUser’: 65535} 2、考试时deployment.yaml的labels标签跟上面的不一致,所以需要将原先的run: couchdb修改为app: couchdb app: couchdb ``` ![image.png](https://cos.easydoc.net/97954506/files/l42f4top.png) ![image.png](https://cos.easydoc.net/97954506/files/l42f556t.png) # 容器安全,删除特权Pod(真题第10题) **Context** 最佳实践是将容器设计为无状态和不可变的。 **Task** 检查在 namespace production中运行的Pod,并删除任何非无状态或非不可变的 Pod。 使用以下对无状态和不可变的严格解释: - 能够在容器内存储数据的 Pod 的容器必须被视为`非无状态`的。 注意:你不必担心数据是否实际上已经存储在容器中。 - 被配置为任何形式的特权 Pod 必须被视为可能是非无状态和非不可变的. 参考资料: `https://kubernetes.io/docs/tasks/configure-pod-container/security-context/` **答题:** 考试时执行,切换集群。模拟环境中不需要执行。 `# 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名。 ``` ![image.png](https://cos.easydoc.net/97954506/files/l42hjq4x.png) 将上面查出来的有特权的pod删除 `kubectl delete pod XXXX -n production` ![image.png](https://cos.easydoc.net/97954506/files/l42hkera.png) 上面只是将特权的pod查出来了,根据题目要求,还应该查挂载volume的pod,命令为 ``` kubectl get pods XXXX -n production -o jsonpath={.spec.volumes} | jq kubectl get pods XXXX -n production -o jsonpath={.spec.volumes} | python -m json.tool ``` 模拟环境里的3个pod,都没有挂载volume,所以无需删除了。考试中也是这样的,都没有挂载volume。 ![image.png](https://cos.easydoc.net/97954506/files/l42hpa1z.png) 什么样的是挂载了volume的pod呢? 比如kube-system命名空间下的etcd-master01是挂载了volume的。 具体是否挂载,可以依据是否有hostPath或路径 ![image.png](https://cos.easydoc.net/97954506/files/l42hpr0n.png) # 网络策略 NetworkPolicy **Task** 创建一个名为`pod-restriction` 的NetworkPolicy来限制对在namespace `dev-team`中运行的Pod `products-service`的访问。 只允许以下Pod连接到Pod `products-service` - namespace `qa`中的Pod - 位于任何namespace,带有标签`environment: testing`的Pod 注意:确保应用NetworkPolicy。 你可以在/cks/net/po.yaml找到一个模板清单文件。 参考资料: `https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/#networkpolicy-resource` **答题:** 考试时执行,切换集群。模拟环境中不需要执行。 `# kubectl config use-context KSSH00301` 1 检查namespace标签 模拟环境已提前打好标签了,所以你只需要检查标签即可。但为了防止考试时,没有给你打标签,所以还是需要你将下面打标签的命令记住。 查看 qa 命名空间标签(name: qa) `kubectl get ns --show-labels` ![image.png](https://cos.easydoc.net/97954506/files/l43f6nss.png) 查看 pod 标签(environment: testing) `kubectl get pod -n dev-team --show-labels` ![image.png](https://cos.easydoc.net/97954506/files/l43f7jxt.png) 如果 Pod 或者 Namespace 没有标签,则需要打上标签。 注意:我这里将pod products-service的标签打成了environment: testing,下面会有解释,不要和题目里要求的“位于任何namespace,带有标签environment: testing的Pod”这句话里的标签混淆了。 ``` kubectl label ns qa name=qa kubectl label pod products-service environment=testing -n dev-team ``` 2 创建NetworkPolicy `vi /cks/net/po.yaml` 根据官网,修改为如下内容: ``` apiVersion: networking.k8s.io/v1 kind: NetworkPolicy 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: qa #命名空间有name: qa标签的 - 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`