保障集群内节点和网络安全
在pod中使用宿主节点的Linux命名空间
部分pod(特别是系统pod)需要在宿主节点的默认命名空间中运行, 以允许它们看到和操作节点级别的资源和设备.
绑定宿主节点上的端口而不使用宿主节点的网络命名空间
这可以通过配置pod的spec.containers.ports字段中某个容器某一个端口的hostPort属性来实现.
如果一个pod绑定了宿主节点上的一个特定端口, 每个宿主节点只能调度一个这样的pod实例, 因为两个进程不能绑定宿主机上的同一个端口. 调度器在调度pod时会考虑这一点, 所以它不会把这样的两个pod调度到同一个节点上.
1 2 3 4 5 6 7 8
| spec: containers: - image: some/image name: <pod的名称> ports: - containerPort: 8080 hostPort: 9000 protocol: TCP
|
hostPort功能最初是用于暴露通过DeamonSet部署在每个节点上的系统服务的.
配置节点的安全上下文
安全上下文中可配置的内容:
- 指定容器中运行进程的用户(用户
ID)
- 阻止容器使用
root用于运行(容器的默认运行用户通常在其镜像中指定, 所以可能需要阻止容器以root用户运行)
- 使用特权模式运行容器, 使其对宿主节点的内核具有完全的访问权限
- 与以上相反, 通过添加或禁用内容功能, 配置细粒度的内核访问权限
- 设置
SELinux选项, 加强对容器的限制
- 阻止进程写入容器的根文件系统
使用指定用户运行容器
1 2 3 4 5 6 7
| spec: containers: - name: main image: alpine command: ["/bin/sleep", "999999"] securityContext: runAsUser: 405
|
阻止容器以root用户运行
1 2 3 4 5 6 7
| spec: containers: - name: main image: alpine command: ["/bin/sleep", "999999"] securityContext: runAsNonRoot: true
|
使用特权模式运行pod
1 2 3 4 5 6 7
| spec: containers: - name: main image: alpine command: ["/bin/sleep", "999999"] securityContext: privileged: true
|
为容器单独添加内核功能
相比于让容器运行在特权模式下以给予其无限的权限, 一个更加安全地做法是只给予它使用真正需要的内核功能的权限. Kubernetes允许为特定的容器添加内核功能, 或禁止部分内核功能, 以允许对容器进行更加细致的权限控制, 限制攻击者潜在侵入的影响.
1 2 3 4 5 6 7 8
| spec: containers: - name: main image: alpine command: ["/bin/sleep", "999999"] securityContext: add: - SYS_TIME
|
在容器中禁用内核功能
1 2 3 4 5 6 7 8
| spec: containers: - name: main image: alpine command: ["/bin/sleep", "999999"] securityContext: drop: - CHOWN
|
阻止对容器跟文件系统的写入
1 2 3 4 5 6 7
| spec: containers: - name: main image: alpine command: ["/bin/sleep", "999999"] securityContext: readOnlyRootFilesystem: true
|
容器使用不同用户时共享存储卷
1 2 3 4
| spec: securityContext: fsGroup: 555 supplementalGroups: [666, 777]
|
限制pod使用安全相关的特性
PodSecurityPolicy资源介绍
PodSecuriyPolicy是一种集群级别(无命名空间)的资源, 它定义了用户能否在pod中使用各种安全相关的特性. 维护PodSecurityPolicy资源中配置策略的工作由集成在API服务器中的PodSercurityPolicy准入控制插件完成.
PodSecurityPolicy可以做的事
- 是否允许
pod使用宿主节点的PID, IPC, 网络命名空间
pod允许绑定的宿主节点的端口
- 容器运行时允许使用的用户
ID
- 是否允许拥有特权模式容器的
pod
- 允许添加哪些内核功能, 默认添加哪些内核功能, 总是禁用哪些内核功能
- 允许容器使用哪些
SELinux选项
- 容器是否允许使用可写的根文件系统
- 允许容器在哪些文件系统组下运行
- 允许
pod使用哪些类型的存储卷
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| apiVersion: extensions/v1beta1 kind: PodSecurityPolicy metadata: name: default spec: hostIPC: false hostPID: false hostNetwork: false hostPorts: - min: 10000 max: 11000 - min: 13000 max: 14000 privileged: false readOnlyRootFilesystem: true runAsUser: rule: RunAsAny fsGroup: rule: RunAsAny supplementalGroups: rule: RunAsAny seLinux: rule: RunAsAny volumes: - '*'
|
了解runAsUser, fsGroup和supplementGroup策略
如果需要限制容器可以使用的用户和用户组ID, 可以将规则改为MustRunAs, 并指定允许使用的ID范围.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| runAsUser: rule: MustRunAs ranges: - min: 2 max: 2 fsGroup: rule: MustRunAs ranges: - min: 2 max: 10 - min: 20 max: 30 supplementalGroups: rule: MustRunAs ranges: - min: 2 max: 10 - min: 20 max: 30
|
如果pod spec试图将其中的任一字段设置为该范围之外的值, 这个pod将不会被API服务器接收.
部署镜像中用户ID在指定范围之外的pod
PodSecurityPolicy会将硬编码覆盖到镜像中的用户ID.
在runAsUser字段中使用mustRunAsNonRoot规则
runAsUser字段中还可以使用另一种规则: mustRunAsNonRoot. 它将阻止用户部署以root用户运行的容器. 在这种情况下, spec容器中必须指定runAsUser字段, 并且不能为0, 或者容器的镜像本身指定了一个用非0的用户ID运行.
配置允许, 默认添加, 禁止使用的内核功能
1 2 3 4 5 6 7 8 9 10
| apiVersion: extensions/v1beta1 kind: PodSecurityPolicy spec: allowedCapabilities - SYS_TIME defaultAddCapabilities - CHOWN requiredDropCapabilities - SYS_ADMIN - SYS_MODULES
|
对不同的用户与组分配不同的PodSecurityPolicy
PodSecurityPolicy是集群级别的资源, 这意味着它不能存储和应用在某一特定的命名空间上. 对不同用户分配不同PodSecurityPolicy是通过RBAC机制实现的. 这个方式是, 创建你需要的PodSecurityPolicy资源, 然后创建ClusterRole资源并通过名称将它们指向不同的策略, 以此使PodSecurityPolicy资源中的策略对不同的用户或组生效. 通过ClusterRoleBinding资源将特定的用户组绑定到ClusterRole上, 当PodSecurityPolicy访问控制插件需要决定是否接纳一个pod时, 它只会考虑创建pod的用户可以访问到的PodSecurityPolicy中的策略.
隔离pod的网络
一个NetworkPolicy会应用在匹配它的标签选择器的pod上, 指明这些允许访问这些pod的源地址, 或这些pod可以访问的目标地址. 这些分别由入向ingress和出向egress规则指定. 这两种规则都可以匹配由标签选择器选出的pod, 或者一个namespace中的所有pod, 或者通过无类别域间路由(CIDR)指定的IP地址段.
在一个命名空间中阻止所有访问
1 2 3 4 5 6
| apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny spec: podSelector:
|
空的标签选择器匹配命名空间中的所有pod.
允许同一命名空间中的部分pod访问一个服务端pod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: postgres-netpolicy spec: podSelector: matchLabels: app: database ingress: - from: - podSelector: matchLabels: app: webserver ports: - port: 5432
|
在不同Kubernetes命名空间之间进行网络隔离
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: shoppingcart-netpolicy spec: podSelector: matchLabels: app: shopping-cart ingress: - from: - namespaceSelector: matchLabels: tenant: manning ports: - port: 80
|
使用CIDR隔离网络
1 2 3 4
| ingress: - from: - ipBlock: cidr: 192.168.1.0/24
|
限制pod的对外访问流量
1 2 3 4 5 6 7 8 9
| spec: podSelector: matchLabels: app: webserver egress: - to: - podSelector: matchLabels: app: database
|