在kubernetes里使用seccomp限制容器的系统调用
一.系统环境
本文主要基于Kubernetes1.22.2和Linux操作系统Ubuntu 18.04。
服务器版本 | docker软件版本 | Kubernetes(k8s)集群版本 | CPU架构 |
---|---|---|---|
Ubuntu 18.04.5 LTS | Docker version 20.10.14 | v1.22.2 | x86_64 |
Kubernetes集群架构:k8scludes1作为master节点,k8scludes2,k8scludes3作为worker节点。
服务器 | 操作系统版本 | CPU架构 | 进程 | 功能描述 |
---|---|---|---|---|
k8scludes1/192.168.110.128 | Ubuntu 18.04.5 LTS | x86_64 | docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico | k8s master节点 |
k8scludes2/192.168.110.129 | Ubuntu 18.04.5 LTS | x86_64 | docker,kubelet,kube-proxy,calico | k8s worker节点 |
k8scludes3/192.168.110.130 | Ubuntu 18.04.5 LTS | x86_64 | docker,kubelet,kube-proxy,calico | k8s worker节点 |
二.前言
随着容器化技术的普及,应用程序的部署和运行变得越来越便捷。然而,容器的安全性也成为了一个日益重要的问题。在Kubernetes中,Seccomp(Secure Computing Mode)提供了一种强大的机制来限制容器可以执行的系统调用,从而提高系统的安全性。
使用seccomp限制容器的系统调用的前提是已经有一套可以正常运行的Kubernetes集群,关于Kubernetes(k8s)集群的安装部署,可以查看博客《Ubuntu 安装部署Kubernetes(k8s)集群》https://www.cnblogs.com/renshengdezheli/p/17632858.html。
三.系统调用简介
系统调用是应用程序请求操作系统提供服务的一种方式。攻击者可能会利用应用程序的系统调用权限执行恶意操作,例如创建新的进程、访问敏感文件等。通过限制容器可以使用的系统调用,我们可以降低攻击者的利用面,提高系统的安全性。
Seccomp 代表安全计算(Secure Computing)模式,自 2.6.12 版本以来,一直是 Linux 内核的一个特性。 它可以用来沙箱化进程的权限,限制进程从用户态到内核态的调用。 Kubernetes 能使你自动将加载到节点上的 seccomp 配置文件应用到你的 Pod 和容器。
四.使用seccomp限制docker容器系统调用
创建目录存放文件。
root@k8scludes1:~# mkdir systemsafe
root@k8scludes1:~# cd systemsafe/
当我们执行一个命令的时候,会存在各种系统调用syscall,strace 跟踪程式执行时的系统调用和所接收的信号,strace是追踪工具,执行strace -fqc cat /etc/hosts 可以查看执行cat /etc/hosts 的时候执行了哪些系统调用。
root@k8scludes1:~/systemsafe# strace -fqc cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 tom
192.168.110.128 k8scludes1
192.168.110.129 k8scludes2
192.168.110.130 k8scludes3
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
34.67 0.000095 14 7 mmap
14.23 0.000039 10 4 mprotect
13.14 0.000036 9 4 openat
10.22 0.000028 14 2 munmap
6.57 0.000018 6 3 read
5.11 0.000014 14 1 write
4.74 0.000013 2 6 close
4.38 0.000012 2 5 fstat
3.65 0.000010 3 3 3 access
2.19 0.000006 2 3 brk
0.73 0.000002 2 1 fadvise64
0.36 0.000001 1 1 arch_prctl
0.00 0.000000 0 1 execve
------ ----------- ----------- --------- --------- ----------------
100.00 0.000274 41 3 total
查看执行ping www.baidu.com的时候执行了哪些系统调用。
root@k8scludes1:~/systemsafe# strace -fqc ping www.baidu.com
PING www.a.shifen.com (14.215.177.38) 56(84) bytes of data.
64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=6 ttl=128 time=53.4 ms
64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=7 ttl=128 time=31.8 ms
^C% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
11.70 0.001336 167 8 write
8.91 0.001018 54 19 read
8.54 0.000976 108 9 sendto
7.52 0.000859 86 10 recvmsg
7.41 0.000847 61 14 1 poll
......
0.27 0.000031 31 1 uname
0.27 0.000031 31 1 geteuid
0.25 0.000028 28 1 rt_sigprocmask
0.04 0.000005 5 1 arch_prctl
0.04 0.000004 4 1 setuid
0.00 0.000000 0 1 execve
------ ----------- ----------- --------- --------- ----------------
100.00 0.011423 242 14 total
--- www.a.shifen.com ping statistics ---
7 packets transmitted, 7 received, 0% packet loss, time 6009ms
rtt min/avg/max/mdev = 31.827/296.919/767.191/313.549 ms
我们可以禁用某个系统调用,比如把read系统调用给禁了,则和read相关的操作都没法执行。
宿主机的操作系统并没有限制系统调用, 如果能执行所有的系统调用,则容器里可以执行所有的操作。
设置容器可以使用哪些系统调用,哪些不能用,可以使用profile文件控制,默认的profile禁用了44个系统调用(总共300多个系统调用),默认的profile可以去https://github.com/moby/moby/blob/master/profiles/seccomp/default.json 查看。
注意:创建seccomp profile配置文件很麻烦,并且很大程度上是基于反复试验,反复测试你需要禁止的系统调用和允许的系统调用。
下载默认的profile文件。
root@k8scludes1:~/systemsafe# wget https://raw.githubusercontent.com/moby/moby/master/profiles/seccomp/default.json
#上面那个网址下载不了的话,使用如下网址
root@k8scludes1:~/systemsafe# wget https://github.com/moby/moby/blob/master/profiles/seccomp/default.json
下载nginx镜像。
root@k8scludes1:~/systemsafe# docker pull nginx
root@k8scludes1:~/systemsafe# docker images | grep nginx
nginx latest 605c77e624dd 4 months ago 141MB
使用docker创建一个nginx容器,关于docker容器的详细操作,请查看博客《一文搞懂docker容器基础:docker镜像管理,docker容器管理》。
root@k8scludes1:~/systemsafe# docker run -dit --name=nginxweb --restart=always nginx
b92aeecb455216a42fdaf9be475ae2fdef197b8d7bfde31407d7acc5d3dd96c4
创建docker 容器的时候没有指定使用哪个seccomp profile,则默认使用默认的seccomp profile。
root@k8scludes1:~/systemsafe# docker ps | grep nginxweb
b92aeecb4552 nginx "/docker-entrypoint.…" 15 seconds ago Up 14 seconds 80/tcp nginxweb
删除docker容器。
root@k8scludes1:~/systemsafe# docker rm -f nginxweb
nginxweb
默认的profile可以去https://raw.githubusercontent.com/moby/moby/master/profiles/seccomp/default.json 或者https://github.com/moby/moby/blob/master/profiles/seccomp/default.json查看。
--security-opt seccomp可以指定docker容器使用哪个seccomp profile文件,nginxweb容器使用刚才下载的default.json作为seccomp profile文件。
root@k8scludes1:~/systemsafe# docker run -dit --name=nginxweb --restart=always --security-opt seccomp=./default.json nginx
29e9718746acffaa2ce0d435f4f8951773d3df6d18c3bc04035479f1b9a4ef37
nginx容器正常运行,因为都是允许了默认的系统调用(其中44个syscall是不被允许的)。
root@k8scludes1:~/systemsafe# docker ps | grep nginxweb
29e9718746ac nginx "/docker-entrypoint.…" 13 seconds ago Up 11 seconds 80/tcp nginxweb
删除docker容器。
root@k8scludes1:~/systemsafe# docker rm -f nginxweb
nginxweb
创建允许所有系统调用的seccomp配置文件,"defaultAction": "SCMP_ACT_ALLOW" 允许所有的系统调用。
系统调用的Action有如下:
- SCMP_ACT_KILL:当一个进程进行相应的系统调用时,内核发送一个SIGSYS信号终止该进程,进程不会收到这个信号
- SCMP_ACT_TRAP:当一个进程进行相应的系统调用时,该进程会收到SIGSYS信号并改变其行为
- SCMP_ACT_ERRNO:当进程进行相应的系统调用时,系统调用失败,进程会收到errno的返回值
- SCMP_ACT_TRACE:当一个进程进行相应的系统调用时,该进程将被跟踪
- SCMP_ACT_ALLOW:允许进程执行相应的系统调用行为
- SCMP_ACT_LOG:记录所有信息
root@k8scludes1:~/systemsafe# cat allowall.json
{
"defaultAction": "SCMP_ACT_ALLOW"
}
创建禁止所有系统调用的seccomp配置文件,"defaultAction": "SCMP_ACT_ERRNO" 禁止所有系统调用。
root@k8scludes1:~/systemsafe# vim denyall.json
root@k8scludes1:~/systemsafe# cat denyall.json
{
"defaultAction": "SCMP_ACT_ERRNO"
}
创建允许所有系统调用的容器nginxweballow,现在nginxweballow这个容器可以使用所有的系统调用,权限过高,有安全隐患。
注意 --security-opt seccomp=./allowall.json 等价于 --security-opt seccomp:unconfined 。
root@k8scludes1:~/systemsafe# docker run -dit --name=nginxweballow --restart=always --security-opt seccomp=./allowall.json nginx
1f12060e25a9724c755106b731bf727c4ee0b01a83b9c5c9e179e12198eac954
root@k8scludes1:~/systemsafe# docker ps | grep nginxweballow
1f12060e25a9 nginx "/docker-entrypoint.…" 12 seconds ago Up 11 seconds 80/tcp nginxweballow
删除nginxweballow。
root@k8scludes1:~/systemsafe# docker rm -f nginxweballow
nginxweballow
创建禁止所有系统调用的容器nginxwebdeny,任何的系统调用都不被允许,容器nginxwebdeny 创建失败。
root@k8scludes1:~/systemsafe# docker run -dit --name=nginxwebdeny --restart=always --security-opt seccomp=./denyall.json nginx
9154203049da171f3c5d7ae93a1b9be486ca0783b6ea9373dcb8544df1d84ff6
docker: Error response from daemon: cannot start a stopped process: unknown.
查看nginx镜像的历史信息,可以发现,nginx容器需要执行"nginx" "-g" "daemon“守护进程,任何的系统调用都被禁止,nginx进程也启动不了,所以创建容器失败。
root@k8scludes1:~/systemsafe# docker history nginx
IMAGE CREATED CREATED BY SIZE COMMENT
605c77e624dd 4 months ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B
<missing> 4 months ago /bin/sh -c #(nop) STOPSIGNAL SIGQUIT 0B
<missing> 4 months ago /bin/sh -c #(nop) EXPOSE 80 0B
<missing> 4 months ago /bin/sh -c #(nop) ENTRYPOINT ["/docker-entr… 0B
<missing> 4 months ago /bin/sh -c #(nop) COPY file:09a214a3e07c919a… 4.61kB
<missing> 4 months ago /bin/sh -c #(nop) COPY file:0fd5fca330dcd6a7… 1.04kB
<missing> 4 months ago /bin/sh -c #(nop) COPY file:0b866ff3fc1ef5b0… 1.96kB
<missing> 4 months ago /bin/sh -c #(nop) COPY file:65504f71f5855ca0… 1.2kB
<missing> 4 months ago /bin/sh -c set -x && addgroup --system -… 61.1MB
<missing> 4 months ago /bin/sh -c #(nop) ENV PKG_RELEASE=1~bullseye 0B
<missing> 4 months ago /bin/sh -c #(nop) ENV NJS_VERSION=0.7.1 0B
<missing> 4 months ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.21.5 0B
<missing> 4 months ago /bin/sh -c #(nop) LABEL maintainer=NGINX Do… 0B
<missing> 4 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 4 months ago /bin/sh -c #(nop) ADD file:09675d11695f65c55… 80.4MB
五.在kubernetes里使用seccomp限制容器的系统调用
5.1 配置seccomp允许pod进行所有系统调用
在kubernetes集群里,seccomp的配置文件默认放在/var/lib/kubelet/seccomp/目录下。
root@k8scludes1:~/systemsafe# mkdir -p /var/lib/kubelet/seccomp/profiles
root@k8scludes1:~/systemsafe# cd /var/lib/kubelet/seccomp/profiles
创建允许所有系统调用的seccomp配置文件。
root@k8scludes1:/var/lib/kubelet/seccomp/profiles# vim allowall_syscall
root@k8scludes1:/var/lib/kubelet/seccomp/profiles# cat allowall_syscall
{
"defaultAction": "SCMP_ACT_ALLOW"
}
创建禁止所有系统调用的seccomp配置文件。
root@k8scludes1:/var/lib/kubelet/seccomp/profiles# vim denyall_syscall
root@k8scludes1:/var/lib/kubelet/seccomp/profiles# cat denyall_syscall
{
"defaultAction": "SCMP_ACT_ERRNO"
}
系统调用的Action有如下:
- SCMP_ACT_KILL:当一个进程进行相应的系统调用时,内核发送一个SIGSYS信号终止该进程,进程不会收到这个信号
- SCMP_ACT_TRAP:当一个进程进行相应的系统调用时,该进程会收到SIGSYS信号并改变其行为
- SCMP_ACT_ERRNO:当进程进行相应的系统调用时,系统调用失败,进程会收到errno的返回值
- SCMP_ACT_TRACE:当一个进程进行相应的系统调用时,该进程将被跟踪
- SCMP_ACT_ALLOW:允许进程执行相应的系统调用行为
- SCMP_ACT_LOG:记录所有信息
创建允许50个系统调用的seccomp配置文件,"defaultAction": "SCMP_ACT_ERRNO"表示默认的规则是禁止,syscalls里面的系统调用才是允许的。
root@k8scludes1:/var/lib/kubelet/seccomp/profiles# vim fine-grained_syscall
root@k8scludes1:/var/lib/kubelet/seccomp/profiles# cat fine-grained_syscall
{
"defaultAction": "SCMP_ACT_ERRNO",
"architectures": [
"SCMP_ARCH_X86_64",
"SCMP_ARCH_X86",
"SCMP_ARCH_X32"
],
"syscalls": [
{
"names": [
"accept4",
"epoll_wait",
"pselect6",
"futex",
"madvise",
"epoll_ctl",
"getsockname",
"setsockopt",
"vfork",
"mmap",
"read",
"write",
"close",
"arch_prctl",
"sched_getaffinity",
"munmap",
"brk",
"rt_sigaction",
"rt_sigprocmask",
"sigaltstack",
"gettid",
"clone",
"bind",
"socket",
"openat",
"readlinkat",
"exit_group",
"epoll_create1",
"listen",
"rt_sigreturn",
"sched_yield",
"clock_gettime",
"connect",
"dup2",
"epoll_pwait",
"execve",
"exit",
"fcntl",
"getpid",
"getuid",
"ioctl",
"mprotect",
"nanosleep",
"open",
"poll",
"recvfrom",
"sendto",
"set_tid_address",
"setitimer",
"writev"
],
"action": "SCMP_ACT_ALLOW"
}
]
}
现在有三个不同的seccomp配置文件。
root@k8scludes1:/var/lib/kubelet/seccomp/profiles# ls
allowall_syscall denyall_syscall fine-grained_syscall
查看node节点的标签。
root@k8scludes1:/var/lib/kubelet/seccomp/profiles# kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
k8scludes1 Ready control-plane,master 30d v1.22.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8scludes1,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
k8scludes2 Ready <none> 30d v1.22.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8scludes2,kubernetes.io/os=linux
k8scludes3 Ready <none> 30d v1.22.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8scludes3,kubernetes.io/os=linux
给k8scludes3节点设置一个标签yy=xx。
root@k8scludes1:/var/lib/kubelet/seccomp/profiles# kubectl label nodes k8scludes3 yy=xx
查看标签为yy=xx的节点,此次创建pod要运行在k8scludes3节点上。
root@k8scludes1:/var/lib/kubelet/seccomp/profiles# kubectl get node -l yy=xx
NAME STATUS ROLES AGE VERSION
k8scludes3 Ready <none> 30d v1.22.2
在k8scludes3节点上拉取镜像hashicorp/http-echo:0.2.3。
root@k8scludes3:~# docker pull hashicorp/http-echo:0.2.3
0.2.3: Pulling from hashicorp/http-echo
86399148984b: Pull complete
Digest: sha256:ba27d460cd1f22a1a4331bdf74f4fccbc025552357e8a3249c40ae216275de96
Status: Downloaded newer image for hashicorp/http-echo:0.2.3
docker.io/hashicorp/http-echo:0.2.3
编辑pod配置文件,在k8scludes3节点上创建pod。
localhostProfile: profiles/allowall_syscall 指定pod使用allowall_syscall这个seccomp配置文件。
使用的镜像为hashicorp/http-echo:0.2.3,需要提前在k8scludes3节点上拉取该镜像。
如果allowall_syscall文件在/var/lib/kubelet/seccomp/profiles目录下,则写为profiles/allowall_syscall,如果allowall_syscall文件在/var/lib/kubelet/seccomp/目录下,则写为allowall_syscall。
root@k8scludes1:/var/lib/kubelet/seccomp/profiles# cd ~/systemsafe/
root@k8scludes1:~/systemsafe# vim pod2.yaml
root@k8scludes1:~/systemsafe# cat pod2.yaml
apiVersion: v1
kind: Pod
metadata:
name: audit-pod
labels:
app: audit-pod
spec:
securityContext:
seccompProfile:
type: Localhost
localhostProfile: profiles/allowall_syscall
#当需要关闭容器时,立即杀死容器而不等待默认的30秒优雅停机时长。
terminationGracePeriodSeconds: 0
#nodeSelector:yy: xx 表示pod运行在标签为yy=xx的节点上
nodeSelector:
yy: xx
containers:
- name: test-container
image: hashicorp/http-echo:0.2.3
#imagePullPolicy: IfNotPresent:表示如果本地已经存在该镜像,则不重新下载;否则从远程 Docker Hub 下载该镜像
imagePullPolicy: IfNotPresent
args:
- "-text=just made some syscalls!"
securityContext:
allowPrivilegeEscalation: false
创建pod。
root@k8scludes1:~/systemsafe# kubectl apply -f pod2.yaml
pod/audit-pod created
pod创建失败。
root@k8scludes1:~/systemsafe# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
audit-pod 0/1 CreateContainerError 0 10s 10.244.218.138 k8scludes2 <none> <none>
查看日志。
root@k8scludes1:~/systemsafe# kubectl logs audit-pod
Error from server (BadRequest): container "test-container" in pod "audit-pod" is waiting to start: CreateContainerError
查看pod的描述信息,最后一行表名找不到/var/lib/kubelet/seccomp/allowall_syscall文件,看来需要把seccomp配置文件放到k8scludes3节点的/var/lib/kubelet/seccomp/目录下。
root@k8scludes1:~/systemsafe# kubectl describe pod audit-pod
Name: podtest
Namespace: systemsafe
Priority: 0
Node: k8scludes2/192.168.110.129
......
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 83s default-scheduler Successfully assigned systemsafe/podtest to k8scludes2
Normal SandboxChanged 80s kubelet Pod sandbox changed, it will be killed and re-created.
Normal Pulled 0s (x10 over 81s) kubelet Container image "hashicorp/http-echo:0.2.3" already present on machine
Warning Failed 0s (x10 over 81s) kubelet Error: failed to generate security options for container "test-container": failed to generate seccomp security options for container: cannot load seccomp profile "/var/lib/kubelet/seccomp/allowall_syscall": open /var/lib/kubelet/seccomp/allowall_syscall: no such file or directory
删除pod。
root@k8scludes1:~/systemsafe# kubectl delete pod audit-pod
pod "audit-pod" deleted
root@k8scludes1:~/systemsafe# kubectl get pod
No resources found in systemsafe namespace.
在k8scludes3节点创建seccomp配置文件目录/var/lib/kubelet/seccomp/profiles。
root@k8scludes3:~# mkdir -p /var/lib/kubelet/seccomp/profiles
root@k8scludes3:~# cd /var/lib/kubelet/seccomp/profiles
root@k8scludes3:/var/lib/kubelet/seccomp/profiles# pwd
/var/lib/kubelet/seccomp/profiles
还是创建这三个文件。
root@k8scludes3:/var/lib/kubelet/seccomp/profiles# ls
allowall_syscall denyall_syscall fine-grained_syscall
再次创建audit-pod。
root@k8scludes1:~/systemsafe# kubectl apply -f pod2.yaml
pod/audit-pod created
这次pod创建成功。
root@k8scludes1:~/systemsafe# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
audit-pod 1/1 Running 0 14s 10.244.1.100 k8scludes3 <none> <none>
创建一个服务,服务类型为NodePort,服务端口为5678,关于服务service的详细操作,请查看博客《Kubernetes(k8s)服务service:service的发现和service的发布》。
root@k8scludes1:~/systemsafe# kubectl expose pod audit-pod --type NodePort --port 5678
service/audit-pod exposed
查看服务,5678端口映射为31163端口。
root@k8scludes1:~/systemsafe# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
audit-pod NodePort 10.107.213.89 <none> 5678:31163/TCP 9s app=audit-pod
访问svc ,访问方式为:物理机IP:端口。
#访问成功
root@k8scludes1:~/systemsafe# curl 192.168.110.128:31163
just made some syscalls!
删除pod。
root@k8scludes1:~/systemsafe# kubectl delete pod audit-pod
pod "audit-pod" deleted
root@k8scludes1:~/systemsafe# kubectl get pod
No resources found in systemsafe namespace.
5.2 配置seccomp禁止pod进行所有系统调用
编辑pod配置文件,在k8scludes3节点上创建pod,这次pod使用denyall_syscall文件。
localhostProfile: profiles/denyall_syscall指定pod使用denyall_syscall这个seccomp配置文件。
root@k8scludes1:~/systemsafe# vim pod2.yaml
root@k8scludes1:~/systemsafe# cat pod2.yaml
apiVersion: v1
kind: Pod
metadata:
name: audit-pod
labels:
app: audit-pod
spec:
securityContext:
seccompProfile:
type: Localhost
localhostProfile: profiles/denyall_syscall
#当需要关闭容器时,立即杀死容器而不等待默认的30秒优雅停机时长。
terminationGracePeriodSeconds: 0
#nodeSelector:yy: xx 表示pod运行在标签为yy=xx的节点上
nodeSelector:
yy: xx
containers:
- name: test-container
image: hashicorp/http-echo:0.2.3
#imagePullPolicy: IfNotPresent:表示如果本地已经存在该镜像,则不重新下载;否则从远程 Docker Hub 下载该镜像
imagePullPolicy: IfNotPresent
args:
- "-text=just made some syscalls!"
securityContext:
allowPrivilegeEscalation: false
创建pod。
root@k8scludes1:~/systemsafe# kubectl apply -f pod2.yaml
pod/audit-pod created
pod创建失败。
root@k8scludes1:~/systemsafe# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
audit-pod 0/1 CrashLoopBackOff 1 (5s ago) 7s 10.244.1.115 k8scludes3 <none> <none>
查看pod日志,因为禁止了所有系统调用,连日志都没有,pod也运行不起来。
root@k8scludes1:~/systemsafe# kubectl logs audit-pod
root@k8scludes1:~/systemsafe# kubectl get pod
NAME READY STATUS RESTARTS AGE
audit-pod 0/1 CrashLoopBackOff 5 (69s ago) 3m59s
删除pod。
root@k8scludes1:~/systemsafe# kubectl delete pod audit-pod
pod "audit-pod" deleted
root@k8scludes1:~/systemsafe# kubectl get pod
No resources found in systemsafe namespace.
5.3 配置seccomp允许pod进行50个系统调用
编辑pod配置文件,在k8scludes3节点上创建pod,这次pod使用fine-grained_syscall文件。
localhostProfile: profiles/fine-grained_syscall指定pod使用fine-grained_syscall这个seccomp配置文件。
fine-grained_syscall这个配置文件允许50个系统调用。
创建pod。
root@k8scludes1:~/systemsafe# vim pod2.yaml
#这次使用fine-grained_syscall文件
root@k8scludes1:~/systemsafe# grep localhostProfile pod2.yaml
localhostProfile: profiles/fine-grained_syscall
root@k8scludes1:~/systemsafe# kubectl apply -f pod2.yaml
pod/audit-pod created
pod创建成功。
root@k8scludes1:~/systemsafe# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
audit-pod 1/1 Running 0 6s 10.244.1.107 k8scludes3 <none> <none>
访问svc服务。
root@k8scludes1:~/systemsafe# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
audit-pod NodePort 10.107.213.89 <none> 5678:31163/TCP 16m
root@k8scludes1:~/systemsafe# curl 192.168.110.128:31163
just made some syscalls!
查看日志。
root@k8scludes1:~/systemsafe# kubectl logs audit-pod
2022/05/16 10:43:31 Server is listening on :5678
2022/05/16 10:44:17 192.168.110.128:31163 10.244.9.0:13880 "GET / HTTP/1.1" 200 25 "curl/7.58.0" 36.059µs
root@k8scludes1:~/systemsafe# tail -10f /var/log/syslog | grep 'http-echo'
^C
删除pod。
root@k8scludes1:~/systemsafe# kubectl delete pod audit-pod
pod "audit-pod" deleted
六.总结
通过使用Seccomp限制容器的系统调用,我们可以显著提高容器的安全性。在这篇博客中,我们学习了如何在Kubernetes环境中应用Seccomp来限制容器的系统调用。通过设置Seccomp配置文件并在Docker容器和Kubernetes Pod中应用该配置,我们可以有效地限制容器的权限,从而保护宿主机的安全。