在kubernetes里使用seccomp限制容器的系统调用

kubernetes,seccomp · 浏览次数 : 7

小编点评

Sure, here's the content with simple indentation: ``` -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 createdpod创建失败。root@k8scludes1:~/systemsafe# kubectl get pod -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESaudit-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 AGEaudit-pod 0/1 CrashLoopBackOff 5 (69s ago) 3m59s删除pod。root@k8scludes1:~/systemsafe# kubectl delete pod audit-pod pod "audit-pod" deletedroot@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 createdpod创建成功。root@k8scludes1:~/systemsafe# kubectl get pod -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESaudit-pod 1/1 Running 0 6s 10.244.1.107 k8scludes3 <none> <none>访问svc服务。 root@k8scludes1:~/systemsafe# kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEaudit-pod NodePort 10.107.213.89 <none> 5678:31163/TCP 16mroot@k8scludes1:~/systemsafe# curl 192.168.110.128:31163just made some syscalls!查看日志。 root@k8scludes1:~/systemsafe# kubectl logs audit-pod 2022/05/16 10:43:31 Server is listening on :56782022/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限制容器的系统调用,我们可以显著提高容器的安全性。 ```

正文

一.系统环境

本文主要基于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中应用该配置,我们可以有效地限制容器的权限,从而保护宿主机的安全。

与在kubernetes里使用seccomp限制容器的系统调用相似的内容:

在kubernetes里使用seccomp限制容器的系统调用

在kubernetes里使用seccomp限制容器的系统调用,Secure Computing Mode,系统调用,使用seccomp限制docker容器系统调用,strace -fqc,SCMP_ACT_ALLOW,SCMP_ACT_LOG,SCMP_ACT_ERRNO,配置seccomp允许po...

在kubernetes里使用AppArmor限制容器对资源的访问

在kubernetes里使用AppArmor限制容器对资源的访问,AppArmor,强制访问控制(MAC),SELinux,使用AppArmor限制nginx程序访问目录,complain模式,enforce模式,aa-autodep,aa-logprof,aa-complain,aa-enforc...

使用 Kubeadm 部署 Kubernetes(K8S) 安装 -- Ingress-Ngnix

前置条件:使用 Kubeadm 部署 Kubernetes(K8S) 安装 安装ingress-nginx组件(在master节点执行) 通过 ip+port 号进行访问,使用 Service 里的 NodePort 实现,把端口对外暴露 缺陷:一个端口只能使用一次,一个端口对应一个应用,实际使用中

使用K8S进行蓝绿部署的简明实操指南

在之前的应用部署系列文章里,我们已经介绍过什么是蓝绿部署。如需回顾,点击下方文章链接即可重温。本文我们将会介绍如何使用 Kubernetes 实现蓝绿部署。 应用部署初探:3个主要阶段、4种常见模式 应用部署初探:微服务的3大部署模式 应用部署初探:6个保障安全的最佳实践 前期准备: Kuberne

如何使用 Blackbox Exporter 监控 URL?

如何在 Kubernetes 中使用 Blackbox Exporter 与 Prometheus 进行 URL 监控采集、展示和告警。

如何在 K8S 集群范围使用 imagePullSecret?

在这篇文章中,我将向你展示如何在 Kubernetes 中使用 imagePullSecrets。

使用Kubernetes中的Nginx来改善第三方服务的可靠性和延迟

使用Kubernetes中的Nginx来改善第三方服务的可靠性和延迟 译自:How we improved third-party availability and latency with Nginx in Kubernetes 本文讨论了如何在Kubernetes中通过配置Nginx缓存来提升第

使用Helm部署Wikijs

使用 Helm 部署 Wiki.js 📚️ 参考文档: Wiki.js 官方文档 - 安装 - Kubernetes Wiki.js 使用 Helm 安装 Wiki.js 官方文档 - 安装 - 侧加载 官方教程 Kubernetes 开始使用 Helm Chart 在 Kubernetes 上安

推荐工具!使终端便于 DevOps 和 Kubernetes 使用

本文将为您推荐帮助用户在 DevOps和 Kubernetes 中从容浏览终端的优秀工具。

使用 Helm 安装 MQTT 服务器-EMQX

EMQX ℹ️ Info: 使用 EMQX 通过 Helm3 在 Kubernetes 上部署 EMQX 4.0 集群 | EMQ emqx/deploy/charts/emqx at main-v4.4 · emqx/emqx (github.com) emqx/values.yaml at ma