k8s 安全机制详解
Token 和 Basic 认证主要是单向的,即只能验证客户端对服务器的身份。而 HTTPS 证书认证可以实现双向认证,这对于需要确保通信双方身份的场景非常重要,比如在 Kubernetes API Server 与 etcd 或其他组件之间的通信中。使用 HTTPS 证书认证可以防止中间人攻击,确保数据传输的安全性。kind: Rolemetadata:rules:- apiGroups: ["
一、安全机制
Kubernetes 的安全机制非常关键,因为它确保了集群的稳定性和数据的安全。
三个主要安全机制
是 Kubernetes 安全架构的核心组成部分:
认证(Authentication):
-
这是安全机制的第一道防线。它负责确认请求者的身份。在 Kubernetes 中,认证通常通过以下几种方式实现:
-
客户端证书:用户或服务可以通过客户端证书进行身份验证。
-
Bearer Tokens:用户可以获取一个令牌(Token),并在请求中携带这个令牌。
-
基本认证:使用用户名和密码进行基本的 HTTP 认证。
-
SSH 密钥:对于某些操作,如节点登录,可以使用 SSH 密钥进行认证。
鉴权(Authorization):
-
一旦用户或服务通过认证,下一步就是确定他们有哪些权限。Kubernetes 提供了几种鉴权机制:
-
Role-Based Access Control (RBAC):这是 Kubernetes 最常用的鉴权方式,它允许管理员定义角色(Role)和角色绑定(RoleBinding),以控制对资源的访问。
-
Attribute-Based Access Control (ABAC):这是一种更细粒度的鉴权方式,它基于用户、资源和操作的属性来决定访问权限。
-
Webhook 鉴权:允许调用外部服务来决定访问权限。
准入控制(Admission Control):
-
即使请求者通过了认证和鉴权,准入控制还会在资源被创建或修改之前进行最后的检查。这是为了确保资源的创建符合集群的策略和规范。准入控制器可以包括:
-
MutatingWebhook:在资源被持久化之前,可以修改资源对象。
-
ValidatingWebhook:验证资源对象是否符合集群的策略和规范。
-
ResourceQuota:限制资源的使用量,如 CPU、内存和存储。
-
NamespaceLifecycle:管理命名空间的生命周期。
这些机制共同工作,确保了 Kubernetes 集群的安全性。管理员可以根据集群的需求和安全策略来配置这些机制。
二、 认证
这些认证方式确保了只有合法的用户和服务能够与 Kubernetes API Server 进行交互
认证方式
-
HTTP Token 认证:
-
客户端需要获取一个 Token,这个 Token 通常是由 Kubernetes API Server 生成并存储在一个安全的地方。
-
客户端在发起请求时,将这个 Token 放在 HTTP 请求的头部(Header)中,通常是
Authorization
字段。 -
API Server 会验证这个 Token 是否有效,以及对应的用户是否有权进行请求的操作。
-
HTTP Basic 认证:
-
用户名和密码组合使用 Base64 编码后,形成一串编码字符串。
-
这串编码字符串被放在 HTTP 请求的
Authorization
头部中,以Basic
开头。 -
API Server 解码后验证用户名和密码的正确性。
-
HTTPS 证书认证:
-
这是一种更为安全的认证方式,通常用于服务之间的通信。
-
客户端和服务器都需要有由可信的证书颁发机构(CA)签发的 SSL/TLS 证书。
-
在建立 HTTPS 连接时,双方会交换并验证对方的证书,确保通信双方的身份。
-
这种方式不仅能够验证客户端的身份,还能验证服务器的身份,实现双向认证(Mutual TLS, mTLS)。
对比总结
- Token 和 Basic 认证主要是单向的,即只能验证客户端对服务器的身份。而 HTTPS 证书认证可以实现双向认证,这对于需要确保通信双方身份的场景非常重要,比如在 Kubernetes API Server 与 etcd 或其他组件之间的通信中。使用 HTTPS 证书认证可以防止中间人攻击,确保数据传输的安全性。
认证机制框架和相关组件
-
需要被认证的访问类型:
-
Kubernetes 组件(如 kubectl、kubelet、kube-proxy)需要与 API Server 通信,这些通信需要通过认证。
-
Kubernetes 管理的 Pod(如 coredns、dashboard)也需要访问 API Server,同样需要认证。
-
安全性说明:
-
控制平面组件(Controller Manager、Scheduler)通常与 API Server 运行在同一台机器上,因此它们可以直接使用非安全端口(如 8080)进行通信。
-
对于需要远程访问 API Server 的组件(如 kubectl、kubelet、kube-proxy),则需要使用 HTTPS 双向认证,通常通过 6443 端口进行。
-
证书颁发:
-
在二进制部署 Kubernetes 时,可能需要手动签发 HTTPS 证书。
-
在 Kubernetes 自动化部署的环境中,kubelet 首次访问 API Server 时使用 Token 进行认证,之后 Controller Manager 会为 kubelet 生成证书,kubelet 使用这个证书进行后续的认证。
-
kubeconfig:
-
kubeconfig 文件包含了集群的访问参数(如 CA 证书、API Server 地址)和客户端认证信息(如证书和私钥)。
-
kubeconfig 文件还包含了集群上下文参数,允许用户在不同的集群之间切换。
-
kubectl 使用的 kubeconfig 文件通常位于用户的主目录下的
.kube/config
。 -
Service Account:
-
Service Account 是 Kubernetes 中的一个资源对象,用于代表 Pod 中的容器访问 API Server。
-
Service Account 允许 Pod 以一种安全的方式获取访问令牌(Token),而不需要为每个 Pod 单独生成证书。
-
Secret 与 Service Account 的关系:
-
Kubernetes 中的 Secret 资源对象用于存储敏感信息,如密码、OAuth 令牌和 ssh 密钥。
-
Service Account 相关的 Secret 包含了用于认证的 Token,这些 Token 被 Pod 中的容器用来访问 API Server。
-
Opaque 类型的 Secret 用于存储任意的非结构化数据,这些数据可以由用户自定义。
这些机制共同构成了 Kubernetes 的安全框架,确保了集群的管理和操作都是安全可控的。通过这些机制,Kubernetes 能够为不同的组件和服务提供适当的认证和授权,同时保持操作的灵活性和便利性。
Service Account 访问权限机制
Service Account 是 Kubernetes 中用于提供对 API Server 的访问权限的机制。它允许 Pod 中的容器以该 Service Account 的身份进行操作,而无需为每个 Pod 单独创建和管理认证凭据。
Service Account 通常包含以下三个部分:
-
Token:
-
这是一个由 API Server 的私钥签名的 Token 字符串序列号。
-
当 Pod 中的容器需要与 API Server 通信时,可以使用这个 Token 进行认证。
-
API Server 会使用其私钥来验证这个 Token 的有效性。
-
ca.crt:
-
这是 API Server 的 CA 根证书。
-
Pod 中的容器使用这个证书来验证 API Server 发送来的证书,确保通信的安全性。
-
这是双向 TLS(mTLS)认证的一部分,确保了通信双方的身份验证。
-
Namespace:
-
这个字段标识了 Service Account 所属的命名空间。
-
Service Account 通常与特定的命名空间关联,这限制了它的作用范围。
默认情况下,每个命名空间都会自动创建一个名为 default
的 Service Account。如果 Pod 在创建时没有指定 Service Account,它将默认使用其所属命名空间的 default
Service Account。这允许 Pod 以该命名空间的权限进行操作。
kubectl get sa
NAME SECRETS AGE
default 1 7d
kubectl get sa
命令输出显示了当前命名空间中的 Service Account 列表。在这个例子中,default
Service Account 已经存在了 7 天,并且有一个与之关联的 Secret。这个 Secret 包含了上述提到的 Token 和 CA 证书。
Service Account 的使用简化了 Pod 的认证流程,使得开发者和管理员可以更轻松地管理 Pod 的权限,同时保持集群的安全性。通过 Service Account,Kubernetes 能够为动态创建和销毁的 Pod 提供一种安全且灵活的认证机制。
当 Pod 在 Kubernetes 集群中启动时,
它会从与它关联的 Service Account 获取必要的认证信息,并将其挂载到特定的目录 /var/run/secrets/kubernetes.io/serviceaccount/
。这个目录包含了三个关键文件:
-
ca.crt:这是 CA 根证书,用于验证 API Server 的身份。Pod 中的容器在与 API Server 通信时,会使用这个证书来确保它们正在与合法的 API Server 通信。
-
namespace:这是一个文件,包含了 Pod 所属的命名空间。这个信息对于 API Server 来说很重要,因为它决定了 Pod 可以访问的资源范围。
-
token:这是一个由 API Server 签发的 Token,用于在 API Server 进行身份验证。当 Pod 中的容器需要访问 API Server 时,它会使用这个 Token 来证明自己的身份。
kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-5c98db65d4-gmmrn 1/1 Running 0 7d
coredns-5c98db65d4-w24d7 1/1 Running 0 7d
etcd-master 1/1 Running 0 7d
kube-apiserver-master 1/1 Running 0 7d
kube-controller-manager-master 1/1 Running 0 7d
kube-flannel-ds-amd64-4dgcs 1/1 Running 0 7d
kube-flannel-ds-amd64-55xzq 1/1 Running 0 7d
kube-flannel-ds-amd64-l8r2b 1/1 Running 0 7d
kube-proxy-4hj92 1/1 Running 0 7d
kube-proxy-dcprb 1/1 Running 0 7d
kube-proxy-prdjp 1/1 Running 0 7d
kube-scheduler-master 1/1 Running 0 7d
kubectl get pod -n kube-system
命令输出显示了 kube-system
命名空间中的 Pod 列表。这些 Pod 包括了 Kubernetes 控制平面组件和其他关键组件。每个 Pod 都会挂载其关联 Service Account 的认证信息。
kubectl exec -it kube-proxy-prdjp -n kube-system sh
通过 kubectl exec -it kube-proxy-prdjp -n kube-system sh
命令,进入了 kube-system
命名空间中名为 kube-proxy-prdjp
的 Pod 的 shell。
ls /var/run/secrets/kubernetes.io/serviceaccount/
ca.crt namespace token
然后,使用 ls /var/run/secrets/kubernetes.io/serviceaccount/
命令列出了挂载的认证信息文件,这证实了每个 Pod 都能够访问其 Service Account 的认证信息。
这种机制确保了 Pod 能够安全地与 API Server 通信,同时也使得 Pod 的管理和认证过程更加自动化和透明。
三、 鉴权
鉴权(Authorization)是 Kubernetes 安全机制中的一个关键环节,它决定了用户或系统组件在通过认证后能够执行哪些操作。鉴权策略定义了对资源的访问权限,确保只有具有适当权限的用户或服务可以访问或修改资源。
授权策略
-
AlwaysDeny:
-
这种策略会拒绝所有的请求,无论请求的内容是什么。
-
通常用于测试环境,以确保在开发或调试过程中不会有意外的资源访问。
-
AlwaysAllow:
-
这种策略允许所有的请求,不对请求进行任何权限检查。
-
这同样通常用于测试环境,或者在不需要进行权限控制的情况下。
-
ABAC(Attribute-Based Access Control):
-
ABAC 是一种细粒度的访问控制策略,它基于用户、资源和操作的属性来决定访问权限。
-
管理员可以定义复杂的规则,这些规则考虑了用户的属性(如角色、部门)和资源的属性(如标签、注解)。
-
ABAC 提供了高度的灵活性,但配置起来可能比较复杂。
-
Webhook:
-
Webhook 鉴权策略允许 API Server 调用外部的 RESTful 服务来决定是否允许请求。
-
这种方式可以与现有的身份管理系统(如 LDAP、OAuth 服务器)集成,实现集中化的鉴权管理。
-
Webhook 鉴权策略提供了一种灵活的方式来扩展 Kubernetes 的鉴权能力。
-
RBAC(Role-Based Access Control):
-
RBAC 是 Kubernetes 自 1.6 版本起默认的鉴权模式。
-
在 RBAC 中,管理员可以定义角色(Role)和角色绑定(RoleBinding)。
-
角色定义了一组权限,而角色绑定则将角色分配给用户或用户组。
-
RBAC 提供了一种结构化的方式来管理权限,使得权限的分配和审计更加清晰和容易。
在实际部署中,RBAC 是最常用的鉴权策略,因为它提供了一种既灵活又易于管理的方式来控制对 Kubernetes 资源的访问。通过定义角色和角色绑定,管理员可以精确地控制不同用户和组件的权限,从而保护集群的安全。
RBAC 管理用户和组对资源访问权限机制
RBAC(Role-Based Access Control)是 Kubernetes 中用于管理用户和组对资源访问权限的一种机制。与其他访问控制方式相比,RBAC 提供了更细粒度的权限控制,并且更加灵活和易于管理。
官方文档:https://kubernetes.io/docs/reference/access-authn-authz/rbac/
RBAC 的优势:
-
全面覆盖:RBAC 可以对集群中的资源(如 Pods、Deployments、Services)和非资源(如元信息或资源状态)进行访问控制。
-
动态管理:RBAC 的策略可以通过 Kubernetes API 动态配置和管理,无需重启 API Server。这与 ABAC(Attribute-Based Access Control)不同,ABAC 通常需要重启 API Server 来更新策略。
-
易于操作:RBAC 的配置完全通过 Kubernetes API 资源对象实现,可以使用
kubectl
或直接通过 API 与 API Server 交互。
RBAC 的 API 资源对象:
-
Role:定义了一组权限,这些权限适用于特定命名空间内的资源。Role 通常用于在单个命名空间内定义访问策略。
-
ClusterRole:与 Role 类似,但 ClusterRole 是集群级别的资源,其定义的权限适用于整个集群范围内的资源。
-
RoleBinding:将 Role 与用户、组或服务账户(ServiceAccount)绑定,从而授予这些主体(Subjects)在特定命名空间内的权限。
-
ClusterRoleBinding:与 RoleBinding 类似,但 ClusterRoleBinding 将 ClusterRole 与主体绑定,授予主体在整个集群范围内的权限。
这些资源对象使得管理员可以灵活地定义和分配权限,以满足不同的安全需求。通过 Role 和 RoleBinding,可以在命名空间级别进行细粒度的访问控制;而通过 ClusterRole 和 ClusterRoleBinding,则可以实现跨命名空间的访问控制。
官方文档提供了关于 RBAC 的详细信息,包括如何创建和管理这些资源对象,以及如何使用它们来保护 Kubernetes 集群的资源。通过提供的链接,可以访问官方文档以获取更多关于 RBAC 的指导和最佳实践。
RBAC(基于角色的访问控制)的核心概念和组件
角色(Role)和集群角色(ClusterRole):
-
Role:定义了在特定命名空间内对资源的一组操作权限。Role 通常用于限制对单个命名空间内资源的访问。
-
ClusterRole:与 Role 类似,但 ClusterRole 提供了跨命名空间的权限。它允许定义一组在整个集群范围内适用的权限。
-
如果使用 RoleBinding 绑定 ClusterRole,仍会受到命名空间的影响;如果使用 ClusterRoleBinding 绑定 ClusterRole, 将会作用于整个 K8S 集群。
角色绑定(RoleBinding)和集群角色绑定(ClusterRoleBinding):
-
RoleBinding:将 Role 与一个或多个用户、组或服务账户(ServiceAccount)绑定,从而授予这些主体在特定命名空间内的权限。
-
ClusterRoleBinding:与 RoleBinding 类似,但 ClusterRoleBinding 将 ClusterRole 与主体绑定,授予主体在整个集群范围内的权限。
主体(Subject):
-
User:代表一个用户,可以是集群外部的用户或集群内部的服务账户。
-
Group:代表一组用户,可以是系统定义的组或自定义组。
-
ServiceAccount:代表一个服务账户,它是 Kubernetes 内部的一个账户,通常用于 Pod 身份认证。
-
User 使用字符串表示,它的前缀 system: 是系统保留的,集群管理员应该确保普通用户不会使用这个前缀格式;Group 书写格式与 User 相同,同样 system: 前缀也为系统保留。
-
Pod使用 ServiceAccount 认证时,service-account-token 中的 JWT 会保存用户信息。 有了用户信息,再创建一对角色/角色绑定(集群角色/集群角色绑定)资源对象,就可以完成权限绑定了。
权限规则(Rules):
- 在 Role 或 ClusterRole 中定义的规则指定了哪些资源(如 Pods、Deployments)和哪些操作(如 get、watch、list)被允许。这些规则是累加的,意味着只有白名单权限,没有黑名单权限。
Role 示例:
#Role 示例:
apiVersion: rbac.authorization.k8s.io/v1 #指定 core API 组和版本
kind: Role #指定类型为 Role
metadata:
namespace: default #使用默认命名空间
name: pod-reader #Role 的名称
rules: #定义规则
- apiGroups: [""] #""表示 apiGroups 和 apiVersion 使用相同的 core API 组,即 rbac.authorization.k8s.io
resources: ["pods"] #资源对象为 Pod 类型
verbs: ["get", "watch", "list"] #被授予的操作权限
- Role 示例定义了一个名为
pod-reader
的角色,它允许用户在default
命名空间中对 Pods 执行获取(get)、监听(watch)和列出(list)操作。
通过这些组件,Kubernetes 管理员可以精细地控制用户和系统组件对资源的访问,从而确保集群的安全性。RBAC 提供了一种声明式的权限管理方式,使得权限的分配和审计变得更加清晰和容易。
ClusterRole 示例
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# "namespace" 被忽略,因为 ClusterRoles 不受名字空间限制
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"] #资源对象为 Secret 类型
verbs: ["get", "watch", "list"]
提供的 ClusterRole 示例定义了一个名为 secret-reader
的集群角色,这个角色授予了对 Kubernetes Secret 资源的读取(get)、观察(watch)和列出(list)权限。由于这是一个 ClusterRole,这些权限将适用于整个 Kubernetes 集群中的所有命名空间,而不仅仅是单个命名空间。
这里是对 ClusterRole 示例的详细解释:
-
apiVersion
:指定了 Kubernetes API 的版本,这里使用的是rbac.authorization.k8s.io/v1
,这是 RBAC API 的稳定版本。 -
kind
:指定了资源类型,这里是ClusterRole
。 -
metadata
:包含了资源的元数据,如名称(name)。对于 ClusterRole,namespace
字段被忽略,因为它不适用于集群级别的资源。 -
rules
:定义了角色的权限规则。每个规则包含以下部分: -
apiGroups
:指定了 API 组,""
表示核心 API 组。 -
resources
:指定了资源类型,这里为"secrets"
,即 Secret 资源。 -
verbs
:指定了允许的操作,这里是"get"
、"watch"
和"list"
。
创建了 ClusterRole 之后,需要创建一个 ClusterRoleBinding 来将这个角色绑定到一个或多个主体(如用户、组或服务账户),从而授予它们相应的权限。例如:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: read-secrets-global
subjects:
- kind: User
name: "jane@example.com"
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
这个 ClusterRoleBinding 将 secret-reader
角色授予了用户 jane@example.com
,使其能够在整个集群中读取 Secret 资源。
RoleBinding and ClusterRoleBinding示例
-
RoloBinding 可以将角色中定义的权限授予用户或用户组,RoleBinding 包含一组主体(subject),subject 中包含有不同形式的待授予权限资源类型(User、Group、ServiceAccount);
-
RoloBinding 同样包含对被绑定的 Role 引用;
-
RoleBinding 适用于某个命名空间内授权,而 ClusterRoleBinding 适用于集群范围内的授权
RoleBinding 示例1:
#RoleBinding 示例1:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: zhangsan
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
-
这个 RoleBinding 将
pod-reader
角色授予了用户zhangsan
。 -
由于 RoleBinding 在
default
命名空间中定义,因此zhangsan
用户在default
命名空间中具有pod-reader
角色的权限。
RoleBinding 示例2:
RoleBinding 同样可以引用 ClusterRole 来对当前 namespace 内 User、Group 或 ServiceAccount 进行授权, 这种操作允许集群管理员在整个集群内定义一些通用的 ClusterRole,然后在不同的 namespace 中使用 RoleBinding 来引用。
#RoleBinding 示例2:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-secrets
namespace: kube-public
subjects:
- kind: User
name: lisi
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
-
这个 RoleBinding 引用了一个 ClusterRole(
secret-reader
),这意味着它授予的权限是集群范围内的。 -
尽管如此,由于 RoleBinding 在
kube-public
命名空间中定义,用户lisi
只能访问kube-public
命名空间中的 Secrets。
ClusterRoleBinding 示例:
#ClusterRoleBinding 示例:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: read-secrets-global
subjects:
- kind: Group
name: manager
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
-
这个 ClusterRoleBinding 授予了
manager
组内的所有用户在整个集群范围内对 Secrets 的访问权限。 -
由于是 ClusterRoleBinding,它不受命名空间的限制,适用于所有命名空间。
这些绑定的创建和管理可以通过 kubectl
命令行工具或直接通过 Kubernetes API 进行。例如,要创建 RoleBinding 或 ClusterRoleBinding,可以使用以下 kubectl
命令:
kubectl create rolebinding <binding-name> --role=<role-name> --user=<user-or-group> --namespace=<namespace>
或者,对于 ClusterRoleBinding:
kubectl create clusterrolebinding <binding-name> --clusterrole=<clusterrole-name> --group=<group-name>
通过这种方式,Kubernetes 提供了灵活的权限管理机制,使得管理员可以根据需要精细地控制用户和系统组件对资源的访问。
Resources 资源
在 Kubernetes 中,资源(Resources)是 API 对象的集合,它们代表了集群中的对象,如 Pods、Services、Secrets 等。资源可以是命名空间作用域的(例如 Pods、Services),也可以是集群作用域的(例如 Nodes、ClusterRoles)。此外,某些资源还可能包含子资源(Subresources),这些子资源提供了对资源的特定操作,例如 Pod 的日志(/pods/{name}/log
)。
在 RBAC(基于角色的访问控制)模型中,可以通过定义 Role 或 ClusterRole 来控制对这些资源及其子资源的访问权限。
如何在 Role 中定义规则以控制对资源及其子资源的访问权限的示例:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-and-pod-logs-reader
rules:
- apiGroups: [""] # 空字符串表示核心 API 组
resources: ["pods", "pods/log"] # "pods" 是资源,"pods/log" 是子资源
verbs: ["get", "list"] # 允许的操作
在这个例子中,pod-and-pod-logs-reader
Role 授予了对 default
命名空间中 Pods 的获取(get)和列出(list)权限,同时也允许对这些 Pods 的日志子资源执行相同的操作。
RBAC 中的 verbs
字段定义了可以对资源执行的操作,常见的 verbs
包括:
-
get
:获取单个资源的详细信息。 -
list
:列出资源。 -
watch
:监视资源的变化。 -
create
:创建新资源。 -
update
:更新现有资源。 -
patch
:部分更新资源。 -
delete
:删除资源。 -
exec
:在 Pod 中执行命令。
resources
字段定义了 Role 适用的资源类型,而 apiGroups
字段定义了资源所属的 API 组。在 Kubernetes 中,资源和 API 组的概念允许对不同类型的资源进行细粒度的访问控制。
rules规则
在 Kubernetes RBAC(基于角色的访问控制)中,rules
字段定义了一组规则,这些规则指定了哪些操作(verbs)可以对哪些资源(resources)执行。rules
字段中的 verbs
、resources
和 apiGroups
是关键的部分,它们共同决定了角色的权限范围。
verbs:
-
get
:读取单个资源的详细信息。 -
list
:列出资源集合。 -
watch
:监视资源集合的实时更新。 -
create
:创建新资源。 -
update
:修改现有资源。 -
patch
:对资源进行部分更新。 -
delete
:删除资源。 -
exec
:在容器内执行命令(通常用于调试或执行特定任务)。
resources:
-
services
、endpoints
、pods
等:这些是 Kubernetes 中的核心资源类型。 -
secrets
、configmaps
:这些是用于存储敏感信息和配置数据的资源类型。 -
deployments
、jobs
、daemonsets
等:这些是应用部署和管理相关的资源类型。 -
nodes
、rolebindings
、clusterroles
等:这些是集群管理和权限控制相关的资源类型。
apiGroups:
-
""
:表示核心 API 组,也就是 Kubernetes 最初的 API 组。 -
"apps"
、"autoscaling"
、"batch"
:这些是 Kubernetes 扩展的 API 组,包含了额外的资源类型和功能。
在定义 Role 或 ClusterRole 时,可以根据需要组合这些 verbs
、resources
和 apiGroups
来精确控制对资源的访问权限。例如,如果你想允许用户查看和列出 Pods,但不允许创建、修改或删除它们,你可以在 rules
中设置 verbs
为 ["get", "list"]
,resources
为 ["pods"]
。
通过这种方式,Kubernetes 提供了一种细粒度的权限管理机制,使得管理员可以根据实际需求为不同的用户和组件分配合适的权限。
四、准入控制
准入控制(Admission Control)是 Kubernetes 中的一个关键特性,它在资源对象被持久化到 etcd 之前,对 API Server 接收到的请求进行检查和验证。准入控制器(Admission Controllers)是一组插件,它们可以拦截和修改请求,或者根据特定的策略拒绝请求。这些控制器有助于维护集群的稳定性和安全性。
Kubernetes 提供了一系列的准入控制器,它们可以按需启用或禁用。
官方推荐的准入控制器,
官方文档参考:https://kubernetes.io/zh/docs/reference/access-authn-authz/admission-controllers/
它们在不同版本的 Kubernetes 中会有所不同:
-
NamespaceLifecycle:管理命名空间的生命周期,例如,防止删除包含活动资源的命名空间。
-
LimitRanger:检查资源请求是否超出了集群设置的限制范围,如 CPU 和内存请求。
-
ServiceAccount:确保 Pod 能够正确地使用服务账户进行身份认证。
-
DefaultStorageClass:为没有指定存储类的 PersistentVolumes 选择默认的存储类。
-
DefaultTolerationSeconds:为没有指定容忍度(Toleration)的 Pods 添加默认的容忍度设置。
-
MutatingAdmissionWebhook:允许外部服务通过 webhook 修改请求对象。
-
ValidatingAdmissionWebhook:允许外部服务通过 webhook 验证请求对象。
-
ResourceQuota:限制命名空间内资源的使用量,如 Pods、CPU 和内存。
-
NodeRestriction:限制 Pods 可以在哪些节点上运行。
管理员可以根据集群的具体需求和安全策略来启用或禁用这些准入控制器。例如,如果集群需要严格的资源限制,那么 LimitRanger
和 ResourceQuota
就非常重要。如果集群需要与外部鉴权服务集成,那么 MutatingAdmissionWebhook
和 ValidatingAdmissionWebhook
就非常有用。
在 Kubernetes 的配置文件中,可以通过 --admission-control
参数来指定启用哪些准入控制器。例如:
kube-apiserver --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,NodeRestriction
这个参数的值是一个逗号分隔的准入控制器列表。通过这种方式,Kubernetes 确保只有符合集群策略的资源对象才能被创建或修改。
常用的控制器插件
-
NamespaceLifecycle:
-
这个控制器管理命名空间的生命周期,确保只有存在的对象才能在命名空间中创建。
-
它防止删除系统预置的命名空间,如
kube-system
。 -
当删除命名空间时,它会确保命名空间中的所有资源对象也被删除。
-
LimitRanger:
-
LimitRanger 用于配额管理,它检查资源请求是否符合命名空间的
LimitRange
限制。 -
这有助于防止资源过度分配,确保集群资源的合理使用。
-
ServiceAccount:
-
这个控制器在创建 Pod 时自动为其添加
ServiceAccount
。 -
它确保 Pod 能够使用
ServiceAccount
的身份访问 API Server,这对于 Pod 的认证和授权至关重要。 -
ResourceQuota:
-
ResourceQuota 控制器用于基于命名空间的配额管理,它确保资源请求不会超过预设的配额限制。
-
这有助于防止单个用户或应用占用过多资源,从而影响集群中其他用户或应用。
-
NodeRestriction:
-
NodeRestriction 控制器用于限制节点加入集群时的权限。
-
它确保节点以最小权限运行,从而减少潜在的安全风险。
完整示例
如何在 Kubernetes 集群中创建一个用户,并限制该用户只能管理指定命名空间的资源。这个过程涉及到用户创建、证书生成、RBAC 授权和 kubeconfig 文件的配置。
创建用户:
useradd zhangsan
passwd zhangsan
- 使用
useradd
和passwd
命令创建一个名为zhangsan
的用户,并设置密码。
生成证书和 kubeconfig 文件:
#使用这个用户进行资源操作,会发现连接 API Server 时被拒绝访问请求
su - zhangsan
kubectl get pods
The connection to the server localhost:8080 was refused - did you specify the right host or port?
#创建用于用户连接到 API Server 所需的证书和 kubeconfig 文件
#先上传证书生成工具 cfssl、cfssljson、cfssl-certinfo 到 /usr/local/bin 目录中
chmod +x /usr/local/bin/cfssl*
mkdir /opt/zhangsan
cd /opt/zhangsan
vim user-cert.sh
#######################
cat > zhangsan-csr.json <<EOF
{
"CN": "zhangsan",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
#API Server 会把客户端证书的 CN 字段作为 User,把 names.O 字段作为 Group
cd /etc/kubernetes/pki/
cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes /opt/zhangsan/zhangsan-csr.json | cfssljson -bare zhangsan
chmod +x user-cert.sh
./user-cert.sh
#/etc/kubernetes/pki/ 目录中会生成 zhangsan-key.pem、zhangsan.pem、zhangsan.csr
-
使用 CFSSL 工具生成用户
zhangsan
的证书和私钥。 -
创建一个
user-cert.sh
脚本,用于自动化证书生成过程。 -
运行脚本生成证书文件。
配置 kubeconfig 文件:
cd /opt/zhangsan
vim rbac-kubeconfig.sh
APISERVER=$1
# 设置集群参数
export KUBE_APISERVER="https://$APISERVER:6443"
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--embed-certs=true \
--server=${KUBE_APISERVER} \
--kubeconfig=zhangsan.kubeconfig
# 设置客户端认证参数
kubectl config set-credentials zhangsan \
--client-key=/etc/kubernetes/pki/zhangsan-key.pem \
--client-certificate=/etc/kubernetes/pki/zhangsan.pem \
--embed-certs=true \
--kubeconfig=zhangsan.kubeconfig
# 设置上下文参数
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=zhangsan \
--namespace=gzb \
--kubeconfig=zhangsan.kubeconfig
# 使用上下文参数生成 zhangsan.kubeconfig 文件
kubectl config use-context kubernetes --kubeconfig=zhangsan.kubeconfig
-
使用
rbac-kubeconfig.sh
脚本设置 kubeconfig 文件,包括集群参数、客户端认证参数和上下文参数。 -
将生成的 kubeconfig 文件复制到用户的家目录,并设置正确的权限。
创建命名空间:
kubectl create namespace gzb
chmod +x rbac-kubeconfig.sh
./rbac-kubeconfig.sh 192.168.41.31
#查看证书
cat zhangsan-kubeconfig
mkdir /home/zhangsan/.kube
cp zhangsan.kubeconfig /home/zhangsan/.kube/config
chown -R zhangsan:zhangsan /home/zhangsan/.kube/
- 使用
kubectl
创建一个名为gzb
的命名空间。
RBAC 授权:
vim rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: gzb
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list", "create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: gzb
subjects:
- kind: User
name: zhangsan
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
kubectl apply -f rbac.yaml
kubectl get role,rolebinding -n gzb
NAME AGE
role.rbac.authorization.k8s.io/pod-reader 32s
NAME AGE
rolebinding.rbac.authorization.k8s.io/read-pods 32s
-
创建一个名为
pod-reader
的 Role,允许在gzb
命名空间中读取 Pods。 -
创建一个 RoleBinding,将
pod-reader
Role 绑定到用户zhangsan
。
测试操作权限:
//切换用户,测试操作权限
su - zhangsan
vim pod-test.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-test
spec:
containers:
- name: nginx
image: nginx
kubectl create -f pod-test.yaml
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-test 1/1 Running 0 114s 10.244.2.2 node02 <none> <none>
//访问 svc 资源就会被拒绝
kubectl get svc
Error from server (Forbidden): services is forbidden: User "zhangsan" cannot list resource "services" in API group "" in the namespace "gzb"
//也无法访问 default 命名空间
kubectl get pods -n default
Error from server (Forbidden): pods is forbidden: User "zhangsan" cannot list resource "pods" in API group "" in the namespace "default"
//使用 root 用户查看
kubectl get pods --all-namespaces -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
gzb pod-test 1/1 Running 0 107s 10.244.2.2 node02 <none> <none>
......
#由此可以看出 RoleBinding 的用户只能管理指定的命名空间中的资源
-
切换到
zhangsan
用户,尝试创建 Pod。 -
尝试访问其他命名空间或资源,如 Services,以验证权限限制。
管理员权限:
#也可以通过绑定 admin 角色,来获得管理员权限
kubectl create rolebinding zhangsan-admin-binding --clusterrole=admin --user=zhangsan --namespace=gzb
- 如果需要,可以创建一个新的 RoleBinding,将
admin
角色绑定到用户zhangsan
,从而授予其管理员权限。
这个过程展示了如何通过 RBAC 和证书管理来控制用户对 Kubernetes 集群资源的访问。通过这种方式,可以确保用户只能访问和操作他们被授权的资源,从而提高集群的安全性。
更多推荐
所有评论(0)