kubernetes--安全上下文(Security Context)

Posted 弓长丿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kubernetes--安全上下文(Security Context)相关的知识,希望对你有一定的参考价值。

安全上下文(Security Context):

K8s对pod和容器提供的安全机制,可以设置Pod特权和访问控制

安全上下文限制维度:

1.自主访问控制((DiscretionaryAccess Control):

基于用户ID(UID)和组ID(GID),来判定对对象(例如文件)的访问权限

2.安全性增强的Linux(SELinux):

为对象赋予安全性标签

3.以特权模式或者非特权模式运行

4.Linux Capabilities:

为进程赋予root用户的部分特权而非全部特权

5.AppArmor:

定义使用AppArmor限制容器对资源访问限制

6.Seccomp:

定义pod使用Seccomp限制容器进程的系统调用

7. AllowPrivilegeEscalation:

禁止容器中进程(通过 SetUID 或 SetGID 文件模式)获得特权提升。当容器以特权模式运行或者具有CAP_SYS_ADMIN能力时,AllowPrivilegeEscalation总为True。

8. readOnlyRootFilesystem:

以只读方式加载容器的根文件系统。

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

【】capsh --print第一行为当前用户的

capability 名称

描述

CAP_AUDIT_CONTROL

启用和禁用内核审计;改变审计过滤规则;检索审计状态和过滤规则

CAP_AUDIT_READ

允许通过 multicast netlink 套接字读取审计日志

CAP_AUDIT_WRITE

将记录写入内核审计日志

CAP_BLOCK_SUSPEND

使用可以阻止系统挂起的特性

CAP_CHOWN

修改文件所有者的权限

CAP_DAC_OVERRIDE

忽略文件的 DAC 访问限制

CAP_DAC_READ_SEARCH

忽略文件读及目录搜索的 DAC 访问限制

CAP_FOWNER

忽略文件属主 ID 必须和进程用户 ID 相匹配的限制

CAP_FSETID

允许设置文件的 setuid 位

CAP_IPC_LOCK

允许锁定共享内存片段

CAP_IPC_OWNER

忽略 IPC 所有权检查

CAP_KILL

允许对不属于自己的进程发送信号

CAP_LEASE

允许修改文件锁的 FL_LEASE 标志

CAP_LINUX_IMMUTABLE

允许修改文件的 IMMUTABLE 和 APPEND 属性标志

CAP_MAC_ADMIN

允许 MAC 配置或状态更改

CAP_MAC_OVERRIDE

忽略文件的 DAC 访问限制

CAP_MKNOD

允许使用 mknod() 系统调用

CAP_NET_ADMIN

允许执行网络管理任务

CAP_NET_BIND_SERVICE

允许绑定到小于 1024 的端口

CAP_NET_BROADCAST

允许网络广播和多播访问

CAP_NET_RAW

允许使用原始套接字

CAP_SETGID

允许改变进程的 GID

CAP_SETFCAP

允许为文件设置任意的 capabilities

CAP_SETPCAP

参考 capabilities man page

CAP_SETUID

允许改变进程的 UID

CAP_SYS_ADMIN

允许执行系统管理任务,如加载或卸载文件系统、设置磁盘配额等

CAP_SYS_BOOT

允许重新启动系统

CAP_SYS_CHROOT

允许使用 chroot() 系统调用

CAP_SYS_MODULE

允许插入和删除内核模块

CAP_SYS_NICE

允许提升优先级及设置其他进程的优先级

CAP_SYS_PACCT

允许执行进程的 BSD 式审计

CAP_SYS_PTRACE

允许跟踪任何进程

CAP_SYS_RAWIO

允许直接访问 /devport、/dev/mem、/dev/kmem 及原始块设备

CAP_SYS_RESOURCE

忽略资源限制

CAP_SYS_TIME

允许改变系统时钟

CAP_SYS_TTY_CONFIG

允许配置 TTY 设备

CAP_SYSLOG

允许使用 syslog() 系统调用

CAP_WAKE_ALARM

允许触发一些能唤醒系统的东西(比如 CLOCK_BOOTTIME_ALARM 计时器)

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

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

1 Dockerfile里使用USER指定运行用户

2 K8s里指定spec.securityContext.runAsUser,指定容器默认用户UID

spec:

securityContext:

runAsUser: 1000 # 镜像里必须有这个用户UID

fsGroup: 1000 # 数据卷挂载后的目录属组设置为该组

containers:

-image: flask-demo:root (镜像自制即可)

name: web

securityContext:

allowPrivilegeEscalation: false # 不允许提权

方法1.Dockerfile

1)可以先注释USER看效果

【】cat /root/flask-demo/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

【】docker build -t flask-demo:v1 .

【】docker run -d --name demo-v1 -p 8080:8080 flask-demo:v1

【】docker exec -it demo-v1 bash

在宿主机查看也有该进程且为root

2)以普通账号运行

cat /root/flask-demo/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

【】docker build -t flask-demo:v2 .

【】docker run -d --name demo-v2 -p 8081:8080 flask-demo:v1

【】docker exec -it demo-v2 bash

方法2:K8s里指定spec.securityContext.runAsUser,指定容器默认用户UID

【】kubectl create deployment flask-demo --image=nginx --dry-run=client -o yaml >deployment.yaml

【】vim deploymeny.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

labels:

app: flask-demo

name: flask-demo

spec:

replicas: 1

selector:

matchLabels:

app: flask-demo

strategy:

template:

metadata:

creationTimestamp: null

labels:

app: flask-demo

spec:

securityContext:

runAsUser: 1000 # 镜像里必须有这个用户UID

fsGroup: 1000 # 数据卷挂载后的目录属组设置为该组

containers:

- image: flask-demo:v1 #上文创建的镜像,默认root权限

name: nginx

resources:

nodeName: "k8s-master1"

进入容器查看id

若使用镜像中不存在的用户则会创建一个普通账号

使用v2版镜像,默认以1000用户则不需要设置上下文即可,默认就是用户id为1000

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

背景:容器中有些应用程序可能需要访问宿主机设备、修改内核等需求(容器引擎已经组止了,测不出来),在默认情况下,容器没有这个能力,因此此时会考虑给容器是设置特权模式。

启用特权模式:

containers:

- image:flask-demo:root

name:web

securityContext:

privileged: true#启用特权

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

Linux Capabilities:是一个内核级别的权限,它允许对内核调用权限进行更细粒度的控制,而不是简单的以root身份能力授权。

Capabilities包括更改文件权限、控制网络子系统和执行系统管理等功能。在securityContext中,可以添加或删除Capabilities,做到容器精细化控制。

验证mount权限,默认无,截图为示列

【】cat tequan

apiVersion: v1

kind: Pod

metadata:

name: pod-sc1

spec:

containers:

-name: sc

image: busybox

command:

-sleep

-24h

securityContext:

privileged: true

【】kubectl exec -it pod-sc1 sh

示列1:容器默认没有挂载文件系统能力,添加SYS_ADMIN增加这个能力

容器默认无此能力,容器引擎以默认阻止

-t tmpfs 临时文件系统

apiVersion: v1
kind: Pod
metadata:
  name: pod-sc2
spec:
  containers:
  - name: test
    image: busybox
    command:
    - sleep
    -  24h
    securityContext:
      capabilities:
        add: ["SYS_ADMIN"]
       #drop:移除特权,可写all

也有这样用的,删除所有,添加指定项,类似于白名单

案列2:以只读挂载文件系统,防止恶意二进制文件创建

普通容器没限制的话可任意增删改查

apiVersion: v1
kind: Pod
metadata:
  name: Pod-sc3
spec:
  containers:
  - name: test
    image: busybox
    command:
    - sleep
    -  24h
    securityContext:
      readOnlyRootFilesystem: true

启动并进入容器

kubernetes使用securityContext和sysctl

前言

在运行一个容器时,有时候需要使用sysctl修改内核参数,比如net.vm.kernel等,sysctl需要容器拥有超级权限,容器启动时加上--privileged参数即可。那么,在kubernetes中是如何使用的呢?

Security Context

kubernetes中有个字段叫securityContext,即安全上下文,它用于定义Pod或Container的权限和访问控制设置。其设置包括:

  • Discretionary Access Control: 根据用户ID(UID)和组ID(GID)来限制其访问资源(如:文件)的权限

针对pod设置:

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo
spec:
  securityContext:
    runAsUser: 1000
    fsGroup: 2000
  volumes:
  - name: sec-ctx-vol
    emptyDir: 
  containers:
  - name: sec-ctx-demo
    image: gcr.io/google-samples/node-hello:1.0
    volumeMounts:
    - name: sec-ctx-vol
      mountPath: /data/demo
    securityContext:
      allowPrivilegeEscalation: false

针对container设置:

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo-2
spec:
  securityContext:
    runAsUser: 1000
  containers:
  - name: sec-ctx-demo-2
    image: gcr.io/google-samples/node-hello:1.0
    securityContext:
      runAsUser: 2000
      allowPrivilegeEscalation: false
  • Security Enhanced Linux (SELinux): 给容器指定SELinux labels
...
securityContext:
  seLinuxOptions:
    level: "s0:c123,c456"
  • Running as privileged or unprivileged:以privilegedunprivileged权限运行
apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo-4
spec:
  containers:
  - name: sec-ctx-4
    image: gcr.io/google-samples/node-hello:1.0
    securityContext:
      privileged: true
  • Linux Capabilities: 给某个特定的进程privileged权限,而不用给root用户所有的privileged权限
apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo-4
spec:
  containers:
  - name: sec-ctx-4
    image: gcr.io/google-samples/node-hello:1.0
    securityContext:
      capabilities:
        add: ["NET_ADMIN", "SYS_TIME"]
  • AppArmor: 使用程序文件来限制单个程序的权限

  • Seccomp: 限制一个进程访问文件描述符的权限

  • AllowPrivilegeEscalation: 控制一个进程是否能比其父进程获取更多的权限,AllowPrivilegeEscalation的值是bool值,如果一个容器以privileged权限运行或具有CAP_SYS_ADMIN权限,则AllowPrivilegeEscalation的值将总是true。

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo-2
spec:
  securityContext:
    runAsUser: 1000
  containers:
  - name: sec-ctx-demo-2
    image: gcr.io/google-samples/node-hello:1.0
    securityContext:
      runAsUser: 2000
      allowPrivilegeEscalation: false

注意:要开启容器的privileged权限,需要提前在kube-apiserverkubelet启动时添加参数--allow-privileged=true,默认已添加。

使用sysctl

sysctl -a可以获取sysctl所有参数列表。

从v1.4开始,kubernetes将sysctl分为safeunsafe,其对safe的sysctl定义如下:

  • 不会影响该节点的其他pod
  • 不会影响节点的正常运行
  • 不会获取超出resource limits范围的CPU和内存资源

目前属于safe sysctl的有:

  • kernel.shm_rmid_forced
  • net.ipv4.ip_local_port_range
  • net.ipv4.tcp_syncookies

其余的都是unsafe sysctl,当kubelet支持更好的隔离机制时,safe sysctl列表将在未来的Kubernetes版本中扩展。

使用safe sysctl例子:

apiVersion: v1
kind: Pod
metadata:
  name: sysctl-example
  annotations:
    security.alpha.kubernetes.io/sysctls: kernel.shm_rmid_forced=1
spec:
  ...

而使用unsafe sysctl时,需要在kubelet的启动参数中指定--experimental-allowed-unsafe-sysctls,如--experimental-allowed-unsafe-sysctls=net.core.somaxconn,具体操作如下:

编辑kubelet配置文件,修改ExecStart=/usr/bin/kubelet那一行,在后面加上--experimental-allowed-unsafe-sysctls=net.core.somaxconn,如:

ExecStart=/usr/bin/kubelet --experimental-allowed-unsafe-sysctls=net.core.somaxconn

因为我是用kubeadm安装的kubernetes,所以在/etc/systemd/system/kubelet.service.d/10-kubeadm.conf文件中加了倒数第3行内容:

[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true"
Environment="KUBELET_NETWORK_ARGS=--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin"
Environment="KUBELET_DNS_ARGS=--cluster-dns=10.96.0.10 --cluster-domain=cluster.local"
Environment="KUBELET_AUTHZ_ARGS=--authorization-mode=Webhook --client-ca-file=/etc/kubernetes/pki/ca.crt"
Environment="KUBELET_CADVISOR_ARGS=--cadvisor-port=0"
Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=systemd"
Environment="KUBELET_CERTIFICATE_ARGS=--rotate-certificates=true --cert-dir=/var/lib/kubelet/pki"
Environment="KUBELET_EXTRA_ARGS=--experimental-allowed-unsafe-sysctls=net.core.somaxconn"
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_AUTHZ_ARGS $KUBELET_CADVISOR_ARGS $KUBELET_CGROUP_ARGS $KUBELET_CERTIFICATE_ARGS $KUBELET_EXTRA_ARGS

重启kubelet:

systemctl daemon-reload
systemctl restart kubelet

在Pod中使用unsafe sysctl,开启privileged权限:

apiVersion: v1
kind: Pod
metadata:
  name: sysctl-example
  annotations:
    security.alpha.kubernetes.io/unsafe-sysctls: net.core.somaxconn=65535                 #使用unsafe sysctl,设置最大连接数
spec:
  securityContext:
    privileged: true                                                                      #开启privileged权限
  ...

总结

线上环境请谨慎使用privileged权限,使用不慎可能导致整个容器崩掉,相关信息可自行查阅。

参考:
https://kubernetes.io/docs/concepts/cluster-administration/sysctl-cluster/
https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

以上是关于kubernetes--安全上下文(Security Context)的主要内容,如果未能解决你的问题,请参考以下文章

kubernetes使用securityContext和sysctl

SYS_TIME 功能现在在 kubernetes 中工作

十一,k8s集群访问控制之ServicAccount

为多个 Kubernetes 上下文创建多个虚拟环境

Kubernetes:如何从 kubectl 配置中删除集群和上下文?

Kubernetes——安全认证