您的位置:首頁 >聚焦 >

Kubernetes_梳理出ServiceAccount服務(wù)賬號(hào)一條線

2022-11-21 16:43:24    來源:程序員客棧
前言

看圖,如下:

左下角的Pod需要訪問k8s的資源,需要通過中間 apiserver 的認(rèn)證、授權(quán)、準(zhǔn)入控制 三個(gè)東西,這就需要一個(gè)serviceAccount,幫助它完成這個(gè)過程,才能訪問k8s的資源。


一、每個(gè)命名空間都會(huì)一個(gè)有個(gè)serviceAccount

serviceAccount的作用是是給集群內(nèi)pod里面的進(jìn)程使用,用來訪問集群內(nèi)的資源,所以每個(gè)ns都會(huì)一個(gè)一個(gè)名稱為default的命名空間,如下:


(資料圖片)

同時(shí)也可以自定義serviceAccount

為什么使用了serviceAccount就可以認(rèn)證集群,因?yàn)槊總€(gè)sa下面都會(huì)擁有的一個(gè)加密的token,使用 secrets 存儲(chǔ),

這個(gè)secrets(加密token)本質(zhì)上等同于userAccount的認(rèn)證集群的三種憑證文件:X509客戶端證書,靜態(tài)token文件,靜態(tài)賬號(hào)密碼文件。

既然這個(gè)ns-monitor命名空間下,有這樣一個(gè)名為default的serviceAccount,我們就來使用一下這個(gè)serviceAccount,如下,新建一個(gè)Pod使用這個(gè)serviceAccount:

查看一下正在運(yùn)行的 kind: daemonSet 資源 node-exporter,但是沒有找到對(duì)serviceAccount的引用,因?yàn)槿魏卫$R像的運(yùn)行資源 (pod replicaset deployment statefulset deamonset job/cronjob) ,對(duì)于serviceAccount(serviceAccount類型的secrets)的引用,都是在底層的Pod里面的,所以要看pod,如下:

查看daemonset底層運(yùn)行的pod,找到了對(duì)于serviceAccount類型type的secrets的引用,如下:至此,這個(gè)名為default的serviceAccount就被pod使用了,這個(gè)pod使用了這個(gè)serviceAccount(其實(shí)是加載了這個(gè)serviceAccount關(guān)聯(lián)的secrets)之后,就可以訪問k8s集群內(nèi)的資源。

那么,為什么pod啟動(dòng)通過volume加載了type類型為serviceAccount的secrets之后,就可以訪問到k8s里面資源呢?我們看一下這個(gè)secrets到底存儲(chǔ)的哪些數(shù)據(jù)data (secrets類似一個(gè)加密的configmap,可以簡(jiǎn)單理解為配置文件,里面存儲(chǔ)了數(shù)據(jù))

一個(gè) secrets (type:serviceAccount) 里面包含的data是:加密的ca.crt、加密的namespace、加密的token,如下:

二、Secret三種type

Kubernetes提供了Secret來處理敏感信息,目前Secret的類型有3種,通過type屬性指定:Opaque(default): 任意字符串,使用base64編碼存儲(chǔ)信息,可以通過base64 --decode解碼獲得原始數(shù)據(jù),因此安全性弱。kubernetes.io/service-account-token: 作用于ServiceAccount,就是上面說的。kubernetes.io/dockercfg: 作用于Docker registry,用戶下載docker鏡像認(rèn)證使用。

type類型創(chuàng)建secret的方式使用這個(gè)secret的方式
Opaque(default)kubectl 命令手動(dòng)創(chuàng)建拉取鏡像的Pod yaml文件中,volume文件掛盤或者env使用
kubernetes.io/service-account-token新建命名空間會(huì)自動(dòng)新建一個(gè)默認(rèn)的serviceAccount,這個(gè)serviceAccount里面會(huì)自動(dòng)新建一個(gè)type為serviceAccount的secret;kubectl 命令手動(dòng)創(chuàng)建,自定義的serviceAccount被創(chuàng)建起來,會(huì)自動(dòng)新建一個(gè)type為serviceAccount的secret運(yùn)行的Pod通過volume文件掛盤使用這個(gè)type為serviceAccount的secret
kubernetes.io/dockercfgkubectl 命令手動(dòng)創(chuàng)建所有需要拉取鏡像的場(chǎng)景/kind類型,可以是Pod,也可以是replicasets deployment statefulset daemonset job/cronjob,yaml文件中被imagePullSecrets屬性使用,用來拉取鏡像的賬號(hào)密碼
2.1 Opaque(default)

Opaque類型的Secret的value為base64位編碼后的值

2.1.1 Secret創(chuàng)建的兩種方式創(chuàng)建方式1:從文件中創(chuàng)建Secret

echo -n "admin" > ./username.txtecho -n "1f2d1e2e67df" > ./password.txt

kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt

kubectl get secret

演示如下:

創(chuàng)建方式2:使用yaml文件創(chuàng)建Secret

(1)對(duì)數(shù)據(jù)進(jìn)行64位編碼

echo -n "admin" | base64echo -n "1f2d1e2e67df" | base64

(2)定義mysecret.yaml文件

apiVersion: v1kind: Secretmetadata:  name: mysecrettype: Opaquedata:  username: YWRtaW4=  password: MWYyZDFlMmU2N2Rm

(3)根據(jù)yaml文件創(chuàng)建資源并查看

kubectl create -f ./secret.yamlkubectl get secretkubectl get secret mysecret -o yaml

演示如下:

2.1.2 Secret使用的兩種方式

以Volume方式

以環(huán)境變量方式

使用方式1:以Volume方式使用Secret

kubectl apply -f mypod.yaml

apiVersion: v1kind: Podmetadata:  name: mypodspec:  containers:  - name: mypod    image: redis    volumeMounts:    - name: foo      mountPath: "/etc/foo"      readOnly: true  volumes:  - name: foo    secret:      secretName: mysecret

kubectl exec -it pod-name bash  ## 進(jìn)去ls /etc/foocat /etc/foo/usernamecat /etc/foo/password

以Volume方式使用Secret,演示如下:

使用方式2:將Secret設(shè)置為環(huán)境變量

kubectl get secret mysecret -o yamlvi secret-env-pod.yamlkubectl apply -f secret-env-pod.yamlkubectl get pod kubectl exec -it 具體pod名稱 bash

apiVersion: v1kind: Podmetadata:  name: secret-env-podspec:  containers:  - name: mycontainer    image: redis    env:      - name: SECRET_USERNAME        valueFrom:          secretKeyRef:            name: mysecret            key: username      - name: SECRET_PASSWORD        valueFrom:          secretKeyRef:            name: mysecret            key: password  restartPolicy: Never

演示如下:

小結(jié):secret兩種方式被創(chuàng)建,創(chuàng)建完之后都可以被pod里面的container去使用

使用的方式:環(huán)境變量(container下面的env)、參數(shù)(container下面的args)、volume目錄掛載(container下面的volume)

2.2 kubernetes.io/service-account-token

一般來說,k8s資源有不同的kind。configmap secret user usergroup serviceAccount 不需要運(yùn)行具體的程序,所以不需要 image: 屬性拉取鏡像pod replicasets deployment statefulset daemonset job/cronjob 需要運(yùn)行具體的程序,所以需要 image: 屬性拉取鏡像

另外,從來沒有一種kind: UserAccount類型的資源

2.3 kubernetes.io/dockercfg

在需要安全驗(yàn)證的環(huán)境中拉取鏡像的時(shí)候,需要通過用戶名和密碼。

apiVersion: v1kind: Secretmetadata:  name: myregistrykey  namespace: awesomeappsdata:  .dockerconfigjson: UmVhbGx5IHJlYWxseSByZWVlZWVlZWVlZWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx5eXl5eXl5eXl5eXl5eXl5eXl5eSBsbGxsbGxsbGxsbGxsbG9vb29vb29vb29vb29vb29vb29vb29vb29vb25ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubmdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2cgYXV0aCBrZXlzCg==type: kubernetes.io/dockerconfigjson

或者直接通過命令創(chuàng)建

kubectl create secret docker-registry myregistrykey \ --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER \ --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL

接下來拉取鏡像的時(shí)候,就可以使用了

apiVersion: v1kind: Podmetadata:  name: foo  namespace: awesomeappsspec:  containers:    - name: foo      image: janedoe/awesomeapp:v1  imagePullSecrets:    - name: myregistrykey

其實(shí)本質(zhì)上還是kubelet把這個(gè)認(rèn)證放到了docker的目錄下面,如下:

cat ~/.docker/config.json {    "auths": {        "10.39.0.118": {            "auth": "Y2hlbm1vOmNtMTM4MTE2NjY3ODY="        },        "10.39.0.12:5000": {            "auth": "dXNlcjAxOjEyMzQ1YQ=="        },        "http://10.39.0.12:5000": {            "auth": "dXNlcjAxOjEyMzQ1YQ=="        }    }}

三、自定義ServiceAccount再分析一遍3.1 Service Account創(chuàng)建

#查看serviceaccount資源[root@k8s-master ~]# kubectl get sa     NAME      SECRETS   AGEdefault   1         7d19h#創(chuàng)建一個(gè)名為admin的serviceaccount資源[root@k8s-master ~]# kubectl create serviceaccount admin    serviceaccount/admin created#查看serviceaccount資源[root@k8s-master ~]# kubectl get sa     NAME      SECRETS   AGEadmin     1         7sdefault   1         7d19h#查看serviceaccount資源admin的詳細(xì)信息,可以看出已經(jīng)自動(dòng)生成了一個(gè)Tokens:admin-token-lc826[root@k8s-master ~]# kubectl describe sa/admin    Name:                adminNamespace:           defaultLabels:              Annotations:         Image pull secrets:  Mountable secrets:   admin-token-lc826Tokens:              admin-token-lc826Events:              #查看secret,可以查看也生成了一個(gè)admin-token-lc826的secret資源[root@k8s-master ~]# kubectl get secret    NAME                  TYPE                                  DATA   AGEadmin-token-lc826     kubernetes.io/service-account-token   3      50s......

3.2 在Pod中使用自定義的service account

每個(gè)Pod對(duì)象均可附加其所屬名稱空間中的一個(gè)Service Account資源,且只能附加一個(gè)。不過,一個(gè)Service Account資源可由所屬名稱空間中的多個(gè)Pod對(duì)象共享使用。創(chuàng)建Pod時(shí),通過“spec.serviceAccountName”進(jìn)行定義。示例如下:

[root@k8s-master manfests]# vim pod-sa-demo.yaml    #編輯資源清單文件apiVersion: v1kind: Podmetadata:  name: pod-sa-demo  namespace: default  labels:    app: myapp    tier: frontendspec:  containers:  - name: myapp    image: ikubernetes/myapp:v1    ports:    - name: http      containerPort: 80  serviceAccountName: admin    #指定serviceAccount資源名稱  [root@k8s-master manfests]# kubectl apply -f pod-sa-demo.yaml pod/pod-sa-demo created[root@k8s-master manfests]# kubectl get pods -l app=myappNAME          READY   STATUS    RESTARTS   AGEpod-sa-demo   1/1     Running   0          9s[root@k8s-master manfests]# [root@k8s-master manfests]# kubectl describe pods/pod-sa-demoName:         pod-sa-demoNamespace:    default......Volumes:  admin-token-lc826:    Type:        Secret (a volume populated by a Secret)    SecretName:  admin-token-lc826      #這里可以看出掛載token就是上面創(chuàng)建的sa所生成的那個(gè)    Optional:    false......

總結(jié)

總結(jié)一下,梳理出ServiceAccount服務(wù)賬號(hào)一條線,kind: serviceAccount 作為k8s集群內(nèi)的一類資源,每個(gè)命名空間都會(huì)一個(gè)名為default的默認(rèn)的serviceAccount,默認(rèn)不指定的情況下,這個(gè)命名空間下所有的pod都是使用名為default的默認(rèn)的serviceAccount,這個(gè)serviceAccount是通過secrets存儲(chǔ)的,這個(gè)secrets等效加密的configmap,就是配置文件一類東西,type是serviceAccount,包含的data是:加密的namespace、加密的ca.crt、加密的token,有了這些data,這個(gè)命名空間下的Pod在啟動(dòng)的時(shí)候通過volume掛盤的方式,將secrets加載到整個(gè)Pod里面,Pod的進(jìn)程就可以訪問k8s集群內(nèi)的資源了。

然后,這種用在serviceAccount上的secrets只是一種類型type的secrets,secrets還有兩種其他類型type的,普通字符串和imagePullSecrets,順便一起學(xué)習(xí)了。

最后,還可以自定義ServiceAccount,再重新分析一遍,加深理解。

這里面有一個(gè)難以搞清的概念,那就是對(duì)于一一對(duì)應(yīng)關(guān)系的serviceAccount和secrets,其實(shí)不用分的這么清楚,serviceAccount是一個(gè)賬號(hào),secrets是這個(gè)賬號(hào)里面存儲(chǔ)的數(shù)據(jù),然后一一綁定在一起,甚至簡(jiǎn)單點(diǎn)理解,兩個(gè)東西作為一個(gè)整體,任何是一個(gè)東西都可以(因?yàn)楹茈y分開)。

關(guān)鍵詞: 命名空間 兩種方式 環(huán)境變量

相關(guān)閱讀