50、Kubernetes 安全:认证、授权与准入控制详解

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
  1. 创建示例 nginx Pod
$ kubectl apply -f 02_rbac/nginx-pod.yaml
pod/nginx-pod created
  1. 创建服务账户
    • 创建 YAML 清单 02_rbac/pod-logger-serviceaccount.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
  1. 创建角色
    • 创建名为 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
  1. 创建 Pod
    • 创建 YAML 清单 02_rbac/pod-logger-app.yaml ,用于创建一个运行在 pod-logger 服务账户下的 Pod:
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
  1. 验证服务账户令牌
$ 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
  1. 查看 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。

  1. 创建角色绑定
    • 创建 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
  1. 再次查看 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 列表。

  1. 删除角色绑定
$ 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 安全体系中的处理流程,从认证开始,经过授权,最后通过准入控制,确保请求的合法性和合规性。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值