保障集群内节点和网络安全

保障集群内节点和网络安全

pod中使用宿主节点的Linux命名空间

部分pod(特别是系统pod)需要在宿主节点的默认命名空间中运行, 以允许它们看到和操作节点级别的资源和设备.

绑定宿主节点上的端口而不使用宿主节点的网络命名空间

这可以通过配置podspec.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, fsGroupsupplementGroup策略

如果需要限制容器可以使用的用户和用户组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
-------------本文结束感谢您的阅读-------------