K8S 的用戶系統
K8S 有兩種類型的用戶
- service account
- 一般用戶(人)
一般用戶
一般用戶被認為是由外部獨立的服務(比如公司的員工)管理的。例如:一個分發私鑰的管理員,一個像Keystone或谷歌帳戶這樣的用戶存儲,甚至一個包含用戶名和密碼列表的文件。在這方面,Kubernetes沒有表示普通用戶帳戶的對象。不能通過API調用將普通用戶添加到集群中。
service account
相反,服務帳戶是由Kubernetes API管理的用戶。它們被綁定到特定的名稱空間,并由API服務器自動創建或通過API調用手動創建。服務帳戶被關聯到一組用作憑證的secret中,這些secret憑證被掛載到pod中,允許集群內進程與Kubernetes API通信。
API請求要么綁定到普通用戶,要么綁定到服務帳戶,要么作為匿名請求處理。這意味著集群內外的每個進程,不論是PC客戶端上使用kubectl的人工用戶或者節點上的kubelets,再到控制平面的成員,向API服務器發出請求時都必須進行身份驗證,或者被視為匿名用戶。
認證
API SERVER 認證方式(K8S 的所有訪問都是通過 api server)
- https 證書認證: 基于CA根證書簽名的雙向數字證書認證方式
- http token 認證: 通過一個token來識別合法用戶
- http basic 認證: 通過用戶名密碼的方式認證
- authenticating proxy: 第三方授權協議
認證策略
api server 擁有一條鏈式的認證插件, 沒個請求被認證插件驗證時,插件會試圖將請求與以下屬性進行關聯
用戶名(username):標識最終用戶的字符串。常見的值可能是kube-admin或jane@example.com。
UID:標識最終用戶并試圖比username更一致和惟一的字符串。
組(group):一組字符串,它將用戶與一組通常分組的用戶相關聯。
額外字段(extra fileds):字符串映射到包含附加信息授權方可能會發現有用的字符串列表。
所有值對身份驗證系統都是不透明的,只有在由授權方( authorizer)使用時才具有意義。
您可以同時啟用多個身份驗證方法。通常應該使用至少兩種方法:
服務帳戶(service account) 的服務帳戶令牌(service account token)
一種用于用戶身份驗證的方法。
當啟用多個驗證器模塊時,第一個模塊將成功地驗證 "請求短路評估" (request short-circuits evaluation)。,如果驗證失敗,則進行斷路操作,API服務器不保證運行驗證器的執行順序。
所有通過驗證的用戶都會被添加進system:authenticated組。
可以使用authenticating proxy 或authentication webhook與其他身份驗證協議(LDAP、SAML、Kerberos、備用x509方案等)集成。
額外知識補充:https證書認證原理
CA: PKI 系統中通信雙方都信任的實體, 被稱為可信第三方(trusted third party TTP)
CA通過證書證實他人的公鑰信息,證書上有CA的簽名. 證書中綁定了公鑰數據和相應私鑰用后者的身份信息,并帶有CA的數字簽名;在證書中也包含的CA的名稱,以方便依賴方找到CA的公鑰,驗證數字證書上的簽名
CA 涉及的概念
**根證書, 自簽名證書, 密鑰, 私鑰, 加密算法 **
CA 認證步驟
- https 通信雙方的服務器端, 想CA 機構申請證書. CA 機構下發根證書,服務端證書,私鑰給申請者
- https 通信雙方的客戶端向CA機構申請證書, CA 機構下發根證書,服務端證書,私鑰給申請者
- 客戶端向服務端發起請求,服務端下發服務端證書給客戶端,客戶端接收到證書后, 通過私鑰揭秘證書, 利用服務端證書中的公鑰認證證書信息比較證書里的消息. 例如,比較域名和公鑰, 與服務器剛發送的相關信息是否一致, 如果一致, 則認為服務端是可信的
- 客戶端發送客戶端證書給服務端,服務端通過私鑰解密證書,獲得客戶端公鑰,并用該公鑰認證證書信息
- 客戶端通過隨機密鑰加密信息發送給服務端. 服務端和客戶端協商好加密方案后,客戶端會產生一個隨機的密鑰,客戶端通過協商好的加密方案加密該密鑰,并發送該隨機密鑰給服務端. 服務器接收密鑰后, 雙方所有內容通過該隨機密鑰加密
http 其他認證方式
token 認證原理
token 是一個難以被模仿的字符串, 每個token對應一個用戶名, 存放在API server能訪問的一個文件中. 當客戶端發起API調用時, token放在header中, API 就能識別是否非法.
http basic 認證
這種認證方式是把 用戶名+冒號+密碼 用base64 算法進行編碼后放到header中進行身份識別
K8S 的 X509 Client Certs 認證
要啟用 X509證書認證,需要在apiserver
的啟動參數中添加--client-ca-file=SOMEFILE
, api server X509 認證的完整啟動參數如下
kube-apiserver
--advertise-address=192.168.10.50
--allow-privileged=true
--authorization-mode=Node,RBAC
--client-ca-file=/etc/kubernetes/pki/ca.crt
--enable-admission-plugins=NodeRestriction
--enable-bootstrap-token-auth=true
--etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
--etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
--etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
--etcd-servers=https://127.0.0.1:2379
--insecure-port=0
--kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
--kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
--proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
--proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
--requestheader-allowed-names=front-proxy-client
--requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
--requestheader-extra-headers-prefix=X-Remote-Extra-
--requestheader-group-headers=X-Remote-Group
--requestheader-username-headers=X-Remote-User
--secure-port=6443
--service-account-key-file=/etc/kubernetes/pki/sa.pub
--service-cluster-ip-range=10.96.0.0/12
--tls-cert-file=/etc/kubernetes/pki/apiserver.crt
--tls-private-key-file=/etc/kubernetes/pki/apiserver.key
K8S 組件的X509證書認證配置
證書管理工具有一下三種
- easyrsa
- openssl
- cfssl
使用openssl 的方式
主要步驟如下
- 生成自簽名 CA 證書
- 為kube-apiserver 生成數字證書, 并用CA證書簽名
- 為kube-apiserver 配置相關啟動參數
- 為每個kube-apiserver的客戶端(kube-controller-manager, kube-scheduler, kubelet, kube-proxy, kubectl, etcd ) 都生成自己的證書,也用CA 進行簽名,并配置起啟動參數
生成 CA 證書
# 生成CA的私鑰
openssl genrsa -out ca.key 2048
# 通過ca私鑰生成ca證書,注意CN= 的部分必須是master的主機名或IP地址
openssl req -x509 -new -nodes -key ca.key -subj "/CN=${MASTER_IP}" -days 10000 -out ca.crt
準備master_ssl.cnf文件,用戶生成X509 V3 版本的證書.該文件中主要設置master服務器的ip地址(192.168.10.3),以及k8s master service的虛擬服務域名(kubernetes.default),以及虛擬服務的cluster ip(10.96.0.1)
master_ssl.cnf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn
[ dn ]
C = <country>
ST = <state>
L = <city>
O = <organization>
OU = <organization unit>
CN = <MASTER_IP>
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.cluster
DNS.5 = kubernetes.default.svc.cluster.local
# apiserver 所在主機的IP
IP.1 = <MASTER_IP>
# 一般為 api server --service-cluster-ip-range=10.96.0.0/12 參數的第一位ip,也就是10.96.
IP.2 = <MASTER_CLUSTER_IP>
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth,clientAuth
subjectAltName=@alt_names
基于master_ssl.cnf 創建server.csr(證書請求) 和server.crt(證書) 文件. 在生成server.csr 時, -subj 參數中 "/CN" 的值需為master的主機名
#### 生成 api server的私鑰
openssl genrsa -out server.key 2048
生成證書請求
openssl req -new -key server.key -subj "CN=k8s-master" -config master_ssl.cnf -out server.csr
# 生成ca 簽名的證書
openssl x509 -req server.csr -CA ca.crt -CAkey ca.key -CAcreaterserial -days 5000 -extensions v3_req -extfile master_ssl.cnf -out server.crt
執行完之后 生成ca.srl server.crt server.csr server.key 將生成的文件和之前生成的ca.key ca.crt 復制到/etc/kubernetes/ssl 文件夾下
設置kuber-apiserver 的三個啟動參數
--client-ca-file=/etc/kubernetes/ssl/ca.crt
--tls-private-key=/etc/kubernetes/ssl/server.key
--tls-cert-file=/etc/kubernetes/ssl/server.crt
同事關閉非安全端口 --insecure-port = 0 并設安全端口 --secure-port=6443 重啟kube-apiserver 服務
生成kube-controller-manager 的證書
openssl genrsa -out cs_client.key 2048
openssl req - new -key cs_client.key -subj "CN=k8s-master" -config master_ssl.cnf -out cs_client.csr
openssl x509 -req cs_client.csr -CA ca.crt -CAkey ca.key -CAcreaterserial -days 5000 -extensions v3_req -extfile master_ssl.cnf -out cs_client.crt
編寫kuber-controller-manager 配置文件
vim /etc/kubernetes/ssl/kubeconfig
# kubeconfig for kube-controller-manager
apiVersion: v1
kind: config
users:
- name: controllermanager
user:
client-certificate: /etc/kubernetes/ssl/cs_client.crt
client-key: /etc/kubernetes/ssl/cs_client.key
clusters:
- name: local
cluster:
certificate-authority: /etc/kubernetes/ssl/ca.crt
server: http://192.168.18.3:6443
contexts:
- context:
cluster: local
user: controllermanager
name: mycontext
current-context: mycontext
修改 kube-controller-manager 的啟動參數
--service-account-key-file=/etc/kubernetes/ssl/server.key
--root-ca-file=/etc/kubernetes/ssl/ca.crt
--kubeconfig=/etc/kubernetes/ssl/kubeconfig
生成kubelet的證書
openssl genrsa -out kubelet_client.key 2048
openssl req - new -key kubelet_client.key -subj "CN=k8s-master" -config master_ssl.cnf -out kubelet_client.csr
openssl x509 -req kubelet_client.csr -CA ca.crt -CAkey ca.key -CAcreaterserial -days 5000 -extensions v3_req -extfile master_ssl.cnf -out kubelet_client.crt
在非master節點編寫kuber-controller-manager 配置文件
vim /etc/kubernetes/ssl/kubeconfig
# kubeconfig for kube-controller-manager
apiVersion: v1
kind: config
users:
- name: controllermanager
user:
client-certificate: /etc/kubernetes/ssl/kubelet_client.crt
client-key: /etc/kubernetes/ssl/kubelet_client.key
clusters:
- name: local
cluster:
certificate-authority: /etc/kubernetes/ssl/ca.crt
server: http://192.168.18.3:6443
contexts:
- context:
cluster: local
user: controllermanager
name: mycontext
current-context: mycontext
修改 kubelet的啟動參數, 添加--kubeconfig=/etc/kubernetes/kubeconfig
生成 admin的證書
openssl genrsa -out admin.key 2048
openssl req -new -key admin.key -out admin.csr -subj "/O=system:masters/CN=dmin"
openssl x509 -req -set_serial $(date +%s%N) -in admin.csr -CA ca.crt -CAkey ca.key -out admin.crt -days 365 -extensions v3_req -extfile req.conf
這樣,通過 證書認證的形式配置了K8S的認證
使用easyrsa 生成證書
1 下載 easy rsa
curl -LO https://storage.googleapis.com/kubernetes-release/easy-rsa/easy-rsa.tar.gz
tar xzf easy-rsa.tar.gz
cd easy-rsa-master/easyrsa3
./easyrsa init-pki
2 生成 ca 證書
# --batch 自動模式,--req-cn 設置默認的CN
./easyrsa --batch "--req-cn=${MASTER_IP}@`date +%s`" build-ca nopass
3 生成api server相關證書
./easyrsa --subject-alt-name="IP:${MASTER_IP},"\
"IP:${MASTER_CLUSTER_IP},"\
"DNS:kubernetes,"\
"DNS:kubernetes.default,"\
"DNS:kubernetes.default.svc,"\
"DNS:kubernetes.default.svc.cluster,"\
"DNS:kubernetes.default.svc.cluster.local" \
--days=10000 \
build-server-full server nopass
4 修改 api server 啟動參數
--client-ca-file=/yourdirectory/ca.crt
--tls-cert-file=/yourdirectory/server.crt
--tls-private-key-file=/yourdirectory/server.key
5 生成 admin 證書
./easyrsa --dn-mode=org --req-cn=admin --req-org=system:masters --req-c= --req-st= --req-city= --req-email= --req-ou= build-client-full admin nopass
cfssl 方式
1編寫cfssl ca 配置文件
ca-config.json
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
2 變現 ca 證書請求配置文件
ca-csr.json
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names":[{
"C": "<country>",
"ST": "<state>",
"L": "<city>",
"O": "<organization>",
"OU": "<organization unit>"
}]
}
3 生成CA證書文件
/opt/local/cfssl/cfssl gencert -initca csr.json | /opt/local/cfssl/cfssljson -bare ca
4 編寫api server 證書配置文件 server-crs.json
{
"CN": "kubernetes",
"hosts": [
"127.0.0.1",
"<MASTER_IP>",
"<MASTER_CLUSTER_IP>",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [{
"C": "<country>",
"ST": "<state>",
"L": "<city>",
"O": "<organization>",
"OU": "<organization unit>"
}]
}
5 生成 api server 證書文件
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem \
--config=ca-config.json -profile=kubernetes \
server-csr.json | ../cfssljson -bare server
6 編輯 admin 配置文件 admin-csr.json
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "ShenZhen",
"L": "ShenZhen",
"O": "system:masters",
"OU": "System"
}
]
}
7 生成 admin 證書
/opt/local/cfssl/cfssl gencert -ca=/etc/kubernetes/ssl/ca.pem \
-ca-key=/etc/kubernetes/ssl/ca-key.pem \
-config=/opt/ssl/config.json \
-profile=kubernetes admin-csr.json | /opt/local/cfssl/cfssljson -bare admin
token 認證
傳統token
api server 支持token認證, 通過在啟動參數中添加 ----token-auth-file=SOMEFILE
進行支持,如果修改token file的內容,必須重啟api server才能生效
在API 請求中通過在請求的header 中添加token 進行驗證
Authorization: Bearer 31ada4fd-adec-460c-809a-9e56ceb75269
Bootstrap Tokens
為了允許對新的集群進行方便的初始化安裝引導,Kubernetes包含一個動態管理的承載令牌類型,稱為引導令牌(bootstrap token)。這些令牌作為secret存儲在kube-system名稱空間中,可以在其中動態管理和創建它們。Controller Manager包含一個TokenCleaner控制器,它在引導令牌過期時刪除它們。
令牌的形式是[a-z0-9]{6}.[a-z0-9]{16}。第一個組件是令牌ID(用戶ID),第二個組件是secret。在HTTP頭中指定令牌,如下所示:
Authorization: Bearer 781292.db7bc3a58fc5f07e
781292就是用戶ID
啟用bootstrap token
您必須在API服務器上使用--enable-bootstrap-token-auth 標志啟用引導令牌身份驗證器。并且必須同時通過--controllers=, tokencleaner*參數啟用TokenCleaner控制器。如果使用kubeadm引導集群,它將自動完成這一任務。
身份驗證器將身份驗證為system:bootstrap:<令牌ID>。它包含在system:bootstrappers組中。有意限制命名和組,以阻止用戶在引導之后使用這些令牌。可以使用用戶名和組(kubeadm也使用這些用戶名和組)來制定適當的授權策略,以支持集群的引導。
有關引導令牌身份驗證器和控制器的詳細文檔,以及如何使用kubeadm管理這些令牌,請參見引導令牌
Static Password File
啟用命令
通過在api server 啟動參數中添加--basic-auth-file=SOMEFILE 啟用靜態密碼驗證。如果修改靜態密碼文件,需要重啟api server 才能生效。
靜態密碼文件說明
基本的靜態密碼是一個csv文件,至少有3列:密碼、用戶名、用戶id。在Kubernetes 1.6或更高版本中,您可以指定一個可選的第4列,其中包含逗號分隔的組名。如果您有多個組,則必須將第四個列值括在雙引號(")中。請看下面的例子:
password,user,uid,"group1,group2,group3"
靜態密碼使用
當使用http客戶機的基本身份驗證時,API服務器期望header basic 的值為 base64編碼的用戶名密碼 (用戶:PASSWORD)。
service account token
服務帳戶(service account)是一個自動啟用的身份驗證器,它使用帶簽名的token來驗證請求。這個插件有兩個可選的標志:
--service-account-key-file包含PEM編碼密鑰的文件,用于對token進行簽名。如果未指定,將使用API服務器的TLS私鑰。
--service-account-lookup如果啟用,從API中刪除的令牌將被撤銷。
服務帳戶通常由API服務器自動創建,并通過ServiceAccount controller manager與集群中運行的pod相關聯。token被掛載到已知位置的pods中,并允許集群內進程與API服務器通信。帳戶可以使用PodSpec的serviceAccountName字段顯式地與pod關聯。
注意:serviceAccountName通常被省略,因為這是自動完成的。
kubectl create serviceaccount jenkins
serviceaccount "jenkins" created
kubectl get serviceaccounts jenkins -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
# ...
secrets:
- name: jenkins-token-1yvwg
# 創建的secret包含API服務器的公共CA和一個簽名的JSON Web令牌(JWT)。
kubectl get secret jenkins-token-1yvwg -o yaml
apiVersion: v1
data:
ca.crt: (APISERVER'S CA BASE64 ENCODED)
namespace: ZGVmYXVsdA==
token: (BEARER TOKEN BASE64 ENCODED)
kind: Secret
metadata:
# ...
type: kubernetes.io/service-account-token
值是用base64編碼的,因為secret總是用base64編碼的。
服務帳戶(service account)使用用戶名system:serviceaccount:(namespace):(serviceaccount)進行身份驗證,并分配給system:serviceaccounts和system:serviceaccounts:(namespace)兩個用戶組。
警告:由于服務帳戶令牌存儲在secret中,任何具有讀訪問這些機密的用戶都可以驗證為服務帳戶。在授予服務帳戶的權限和secret的讀取功能時要謹慎。
如果文章對您有幫助,請點一下下面的 "喜歡"