客戶端請求API Server過程
客戶端 --> API Server(識別用戶是否有通過api server執行操作的權限)
api Server識別內容:
user: username,uid
group: 用戶組
extra: 字段,提供額外信息
客戶端請求的API(Request Path):
例如客戶端對一個k8s集群中的名為myapp-deploy的deployment的資源發起請求,地址為下,成功的話則可進行增刪改查;
http://192.168.133.128:6443/apis/apps/v1/namespaces/default/deployments/myapp-deploy
注釋:
192.168.222.100: master地址
6443: API server端口
apis: 固定入口(除核心群組(/api/v1/)外)
apps: app組
v1: 組版本
namespaces: 名稱空間級別
default: 名稱空間的名稱
deployments: 訪問deployment資源
myapp-deploy: deployment名稱
請求操作(action):
http的方法請求:
get
post
put
delete
k8s請求動作:
增: create
刪: delete,deletecollection(刪除一個集合)
改: edit,patch
查: get,list,watch(-w)
API Server是整個訪問請求進入的網關接口,請求過程中
認證用於實現身份識別;
授權用於實現權限檢查,檢查用戶是否擁有對資源執行各種k8s請求動作;
准入控制機制用來進一步補充授權機制,創建、刪除、修改時需要;
k8s集群有兩類認證時的認證賬號:
1. useraccount
2. serviceaccount
訪問API Server的客戶端分為以下兩類:
1. 集群之外的客戶端訪問節點地址進行通信;
2. 集群內部的Pod等,使用API Server在集群內的地址(kubectl get svc(kubernetes這個svc),將集群外部地址引入到集群內部供內部組件使用;
# 經過查看某一個Pod的詳細信息發現Pod會自動擁有一個Volumes,這個Volumes的名稱叫做"default-token-ppzsj"也就是令牌,這就是Pod連接API Server的認證信息,通過secret來定義,並以存儲卷的方式關聯到Pod上,
使Pod內的運行的應用通過對應的secret中保存的認證信息連接API Server來完成認證的;
$ kubectl describe pod deploy-demo-854b57c687-f7txr .... Volumes: default-token-ppzsj: Type: Secret (a volume populated by a Secret) SecretName: default-token-ppzsj Optional: false QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300s ....
# 經查,發現每個名稱空間下都會有一個默認的secret(default-token-ppzsj)
$ kubectl get secret NAME TYPE DATA AGE default-token-ppzsj kubernetes.io/service-account-token 3 26d
創建Pod與API Server通信的serviceaccount(與權限無關,僅認證):
# 首先查看系統上已有的serviceaccount; $ kubectl get serviceaccount NAME SECRETS AGE default 1 26d # 直接使用create創建一個名為admin的sa; $ kubectl create sa admin # 再次查詢,發現創建成功; $ kubectl get sa NAME SECRETS AGE admin 1 84s default 1 26d # 查看sa的詳細信息,發現了名為"admin-token-pfp5j"的secret; $ kubectl describe sa admin Name: admin Namespace: default Labels: <none> Annotations: <none> Image pull secrets: <none> Mountable secrets: admin-token-pfp5j Tokens: admin-token-pfp5j Events: <none> # 查看secret,發現剛創建的sa自動創建了一個"admin-token-pfp5j"secret; $ kubectl get secret NAME TYPE DATA AGE admin-token-pfp5j kubernetes.io/service-account-token 3 2m32s default-token-ppzsj kubernetes.io/service-account-token 3 26d # 創建Pod使用新創建的sa; $ vim pod-sa.yaml apiVersion: v1 kind: Pod metadata: name: pod-sa namespace: default spec: containers: - name: sa-container image: ikubernetes/myapp:v1 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 # 自定義serviceaccount的名稱 serviceAccountName: admin $ kubectl apply -f pod-sa.yaml # 查看詳細信息發現默認自帶的volumes中的名稱變為了"admin-token-pfp5j"也就是我們剛創建sa后,集群自動幫我們創建的secret; $ kubectl describe pods pod-sa .... Volumes: admin-token-pfp5j: Type: Secret (a volume populated by a Secret) SecretName: admin-token-pfp5j Optional: false QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300s ....
配置文件連接API Server:
API Server的客戶端在認證時,如果我們要基於配置文件來保存客戶端的認證信息,就要配置個配置文件,k8s集群中的所有組件,除API Server外都需要連接至API Server,都需要被API Server認證
每一個組件為了能夠連入正確的集群,提供正確的賬號、證書、私鑰等認證信息,需要將這些信息保存為配置文件(kubeconfig),也就是API Server的客戶端連入API Server時使用的認證格式的配置文件;
# 查看配置 $ kubectl config view apiVersion: v1 clusters: - cluster: certificate-authority-data: DATA+OMITTED server: https://192.168.133.128: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
注釋:
clusters: 集群列表,可以包含多個集群
certificate-authority-data: 認證方式
server: API Server路徑
name: 集群名稱
users: 用戶列表
name: 用戶賬號名
client-certificate-data: 客戶端證書
client-key-data: 客戶端私鑰
contexts: 上下文列表,一個上下文用來指明哪個賬號管理哪個集群;
cluster: 訪問哪個集群
user: 使用哪個用戶
name: 給上下文取名
current-context: 當前上下文,當前使用哪個賬號管理哪個集群;
由於客戶端連入API Server要做雙向認證,所以可以去"/etc/kubernetes/pki"目錄下找到各種key、ca;
創建新賬號來連接API Server
# cd /etc/kubernetes/pki # (umask 077; openssl genrsa -out kfree.key 2048) # openssl req -new -key kfree.key -out kfree.csr -subj "/CN=kfree" # openssl x509 -req -in kfree.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -out kfree.crt -days 365 # su - kubeadm $ kubectl config set-credentials kfree --client-certificate=/etc/kubernetes/pki/kfree.crt --client-key=/etc/kubernetes/pki/kfree.key $ kubectl config set-context kfree@kubernetes --cluster=kubernetes --user=kfree $ kubectl config view apiVersion: v1 clusters: - cluster: certificate-authority-data: DATA+OMITTED server: https://192.168.133.128:6443
name: kubernetes contexts: - context: cluster: kubernetes user: kfree name: kfree@kubernetes - context: cluster: kubernetes user: kubernetes-admin name: kubernetes-admin@kubernetes current-context: kubernetes-admin@kubernetes kind: Config preferences: {} users: - name: kfree user: client-certificate: /etc/kubernetes/pki/kfree.crt client-key: /etc/kubernetes/pki/kfree.key - name: kubernetes-admin user: client-certificate-data: REDACTED client-key-data: REDACTED
$ kubectl config use-context kfree@kubernetes # 因為我們只處理了認證,沒有授予權限,所以沒有權限的; $ kubectl get pods Error from server (Forbidden): pods is forbidden: User "kfree" cannot list resource "pods" in API group "" in the namespace "default"