Kubernetes 安全保障:Admission 控制器、安全上下文与网络策略
1. Admission 控制器的启用与禁用
在 Kubernetes 中,要查看哪些 Admission 控制器已启用,通常需要检查 Kubernetes API 服务器的配置。一般通过访问定义 API 服务器的配置文件来完成,该文件通常位于系统的配置目录中,或通过配置管理工具进行管理。查找
--enable-admission-plugins
标志,它指定了当前活动的 Admission 控制器列表。
例如,在 minikube 环境中,可按以下步骤操作:
1. 使用
minikube ssh
命令 SSH 进入 minikube VM。
2. 定位并检查
/etc/kubernetes/manifests/
目录下的
kube-apiserver.yaml
文件。
3. 使用
sudo cat /etc/kubernetes/manifests/kube-apiserver.yaml
查看其内容,并查找
--enable-admission-plugins
标志。
$ minikube ssh 'sudo grep -- '--enable-admission-plugins' /etc/kubernetes/manifests/kube-apiserver.yaml'
- --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota
若要修改已启用插件的列表,可使用文本编辑器(如
nano
或
vi
)编辑该文件,根据需要调整插件,然后保存更改。kubelet 会监视清单文件,若检测到清单文件有任何更改,将自动重启 API 服务器(重新创建 Pod)。
也可以按以下方式关闭默认的 Admission 控制器:
kube-apiserver --disable-admission-plugins=PodNodeSelector,AlwaysDeny ...
2. 常见的 Admission 控制器
Kubernetes 中的 Admission 控制器内置于 kube - apiserver 中,通常仅由集群管理员进行配置。其中,
MutatingAdmissionWebhook
和
ValidatingAdmissionWebhook
尤为显著。以下是常见的 Admission 控制器分类:
| 分类 | 控制器 |
| ---- | ---- |
| 基本控制 | AlwaysAdmit(已弃用)、AlwaysDeny(已弃用)、AlwaysPullImages |
| 默认设置 | DefaultStorageClass、DefaultTolerationSeconds |
| 安全相关 | DenyEscalatingExec、DenyServiceExternalIPs、PodSecurityPolicy、SecurityContextDeny |
| 资源管理 | LimitRanger、ResourceQuota、RuntimeClass |
| 对象生命周期 | NamespaceAutoProvision、NamespaceExists、NamespaceLifecycle、PersistentVolumeClaimResize、StorageObjectInUseProtection |
| 节点管理 | NodeRestriction、TaintNodesByCondition |
| 网络钩子 | MutatingAdmissionWebhook、ValidatingAdmissionWebhook |
| 其他 | EventRateLimit、LimitPodHardAntiAffinityTopology、OwnerReferencesPermissionEnforcement、PodNodeSelector(已弃用)、Priority、ServiceAccount |
3. Admission 控制器的优势
使用 Admission 控制器在 Kubernetes 集群中有诸多优势:
-
增强安全性
:通过实施安全策略(如 Pod 安全标准),Admission 控制器有助于保护集群免受未经授权或易受攻击的部署。
-
策略执行
:可以定义资源使用、镜像拉取等规则,Admission 控制器将自动执行这些规则。
-
一致性和标准化
:Admission 控制器确保集群中的资源遵循既定的最佳实践和配置。
4. 使用安全上下文保护 Pod 和容器
在 Kubernetes 中,
securityContext
定义了一组安全设置,用于确定 Pod 或容器在集群内的运行方式。其主要目的是通过定义 Pod 或容器在集群内的运行方式来增强 Kubernetes 集群的安全性。通过指定安全设置,可以确保应用程序遵循最小权限原则,减少恶意活动和意外配置错误的可能性。
以下是
securityContext
的关键组件及示例:
-
用户和组
:指定容器内进程运行的用户和组 ID,遵循最小权限原则。
apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: app-container
securityContext:
runAsUser: 1000 # Run container processes as user ID 1000
runAsGroup: 1000 # Run container processes as group ID 1000
- Linux 功能 :允许为容器授予特殊权限,而无需提供完整的根访问权限。
apiVersion: v1
kind: Pod
metadata:
name: privileged-container
spec:
containers:
- name: app-container
securityContext:
capabilities:
add:
- CAP_NET_ADMIN # Grant network management capabilities
-
特权模式
:默认情况下,容器以非特权模式运行。
securityContext提供了以特权模式运行容器的选项,但由于安全风险增加,应谨慎使用。
apiVersion: v1
kind: Pod
metadata:
name: privileged-container
spec:
containers:
- name: app-container
securityContext:
privileged: true # Run container in privileged mode (use cautiously)
- 只读根文件系统 :将容器的根文件系统挂载为只读,防止对基础系统进行意外或恶意修改。
apiVersion: v1
kind: Pod
metadata:
name: read-only-container
spec:
containers:
- name: app-container
securityContext:
readOnlyRootFilesystem: true # Mount root filesystem as read-only
5. 在 Pod 和容器级别应用安全上下文
securityContext
可以在 Pod 级别和容器级别应用,为应用程序的安全设置提供了灵活性。
-
Pod 级别安全上下文
:应用于 Pod 级别时,
securityContext
设置将被 Pod 内的所有容器继承,适用于设置统一的默认安全配置。
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
securityContext:
runAsUser: 1000 # All containers in the pod run as user ID 1000
runAsGroup: 1000 # All containers in the pod run as group ID 1000
containers:
- name: app-container
image: my-app-image
- name: sidecar-container
image: my-sidecar-image
-
容器级别安全上下文
:应用于容器级别时,
securityContext设置仅影响特定容器,允许对同一 Pod 内的不同容器进行更精细的安全配置。
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: app-container
image: my-app-image
securityContext:
runAsUser: 1000 # This container runs as user ID 1000
capabilities:
add: ["CAP_NET_ADMIN"] # Grant specific capabilities
- name: sidecar-container
image: my-sidecar-image
securityContext:
runAsUser: 2000 # This container runs as user ID 2000
readOnlyRootFilesystem: true # This container has a read-only root filesystem
6. 应用安全上下文到 Pod
以下示例创建一个具有只读根文件系统的 Pod,并指定非根用户和组 ID:
# pod-with-security-context.yaml
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
containers:
- name: app-container
image: nginx:latest
securityContext:
runAsUser: 1000 # Run container processes as user ID 1000
runAsGroup: 1000 # Run container processes as group ID 1000
readOnlyRootFilesystem: true # Mount the root filesystem as read-only
volumeMounts:
- name: html-volume
mountPath: /usr/share/nginx/html
volumes:
- name: html-volume
emptyDir: {} # Volume to provide writable space
创建 Pod:
$ kubectl apply -f pod-with-security-context.yaml
pod/security-context-demo created
验证安全上下文:
$ kubectl exec -it security-context-demo -- /bin/sh
~ $ id
uid=1000 gid=1000 groups=1000
~ $ touch /testfile
touch: /testfile: Read-only file system
7. 使用 NetworkPolicy 对象保护 Pod
NetworkPolicy
对象可在集群中直接定义网络防火墙。
7.1 为何需要 NetworkPolicy
在生产环境中管理 Kubernetes 工作负载时,会部署越来越多的应用程序,这些应用程序通常需要通过网络进行通信,因此需要使用防火墙来保障网络安全。Kubernetes 的
NetworkPolicy
就是这样一种网络防火墙实现。
7.2 NetworkPolicy 的好处
- 可以基于无类别域间路由(CIDR)块构建出口/入口规则。
- 可以基于 Pod 标签和选择器构建出口/入口规则。
- 可以基于命名空间构建出口/入口规则。
使用
NetworkPolicy
需要安装 CNI 插件,例如在使用
minikube
学习时,可以通过以下命令重新创建集群来集成 Calico 插件:
$ minikube start --network-plugin=cni --cni=calico --container-runtime=containerd
7.3 Pod 默认不隔离
在 Kubernetes 中,默认情况下 Pod 不隔离,任何 Pod 都可以无限制地访问其他 Pod。只有为 Pod 附加
NetworkPolicy
后,才会应用其中定义的规则。要使两个关联了网络策略的 Pod 能够通信,双方都必须开放相应规则,即 Pod A 必须有到 Pod B 的出口规则,Pod B 必须有来自 Pod A 的入口规则,否则流量将被拒绝。
8. 使用标签和选择器配置 NetworkPolicy
下面通过创建两个 nginx Pod 来演示如何使用标签和选择器配置
NetworkPolicy
。
8.1 创建命名空间和 Pod
创建
web1
命名空间和
nginx1
Pod:
# web1-app.yaml
---
apiVersion: v1
kind: Namespace
metadata:
labels:
project: web1
name: web1
---
apiVersion: v1
kind: Pod
metadata:
name: nginx1
namespace: web1
labels:
app: nginx1
spec:
containers:
- name: nginx1
image: nginx
创建
web2
命名空间和
nginx2
Pod:
# web2-app.yaml
---
apiVersion: v1
kind: Namespace
metadata:
labels:
project: web2
name: web2
---
apiVersion: v1
kind: Pod
metadata:
name: nginx2
namespace: web2
labels:
app: nginx2
spec:
containers:
- name: nginx2
image: nginx
创建资源并验证 Pod:
$ kubectl apply -f web1-app.yaml
namespace/web1 created
pod/nginx1 created
$ kubectl apply -f web2-app.yaml
namespace/web2 created
pod/nginx2 created
$ kubectl get po -o wide -n web1
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx1 1/1 Running 0 3m 10.244.120.71 minikube <none> <none>
$ kubectl get po -o wide -n web2
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx2 1/1 Running 0 2m53s 10.244.120.72 minikube <none> <none>
验证默认情况下网络流量是否允许:
$ kubectl -n web1 exec nginx1 -- curl 10.244.120.72
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 615 100 615 0 0 698k 0 --:--:-- --:--:-- --:--:-- 600k
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...<removed for brevity>...
8.2 阻止 web2 命名空间的所有入口流量
创建默认拒绝入口流量的策略:
# default-deny-ingress.yaml
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
spec:
podSelector: {}
policyTypes:
- Ingress
ingress: []
此 YAML 文件中:
-
podSelector: {}
:选择应用该
NetworkPolicy
的 Pod,这里选择命名空间中的所有 Pod。
-
policyTypes: - Ingress
:指定应用的策略类型为入口策略。
-
ingress: []
:表示没有定义具体的入口规则,即默认拒绝所有进入所选 Pod 的流量。
应用该策略:
$ kubectl apply -f default-deny-ingress.yaml -n web2
networkpolicy.networking.k8s.io/default-deny-ingress created
再次尝试访问
nginx2
Pod:
$ kubectl -n web1 exec nginx1 -- curl 10.244.120.72
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- 0:02:15 --:--:-- 0
curl: (28) Failed to connect to 10.244.120.72 port 80 after 135435 ms: Couldn't connect to server
command terminated with exit code 28
可以看到流量已被拒绝。
8.3 允许来自 web1 命名空间的流量
创建允许来自
web1
命名空间流量的策略:
# allow-from-web1-netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-web1-netpol
namespace: web2
spec:
podSelector:
matchLabels:
app: nginx2
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
project: web1
- podSelector:
matchLabels:
app: nginx1
ports:
- protocol: TCP
port: 80
应用该策略:
$ kubectl apply -f allow-from-web1-netpol.yaml
networkpolicy.networking.k8s.io/nginx2-networkpolicy created
再次尝试访问
nginx2
Pod:
$ kubectl -n web1 exec nginx1 -- curl 10.244.120.72
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 615 100 615 0 0 1280k 0 --:--:-- --:--:-- --:--:-- 600k
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...<removed for brevity>...
此时可以正常访问。
总结
通过使用 Admission 控制器、安全上下文和
NetworkPolicy
,可以显著增强 Kubernetes 集群的安全性。Admission 控制器可以帮助实施安全策略和资源管理规则;安全上下文可以限制 Pod 和容器的权限;
NetworkPolicy
可以控制 Pod 之间的网络流量。在实际应用中,应根据具体需求合理配置这些安全机制。
下面用 mermaid 流程图展示整个安全配置流程:
graph LR
A[开始] --> B[配置Admission控制器]
B --> C[启用或禁用控制器]
C --> D[配置安全上下文]
D --> E[Pod级别配置]
D --> F[容器级别配置]
E --> G[应用到Pod]
F --> G
G --> H[配置NetworkPolicy]
H --> I[创建命名空间和Pod]
I --> J[设置默认拒绝策略]
J --> K[设置允许特定流量策略]
K --> L[验证网络流量]
L --> M[结束]
通过以上步骤和配置,能够构建一个安全可靠的 Kubernetes 环境。
超级会员免费看

被折叠的 条评论
为什么被折叠?



