- 一.系統環境
- 二.前言
- 三.系統呼叫簡介
- 四.使用seccomp限制docker容器系統呼叫
- 五.在kubernetes裡使用seccomp限制容器的系統呼叫
- 5.1 配置seccomp允許pod進行所有系統呼叫
- 5.2 配置seccomp禁止pod進行所有系統呼叫
- 5.3 配置seccomp允許pod進行50個系統呼叫
- 六.總結
一.系統環境
本文主要基於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中應用該配置,我們可以有效地限制容器的許可權,從而保護宿主機的安全。