Kubernetes(k8s)密碼管理:Secret

人生的哲理發表於2023-02-01

一.系統環境

伺服器版本 docker軟體版本 Kubernetes(k8s)叢集版本 CPU架構
CentOS Linux release 7.4.1708 (Core) Docker version 20.10.12 v1.21.9 x86_64

Kubernetes叢集架構:k8scloude1作為master節點,k8scloude2,k8scloude3作為worker節點

伺服器 作業系統版本 CPU架構 程式 功能描述
k8scloude1/192.168.110.130 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico k8s master節點
k8scloude2/192.168.110.129 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kubelet,kube-proxy,calico k8s worker節點
k8scloude3/192.168.110.128 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kubelet,kube-proxy,calico k8s worker節點

二.前言

使用secret的前提是已經有一套可以正常執行的Kubernetes叢集,關於Kubernetes(k8s)叢集的安裝部署,可以檢視部落格《Centos7 安裝部署Kubernetes(k8s)叢集》https://www.cnblogs.com/renshengdezheli/p/16686769.html。

三.Secret概覽

Secret 是一種包含少量敏感資訊例如密碼、令牌或金鑰的物件。 這樣的資訊可能會被放在 Pod 規約中或者映象中。 使用 Secret 意味著你不需要在應用程式程式碼中包含機密資料

由於建立 Secret 可以獨立於使用它們的 Pod, 因此在建立、檢視和編輯 Pod 的工作流程中暴露 Secret(及其資料)的風險較小。 Kubernetes 和在叢集中執行的應用程式也可以對 Secret 採取額外的預防措施, 例如避免將機密資料寫入非易失性儲存。

Secret 類似於 ConfigMap 但專門用於儲存機密資料。

注意:預設情況下,Kubernetes Secret 未加密地儲存在 API 伺服器的底層資料儲存(etcd)中。 任何擁有 API 訪問許可權的人都可以檢索或修改 Secret,任何有權訪問 etcd 的人也可以。 此外,任何有許可權在名稱空間中建立 Pod 的人都可以使用該訪問許可權讀取該名稱空間中的任何 Secret; 這包括間接訪問,例如建立 Deployment 的能力。為了安全地使用 Secret,請至少執行以下步驟:

  • 為 Secret 啟用靜態加密。

  • 以最小特權訪問 Secret 並啟用或配置 RBAC 規則。

  • 限制 Secret 對特定容器的訪問。

  • 考慮使用外部 Secret 儲存驅動。

四.Secret 的型別

建立 Secret 時,你可以使用 Secret 資源的 type 欄位,或者與其等價的 kubectl 命令列引數(如果有的話)為其設定型別。 Secret 型別有助於對 Secret 資料進行程式設計處理。

Kubernetes 提供若干種內建的型別,用於一些常見的使用場景。 針對這些型別,Kubernetes 所執行的合法性檢查操作以及對其所實施的限制各不相同。

透過為 Secret 物件的 type 欄位設定一個非空的字串值,你也可以定義並使用自己 Secret 型別(如果 type 值為空字串,則被視為 Opaque 型別)。
當 Secret 配置檔案中未作顯式設定時,預設的 Secret 型別是 Opaque。 當你使用 kubectl 來建立一個 Secret 時,你會使用 generic 子命令來標明要建立的是一個 Opaque 型別 的Secret。 例如,下面的命令會建立一個空的 Opaque 型別 Secret 物件:

kubectl create secret generic empty-secret
kubectl get secret empty-secret
內建型別 用法
Opaque 使用者定義的任意資料
kubernetes.io/service-account-token 服務賬號令牌
kubernetes.io/dockercfg ~/.dockercfg 檔案的序列化形式
kubernetes.io/dockerconfigjson ~/.docker/config.json 檔案的序列化形式
kubernetes.io/basic-auth 用於基本身份認證的憑據
kubernetes.io/ssh-auth 用於 SSH 身份認證的憑據
kubernetes.io/tls 用於 TLS 客戶端或者伺服器端的資料
bootstrap.kubernetes.io/token 啟動引導令牌資料

五.各種型別的secret使用例項

5.1 建立kubernetes.io/service-account-token型別的secret

檢視secret,存在一個預設的secret。

[root@k8scloude1 secret-manage]# kubectl get secrets
NAME                  TYPE                                  DATA   AGE
default-token-wkjv8   kubernetes.io/service-account-token   3      26m

kubernetes.io/service-account-token型別的secret:每建立一個service-account賬號,都會自動建立一個secret,這個secret用於儲存token。

#檢視sa
[root@k8scloude1 secret-manage]# kubectl get sa
NAME      SECRETS   AGE
default   1         170m

#建立service-account
[root@k8scloude1 secret-manage]# kubectl create sa satest
serviceaccount/satest created

#自動建立一個secret
[root@k8scloude1 secret-manage]# kubectl get secrets 
NAME                  TYPE                                  DATA   AGE
default-token-wkjv8   kubernetes.io/service-account-token   3      171m
satest-token-xv8x5    kubernetes.io/service-account-token   3      5s

刪除service-account

[root@k8scloude1 secret-manage]# kubectl delete sa satest 
serviceaccount "satest" deleted

[root@k8scloude1 secret-manage]# kubectl get secrets 
NAME                  TYPE                                  DATA   AGE
default-token-wkjv8   kubernetes.io/service-account-token   3      171m

5.2 建立Docker映象倉庫型別的secret

檢視imagePullSecrets的說明資訊,imagePullSecrets 欄位是一個列表,包含對同一名稱空間中 Secret 的引用。 你可以使用 imagePullSecrets 將包含 Docker(或其他)映象倉庫密碼的 Secret 傳遞給 kubelet。kubelet 使用此資訊來替 Pod 拉取私有映象。

[root@k8scloude1 secret-manage]# kubectl explain pods.spec.imagePullSecrets
KIND:     Pod
VERSION:  v1

RESOURCE: imagePullSecrets <[]Object>

DESCRIPTION:
     ImagePullSecrets is an optional list of references to secrets in the same
     namespace to use for pulling any of the images used by this PodSpec. If
     specified, these secrets will be passed to individual puller
     implementations for them to use. For example, in the case of docker, only
     DockerConfig type secrets are honored. More info:
     https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod

     LocalObjectReference contains enough information to let you locate the
     referenced object inside the same namespace.

FIELDS:
   name	<string>
     Name of the referent. More info:
     https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names

檢視Docker映象倉庫型別的secret幫助

[root@k8scloude1 secret-manage]# kubectl create secret docker-registry --help | grep docker
      '$ docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'.
 That produces a ~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to authenticate to the registry. The email address is optional.
  by creating a dockercfg secret and attaching it to your service account.
  # If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using:
  kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
  # Create a new secret named my-secret from ~/.docker/config.json
  kubectl create secret docker-registry my-secret --from-file=.dockerconfigjson=path/to/.docker/config.json
      --docker-email='': Email for Docker registry
      --docker-password='': Password for Docker registry authentication
      --docker-server='https://index.docker.io/v1/': Server location for Docker registry
      --docker-username='': Username 為 Docker registry authentication
  kubectl create secret docker-registry NAME --docker-username=user --docker-password=password --docker-email=email [--docker-server=string] [--from-file=[key=]source] [--dry-run=server|client|none] [options]

建立一個映象倉庫型別的secret,該secret包含了映象倉庫的賬號,密碼,伺服器地址

[root@k8scloude1 secret-manage]# kubectl create secret docker-registry dockerregistrysecret --docker-username=LZ --docker-password='qwer' --docker-server=http://192.168.110.133
secret/dockerregistrysecret created

[root@k8scloude1 secret-manage]# kubectl get secrets 
NAME                   TYPE                                  DATA   AGE
default-token-wkjv8    kubernetes.io/service-account-token   3      3h3m
dockerregistrysecret   kubernetes.io/dockerconfigjson        1      14s

kubernetes.io/dockerconfigjson型別的secrets用於映象倉庫不允許匿名使用者pull映象的情況,imagePullSecrets: dockerregistrysecret 指定映象倉庫的secret,dockerregistrysecret這個secrets裡記錄了映象倉庫的賬號密碼,這樣就可以成功pull映象下來了。

[root@k8scloude1 secret-manage]# vim test.yaml 

[root@k8scloude1 secret-manage]# cat test.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: mysql
  name: mysql
spec:
  terminationGracePeriodSeconds: 0
  #imagePullSecrets: dockerregistrysecret  指定映象倉庫的secret
  imagePullSecrets: dockerregistrysecret
  containers:
  - image: 192.168.110.133/secret/mysql:latest
    imagePullPolicy: IfNotPresent
    name: mysql
    resources: {}
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: rootsec
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

刪除dockerregistrysecret

[root@k8scloude1 secret-manage]# kubectl delete secrets dockerregistrysecret 
secret "dockerregistrysecret" deleted

[root@k8scloude1 secret-manage]# kubectl get secrets 
NAME                  TYPE                                  DATA   AGE
default-token-wkjv8   kubernetes.io/service-account-token   3      3h11m

5.3 建立Opaque型別的secret(鍵值對)

Opaque型別的secret建立語法為

kubectl create secret generic name --from-literal=鍵=值 --from-literal=鍵1=值1

建立secret的名字為genericsecret,兩個鍵值對:tom=asd lisi=qwe,可以認為tom的密碼為:asd,以此類推

[root@k8scloude1 secret-manage]# kubectl create secret generic genericsecret --from-literal=tom=asd --from-literal=lisi=qwe
secret/genericsecret created

檢視secret

[root@k8scloude1 secret-manage]# kubectl get secrets 
NAME                  TYPE                                  DATA   AGE
default-token-wkjv8   kubernetes.io/service-account-token   3      3h20m
genericsecret         Opaque                                2      20s

檢視secret的描述資訊,在Data那裡可以看到lisi和tom的密碼是沒有顯示的

[root@k8scloude1 secret-manage]# kubectl describe secrets genericsecret 
Name:         genericsecret
Namespace:    secret-manage
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
lisi:  3 bytes
tom:   3 bytes

以yaml檔案的形式顯示secrets,可以看到lisi和tom的密碼已經被加密顯示,是base64加密的。

lisi: cXdl tom: YXNk lisi和tom的密碼是被base64加密過的。

[root@k8scloude1 secret-manage]# kubectl get secrets genericsecret -o yaml
apiVersion: v1
data:
  lisi: cXdl
  tom: YXNk
kind: Secret
metadata:
  creationTimestamp: "2022-01-21T07:13:57Z"
  name: genericsecret
  namespace: secret-manage
  resourceVersion: "875438"
  selfLink: /api/v1/namespaces/secret-manage/secrets/genericsecret
  uid: 6326fa13-ec9f-42dd-8eed-b35261389dde
type: Opaque

可以對密碼進行解密:

[root@k8scloude1 secret-manage]# echo cXdl | base64 -d
qwe

[root@k8scloude1 secret-manage]# echo YXNk | base64 -d
asd

以JSON的格式顯示

[root@k8scloude1 secret-manage]# kubectl get secrets genericsecret -o json
{
    "apiVersion": "v1",
    "data": {
        "lisi": "cXdl",
        "tom": "YXNk"
    },
    "kind": "Secret",
    "metadata": {
        "creationTimestamp": "2022-01-21T07:13:57Z",
        "name": "genericsecret",
        "namespace": "secret-manage",
        "resourceVersion": "875438",
        "selfLink": "/api/v1/namespaces/secret-manage/secrets/genericsecret",
        "uid": "6326fa13-ec9f-42dd-8eed-b35261389dde"
    },
    "type": "Opaque"
}

查詢lisi,tom的密碼

[root@k8scloude1 secret-manage]# kubectl get secrets genericsecret -o jsonpath={.data.lisi}
cXdl

[root@k8scloude1 secret-manage]# kubectl get secrets genericsecret -o jsonpath={.data.tom}
YXNk

查詢secret的型別

[root@k8scloude1 secret-manage]# kubectl get secrets genericsecret -o jsonpath={.type}
Opaque

5.4 建立Opaque型別的secret(對檔案加密)

secret可以直接使用檔案進行加密,鍵為:檔名 值為:檔案內容,使用檔案進行加密的語法如下:

kubectl create secret generic name --from-file=/dir/file --from-file=/dir1/file1

這個也是鍵值對,鍵:/etc/hosts檔案 值:檔案內容

[root@k8scloude1 secret-manage]# kubectl create secret generic filesecret --from-file=/etc/hosts
secret/filesecret created

[root@k8scloude1 secret-manage]# kubectl get secrets 
NAME                  TYPE                                  DATA   AGE
default-token-wkjv8   kubernetes.io/service-account-token   3      3h34m
filesecret            Opaque                                1      6s
genericsecret         Opaque                                2      14m

檢視secret的內容,host的內容同樣被加密

[root@k8scloude1 secret-manage]# kubectl get secrets filesecret -o yaml
apiVersion: v1
data:
  hosts: MTI3LjAuMC4xICAgbG9jYWxob3N0IGxvY2FsaG9zdC5sb2NhbGRvbWFpbiBsb2NhbGhvc3Q0IGxvY2FsaG9zdDQubG9jYWxkb21haW40Cjo6MSAgICAgICAgIGxvY2FsaG9zdCBsb2NhbGhvc3QubG9jYWxkb21haW4gbG9jYWxob3N0NiBsb2NhbGhvc3Q2LmxvY2FsZG9tYWluNgoxOTIuMTY4LjExMC4xMzAgazhzY2xvdWRlMQoxOTIuMTY4LjExMC4xMjkgazhzY2xvdWRlMgoxOTIuMTY4LjExMC4xMjggazhzY2xvdWRlMwo=
kind: Secret
metadata:
  creationTimestamp: "2022-01-21T07:28:10Z"
  name: filesecret
  namespace: secret-manage
  resourceVersion: "877063"
  selfLink: /api/v1/namespaces/secret-manage/secrets/filesecret
  uid: 30880892-3fbe-4baf-8d9b-953c7cbe5534
type: Opaque


[root@k8scloude1 secret-manage]# kubectl get secrets filesecret -o jsonpath={.data.hosts}
MTI3LjAuMC4xICAgbG9jYWxob3N0IGxvY2FsaG9zdC5sb2NhbGRvbWFpbiBsb2NhbGhvc3Q0IGxvY2FsaG9zdDQubG9jYWxkb21haW40Cjo6MSAgICAgICAgIGxvY2FsaG9zdCBsb2NhbGhvc3QubG9jYWxkb21haW4gbG9jYWxob3N0NiBsb2NhbGhvc3Q2LmxvY2FsZG9tYWluNgoxOTIuMTY4LjExMC4xMzAgazhzY2xvdWRlMQoxOTIuMTY4LjExMC4xMjkgazhzY2xvdWRlMgoxOTIuMTY4LjExMC4xMjggazhzY2xvdWRlMwo=

對secret進行解密

[root@k8scloude1 secret-manage]# kubectl get secrets filesecret -o jsonpath={.data.hosts} | base64 -d
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.110.130 k8scloude1
192.168.110.129 k8scloude2
192.168.110.128 k8scloude3

直接使用兩個檔案建立secret

[root@k8scloude1 secret-manage]# kubectl create secret generic filesecret2 --from-file=/etc/hosts --from-file=/etc/shadow
secret/filesecret2 created

[root@k8scloude1 secret-manage]# kubectl get secrets filesecret2 -o yaml
apiVersion: v1
data:
  hosts: MTI3LjAuMC4xICAgbG9jYWxob3N0IGxvY2FsaG9zdC5sb2NhbGRvbWFpbiBsb2NhbGhvc3Q0IGxvY2FsaG9zdDQubG9jYWxkb21haW40Cjo6MSAgICAgICAgIGxvY2FsaG9zdCBsb2NhbGhvc3QubG9jYWxkb21haW4gbG9jYWxob3N0NiBsb2NhbGhvc3Q2LmxvY2FsZG9tYWluNgoxOTIuMTY4LjExMC4xMzAgazhzY2xvdWRlMQoxOTIuMTY4LjExMC4xMjkgazhzY2xvdWRlMgoxOTIuMTY4LjExMC4xMjggazhzY2xvdWRlMwo=
  shadow: cm9vdDokNiRaZEx6M20wRTk1clQ2RlJyJGNuWVJwMDU2bkZxVWJublovS3g4QzdzVkY0ZnZoWjNyM1VBRk5LWFYvVkhMQ1AwTGlwNGYzcDgydXMwLlYxeVcyb25RRzM5SzQ4LnAweUhTSmRkZnQuOjowOjk5OTk5Ojc6OjoKYmluOio6MTcxMTA6MDo5OTk5OTo3Ojo6CmRhZW1vbjoqOjE3MTEwOjA6OTk5OTk6Nzo6OgphZG06KjoxNzExMDowOjk5OTk5Ojc6OjoKbHA6KjoxNzExMDowOjk5OTk5Ojc6OjoKc3luYzoqOjE3MTEwOjA6OTk5OTk6Nzo6OgpzaHV0ZG93bjoqOjE3MTEwOjA6OTk5OTk6Nzo6OgpoYWx0Oio6MTcxMTA6MDo5OTk5OTo3Ojo6Cm1haWw6KjoxNzExMDowOjk5OTk5Ojc6OjoKb3BlcmF0b3I6KjoxNzExMDowOjk5OTk5Ojc6OjoKZ2FtZXM6KjoxNzExMDowOjk5OTk5Ojc6OjoKZnRwOio6MTcxMTA6MDo5OTk5OTo3Ojo6Cm5vYm9keToqOjE3MTEwOjA6OTk5OTk6Nzo6OgpzeXN0ZW1kLW5ldHdvcms6ISE6MTc4MjI6Ojo6OjoKZGJ1czohIToxNzgyMjo6Ojo6Ogpwb2xraXRkOiEhOjE3ODIyOjo6Ojo6CnBvc3RmaXg6ISE6MTc4MjI6Ojo6OjoKc3NoZDohIToxNzgyMjo6Ojo6OgpjaHJvbnk6ISE6MTc4MjI6Ojo6OjoKdG9tOiQ2JDEzdFdxdkFXUTBuR1hIMUUkVUx4aC5NcmZzUGh5QXhBMm84RUVqVTlrSnpSUlJPVEcxb1BkZXJvNlUyYmljZjRYYkFNVThyanZSQ2lTSlhnWEVrWjltTjhqYjFlZVJja1dmdm1XWjA6OjA6OTk5OTk6Nzo6Ogo=
kind: Secret
metadata:
  creationTimestamp: "2022-01-21T07:34:10Z"
  name: filesecret2
  namespace: secret-manage
  resourceVersion: "877748"
  selfLink: /api/v1/namespaces/secret-manage/secrets/filesecret2
  uid: e18212f1-eac1-457a-9b5f-aad39485f4dd
type: Opaque

解密

[root@k8scloude1 secret-manage]# kubectl get secrets filesecret2 -o jsonpath={.data.shadow} | base64 -d
root:$6$ZdLz3m0E95rT6FRr$cnYRp056nFqUbnnZ/Kx8C7sVF4fvhZ3r3UAFNKXV/VHLCP0Lip4f3p82us0.V1yW2onQG39K48.p0yHSJddft.::0:99999:7:::
bin:*:17110:0:99999:7:::
daemon:*:17110:0:99999:7:::
adm:*:17110:0:99999:7:::
lp:*:17110:0:99999:7:::
sync:*:17110:0:99999:7:::
shutdown:*:17110:0:99999:7:::
halt:*:17110:0:99999:7:::
mail:*:17110:0:99999:7:::
operator:*:17110:0:99999:7:::
games:*:17110:0:99999:7:::
ftp:*:17110:0:99999:7:::
nobody:*:17110:0:99999:7:::
systemd-network:!!:17822::::::
dbus:!!:17822::::::
polkitd:!!:17822::::::
postfix:!!:17822::::::
sshd:!!:17822::::::
chrony:!!:17822::::::
tom:$6$13tWqvAWQ0nGXH1E$ULxh.MrfsPhyAxA2o8EEjU9kJzRRROTG1oPdero6U2bicf4XbAMU8rjvRCiSJXgXEkZ9mN8jb1eeRckWfvmWZ0::0:99999:7:::

六.以環境變數的方式使用 Secret

6.1 明文方式儲存MySQL密碼

建立目錄存放yaml檔案

[root@k8scloude1 ~]# mkdir secret-manage   

建立名稱空間

[root@k8scloude1 ~]# kubectl create ns secret-manage  

把名稱空間切換到secret-manage

[root@k8scloude1 secret-manage]# kubens secret-manage
Context "kubernetes-admin@kubernetes" modified.
Active namespace is "secret-manage".

現在還沒有pod

[root@k8scloude1 ~]# cd secret-manage/

[root@k8scloude1 secret-manage]# pwd
/root/secret-manage

[root@k8scloude1 secret-manage]# kubectl get pod -o wide
No resources found in secret-manage namespace.

配置一個mysql pod,設定mysql 的root密碼為rootsec

[root@k8scloude1 secret-manage]# cat mysql.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: mysql
  name: mysql
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - image: hub.c.163.com/library/mysql:latest
    imagePullPolicy: IfNotPresent
    name: mysql
    resources: {}
    #設定環境變數
    env:
    #MySQL資料庫的root密碼為rootsec
    - name: MYSQL_ROOT_PASSWORD
      value: rootsec
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

建立pod

[root@k8scloude1 secret-manage]# kubectl apply -f mysql.yaml 
pod/mysql created

[root@k8scloude1 secret-manage]# kubectl get pods -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
mysql   1/1     Running   0          6s    10.244.112.133   k8scloude2   <none>           <none>

安裝mysql客戶端,mariadb命令和mysql命令基本相同

[root@k8scloude1 secret-manage]# yum -y install mariadb

連線mysql容器,成功連線mysql

[root@k8scloude1 secret-manage]# mysql -uroot -prootsec -h 10.244.112.133
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.18 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> exit
Bye

檢視pod的描述資訊,發現mysql root密碼是以明文的形式存在。

MYSQL_ROOT_PASSWORD: rootsec 直接就看到root密碼了,不安全。所以我們可以採用secret的方式讓賬號密碼不以明文的形式顯示。

[root@k8scloude1 secret-manage]# kubectl describe pod mysql | grep -A10 Environment
    Environment:
      MYSQL_ROOT_PASSWORD:  rootsec
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-gbdtf (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:

刪除pod

[root@k8scloude1 secret-manage]# kubectl delete pod mysql --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "mysql" force deleted

[root@k8scloude1 secret-manage]# kubectl get pod -o wide
No resources found in secret-manage namespace.

6.2 使用secret密文方式儲存MySQL密碼

現在把secret運用到pod裡,配置MySQL pod的yaml檔案

[root@k8scloude1 secret-manage]# vim mysqlsecret.yaml 

#以環境變數的方式引用secret
[root@k8scloude1 secret-manage]# cat mysqlsecret.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: mysql
  name: mysql
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - image: hub.c.163.com/library/mysql:latest
    imagePullPolicy: IfNotPresent
    name: mysql
    resources: {}
    env:
    - name: MYSQL_ROOT_PASSWORD
      valueFrom:
        secretKeyRef:
          #指定secret的名字和key
          name: genericsecret
          key: lisi
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

建立pod

[root@k8scloude1 secret-manage]# kubectl apply -f mysqlsecret.yaml 
pod/mysql created

[root@k8scloude1 secret-manage]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
mysql   1/1     Running   0          26s   10.244.112.132   k8scloude2   <none>           <none>

成功登入mysql

[root@k8scloude1 secret-manage]# mysql -uroot -pqwe -h 10.244.112.132
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.18 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> exit
Bye

檢視pod的描述資訊:MYSQL_ROOT_PASSWORD: <set to the key 'lisi' in secret 'genericsecret'> Optional: false,mysql的密碼沒有顯示,這時候,MYSQL_ROOT_PASSWORD密碼就不會以明文的方式顯示了

[root@k8scloude1 secret-manage]# kubectl describe pod mysql | grep -A10 Environment
    Environment:
      MYSQL_ROOT_PASSWORD:  <set to the key 'lisi' in secret 'genericsecret'>  Optional: false
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-wl5jt (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:

刪除pod

[root@k8scloude1 secret-manage]# kubectl delete pod mysql --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "mysql" force deleted

七.以卷的方式使用secret

7.1 以卷的方式使用secret

配置mysql pod的yaml檔案,讓secret以卷的方式應用,把filesecret值的內容掛載到/secret目錄

[root@k8scloude1 secret-manage]# vim volumesecret.yaml 

[root@k8scloude1 secret-manage]# cat volumesecret.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: mysql
  name: mysql
spec:
  terminationGracePeriodSeconds: 0
  #定義secret型別的卷
  volumes:
  - name: sec1
    secret:
      secretName: filesecret
  containers:
  - image: hub.c.163.com/library/mysql:latest
    imagePullPolicy: IfNotPresent
    name: mysql
    resources: {}
    #把sec1卷掛載到/secret目錄
    volumeMounts:
    - name: sec1
      mountPath: /secret
    env:
    - name: MYSQL_ROOT_PASSWORD
      valueFrom:
        secretKeyRef:
          name: genericsecret
          key: lisi
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

建立pod

[root@k8scloude1 secret-manage]# kubectl apply -f volumesecret.yaml 
pod/mysql created

[root@k8scloude1 secret-manage]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
mysql   1/1     Running   0          57s   10.244.112.134   k8scloude2   <none>           <none>

進入mysql容器,hosts檔案已經被掛載到/secret/目錄下

[root@k8scloude1 secret-manage]# kubectl exec -it mysql -- bash
root@mysql:/# ls /secret/
hosts
root@mysql:/# cat /secret/hosts 
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.110.130 k8scloude1
192.168.110.129 k8scloude2
192.168.110.128 k8scloude3
root@mysql:/# 
root@mysql:/# exit
exit

刪除pod

[root@k8scloude1 secret-manage]# kubectl delete pod mysql --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "mysql" force deleted

filesecret2這個secret包含了兩個檔案,所以就掛載了兩個檔案到/secret目錄下

[root@k8scloude1 secret-manage]# vim volumesecret.yaml 

[root@k8scloude1 secret-manage]# cat volumesecret.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: mysql
  name: mysql
spec:
  terminationGracePeriodSeconds: 0
  #定義secret型別的卷
  volumes:
  - name: sec1
    secret:
      secretName: filesecret2
  containers:
  - image: hub.c.163.com/library/mysql:latest
    imagePullPolicy: IfNotPresent
    name: mysql
    resources: {}
    #把sec1卷掛載到/secret目錄
    volumeMounts:
    - name: sec1
      mountPath: /secret
    env:
    - name: MYSQL_ROOT_PASSWORD
      valueFrom:
        secretKeyRef:
          name: genericsecret
          key: lisi
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

建立pod

[root@k8scloude1 secret-manage]# kubectl apply -f volumesecret.yaml 
pod/mysql created

[root@k8scloude1 secret-manage]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
mysql   1/1     Running   0          12s   10.244.112.135   k8scloude2   <none>           <none>

/secret/下有兩個檔案

[root@k8scloude1 secret-manage]# kubectl exec -it mysql -- bash
root@mysql:/# ls /secret/
hosts  shadow
root@mysql:/# exit
exit

刪除pod

[root@k8scloude1 secret-manage]# kubectl delete pod mysql --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "mysql" force deleted

filesecret2這個secret包含兩個檔案,subPath: shadow表示只掛載shadow檔案

[root@k8scloude1 secret-manage]# vim volumesecret.yaml 

[root@k8scloude1 secret-manage]# cat volumesecret.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: mysql
  name: mysql
spec:
  terminationGracePeriodSeconds: 0
  volumes:
  - name: sec1
    secret:
      secretName: filesecret2
  containers:
  - image: hub.c.163.com/library/mysql:latest
    imagePullPolicy: IfNotPresent
    name: mysql
    resources: {}
    volumeMounts:
    - name: sec1
      mountPath: /secret/sha.txt
      #subPath: shadow表示只掛載shadow檔案
      subPath: shadow
    env:
    - name: MYSQL_ROOT_PASSWORD
      valueFrom:
        secretKeyRef:
          name: genericsecret
          key: lisi
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

建立pod

[root@k8scloude1 secret-manage]# kubectl apply -f volumesecret.yaml 
pod/mysql created

[root@k8scloude1 secret-manage]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
mysql   1/1     Running   0          16s   10.244.112.136   k8scloude2   <none>           <none>

只有一個檔案被掛載

[root@k8scloude1 secret-manage]# kubectl exec -it mysql -- bash
root@mysql:/# ls /secret/
sha.txt
root@mysql:/# cat /secret/sha.txt 
root:$6$ZdLz3m0E95rT6FRr$cnYRp056nFqUbnnZ/Kx8C7sVF4fvhZ3r3UAFNKXV/VHLCP0Lip4f3p82us0.V1yW2onQG39K48.p0yHSJddft.::0:99999:7:::
bin:*:17110:0:99999:7:::
daemon:*:17110:0:99999:7:::
adm:*:17110:0:99999:7:::
lp:*:17110:0:99999:7:::
sync:*:17110:0:99999:7:::
shutdown:*:17110:0:99999:7:::
halt:*:17110:0:99999:7:::
mail:*:17110:0:99999:7:::
operator:*:17110:0:99999:7:::
games:*:17110:0:99999:7:::
ftp:*:17110:0:99999:7:::
nobody:*:17110:0:99999:7:::
systemd-network:!!:17822::::::
dbus:!!:17822::::::
polkitd:!!:17822::::::
postfix:!!:17822::::::
sshd:!!:17822::::::
chrony:!!:17822::::::
tom:$6$13tWqvAWQ0nGXH1E$ULxh.MrfsPhyAxA2o8EEjU9kJzRRROTG1oPdero6U2bicf4XbAMU8rjvRCiSJXgXEkZ9mN8jb1eeRckWfvmWZ0::0:99999:7:::
root@mysql:/# 
root@mysql:/# exit
exit

刪除pod

[root@k8scloude1 secret-manage]# kubectl delete pod mysql --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "mysql" force deleted

7.2 使用secret傳遞Nginx配置檔案

以卷的方式引用secret,這種方式可以用來傳遞配置檔案,不過更推薦使用ConfigMap傳遞配置檔案

建立一個名為nginxconfsecret的secret,該secret裡包含一個Nginx的配置檔案。

[root@k8scloude1 secret-manage]# kubectl create secret generic nginxconfsecret --from-file=nginx.conf 
secret/nginxconfsecret created

[root@k8scloude1 secret-manage]# kubectl get secrets 
NAME                  TYPE                                  DATA   AGE
default-token-wkjv8   kubernetes.io/service-account-token   3      4h47m
filesecret            Opaque                                1      73m
filesecret2           Opaque                                2      67m
genericsecret         Opaque                                2      87m
nginxconfsecret       Opaque                                1      17s

以yaml檔案的形式檢視secret

[root@k8scloude1 secret-manage]# kubectl get secrets nginxconfsecret -o yaml
apiVersion: v1
data:
  nginx.conf: CnVzZXIgIG5naW54Owp3b3JrZXJfcHJvY2Vzc2VzICBhdXRvOwoKZXJyb3JfbG9nICAvdmFyL2xvZy9uZ2lueC9lcnJvci5sb2cgbm90aWNlOwpwaWQgICAgICAgIC92YXIvcnVuL25naW54LnBpZDsKCgpldmVudHMgewogICAgd29ya2VyX2Nvbm5lY3Rpb25zICAxMDI0Owp9CgoKaHR0cCB7CiAgICBpbmNsdWRlICAgICAgIC9ldGMvbmdpbngvbWltZS50eXBlczsKICAgIGRlZmF1bHRfdHlwZSAgYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtOwoKICAgIGxvZ19mb3JtYXQgIG1haW4gICckcmVtb3RlX2FkZHIgLSAkcmVtb3RlX3VzZXIgWyR0aW1lX2xvY2FsXSAiJHJlcXVlc3QiICcKICAgICAgICAgICAgICAgICAgICAgICckc3RhdHVzICRib2R5X2J5dGVzX3NlbnQgIiRodHRwX3JlZmVyZXIiICcKICAgICAgICAgICAgICAgICAgICAgICciJGh0dHBfdXNlcl9hZ2VudCIgIiRodHRwX3hfZm9yd2FyZGVkX2ZvciInOwoKICAgIGFjY2Vzc19sb2cgIC92YXIvbG9nL25naW54L2FjY2Vzcy5sb2cgIG1haW47CgogICAgc2VuZGZpbGUgICAgICAgIG9uOwogICAgI3RjcF9ub3B1c2ggICAgIG9uOwoKICAgIGtlZXBhbGl2ZV90aW1lb3V0ICA2NTsKCiAgICAjZ3ppcCAgb247CgogICAgaW5jbHVkZSAvZXRjL25naW54L2NvbmYuZC8qLmNvbmY7Cn0KCg==
kind: Secret
metadata:
  creationTimestamp: "2022-01-21T08:40:57Z"
  name: nginxconfsecret
  namespace: secret-manage
  resourceVersion: "885421"
  selfLink: /api/v1/namespaces/secret-manage/secrets/nginxconfsecret
  uid: 97da759f-ef07-4edb-94a2-f04b043d7336
type: Opaque

配置Nginx pod的配置檔案,把secret:nginxconfsecret包含的nginx.conf掛載到/etc/nginx/nginx.conf下

[root@k8scloude1 secret-manage]# vim volumenginxconfsecret.yaml 

[root@k8scloude1 secret-manage]# cat volumenginxconfsecret.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx
  name: nginx
spec:
  terminationGracePeriodSeconds: 0
  #定義secret型別的卷
  volumes:
  - name: sec1
    secret:
      secretName: nginxconfsecret
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: nginx
    resources: {}
    #把nginxconfsecret這個secret掛載到/etc/nginx/nginx.conf
    volumeMounts:
    - name: sec1
      mountPath: /etc/nginx/nginx.conf
      subPath: nginx.conf
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

建立pod

[root@k8scloude1 secret-manage]# kubectl apply -f volumenginxconfsecret.yaml 
pod/nginx created

[root@k8scloude1 secret-manage]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          15s   10.244.112.138   k8scloude2   <none>           <none>

進入Nginx容器,檢視Nginx的配置檔案

[root@k8scloude1 secret-manage]# kubectl exec -it nginx -- bash
root@nginx:/# ls /etc/nginx/
conf.d	fastcgi_params	mime.types  modules  nginx.conf  scgi_params  uwsgi_params
root@nginx:/# ls /etc/nginx/nginx.conf 
/etc/nginx/nginx.conf

root@nginx:/# cat /etc/nginx/nginx.conf | head -3

user  nginx;
worker_processes  auto;
root@nginx:/# exit
exit

這種方式可以改變secret的內容從而達到改變容器裡配置檔案內容的目的,但是編輯secret(edit secret)的時候內容加密了,不好修改,這種方式不常用,推薦使用ConfigMap傳遞配置檔案。

刪除pod

[root@k8scloude1 secret-manage]# kubectl delete pod nginx --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "nginx" force deleted

相關文章