配置容器級別的安全控制
使用宿主機的網絡模式
可以通過設置pod的spec的hostNetwork參數為true開啟容器的“host”network模式
spec:
hostNetwork: true
containers:
- name: name
image: Enter containers image
綁定宿主機的端口
這種方式不需要創建service來做port映射,相當於docker中的-p映射端口的操作
spec:
containers:
- name: name
image: Enter containers image
ports:
# 容器內部的端口
- containerPort: 8080
# 映射在宿主機上的端口
hostPort: 9000
protocol: TCP
使用宿主機的PID和IPC命名空間
通過開啟pod的spec.hostPID使用宿主機的pid,同樣通過開始hostIPC使用宿主機的ipc
spec:
hostPID: true
hostIPC: true
containers:
- name: name
image: Enter containers image
將hostPID設置為true,pod內就可以看到宿主機上的所有進程pid,同時自己的進程也會有宿主機管理。
將hostIPC設置為true,pod中的進程就可以與宿主機上的其他所有進程進行通信。
配置pod的安全上下文
針對於container級別的控制
指定運行容器的用戶
spec:
containers:
- name: name
image: Enter containers image
securityContext:
# 405為容器中用戶的id,這里僅可以通過id指定運行容器的用戶
runAsUser: 405
阻止容器以root用戶運行
有的應用在容器中設置了運行用戶,然后可能會有黑客上傳一個以root用戶運行的鏡像到我們的鏡像倉庫。然后在容器中利用root用戶
的權限,這樣是很危險的,所以我們可以禁用容器中的root用戶,讓他不能以root用戶啟動容器
spec:
containers:
- name: name
image: Enter containers image
securityContext:
runAsNonRoot: true
使用特權模式啟動容器
使容器具有宿主機上的所有操作權限,這樣容器中就可以使用宿主機上的設備了
spec:
containers:
- name: name
image: Enter containers image
securityContext:
privileged: true
為容器添加linux內核的功能
使用特權模式啟動的容器被賦予了過大的權限,我們可以根據需求給予容器所需的linux內核的能力。
spec:
containers:
- name: name
image: Enter containers image
securityContext:
# 通過capabilities開啟或者禁用linux的內核功能
capabilities:
# 授予容器能力
add:
- SYS_TIME
# 禁用容器能力
drop:
- CHOWN
注意:在linux中內核功能通常以CAP_開頭,這里需要省略掉
阻止容器對根目錄的寫入
spec:
containers:
- name: test-container
image: test-container
imagePullPolicy: IfNotPresent
securityContext:
# 這個容器的根目錄不允許寫入操作
readOnlyRootFilesystem: true
volumeMounts:
# 但是允許向volume目錄寫入,這個目錄是一個掛載卷
- mountPath: /volume
name: test-volume
readOnly: false
volumes:
- name: test-volume
emptyDir: {}
問題:如果不采用掛載的方式,可否將一個目錄釋放出來允許寫入呢?
pod級別的安全上下文
容器使用不同用戶運行時共享存儲卷
當一個pod中的兩個容器都使用root用戶運行時,他們之前可以互相讀取對方的掛載卷。但是,當我們為每個容器配置其他的啟動用戶時,
可以會出現一些訪問權限的問題。
在kubernetes中,可以為pod中的容器指定一個supplemental組,以允許他們無論通過哪個用戶啟動容器都可以共享文件。
spec:
securityContext:
# 用戶組id設置為555,則創建存儲卷時存儲卷屬於用戶ID為555的用戶組
fsGroup: 555
# 定義了某個用戶所關聯的額外的用戶組
supplementalGroups:
- 666
- 777
containers:
- name: test-A
image: test-container
imagePullPolicy: IfNotPresent
securityContext:
runAsUser: 01
volumeMounts:
- mountPath: /volume
name: test-volume
readOnly: false
- name: test-B
image: test-container
imagePullPolicy: IfNotPresent
securityContext:
runAsUser: 02
volumeMounts:
- mountPath: /volume
name: test-volume
readOnly: false
volumes:
- name: test-volume
emptyDir: {}
在pod級別指定fsGroup與supplementalGroups屬性,然后分別指定兩個容器的啟動用戶為01、02。然后在啟動容器,在容器中執行id
命令
可以查看容器的用戶和用戶組,然后就可以看到兩個容器雖然用戶不同,但是都屬於“555、666、777”這三個組中。
統一限制pod的安全相關特性 PodSecurityPolicy
PodSecurityPolicy在kubernetes中簡稱為psp,主要定義了用戶能否在pod中使用各種安全相關的特性。
當有人調用api server創建pod時,PodSecurityPolicy會拿到這個pod的信息與自己個規則做比較。如果符合規則,就運行其存入etcd;否則會被拒絕。
因為是在創建pod時校驗的,所以修改psp,不會對已創建的pod采取措施。也可以設置默認值,就是用psp中配置的默認值替換掉pod中的值。
主要提供了以下能力:
- 是否允許pod使用宿主節點的PID、IPC、網絡命名空間
- pod允許綁定的宿主節點端口
- 容器運行時允許使用的用戶ID
- 是否允許擁有特權模式容器的pod
- 允許添加哪些內核功能, 默認添加哪些內核功能, 總是禁用哪些內核功能
- 允許容器使用哪些 SELinux 選項
- 容器是否允許使用可寫的根文件系統
- 允許容器在哪些文件系統組下運行
- 允許pod使用哪些類型的存儲卷
以下為demo:
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: exporter-node-cluster-monitoring
spec:
allowPrivilegeEscalation: false
# 強制使用只讀的根文件系統
readOnlyRootFilesystem: true
# 不允許使用特權方式運行容器
privileged: false
allowedHostPaths:
- pathPrefix: /
readOnly: true
# 指定容器可以使用的用戶組id范圍
fsGroup:
ranges:
- max: 65535
min: 1
rule: MustRunAs
supplementalGroups:
ranges:
- max: 65535
min: 1
rule: MustRunAs
# 允許使用宿主機的網絡命名空間
hostNetwork: true
# 允許使用宿主機的PID
hostPID: true
# 允許使用宿主機的IPC
hostIPC: true
# 只允許綁定宿主機的9796端口,和1000~1080的端口
hostPorts:
- max: 9796
min: 9796
- max: 1000
min: 1080
# 可以使用任意用戶運行
runAsUser:
rule: RunAsAny
# 可以使用seLinux的任意規則
seLinux:
rule: RunAsAny
# 支持的掛載方式
volumes:
- configMap
- emptyDir
- projected
- secret
- downwardAPI
- persistentVolumeClaim
- hostPath
配置允許、默認添加、禁用內核功能
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: exporter-node-cluster-monitoring
spec:
# 允許容器添加SYS_TIME功能
allowedCapabilities:
- SYS_TIME
# 為每個容器添加CHOWN能力
defaultAddCapabilities:
- CHOWN
# 要求容器禁用SYS_ADMIN和SYS_MODULE
requiredDropCapabilities:
- SYS_ADMIN
- SYS_MODULE
利用RBAC分配PodSecurityPolicy
psp屬於集群級別的資源,所以默認是作用於整個集群的。但是我們有時候只需要針對某些應用采用這些設置。可以通過創建一個ClusterRole然后將其
指向一個psp,再通過使用ClusterRoleBinding到不同的用戶,這樣的話這個psp的規則就只作用於這個用戶創建的pod了。
kubectl create clusterrole psp -privileged --verb=use --resource=podsecuritypolicies --resource-name=privileged
注意:這里的verb采用的是use
然后再將這個clusterrole綁定到用戶或者用戶組上就可以了
pod間的訪問隔離
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: networkPolicy-demo
spec:
# 允許可以訪問哪些pod
# 當標簽中為空時,表示不允許任何pod訪問
podSelector:
配置同一命名空間(foo)下的相互訪問權限
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: networkPolicy-demo
namespace: foo
spec:
# 允許哪些pod可以訪問當前命名空間中的pod
podSelector:
matchLabels:
app: mysql
ingress:
- from:
# 允許哪個pod可以訪問
- podSelector:
matchLabels:
app: service-a
# 允許被訪問的pod
- ports:
- 3306
配置跨命名空間的訪問權限
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: networkPolicy-demo
namespace: foo
spec:
# 允許哪些pod可以訪問當前命名空間中的pod
podSelector:
matchLabels:
app: service-b
ingress:
- from:
# 允許帶有標簽為(tenant=service-a)的命名空間中的pod訪問
- namespaceSelector:
matchLabels:
tenant: service-a
- ports:
- 80
可以通過網段限制進入的流量
ingress:
- from:
# 值允許來自ip端為192.168.1.0/24的流量
- ipBlock:
cidr: 192.168.1.0/24
- ports:
- 3306
限制pod流出流量
spec:
podSelector:
matchLabels:
app: service-b
egress:
- to:
# 只允許流量流出到標簽為(app=service-c)的pod
- podSelector:
matchLabels:
app: service-c