一、課程回顧及安全重要性
-
課程總結:節點上組件間的關系及作用
-
etcd :
- 在k8s中扮演了狀態存儲系統,存儲了當前集群的每一個節點的用戶定義的相關的期望狀態及當前集群中資源運行的狀態,保存在etcd的spec和status當中,當然有一些資源是沒有spec字段比如ConfigMap和Secret資源,但是此類資源中其實也是存在spec的只不過是過於簡單沒有進行其狀態嵌套而已。
- 如果etcd宕機或者數據丟失,則導致整個集群的所有狀態則丟失,所以一般來說一定要對etcd做高可用,etcd本身是一個有狀態應用,如果etcd自身也運行在k8s之上我們就應該使用一個Operator或者使用StatefulSet來對其進行管理。
- 此前使用kubeadm方式進行部署,僅對etcd僅部署了一個實例,並非三個,所以是很有風險的,所以說kubeadm方式部署k8s集群是不太適用於生產環境的。
-
API Server :
- 在k8s之上部署的一個應用程序或者運行的運行的守護進程稱之為Kube-apiserver,確實整個ectd存儲服務的存儲服務的訪問入口,可以說集群中所有的有狀態信息都必須保存在etcd中,任何客戶端都不能直接寫入,可以理解為etcd的唯一客戶端就是API Server。
- 用戶想要創建比如一個Pod資源,通常用戶應該使用像kubectl這樣的客戶端工具與API Server通訊,將數據線交給API Server,再由API Server存儲到etcd中,因此可以理解為API Server是我們接入整個k8s集群的網關。
- 這里拿創建一個Pod實例流程進行概述:
- 1、通常用戶應該使用像kubectl這樣的客戶端工具與API Server通訊,將數據線交給API Server,再由API Server存儲到etcd中,因此可以理解為API Server是我們接入整個k8s集群的網關。
- 2、Pod是如果被調度到集群節點的Worker-Node節點之上的,由這個Node節點上的kubectl調用docker將其運行Pod資源
- 調度器如何知道由一個新建的Pod產生?
- kube-scheduler也是API Server的客戶端之一,一旦有kebectl提交了一個新的Pod定義交給API Server,API Server自己把etcd的數據變動能夠通知給注冊、監視相關資源的程序,而kube-scheduler就像API Server中注冊了哪個沒有被調度結果的Pod信息,需要通過API Server完成Pod的查詢、修改,最后通過API Server將調度的結果保存到etcd當中
- 調度器如何知道由一個新建的Pod產生?
-
Controller-manager
- controller-manager當中運行了很多contraller,在運行着很多的Contraller-loop也可以稱之為和解循環
- 和解循環的相關操作必要時又可能需要獲取到當前集群中對應的每一個資源的真實狀態,並將其狀態更新並保存至kube-api server中,Contraller-loop也不能直接操作etcd,必須向API Server發起請求,所以Contraller-Manager也是API Server的客戶端
-kubectl (每一個Node節點運行)
- kubectl作為k8s集群中運行在每一個節點之上的代理程序,它用與獲取API Server加載對Pod的定義,並加載本地node節點的Docker引擎將其運行為容器,但是在kubernetes表現為Pod
- Kubectl 和其他資源一樣需要注冊監聽在於自己節點上的Pod的相關信息,kubectl創建完本機節點的Pod資源之后,也需要將自己節點上的Pod信息比如Pod啟動成功與否等信息保存在etcd當中,也需要借助API Server
- 所以API Server 是操作etcd存儲的唯一入口,也可以稱之為HUB
-
Kube-proxy
- API Server上有所有用戶提交的關於Service的定義,都會被Kube-proxy所捕獲,並讀取到本機,並將其轉換為IPVS或者IPTABLES規則,而Service的定義一定是在API Server上,Kube-proxy也是扮演的API Server的客戶端將本機的Service當前狀態保存到etcd當中
- API Server作為Kubernetes網關,是訪問和管理資源對象的唯一入口,其各種集群組件訪問資源都需要經過網關才能進行正常訪問和管理。每一次的訪問請求都需要進行合法性的檢驗,其中包括身份驗證、操作權限驗證以及操作規范驗證等,需要通過一系列驗證通過之后才能訪問或者存儲數據到etcd當中。如下圖:
二、認證
2.1、權限模型介紹及操作邏輯
- 不同的應用程序需要我們組織不同的權限模型,為此k8s在API Server內部通過三類插件分別完成以下功能
- Client → API Server (authentication)→ Auth policies → Admission Contol → Allow access
- authentication 認證插件 : 自上而下,認證邏輯為一票通過可以理解為短路操作(邏輯或)
- Auth policies 授權插件 : 自上而下,授權邏輯為一票通過可以理解為短路操作(邏輯或)
- Admission Contol 准入控制插件 :自上而下,控制邏輯為一票否決(每一個控制都要檢查,所有認證都要通過准入控制檢查)
2.2、K8s支持的認證方式(authentication)
具體來說, API Server 支持以下幾種具體的認證方式,其中所有的令牌認證機制通常被統稱為承載令牌認證
- 1、X509客戶端證書認證
- 客戶端在請求報文 中攜帶 X509 格式的數字證書用於認證,認證通過后,證書中的主體標識( ubj ect )將被識別為用戶標識,其中的 CN (CommonName 宇段是用戶名, (Organization )是用戶所屬的組,如“/CN=iIinux/O=opmasters/ O=admin ”中 ,用戶名為 ilinux ,其屬於 opmasters admin 兩個組
- 2、靜態令牌文件
- ( Static Token File )即保存着令牌信息的文件,由 kube apiserver 的命令行選項 token -au th file 加載,且服務器啟動后不可更改; HTTP 客戶端也能使用承載令牌進行身份驗證,將令牌進行編碼后,通過請求報文 中的 Authorization 首部承載傳遞給API Server即可
- 3、引導令牌
- ( Bootstrap Tokens ):一種動態管理承載令牌進行身份認證的方式,常用於 簡化新建 ub metes 集群的節點認證過程,需要通過一experimental-bootstrap-token auth 選項啟用;有新的工作節點首次加入時, Master 使用引導令牌確認節點身份的合法性之后自動為其簽署數字證書以用於后續的安全通信,使用 kubeadm join 令將節點加入 kubeadm初始化的集群時使用的即是這種認證方式;這些令牌作為 Secrets 存儲在 kube-syst 命名空間中時,可以動態管理和創建它們,而 Controller Manager 包含 Token Cleaner 控制器,用於刪除過期的引導令牌
- 4、靜態密碼文件
- 用戶名和密碼等令牌以明文格式存儲的 csv 格式文件,由 kube apiserver 使用 bas ic auth-fil 選項進行加載;客戶端在 HTTP basic 認證中將認證用戶的用戶名和密碼編碼后以承載令牌 的格式進行認證
- 5、服務賬戶令牌
- 由 kube-apiserver 自動啟用,並可使用可選選項加載 --service-account-key-file 驗證承載令牌的密鑰,省略時將使用 kube-apiserver 自己的證書匹配的私鑰文件;Service Account 通常由 API Server 自動創建並通過 ServiceAccount 准入控制器將其注入Pod 對象,包括 Service Account 上的承載令牌,容器中的應用程序請求 API Server 的服務時將以此完成身份認證
- 6、OpenID連接令牌
- OAuth2 的一種認證風格,由 Azure AD Salesforc 巳和 Google 等0Auth2 服務商所支持,協議的主要擴展是返回的附加字段,其中的訪問令牌也稱為 ID 令牌 ;它屬於 JSON Web 令牌( JWT )類型,有着服務器簽名過的常用字段,如 email 等;kube-apiserver 啟用這種認證功能的相關選項較多
- 7、Webhook令牌
- HTTP 身份驗證允許將服務器的 URL 注冊為 Webhook ,並接收帶有承載令牌的 POST 請求進行身份認證;客戶端使用 kubeconfig 格式的配置文件,在文件中,“ users ”指的是 API 服務器 Webhook ,“ clusters ”指的是 API Server。
- 8、認證代理
- API Server 支持從請求首部的值中識別用戶,如 Remote User 首部,它旨在與身份驗證代理服務相結合,並由該代理設置相應的請求首部
- 9、Keystone密碼
- 借助於外部的 Keystone 務器進行身份認證
- 10、匿名請求
- 未被任何驗證機制明確拒絕的用戶即為匿名用戶,其會被自動標識 為用戶名 system:anonymous ,並隸屬於 system:unauthenticated 用戶組;在 API Server 啟用了除 AlwaysA!low 以外的認證機制時,匿名用戶處於啟用狀態,不過,管理員可通過--anonymous auth=false 選項將其禁用
2.3、K8s支持的認證功能
- 一個API 請求要么以常規用戶的身份進行,要么以某特定服務賬號的身份進行,否則統一被視為匿名用戶。
- 無論來自於Kubernetes集群內或集群外的任何進程的請求,都必須由API Server實現完成認證;常見的客戶端進程包括:
- kube-scheduler
- kube-controller-manager
- kubectl
- kubelet
- kube-proxy
- Dashboard、CoreDNS、Flannel等
- 集群上運行於Pod中的進程認證時使用的賬號即Service Account
[root@k8s ~]# ls /etc/kubernetes/
admin.conf controller-manager.conf kubelet.conf manifests pki scheduler.conf
2.4、K8S中用戶賬戶與用戶組
- Kubernetes 並不會存儲由認證插件從客戶端請求中提取出的用戶及所屬組的信息,它們僅僅用於檢驗用戶是否有權限執行其所請求的操作 客戶端訪問 AP 務的途徑通常有種: kubectl 客戶端庫或者 接使用 REST 接口進行請求,而可以執行此類請求的主體也被Kubernetes 分為兩類:現實中的“人”和 Pod 象,它們的用戶身份分別對應於常規用戶(User Account )和服務賬號 (Service Account)
User Account (用戶賬號 → 人類用戶在系統上不存在即使用加密方式進程認證不關系用戶名)
: 一般是指由獨立於 kubernete 之外的其他服務管理的用戶賬號,例如由管理員分發的密鑰 Keystone 一類的用戶存儲(賬號庫)、甚至是包含有用戶名和密碼列表的文件等 Kubernetes 不存在表示 類用戶賬號的對象,因此不能被直接添加進 Kubernetes 系統中。Sevice Account (服務賬號 → 程序自身運行所需要的賬號,真實存在)
: 是指 kubernetes API 管理的賬號,用於為 Pod 之中的服務進程在訪問 Kubernetes API 時提供身份標識( identity Service Account 通常要綁定於特定的名稱空間,它們由 API Server 建,或者通過 API 用於動創建,附帶着一組存儲為 cret 的用於訪問 API Server 的憑據。
# Service Account 服務賬號,k8s會通過一個標准的資源簡稱為sa
-
User Account 通常用於復雜的業務邏輯管控,它作用於系統全局,故其名稱必須 局唯相比較來說, Service Account 隸屬於名稱空間,僅用於實現某些特定的操作任務,因此要輕量得多 這兩類賬號都可以隸屬於一個或多個用戶組 用戶組只是用戶賬號的邏輯集合,它本身並沒有操作權限,但附加於組上的權限可由其內部的所有用戶繼承,以實現高效的授權管理機制 Kubernetes 有着以下幾個內建的用於特殊目的的組。
- system:unauthenticated :未能通過任何 個授權插件檢驗的賬號,即未通過認證測試的用戶所屬的組
- system :authenticated :認證成功后的用戶自動加入的 個組,用於快捷引用所有正常通過認證的用戶賬號
- system seviceaccounts :當前系統上的所有 Service Account 對象
- system :serviceaccounts : <namespace >:特定名稱空間內所有的 Service Account 對象
-
API 請求要么與普通用戶或服務賬戶進行綁定,要么被視為匿名請求 這意味着群集內部或外部的每個進程,包括由人類用戶使用的 kubectl ,到節點上的 ubelet ,再到控制平面的成員組件,必須在向 API 服務器發出請求時進行身份驗證,否則即被視為匿名用戶
2.5、Kubeconfig(任何客戶端需要連入K8S都需要借助Kubeconfig配置文件)→ 普通用戶
2.5.1、Kubeconfig介紹
- 一個Kubeconfig文件是YAML格式的配置文件,它通常由以下幾個配置段組成:
- users : 用戶賬號及其認證信息列表
- cluster : 目標集群列表
- cntexts : 以哪個user接入那個clusterr的連接組合
- curren-context : 當前使用的context
~]# cat /etc/kubernetes/admin.conf
apiVersion: v1
clusters:
# 目標集群列表
- cluster:
# 集群中被API Server所信任的證書
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJd01EUXlOREUyTkRrd05Gb1hEVE13TURReU1qRTJORGt3TkZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTkhKCjE4WTNjcCtUNSsrRnBzWnZuVmNwejhIalpuV0Z4TzNvRXpyRDBYd1gxN01rSkxOQjNySGlSenp3blZvRVppKzMKZE5rOGRPem5XOCtlV0U1UjNQOFhlUDRkUEFab0FlT1Nvc1JIYnpqMGsydlFiSHJuV0dlZDhQZ001R015em82UQorRUFKeTBvd0tZeXBET1VERjViQ1NyYjFxY3NTUWZzZHlFQXFlL2VNY3B6UDhZR3pscCt1bGhsUTlNeTBINWtHCmV0bDBYTG5wNm9SVDlyaVlSZEE3NFhCcjhlRExGZ3RjVVpDdWVSM0c1akQyZjBneDhmTmcxcnZBc1FNOWcxWUsKczdlZDE2bDJHZGpFWUxWQ3N6Q01IZXVCeEE1Z2EwNzNhUG9hZWNtcU5NK0FsemZrTVNnZ29qQnVoMFdzbTQ2MQpZczhLM1RYY1VpaTVObG41L0pjQ0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFGWXdWS3VTNjRGVHZaTzJFM2ZPTGZvYVBZRWQKUXg3SDdYbnNkZVRRR2ROd2JzMzhFRU91bDJzYVBRY0xCdjZNS1VQWVlNUjNJdTBkZ0hBRFZtRkwrQkdZajhqSQpYSkh0VlovY3VzV3dPY3FkUGRmaUlJektNNnlpdDJ2WnJieDJ0Nm5mdXVPM1lwZUtVUVJ5aXhxbitoTDVsTVJUCldya0dMcUhYSy9oc1kvdkl1dFMzdk9CVlR4ZUhPSk9VVDdESytuL09FNGs2anFmTGNqY3dKTVNOZ0hZOGc1YmcKYnRhcWlRZFpNajBrMkRkdDA0VGZmaWNNdlJpTVVDUHJRQmM5TS9LUGpKcHV3Z0hkZUhrd1pIMXRrcVZWMzgxKwpTem1pUS9xS1ViSWZad3FSYitpclpWMFp3SnRXQWU5Y0dzYTYyeGpTVkF0YmN6cWF5ZDllRWJ2a1RXTT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
# 集群的訪問地址和端口
server: https://192.168.20.236:6443
# 集群名稱
name: kubernetes
# 以哪個user接入那個clusterr的連接組合
contexts:
- context:
# 集群名稱
cluster: kubernetes
# 哪個用戶可以接入此集群
user: kubernetes-admin
# 接入的集群名稱
name: kubernetes-admin@kubernetes
# 當前使用的context
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
# 用戶列表
users:
# 用戶名稱
- name: kubernetes-admin
# 定義用戶信息,用戶憑證
user:
# 用戶證書
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM4akNDQWRxZ0F3SUJBZ0lJSUZaWTVkYlo1aW93RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TURBME1qUXhOalE1TURSYUZ3MHlNVEEwTWpReE5qUTVNVE5hTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXUxQVJQSjR6dkw4UmRYRFoKQk1OdjRHUXdOSTgzdEpXWUMyNlgvbTIrZG9FZEJkUi9iTlVuSURwNWg3MlFJUk5KWERVQjl5Rk1DLzBOdHBCTQo3dHJ3ajVHdERmdU9qRmtNdGNpY253RWdTZk93b2VOcjdGS0oyTVJmOElNSW1zS2d0TW04bmorSlltN2hPL3N4CkRVZUdGclMxSXJ6LzBkcTluR3FRSkg1WTFWaTBTMEtCbXV1WngxdEJEdUozTWJaeW1IK0lvMW96bHEzQ3kyZEUKWDZSUG5RTlpNWjRxVlZTUk0yZm5VeGc3dGNyME9TOUsvMEs0TS9DNXZiZ3RGeVJBSEcySEV4d2NTL0tETUJITwp3V0lMMmpXc0tIeDZMeGN2R3BBYXE3ditua3NLanpsU1Z0V1hBVW11K3grK1JFNExFQjBIY3hYNXczUFFCWFBJCjJTcXBPd0lEQVFBQm95Y3dKVEFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFKVlg3Nzd1OXlXU1JybUZ4cmRLSVg5UEREWktYY05odUhoeQphbFpNamp2WHNFUmh3cTM5cGdkT1hBaStobjIvRTZ1eGh3TnhwQVZFbjBkMDgxcytBbTdBbmhQQy85cTU2bi9xCjE3bFVUV2V1c2Vhb0lPSDRlTXdWOXV5T1Q0dzJyN21jOHVnWUFsaXkvamNjaTNDR3dEckpIK3cyOEhuVElkci8KMnJ1YmlUTUttQkdRQlNnNnkrQ0plQ05QNDlnNWFoOHQ2S0QxQnE2MEtHN2NJVW1sNEIwUTdSSXA4RUt6U0JOTwp5Y3BhR3JiU0U4czBPazRZLzM4NmxqZUU4WnoraTJtVTZIY0hKa1dKblhEMmtKclJPczBRcVFSbDJqSlNFNjBLCkNDRWNqYWtuYTNqSFN2RkZEZmY1ek1JSzRZY2ZlQjlsZk8xdGpFdjNBNi9Wd1BEMU5hST0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
# 用戶私鑰
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBdTFBUlBKNHp2TDhSZFhEWkJNTnY0R1F3Tkk4M3RKV1lDMjZYL20yK2RvRWRCZFIvCmJOVW5JRHA1aDcyUUlSTkpYRFVCOXlGTUMvME50cEJNN3Ryd2o1R3REZnVPakZrTXRjaWNud0VnU2ZPd29lTnIKN0ZLSjJNUmY4SU1JbXNLZ3RNbThuaitKWW03aE8vc3hEVWVHRnJTMUlyei8wZHE5bkdxUUpINVkxVmkwUzBLQgptdXVaeDF0QkR1SjNNYlp5bUgrSW8xb3pscTNDeTJkRVg2UlBuUU5aTVo0cVZWU1JNMmZuVXhnN3RjcjBPUzlLCi8wSzRNL0M1dmJndEZ5UkFIRzJIRXh3Y1MvS0RNQkhPd1dJTDJqV3NLSHg2THhjdkdwQWFxN3YrbmtzS2p6bFMKVnRXWEFVbXUreCsrUkU0TEVCMEhjeFg1dzNQUUJYUEkyU3FwT3dJREFRQUJBb0lCQUh1ZDNMSkhxZGRQdFlMdgpCWm9hTE5SRzZuVlZheXIzYXM5b25sQ2dOb2xZcmtHeHVxS2xqVnU4bTRYVXViREtYS2pJcHRKa25CNXhVOEovCk92YUxjU1VldTdtMW9aN0lDaFpTSGVMbHlGeGx3ZFVsRkkxeTcxd3FSVEtpRjJTak81SDBiVkYybHdGcU1hVDMKSXFrajRiOU1aUnBXNXZHa3pXdlQrK3JKbzNDd0o4citBekx6MHE0MHU1WFVLK3huU2dxeXFPRXFWN05DaTF5NApERHVZUzAybXhPaFhyd1grSmpidlJoMFRhdmxhemZuUFNPY1VYNWx4Y1lXY0llZEV4UVlycFc0aW44UUE4UStCCjdtaThvYXQ5WkpKVzYyRytiUDE5N1BySi8zUkVBSmZSRFA5bW43aUxLTkd2azV2WXBFaENWQ2hhZjh5QmN1blAKWGdFbmpxRUNnWUVBMjh3TnArTlVnY1hkR1VlVkJvOW56MVFLNFB4RVJXalpNTVFDWm9mTXdRQlVFV0wyejQyRgpZZlRxZ2IwbE9MRmhLQVRCSTVEOTZPM2FpM0p4VG1zbDJpUWtkU1ZRV21wUlhyaHBRR3ZNampkK3NNa1k3SkFzCnNOVlIyZHFTL05nV29ieGVIaVlUVkp4eTlDaWF1cUQ0V2xvRkpIc2pvVytYVE1XMURTWXZLS3NDZ1lFQTJpcEkKWFROZDdrdCtyVy9KV1RjZEs2bmEwdjMvZjVlSkJIVkoyOWEyM0lrQ2ZGSEVQS01qOWRSMGdCZzNUZUFhRmRzLwpnN1h6ai9LNVhEbUZwaUc4TmdWWnVPMVhBRDdaT3R5dFR6UnpFZG5jZEZEY1k5WEdHdTF4TUZRY1pHbHFyOTBqCnVzN2hMRm5NK1NUTlpTbHdTZ3EvamtuRnAva0lwMVhTTHhYMG9iRUNnWUFyYWkzVVdLbnJqRHEwOEplMkdRTm4KUjNGeXFVR08rRHZXVHhFdVVXcVhRTXBhT05NSmdpbXpoSjRCakd2YXUrYTE4ZUo0ZFA1Q1VTRVc1RDhQUDBqVgp3c2ZVdjg4VVhPVy9zT3RSUnptN2FhakRvS1VrclFHMjJCdjN6UjIxaGJWS3N4dGdGeU5BVmpxNmtYNm1tSDhWCjBhd3NYWXBYSytTVnpJT0xtbHc4U3dLQmdFeGlkWWU4VG16Nm5kWFh4K1dtdUYzclVLU0RMZ3ZjWUtyZzdnVTgKdmpXayt1dlFMU2NWNzZkSXhhbDcwUkZCSDZEN2JOZU93MEpwTjZFa3VyaWFJeTIrM2RVenREeHZ4TnNwSEwwWQpuaGxuOEJvQm5jaU90cGdDL3Bodk9xbWxoeWNnQkR5SjVxa0NvQk96WVA3RWJYNWZHUWFXcWMvUUQ4bVc4TXB2Cm80RmhBb0dCQUpuMmYxbVVHVEdlOTNNZmNUeXlFTEFtMWF3dDJ2L2ZzODNUYVRzYURHT0ZnQWJ4cytvdXdTZjUKU2xnZkx5YWZnQnZ0YjhMR2lwZFQrL3locUVOcVV0dExVT01PUVZGbnR3OS9pVCtsRWl4RENGWjRQbVE2WmpLcwpuRmFBeHBVVFk1VWgvTVVxU05JRmRhdmUzRWtKNWl4NitqTVdGcm9jVE01UjA3V0pTM1lDCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
- name: ui-admin
user:
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IkdlVkVpWXIwU0FEVmVDT2pwbGtraTlhWDY2UmFCd2ZhUHM3emtqY0VqT0UifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJ1aS1hZG1pbi10b2tlbi0yMnFoMiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJ1aS1hZG1pbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjdhOWExNGI3LTI3MGQtNGY0ZS05YmYxLTUxMDBlYzc2YTVjNCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTp1aS1hZG1pbiJ9.iXWwtlH2DUKiNTV6TnuVG2nyKtpY4D8jykFuiQRYp4xt-wh-4gN2-KYJ_TpSJs3M6NvbkJ-dfWXThiuznSZEno9Ay7Vnhxv63vAW9QoyDK9tNfUlSMkjGOlnktT0X7nZvucMWfG53R_I7qU-ExjYIGR3J1Ur_Mlgia7ejkxVP3Dd7QhTqy__wK6RBZp2cIH0aGUJbMAHEa8ycI6bkMzeF5V6K6GEVxUM6nadWvVtEMKs4EkEZD-XvTeaNTyNwrLcbwS0d8y-FCMXXIqHMYvuNk3SI7F_MvyuBttQYHTNGnE9GTlyFyAD9TP8NTsgpZ5hIgu3k8UUXv5fQ99HB4XbMA
-----------------------------------------------
# 使用view方式顯示
~]# kubectl --kubeconfig=/etc/kubernetes/admin.conf config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.20.236: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
- name: ui-admin
user:
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IkdlVkVpWXIwU0FEVmVDT2pwbGtraTlhWDY2UmFCd2ZhUHM3emtqY0VqT0UifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJ1aS1hZG1pbi10b2tlbi0yMnFoMiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJ1aS1hZG1pbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjdhOWExNGI3LTI3MGQtNGY0ZS05YmYxLTUxMDBlYzc2YTVjNCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTp1aS1hZG1pbiJ9.iXWwtlH2DUKiNTV6TnuVG2nyKtpY4D8jykFuiQRYp4xt-wh-4gN2-KYJ_TpSJs3M6NvbkJ-dfWXThiuznSZEno9Ay7Vnhxv63vAW9QoyDK9tNfUlSMkjGOlnktT0X7nZvucMWfG53R_I7qU-ExjYIGR3J1Ur_Mlgia7ejkxVP3Dd7QhTqy__wK6RBZp2cIH0aGUJbMAHEa8ycI6bkMzeF5V6K6GEVxUM6nadWvVtEMKs4EkEZD-XvTeaNTyNwrLcbwS0d8y-FCMXXIqHMYvuNk3SI7F_MvyuBttQYHTNGnE9GTlyFyAD9TP8NTsgpZ5hIgu3k8UUXv5fQ99HB4XbMA
-----------------------------------------------
# 獲取集群名稱
~]# kubectl --kubeconfig=/etc/kubernetes/admin.conf config get-clusters
NAME
kubernetes
-----------------------------------------------
# 獲取上下文
~]# kubectl --kubeconfig=/etc/kubernetes/admin.conf config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* kubernetes-admin@kubernetes kubernetes kubernetes-admin
-----------------------------------------------
# 獲取當前連入上下文
~]# kubectl --kubeconfig=/etc/kubernetes/admin.conf config current-context
kubernetes-admin@kubernetes
- 我們也可以自己做自己需要的賬號:
- 注意 :證書想要能夠認證到K8S集群上來可以使用的賬號認證方式:
- 1、證書認證
- 最簡單可以后期定制
- 使用API Server默認的CA向外簽署證書,客戶端僅需要請求API Server的CA認證簽署證書就可以登陸K8S (/etc/kubernetes/pki/ca.crt),CN代表用戶名,用戶名無需實現在系統上出現
- 2、令牌認證
- 使用令牌認證方式也需要修改API Server啟動時加載的令牌文件
- 3、密碼認證 :
- 使用用戶名及密碼認證一定要修改API Server啟動時加載的賬號密碼文件,默認是沒有加載任何賬號密碼文件的
2.5.2、自建Kubeconfig證書認證連入K8S
- 自建k8s客戶端證書,使用自建的用戶賬戶連入k8s並且並以為kubeconfig使用(不再使用默認的admin.conf中的管理員客戶端,使用創建的普通用戶權限連入客戶端)
1、手動創建一個私鑰
~]# cd /etc/kubernetes/pki/
pki]# openssl genrsa -out ilinux.key 2048
Generating RSA private key, 2048 bit long modulus
..................+++
......................................................................................+++
e is 65537 (0x10001)
2、為此用戶生成一個證書簽署請求,並且使用k8s API Server默認的ca.crt進行簽署
# CN=用戶名
# O=用戶組
pki]# openssl req -new -key ilinux.key -out ilinux.csr -subj "/CN=ilinux/O=kubeusers"
3、使用k8s API Server默認的ca.crt進行對用戶證書簽署
pki]# openssl x509 -req -in ilinux.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -out ilinux.crt -days 3560
Signature ok
subject=/CN=ilinux/O=kubeusers
Getting CA Private Key
4、使用kubeconfig創建新的集群(set-cluster)
# 集群名稱 # 指定API Server服務器地址 # 集群所使用的CA的證書文件 # 證書是否需要打包起來存放
# kubectl config set-cluster e2e --server=https://1.2.3.4 --certificate-authority= --embed-certs=false
# API Server 地址 : kube-apiserver-k8s.master1 1/1 Running 2 33d 192.168.20.236
# pki]# kubectl config set-cluster mykube --server="https://192.168.20.236:6443" --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true
# Cluster "mykube" set.
# 沒有指定創建的配置文件位置,默認保存在當前配置文件中,獲取創建的群組
# pki]# kubectl config get-clusters
# NAME
# kubernetes
# mykube
# 如果想要定義在另外的配置文件中(如果使用默認的配置文件如下的--kubeconfig= 都無需指定)
pki]# kubectl config set-cluster mykube --server="https://192.168.20.236:6443" --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --kubeconfig=/tmp/ilinux.kebeconfig
Cluster "mykube" set.
5、在創建的集群中添加用戶(set-credentials)
pki]# kubectl config set-credentials
#Usage:
kubectl config set-credentials NAME [--client-certificate=path/to/certfile] [--client-key=path/to/keyfile] [--token=bearer_token] [--username=basic_user] [--password=basic_password] [--auth-provider=provider_name] [--auth-provider-arg=key=value] [--exec-command=exec_command] [--exec-api-version=exec_api_version] [--exec-arg=arg] [--exec-env=key=value] [options]
# NAME : 添加用戶的標識
# --client-certificate= 客戶端證書文件路勁
# --client-key= 客戶端私鑰文件路徑
# --username= 用戶的用戶名
pki]# kubectl config set-credentials ilinux --client-certificate=/etc/kubernetes/pki/ilinux.crt --client-key=/etc/kubernetes/pki/ilinux.key --username=ilinux --embed-certs=true -- kubeconfig=/tmp/ilinux.kebeconfig
User "ilinux" set.
6、將用戶和集群進行組合(cntexts)
# 集群名稱 # 用戶名稱
# kubectl config set-context [NAME | --current] [--cluster=cluster_nickname] [--user=user_nickname][--namespace=namespace] [options]
pki]# kubectl config set-context ilinux@mykube --cluster=mykube --user=ilinux --kubeconfig=/tmp/ilinux.kebeconfig
Context "ilinux@mykube" created.
# 查看自己的配置文件(kubectl config view : 查看默認配置文件)
pki]# kubectl config view --kubeconfig=/tmp/ilinux.kebeconfig
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.20.236:6443
name: mykube
contexts:
- context:
cluster: mykube
user: ilinux
name: ilinux@mykube
current-context: ""
kind: Config
preferences: {}
users:
- name: ilinux
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
username: ilinux
7、定義自己創建的config的當前上下文
pki]# kubectl config use-context ilinux@mykube --kubeconfig=/tmp/ilinux.kebeconfig
Switched to context "ilinux@mykube".
pki]# kubectl config get-contexts --kubeconfig=/tmp/ilinux.kebeconfig
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* ilinux@mykube mykube ilinux
8、驗證訪問pods
pki]# kubectl get pods --kubeconfig=/tmp/ilinux.kebeconfig
Error from server (Forbidden): pods is forbidden: User "ilinux" cannot list resource "pods" in API group "" in the namespace "default" # 返回無權限
# 使用默認的
pki]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-5d587c4d45-b24w7 1/1 Running 1 32d
myapp-5d587c4d45-cvj4z 1/1 Running 2 32d
# 換個配置文件則換個用戶及權限
# 如果創建集群時不使用--kebeconfig 選項則標識存放至默認的配置文件中,那么以下的操作都無需使用--kubeconfig選項,切換身份時也無需指定此選項。
- 在上面的配置文件當中,定義了集群、上下文以及用戶。其中Config也是K8S的標准資源之一,在該配置文件當中定義了一個集群列表,指定的集群可以有多個;用戶列表也可以有多個,指明集群中的用戶;而在上下文列表當中,是進行定義可以使用哪個用戶對哪個集群進行訪問,以及當前使用的上下文是什么。如圖:定義了用戶kubernetes-admin可以對kubernetes該集群的訪問,用戶kubernetes-user1對Clluster1集群的訪問
2.6、Service Account服務賬號管理與應用
- 運行過程中, Pod 資源里的容器進程在某些場景中需要調用 Kubemetes API 或者其他類型的服務,而這些服務通常需要認證客戶端身份,如調度器、 Pod 控制器或節點控制器,甚至是獲取啟動容器的鏡像訪問的私有 Registry 服務等 服務賬戶就是用於讓 Pod 對象內的容器進程訪問其他服務時提供身份認證信息的賬戶 Service Account 資源一般由用戶名及相關的 Secret 對象組成
2.6.1、Service Account自動化介紹
- Service account是為了方便Pod里面的進程調用Kubernetes API或其他外部服務而設計的。它與User account不同
- User account是為人設計的,而service account則是為Pod中的進程調用Kubernetes API而設計;
- User account是跨namespace的,而service account則是僅局限它所在的namespace;
- 每個namespace都會自動創建一個default service account
- Token controller檢測service account的創建,並為它們創建secret
- 開啟ServiceAccount Admission Controller后
- 每個Pod在創建后都會自動設置spec.serviceAccount為default(除非指定了其他ServiceAccout)
- 驗證Pod引用的service account已經存在,否則拒絕創建
- 如果Pod沒有指定ImagePullSecrets,則把service account的ImagePullSecrets加到Pod中
- 每個container啟動后都會掛載該service account的token和ca.crt到/var/run/secrets/kubernetes.io/serviceaccount/
- Service Account也是一種標准的k8s資源並簡稱為sa
~]# kubectl explain sa
KIND: ServiceAccount
VERSION: v1 # 屬於核心群組
DESCRIPTION:
ServiceAccount binds together: * a name, understood by users, and perhaps
by peripheral systems, for an identity * a principal that can be
authenticated and authorized * a set of secrets
FIELDS:
apiVersion <string>
APIVersion defines the versioned schema of this representation of an
object. Servers should convert recognized schemas to the latest internal
value, and may reject unrecognized values. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
automountServiceAccountToken <boolean>
AutomountServiceAccountToken indicates whether pods running as this service
account should have an API token automatically mounted. Can be overridden
at the pod level.
imagePullSecrets <[]Object> # 此secrets認證信息還可以通過imagePullSecrets接入到某一個docker倉儲中,實現托取私有倉庫鏡像
ImagePullSecrets is a list of references to secrets in the same namespace
to use for pulling any images in pods that reference this ServiceAccount.
ImagePullSecrets are distinct from Secrets because Secrets can be mounted
in the pod, but ImagePullSecrets are only accessed by the kubelet. More
info:
https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod
kind <string>
Kind is a string value representing the REST resource this object
represents. Servers may infer this from the endpoint the client submits
requests to. Cannot be updated. In CamelCase. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
metadata <Object>
Standard object's metadata. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
secrets <[]Object> # 通過serets資源保存了賬號接入api Service的認證信息
Secrets is the list of secrets allowed to be used by pods running using
this ServiceAccount. More info:
https://kubernetes.io/docs/concepts/configuration/secret
- 細心的讀者或許已經注意到,此前創建的每個 Pod 資源都自動關聯了一個存儲卷,並由其容器掛載至/var/run/secrets/kubernetes.io/servic account 目錄,例如,下面由“ kubectl describe pod ”命令顯示的某 Pod 對象描述信息的片斷
~]# kubectl describe pods mypod
Name: mypod
Namespace: default
Priority: 0
Node: k8s.node2/192.168.20.214
Start Time: Thu, 30 Apr 2020 14:13:03 +0800
Labels: <none>
Annotations: Status: Running
IP: 10.244.2.51
IPs:
IP: 10.244.2.51
Containers:
myapp:
Container ID: docker://e529e2d176d022d6189e46fde07b88660d9e859018c29c3efa54a847e2749899
Image: ikubernetes/myapp:v1
Image ID: docker-pullable://ikubernetes/myapp@sha256:9c3dc30b5219788b2b8a4b065f548b922a34479577befb54b03330999d30d513
Port: 80/TCP
Host Port: 8080/TCP
State: Running
Started: Sat, 23 May 2020 16:29:14 +0800
Last State: Terminated
Reason: Completed
Exit Code: 0
Started: Thu, 30 Apr 2020 14:13:04 +0800
Finished: Sat, 23 May 2020 16:28:57 +0800
Ready: True
Restart Count: 1
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-q97bf (ro)
# (令牌的使用方式)令牌放置路徑,在容器內部(里面保存的就是當前運行的pod的service賬號的用於認證到API Server上的賬號的相關令牌,認證掛載之后基本上都能夠連入API Server)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-q97bf: # 默認的令牌,用戶當前的Pod用於連入api server 更新自己的信息
Type: Secret (a volume populated by a Secret)
SecretName: default-token-q97bf
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events: <none>
-
從上面可以看到每個Pod無論定義與否都會有個存儲卷,這個存儲卷為default-token-*** token令牌,這就是pod和serviceaccount認證信息。通過secret進行定義,由於認證信息屬於敏感信息,所以需要保存在secret資源當中,並以存儲卷的方式掛載到Pod當中。從而讓Pod內運行的應用通過對應的secret中的信息來連接apiserver,並完成認證。每個 namespace 中都有一個默認的叫做 default 的 service account 資源。進行查看名稱空間內的secret,也可以看到對應的default-token。讓當前名稱空間中所有的pod在連接apiserver時可以使用的預制認證信息,從而保證pod之間的通信。
-
為了方便每創建一個Pod都要添加一個令牌和認證文件,Pod連接API Server更新自己的Pod信息是一個巨大的麻煩,k8s借助一個准入控制器,當創建Pod時可以接入准入控制器可以自動為Pod創建一個Serveraccount-name,並且連入API Server,所以Pod中的守護進程需要連入API Server時,
[root@k8s-master ~]# kubectl get sa
NAME SECRETS AGE
default 1 50d
[root@k8s-master ~]# kubectl get sa -n ingress-nginx #前期創建的ingress-nginx名稱空間也存在這樣的serviceaccount
NAME SECRETS AGE
default 1 11d
nginx-ingress-serviceaccount 1 11d
[root@k8s-master ~]# kubectl get secret
NAME TYPE DATA AGE
default-token-j5pf5 kubernetes.io/service-account-token 3 50d
mysecret Opaque 2 1d
tomcat-ingress-secret kubernetes.io/tls 2 10d
[root@k8s-master ~]# kubectl get secret -n ingress-nginx
NAME TYPE DATA AGE
default-token-zl49j kubernetes.io/service-account-token 3 11d
nginx-ingress-serviceaccount-token-mcsf4 kubernetes.io/service-account-token 3 11d
- 而默認的service account 僅僅只能獲取當前Pod自身的相關屬性,無法觀察到其他名稱空間Pod的相關屬性信息。如果想要擴展Pod,假設有一個Pod需要用於管理其他Pod或者是其他資源對象,是無法通過自身的名稱空間的serviceaccount進行獲取其他Pod的相關屬性信息的,此時就需要進行手動創建一個serviceaccount,並在創建Pod時進行定義。那么serviceaccount該如何進行定義呢???實際上,service accout也屬於一個k8s資源,如下查看service account的定義方式:
2.6.2、Service Account創建
#1、sa創建實例 , secret不用創建會自動引用相對應的名稱空間下默認的Token令牌機制賦予一個令牌Token認證的secret
chapter10]# cat serviceaccount-demo.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-demo
namespace: default
2、使用聲明式接口創建資源
chapter10]# kubectl apply -f serviceaccount-demo.yaml
serviceaccount/sa-demo created
3、獲取創建的sa資源
chapter10]# kubectl get sa -n default
NAME SECRETS AGE
default 1 33d
sa-demo 1 26s
# 如果創建Pod時沒有指明所調用的sa是什么則默認使用default的sa
4、獲取默認的default 的sa的secret
chapter10]# kubectl describe sa default
Name: default
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: default-token-q97bf
Tokens: default-token-q97bf # 默認的Token令牌機制賦予一個令牌Token認證的secret
Events: <none>
chapter10]# kubectl get secrets
NAME TYPE DATA AGE
default-token-q97bf kubernetes.io/service-account-token 3 33d
sa-demo-token-6q6n7 kubernetes.io/service-account-token 3 3m20s
- 看到有一個 token 已經被自動創建,並被 service account 引用。設置非默認的 service account,只需要在 pod 的spec.serviceAccountName 字段中將name設置為您想要用的 service account 名字即可。在 pod 創建之初 service account 就必須已經存在,否則創建將被拒絕。需要注意的是不能更新已創建的 pod 的 service account。
四、K8s 授權模塊
- Node : 專用的授權插件,根據Pod對象調度結果為Node進行授權
- ABAC : 基於屬性的訪問控制
- RBAC : 基於角色的訪問控制
- Webhook :基於http回調機制的訪問控制
# 查看當前k8s集群啟動的授權方式
# cat /etc/kubernetes/manifests/kube-apiserver.yaml
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=192.168.20.236
- --allow-privileged=true
- --authorization-mode=Node,RBAC
4.1、授權RBAC角色訪問控制介紹
-
Kubernetes的授權是基於插件形式的,其常用的授權插件有以下幾種:
- Node(節點認證)
- ABAC(基於屬性的訪問控制)
- RBAC(基於角色的訪問控制)
- 用戶→ Subjects
- User Account
- Service Account
- 角色 → Objects
- Resources : 資源
- SjResources : 子資源
- URL :非資源性URL
- Role,RoleBinding(所謂的授權僅是能讓用戶操作角色僅此而已,但是又不能直接產生關聯關系,所以一需要借助Role,RoleBinding)
- Role : 名稱空間級別的角色 ,比如名稱空間級別的資源(pods、service、contaller等)
- ClusterRole : 集群級別的角色 , 比如集群級別的資源(node、pv、ns等)
- 定義對哪個或哪些資源施加何種操作
- 能夠對角色施加的操作
- POST → create
- GET ,head → get ,list
- PUT → update
- PATCH → patch
- DELETE → delete,deletecollections
- 能夠對角色施加的操作
- 定義對哪個或哪些資源施加何種操作
- RoleBinding : 將用戶綁定到Role , 也能將用戶綁定至ClusterRole
- ClusterBinding : 用戶綁定到ClusterRole
- 從而使得讓用戶扮演某個角色
- 用戶→ Subjects
- Webhook(基於http回調機制的訪問控制)
-
讓一個用戶(Users)扮演一個角色(Role),角色擁有權限,從而讓用戶擁有這樣的權限,隨后在授權機制當中,只需要將權限授予某個角色,此時用戶將獲取對應角色的權限,從而實現角色的訪問控制。如圖:
- 基於角色的訪問控制(Role-Based Access Control, 即”RBAC”)使用”rbac.authorization.k8s.io” API Group實現授權決策,允許管理員通過Kubernetes API動態配置策略。
- 在k8s的授權機制當中,采用RBAC的方式進行授權,其工作邏輯是 把對對象的操作權限定義到一個角色當中,再將用戶綁定到該角色,從而使用戶得到對應角色的權限。此種方式僅作用於名稱空間當中,這是什么意思呢?當User1綁定到Role角色當中,User1就獲取了對該NamespaceA的操作權限,但是對NamespaceB是沒有權限進行操作的,如get,list等操作。
- 另外,k8s為此還有一種集群級別的授權機制,就是定義一個集群角色(ClusterRole),對集群內的所有資源都有可操作的權限,從而將User2,User3通過ClusterRoleBinding到ClusterRole,從而使User2、User3擁有集群的操作權限。Role、RoleBinding、ClusterRole和ClusterRoleBinding的關系如下圖:
- 但是這里有2種綁定ClusterRoleBinding、RoleBinding。也可以使用RoleBinding去綁定ClusterRole。
- 當使用這種方式進行綁定時,用戶僅能獲取當前名稱空間的所有權限。為什么這么繞呢??
- 舉例有10個名稱空間,每個名稱空間都需要一個管理員,而該管理員的權限都是一致的。那么此時需要去定義這樣的管理員,使用RoleBinding就需要創建10個Role,這樣顯得更加繁重。為此當使用RoleBinding去綁定一個ClusterRole時,該User僅僅擁有對當前名稱空間的集群操作權限,換句話說,此時只需要創建一個ClusterRole就解決了以上的需求。
- 這里要注意的是:RoleBinding僅僅對當前名稱空間有對應的權限。
- 在RBAC API中,一個角色包含了一套表示一組權限的規則。 權限以純粹的累加形式累積(沒有”否定”的規則)。 角色可以由命名空間(namespace)內的Role對象定義,而整個Kubernetes集群范圍內有效的角色則通過ClusterRole對象實現。
4.2、Kubernetes RBAC的演示
User --> Rolebinding --> Role
4.2.1、角色創建
一個Role對象只能用於授予對某一單一命名空間中資源的訪問權限
[root@k8s-master ~]# kubectl create role -h #查看角色創建幫助
Create a role with single rule.
Examples:
# Create a Role named "pod-reader" that allows user to perform "get", "watch" and "list" on pods
kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods
# Create a Role named "pod-reader" with ResourceName specified
kubectl create role pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
# Create a Role named "foo" with API Group specified
kubectl create role foo --verb=get,list,watch --resource=rs.extensions
# Create a Role named "foo" with SubResource specified
kubectl create role foo --verb=get,list,watch --resource=pods,pods/status
Options:
--allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in
the template. Only applies to golang and jsonpath output formats.
--dry-run=false: If true, only print the object that would be sent, without sending it.
-o, --output='': Output format. One of:
json|yaml|name|go-template|go-template-file|templatefile|template|jsonpath|jsonpath-file.
--resource=[]: Resource that the rule applies to
--resource-name=[]: Resource in the white list that the rule applies to, repeat this flag for multiple items
--save-config=false: If true, the configuration of current object will be saved in its annotation. Otherwise, the
annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
--template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The
template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
--validate=true: If true, use a schema to validate the input before sending it
--verb=[]: Verb that applies to the resources contained in the rule
Usage:
kubectl create role NAME --verb=verb --resource=resource.group/subresource [--resource-name=resourcename] [--dry-run]
[options]
使用kubectl create進行創建角色,指定角色名稱,--verb指定權限,--resource指定資源或者資源組,--dry-run單跑模式並不會創建
Use "kubectl options" for a list of global command-line options (applies to all commands).
[root@k8s-master ~]# kubectl create role pods-reader --verb=get,list,watch --resource=pods --dry-run -o yaml #干跑模式查看role的定義
apiVersion: rbac.authorization.k8s.io/v1
kind: Role #資源類型
metadata:
creationTimestamp: null
name: pods-reader
rules:
- apiGroups: #對那些api組內的資源進行操作
- ""
resources: #對那些資源定義
- pods
verbs: #操作權限定義
- get
- list
- watch
[root@k8s-master ~]# cd mainfests/
[root@k8s-master mainfests]# kubectl create role pods-reader --verb=get,list,watch --resource=pods --dry-run -o yaml > role-demo.yaml
[root@k8s-master mainfests]# vim role-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pods-reader
namespace: default
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
[root@k8s-master mainfests]# kubectl apply -f role-demo.yaml #角色創建
role.rbac.authorization.k8s.io/pods-reader created
[root@k8s-master mainfests]# kubectl get role
NAME AGE
pods-reader 3s
[root@k8s-master mainfests]# kubectl describe role pods-reader
Name: pods-reader
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"rbac.authorization.k8s.io/v1","kind":"Role","metadata":{"annotations":{},"name":"pods-reader","namespace":"default"},"rules":[{"apiGroup...
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
pods [] [] [get list watch] #此處已經定義了pods-reader這個角色對pods資源擁有get、list、watch的權限
4.2.2、角色的綁定
RoleBinding可以引用在同一命名空間內定義的Role對象
[root@k8s-master ~]# kubectl create rolebinding -h #角色綁定創建幫助
Create a RoleBinding for a particular Role or ClusterRole.
Examples:
# Create a RoleBinding for user1, user2, and group1 using the admin ClusterRole
kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1
Options:
--allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in
the template. Only applies to golang and jsonpath output formats.
--clusterrole='': ClusterRole this RoleBinding should reference
--dry-run=false: If true, only print the object that would be sent, without sending it.
--generator='rolebinding.rbac.authorization.k8s.io/v1alpha1': The name of the API generator to use.
--group=[]: Groups to bind to the role
-o, --output='': Output format. One of:
json|yaml|name|templatefile|template|go-template|go-template-file|jsonpath-file|jsonpath.
--role='': Role this RoleBinding should reference
--save-config=false: If true, the configuration of current object will be saved in its annotation. Otherwise, the
annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
--serviceaccount=[]: Service accounts to bind to the role, in the format <namespace>:<name>
--template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The
template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
--validate=true: If true, use a schema to validate the input before sending it
Usage:
kubectl create rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname]
[--serviceaccount=namespace:serviceaccountname] [--dry-run] [options]
使用kubectl create進行創建角色綁定,指定角色綁定的名稱,--role|--clusterrole指定綁定哪個角色,--user指定哪個用戶
Use "kubectl options" for a list of global command-line options (applies to all commands).
[root@k8s-master mainfests]# kubectl create rolebinding magedu-read-pods --role=pods-reader --user=magedu --dry-run -o yaml > rolebinding-demo.yaml
[root@k8s-master mainfests]# cat rolebinding-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
creationTimestamp: null
name: magedu-read-pods
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pods-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: magedu
[root@k8s-master mainfests]# kubectl apply -f rolebinding-demo.yaml #創建角色綁定
rolebinding.rbac.authorization.k8s.io/magedu-read-pods created
[root@k8s-master mainfests]# kubectl describe rolebinding magedu-read-pods #查看角色綁定的信息,這里可以看到user:magedu綁定到了pods-reader這個角色上
Name: magedu-read-pods
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"rbac.authorization.k8s.io/v1","kind":"RoleBinding","metadata":{"annotations":{},"creationTimestamp":null,"name":"magedu-read-pods","name...
Role:
Kind: Role
Name: pods-reader
Subjects:
Kind Name Namespace
---- ---- ---------
User magedu
[root@k8s-master ~]# kubectl config use-context magedu@kubernetes #切換magedu這個用戶,並使用get獲取pods資源信息
Switched to context "magedu@kubernetes".
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
filebeat-ds-hxgdx 1/1 Running 1 36d
filebeat-ds-s466l 1/1 Running 2 36d
myapp-0 1/1 Running 0 2d
myapp-1 1/1 Running 0 2d
myapp-2 1/1 Running 0 2d
myapp-3 1/1 Running 0 2d
pod-sa-demo 1/1 Running 0 1d
pod-vol-demo 2/2 Running 0 3d
redis-5b5d6fbbbd-q8ppz 1/1 Running 1 4d
[root@k8s-master ~]# kubectl get pods -n ingress-nginx #測試獲取ingress-nginx這個名稱空間的pods信息
No resources found.
Error from server (Forbidden): pods is forbidden: User "magedu" cannot list pods in the namespace "ingress-nginx"
- 從上面的操作,可以總結出,role的定義和綁定,僅作用於當前名稱空間,在獲取ingress-nginx名稱空間時,一樣會出現Forbidden!!!
User --> Clusterrolebinding --> Clusterrole
4.2.3、clusterrole定義
- ClusterRole對象可以授予與Role對象相同的權限,但由於它們屬於集群范圍對象, 也可以使用它們授予對以下幾種資源的訪問權限:
- 集群范圍資源(例如節點,即node)
- 非資源類型endpoint(例如”/healthz”)
- 跨所有命名空間的命名空間范圍資源(例如pod,需要運行命令kubectl get pods --all-namespaces來查詢集群中所有的pod)
[root@k8s-master mainfests]# kubectl config use-context kubernetes-admin@kubernetes #切換會kubernetes-admin用戶
Switched to context "kubernetes-admin@kubernetes".
[root@k8s-master mainfests]# kubectl create clusterrole cluster-read --verb=get,list,watch --resource=pods -o yaml > clusterrole-demo.yaml
[root@k8s-master mainfests]# vim clusterrole-demo.yaml #定義clusterrole和權限
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-read
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
[root@k8s-master mainfests]# kubectl apply -f clusterrole-demo.yaml #創建clusterrole
clusterrole.rbac.authorization.k8s.io/cluster-read configured
- 這里我們需要切換回kubernetes-admin賬戶,是由於magedu賬戶不具備創建的權限,這也說明普通用戶是無法進行創建K8S資源的,除非進行授權。如下,我們另開一個終端,將配置到一個普通用戶ik8s上,使其使用magedu賬戶進行通信
[root@k8s-master ~]# useradd ik8s
[root@k8s-master ~]# cp -rp .kube/ /home/ik8s/
[root@k8s-master ~]# chown -R ik8s.ik8s /home/ik8s/
[root@k8s-master ~]# su - ik8s
[ik8s@k8s-master ~]$ kubectl config use-context magedu@kubernetes
Switched to context "magedu@kubernetes".
[ik8s@k8s-master ~]$ kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: REDACTED
server: https://192.168.56.11:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
- context:
cluster: kubernetes
user: magedu
name: magedu@kubernetes
current-context: magedu@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
- name: magedu
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
4.2.4、clusterrolebinding定義
[root@k8s-master mainfests]# kubectl get rolebinding #獲取角色綁定信息
NAME AGE
magedu-read-pods 1h
[root@k8s-master mainfests]# kubectl delete rolebinding magedu-read-pods #刪除前面的綁定
rolebinding.rbac.authorization.k8s.io "magedu-read-pods" deleted
[ik8s@k8s-master ~]$ kubectl get pods #刪除后,在ik8s普通用戶上進行獲取pods資源信息,就立馬出現forbidden了
No resources found.
Error from server (Forbidden): pods is forbidden: User "magedu" cannot list pods in the namespace "default"
[root@k8s-master mainfests]# kubectl create clusterrolebinding magedu-read-all-pods --clusterrole=cluster-read --user=magedu --dry-run -o yaml > clusterrolebinding-demo.yaml
[root@k8s-master mainfests]# vim clusterrolebinding-demo.yaml #創建角色綁定,將magedu綁定到clusterrole:magedu-read-all-pods上
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: magedu-read-all-pods
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-read
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: magedu
[root@k8s-master mainfests]# kubectl get clusterrole
NAME AGE
admin 52d
cluster-admin 52d
cluster-read 13m
......
[root@k8s-master mainfests]# kubectl apply -f clusterrolebinding-demo.yaml
clusterrolebinding.rbac.authorization.k8s.io/magedu-read-all-pods created
[root@k8s-master mainfests]# kubectl get clusterrolebinding
NAME AGE
......
magedu-read-all-pods 10s
[root@k8s-master mainfests]# kubectl describe clusterrolebinding magedu-read-all-pods
Name: magedu-read-all-pods
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"rbac.authorization.k8s.io/v1beta1","kind":"ClusterRoleBinding","metadata":{"annotations":{},"name":"magedu-read-all-pods","namespace":""...
Role:
Kind: ClusterRole
Name: cluster-read
Subjects:
Kind Name Namespace
---- ---- ---------
User magedu
[ik8s@k8s-master ~]$ kubectl get pods #角色綁定后在ik8s終端上進行獲取pods信息,已經不會出現forbidden了
NAME READY STATUS RESTARTS AGE
filebeat-ds-hxgdx 1/1 Running 1 36d
filebeat-ds-s466l 1/1 Running 2 36d
myapp-0 1/1 Running 0 2d
myapp-1 1/1 Running 0 2d
myapp-2 1/1 Running 0 2d
myapp-3 1/1 Running 0 2d
pod-sa-demo 1/1 Running 0 1d
pod-vol-demo 2/2 Running 0 4d
redis-5b5d6fbbbd-q8ppz 1/1 Running 1 4d
[ik8s@k8s-master ~]$ kubectl get pods -n ingress-nginx #更換名稱空間進行查看也是可行的
NAME READY STATUS RESTARTS AGE
default-http-backend-7db7c45b69-nqxw9 1/1 Running 1 4d
nginx-ingress-controller-6bd7c597cb-9fzbw 1/1 Running 0 4d
[ik8s@k8s-master ~]$ kubectl delete pods pod-sa-demo #但是進行刪除pod就無法進行,因為在授權時是沒有delete權限的
Error from server (Forbidden): pods "pod-sa-demo" is forbidden: User "magedu" cannot delete pods in the namespace "default"
- 從上面的實驗,我們可以知道對用戶magedu進行集群角色綁定,用戶magedu將會獲取對集群內所有資源的對應權限。
User --> Rolebinding --> Clusterrole
- 將maedu通過rolebinding到集群角色magedu-read-pods當中,此時,magedu僅作用於當前名稱空間的所有pods資源的權限
[root@k8s-master mainfests]# kubectl delete clusterrolebinding magedu-read-all-pods
clusterrolebinding.rbac.authorization.k8s.io "magedu-read-all-pods" deleted
[root@k8s-master mainfests]# kubectl create rolebinding magedu-read-pods --clusterrole=cluster-read --user=magedu --dry-run -o yaml > rolebinding-clusterrole-demo.yaml
[root@k8s-master mainfests]# vim rolebinding-clusterrole-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: magedu-read-pods
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-read
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: magedu
[root@k8s-master mainfests]# kubectl apply -f rolebinding-clusterrole-demo.yaml
rolebinding.rbac.authorization.k8s.io/magedu-read-pods created
[ik8s@k8s-master ~]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
filebeat-ds-hxgdx 1/1 Running 1 36d
filebeat-ds-s466l 1/1 Running 2 36d
myapp-0 1/1 Running 0 2d
myapp-1 1/1 Running 0 2d
myapp-2 1/1 Running 0 2d
myapp-3 1/1 Running 0 2d
pod-sa-demo 1/1 Running 0 1d
pod-vol-demo 2/2 Running 0 4d
redis-5b5d6fbbbd-q8ppz 1/1 Running 1 4d
[ik8s@k8s-master ~]$ kubectl get pods -n ingress-nginx
No resources found.
Error from server (Forbidden): pods is forbidden: User "magedu" cannot list pods in the namespace "ingress-nginx"
五、RBAC的三種授權訪問
- RBAC不僅僅可以對user進行訪問權限的控制,還可以通過group和serviceaccount進行訪問權限控制。當我們想對一組用戶進行權限分配時,即可將這一組用戶歸並到一個組內,從而通過對group進行訪問權限的分配,達到訪問權限控制的效果。
- 從前面serviceaccount我們可以了解到,Pod可以通過 spec.serviceAccountName來定義其是以某個serviceaccount的身份進行運行,當我們通過RBAC對serviceaccount進行訪問授權時,即可以實現Pod對其他資源的訪問權限進行控制。也就是說,當我們對serviceaccount進行rolebinding或clusterrolebinding,會使創建Pod擁有對應角色的權限和apiserver進行通信。如圖: