K8S认证体系与ServiceAccount

                                              作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

一.Kubernetes认证体系概述

1.API Server内置的访问控制机制

API Server的访问方式:
	- 集群外部: https://IP:Port
	- 集群内部: https://kubernetes.default.svc


API Server内置了插件化的访问控制机制(每种访问控制机制均有一组专用的插件栈)
	认证(Authentication):
		核验请求者身份的合法性,进行身份识别,验证客户端身份。
		身份核验过程遵循“或”逻辑,且任何一个插件核验成功后都将不再进行后续的插件验证。
		均不成功,则失败,或以“匿名者”身份访问,建议禁用“匿名者”。
        
	授权(Authorization):
		核验请求的操作是否获得许可,验证客户端是否有权限操作资源对象。
		鉴权过程遵循“或”逻辑,且任何一个插件对操作的许可授权后都将不再进行后续的插件验证。
		均未许可,则拒绝请求的操作
    
	准入控制(Admission Control):
		检查操作内容是否合规,仅同"写"请求相关,负责实现"检验"字段类型是否合法及和补全默认字段。
		内容合规性检查过程遵循“与”逻辑,且无论成败,每次的操作请求都要经由所有插件的检验。
		将数据写入etcd前,负责检查内容的有效性,因此仅对“写”操作有效。
		分两类:validating(校验)和 mutating(补全或订正)。

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没有为这类账户提供保存其信息的资源类型,相关的信息通常保存于外部的文件或认证系统中。
		身份核验操作可由API Server进行,也可能是由外部身份认证服务完成。

	Anonymous Account:
		不能被识别为Service Account,也不能被识别为User Account的用户。
		这类账户K8S系统称之为"system:anonymous",即“匿名用户”。

3.身份认证策略

- X.509客户端证书认证:
	在双向TLS通信中,客户端持有数字证书信任的CA,需要在kube-apiserver程序启动时,通过--client-ca-file选项传递。
	认证通过后,客户端数字证书中的CN(Common Name)即被识别为用户名,而O(Organization)被识别为组名。
	kubeadm部署的K8s集群,默认使用"/etc/kubernetes/pki/ca.crt"(各组件间颁发数字证书的CA)进行客户端认证。

	
- 持有者令牌:
	- 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来验证代理服务器身份。

- 匿名请求:
	生产环境中建议禁用匿名认证。

4.API Server启用的身份认证机制

基于认证插件支持多种认证方式,而相应认证插件的启用需要经由kube-apiserver上的专用选项完成。

kubeadm v1.23.17部署的集群默认启用的认证机制如上图红框中的选项,它们依次是
	- 1.X509客户端证书认证
	- 2.Bootstrap令牌认证
	- 3.身份认证代理
	- 4.Service Account认证
	
值得注意的是,API Server并不保证各认证插件的生效次序与定义的次序相同。

5.kubelet启用的身份认证机制

如上图所示,kubelet默认开启了客户端身份进行认证。

API Server是该API端点的客户端,因此,kubelet需要在验证客户端身份时信任给API Server颁发数字证书的CA

kubelet的REST API端点默认通过TCP协议的10250端口提供,支持管理操作如下表所示。
Kubernetes API 功能描述
/pods 列出当前kubelet节点的Pod列表。
/run 在一个容器内运行指定的命令。
/exec 在一个容器内运行指定的命令。
/configz 设置kubelet的配置文件参数。
/debug 调试信息。

二.静态令牌文件认证测试案例

1.模拟生成token

[root@master231 ~]# echo "$(openssl rand -hex 3).$(openssl rand -hex 8)"
309837.3a7a5c1fe08fb422
[root@master231 ~]# 
[root@master231 ~]# echo "$(openssl rand -hex 3).$(openssl rand -hex 8)"
f2285b.39b1c2eeb4d22e51
[root@master231 ~]# 
[root@master231 ~]# echo "$(openssl rand -hex 3).$(openssl rand -hex 8)"
f13928.3c1423beb3eb5d98
[root@master231 ~]# 

2.创建csv文件

[root@master231 yinzhengjie-authCase]# cat token.csv 
309837.3a7a5c1fe08fb422,yinzhengjie,10001,k8s
f2285b.39b1c2eeb4d22e51,jasonyin,10002,k8s
f13928.3c1423beb3eb5d98,jiege,10003,k3s
[root@master231 yinzhengjie-authCase]# 

温馨提示:
	文件格式为CSV,每行定义一个用户,由“令牌、用户名、用户ID和所属的用户组”四个字段组成,用户组为可选字段
	具体格式: token,user,uid,"group1,group2,group3"

3.修改api-server参数加载token文件

[root@master231 ~]# cat /etc/kubernetes/manifests/kube-apiserver.yaml 
...
spec:
  containers:
  - command:
    - kube-apiserver
    - --token-auth-file=/etc/kubernetes/yinzhengjie-authCase/token.csv
    ...
    volumeMounts:
    ...
    - mountPath: /etc/kubernetes/yinzhengjie-authCase/token.csv
      name: yinzhengjie-static-token-file
      readOnly: true
  ...
  volumes:
  ...
  - hostPath:
      path: /etc/kubernetes/yinzhengjie-authCase/token.csv
      type: File
    name: yinzhengjie-static-token-file
status: {}
[root@master231 ~]# 

4.kubectl使用token认证并指定api-server的证书

[root@worker232 ~]# kubectl --server=https://10.0.0.231:6443 --token=309837.3a7a5c1fe08fb422 --certificate-authority=/etc/kubernetes/pki/ca.crt  get nodes
Error from server (Forbidden): nodes is forbidden: User "yinzhengjie" cannot list resource "nodes" in API group "" at the cluster scope
[root@worker232 ~]# 

5.kubectl使用token认证并跳过证书校验

[root@worker232 ~]# kubectl --server=https://10.0.0.231:6443 --token=f2285b.39b1c2eeb4d22e51 --insecure-skip-tls-verify  get nodes
Error from server (Forbidden): nodes is forbidden: User "jasonyin" cannot list resource "nodes" in API group "" at the cluster scope
[root@worker232 ~]# 

6.curl基于token认证案例

[root@worker232 ~]# curl -k https://10.0.0.231:6443   # 如果不指定认证信息,将被识别为匿名"system:anonymous"用户。
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "forbidden: User \"system:anonymous\" cannot get path \"/\"",
  "reason": "Forbidden",
  "details": {},
  "code": 403
}

[root@worker232 ~]# curl -k -H "Authorization: Bearer f13928.3c1423beb3eb5d98"  https://10.0.0.231:6443/api/v1/pods
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "pods is forbidden: User \"jiege\" cannot list resource \"pods\" in API group \"\" at the cluster scope",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403
}

三.X509 数字证书认证测试案例

1.基于API-Server签发

1.1 创建证书签署请求

	1.创建证书签署请求的密钥
[root@master231 ~]# openssl genrsa -out jasonyin.key 2048
[root@master231 ~]# 
[root@master231 ~]# ll jasonyin.key 
-rw------- 1 root root 1704 Feb 20 21:36 jasonyin.key
[root@master231 ~]# 

	
	2.创建证书签署请求
[root@master231 ~]# openssl req -new -key jasonyin.key -out jasonyin.csr -subj "/CN=jasonyin/O=jiege"
[root@master231 ~]# 
[root@master231 ~]# ll jasonyin.*
-rw-r--r-- 1 root root  911 Feb 20 21:37 jasonyin.csr
-rw------- 1 root root 1704 Feb 20 21:36 jasonyin.key
[root@master231 ~]# 


	3.将证书签署请求证书使用base64编码
[root@master231 ~]# cat jasonyin.csr | base64 | tr -d '\n'
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ2FEQ0NBVkFDQVFBd0l6RVJNQThHQTFVRUF3d0lhbUZ6YjI1NWFXNHhEakFNQmdOVkJBb01CV3BwWldkbApNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQW5rdGFVMmw0NmpqK2VVY3VML1JpCnYzU044RTlxM1ZOczRTUkJqRy9RcDh1UXpOUGd2Mm00MldpZFBERFZpOUFwVWdxajJSc0d4WjFJQ2w1MFBlcWUKOG51TFh0T21ZWTNlVC9iVmtsVVlyMThKbUpGMFFPNTVYanpXckN3MXdJcWhLL0RJOTE3Z1poR0hBNlFsd1ZrSwplSm50OGJkT2tNRVdjVndncENWcHlOUnNFQS9VNDZTWDlEL0ljRzUydWlQVW1zTGI5eUk4WmUzK2FubzlnQkVmCndOV1Rnbkk5dEtUN3pvUTNlVlBYYjByclJtcFVTOTNqT1ZRSStGcEw4ZWxIa2VLOWJ5WW90NUlYUFFFYWlVa0QKeGc5SjN5eTdtb2VGSmZjNDJPR1lmcjZ6T256a295YUt6VjdJQi9xMmlmN1oyUXlPMFZvcW83TXdOK0t6YjNqSwp0UUlEQVFBQm9BQXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBRWgxV0ZJRkpVOGJiUVJXeUZFT0RBMnloeThUCmJHS0g1ODZSRFFZdjlIS1BpOGUwMVRxRDBFbFFDQjNQYWsrRU1uZGRLc2xVS1JYTXZ1eFdVckRnc3lsbEFVVTkKL09YZ2E3dENGV2dNYkVHdFg5ZDlDcThTdUxqWHErZ04wSnJFNVFyamN1NEQ0RC85T0NOekZ3c1plZkRiZ0xRSQo2RnZmT3haRm9DOEI4SHVOTmFoZUVSVkI3MDZVTGVMQlZQSXMyZC85WjZlYnM4dWd5OW1tUVJOY0RTb2lXOXFsCjNieTZlMnV1TWRxRUw3N1Y2SkV0UkRQaUJNanNtNmhSU3VVc25sZjdwUndmNGxUcEw3bjhONUlRQzlLY2R6aFUKc0ozcFprR3phM1FRbkt3L1dHdWFOUFl2VEpJeFJtN2tFUlE0VTJmK1dMSlA4VkRldWFGTDdGRWR4V1E9Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo= 

1.2 手动创建csr资源

	1.编写资源清单,将证书签署请求编码后的数据使用csr资源封装
[root@master231 ~]# cat certificateSigningRequests-jason.yaml 
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: jasonyin-csr
spec:
  # 将证书签发请求使用base64编码
  request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ2FEQ0NBVkFDQVFBd0l6RVJNQThHQTFVRUF3d0lhbUZ6YjI1NWFXNHhEakFNQmdOVkJBb01CV3BwWldkbApNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQW5rdGFVMmw0NmpqK2VVY3VML1JpCnYzU044RTlxM1ZOczRTUkJqRy9RcDh1UXpOUGd2Mm00MldpZFBERFZpOUFwVWdxajJSc0d4WjFJQ2w1MFBlcWUKOG51TFh0T21ZWTNlVC9iVmtsVVlyMThKbUpGMFFPNTVYanpXckN3MXdJcWhLL0RJOTE3Z1poR0hBNlFsd1ZrSwplSm50OGJkT2tNRVdjVndncENWcHlOUnNFQS9VNDZTWDlEL0ljRzUydWlQVW1zTGI5eUk4WmUzK2FubzlnQkVmCndOV1Rnbkk5dEtUN3pvUTNlVlBYYjByclJtcFVTOTNqT1ZRSStGcEw4ZWxIa2VLOWJ5WW90NUlYUFFFYWlVa0QKeGc5SjN5eTdtb2VGSmZjNDJPR1lmcjZ6T256a295YUt6VjdJQi9xMmlmN1oyUXlPMFZvcW83TXdOK0t6YjNqSwp0UUlEQVFBQm9BQXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBRWgxV0ZJRkpVOGJiUVJXeUZFT0RBMnloeThUCmJHS0g1ODZSRFFZdjlIS1BpOGUwMVRxRDBFbFFDQjNQYWsrRU1uZGRLc2xVS1JYTXZ1eFdVckRnc3lsbEFVVTkKL09YZ2E3dENGV2dNYkVHdFg5ZDlDcThTdUxqWHErZ04wSnJFNVFyamN1NEQ0RC85T0NOekZ3c1plZkRiZ0xRSQo2RnZmT3haRm9DOEI4SHVOTmFoZUVSVkI3MDZVTGVMQlZQSXMyZC85WjZlYnM4dWd5OW1tUVJOY0RTb2lXOXFsCjNieTZlMnV1TWRxRUw3N1Y2SkV0UkRQaUJNanNtNmhSU3VVc25sZjdwUndmNGxUcEw3bjhONUlRQzlLY2R6aFUKc0ozcFprR3phM1FRbkt3L1dHdWFOUFl2VEpJeFJtN2tFUlE0VTJmK1dMSlA4VkRldWFGTDdGRWR4V1E9Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
  # 指定颁发证书的请求类型,仅支持如下三种,切均可以由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
[root@master231 ~]# 


	2.创建csr资源
[root@master231 ~]# kubectl apply -f  certificateSigningRequests-jason.yaml 
certificatesigningrequest.certificates.k8s.io/jasonyin-csr created
[root@master231 ~]# 
[root@master231 ~]# kubectl get csr
NAME           AGE   SIGNERNAME                            REQUESTOR          REQUESTEDDURATION   CONDITION
jasonyin-csr   5s    kubernetes.io/kube-apiserver-client   kubernetes-admin   24h                 Pending
[root@master231 ~]# 

1.3 管理员手动签署(approve)证书请求csr

	1.为签署证书的状态为Pending
[root@master231 ~]# kubectl get csr
NAME           AGE   SIGNERNAME                            REQUESTOR          REQUESTEDDURATION   CONDITION
jasonyin-csr   67s   kubernetes.io/kube-apiserver-client   kubernetes-admin   24h                 Pending
[root@master231 ~]# 


	2.手动批准证书
[root@master231 ~]# kubectl certificate approve jasonyin-csr
certificatesigningrequest.certificates.k8s.io/jasonyin-csr approved
[root@master231 ~]# 


	3.再次查看证书状态
[root@master231 ~]# kubectl get csr
NAME           AGE   SIGNERNAME                            REQUESTOR          REQUESTEDDURATION   CONDITION
jasonyin-csr   80s   kubernetes.io/kube-apiserver-client   kubernetes-admin   24h                 Approved,Issued
[root@master231 ~]# 

1.4 获取签发后的证书

	1.获取签发后的证书
[root@master231 ~]# kubectl get csr jasonyin-csr -o jsonpath='{.status.certificate}' | base64 -d > jasonyin.crt
[root@master231 ~]# 
[root@master231 ~]# ll jasonyin.crt
-rw-r--r-- 1 root root 1111 Feb 20 22:23 jasonyin.crt
[root@master231 ~]# 

	2.将证书拷贝到客户端节点,便于后续使用
[root@master231 ~]# scp jasonyin.key jasonyin.crt  10.0.0.232:/opt

1.5 使用签发后的证书进行认证

[root@worker232 ~]# kubectl -s https://10.0.0.231:6443 --client-key /opt/jasonyin.key  --client-certificate /opt/jasonyin.crt --insecure-skip-tls-verify get nodes
Error from server (Forbidden): nodes is forbidden: User "jasonyin" cannot list resource "nodes" in API group "" at the cluster scope
[root@worker232 ~]# 

2.手动签发证书【扩展】

2.1 创建证书签发请求

	1.进入到K8S集群证书目录
[root@master231 ~]# cd /etc/kubernetes/pki/
[root@master231 pki]# 
[root@master231 pki]# ls
apiserver.crt              apiserver.key                 ca.crt  front-proxy-ca.crt      front-proxy-client.key
apiserver-etcd-client.crt  apiserver-kubelet-client.crt  ca.key  front-proxy-ca.key      sa.key
apiserver-etcd-client.key  apiserver-kubelet-client.key  etcd    front-proxy-client.crt  sa.pub
[root@master231 pki]# 


	2.创建证书签发请求
[root@master231 pki]# openssl genrsa -out jiege.key 4096
[root@master231 pki]# 
[root@master231 pki]# openssl req -new -key jiege.key -out jiege.csr -subj "/CN=jiege/O=k8s"
[root@master231 pki]# 
[root@master231 pki]# ll jiege.*
-rw-r--r-- 1 root root 1598 Feb 20 22:37 jiege.csr
-rw------- 1 root root 3268 Feb 20 22:37 jiege.key
[root@master231 pki]# 

温馨提示:
	如果我们是管理员,且可以访问到API-SERVER的CA证书文件,完全可以基于CA证书手动签发,步骤更加简单。

2.2 手动签发证书

	1.手动签发证书
[root@master231 pki]# openssl x509 -req -days 1 -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -in jiege.csr -out jiege.crt
Certificate request self-signature ok
subject=CN = jiege, O = k8s
[root@master231 pki]# 
[root@master231 pki]# ll jiege.*
-rw-r--r-- 1 root root 1354 Feb 20 22:39 jiege.crt
-rw-r--r-- 1 root root 1598 Feb 20 22:37 jiege.csr
-rw------- 1 root root 3268 Feb 20 22:37 jiege.key
[root@master231 pki]# 

	2.将证书拷贝到客户端节点,便于后续使用
[root@master231 ~]# scp jiege.key jiege.crt  10.0.0.233:/opt

2.3 使用签发后的证书认证

[root@worker233 ~]# kubectl -s https://10.0.0.231:6443 --client-key /opt/jiege.key  --client-certificate /opt/jiege.crt --insecure-skip-tls-verify get cs
Error from server (Forbidden): componentstatuses is forbidden: User "jiege" cannot list resource "componentstatuses" in API group "" at the cluster scope
[root@worker233 ~]# 

四.kubeconfig文件管理认证信息

1.kubeconfig的组成部分

kubeconfig是YAML格式的文件,用于存储身份认证信息,以便于客户端加载并认证到API Server。

kubeconfig保存有认证到一至多个Kubernetes集群的相关配置信息,并允许管理员按需在各配置间灵活切换
	clusters:
		Kubernetes集群访问端点(API Server)列表。
	users:
		认证到API Server的身份凭据列表。
	contexts:
		将每一个user同可认证到的cluster建立关联的上下文列表。
	current-context:
		当前默认使用的context。

2.客户端程序加载的kubeconfig文件顺序

客户端程序加载的kubeconfig文件的途径及次序如下所示:
	- 1.--kubeconfig;
	- 2.KUBECONFIG环境变量:其值是包含有kubeconfig文件的列表
	- 3.默认路径:$HOME/.kube/config
	
当然,我们也可以使用别名来使用上面任意一种方式来管理kubeconfig文件。

3.为静态令牌认证的用户生成kubeconfig实战

3.1 定义集群

	1.创建一个集群
[root@master231 ~]# kubectl config set-cluster myk8s --embed-certs=true --certificate-authority=/etc/kubernetes/pki/ca.crt --server="https://10.0.0.231:6443" --kubeconfig=./yinzhengjie-k8s.conf
Cluster "myk8s" set.
[root@master231 ~]# 
[root@master231 ~]# ll yinzhengjie-k8s.conf 
-rw------- 1 root root 1663 Feb 20 23:15 yinzhengjie-k8s.conf
[root@master231 ~]# 


	2.查看集群信息
[root@master231 ~]# kubectl config get-clusters --kubeconfig=./yinzhengjie-k8s.conf 
NAME
myk8s
[root@master231 ~]#  

3.2 定义用户

	1.查看令牌认证文件
[root@master231 ~]# cat /etc/kubernetes/yinzhengjie-authCase/token.csv
309837.3a7a5c1fe08fb422,yinzhengjie,10001,k8s
f2285b.39b1c2eeb4d22e51,jasonyin,10002,k8s
f13928.3c1423beb3eb5d98,jiege,10003,k3s
[root@master231 ~]# 

	2.创建用户信息
[root@master231 ~]# kubectl config set-credentials yinzhengjie --token="309837.3a7a5c1fe08fb422" --kubeconfig=./yinzhengjie-k8s.conf 
User "yinzhengjie" set.
[root@master231 ~]# 
[root@master231 ~]# kubectl config set-credentials jasonyin --token="f2285b.39b1c2eeb4d22e51" --kubeconfig=./yinzhengjie-k8s.conf 
User "jasonyin" set.
[root@master231 ~]# 

 
 
	3.查看用户信息
[root@master231 ~]# kubectl config get-users --kubeconfig=./yinzhengjie-k8s.conf 
NAME
jasonyin
yinzhengjie
[root@master231 ~]# 

3.3 定义上下文

	1.定义上下文
[root@master231 ~]# kubectl config set-context yinzhengjie@myk8s --user=yinzhengjie --cluster=myk8s --kubeconfig=./yinzhengjie-k8s.conf 
Context "yinzhengjie@myk8s" created.
[root@master231 ~]#
[root@master231 ~]# kubectl config set-context jasonyin@myk8s --user=jasonyin --cluster=myk8s --kubeconfig=./yinzhengjie-k8s.conf 
Context "jasonyin@myk8s" created.
[root@master231 ~]# 


	2.查看上下文列表
[root@master231 ~]# kubectl config get-contexts --kubeconfig=./yinzhengjie-k8s.conf 
CURRENT   NAME                CLUSTER   AUTHINFO      NAMESPACE
          jasonyin@myk8s      myk8s     jasonyin      
          yinzhengjie@myk8s   myk8s     yinzhengjie   
[root@master231 ~]# 

3.4 定义当前使用的上下文

	1.定义当前使用的上下文
[root@master231 ~]# kubectl config use-context yinzhengjie@myk8s --kubeconfig=./yinzhengjie-k8s.conf 
Switched to context "yinzhengjie@myk8s".
[root@master231 ~]# 

	2.查看当前使用的上下文
[root@master231 ~]# kubectl config current-context --kubeconfig=./yinzhengjie-k8s.conf 
yinzhengjie@myk8s
[root@master231 ~]# 
[root@master231 ~]# kubectl config get-contexts --kubeconfig=./yinzhengjie-k8s.conf 
CURRENT   NAME                CLUSTER   AUTHINFO      NAMESPACE
          jasonyin@myk8s      myk8s     jasonyin      
*         yinzhengjie@myk8s   myk8s     yinzhengjie   
[root@master231 ~]# 

3.5 查看kubeconfig信息

	1.打印kubeconfig信息,默认会使用“REDACTED”或者“DATA+OMITTED”关键字隐藏证书信息。
[root@master231 ~]# kubectl config view --kubeconfig=./yinzhengjie-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: yinzhengjie
  name: yinzhengjie@myk8s
current-context: yinzhengjie@myk8s
kind: Config
preferences: {}
users:
- name: jasonyin
  user:
    token: REDACTED
- name: yinzhengjie
  user:
    token: REDACTED
[root@master231 ~]# 



	2.查看源文件格式【危险,证书会被泄露】
[root@master231 ~]# kubectl config view --kubeconfig=./yinzhengjie-k8s.conf --raw 
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJME1USXhOVEEzTkRZek1Gb1hEVE0wTVRJeE16QTNORFl6TUZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTUk3CjQrNTBsR09mVm1TenRlL3R1SStqMlgvY2R3cWZWR0lydkN5TWROM3dFd3hnQjFhb3k0SDU1c2tIcUI0MGdRS3cKbXR4ZjVyRFlFRS9iMXdPWmdXL1h6RTU2dUx2enRvQjBtNEpmdVhGT3pMOExqVUx2OXMvbDVEUWFJOFVidVVSWApnZ1NEYnlhQnFqZDljcU0yY3hubjR3VC9SZktReURtaUJ2Nnp4MFd3USszMUlac3hDMzJGZU5Zb05GbWpxTjFpCnB4R09aRTN0QmtWYUl4cHVlRjdLVnpNQU1mMjR4NlcwZUZhd015LzZ6Wmt4emw2bDZ0cWh5cWVTUEltZm9lcW0KVVUwMzRYODNoUWdCalBEYU9nQ2gvMFUzbkZCWW5yN25DcTBUK1lPbmhaQ1NldUVxaU5Vd2JRTXFEUE04QzhlTQpPb29ZdkY4RGVXU3ZmNHo2aS9zQ0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZLbG9PNlZuelI3R0g3QW14ZUlrazRPMDZCTy9NQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBRmk5VkZnU2k4d2JrR1piYVVHTgpFYithMDRXenRXU1crTUVrTGNBYmNyYjhwaGlsa2NBY3puNitrRmhwUy92eWJ2N1ViSUlMUGZXRmp0SEdNSVNvCklRV3o5K0FsdDhieVZmMGR5cHdTVTlBZ1BnSXhySy90ZXNQc0ZmcmprK0w1elVHaUhpOEg1M09pZ3F1ZU1vYVAKL0pVQXZ5TitjeGEyYWF6ZDJiVUd5eVNjZEo5bU5Zd3RtenZxdFQyU3hzTU9MeUNQczBHS2YvNmV6UGpDUFhRYgpKWDhwTHpmclZwSzhRN1NxNGltS01EeldadFVQeURJQXo0RTE4WEZ4aTdUd1UxVDlNckd5dUREenRpOXQ2OUdiCnFid1VyQlk3ekg4cStCOGNCM0lwY014NzJBcllyQmxIVHdQYjZONU84aXZrb3hQOExNSVNmL0lpSXhGVXVWbUMKRDljPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://10.0.0.231:6443
  name: myk8s
contexts:
- context:
    cluster: myk8s
    user: jasonyin
  name: jasonyin@myk8s
- context:
    cluster: myk8s
    user: yinzhengjie
  name: yinzhengjie@myk8s
current-context: yinzhengjie@myk8s
kind: Config
preferences: {}
users:
- name: jasonyin
  user:
    token: f2285b.39b1c2eeb4d22e51
- name: yinzhengjie
  user:
    token: 309837.3a7a5c1fe08fb422
[root@master231 ~]# 

3.6 使用kubeconfig文件验证

	1.不难发现,默认使用的是"yinzhengjie@myk8s"上下文验证的
[root@master231 ~]# kubectl  --kubeconfig=./yinzhengjie-k8s.conf get nodes
Error from server (Forbidden): nodes is forbidden: User "yinzhengjie" cannot list resource "nodes" in API group "" at the cluster scope
[root@master231 ~]# 


	2.使用指定的"jasonyin@myk8s"上下文验证
[root@master231 ~]# kubectl  --kubeconfig=./yinzhengjie-k8s.conf get nodes --context="jasonyin@myk8s"
Error from server (Forbidden): nodes is forbidden: User "jasonyin" cannot list resource "nodes" in API group "" at the cluster scope
[root@master231 ~]# 

4.为X509 数字证书的用户生成kubeconfig实战

4.1 添加证书用户

	1.添加证书用户
[root@master231 ~]# kubectl config set-credentials jiege --client-certificate=/etc/kubernetes/pki/jiege.crt --client-key=/etc/kubernetes/pki/jiege.key --embed-certs=true --kubeconfig=./yinzhengjie-k8s.conf 
User "jiege" set.
[root@master231 ~]# 


	2.查看用户列表
[root@master231 ~]# kubectl config get-users --kubeconfig=./yinzhengjie-k8s.conf 
NAME
jasonyin
jiege
yinzhengjie
[root@master231 ~]# 

4.2 创建上下文

	1.配置上下文
[root@master231 ~]# kubectl config set-context jiege@myk8s --user=jiege --cluster=myk8s --kubeconfig=./yinzhengjie-k8s.conf 
Context "jiege@myk8s" created.
[root@master231 ~]#


	2.查看上下文列表
[root@master231 ~]# kubectl config get-contexts --kubeconfig=./yinzhengjie-k8s.conf 
CURRENT   NAME                CLUSTER   AUTHINFO      NAMESPACE
          jasonyin@myk8s      myk8s     jasonyin      
          jiege@myk8s         myk8s     jiege         
*         yinzhengjie@myk8s   myk8s     yinzhengjie   
[root@master231 ~]# 


	3.查看kubeconfig信息
[root@master231 ~]# kubectl  --kubeconfig=./yinzhengjie-k8s.conf config view
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: jiege
  name: jiege@myk8s
- context:
    cluster: myk8s
    user: yinzhengjie
  name: yinzhengjie@myk8s
current-context: yinzhengjie@myk8s
kind: Config
preferences: {}
users:
- name: jasonyin
  user:
    token: REDACTED
- name: jiege
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: yinzhengjie
  user:
    token: REDACTED
[root@master231 ~]# 

4.3 使用指定上下文访问验证

[root@master231 ~]# kubectl  --kubeconfig=./yinzhengjie-k8s.conf get nodes --context="jiege@myk8s"
Error from server (Forbidden): nodes is forbidden: User "jiege" cannot list resource "nodes" in API group "" at the cluster scope
[root@master231 ~]# 

5.合并kubeconfig文件案例

客户端能够通过多种途径获取到kubeconfig文件时,将遵循如下逻辑进行文件合并:
	1.设置了"--kubeconfig"参数时,则仅使用指定的文件,且不进行合并;该参数只能使用一次;
	2.否则,若设置了KUBECONFIG环境变量,则将其值用作应合并的文件列表;
	3.否则,将使用默认的“${HOME}/.kube/config”,且不进行合并

context的判定机制
	1.若使用了"--context"选项,则加载该选项指定要使用的上下文;
	2.否则,将使用合并后的kubeconfig文件中的current-context的设定;
	
	
合并kubeconfig文件案例:
	1.未合并前
[root@master231 ~]# kubectl config view 
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.0.0.231:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
[root@master231 ~]# 

	2.定义变量,配置多个kubeconfig文件路径
[root@master231 ~]# export KUBECONFIG='/root/yinzhengjie-k8s.conf:/etc/kubernetes/admin.conf'
[root@master231 ~]# 

	3.再次查看配置文件信息
[root@master231 ~]# kubectl config view 
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.0.0.231:6443
  name: kubernetes
- 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: jiege
  name: jiege@myk8s
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
- context:
    cluster: myk8s
    user: yinzhengjie
  name: yinzhengjie@myk8s
current-context: yinzhengjie@myk8s
kind: Config
preferences: {}
users:
- name: jasonyin
  user:
    token: REDACTED
- name: jiege
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: yinzhengjie
  user:
    token: REDACTED
[root@master231 ~]# 

五.Service Account实战

1.为何需要Service Account

Kubernetes原生(kubernetes-native)托管运行于Kubernetes之上,通常需要直接与API Server进行交互以获取必要的信息。

API Server同样需要对这类来自于Pod资源中客户端程序进行身份验证,Service Account也就是设计专用于这类场景的账号。

ServiceAccount是API Server支持的标准资源类型之一。
	- 1.基于资源对象保存ServiceAccount的数据;
	- 2.认证信息保存于ServiceAccount对象专用的Secret中(v1.23-版本)
	- 3.隶属名称空间级别,专供集群上的Pod中的进程访问API Server时使用;

2.Pod使用ServiceAccount方式

在Pod上使用Service Account通常有两种方式:
	自动设定:
		Service Account通常由API Server自动创建并通过ServiceAccount准入控制器自动关联到集群中创建的每个Pod上。
		
	自定义:
		在Pod规范上,使用serviceAccountName指定要使用的特定ServiceAccount。

Kubernetes基于三个组件完成Pod上serviceaccount的自动化,分别对应: ServiceAccount Admission Controller,Token Controller,ServiceAccount Controller。
	- ServiceAccount Admission Controller:
		API Server准入控制器插件,主要负责完成Pod上的ServiceAccount的自动化。
		为每个名称空间自动生成一个"default"的sa,若用户未指定sa,则默认使用"default"。
   
	- Token Controller:
		为每一个sa分配一个token的组件,已经集成到Controller manager的组件中。
	
	- ServiceAccount Controller:
		为sa生成对应的数据信息,已经集成到Controller manager的组件中。

温馨提示:
	需要用到特殊权限时,可为Pod指定要使用的自定义ServiceAccount资源对象

3.ServiceAccount Token的不同实现方式

ServiceAccount使用专用的Secret对象(Kubernetes v1.23-)存储相关的敏感信息
	- 1.Secret对象的类型标识为“kubernetes.io/serviceaccount”
	- 2.该Secret对象会自动附带认证到API Server用到的Token,也称为ServiceAccount Token
	

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.ServiceAccount中的数据

如上图所示,ServiceAccount专用的Secret对象有三个固定的数据项,它们的键名称分别为:
	ca.crt:
		Kubernetes CA的数字证书。
	namespace:
		该ServiceAccount可适用的名称空间。
	token:
		认证到API Server的令牌,其生成方式曾多次变动。
		
温馨提示:
	若需要一个永不过期的Token,可手动创建ServiceAccount专用类型的Secret,并将其关联到ServiceAccount之上。

5.Pod基于projected存储卷引用ServiceAccount案例

如下图所示,Kubernetes v1.21+版本中,Pod加载上面三种数据的方式,改变为基于projected卷插件,通过三个数据源(source)分别进行
	serviceAccountToken:
		提供由Kubelet负责向TokenRequest API请求生成的Token。
	configMap:
		经由kube-root-ca.crt这个ConfigMap对象的ca.crt键,引用Kubernetes CA的证书
	downwardAPI:
		基于fieldRef,获取当前Pod所处的名称空间。
		
		

实战案例:
[root@master231 ~]# kubectl get pods -o wide
NAME         READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
xiuxian-v1   1/1     Running   0          39m   10.100.203.145   worker232   <none>           <none>
xiuxian-v2   1/1     Running   0          39m   10.100.140.83    worker233   <none>           <none>
[root@master231 ~]# 
[root@master231 ~]# kubectl get pods xiuxian-v1 -o yaml
apiVersion: v1
kind: Pod
metadata:
  ...
  name: xiuxian-v1
  namespace: default
  ...
spec:
  containers:
  - image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1
    ...
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: kube-api-access-v929g
      readOnly: true
  ...
  serviceAccount: default
  serviceAccountName: default
  ...
  volumes:
  - name: kube-api-access-v929g
    projected:
      defaultMode: 420
      sources:
      - serviceAccountToken:
          expirationSeconds: 3607
          path: token
      - configMap:
          items:
          - key: ca.crt
            path: ca.crt
          name: kube-root-ca.crt
      - downwardAPI:
          items:
          - fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
            path: namespace
status:
  ...
[root@master231 ~]# 

posted @ 2025-02-21 00:49  尹正杰  阅读(193)  评论(2)    收藏  举报