Kubernetes 系统强化 Pod安全上下文

安全上下文(Security Context):K8s对Pod和容器提供的安全机制,可以设置Pod特权和访问控制。

背景:容器中的应用程序默认以root账号运行的,这个root与宿主机root账号是相同的, 拥有大部分对Linux内核的系统调用权限, 这样是不安全的, 所以我们应该将容器以普通用户运行,减少应用程序对权限的使用。 (容器是宿主机上面的进程,该进程有非常大的权限,容器只是在宿主机上面封装了状态,也是一个实际进程)
可以通过两种方法设置普通用户:
  • Dockerfile里使用USER指定运行用户
  • K8s里指定spec.securityContext.runAsUser,指定容器默认用户UID
[root@master ~]# cd flask-demo
[root@master flask-demo]# ls
Dockerfile  main.py  templates

#正常开发了网站程序,现在要将该网站程序容器化,第一步要写dockerfile制作镜像
#要基于某个镜像去制作镜像,一般基于java,或者操作系统centos 
#下面是基于官方的python镜像去制作,也就是将程序打包到我的镜像,然后再到镜像准备python应用的环境
[root@master flask-demo]# ls
Dockerfile  main.py  templates
[root@master flask-demo]# cat Dockerfile 
FROM python
#RUN useradd python
RUN mkdir /data/www -p
COPY . /data/www
#RUN chown -R python /data
RUN pip install flask -i https://mirrors.aliyun.com/pypi/simple/ && \
    pip install prometheus_client -i https://mirrors.aliyun.com/pypi/simple/
WORKDIR /data/www
#USER python
CMD python main.py 

现在将上面用户这些注释掉。先构造镜像将其跑起来

[root@master flask-demo]# docker build -t flask-demo .
[root@master flask-demo]# docker run -itd --name=demo -p 88:8080 flask-demo
66703f73e8e6f15b1cefe28c9c4f5dd65f3696a6382c79b7480e88df822bba94
[root@master flask-demo]# docker ps
CONTAINER ID   IMAGE                     COMMAND                  CREATED         STATUS         PORTS                                   NAMES
66703f73e8e6   flask-demo                "/bin/sh -c 'python ??   6 seconds ago   Up 5 seconds   0.0.0.0:88->8080/tcp, :::88->8080/tcp   demo


[root@master flask-demo]# curl localhost:88
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>棣.〉</title>
</head>
<body>

<h1>Hello Python!</h1>

</body>

可以看到业务可以访问,在构造镜像的时候应该设置为普通用户,这样可以减少里面的应用对linux内核系统调用的权限,阻断一些异常的系统调用。

[root@master flask-demo]# docker exec -it demo bash
root@66703f73e8e6:/data/www# id
uid=0(root) gid=0(root) groups=0(root)

uid=0的就具有Linux内核所有的操作权限

[root@master flask-demo]# docker exec -it demo bash
root@66703f73e8e6:/data/www# id
uid=0(root) gid=0(root) groups=0(root)

root@66703f73e8e6:/data/www# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 14:18 pts/0    00:00:00 /bin/sh -c python main.py
root         7     1  0 14:18 pts/0    00:00:00 python main.py
root         9     0  0 14:26 pts/1    00:00:00 bash
root        16     9  0 14:28 pts/1    00:00:00 ps -ef
root@66703f73e8e6:/data/www# ls
Dockerfile  main.py  templates
root@66703f73e8e6:/data/www# ls -l
total 12
-rw-r--r-- 1 root root  297 Jul  6 14:15 Dockerfile
-rw-r--r-- 1 root root  200 Jul  2 02:35 main.py
drwxr-xr-x 2 root root 4096 Jul  2 02:17 templates


#可以看到可以安装工具
root@66703f73e8e6:/data/www# apt-get install wget
Reading package lists... Done
Building dependency tree       
Reading state information... Done
wget is already the newest version (1.20.1-1.1).
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

在dockerfile里面指定用户,那么宿主机上面就应该先有这个用户。

FROM python
RUN useradd python
RUN mkdir /data/www -p
COPY . /data/www
RUN chown -R python /data
RUN pip install flask -i https://mirrors.aliyun.com/pypi/simple/ && \
    pip install prometheus_client -i https://mirrors.aliyun.com/pypi/simple/
WORKDIR /data/www
USER python
CMD python main.py

重新构建 

[root@master flask-demo]# docker build -t flask-demo .

[root@master flask-demo]# docker run -itd --name=demo1 -p 87:8080 flask-demo
b658c8b614eb7b903d3f9cca0351a8a3a652b7166804a8b3336114abb9f654c3
[root@master flask-demo]# docker exec -it demo1 bash
python@b658c8b614eb:/data/www$ id
uid=1000(python) gid=1000(python) groups=1000(python)
python@b658c8b614eb:/data/www$ ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
python       1     0  0 14:43 pts/0    00:00:00 /bin/sh -c python main.py
python       7     1  0 14:43 pts/0    00:00:00 python main.py
python       8     0  0 14:43 pts/1    00:00:00 bash
python      16     8  0 14:43 pts/1    00:00:00 ps -ef
python@b658c8b614eb:/data/www$ ls -l
total 12
-rw-r--r-- 1 python root  294 Jul  6 14:41 Dockerfile
-rw-r--r-- 1 python root  200 Jul  2 02:35 main.py
drwxr-xr-x 1 python root 4096 Jul  2 02:17 templates
  • RUN useradd python 先添加这个用户 USER python 这个用户必须系统当中包含,否则怎么帮你去设置这个用户?
  • 当容器起来的时候,被禁锢在了python用户的环境下,python和root区别在于uid是不一样的,这样就在权限方面是不一样的,权限非常有限。
  • 注意网站根目录也需要设置权限,要不然网站不能正常访问。

可以看到是以普通用户去运行镜像的。

python@b658c8b614eb:/data/www$ apt-get install wget
E: Could not open lock file /var/lib/dpkg/lock-frontend - open (13: Permission denied)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), are you root?

除了在dockefile里面去指定用户,还可以在securitycontext下面去指定。

案例1:设置容器以普通用户运行


背景:容器中的应用程序默认以root账号运行的,这个root与宿主机root账号是相同的, 拥有大部分对Linux内核的系统调用权限,这样是不安全的,所以我们应该将容器以普通用户运行,减少应用程序对权限的使用。

可以通过两种方法设置普通用户:
  • Dockerfile里使用USER指定运行用户
  • K8s里指定spec.securityContext.runAsUser,指定容器默认用户UID在这里只能指定ID,不能指定用户名了
[root@k8s-master ~]# cat flask-demo1.yaml 
apiVersion: v1
kind: Pod
metadata: 
  name: flask-1
spec:
  securityContext:
    runAsUser: 1000  # 镜像里必须有这个用户UID
    fsGroup: 1000    # 数据卷挂载后的目录属组设置为该组
  containers:
  - name: web 
    image: lizhenliang/flask-demo:root 
    volumeMounts:
    - name: tmp
      mountPath: /opt/data
  securityContext:
    allowPrivilegeEscalation: false # 不允许提权
    
  volumes: 
  - name: tmp
    emptyDir: {} 


[root@k8s-master ~]# kubectl get pod
NAME      READY   STATUS    RESTARTS   AGE
flask-1   1/1     Running   0          46s
[root@k8s-master ~]# kubectl exec -it flask-1  sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
$ id
uid=1000(python) gid=1000(python) groups=1000(python)

[root@k8s-master ~]# kubectl get pod
NAME      READY   STATUS    RESTARTS   AGE
flask-1   1/1     Running   0          9s
[root@k8s-master ~]# kubectl exec -it flask-1  sh
$ ls -l /opt/data 
total 0
$ ls -ld /opt/data
drwxrwsrwx 2 root python 6 Jul  8 20:17 /opt/data
$ id
uid=1000(python) gid=1000(python) groups=1000(python)

案例2:避免使用特权容器


背景:容器中有些应用程序可能需要访问宿主机设备、修改内核等需求,在默认情况下, 容器没这个有这个能力,因此这时会考虑给容器设置特权模式。

启用特权模式:
containers:
- image: lizhenliang/flask-demo:root
  name: web
  securityContext:
    privileged: true

启用特权模式就意味着,你要为容器提供了访问Linux内核的所有能力,这是很危险的,为了减少系统调用的供给,可以使用Capabilities为容器赋予仅所需的能力。

Linux Capabilities: Capabilities 是一个内核级别的权限,它允许对内核调用权限进行更细粒度的控制,而不是简单地以 root 身份能力授权。
Capabilities 包括更改文件权限、控制网络子系统和执行系统管理等功能。在securityContext 中,可以添加或删除 Capabilities,做到容器精细化权限控制。

          securityContext:
            allowPrivilegeEscalation: true
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
            # www-data -> 101
            runAsUser: 101
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值