9、网络策略(二)
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 我到一个模板清单文件
清单文件就没啥内容,这里不贴了。
首先分析下题目要求,这里有两个要求:
- 指定了具体 namespace 为 qaga 下的Pod可以访问
- 指定了任何namespace下带有 指定标签的Pod可以访问 这两点是或的关系。满足任何一点都可以访问。
官方文档搜索 networkpolicy 找到关于网络策略的介绍,然后我们点击右侧"NetworkPolicy 资源"可以找到一个模板,模板算是比较全了,直接复制下来再修改。
题目要求是对指定pod的访问,所以应该是入站流量,也即是 Ingress,所以我们只保留Ingress部分。
题目要求要实现指向特定名字的空间,可以利用匹配k8s给namespace默认的标签来实现。理论上这个标签是唯一的。
视频里的做法是给namespace打上一个 name=qaqa 的标签,但是这种并不能保证是唯一的,因为其它的namespace也可以打这个标签。
然后我们看看namespace默认的label:
# kubectl get ns --show-labels
NAME STATUS AGE LABELS
db Active 2d2h kubernetes.io/metadata.name=db
default Active 44d kubernetes.io/metadata.name=default
front-apps Active 45h kubernetes.io/metadata.name=front-apps
istio-system Active 42h kubernetes.io/metadata.name=istio-system
可以看到,每个命令空间都有一个默认的label是跟他们名字挂钩的,所以我们可以利用这个来指定命名空间。
第二个要求是任意namespace下满足标签匹配的的所有pod。这里有几个知识点需要掌握的:
- podSelector在没有明确指定namespace的条件的时候,默认只对该策略所在的命名空间生效。
- 规则之间可以并存的,可以同时设置满足namespace和pod的条件。两者的关系可以是and和or。
- 如果前面是 - 开头的,那么规则的关系是 or,否则是 and。
另外,由于是针对某个pod的限制访问,我们也需要通过标签来对该pod进行匹配。所以我们先要查下这个pod的标签(考试时一定要先查,因为可能每次设置的标签并不一样)
#kubectl get pod -n dev-team --show-labels
按照题目要求,我们对yaml进行修改。完整YAML及修改说明如下
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: egress-namespaces ## 修改名字
namespace: dev-team ## 增加命名空间为需要限制访问的pod所在的namespace
spec:
podSelector:
matchLabels:
app: products-service ## 修改为指定要限制的pod的标签,要提前查出来,按查到的修改。
policyTypes:
- Ingress ## 只保留限制类型为 Ingress
ingress: ## 只保留 ingress
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: qaqa ## 修改为题目要求的空间的默认标签
- namespaceSelector: {} ## 显示指定命名空间,{}表示匹配所有命名空间。这个一定不能少。
podSelector: ## 前面不能再加 - 因为和上一行是 and 的关系
matchLabels:
environment: testing ## 修改为题目要求的pod标签
最后我们需要应用该yaml文件
#kubectl apply -f 9_network.yaml
实际考试时题目可能不太一样,可能会变成出站流量限制或者是要求对某个段的IP进行限制。也可能会加上对端口的限制。所以最好能把官方文档里面介绍的内容都掌握了。
10、Trivy 扫描镜像安全漏洞
Task
使用 Trivy 开源器扫描器检测 namespace kamino 中 Pod 使用的具有严重漏洞的镜像.
查找具有 High 或 Critical 严重性漏洞的镜像,并删除使用这些镜像的 Pod。
注意: Triw 仅安装在 cluster 的 master 节点上
在工作节点上不可使
你必须切换到 cluster 的 master 节点才能使用Trivy。
这道题考察对 Trivy 工具的使用,但是我觉得这不是重点,因为这个工具使用实在太简单了,这里主要问题是pod的镜像很多(好像是5、6个pod,然后每个pod有1-2个镜像)。
最大的问题是要把这些pod及其对应的镜像找出来,然后使用 Trivy 扫描这些镜像后找到有严重漏洞的镜像 ,在对应回 pod ,把这些pod删除。
而且考试时要去到集群的master节点才能运行 Trivy 工具,而master上又不能使用kubectl命令(没配置)。所以操作起来非常麻烦。
输出pod名字及对应的image的命令如下,命令有些复杂,但是必须要记住,不然一个个去看和处理会非常繁琐,浪费很多时间。
# kubectl get pod -o jsonpath='{range .items[*]}{.metadata.name},{.spec.containers[*].image}{"\n"}{end}' -n kubesphere-devops-system
kube-state-metrics-7667b7b6b4-p2rq6,harbor.timesgroup.cn/kubesphere/kube-state-metrics:v2.5.0 harbor.timesgroup.cn/kubesphere/kube-rbac-proxy:v0.11.0 harbor.timesgroup.cn/kubesphere/kube-rbac-proxy:v0.11.0
node-exporter-6g226,tharbor.timesgroup.cn/prom/node-exporter:v1.3.1 tharbor.timesgroup.cn/kubesphere/kube-rbac-proxy:v0.11.0
pod的名字和镜像直接使用逗号分隔,多个镜像间使用空格分隔。我们先把这些找出来然后把结果复制写入到master的临时文件 image.txt 里去。
Trivy 扫描镜像的命令非常简单,直接 trivy image 镜像 (其实不加 image 也可以)。题目要求是找High 或 Critical 级别的漏洞,所以可以加上参数来指定
#trivy image --severity CRITICAL,HIGH tharbor.timesgroup.cn/chenhq/nginx-web1:v3
主要是批量处理,下面是我写的批量处理脚本,供参考(当然,你也可以一个个去扫)
cat image.txt|while read line
do
echo $line|awk -F"," '{print $1}'
for image in `echo $line|awk -F"," '{print $2}'`
do
trivy image --skip-db-update=true --severity CRITICAL,HIGH $image|grep "Total"
done
done
我测试出来的结果如下
reditate-metrics-7667b7b6b4-p2rq6
Total: 4 (HIGH: 4, CRITICAL: 0)
Total: 0 (HIGH: 0, CRITICAL: 0)
Total: 4 (HIGH: 4, CRITICAL: 0)
node-exporter-6g226
Total: 4 (HIGH: 4, CRITICAL: 0)
Total: 0 (HIGH: 0, CRITICAL: 0)
脚本会先输出pod的名字,然后打印扫描的结果汇总,如果不为0说明存在符合指定级别的漏洞,则要删除对应的pod(只要有一个image有漏洞,这个pod都得删除)
如果不加 –severity CRITICAL,HIGH 参数,也可以,只是要根据结果查看是否指定漏洞级别的漏洞数量是否不为0.
11、AppArmor
Context
APPArmor 已在 cluster 的工作节点 node02 上被启用。一个 APPArmor 配置文件已存在,但尚未被实施
Task
在 custer 的工作节点 node02 上,实施位于 /etc/apparmor.d/nginx_apparmor 的现有 APPArmor 配置文件
编辑位于 /cks/KSSH00401/nginx-deploy.yaml 的现有清单文件以应用 AppArmor 配置文件。
最后,应用清单文件并创建其中指定的 Pod
/etc/apparmor.d/nginx_apparmor 内容如下:
#include <tunables/global>
profile nginx-profile-3 flags=(attach_disconnected){
#include <abstractions/base>
file,
# Deny all file weites.
deny /** w,
}
/cks/KSSH00401/nginx-deploy.yaml 内容如下:
apiversion: v1
kind: Pod
metadata:
name: podx
spec:
containers :
- image: busybox
imagePullPolicy: IfNotPresent
name : podx
command: [ "sh",-c" "echo 'Hello AppArmor!: && sleep 5h" ]
resources:
nodeName: node02
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
AppArmor 用来限制容器对资源的访问,一般就是限制对主机文件系统的访问权限。官方文档搜索Apparmor 第一篇就是其介绍。
11.1 增加 Apparmor 配置
按照题目要求,配置文件放在node02节点,而且查看pod的yaml文件,也是指定了 nodeName: node02 ,所以我们只需要去到 node02 进行配置即可
# apparmor_parser -q /etc/apparmor.d/nginx_apparmor
# apparmor_status ## 查看当前配置,检查是否加载成功。
11.2 给pod添加Apparmor限制
在文档里点击右侧的"举例",然后往下拉一点,就有个给pod应用Apparmor规则的例子,只需要在metadata处增加注解,如下
apiversion: v1
kind: Pod
metadata:
name: podx
annotations: ## add
container.apparmor.security.beta.kubernetes.io/podx: localhost/nginx-profile-3 # add
spec:
...
关于 container.apparmor.security.beta.kubernetes.io/podx: localhost/nginx-profile-3 的说明
- podx 是容器的名字,不是pod的名字。上面给出的yaml文件里pod和容器名字一样的,不要搞混。
- localhost 是指本地的,因为我们是直接在node上创建的,所以使用该值。
- nginx-profile-3 就是我们创建的配置项的名字,来自于 /etc/apparmor.d/nginx_apparmor 里的profile后面的名字。 最后,要求创建这个yaml文件。
#kubectl apply -f /cks/KSSH00401/nginx-deploy.yaml
要注意,如果给出的 nginx-deploy.yaml 文件里没有 nodeName: node02 参数则应该加上,否则pod可能没分配到这个节点,无法正常加载配置从而导致启动失败。
12、Sysdiag & Falco
Task:
使用运行时检测工具来检测 Pod tomcat123 单个容器中频发生成和执行的异常进程
有两种工具可供使用:
- sysdig
- falco
注: 这些工具只预装在 cluster 的工作节点 node02 上,不在 master 节点。
使用工具至少分析 30 秒,使用过滤器检查生成和执行的进程,将事件写到 /opt/KSR00101/incidents/summary 文件中,
其中包含检测的事件,格式如下:
timestamp,uid/username,processName
以下示例显示了格式正确的事件文件:
01:40:19.601363716,root,init
01:40:20.606013716,nobody,bash
01:40:21.137163716,1000,tar
保持工具的原始时间戳格式不变。
注: 确保事件文件存储在集群的工作节点上。
注意题目里已经指明要到工作节点node2上操作,且结果文件也要存储在工作节点上。
12.1 使用Sysdig工具检查
这个工具比较容易安装,Ubuntu下直接apt install sysdig 就可以安装。视频里也只讲了这个工具,所以可以重点只掌握这个工具的使用。
可以查看帮助,里面有一些例子
#sysdig -h
...
-M <num_seconds> Stop collecting after <num_seconds> reached.
...
Print the name of the files opened by cat
$ sysdig -p"%evt.arg.name" proc.name=cat and evt.type=open
-M 这个参数我们需要用到,题目要求至少分析30秒,就可以用这个参数指定。
具体的字段可以通过 sysdig -l 命令查看到,下面我只列出了我们需要用到的字段
# sysdig -l|grep time
evt.time event timestamp as a time string that includes the nanosecond p
# sysdig -l|grep container
container.id the container id.
container.name the container name.
# sysdig -l|grep user
user.uid user ID.
user.name user name.
# sysdig -l|grep proc
proc.name the name (excluding the path) of the executable generating the
我安装的版本是可以直接指定pod的,但是测试过发现啥都不能输出,所以估计是不行。所以还是稳妥点使用container的参数。
找到这个pod的container id 或者 name, 考试时的运行时是containerd,不是docker,所以最好自己的环境安装containerd来测试下。
#crictl info|grep sock # 查使用的cri,后面需要用到
"containerdEndpoint": "/run/containerd/containerd.sock",
#crictl ps |grep tomcat123
结合上面的我们可以得到最终的命令如下(不知道为何,我的环境的container.id 在sysdig 命令里是少了最后一位的,怀疑是被截断了,所以最好使用container.name)
#sysdig -M 30 -p"%evt.time,%user.uid,%prod.name" --cri /run/containerd/containerd.sock container.name=tomcat123 >>/opt/KSR00101/incidents/summary
#sysdig -M 30 -p"%evt.time,%user.name,%prod.name" --cri /run/containerd/containerd.sock container.name=tomcat123 >>/opt/KSR00101/incidents/summary
按题目意思,应该是输出user.uid 或者 user.name 其中一个就可以,但是看视频答案和其给出的正确格式例子里都同时包含了uid和name。所以我们可以各打印一次都写到同一个文件。
视频还提到,如果运行sysdig命令报错“Unable to load the driver” 则需要执行命令 sysdig-probe-loader 。如果还是报错,则重装 apt install sysdig.
falco暂时不说了,后面有空再补充。安装和配置都比较麻烦。
...