目录
[1.1 证书颁发](#1.1 证书颁发)
[1.2 config文件](#1.2 config文件)
[1.3 认证类型](#1.3 认证类型)
[1.4 Service Account](#1.4 Service Account)
[1.4.1 作用](#1.4.1 作用)
[1.4.2 包含内容](#1.4.2 包含内容)
[1.4.3 与Secret的关系](#1.4.3 与Secret的关系)
[2.Bearer Tokens](#2.Bearer Tokens)
[5. 主体(subject)类型](#5. 主体(subject)类型)
[5.1 User](#5.1 User)
[5.2 Group](#5.2 Group)
[5.3 ServiceAccount](#5.3 ServiceAccount)
引言
随着云计算和容器技术的蓬勃发展,Kubernetes(K8s)作为容器编排的领头羊,其安全性成为了众多企业和开发者关注的焦点。本文将详细解析Kubernetes的安全机制,包括认证、鉴权和准入控制,以确保集群的稳定性和数据的安全。
一、Kubernetes安全机制概述
Kubernetes的安全机制主要围绕三个核心组件:认证、鉴权和准入控制。认证是安全机制的第一道防线,负责确认请求者的身份;鉴权则是根据用户的身份和权限策略,确定其是否有权执行特定操作;最后,准入控制对API资源对象的修改和校验进行把关。
二、认证机制
(一)认证方式
1.HTTPS证书认证
HTTPS证书认证:基于CA(证书颁发机构)证书签名的数字证书认证。
适用于kube-apiserver、etcd、kubelet等组件之间的连接,确保通信的安全性。
当Pod在Kubernetes集群中启动时,Service Account通常会使用客户端证书进行身份验证。
1.1 证书颁发
手动签发:使用二进制部署时,需要先手动跟 CA 进行签发 HTTPS 证书
自动签发:kubelet 首次访问 API Server 时,使用 token 做认证,通过后,Controller Manager 会为 kubelet 生成一个证书, 以后的访问都是用证书做认证了
1.2 config文件
[root@master01 ~]#ll ~/.kube/config
-rw------- 1 root root 5565 5月 16 15:19 /root/.kube/config
#家目录下的.kube/config文件,用于存储用户的认证信息
#kubectl通过该文件的令牌信息,确定使用的用户,以及对应的权限
1.3 认证类型
Kubernetes 组件对 API Server 的访问,如kubelet、kubectl、kube-proxy,由于这些组件是在node节点上,所以需要证书进行HTTPS双向认证,端口号使用6443端口
Kubernetes 管理的 Pod 对 API Server 的访问
注释:访问安全性要求
kubernetes中,API Server会启动8080端口(非安全端口)与6443端口(安全端口)
安全性:8080端口没有认证和授权检查,存在安全风险;而6443端口有TLS保护,更加安全。
用途:8080端口主要用于调试或内部通信;而6443端口是Kubernetes集群的官方通信端口,用于与外部工具和组件进行交互。
配置:两个端口的配置都可以通过apiserver的启动参数进行修改。在生产环境中,通常建议只开启6443端口,并确保其安全性。
1.4 Service Account
1.4.1 作用
Service Account是Kubernetes中的一种资源对象,用于定义Pod中应用程序的身份。
主要作用是为Pod提供身份,使得Pod可以在Kubernetes集群中被唯一标识,并通过身份验证和授权机制获取访问API Server的权限
因为 Pod 的创建、销毁是动态的,所以要为每一个 Pod 手动生成证书就不可行了。 Kubenetes 使用了 Service Account 来循环认证。Service Account提供了一个在Pod内部使用的身份令牌,用于在Pod与Kubernetes API之间进行交互。
1.4.2 包含内容
●Token:是使用 API Server 私钥签名的 Token 字符串序列号,用于访问 API Server 时,Server 端认证
●ca.crt:ca 根证书,用于 Client 端验证 API Server 发送来的证书
●namespace:标识这个 service-account-token 的作用域名空间
每个命名空间都有一个默认的ServiceAccount,如果用户不指定ServiceAccount,Pod将自动关联到该默认的ServiceAccount上。
1.4.3 与Secret的关系
当Service Account创建时,Kubernetes会自动为每个ServiceAccount创建一个与之关联的Secret,其中包含了ServiceAccount的身份令牌。
[root@master01 opt]#kubectl describe pod nginx
......
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-vgx6f (ro)
......
2.Bearer Tokens
令牌认证:用户或服务可以通过获取一个令牌(Token)并在请求中携带该令牌来进行身份验证。
HTTP Token 的认证是用一个很长的特殊编码方式的并且难以被模仿的 Token 字符串来表达客户的一种方式。Token 是一个很长的很复杂的字符串,每一个 Token 对应一个用户名存储在 API Server 能访问的文件中。当客户端发起 API 调用请求时,需要在 HTTP Header 里放入 Token。
在node节点加入master时,就需要令牌来进行连接
3.基本认证
HTTP Basic Auth:使用用户名和密码进行基本的HTTP认证。
在Kubernetes中,这种认证方式相对较少使用,因为它不如其他方式安全。
注释:Token 认证和 Base 认证方式只能进行服务端对客户端的单向认证,而客户端不知道服务端是否合法;而 HTTPS 证书认证方式 则可以实现双向认证。
三、鉴权
(一)鉴权机制
1.基于RBAC
Kubernetes的鉴权机制主要基于Role-Based Access Control(RBAC)实现。RBAC允许管理员定义角色(Role)和角色绑定(RoleBinding),以控制用户对资源的访问权限。角色定义了用户可以执行的操作和可以访问的资源,而角色绑定则将角色与用户或用户组进行关联。通过这种方式,管理员可以灵活地配置权限策略,确保只有授权用户才能执行特定操作。
2.其它鉴权机制
●AlwaysDeny:表示拒绝所有的请求,一般用于测试
●AlwaysAllow:允许接收所有请求,如果集群不需要授权流程,则可以采用该策略,一般用于测试
●ABAC(Attribute-Based Access Control):基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制。也就是说定义一个访问类型的属性,用户可以使用这个属性访问对应的资源。此方式设置较为繁琐,每次设置需要定义一长串的属性才可以。
●Webhook:通过调用外部 REST 服务对用户进行授权,即可在集群外部对K8S进行鉴权
(二)RBAC的API资源对象
1.Role(角色)
定义:Role 是一个针对单个命名空间的权限控制对象,包含了若干的rules,这些rules代表了一组的permissions(准入、权限)。这些准入是叠加起作用的,并且RBAC在Kubernetes中是一种白名单机制,即都是"允许干xxx",而不是"不允许干xxx"。
使用:Role属于某个特定的namespace,所以在创建Role时需要指定其所属的namespace。
2.ClusterRole(集群角色)
定义:ClusterRole 是一个集群范围的概念,用于定义对Kubernetes资源(集群级别,包含全部命名空间)的访问规则。ClusterRole 不属于某个特定的namespace,它可以定义跨所有命名空间的资源权限,也可以定义集群级别的资源权限。
使用:ClusterRole 可以像Role一样使用,用于对cluster-scoped resources(如nodes)和非资源端点(如/healthz)进行权限的赋予。
3.RoleBinding(角色绑定)
定义:RoleBinding 定义了"Role"和"Subject"(如User、Group或ServiceAccount)的绑定关系,即将用户以及操作权限进行绑定。
使用:使用RoleBinding可以将User和某个Role进行绑定,这样User就拥有了Role所定义的权限,但只能操作RoleBinding所在的命名空间。
4.ClusterRoleBinding(集群角色绑定)
定义:ClusterRoleBinding 定义了用户和集群角色的关系,即通过ClusterRoleBinding将User和ClusterRole进行绑定。
使用:通过ClusterRoleBinding,User可以获得ClusterRole所定义的权限,从而拥有操作所有命名空间的权限。
5. 主体(subject)类型
在Kubernetes中,User、Group 和 ServiceAccount 都是安全认证和授权模型中的主体(subject)类型。这些主体代表了可以执行操作的实体,并且与特定的权限相关联
5.1 User
用户通常代表一个真实的或虚拟的人。在Kubernetes中,用户可能是一个集群外部的实体,如一个开发者或管理员,他们使用kubectl或其他客户端工具与集群交互。
用户的身份验证可以通过多种方式进行,包括静态令牌、OAuth令牌、OpenID Connect(OIDC)等。
一旦通过身份验证,用户的身份会与一个或多个Group关联,以进一步简化授权。
5.2 Group
用户组是用户的集合,通常用于简化权限管理。例如,你可能有一个名为"developers"的用户组,并为该组分配特定的权限。
用户的组成员资格可以静态定义,也可以通过身份验证机制(如OIDC)动态确定。
授权策略可以基于用户组进行定义,从而允许或拒绝整个组的访问。
5.3 ServiceAccount
服务账号(ServiceAccount)是Kubernetes内部的一个实体,用于给Pods中的进程提供访问集群API的凭据。
每个Pod都可以与一个ServiceAccount关联,该ServiceAccount包含了一个API令牌,该令牌允许Pod中的容器以Pod的身份对Kubernetes API发起请求。
ServiceAccount是Pod的安全上下文的一部分,通常与特定的命名空间相关联。
与User和Group不同,ServiceAccount是专为集群内部的服务和工作负载设计的。
(三)创建角色及绑定
1.创建服务账号
首先创建一个服务账号(Service Account)
cs
[root@master01 rbac]#vim sa.yaml
[root@master01 rbac]#cat sa.yaml
apiVersion: v1
kind: Namespace #创建命名空间
metadata:
name: web #指定命名空间名称
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: rbac-sa #服务账号名称
namespace: web #所在命名空间
[root@master01 rbac]#kubectl apply -f sa.yaml
namespace/web created
serviceaccount/rbac-sa created
[root@master01 rbac]#kubectl get serviceaccounts rbac-sa -n web
NAME SECRETS AGE
rbac-sa 1 26s
2.创建Role
cs
[root@master01 rbac]#cat role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: rbac-role
namespace: web
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
[root@master01 rbac]#kubectl apply -f role.yaml
role.rbac.authorization.k8s.io/rbac-role created
[root@master01 rbac]#kubectl get role rbac-role -n web
NAME CREATED AT
rbac-role 2024-06-05T16:07:54Z
------------------------------------------------------------------------------
apiGroups
apiGroups字段指定了资源所属的API群组。常用apiGroups的有
""(空字符串):核心API群组,例如Pods、Services、Endpoints等。
"apps":包含Deployments、StatefulSets、DaemonSets等应用相关的资源。
"batch":包含Jobs、CronJobs等资源。
"extensions":在旧版Kubernetes中用于某些beta API,但在新版中很多资源已经移至其他群组。
"networking.k8s.io":网络相关的资源,如Ingress。
"rbac.authorization.k8s.io":RBAC相关的资源,如Role、RoleBinding等。
----------------------------------------------------------------------------------
resources
resources字段列出了该角色可以访问的具体资源类型。这些资源类型必须是Kubernetes API中定义的。
以下是一些常见的资源类型示例:
pods
services
deployments
configmaps
secrets
ingresses
nodes(对于ClusterRole)
roles 或 rolebindings(对于ClusterRole,允许管理RBAC资源)
-----------------------------------------------------------------------------------
verbs
verbs字段定义了可以对资源执行的操作。以下是一些常用的verbs示例:
get:读取资源。
list:列出所有资源。
watch:观察资源的更改。
create:创建资源。
update:更新资源。
patch:部分更新资源。
delete:删除资源。
deletecollection:删除资源集合。
exec:在Pod中执行命令(通常与Pod资源一起使用)
------------------------------------------------------------------------------------
3.创建RoleBinding
cs
[root@master01 rbac]#cat rolebind.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: rbac-rolebind
namespace: web #RoleBinding所属的命名空间(RoleBinding也是命名空间作用域的,必须指定)
subjects: #定义主体类型
- kind: ServiceAccount #主体类型为ServiceAccount
name: rbac-sa #ServiceAccount名称
namespace: web #指定的ServiceAccount所在命名空间
roleRef: #引用Role或者ClusterRole
kind: Role #引用的资源类型为Role
name: rbac-role #引用的Role的名称
apiGroup: rbac.authorization.k8s.io #表示RBAC API群组
[root@master01 rbac]#kubectl apply -f rolebind.yaml
rolebinding.rbac.authorization.k8s.io/rbac-rolebind created
[root@master01 rbac]#kubectl get rolebindings rbac-rolebind -n web -owide
NAME ROLE AGE USERS GROUPS SERVICEACCOUNTS
rbac-rolebind Role/rbac-role 35s web/rbac-sa
4.创建pod
创建pod是为了验证角色绑定后的权限效果
cs
[root@master01 rbac]#cat rbac-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: rbac-centos
namespace: web
spec:
serviceAccountName: rbac-sa
containers:
- name: centos
image: centos:7
command: ["/bin/sh","-c","sleep 36000"]
[root@master01 rbac]#kubectl apply -f rbac-pod.yaml
pod/rbac-centos created
在pod内部,使用curl命令的方式,获取到pod的信息,类似于执行了get权限
curl -k -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://<API_SERVER_ADDRESS>:<API_SERVER_PORT>/api/v1/namespaces/default/pods
<API_SERVER_ADDRESS>:APIServer的地址,也就是master的地址
<API_SERVER_PORT>:APIServer的监听端口,也就是6443
default:指定命名空间
创建一个不指定serviceaccount的pod,它就不具备权限,使用curl命令访问会出现403报错,表示权限拒绝
cs
[root@master01 rbac]#vim rbac-pod.yaml
[root@master01 rbac]#cat rbac-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: rbac-centos-test
namespace: web
spec:
# serviceAccountName: rbac-sa #注释serviceAccountName字段信息
containers:
- name: centos
image: centos:7
command: ["/bin/sh","-c","sleep 36000"]
[root@master01 rbac]#kubectl apply -f rbac-pod.yaml
pod/rbac-centos-test created
[root@master01 rbac]#kubectl get pod rbac-centos-test -n web
NAME READY STATUS RESTARTS AGE
rbac-centos-test 1/1 Running 0 25s
5.示例总结
通过上面的示例,我们创建了一个名为rbac-sa 的ServiceAccount,一个名为rbac-role 的Role(允许在web 命名空间中读取Pod资源),以及一个名为rbac-rolebind 的RoleBinding(将rbac-role Role绑定到rbac-sa ServiceAccount上)。
效果是:任何使用rbac-sa ServiceAccount的Pod都将具有在web命名空间中读取Pod资源的权限。这允许Pod中的进程通过Kubernetes API获取Pod列表、读取Pod详细信息或监视Pod更改,但不允许它们创建、更新或删除Pod(除非Role中明确允许这些操作)
四、准入控制
准入控制是Kubernetes安全机制的最后一道防线,对API资源对象的修改和校验进行把关。Kubernetes提供了一个插件列表,所有请求都需要经过这个列表中的每个准入控制插件进行处理。这些插件可以对请求进行各种检查和修改,如检查请求是否符合特定的规范、限制请求的资源配额等。通过启用不同的准入控制插件,管理员可以实现对集群的细粒度控制和管理。一般建议直接采用官方默认的准入控制器
(一)准入控制器的工作流程
当向Kubernetes API服务器提交一个请求(如创建、更新或删除资源)时,API服务器会将请求传递给一系列注册的准入控制器进行检查。每个控制器都会根据其配置的规则来决定是否允许请求继续。如果任何一个控制器拒绝了请求,那么整个操作将不会被执行。
(二)准入控制器的类型
Kubernetes提供了多种内置的准入控制器,包括但不限于:
NamespaceAutoProvision: 自动创建请求的命名空间,如果它还不存在。
ResourceQuota: 检查资源配额,确保请求的资源不会超过限定。
ServiceAccount: 确保Pod自动关联一个ServiceAccount。
NodeRestriction: 限制Node上可执行的操作。
PodSecurityPolicy: 应用Pod安全策略,控制Pod的运行方式。
MutatingAdmissionWebhook: 执行自定义的HTTP请求,允许修改请求体。
ValidatingAdmissionWebhook: 类似于MutatingAdmissionWebhook,但仅用于验证,不允许修改请求。
五、对用户的权限设置
平时我们都是默认的root用户进行操作,因为在~/.kube/config的配置文件中进行了令牌认证,它与k8s的admin用户进行了绑定,所以,它会有k8s的所有操作权限。如果使用其它用户进行操作就无法使用
cs
[root@master01 ~]#useradd rbac #创建一个普通用户
[root@master01 pki]#passwd rbac
更改用户 rbac 的密码 。
新的 密码:
无效的密码: 密码少于 8 个字符
重新输入新的 密码:
passwd:所有的身份验证令牌已经成功更新。
[root@master01 ~]#su - rbac
[rbac@master01 ~]$ kubectl get pod #以普通用户的身份执行kubectl命令
The connection to the server localhost:8080 was refused - did you specify the right host or port?
[rbac@master01 ~]$ ls ~/.kube/config
ls: 无法访问/home/rbac/.kube/config: 没有那个文件或目录
#错误信息表示kubectl命令试图连接到默认的Kubernetes API服务器地址(localhost:8080),但连接被拒绝了
#因为APIServer的监听端口是6443,而使用kubectl命令在没有kubeconfig文件的指定情况下
#连接的是8080端口(非安全端口),所以需要进行证书认证并访问644端口
比如现在的需求是创建一个用户只能管理指定的命名空间,首先要做的就是创建用户用于连接到 API Server 所需的证书和 kubeconfig 文件
(一)创建证书
下载生成TSL证书工具并上传到系统当中
下载地址
https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
1.获取工具
cs
[root@master01 cfssl]#ls
cfssl cfssl-certinfo cfssljson
[root@master01 cfssl]#chmod +x ./*
[root@master01 cfssl]#ll
总用量 18808
-rwxr-xr-x 1 root root 10376657 2月 17 2021 cfssl
-rwxr-xr-x 1 root root 6595195 2月 17 2021 cfssl-certinfo
-rwxr-xr-x 1 root root 2277873 2月 17 2021 cfssljson
[root@master01 cfssl]#mv * /usr/local/sbin/
2.创建生成证书的配置文件
以下JSON文件是一个CFSSL(Cloudflare's PKI/TLS toolkit)的配置文件,用于生成一个TLS证书和私钥
cs
[root@master01 cfssl]#mkdir -p /k8s/rbac
[root@master01 cfssl]#vim /k8s/rbac/rbac-csr.json
[root@master01 cfssl]#cat /k8s/rbac/rbac-csr.json
{
"CN": "rbac",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
"CN": "rbac": 这指定了证书的Common Name(CN),即证书的主题名。在这里,它被设置为"rbac",但在实际应用中,这个值应该反映证书将被用于的服务或组件的实际名称。
"hosts": []: 这定义了证书应该覆盖的主机名列表。在这个例子中,列表是空的,意味着证书不会为任何特定的主机名提供验证。在Kubernetes中,这通常不是必需的,因为证书验证通常是通过其他方式(如证书颁发机构或内部CA)进行的。
"key": 这个部分定义了私钥的生成参数。
"algo": "rsa": 指定了密钥算法为RSA。
"size": 2048: 指定了密钥的大小为2048位。
"names": 这个部分定义了证书的主题(Subject)信息。
"C": "CN": 指定了国家代码(Country Code),这里是"CN"代表中国。
"ST": "BeiJing": 指定了州/省(State/Province),这里是"BeiJing"代表北京。
"L": "BeiJing": 指定了城市/地区(Locality),同样是"BeiJing"。
"O": "k8s": 指定了组织(Organization),这里是"k8s"代表Kubernetes。
"OU": "System": 指定了组织单位(Organizational Unit),这里是"System"。
#API Server 会把客户端证书的 CN 字段作为 User,把 names.O 字段作为 Group
3.生成证书
cs
[root@master01 pki]#cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes /k8s/rbac/rbac-csr.json | cfssljson -bare rbac
2024/06/06 08:51:45 [INFO] generate received request
2024/06/06 08:51:45 [INFO] received CSR
2024/06/06 08:51:45 [INFO] generating key: rsa-2048
2024/06/06 08:51:45 [INFO] encoded CSR
2024/06/06 08:51:45 [INFO] signed certificate with serial number 6178924093556289309011739985572884710402992043
2024/06/06 08:51:45 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
[root@master01 pki]#ls rbac*
rbac.csr rbac-key.pem rbac.pem
-----------------------------------------------------------------------------------------
cfssl gencert:这是 CFSSL 的一个子命令,用于生成证书。
-ca=ca.crt:指定了 CA(证书颁发机构)的证书文件。
-ca-key=ca.key:指定了 CA 的私钥文件。
-profile=kubernetes:指定了一个配置文件中的签名配置(profile)。这个配置文件通常定义了证书的签名算法、有效期等参数。
/k8s/rbac/rbac-csr.json:这是 CSR(证书签名请求)文件的路径。这个文件包含了要生成的证书的请求信息,如 CN(Common Name)、hosts、密钥算法等。
cfssljson -bare rbac:这是 CFSSL 的另一个子命令 cfssljson,用于解析 CFSSL 生成的 JSON 格式的输出,并将其转换为 PEM 格式的证书和私钥文件。
-bare rbac 表示输出的文件名将以 "rbac" 为前缀,因此你会得到 rbac.pem(证书文件)和 rbac-key.pem(私钥文件)。
综上所述,这条命令的作用是:使用指定的 CA 证书和私钥,以及 "kubernetes" profile,根据/k8s/rbac/rbac-csr.json 文件中的请求信息来生成一个 TLS 证书和私钥,并将结果保存为 rbac.pem和 rbac-key.pem 文件。
(二)生成config文件
cs
[root@master01 pki]#cd /k8s/rbac/
[root@master01 rbac]#vim rbac-config.sh
[root@master01 rbac]#cat rbac-config.sh
#!/bin/bash
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=rbac.kubeconfig
kubectl config set-credentials rbac \
--client-key=/etc/kubernetes/pki/rbac-key.pem \
--client-certificate=/etc/kubernetes/pki/rbac.pem \
--embed-certs=true \
--kubeconfig=rbac.kubeconfig
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=rbac \
--namespace=kgc \
--kubeconfig=rbac.kubeconfig
kubectl config use-context kubernetes --kubeconfig=rbac.kubeconfig
-----------------------------------------------------------------------------------
#以脚本的形式创建,或者以命令的方式,分别执行
APISERVER=$1
这是一个 Bash 脚本变量赋值语句,它将脚本的第一个参数(1)赋值给变量 APISERVER。这个参数是 Kubernetes API 服务器的地址。 **export KUBE_APISERVER="https://APISERVER:6443"**
设置环境变量,引用$1的参数生成的变量
设置集群参数
使用 kubectl config set-cluster 命令设置 kubeconfig 文件中的集群信息。
--certificate-authority=/etc/kubernetes/pki/ca.crt: 指定 CA 证书的路径,用于验证 API 服务器的 TLS 证书。
--embed-certs=true: 将 CA 证书嵌入到 kubeconfig 文件中,而不是仅引用文件路径。
--server={KUBE_APISERVER}: 设置 API 服务器的 URL。{KUBE_APISERVER} 是之前通过 $1 设置的变量。
--kubeconfig=rbac.kubeconfig: 指定要修改的 kubeconfig 文件的名称。
设置客户端认证参数
使用 kubectl config set-credentials 命令设置 kubeconfig 文件中的用户认证信息。
--client-key=/etc/kubernetes/pki/rbac-key.pem: 指定客户端私钥的路径。
--client-certificate=/etc/kubernetes/pki/rbac.pem: 指定客户端证书的路径。
--embed-certs=true: 类似于集群设置,这也会将证书嵌入到 kubeconfig 文件中。
--kubeconfig=rbac.kubeconfig: 指定要修改的 kubeconfig 文件的名称。
设置上下文参数
使用 kubectl config set-context 命令设置 kubeconfig 文件中的上下文信息。
--cluster=kubernetes: 指定要使用的集群名称(这必须与 kubectl config set-cluster 命令中使用的名称相匹配)。
--user=rbac: 指定要使用的用户名称(这必须与 kubectl config set-credentials 命令中使用的名称相匹配)。
--namespace=rbac-ns: 设置默认的命名空间为rbac-ns。
--kubeconfig=rbac.kubeconfig: 指定要修改的 kubeconfig 文件的名称。
使用上下文参数生成 rbac.kubeconfig 文件
使用 kubectl config use-context 命令将指定的上下文设置为 kubeconfig 文件中的当前上下文。
--kubeconfig=rbac.kubeconfig: 指定要修改的 kubeconfig 文件的名称。
cs
[root@master01 rbac]#kubectl create ns rbac-ns
namespace/rbac-ns created
#创建默认的命名空间,与上述文件中指定命名空间一致
[root@master01 rbac]#chmod +x rbac-config.sh
[root@master01 rbac]#./rbac-config.sh 192.168.83.30
Cluster "kubernetes" set.
User "rbac" set.
Context "kubernetes" created.
Switched to context "kubernetes".
查看config文件
这样看起来是不是与~/.kube/config文件很相似,而后将文件移动到用户的目录下,改名为config
cs
[root@master01 rbac]#mkdir -p /home/rbac/.kube
[root@master01 rbac]#mv rbac.kubeconfig /home/rbac/.kube/config
[root@master01 rbac]#chown -R rbac:rbac /home/rbac/.kube/
[root@master01 rbac]#ls /home/rbac/.kube/
config
(三)RBAC授权
1.创建Role资源
cs
[root@master01 rbac]#vim role.yaml
[root@master01 rbac]#cat role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role #创建Role资源
metadata:
namespace: rbac-ns
name: rbac-pod
rules: #定义授权的信息
- apiGroups: [""] #指定资源核心组,例如Pod、Service等
resources: ["pods"] #指定对pod资源进行授权
verbs: ["get", "watch", "list", "create"]
#授与get(获取)、watch(监听)、list(列出)、create(创建)权限
[root@master01 rbac]#kubectl apply -f role.yaml
role.rbac.authorization.k8s.io/rbac-pod created
[root@master01 rbac]#kubectl get role -n rbac-ns
NAME CREATED AT
rbac-pod 2024-06-06T01:30:44Z
[root@master01 rbac]#kubectl describe role rbac-pod -n rbac-ns
Name: rbac-pod
Labels: <none>
Annotations: <none>
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
pods [] [] [get watch list create]
2.Role绑定
cs
[root@master01 rbac]#vim rolebind.yaml
[root@master01 rbac]#cat rolebind.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding #创建角色绑定资源
metadata:
name: rolebind-pod
namespace: rbac-ns
subjects: #定义了哪些用户、组或服务账户可以被这个RoleBinding授权
- kind: User #指定授权的主体类型是User(用户)
name: rbac #指定用户的名称
apiGroup: rbac.authorization.k8s.io #指定API组,对于用户而言,不需要指定,可省略
roleRef: #引用Role或者ClusterRole
kind: Role #定义了被引用的资源的类型为Role
name: rbac-pod #被引用的角色的名称
apiGroup: rbac.authorization.k8s.io #表示它们来自RBAC API组
[root@master01 rbac]#kubectl apply -f rolebind.yaml
rolebinding.rbac.authorization.k8s.io/rolebind-pod created
[root@master01 rbac]#kubectl get rolebindings -n rbac-ns
NAME ROLE AGE
rolebind-pod Role/rbac-pod 9s
[root@master01 rbac]#kubectl describe rolebindings rolebind-pod -n rbac-ns
Name: rolebind-pod
Labels: <none>
Annotations: <none>
Role:
Kind: Role
Name: rbac-pod
Subjects:
Kind Name Namespace
---- ---- ---------
User rbac
(四)切换用户使用
在rbac用户指定操作内容
1.创建pod
cs
[root@master01 ~]#su - rbac
上一次登录:四 6月 6 08:01:29 CST 2024pts/5 上
[rbac@master01 ~]$ kubectl get pod
No resources found in rbac-ns namespace.
#默认的命名空间为rbac-ns
[rbac@master01 ~]$ kubectl run nginx --image=nginx:1.18.0
pod/nginx created
[rbac@master01 ~]$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 6s
--------------------------------------------------------------------------------------
#可以看到,rbac用于经过授权之后,可以进行查看以及创建pod的操作
2.其它权限
cs
[rbac@master01 ~]$ kubectl get ns
Error from server (Forbidden): namespaces is forbidden: User "rbac" cannot list resource "namespaces" in API group "" at the cluster scope
#查看命名空间被权限拒绝
[rbac@master01 ~]$ kubectl get svc
Error from server (Forbidden): services is forbidden: User "rbac" cannot list resource "services" in API group "" in the namespace "rbac-ns"
#查看service资源被权限拒绝
[rbac@master01 ~]$ kubectl delete pod nginx
Error from server (Forbidden): pods "nginx" is forbidden: User "rbac" cannot delete resource "pods" in API group "" in the namespace "rbac-ns"
#同样的,没有对pod资源授予删除权限,所以无法删除
[rbac@master01 ~]$ kubectl get pod nginx
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 4m
-------------------------------------------------------------------------------------[root@master01 rbac]#kubectl get pod -n rbac-ns
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 5m40s
#在root用户,同样可以查看到新建的pod
3.获取管理员权限
cs
//在root用户中操作
[root@master01 rbac]#kubectl create rolebinding rbac-admin-binding --clusterrole=admin --user=rbac -n rbac-ns
#将rbac用户与admin集群角色进行绑定,并指定rbac-ns命名空间
#执行此命令后,rbac用户会拥有rbac-ns命名空间中所有的资源的管理权限
rolebinding.rbac.authorization.k8s.io/rbac-admin-binding created
[root@master01 rbac]#kubectl get rolebindings rbac-admin-binding -n rbac-ns
NAME ROLE AGE
rbac-admin-binding ClusterRole/admin 20s
//在rbac用户中操作
[rbac@master01 ~]$ kubectl get service
No resources found in rbac-ns namespace.
[rbac@master01 ~]$ kubectl expose pod nginx --port=80 --target-port=80 --name=nginx-svc --type=NodePort
service/nginx-svc exposed
[rbac@master01 ~]$ kubectl get service -owide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
nginx-svc NodePort 10.96.211.179 <none> 80:30309/TCP 8s run=nginx
#可以看到,rbac用于拥有对其它资源的同样拥有操作权限
但是该管理员权限,仅限于指定的命名空间,无法所其它命名空间进行操作
在工作环境中,对于不同的层次,可以对指定的命令空间有不同的权限,负责人或领导也可能需要一个命名空间的所有权限,类似于一个项目,每个人都有不同的职责,一个人负责pod创建,一个人负责对外发布,各司其职,所有需要不同的权限,但是在赋权时一定要谨慎
声明式删除资源
cs
[rbac@master01 ~]$ kubectl delete svc nginx-svc
service "nginx-svc" deleted
[rbac@master01 ~]$ kubectl delete pod nginx
pod "nginx" deleted
[rbac@master01 ~]$ kubectl get svc,pod
No resources found in rbac-ns namespace.