0.1 一、Kubernetes 的安全机制
Kubernetes 的安全体系主要分为三个关键环节:
认证(Authentication):你是谁?
认证用于验证请求发起者的身份,确保请求确实来自某个合法的实体(用户、服务账户等)。Kubernetes 支持多种认证方式:
(1)Token 认证
- 静态 Token 文件
将用户名和 Token 的映射关系存储在 API Server 的配置文件中(--token-auth-file
参数指定)。 - ServiceAccount Token
每个 ServiceAccount 会自动生成一个 Token(存储在 Secret 中),用于 Pod 访问 API Server。 - 其他 Token 方式
如 OAuth、OIDC(OpenID Connect)等集成外部认证系统。
(2)X.509 证书认证(x509)
- 客户端通过 TLS 证书进行身份验证,证书中包含用户名(通常为
CN
字段)。 - 适用于:
- 用户通过
kubectl
访问集群(需配置~/.kube/config
中的证书)。 - Pod 通过 ServiceAccount 的证书访问 API Server(默认使用
ServiceAccount
的 Secret 中的证书)。
- 用户通过
其他认证方式还包括:
- Webhook Token Authentication:通过外部服务动态验证 Token。
- OpenID Connect (OIDC):集成外部身份提供商(如 Google、Azure AD)。
鉴权(Authorization):你能干啥?
认证通过后,Kubernetes 需要检查该用户/服务是否有权限执行请求的操作。Kubernetes 的鉴权机制基于 RBAC(Role-Based Access Control,基于角色的访问控制)。
(1)RBAC(Role-Based Access Control)
RBAC 是 Kubernetes 的默认鉴权机制,通过以下组件实现:
- 角色(Role):定义一组权限规则(针对某个 Namespace)。
- 集群角色(ClusterRole):定义一组权限规则(集群范围,如管理节点、PV 等)。
- 角色绑定(RoleBinding):将角色绑定到主体(用户、组、ServiceAccount)。
- 集群角色绑定(ClusterRoleBinding):将集群角色绑定到主体(适用于集群范围的操作)。
类型 | 作用范围 | 典型用途 |
---|---|---|
Role | 单个 Namespace | 定义某个 Namespace 内的权限(如管理该 Namespace 的 Pod)。 |
ClusterRole | 整个集群 | 定义集群范围的权限(如管理节点、PV、Namespace 等)。 |
(2)RBAC 的核心概念
- 规则(Rules):定义允许的操作(如
get
、list
、create
)和资源(如pods
、services
)。 - 主体(Subjects):被授权的实体,包括:
- User:普通用户(通常由外部认证系统管理,K8s 不直接创建)。
- Group:用户组(通常由外部认证系统管理)。
- ServiceAccount:Kubernetes 内置的服务账户(用于 Pod 或应用访问 API Server)。
(3)RBAC 的典型场景
- 允许某个用户查看所有 Namespace 的 Pod:
- 创建一个
ClusterRole
定义get/list pods
权限。 - 通过
ClusterRoleBinding
绑定到该用户。
- 创建一个
- 允许某个 ServiceAccount 在特定 Namespace 中创建 Deployment:
- 创建一个
Role
定义create deployments
权限。 - 通过
RoleBinding
绑定到该 ServiceAccount。
- 创建一个
准入控制(Admission Control):修订和补全
准入控制是在 API 请求通过认证和鉴权后、实际执行前的一道“关卡”,用于:
- 验证(Validation):检查请求是否符合规则(如 Pod 的安全策略)。
- 修订(Mutation):修改请求的内容(如自动注入 Sidecar 容器、设置默认资源限制)。
0.2 二、Kubernetes 的用户类型
Kubernetes 中有三种主要的用户类型:
User Account(用户账户)
- 特点:
- 代表外部系统的用户(如开发人员、运维人员)。
- Kubernetes 不直接管理 User Account(即没有
kubectl create user
命令)。 - 通常通过外部认证系统(如 LDAP、OIDC)集成。
- 使用场景:
- 开发人员通过
kubectl
访问集群。 - 运维人员管理集群资源。
- 开发人员通过
Service Account(服务账户)
- 特点:
- Kubernetes 内置的账户,用于 Pod 或应用访问 API Server。
- 每个 Namespace 可以创建多个 ServiceAccount。
- 每个 ServiceAccount 会自动生成一个 Token(存储在 Secret 中)。
- 使用场景:
- Pod 内的应用需要访问 Kubernetes API(如 Operator、Controller)。
- 应用以特定权限访问集群资源(如只读权限)。
匿名用户(Anonymous User)
- 特点:
- 未提供任何认证信息的请求会被视为匿名用户。
- 默认情况下,匿名用户有非常有限的权限(可通过
--anonymous-auth=false
禁用)。
- 使用场景:
- 未配置认证的请求(如直接访问 API Server 的 IP)。
- 通常应禁用匿名访问以提高安全性。
0.3 四、总结
组件 | 作用 |
---|---|
认证(Authentication) | 验证请求者的身份(Token、X.509 等)。 |
鉴权(Authorization) | 检查权限(RBAC 是默认机制)。 |
准入控制(Admission Control) | 修订或拒绝请求(实现安全策略、自动化配置)。 |
用户类型 | User Account(外部用户)、Service Account(内部服务)、匿名用户。 |
RBAC | 通过 Role/ClusterRole 和 RoleBinding/ClusterRoleBinding 实现细粒度权限控制。 |
1 身份认证策略
1.1 X.509客户端证书认证
在双向TLS通信中,客户端持有数字证书信任的CA,需要在kube-apiserver程序启动时,通过--client-ca-file选项传递。
认证通过后,客户端数字证书中的CN(Common Name)即被识别为用户名,而O(Organization)被识别为组名。
kubeadm部署的K8s集群,默认使用"/etc/kubernetes/pki/ca.crt"(各组件间颁发数字证书的CA)进行客户端认证。
1.2 持有者令牌(token)
- 持有者令牌(token):
- 1.静态令牌文件(Static Token File):
令牌信息保存于文本文件中,由kube-apiserver在启动时通过--token-auth-file选项加载。
加载完成后的文件变动,仅能通过重启程序进行重载,因此,相关的令牌会长期有效。
客户端在HTTP请求中,通过“Authorization: Bearer TOKEN”标头附带令牌令牌以完成认证。
- 2.Bootstrap令牌:
一般用于加入集群时使用,尤其是在集群的扩容场景时会用到。
- 3.Service Account令牌:
该认证方式将由kube-apiserver程序内置直接启用,它借助于经过签名的Bearer Token来验证请求。
签名时使用的密钥可以由--service-account-key-file选项指定,也可以默认使用API Server的tls私钥
用于将Pod认证到API Server之上,以支持集群内的进程与API Server通信。
K8s可使用ServiceAccount准入控制器自动为Pod关联ServiceAccount。
- 4.OIDC(OpenID Connect)令牌:
有点类似于"微信","支付宝"认证的逻辑,自建的话需要配置认证中心。
OAuth2认证机制,通常由底层的IaaS服务所提供。
- 5.Webhook令牌:
基于web的形式进行认证,比如之前配置的"钉钉机器人","微信机器人"等;
是一种用于验证Bearer Token的回调机制,能够扩展支持外部的认证服务,例如LDAP等。
- 身份认证代理(Authenticating Proxy):
由kube-apiserver从请求报文的特定HTTP标头中识别用户身份,相应的标头名称可由特定的选项配置指定。
kube-apiserver应该基于专用的CA来验证代理服务器身份。
- 匿名请求:
生产环境中建议禁用匿名认证。
2 Kubernetes的用户类型
“用户”即服务请求者的身份指代,一般使用身份标识符进行识别,比如用户名,用户组,服务账号,匿名用户等。
Kubernetes系统的用户大体可分Service Account,User Account和Anonymous Account。
Service Account:
Kubernetes内置的资源类型,用于Pod内的进程访问API Server时使用的身份信息。
引用格式: "system:serviceaccount:NAMESPACE:SA_NAME"
User Account:
用户账户,指非Pod类的客户端访问API Server时使用的身份标识,一般是现实中的"人"。
API Server没有为这类账户提供保存其信息的资源类型,相关的信息通常保存于外部的文件(特指"kubeconfig"文件)或认证系统中。
身份核验操作可由API Server进行,也可能是由外部身份认证服务完成。
可以手动定义证书,其中O字段表示组,CN字段表示用户名。
Anonymous Account:
不能被识别为Service Account,也不能被识别为User Account的用户。
这类账户K8S系统称之为"system:anonymous",即“匿名用户”。
3 静态令牌文件认证测试案例
1.模拟生成token
1.1 方式1 :
[root@master231 ~]# echo "$(openssl rand -hex 3).$(openssl rand -hex 8)"
01b202.d5c4210389cbff08
[root@master231 ~]#
[root@master231 ~]# echo "$(openssl rand -hex 3).$(openssl rand -hex 8)"
497804.9fc391f505052952
[root@master231 ~]#
[root@master231 ~]#
[root@master231 ~]# echo "$(openssl rand -hex 3).$(openssl rand -hex 8)"
8fd32c.0868709b9e5786a8
[root@master231 ~]#
1.2 方式2 :
[root@master231 ~]# kubeadm token generate
jvt496.ls43vufojf45q73i
[root@master231 ~]#
[root@master231 ~]# kubeadm token generate
qo7azt.y27gu4idn5cunudd
[root@master231 ~]#
[root@master231 ~]#
[root@master231 ~]# kubeadm token generate
mic1bd.mx3vohsg05bjk5rr
[root@master231 ~]#
2.创建csv文件
[root@master231 ~]# cd /etc/kubernetes/pki/
[root@master231 pki]#
[root@master231 pki]# cat > token.csv <<EOF
01b202.d5c4210389cbff08,cmy,10001,k8s
497804.9fc391f505052952,jasonyin,10002,k8s
8fd32c.0868709b9e5786a8,linux97,10003,k3s
jvt496.ls43vufojf45q73i,linux98,10004,k3s
qo7azt.y27gu4idn5cunudd,linux99,10005,k3s
mic1bd.mx3vohsg05bjk5rr,linux100,10006,k3s
EOF
温馨提示:
文件格式为CSV,每行定义一个用户,由“令牌、用户名、用户ID和所属的用户组”四个字段组成,用户组为可选字段
具体格式: token,user,uid,"group1,group2,group3",但K8S 1.23.17版本中实际测试貌似多个组使用逗号分割存在一定问题。
3.修改api-server参数加载token文件
[root@master231 pki]# vim /etc/kubernetes/manifests/kube-apiserver.yaml
...
spec:
containers:
- command:
- kube-apiserver
- --token-auth-file=/etc/kubernetes/pki/token.csv
...
volumeMounts:
...
- mountPath: /etc/kubernetes/pki/token.csv
name: cmy-static-token-file
readOnly: true
...
volumes:
...
- hostPath:
path: /etc/kubernetes/pki/token.csv
type: File
name: cmy-static-token-file
...
[root@master231 pki]# mv /etc/kubernetes/manifests/kube-apiserver.yaml /opt/
[root@master231 pki]#
[root@master231 pki]# mv /opt/kube-apiserver.yaml /etc/kubernetes/manifests/
[root@master231 pki]#
[root@master231 pki]# kubectl get pods -n kube-system -l component=kube-apiserver -o wide # 最少要等待30s+
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-apiserver-master231 1/1 Running 0 32s 10.168.10.231 master231 <none> <none>
[root@master231 pki]#
4.kubectl使用token认证并指定api-server的证书
[root@worker232 ~]# kubectl --server=https://10.168.10.231:6443 --certificate-authority=/etc/kubernetes/pki/ca.crt --token=01b202.d5c4210389cbff08 get nodes
Error from server (Forbidden): nodes is forbidden: User "cmy" cannot list resource "nodes" in API group "" at the cluster scope
[root@worker232 ~]#
[root@worker232 ~]# kubectl --server=https://10.168.10.231:6443 --certificate-authority=/etc/kubernetes/pki/ca.crt --token=8fd32c.0868709b9e5786a8 get nodes
Error from server (Forbidden): nodes is forbidden: User "linux97" cannot list resource "nodes" in API group "" at the cluster scope
[root@worker232 ~]#
[root@worker232 ~]# kubectl --server=https://10.168.10.231:6443 --certificate-authority=/etc/kubernetes/pki/ca.crt --token=oldboy.cmyjason get nodes
error: You must be logged in to the server (Unauthorized) # 未认证!
[root@worker232 ~]#
[root@worker232 ~]# kubectl --server=https://10.168.10.231:6443 --certificate-authority=/etc/kubernetes/pki/ca.crt get nodes # 不使用token登录,判定为匿名用户
Please enter Username: admin
Please enter Password: Error from server (Forbidden): nodes is forbidden: User "system:anonymous" cannot list resource "nodes" in API group "" at the cluster scope
[root@worker232 ~]#
5.curl基于token认证案例
[root@worker232 ~]# curl -k https://10.168.10.231:6443;echo # 如果不指定认证信息,将被识别为匿名"system:anonymous"用户。
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "forbidden: User \"system:anonymous\" cannot get path \"/\"",
"reason": "Forbidden",
"details": {},
"code": 403
}
4 X509数字证书认证测试案例
客户端节点创建证书签发请求
1.客户端节点创建证书签发请求
1.1 创建证书签署请求的密钥
[root@worker233 ~]# openssl genrsa -out cmy.key 2048
[root@worker233 ~]#
[root@worker233 ~]# ll cmy.key
-rw------- 1 root root 1704 Apr 14 10:43 cmy.key
[root@worker233 ~]#
1.2 创建证书签署请求
[root@worker233 ~]# openssl req -new -key cmy.key -out cmy.csr -subj "/CN=cmy/O=cmy"
[root@worker233 ~]#
[root@worker233 ~]# ll cmy*
-rw-r--r-- 1 root root 911 Apr 14 10:43 cmy.csr
-rw------- 1 root root 1704 Apr 14 10:43 cmy.key
[root@worker233 ~]#
1.3 将证书签署请求证书使用base64编码【改成你自己的证书内容,我的跟你不一样!】
[root@worker233 ~]# cat cmy.csr | base64 | tr -d '\n';echo
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1p6Q0NBVThDQVFBd0lqRU1NQW9HQTFVRUF3d0RZMjE1TVJJd0VBWURWUVFLREFsdmJHUmliM2xsWkhVdwpnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDOEI1ZkZRSFJGWlh6T1hOOWtGSklwCklCV1ptSG05UFBXRFVQd3lFdFJSeXZ4c2JPR2RUUUoyUGxTZVUvMVlkWHRQQVlPUWpoNHdUaFpDL2g1QTIwZDYKcitJeUJvbFUwSzc5WkpUSDMvb0pJOVhzZ3JWZjJWY2lvTC8yWmQ3dlFZRVJVTnhiaW44ZENUUUt6NXFOOWdKcgowNllINUxxOVpLLzFNSTJVUldmK3N0OTQ5c1hoRkFvanF2dUpqcS84MjZUTmRoUjI5MHo1NGFFbDNpODhEUWlyCmgyQ3FzVXBsMTN0UENjQlZmSWN5T0xkcWdQc3ZhK3VOWnFEYm1ZNkxEamU3WW55VnFkYzhTY1FYTFF4NmQ0c1EKY0swZVMzcU1VZXFCSVpHVVlsdVhQMEhWS2lBLzI3R2puTTVuWFViUDhDajFkOE8rRlU3NWVYbnBsbUhCR1FJeApBZ01CQUFHZ0FEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFGWE5rc0xpa2ViUEJDVytod1lML2thSWo5WHBoCjNkeTN5TmJCeHFtU05MTFBNY0ZmM0hxek9IWHQwUjlHTjNTaUhOYkQ1aVN4MmJkc3VvbW9QVFpoRnVDSFJzRm8KQithR3JaYnlDWnUvb25CZSs4aFpLMzF1emlyWHJ2TFp3RXBMTzdCWUYzamFpU1IvSUhHdHdXWmJjSTZ5RUovKwpxNk9zVkN1NlFpVXJ0OFJISWZwV2ovdmF5TExOMExMSkZnNmZHSHZKb3dGcFp4bmk2Y1lNa0c3M3lRRVZueDhuCmRHWjVWcHJReXc5OTJLOU4xS01hWXFCVUl0WTJrUndDZFBkdzZud1NyQ3dXNzlkTDBqOVJTZDNkRTZzTVE0RFcKODBGckU5U2c5YlVhUmMrVk1oK3F1ZE94b2RLMm1ITVIxZUpwQW5KNGRLYjFwWkVWeXQzZFZTOGtlZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
[root@worker233 ~]#
服务端签发证书
2.服务端签发证书
1.2 为客户端创建csr资源证书签发请求资源清单
[root@master231 ~]# cat > csr-cmy.yaml << EOF
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: cmy-csr
spec:
# 将客户端证书签发请求使用base64编码存储,拷贝上一步生成的base64代码替换即可。
request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ2F6Q0NBVk1DQVFBd0pqRVFNQTRHQTFVRUF3d0hhemh6TVMweU1qRVNNQkFHQTFVRUNnd0piMnhrWW05NQpaV1IxTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFyWU8wQ3FjbXh1WG8xamRZCi85UlRWTUd1SU5zNWFjVTNiSURDUXk0WXVsMys0cFZiUVBWU3dkN2FpT01YeWNCcXgyR0xmcXA0SEhmdExtUXEKVWtJc3ZnVGJ0Mm9RdDBiamFWdktOOEJKV1N3OVlHYlo5bFR0bFUxVFpCblNDRXk3TS8wbHRaWnVWWTV3Si83dApzMi9sRG5wVVJDQ0dZR3Y4aW5DU0Zac2I4TU5CSEk3TllmYjk0elNERC9CYzlVVkNoK0ROTnZkcUFqVzdhV0krClNUS0VSSHJXVVJDM0h6MzMvY00xaC9Gc0xFMGhKWXdZQncyYzZaYXF2R0J4MmlhSnZmdUVrVVI3azdSbW9JV1cKdDhKL3YzSjZmelk4VG1TN3piYkRUZjhwaE9xczlMVXpWaTNtbHNycDB4UjB4U3FVWlFRa1V6RVZFMDdHc0JUYwowcTdWZVFJREFRQUJvQUF3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUtRc0svTHFjYW5LUk9PejhaOW8xcG1uCmc2d1BWVExxZmh2Z0prRWoxa0EvVWxPYmt3S0Z5ZXhIb09FRDFsZktCWEVtRGhMTmtZaWJJNnpoMzFpa2YzMloKbTQrcXBNSHZ5OFRLdVQ3QzQzQTdtMkhyeFU3aEZYYWdMdElEZkJ1U0syak1FeFY2VXR1aklJQWlWL201REE3aApwWEVoQ2VUSTgwSWN4NndqdHRINHMxazFSdnJzZzNnUXdpRG5waExMYWlNYkM4S3FqQll0YS9lQ2lPczhHaXNNCkhlQ0FiNHowOVFabVFqTFhmV0RLRDR0Ukc2Q1VpeDdGUFR4UWtETkdoMGE4WjZWUnFVNUs0b0c0cXNhNXg0RFEKVU5JSjQwTmtHQU1XNVR1V2VNZkhQcDl2NUdJbDFwWlJ2Y3lNOUpzVUNTdDl1TnhxVWlMbGFiUUVGWHBxNW1vPQotLS0tLUVORCBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0K
# 指定颁发证书的请求类型,仅支持如下三种,切均可以由kube-controllmanager中的“csrsigning”控制器发出。
# "kubernetes.io/kube-apiserver-client":
# 颁发用于向kube-apiserver进行身份验证的客户端证书。
# 对该签名者的请求是Kubernetes控制器管理器从不自动批准。
#
# "kubernetes.io/kube-apiserver-client-kubelet":
# 颁发kubelets用于向kube-apiserver进行身份验证的客户端证书。
# 对该签名者的请求可以由kube-controllermanager中的“csrapproving”控制器自动批准。
#
# "kubernetes.io/kubelet-serving":
# 颁发kubelets用于服务TLS端点的证书,kube-apiserver可以连接到这些端点安全。
# 对该签名者的请求永远不会被kube-controllmanager自动批准。
signerName: kubernetes.io/kube-apiserver-client
# 指定证书的过期时间,此处我设置的是24h(3600*24=86400)
expirationSeconds: 86400
# 指定在颁发的证书中请求的一组密钥用法。
# 对TLS客户端证书的请求通常请求:
# “数字签名(digital signature)”、“密钥加密(key encipherment)”、“客户端身份验证(client auth)”。
# 对TLS服务证书的请求通常请求:
# “密钥加密(key encipherment)”、“数字签名(digital signature)”、“服务器身份验证(server auth)”。
#
# 有效值的值为: "signing", "digital signature", "content commitment", "key encipherment","key agreement",
# "data encipherment", "cert sign", "crl sign", "encipher only", "decipher only", "any", "server auth",
# "client auth", "code signing", "email protection", "s/mime", "ipsec end system", "ipsec tunnel","ipsec user",
# "timestamping", "ocsp signing", "microsoft sgc", "netscape sgc"。
usages:
- client auth
EOF
1.2 创建证书签发请求
[root@master231 csr]# kubectl get csr
No resources found
[root@master231 csr]#
[root@master231 csr]# kubectl apply -f csr-cmy.yaml
certificatesigningrequest.certificates.k8s.io/cmy-csr created
[root@master231 csr]#
[root@master231 csr]# kubectl get csr
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
cmy-csr 2s kubernetes.io/kube-apiserver-client kubernetes-admin 24h Pending
[root@master231 csr]#
1.3 服务端手动签发证书
[root@master231 csr]# kubectl certificate approve cmy-csr
certificatesigningrequest.certificates.k8s.io/cmy-csr approved
[root@master231 csr]#
[root@master231 csr]# kubectl get csr
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
cmy-csr 40s kubernetes.io/kube-apiserver-client kubernetes-admin 24h Approved,Issued
[root@master231 csr]#
1.4 获取签发后的证书
[root@master231 csr]# kubectl get csr cmy-csr -o jsonpath='{.status.certificate}' | base64 -d > /opt/cmy.crt
[root@master231 csr]#
[root@master231 csr]# ll /opt/cmy.crt
-rw-r--r-- 1 root root 1115 Jun 3 10:21 /opt/cmy.crt
[root@master231 csr]#
1.5 将证书拷贝到客户端节点,便于后续使用
[root@master231 ~]# scp /opt/cmy.crt 10.0.0.233:~
客户端测试验证
3.客户端测试验证
3.1 查看本地证书文件
[root@worker233 ~]# ll cmy.*
-rw-r--r-- 1 root root 1115 Jun 3 10:22 cmy.crt
-rw-r--r-- 1 root root 911 Jun 3 10:12 cmy.csr
-rw------- 1 root root 1704 Jun 3 10:11 cmy.key
3.2 访问api-server
[root@worker233 ~]# kubectl -s https://10.168.10.231:6443 --client-key cmy.key --client-certificate cmy.crt --insecure-skip-tls-verify get nodes
Error from server (Forbidden): nodes is forbidden: User "cmy" cannot list resource "nodes" in API group "" at the cluster scope
[root@worker233 ~]#
5 kubeconfig
5.1 kubeconfig的组成部分
kubeconfig是YAML格式的文件,用于存储身份认证信息,以便于客户端加载并认证到API Server。
kubeconfig保存有认证到一至多个Kubernetes集群的相关配置信息,并允许管理员按需在各配置间灵活切换
clusters:
Kubernetes集群访问端点(API Server)列表。
说白了,就是可以定义多个K8S集群列表。
users:
认证到API Server的身份凭据列表。
说白了,可以定义多个用户列表,这个用户可以是token,或者x509证书凭据。
contexts:
将每一个user同可认证到的cluster建立关联的上下文列表。
说白了,就是将多个用户和对应的集群进行关联,将来使用哪个用户,就会去关联的集群进行访问认证。也可以定义多个上下文的关系。
current-context:
当前默认使用的context。
5.2 静态令牌认证kubeconfig实战
创建一个集群
1 创建一个集群
[root@worker232 ~]# kubectl config set-cluster myk8s --embed-certs=true --certificate-authority=/etc/kubernetes/pki/ca.crt --server="https://10.0.0.231:6443" --kubeconfig=./cmy-k8s.conf
Cluster "myk8s" set.
[root@worker232 ~]#
[root@worker232 ~]# cat ./cmy-k8s.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd
server: https://10.0.0.231:6443
name: myk8s
contexts: null
current-context: ""
kind: Config
preferences: {}
users: null
[root@worker232 ~]#
[root@worker232 ~]# ll cmy-k8s.conf
-rw------- 1 root root 1663 Apr 14 11:26 cmy-k8s.conf
[root@worker232 ~]#
2.查看集群信息
[root@worker232 ~]# kubectl config get-clusters --kubeconfig=./cmy-k8s.conf
NAME
myk8s
[root@worker232 ~]#
创建用户信息
3.查看令牌认证文件
[root@master231 ~]# cat /etc/kubernetes/pki/token.csv
01b202.d5c4210389cbff08,cmy,10001,k8s
497804.9fc391f505052952,jasonyin,10002,k8s
8fd32c.0868709b9e5786a8,linux97,10003,k3s
mic1bd.mx3vohsg05bjk5rr,linux100,10006,k3s
[root@master231 ~]#
4.创建用户信息
[root@worker232 ~]# kubectl config set-credentials cmy --token="01b202.d5c4210389cbff08" --kubeconfig=./cmy-k8s.conf
User "cmy" set.
[root@worker232 ~]#
[root@worker232 ~]# kubectl config set-credentials jasonyin --token="497804.9fc391f505052952" --kubeconfig=./cmy-k8s.conf
User "jasonyin" set.
[root@worker232 ~]#
[root@worker232 ~]# cat cmy-k8s.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd
server: https://10.0.0.231:6443
name: myk8s
contexts: null
current-context: ""
kind: Config
preferences: {}
users:
- name: jasonyin
user:
token: 497804.9fc391f505052952
- name: cmy
user:
token: 01b202.d5c4210389cbff08
[root@worker232 ~]#
5.查看用户信息
[root@worker232 ~]# kubectl config get-users --kubeconfig=./cmy-k8s.conf
NAME
jasonyin
cmy
[root@worker232 ~]#
定义上下文
[root@worker232 ~]# kubectl config set-context cmy@myk8s --user=cmy --cluster=myk8s --kubeconfig=./cmy-k8s.conf
Context "cmy@myk8s" created.
[root@worker232 ~]#
[root@worker232 ~]# kubectl config set-context jasonyin@myk8s --user=jasonyin --cluster=myk8s --kubeconfig=./cmy-k8s.conf
Context "jasonyin@myk8s" created.
[root@worker232 ~]#
[root@worker232 ~]# cat cmy-k8s.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd
server: https://10.0.0.231:6443
name: myk8s
contexts:
- context:
cluster: myk8s
user: jasonyin
name: jasonyin@myk8s
- context:
cluster: myk8s
user: cmy
name: cmy@myk8s
current-context: ""
kind: Config
preferences: {}
users:
- name: jasonyin
user:
token: 497804.9fc391f505052952
- name: cmy
user:
token: 01b202.d5c4210389cbff08
[root@worker232 ~]#
7. 查看上下文列表
[root@worker232 ~]# kubectl config get-contexts --kubeconfig=./cmy-k8s.conf
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
jasonyin@myk8s myk8s jasonyin
cmy@myk8s myk8s cmy
[root@worker232 ~]#
8.定义当前使用的上下文
[root@worker232 ~]# kubectl config use-context cmy@myk8s --kubeconfig=./cmy-k8s.conf
Switched to context "cmy@myk8s".
[root@worker232 ~]#
[root@worker232 ~]# cat cmy-k8s.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd
server: https://10.0.0.231:6443
name: myk8s
contexts:
- context:
cluster: myk8s
user: jasonyin
name: jasonyin@myk8s
- context:
cluster: myk8s
user: cmy
name: cmy@myk8s
current-context: cmy@myk8s
kind: Config
preferences: {}
users:
- name: jasonyin
user:
token: 497804.9fc391f505052952
- name: cmy
user:
token: 01b202.d5c4210389cbff08
[root@worker232 ~]#
9. 查看当前使用的上下文
[root@worker232 ~]# kubectl config current-context --kubeconfig=./cmy-k8s.conf
cmy@myk8s
[root@worker232 ~]#
[root@worker232 ~]# kubectl config get-contexts --kubeconfig=./cmy-k8s.conf
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
jasonyin@myk8s myk8s jasonyin
* cmy@myk8s myk8s cmy
[root@worker232 ~]#
10.打印kubeconfig信息,默认会使用“REDACTED”或者“DATA+OMITTED”关键字隐藏证书信息
[root@worker232 ~]# kubectl config view --kubeconfig=./cmy-k8s.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://10.0.0.231:6443
name: myk8s
contexts:
- context:
cluster: myk8s
user: jasonyin
name: jasonyin@myk8s
- context:
cluster: myk8s
user: cmy
name: cmy@myk8s
current-context: cmy@myk8s
kind: Config
preferences: {}
users:
- name: jasonyin
user:
token: REDACTED
- name: cmy
user:
token: REDACTED
[root@worker232 ~]#
客户端进行认证
[root@worker232 ~]# kubectl get pods --kubeconfig=./cmy-k8s.conf
Error from server (Forbidden): pods is forbidden: User "cmy" cannot list resource "pods" in API group "" in the namespace "default"
[root@worker232 ~]#
[root@worker232 ~]# kubectl get pods --kubeconfig=./cmy-k8s.conf --context=jasonyin@myk8s
Error from server (Forbidden): pods is forbidden: User "jasonyin" cannot list resource "pods" in API group "" in the namespace "default"
5.3 kubectl加载kubeconfig的优先级验证*****
1.基于KUBECONFIG变量
[root@worker232 ~]# export KUBECONFIG=/root/cmy-k8s.conf
[root@worker232 ~]# kubectl get pods
Error from server (Forbidden): pods is forbidden: User "cmy" cannot list resource "pods" in API group "" in the namespace "default"
[root@worker232 ~]#
[root@worker232 ~]# kubectl get pods --context=jasonyin@myk8s
Error from server (Forbidden): pods is forbidden: User "jasonyin" cannot list resource "pods" in API group "" in the namespace "default"
[root@worker232 ~]#
2.指定kubeconfig文件,优先级高于KUBECONFIG变量
2.1 拷贝kubeconfig文件
[root@master231 ~]# scp /etc/kubernetes/admin.conf 10.0.0.232:~
2.2 测试验证
[root@worker232 ~]# env | grep KUBECONFIG
KUBECONFIG=/root/cmy-k8s.conf
[root@worker232 ~]#
[root@worker232 ~]# kubectl get nodes
Error from server (Forbidden): nodes is forbidden: User "cmy" cannot list resource "nodes" in API group "" at the cluster scope
[root@worker232 ~]#
[root@worker232 ~]# kubectl get nodes --kubeconfig=admin.conf
NAME STATUS ROLES AGE VERSION
master231 Ready control-plane,master 12d v1.23.17
worker232 Ready <none> 12d v1.23.17
worker233 NotReady <none> 5d18h v1.23.17
[root@worker232 ~]#
3.指定kubeconfig文件,优先级高于"~/.kube/config"文件
3.1 拷贝kubeconfig文件
[root@worker232 ~]# scp cmy-k8s.conf 10.0.0.231:~
3.2 测试验证
[root@master231 ~]# env | grep KUBECONFIG
[root@master231 ~]# ll ~/.kube/config
-rw------- 1 root root 5638 May 22 10:59 /root/.kube/config
[root@master231 ~]#
[root@master231 ~]# kubectl get nodes --kubeconfig=cmy-k8s.conf
Error from server (Forbidden): nodes is forbidden: User "cmy" cannot list resource "nodes" in API group "" at the cluster scope
[root@master231 ~]#
4."~/.kube/config"和KUBECONFIG变量的优先级比较
4.1 配置环境变量
[root@master231 ~]# env | grep KUBECONFIG
[root@master231 ~]#
[root@master231 ~]# export KUBECONFIG=/root/cmy-k8s.conf
[root@master231 ~]#
[root@master231 ~]# env | grep KUBECONFIG
KUBECONFIG=/root/cmy-k8s.conf
[root@master231 ~]#
[root@master231 ~]# ll ~/.kube/config
-rw------- 1 root root 5638 May 22 10:59 /root/.kube/config
[root@master231 ~]#
4.2 测试验证
[root@master231 ~]# kubectl get nodes
Error from server (Forbidden): nodes is forbidden: User "cmy" cannot list resource "nodes" in API group "" at the cluster scope
[root@master231 ~]#
4.3 删除变量
[root@master231 ~]# unset KUBECONFIG
[root@master231 ~]# env | grep KUBECONFIG
[root@master231 ~]#
[root@master231 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master231 Ready control-plane,master 12d v1.23.17
worker232 Ready <none> 12d v1.23.17
worker233 NotReady <none> 5d18h v1.23.17
[root@master231 ~]#
5.综上所述,kubectl加载kubeconfig文件的优先级总结
- 1.使用--kubeconfig的优先级最大,直接无视后面的两个配置文件;
- 2.使用KUBECONFIG变量的优先级次之;
- 3.使用默认的"~/.kube/config"最后加载;
5.4 X509数字证书生成kubeconfig实战
准备证书
[root@worker233 ~]# ll cmy.*
-rw-r--r-- 1 root root 1115 Apr 14 10:58 cmy.crt
-rw-r--r-- 1 root root 911 Apr 14 10:43 cmy.csr
-rw------- 1 root root 1704 Apr 14 10:43 cmy.key
[root@worker233 ~]#
添加证书用户
2 添加证书用户
[root@worker233 ~]# kubectl config set-credentials cmy --client-certificate=/root/cmy.crt --client-key=/root/cmy.key --embed-certs=true --kubeconfig=./cmy-k8s.conf
User "cmy" set.
3 查看用户列表
[root@worker233 ~]# kubectl config get-users --kubeconfig=./cmy-k8s.conf
NAME
cmy
[root@worker233 ~]#
创建一个集群
4.创建一个集群
[root@worker233 ~]# kubectl config set-cluster myk8s --embed-certs=false --certificate-authority=/etc/kubernetes/pki/ca.crt --server="https://10.0.0.231:6443" --kubeconfig=./cmy-k8s.conf
Cluster "myk8s" set.
[root@worker233 ~]#
配置上下文
[root@worker233 ~]# kubectl config set-context cmy@myk8s --user=cmy --cluster=myk8s --kubeconfig=./cmy-k8s.conf
6.查看上下文列表
[root@worker233 ~]# kubectl config get-contexts --kubeconfig=./cmy-k8s.conf
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
cmy@myk8s myk8s cmy
[root@worker233 ~]#
9.配置默认上下文
[root@worker233 ~]# kubectl config use-context cmy@myk8s --kubeconfig=./cmy-k8s.conf
Switched to context "cmy@myk8s".
[root@worker233 ~]#
测试
10.测试
[root@worker233 ~]# kubectl config current-context --kubeconfig=./cmy-k8s.conf
cmy@myk8s
[root@worker233 ~]#
[root@worker233 ~]# kubectl config get-contexts --kubeconfig=./cmy-k8s.conf
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* cmy@myk8s myk8s cmy
[root@worker233 ~]#
[root@worker233 ~]# kubectl get pods --kubeconfig=./cmy-k8s.conf
Error from server (Forbidden): pods is forbidden: User "cmy" cannot list resource "pods" in API group "" in the namespace "default"
[root@worker233 ~]#
11.配置KUBECONFIG环境变量
[root@worker233 ~]# export KUBECONFIG=/root/cmy-k8s.conf
[root@worker233 ~]#
[root@worker233 ~]# kubectl get pods
Error from server (Forbidden): pods is forbidden: User "cmy" cannot list resource "pods" in API group "" in the namespace "default"
[root@worker233 ~]#
5.5 K8S默认基于sa进行认证
ServiceAccount(SA,服务账户) 是一种用于标识 Pod 中运行的应用程序身份的安全机制。它允许 Pod 以特定的权限访问 Kubernetes API 和其他集群资源,类似于人类用户的账户
ServiceAccount 的作用
- 身份认证:Pod 中的容器需要访问 Kubernetes API 或其他资源时,必须通过 ServiceAccount 进行身份验证。
- 权限控制:通过 Role 或 ClusterRole 绑定,可以限制 ServiceAccount 的访问权限(类似 RBAC)。
- 默认行为:
- 每个 Namespace 默认有一个
default
ServiceAccount。 - 如果 Pod 没有显式指定 ServiceAccount,则会使用该 Namespace 的
default
ServiceAccount。
- 每个 Namespace 默认有一个
ServiceAccount 的工作原理**
- Pod 创建时:
- Kubernetes 会自动为 Pod 分配一个 ServiceAccount(默认是
default
)。 - Pod 的
spec.serviceAccountName
字段可以指定其他 ServiceAccount(如果未指定,则使用default
)。
- Kubernetes 会自动为 Pod 分配一个 ServiceAccount(默认是
- 访问 API 时:
- Pod 中的容器通过
ServiceAccount
的 Token(存储在/var/run/secrets/kubernetes.io/serviceaccount/token
)访问 Kubernetes API。 - 容器还可以访问
ca.crt
(集群 CA 证书)和namespace
文件(当前 Namespace 名称)。
- Pod 中的容器通过
- RBAC 控制:
- 通过
Role
或ClusterRole
定义权限。
- 通过
基于sa进行认证实战
ServiceAccount Token的不同实现方式
- 1.Kubernetes v1.20-
系统自动生成专用的Secret对象,并基于secret卷插件关联至相关的Pod;
Secret中会自动附带Token且永久有效(安全性低,如果将来获取该token可以长期登录)。
- 2.Kubernetes v1.21-v1.23:
系统自动生成专用的Secret对象,并通过projected卷插件关联至相关的Pod;
Pod不会使用Secret上的Token,被弃用后,在未来版本就不在创建该token。
而是由Kubelet向TokenRequest API请求生成,默认有效期为一年,且每小时更新一次;
- 3.Kubernetes v1.24+:
系统不再自动生成专用的Secret对象。
而是由Kubelet负责向TokenRequest API请求生成Token,默认有效期为一年,且每小时更新一次;
4.创建sa并让pod引用指定的sa
[root@master231 pods]# cat 14-pods-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: oldboy
---
apiVersion: v1
kind: Pod
metadata:
name: cmy-pods-sa
spec:
# 使用sa的名称
serviceAccountName: oldboy
containers:
- name: c1
image: registry.cn-hangzhou.aliyuncs.com/cmy-k8s/apps:v1
[root@master231 pods]#
[root@master231 pods]# kubectl apply -f 14-pods-sa.yaml
serviceaccount/oldboy created
pod/cmy-pods-sa created
[root@master231 pods]#
[root@master231 pods]# kubectl get -f 14-pods-sa.yaml
NAME SECRETS AGE
serviceaccount/oldboy 1 4s
NAME READY STATUS RESTARTS AGE
pod/cmy-pods-sa 1/1 Running 0 4s
[root@master231 pods]#
5.验证pod使用sa的验证身份
[root@master231 auth]# kubectl exec -it cmy-pods-sa -- sh
/ # ls -l /var/run/secrets/kubernetes.io/serviceaccount
total 0
lrwxrwxrwx 1 root root 13 Feb 23 04:13 ca.crt -> ..data/ca.crt
lrwxrwxrwx 1 root root 16 Feb 23 04:13 namespace -> ..data/namespace
lrwxrwxrwx 1 root root 12 Feb 23 04:13 token -> ..data/token
/ #
/ # TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
/ #
/ # curl -k -H "Authorization: Bearer ${TOKEN}" https://kubernetes.default.svc.cmy.com;echo
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "forbidden: User \"system:serviceaccount:default:oldboy\" cannot get path \"/\"",
"reason": "Forbidden",
"details": {},
"code": 403
}
/ #
6 RBAC*****
实体(Entity):
在RBAC也称为Subject,通常指的是User、Group或者是ServiceAccount;
角色(Role):
承载资源操作权限的容器。
资源(Resource):
在RBAC中也称为Object,指代Subject期望操作的目标,例如Service,Deployments,ConfigMap,Secret、Pod等资源。
仅限于"/api/v1/..."及"/apis/<group>/<version>/..."起始的路径;
其它路径对应的端点均被视作“非资源类请求(Non-Resource Requests)”,例如"/api"或"/healthz"等端点;
动作(Actions):
Subject可以于Object上执行的特定操作,具体的可用动作取决于Kubernetes的定义。
资源型对象:
只读操作:get、list、watch等。
读写操作:create、update、patch、delete、deletecollection等。
非资源型端点仅支持"get"操作。
角色绑定(Role Binding):
将角色关联至实体上,它能够将角色具体的操作权限赋予给实体。
角色的类型:
Namespace级别:
称为Role,定义名称空间范围内的资源操作权限集合。
Namespace和Cluster级别:
称为ClusterRole,定义集群范围内的资源操作权限集合,包括集群级别及名称空间级别的资源对象。
角色绑定的类型:
Cluster级别:
称为ClusterRoleBinding,可以将实体(User、Group或ServiceAccount)关联至ClusterRole。
Namespace级别:
称为RoleBinding,可以将实体关联至ClusterRole或Role。
即便将Subject使用RoleBinding关联到了ClusterRole上,该角色赋予到Subject的权限也会降级到RoleBinding所属的Namespace范围之内。
- ClusterRole
启用RBAC鉴权模块时,API Server会自动创建一组ClusterRole和ClusterRoleBinding对象
多数都以“system:”为前缀,也有几个面向用户的ClusterRole未使用该前缀,如cluster-admin、admin等。
它们都默认使用“kubernetes.io/bootstrapping: rbac-defaults”这一标签。
默认的ClusterRole大体可以分为5个类别。 了解
API发现相关的角色:
包括system:basic-user、system:discovery和system:public-info-viewer。
面向用户的角色:
包括cluster-admin、admin、edit和view。
核心组件专用的角色:
包括system:kube-scheduler、system:volume-scheduler、system:kube-controller-manager、system:node和system:node-proxier等。
其它组件专用的角色:
包括system:kube-dns、system:node-bootstrapper、system:node-problem-detector和system:monitoring等。
内置控制器专用的角色:
专为内置的控制器使用的角色,具体可参考官网文档。
查看面向用户的四个角色
1.查看角色列表
[root@master231 pods]# kubectl get clusterrole | egrep -v "^system|calico|metallb|kubeadm|tigera"
NAME CREATED AT
admin 2025-05-22T02:57:49Z
cluster-admin 2025-05-22T02:57:49Z
edit 2025-05-22T02:57:49Z
view 2025-05-22T02:57:49Z
[root@master231 pods]#
2.查看集群角色'cluster-admin'相当于Linux的root用户。
[root@master231 pods]# kubectl get clusterrole cluster-admin -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: "2025-05-22T02:57:49Z"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: cluster-admin
resourceVersion: "86"
uid: 7324f527-e03e-425a-a4ba-3f4dca4a6017
rules:
- apiGroups:
- '*'
resources:
- '*'
verbs:
- '*'
- nonResourceURLs:
- '*'
verbs:
- '*'
[root@master231 pods]#
- 验证管理员绑定的cluster-admin角色
1.查看集群角色绑定
[root@master231 pods]# kubectl get clusterrolebindings cluster-admin -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: "2025-05-22T02:57:49Z"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: cluster-admin
resourceVersion: "148"
uid: 96e93f0a-c1fc-4740-b879-72fc2fd30d3e
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:masters
[root@master231 pods]#
2.查看管理员证书
[root@master231 pods]# kubectl config view --raw -o jsonpath='{.users[0].user.client-certificate-data}' | base64 -d > /tmp/xixi.cert
[root@master231 pods]#
[root@master231 pods]# openssl x509 -in /tmp/xixi.cert -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 4201491904469302487 (0x3a4eb2a06c927cd7)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = kubernetes
Validity
Not Before: May 22 02:57:42 2025 GMT
Not After : May 22 02:57:44 2026 GMT
Subject: O = system:masters, CN = kubernetes-admin
Subject Public Key Info:
...
6.1 Role授权给一个用户类型实战
1.未授权前测试
[root@worker233 ~]# kubectl get pods --kubeconfig=./cmy-k8s.conf
Error from server (Forbidden): pods is forbidden: User "cmy" cannot list resource "pods" in API group "" in the namespace "default"
[root@worker233 ~]#
2.创建Role
[root@master231 ~]# kubectl create role reader --resource=po,svc --verb=get,watch,list -o yaml --dry-run=client # 将来可用于声明式
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: null
name: reader
rules:
- apiGroups:
- ""
resources:
- pods
- services
verbs:
- get
- watch
- list
[root@master231 ~]#
[root@master231 ~]# kubectl create role reader --resource=po,svc --verb=get,watch,list # 响应式创建
role.rbac.authorization.k8s.io/reader created
[root@master231 ~]#
[root@master231 ~]# kubectl get role reader
NAME CREATED AT
reader 2025-04-14T07:16:25Z
[root@master231 ~]#
4.创建角色绑定
[root@master231 ~]# kubectl create rolebinding cmy-as-reader --user=cmy --role=reader -o yaml --dry-run=client
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
creationTimestamp: null
name: cmy-as-reader
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: reader
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: cmy
[root@master231 ~]#
[root@master231 ~]# kubectl create rolebinding cmy-as-reader --user=cmy --role=reader
rolebinding.rbac.authorization.k8s.io/cmy-as-reader created
[root@master231 ~]#
[root@master231 ~]# kubectl get rolebindings cmy-as-reader
NAME ROLE AGE
cmy-as-reader Role/reader 13s
[root@master231 ~]#
[root@master231 ~]#
5.授权后再次验证
[root@worker233 ~]# kubectl get pods,svc -o wide --kubeconfig=./cmy-k8s.conf
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/scheduler-nodeselector-774bf9875f-4mrjp 1/1 Running 0 46s 10.100.203.144 worker232 <none> <none>
pod/scheduler-nodeselector-774bf9875f-6hwzv 1/1 Running 0 46s 10.100.203.143 worker232 <none> <none>
pod/scheduler-nodeselector-774bf9875f-8mfvr 1/1 Running 0 46s 10.100.203.146 worker232 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.200.0.1 <none> 443/TCP 7d4h <none>
service/yiliao LoadBalancer 10.200.160.162 10.0.0.150 80:30020/TCP 3d3h app=yiliao
[root@worker233 ~]#
[root@worker233 ~]#
[root@worker233 ~]# kubectl get deploy --kubeconfig=./cmy-k8s.conf
Error from server (Forbidden): deployments.apps is forbidden: User "cmy" cannot list resource "deployments" in API group "apps" in the namespace "default"
[root@worker233 ~]#
6.修改权限
方式一: (响应式)
[root@master231 ~]# kubectl create role reader --resource=po,svc,deploy --verb=get,watch,list -o yaml --dry-run=client | kubectl apply -f -
Warning: resource roles/reader is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
role.rbac.authorization.k8s.io/reader configured
[root@master231 ~]#
方式二: (声明式)
[root@master231 ~]# kubectl create role reader --resource=po,svc,deploy --verb=get,watch,list -o yaml --dry-run=client
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: null
name: reader
rules:
- apiGroups:
- ""
resources:
- pods
- services
verbs:
- get
- watch
- list
- apiGroups:
- apps
resources:
- deployments
verbs:
- get
- watch
- list
[root@master231 ~]#
[root@master231 ~]# kubectl create role reader --resource=po,svc,deploy --verb=get,watch,list -o yaml --dry-run=client > 01-Role-cmy.yaml
[root@master231 ~]#
[root@master231 ~]# kubectl apply -f 01-Role-cmy.yaml
role.rbac.authorization.k8s.io/reader configured
[root@master231 ~]#
7.测试验证
[root@worker233 ~]# kubectl get deploy --kubeconfig=./cmy-k8s.conf -n default
NAME READY UP-TO-DATE AVAILABLE AGE
scheduler-nodeselector 5/5 5 5 6m44s
[root@worker233 ~]#
[root@worker233 ~]# kubectl get deploy --kubeconfig=./cmy-k8s.conf
NAME READY UP-TO-DATE AVAILABLE AGE
scheduler-nodeselector 5/5 5 5 6m45s
[root@worker233 ~]#
6.2 ClusterRole授权给用户组
1.授权前测试
[root@worker232 ~]# cat cmy-k8s.conf
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJN
name: myk8s
contexts:
- context:
cluster: myk8s
user: jasonyin
name: jasonyin@myk8s
- context:
cluster: myk8s
user: cmy
name: cmy@myk8s
current-context: cmy@myk8s
kind: Config
preferences: {}
users:
- name: jasonyin
user:
token: 497804.9fc391f505052952
- name: cmy
user:
token: 01b202.d5c4210389cbff08
[root@worker232 ~]#
[root@worker232 ~]# kubectl get pods --kubeconfig=./cmy-k8s.conf
Error from server (Forbidden): pods is forbidden: User "cmy" cannot list resource "pods" in API group "" in the namespace "default"
[root@worker232 ~]#
[root@worker232 ~]# kubectl get pods --kubeconfig=./cmy-k8s.conf --context=jasonyin@myk8s
Error from server (Forbidden): pods is forbidden: User "jasonyin" cannot list resource "pods" in API group "" in the namespace "default"
[root@worker232 ~]#
2.创建集群角色
[root@master231 manifests]# kubectl create clusterrole reader --resource=deploy,rs,pods,nodes --verb=get,watch,list -o yaml --dry-run=client
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
creationTimestamp: null
name: reader
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- watch
- list
- apiGroups:
- apps
resources:
- deployments
- replicasets
verbs:
- get
- watch
- list
[root@master231 manifests]#
[root@master231 manifests]# kubectl create clusterrole reader --resource=deploy,rs,pods --verb=get,watch,list
clusterrole.rbac.authorization.k8s.io/reader created
[root@master231 manifests]#
[root@master231 manifests]# kubectl get clusterrole reader
NAME CREATED AT
reader 2025-04-14T07:44:31Z
[root@master231 manifests]#
3.将集群角色绑定给k8s组
[root@master231 ~]# cat /etc/kubernetes/pki/token.csv
01b202.d5c4210389cbff08,cmy,10001,k8s
497804.9fc391f505052952,jasonyin,10002,k8s
8fd32c.0868709b9e5786a8,linux97,10003,k3s
jvt496.ls43vufojf45q73i,linux98,10004,k3s
qo7azt.y27gu4idn5cunudd,linux99,10005,k3s
mic1bd.mx3vohsg05bjk5rr,linux100,10006,k3s
[root@master231 ~]#
[root@master231 ~]# kubectl create clusterrolebinding k8s-as-reader --clusterrole=reader --group=k8s -o yaml --dry-run=client
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
creationTimestamp: null
name: k8s-as-reader
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: reader
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: k8s
[root@master231 ~]#
[root@master231 ~]# kubectl create clusterrolebinding k8s-as-reader --clusterrole=reader --group=k8s
clusterrolebinding.rbac.authorization.k8s.io/k8s-as-reader created
[root@master231 ~]#
[root@master231 ~]# kubectl get clusterrolebindings k8s-as-reader
NAME ROLE AGE
k8s-as-reader ClusterRole/reader 10s
[root@master231 ~]#
4.基于kubeconfig测试
[root@worker232 ~]# kubectl get deploy,rs,pod -o wide --kubeconfig=./cmy-k8s.conf --context=jasonyin@myk8s
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/scheduler-nodeselector 5/5 5 5 29m c1 harbor250.cmy.com/cmy-xiuxian/apps:v1 apps=xiuxian
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/scheduler-nodeselector-774bf9875f 5 5 5 29m c1 harbor250.cmy.com/cmy-xiuxian/apps:v1 apps=xiuxian,pod-template-hash=774bf9875f
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/scheduler-nodeselector-774bf9875f-4mrjp 1/1 Running 0 29m 10.100.203.144 worker232 <none> <none>
pod/scheduler-nodeselector-774bf9875f-6hwzv 1/1 Running 0 29m 10.100.203.143 worker232 <none> <none>
[root@worker232 ~]#
[root@worker232 ~]# kubectl get deploy,rs,pod -o wide --kubeconfig=./cmy-k8s.conf
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/scheduler-nodeselector 5/5 5 5 29m c1 harbor250.cmy.com/cmy-xiuxian/apps:v1 apps=xiuxian
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/scheduler-nodeselector-774bf9875f 5 5 5 29m c1 harbor250.cmy.com/cmy-xiuxian/apps:v1 apps=xiuxian,pod-template-hash=774bf9875f
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/scheduler-nodeselector-774bf9875f-4mrjp 1/1 Running 0 29m 10.100.203.144 worker232 <none> <none>
pod/scheduler-nodeselector-774bf9875f-6hwzv 1/1 Running 0 29m 10.100.203.143 worker232 <none> <none>
5.基于token测试
[root@worker232 ~]# kubectl --server=https://10.0.0.231:6443 --token=01b202.d5c4210389cbff08 --certificate-authority=/etc/kubernetes/pki/ca.crt get deploy,rs,po -o wide -A
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
calico-apiserver deployment.apps/calico-apiserver 2/2 2 2 7d4h calico-apiserver docker.io/calico/apiserver:v3.25.2 apiserver=true
calico-system deployment.apps/calico-kube-controllers 1/1 1 1 7d4h calico-kube-controllers docker.io/calico/kube-controllers:v3.25.2 k8s-app=calico-kube-controllers
calico-system deployment.apps/calico-typha 2/2 2 2 7d4h calico-typha docker.io/calico/typha:v3.25.2 k8s-app=calico-typha
default deployment.apps/scheduler-nodeselector 5/5 5 5 31m c1 harbor250.cmy.com/cmy-xiuxian/apps:v1 apps=xiuxian
....
metallb-system pod/speaker-srvw8 1/1 Running 1 (7h17m ago) 4d6h 10.0.0.231 master231 <none> <none>
metallb-system pod/speaker-tgwql 1/1 Running 1 (7h17m ago) 4d4h 10.0.0.232 worker232 <none> <none>
metallb-system pod/speaker-zpn5c 1/1 Running 1 (7h17m ago) 4d1h 10.0.0.233 worker233 <none> <none>
tigera-operator pod/tigera-operator-8d497bb9f-bcj5s 1/1 Running 4 (5h44m ago) 4d3h 10.0.0.232 worker232 <none> <none>
[root@worker232 ~]#
[root@worker232 ~]#
[root@worker232 ~]# kubectl --server=https://10.0.0.231:6443 --token=8fd32c.0868709b9e5786a8 --certificate-authority=/etc/kubernetes/pki/ca.crt get deploy,rs,po -o wide -A # 很明显,linux97属于k3s分组,不属于K8S组的,因此无法访问!
Error from server (Forbidden): deployments.apps is forbidden: User "linux97" cannot list resource "deployments" in API group "apps" at the cluster scope
Error from server (Forbidden): replicasets.apps is forbidden: User "linux97" cannot list resource "replicasets" in API group "apps" at the cluster scope
Error from server (Forbidden): pods is forbidden: User "linux97" cannot list resource "pods" in API group "" at the cluster scope
[root@worker232 ~]#
6.更新权限
[root@worker232 ~]# kubectl --kubeconfig=./cmy-k8s.conf delete pod/scheduler-nodeselector-774bf9875f-4mrjp # 只能读取不能删除
Error from server (Forbidden): pods "scheduler-nodeselector-774bf9875f-4mrjp" is forbidden: User "cmy" cannot delete resource "pods" in API group "" in the namespace "default"
[root@worker232 ~]#
[root@master231 ~]# kubectl create clusterrole reader --resource=deploy,rs,pods --verb=get,watch,list,delete -o yaml --dry-run=client | kubectl apply -f -
Warning: resource clusterroles/reader is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
clusterrole.rbac.authorization.k8s.io/reader configured
[root@master231 ~]#
7.验证删除权限是否生效
[root@worker232 ~]# kubectl get pod -o wide --kubeconfig=./cmy-k8s.conf
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
scheduler-nodeselector-774bf9875f-4mrjp 1/1 Running 0 35m 10.100.203.144 worker232 <none> <none>
scheduler-nodeselector-774bf9875f-6hwzv 1/1 Running 0 35m 10.100.203.143 worker232 <none> <none>
scheduler-nodeselector-774bf9875f-8mfvr 1/1 Running 0 35m 10.100.203.146 worker232 <none> <none>
scheduler-nodeselector-774bf9875f-ftdrt 1/1 Running 0 35m 10.100.203.141 worker232 <none> <none>
scheduler-nodeselector-774bf9875f-r5ff6 1/1 Running 0 35m 10.100.203.140 worker232 <none> <none>
[root@worker232 ~]#
[root@worker232 ~]#
[root@worker232 ~]# kubectl --kubeconfig=./cmy-k8s.conf delete pods --all
pod "scheduler-nodeselector-774bf9875f-4mrjp" deleted
pod "scheduler-nodeselector-774bf9875f-6hwzv" deleted
pod "scheduler-nodeselector-774bf9875f-8mfvr" deleted
pod "scheduler-nodeselector-774bf9875f-ftdrt" deleted
pod "scheduler-nodeselector-774bf9875f-r5ff6" deleted
[root@worker232 ~]#
[root@worker232 ~]# kubectl get pod -o wide --kubeconfig=./cmy-k8s.conf
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
scheduler-nodeselector-774bf9875f-cklnv 1/1 Running 0 10s 10.100.203.139 worker232 <none> <none>
scheduler-nodeselector-774bf9875f-h7bmb 1/1 Running 0 10s 10.100.203.136 worker232 <none> <none>
scheduler-nodeselector-774bf9875f-hdv7b 1/1 Running 0 10s 10.100.203.131 worker232 <none> <none>
scheduler-nodeselector-774bf9875f-hqqt4 1/1 Running 0 10s 10.100.203.147 worker232 <none> <none>
scheduler-nodeselector-774bf9875f-sbkg9 1/1 Running 0 10s 10.100.203.133 worker232 <none> <none>
[root@worker232 ~]#
6.3 ClusterRole授权给SA类型
1.导入镜像
[root@worker232 ~]# wget http://192.168.14.253/Resources/Kubernetes/RBAC/python-v3.9.16.tar.gz
[root@worker232 ~]# docker load -i python-v3.9.16.tar.gz
2.编写资源清单
[root@master231 sa]# cat > cmy-sa-rbac.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: oldboy
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: xiuxian
spec:
replicas: 1
selector:
matchLabels:
app: xiuxian
template:
metadata:
labels:
app: xiuxian
spec:
nodeName: worker232
serviceAccountName: oldboy
containers:
- image: python:3.9.16-alpine3.16
command:
- tail
- -f
- /etc/hosts
name: apps
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: reader-oldboy
rules:
- apiGroups:
- ""
resources:
- pods
- services
verbs:
- get
- watch
- list
- delete
- apiGroups:
- apps
resources:
- deployments
verbs:
- get
- watch
- list
- delete
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: reader-oldboy-bind
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: reader-oldboy
subjects:
- kind: ServiceAccount
name: oldboy
namespace: default
EOF
3.创建资源
[root@master231 sa]# kubectl apply -f cmy-sa-rbac.yaml
serviceaccount/oldboy created
deployment.apps/xiuxian created
clusterrole.rbac.authorization.k8s.io/reader-oldboy created
clusterrolebinding.rbac.authorization.k8s.io/reader-oldboy-bind created
[root@master231 sa]#
[root@master231 sa]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
xiuxian-6dffdd86b-m8f2h 1/1 Running 0 2m3s 10.100.140.78 worker233 <none> <none>
[root@master231 sa]#
4.安装依赖包
[root@master231 sa]# kubectl exec -it xiuxian-6dffdd86b-m8f2h -- sh
/ #
/ # pip install kubernetes -i https://pypi.tuna.tsinghua.edu.cn/simple/
...
Successfully installed cachetools-5.5.2 certifi-2025.1.31 charset-normalizer-3.4.1 durationpy-0.9 google-auth-2.38.0 idna-3.10 kubernetes-32.0.1 oauthlib-3.2.2 pyasn1-0.6.1 pyasn1-modules-0.4.2 python-dateutil-2.9.0.post0 pyyaml-6.0.2 requests-2.32.3 requests-oauthlib-2.0.0 rsa-4.9 six-1.17.0 urllib3-2.4.0 websocket-client-1.8.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
WARNING: You are using pip version 22.0.4; however, version 25.0.1 is available.
You should consider upgrading via the '/usr/local/bin/python -m pip install --upgrade pip' command.
/ #
5.编写python脚本
/ # cat > view-k8s-resources.py <<EOF
from kubernetes import client, config
with open('/var/run/secrets/kubernetes.io/serviceaccount/token') as f:
token = f.read()
configuration = client.Configuration()
configuration.host = "https://kubernetes" # APISERVER地址
configuration.ssl_ca_cert="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" # CA证书
configuration.verify_ssl = True # 启用证书验证
configuration.api_key = {"authorization": "Bearer " + token} # 指定Token字符串
client.Configuration.set_default(configuration)
apps_api = client.AppsV1Api()
core_api = client.CoreV1Api()
try:
print("###### Deployment列表 ######")
#列出default命名空间所有deployment名称
for dp in apps_api.list_namespaced_deployment("default").items:
print(dp.metadata.name)
except:
print("没有权限访问Deployment资源!")
try:
#列出default命名空间所有pod名称
print("###### Pod列表 ######")
for po in core_api.list_namespaced_pod("default").items:
print(po.metadata.name)
except:
print("没有权限访问Pod资源!")
EOF
3.运行python脚本
/ # python3 view-k8s-resources.py
###### Deployment列表 ######
xiuxian
###### Pod列表 ######
xiuxian-6dffdd86b-m8f2h
/ #
4.更新权限
[root@master231 scheduler]# kubectl edit clusterrole reader-oldboy
...
15 rules:
16 - apiGroups:
17 - ""
18 resources: # 注意哈,此处我删除了Pod的资源!表示无法访问
19 - services
20 verbs:
21 - get
22 - watch
23 - list
24 - delete
25 - apiGroups:
26 - apps
27 resources:
28 - deployments
29 verbs:
30 - get
31 - watch
32 - list
33 - delete
5.再次测试验证
/ # python3 view-k8s-resources.py
###### Deployment列表 ######
xiuxian
###### Pod列表 ######
没有权限访问Pod资源!
/ #
练习!!!
- 创建一个sa账号,并为其授权测试如下:
- 1.可以正常访问svc,po,no资源
- 2.不可以删除po但可以删除svc;
1.创建ClusterRole并绑定用户组
cat cmy-sa-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: test
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: xiuxian
spec:
replicas: 1
selector:
matchLabels:
app: xiuxian
template:
metadata:
labels:
app: xiuxian
spec:
nodeName: master-231
serviceAccountName: test
containers:
- image: python:3.9.16-alpine3.16
command:
- tail
- -f
- /etc/hosts
name: apps
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
creationTimestamp: null
name: reader
rules:
- apiGroups:
- ""
resources:
- pods
- nodes
verbs:
- get
- watch
- list
- apiGroups:
- ""
resources:
- services
verbs:
- delete
- get
- watch
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: reader-test-bind
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: reader
subjects:
- kind: ServiceAccount
name: test
namespace: default
2.进入容器验证权限
kubectl get pods
NAME READY STATUS RESTARTS AGE
cmy-pods-sa 1/1 Running 0 3h34m
xiuxian-68b98c654f-vv999 1/1 Running 0 18m
[root@master-231 /cmy/manifests/pods]# kubectl exec -it xiuxian-68b98c654f-vv999 -- sh
/ # cat test.py
from kubernetes import client, config
# 从 ServiceAccount 的 Token 文件读取 Token
with open('/var/run/secrets/kubernetes.io/serviceaccount/token') as f:
token = f.read()
configuration = client.Configuration()
configuration.host = "https://kubernetes.default.svc" # 正确的 API Server 地址
configuration.ssl_ca_cert = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" # CA 证书
configuration.verify_ssl = True # 启用证书验证
configuration.api_key = {"authorization": "Bearer " + token} # 使用 Token 认证
client.Configuration.set_default(configuration)
core_api = client.CoreV1Api()
def list_resources():
"""列出当前命名空间中的 Pod 和 Service"""
print("\n###### 当前命名空间中的资源 ######")
# 列出 Pod
print("\nPod 列表:")
try:
pods = core_api.list_namespaced_pod("default").items
for pod in pods:
print(f"- {pod.metadata.name}")
except Exception as e:
print(f"无法读取 Pod!错误:{e}")
# 列出 Service
print("\nService 列表:")
try:
services = core_api.list_namespaced_service("default").items
for svc in services:
print(f"- {svc.metadata.name}")
except Exception as e:
print(f"无法读取 Service!错误:{e}")
def delete_pod(pod_name):
"""尝试删除指定的 Pod(应该失败)"""
print(f"\n尝试删除 Pod:{pod_name}")
try:
core_api.delete_namespaced_pod(pod_name, "default")
print(f"成功删除 Pod:{pod_name}(这不应该发生!)")
except Exception as e:
print(f"无法删除 Pod!错误:{e}(这是预期的行为)")
def delete_svc(svc_name):
"""尝试删除指定的 Service(应该成功)"""
print(f"\n尝试删除 Service:{svc_name}")
try:
core_api.delete_namespaced_service(svc_name, "default")
print(f"成功删除 Service:{svc_name}(这是预期的行为)")
except Exception as e:
print(f"无法删除 Service!错误:{e}(这不应该发生!)")
def list_all_resources():
"""列出集群中的所有 Node、Pod 和 Service"""
print("\n###### 集群中的所有资源 ######")
# 列出所有 Node
print("\nNode 列表:")
try:
nodes = core_api.list_node()
for node in nodes.items:
print(f"- {node.metadata.name}")
except Exception as e:
print(f"无法读取 Node!错误:{e}")
# ...... Pod
print("\nPod .........")
try:
pods = core_api.list_namespaced_pod("default").items
for pod in pods:
print(f"- {pod.metadata.name}")
except Exception as e:
print(f"............ Pod............{e}")
# ...... Service
print("\nService .........")
try:
services = core_api.list_namespaced_service("default").items
for svc in services:
print(f"- {svc.metadata.name}")
except Exception as e:
print(f"............ Service............{e}")
def main():
# 列出当前资源
list_resources()
# 提示用户输入要删除的 Pod 名称
pod_name = input("\n请输入要删除的 Pod 名称(直接回车跳过):").strip()
if pod_name:
delete_pod(pod_name)
# 提示用户输入要删除的 Service 名称
svc_name = input("\n请输入要删除的 Service 名称(直接回车跳过):").strip()
if svc_name:
delete_svc(svc_name)
# 最后列出集群中的所有资源
list_all_resources()
if __name__ == "__main__":
main()
/ # python test.py