Kubernetes 安全:认证、授权与准入控制详解
1. Kubernetes 认证方法
Kubernetes 采用了多种认证方法,其中引导令牌(bootstrap tokens)是一种特殊的认证方式。它并非用于常规认证,而是专门针对集群节点。引导令牌是 Kubernetes 中的一种特殊秘密类型,存储在
kube-system
命名空间中。这些短期有效的令牌允许 API 服务器在初始连接时对节点上运行的 kubelet 进行认证,简化了新节点加入集群或从头创建新集群的过程。它可以与
kubeadm
工具配合使用,也可以独立使用,并且能与 Kubelet TLS 引导无缝协作,实现安全通信。若想了解引导令牌认证和 TLS 引导的详细信息,可参考文档(https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens)。
在某些特殊情况下,当你希望集成组织中 Kubernetes 原生不支持的现有身份提供者时,可能需要使用认证代理和 Webhook 令牌认证方法。
2. 认证与授权概述
Kubernetes 的安全依赖于两个关键过程:认证和授权。认证用于验证试图访问系统的用户身份,通常通过检查用户名、密码或令牌等凭证来实现。成功认证后,授权开始发挥作用,它决定了用户在系统中可以执行的操作。在 Kubernetes 中,API 服务器会评估用户身份(通过认证获得)以及其他请求属性,如特定的 API 端点或请求的操作。基于预定义的策略或外部服务,授权模块决定是否允许该请求。
在 Kubernetes API 服务器中,对请求进行认证会产生一组额外的请求属性,如用户、组、API 请求动词、HTTP 请求动词等。这些属性随后会传递给授权模块,授权模块根据这些属性判断用户是否被允许执行该操作。如果请求被任何一个模块拒绝,用户将收到 HTTP 状态码 403(禁止访问)。
3. Kubernetes 授权模式
Kubernetes 提供了多种授权模式,可在启动 Kubernetes API 服务器时使用
authorization-mode
参数启用,示例配置如下:
# /etc/kubernetes/manifests/kube-apiserver.yaml
...<removed for brevity>...
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=192.168.59.154
- --allow-privileged=true
- --authorization-mode=Node,RBAC
...<removed for brevity>...
Kubernetes 中的授权模式包括:
| 授权模式 | 说明 |
| ---- | ---- |
| RBAC(基于角色的访问控制) | 允许使用角色和权限来组织访问控制和管理,是访问管理的行业标准之一。角色可以分配给系统中的用户,赋予他们特定的权限和访问权限,可实现细粒度的访问管理,遵循最小权限原则。在 Kubernetes 中,RBAC 是允许式的,默认拒绝所有操作,需要定义允许规则。 |
| Attribute-Based Access Control(ABAC,基于属性的访问控制) | 使用基于用户、资源和环境属性的策略,是一种细粒度的访问控制方法。在 Kubernetes 中,通过策略对象进行建模。 |
| Node | 一种特殊用途的授权模式,用于授权集群中 kubelet 发出的 API 请求。 |
| Webhook | 类似于用于认证的 Webhook,可定义一个外部服务来处理 Kubernetes API 服务器发送的包含
SubjectAccessReview
对象的 HTTP POST 请求,该服务需处理请求并确定是否允许该请求。 |
| AlwaysAllow | 授予所有请求不受限制的访问权限,仅适用于测试环境。 |
| AlwaysDeny | 阻止所有请求,仅用于测试目的,以建立授权的基线。 |
目前,由于 RBAC 的灵活性和易于管理,它被认为是 Kubernetes 中的行业标准,下面将详细介绍 RBAC 模式。
4. Kubernetes 中的 RBAC 模式
在 Kubernetes 中使用 RBAC 涉及属于
rbac.authorization.k8s.io
API 组的以下类型的 API 资源:
-
Role 和 ClusterRole
:定义一组权限。
Role
中的每个规则指定了允许对哪些 API 资源执行哪些动词。
Role
是命名空间作用域的,而
ClusterRole
是全局的。
-
RoleBinding 和 ClusterRoleBinding
:将用户或一组用户(也可以是组或服务账户)与给定的角色关联起来。
RoleBinding
是命名空间作用域的,而
ClusterRoleBinding
是集群范围的。需要注意的是,
ClusterRoleBinding
与
ClusterRole
配合使用,而
RoleBinding
可以与
ClusterRole
和
Role
配合使用。
这些 Kubernetes 对象可以使用
kubectl
和 YAML 清单进行管理,就像管理 Pod、服务等一样。下面通过一个实际示例来演示如何使用 RBAC:
1.
创建专用命名空间
:
- 创建 YAML 文件
02_rbac/rbac-demo-ns.yaml
:
---
apiVersion: v1
kind: Namespace
metadata:
name: rbac-demo-ns
- 应用 YAML 文件创建命名空间:
$ kubectl apply -f 02_rbac/rbac-demo-ns.yaml
namespace/rbac-demo-ns created
- 创建示例 nginx Pod :
$ kubectl apply -f 02_rbac/nginx-pod.yaml
pod/nginx-pod created
-
创建服务账户
:
-
创建 YAML 清单
02_rbac/pod-logger-serviceaccount.yaml:
-
创建 YAML 清单
apiVersion: v1
kind: ServiceAccount
metadata:
name: pod-logger
namespace: rbac-demo-ns
- 应用清单到集群:
$ kubectl apply -f 02_rbac/pod-logger-serviceaccount.yaml
serviceaccount/pod-logger created
-
创建角色
:
-
创建名为
pod-reader的角色,该角色只允许对 Kubernetes RESTful API 中的pods资源执行get、watch和list操作。创建02_rbac/pod-reader-role.yaml文件:
-
创建名为
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: rbac-demo-ns
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
- 应用清单到集群:
$ kubectl apply -f 02_rbac/pod-reader-role.yaml
role.rbac.authorization.k8s.io/pod-reader created
-
创建 Pod
:
-
创建 YAML 清单
02_rbac/pod-logger-app.yaml,用于创建一个运行在pod-logger服务账户下的 Pod:
-
创建 YAML 清单
apiVersion: v1
kind: Pod
metadata:
name: pod-logger-app
namespace: rbac-demo-ns
spec:
serviceAccountName: pod-logger
containers:
- name: logger
image: quay.io/iamgini/k8sutils:debian12
command:
- /bin/sh
- -c
- |
SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
TOKEN=$(cat ${SERVICEACCOUNT}/token)
while true
do
echo "Querying Kubernetes API Server for Pods in default namespace..."
curl --cacert $SERVICEACCOUNT/ca.crt --header "Authorization: Bearer $TOKEN" -X GET https://kubernetes.default.svc.cluster.local/api/v1/namespaces/rbac-demo-ns/pods
sleep 10
done
- 应用清单创建 Pod:
$ kubectl apply -f 02_rbac/pod-logger-app.yaml
pod/pod-logger-app created
$ kubectl get po -n rbac-demo-ns
NAME READY STATUS RESTARTS AGE
nginx-pod 1/1 Running 0 15m
pod-logger-app 1/1 Running 0 9s
- 验证服务账户令牌 :
$ kubectl exec -it -n rbac-demo-ns pod-logger-app -- bash
root@pod-logger-app:/# ls -l /var/run/secrets/kubernetes.io/serviceaccount/
total 0
lrwxrwxrwx 1 root root 13 Jul 14 03:33 ca.crt -> ..data/ca.crt
lrwxrwxrwx 1 root root 16 Jul 14 03:33 namespace -> ..data/namespace
lrwxrwxrwx 1 root root 12 Jul 14 03:33 token -> ..data/token
- 查看 Pod 日志 :
$ kubectl logs -n rbac-demo-ns pod-logger-app -f
Querying Kubernetes API Server for Pods in rbac-demo-ns namespace...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 336 100 336 0 0 25611 0 --:--:-- --:--:-- --:--:-- 25846
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "pods is forbidden: User \"system:serviceaccount:rbac-demo-ns:pod-logger\" cannot list resource \"pods\" in API group \"\" in the namespace \"rbac-demo-ns\"",
"reason": "Forbidden",
"details": {
"kind": "pods"
},
"code": 403
}
由于服务账户尚未与
pod-reader
角色关联,因此会收到 HTTP 状态码 403。
-
创建角色绑定
:
-
创建
02_rbac/read-pods-rolebinding.yaml文件:
-
创建
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: rbac-demo-ns
subjects:
- kind: ServiceAccount
name: pod-logger
namespace: rbac-demo-ns
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
- 应用角色绑定清单:
$ kubectl apply -f 02_rbac/read-pods-rolebinding.yaml
rolebinding.rbac.authorization.k8s.io/read-pods created
- 再次查看 Pod 日志 :
$ kubectl logs -n rbac-demo-ns pod-logger-app -f
...<removed for brevity>...
Querying Kubernetes API Server for Pods in default namespace...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
{
"kind": "PodList",
"apiVersion": "v1",
"metadata": {
"resourceVersion": "4889"
},
"items": [
{
"metadata": {
"name": "nginx-pod",
"namespace": "rbac-demo-ns",
"uid": "b62b2bdb-2677-4809-a134-9d6cfa07ecad",
...<removed for brevity>...
此时,Pod 能够成功检索
rbac-demo-ns
命名空间中的 Pod 列表。
- 删除角色绑定 :
$ kubectl delete rolebinding read-pods -n rbac-demo-ns
再次查看
pod-logger-app
Pod 的日志,请求将再次被拒绝,返回 HTTP 状态码 403。
5. 准入控制简介
准入控制器在 Kubernetes 中充当集群的守门人,在资源创建、删除或修改之前拦截对 Kubernetes API 服务器的请求。它们可以根据预定义规则验证或修改请求,确保只有授权且配置正确的资源进入系统。需要注意的是,准入控制器不会(也不能)阻止对对象的读取(
get
、
watch
或
list
)请求。
准入控制器分为两种类型:
-
验证控制器
:仔细检查传入的请求,如果发现任何可疑或不符合策略的内容,将完全拒绝该请求。
-
变异控制器
:在请求永久存储之前有权修改请求,例如添加缺失的安全注释或调整资源限制。
6. 两阶段准入过程
Kubernetes 的准入控制采用两步过程,确保只有符合要求的资源进入集群。
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
A([请求进入]):::startend --> B(变异阶段):::process
B --> C(验证阶段):::process
C --> D([请求处理结果]):::startend
- 变异阶段 :在此阶段,充当变异控制器的组件会更改传入的 API 请求,使其符合集群策略。这些控制器就像“塑造者”,不仅确保请求与既定设置一致,还能自动添加或调整设置,如默认值或安全标签,使系统在无需手动输入的情况下保持策略合规性和配置一致性。例如,为 Pod 添加缺失的安全注释、根据预定义规则调整 Pod 的资源请求和限制、注入用于特定功能的边车容器。
- 验证阶段 :在变异阶段之后,验证控制器会仔细审查可能已被某些控制器修改过的传入请求。这些控制器常被称为“守护者”,检查请求是否符合集群策略和安全标准。这是防止配置错误和未经授权更改的重要阶段,通过拒绝不符合设定标准的请求来维护集群的完整性和安全性。例如,如果请求符合设定的标准(如资源配额、安全标准),则批准该请求;如果请求违反任何策略,则拒绝该请求,并提供详细的错误消息。
通过以上对 Kubernetes 认证、授权和准入控制的介绍,我们可以更好地理解和实施 Kubernetes 集群的安全策略。
Kubernetes 安全:认证、授权与准入控制详解
7. 准入控制器的重要性及依赖关系
多个 Kubernetes 的关键特性依赖特定的准入控制器才能正常工作。因此,没有适当准入控制器的 Kubernetes API 服务器是不完整的,无法支持所有预期的功能。准入控制器在整个 API 请求处理流程中扮演着至关重要的角色,确保了集群的安全性、策略合规性以及资源的正确配置。
8. 常见准入控制器示例
以下是一些常见的准入控制器及其功能:
| 准入控制器名称 | 类型 | 功能描述 |
| ---- | ---- | ---- |
| LimitRanger | 验证控制器 | 确保资源请求和限制符合命名空间的限制策略。例如,限制 Pod 的 CPU 和内存使用量。 |
| ResourceQuota | 验证控制器 | 对命名空间内的资源使用进行配额管理,防止资源过度使用。比如,限制命名空间内 Pod 的总数。 |
| PodSecurityPolicy | 验证控制器 | 定义 Pod 的安全策略,如允许的主机端口、挂载的卷类型等,确保 Pod 以安全的方式运行。 |
| MutatingAdmissionWebhook | 变异控制器 | 允许用户自定义变异逻辑,通过外部 Webhook 服务对请求进行修改。例如,为所有 Pod 添加特定的标签。 |
| ValidatingAdmissionWebhook | 验证控制器 | 允许用户自定义验证逻辑,通过外部 Webhook 服务对请求进行验证。例如,检查 Pod 的镜像是否来自可信的镜像仓库。 |
9. 配置准入控制器
要配置准入控制器,需要在启动 Kubernetes API 服务器时指定启用的准入控制器列表。可以通过修改 API 服务器的启动参数来实现。以下是一个示例:
# /etc/kubernetes/manifests/kube-apiserver.yaml
...<removed for brevity>...
spec:
containers:
- command:
- kube-apiserver
- --enable-admission-plugins=LimitRanger,ResourceQuota,PodSecurityPolicy
...<removed for brevity>...
在上述示例中,启用了
LimitRanger
、
ResourceQuota
和
PodSecurityPolicy
三个准入控制器。
10. 准入控制器的最佳实践
为了更好地使用准入控制器,以下是一些最佳实践:
-
了解业务需求
:根据业务需求和安全策略,选择合适的准入控制器。例如,如果需要严格控制 Pod 的安全配置,可以启用
PodSecurityPolicy
。
-
逐步启用
:在生产环境中,建议逐步启用准入控制器,先在测试环境中进行充分测试,确保不会对现有业务造成影响。
-
监控和日志记录
:对准入控制器的操作进行监控和日志记录,及时发现和处理异常情况。可以使用 Kubernetes 的日志系统和监控工具来实现。
-
定期审查策略
:定期审查准入控制器的策略,确保其符合最新的安全标准和业务需求。
11. 总结
Kubernetes 的安全体系涵盖了认证、授权和准入控制三个重要方面。认证用于验证用户身份,确保只有合法的用户能够访问系统;授权决定了用户在系统中可以执行的操作,遵循最小权限原则;准入控制器则在资源创建、删除或修改之前进行拦截和检查,确保只有符合策略的资源进入系统。
通过合理配置和使用这些安全机制,可以有效保护 Kubernetes 集群的安全,防止未经授权的访问和操作。以下是对整个安全体系的总结表格:
| 安全机制 | 作用 | 关键组件 |
| ---- | ---- | ---- |
| 认证 | 验证用户身份 | 引导令牌、认证代理、Webhook 令牌认证等 |
| 授权 | 决定用户操作权限 | RBAC、ABAC、Node、Webhook、AlwaysAllow、AlwaysDeny 等授权模式 |
| 准入控制 | 拦截和检查资源请求 | 验证控制器、变异控制器,如 LimitRanger、ResourceQuota 等 |
在实际应用中,建议优先使用 RBAC 进行授权管理,因为它具有灵活性和易于管理的特点。同时,合理配置准入控制器,确保集群的安全性和策略合规性。通过不断学习和实践,我们可以更好地掌握 Kubernetes 的安全机制,为企业的容器化应用提供可靠的保障。
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
A([用户请求]):::startend --> B(认证):::process
B --> C(授权):::process
C --> D(准入控制):::process
D --> E([请求处理结果]):::startend
以上流程图展示了用户请求在 Kubernetes 安全体系中的处理流程,从认证开始,经过授权,最后通过准入控制,确保请求的合法性和合规性。
超级会员免费看
1209

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



