3.k8s儲存之ConfigMap、Secret

xiaokantianse發表於2021-01-11

1、ConfigMap

  • ConfigMap 功能在 Kubernetes1.2 版本中引入,許多應用程式會從配置檔案、命令列引數或環境變數中讀取配置資訊。ConfigMap API 給我們提供了向容器中注入配置資訊的機制,ConfigMap 可以被用來儲存單個屬性,也可以用來儲存整個配置檔案或者 JSON 二進位制大物件
  • 相當於一個配置檔案的註冊中心,將資料儲存在etcd中,讓Pod以變數和volume掛載
  • 應用場景
    • 比如好幾個Pod共用一個配置檔案

1.1、目錄建立

  • —from-file 指定在目錄下的所有檔案都會被用在 ConfigMap 裡面建立一個鍵值對,鍵的名字就是檔名,值就是檔案的內容 (—from-file 指定目錄)

  • # 建立game.properties 和 ui.properties 檔案
    [root@k8smaster configmap]# cat properties/game.properties
    enemies=aliens
    lives=3
    enemies.cheat=true
    enemies.cheat.level=noGoodRotten
    secret.code.passphrase=UUDDLRLRBABAS
    secret.code.allowed=true
    secret.code.lives=30
    [root@k8smaster configmap]# cat properties/ui.properties
    color.good=purple
    color.bad=yellow
    allow.textmode=true
    how.nice.to.look=fairlyNice
    
    # 使用命令建立 並且檢視 DATA 表示鍵的數量
    [root@k8smaster configmap]# kubectl create configmap game-config --from-file=/root/configmap/properties
    configmap/game-config created
    [root@k8smaster configmap]# kubectl get configmap
    NAME          DATA   AGE
    game-config   2      11s
    
    # 檢視詳細資訊
    [root@k8smaster configmap]# kubectl get configmap game-config -o yaml
    apiVersion: v1
    data:
      game.properties: |
        enemies=aliens
        lives=3
        enemies.cheat=true
        enemies.cheat.level=noGoodRotten
        secret.code.passphrase=UUDDLRLRBABAS
        secret.code.allowed=true
        secret.code.lives=30
      ui.properties: |
        color.good=purple
        color.bad=yellow
        allow.textmode=true
        how.nice.to.look=fairlyNice
    kind: ConfigMap
    metadata:
      creationTimestamp: "2020-12-17T03:31:25Z"
      managedFields:
      - apiVersion: v1
        fieldsType: FieldsV1
        fieldsV1:
          f:data:
            .: {}
            f:game.properties: {}
            f:ui.properties: {}
        manager: kubectl
        operation: Update
        time: "2020-12-17T03:31:25Z"
      name: game-config
      namespace: default
      resourceVersion: "1357422"
      selfLink: /api/v1/namespaces/default/configmaps/game-config
      uid: 2085e855-4bf9-4cdb-9ee8-30f1385ae2c5
    
    

1.2、檔案建立

  • 只要指定為一個檔案就可以從單個檔案中建立 ConfigMap

  • —from-file 這個引數可以使用多次,你可以使用兩次分別指定上個例項中的那兩個配置檔案,效果就跟指定整個目錄是一樣的 (—from-file 指定檔案)

  • # 建立configmap 並檢視
    [root@k8smaster configmap]# kubectl create configmap game-config1 --from-file=/root/configmap/properties/ui.properties
    configmap/game-config1 created
    [root@k8smaster configmap]# kubectl get configmap game-config1
    NAME           DATA   AGE
    game-config1   1      22s
    
    # 檢視詳細資訊 和目錄建立效果一樣
    [root@k8smaster configmap]# kubectl get configmap game-config1 -o yaml
    apiVersion: v1
    data:
      ui.properties: |
        color.good=purple
        color.bad=yellow
        allow.textmode=true
        how.nice.to.look=fairlyNice
    kind: ConfigMap
    metadata:
      creationTimestamp: "2020-12-17T03:37:30Z"
      managedFields:
      - apiVersion: v1
        fieldsType: FieldsV1
        fieldsV1:
          f:data:
            .: {}
            f:ui.properties: {}
        manager: kubectl
        operation: Update
        time: "2020-12-17T03:37:30Z"
      name: game-config1
      namespace: default
      resourceVersion: "1358296"
      selfLink: /api/v1/namespaces/default/configmaps/game-config1
      uid: 46e88eb8-1377-4710-abf6-a1d92273d5bf
    
    
    [root@k8smaster configmap]# kubectl describe configmap game-config1
    Name:         game-config1
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    
    Data
    ====
    ui.properties:
    ----
    color.good=purple
    color.bad=yellow
    allow.textmode=true
    how.nice.to.look=fairlyNice
    

1.3、字面值建立

  • 使用文字值建立,利用 —from-literal 引數傳遞配置資訊,該引數可以使用多次

  • # 建立configmap並檢視
    [root@k8smaster configmap]# kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
    configmap/special-config created
    [root@k8smaster configmap]# kubectl describe configmap special-config
    Name:         special-config
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    
    Data
    ====
    special.how:
    ----
    very
    special.type:
    ----
    charm
    Events:  <none>
    
    # 檢視詳細資訊 用cm也可以
    [root@k8smaster configmap]# kubectl get cm  special-config -o yaml
    apiVersion: v1
    data:
      special.how: very
      special.type: charm
    kind: ConfigMap
    metadata:
      creationTimestamp: "2020-12-17T03:43:34Z"
      managedFields:
      - apiVersion: v1
        fieldsType: FieldsV1
        fieldsV1:
          f:data:
            .: {}
            f:special.how: {}
            f:special.type: {}
        manager: kubectl
        operation: Update
        time: "2020-12-17T03:43:34Z"
      name: special-config
      namespace: default
      resourceVersion: "1359169"
      selfLink: /api/v1/namespaces/default/configmaps/special-config
      uid: 96b10ac7-964d-4c49-8dec-9dfd1697be72
    
    

1.4、Pod中使用

  • 使用 ConfigMap 來替代環境變數

    • 資源清單示例

      • 如果建立ConfigMap是對應的name已經存在,則會更新其中的鍵值對,不會刪除或建立失敗

      • 如果使用不存在的configmap 會出現失敗等錯誤

      • apiVersion: v1
        kind: ConfigMap
        metadata:
          name: special-config
          namespace: default
        # ConfigMap 中的鍵值對
        data:
          special.how: very
          special.type: charm
        
      • apiVersion: v1
        kind: ConfigMap
        metadata:
          name: log-config
          namespace: default
        # ConfigMap 中的鍵值對
        data:
          log_level: INFO
        
      • apiVersion: v1
        kind: Pod
        metadata:
          name: env-test-pod
        spec:
          containers:
          - name: test-container
            image: nginx
            # 打出環境變數
            command: [ "/bin/sh", "-c", "env" ]
            # 設定容器的環境變數 多個
            env:
            # 環境變數名稱為 SPECIAL_LEVEL_KEY
            - name: SPECIAL_LEVEL_KEY
              # 對應的值從configmap中取 configmap的名稱為special-config 取得是key為special.how的值 做為 環境變數的值
              valueFrom:
                configMapKeyRef:
                  name: special-config
                  key: special.how
            - name: SPECIAL_TYPE_KEY
              valueFrom:
                configMapKeyRef:
                  name: special-config
                  key: special.type
            - name: UI_PROPERTIES
              valueFrom:
                configMapKeyRef:
                  name: game-config
                  key: ui.properties
            # 將configmap所有的鍵值對作為 環境變數 key為名稱 value為值
            envFrom:
            - configMapRef:
                name: log-config
          restartPolicy: Never
        
      • # 建立Pod 並檢視日誌
        [root@k8smaster configmap]# kubectl apply -f env-test-pod.yaml
        pod/env-test-pod created
        [root@k8smaster configmap]# kubectl get pod
        NAME                            READY   STATUS      RESTARTS   AGE
        env-test-pod                    0/1     Completed   0          54s
        
        # 檢視日誌後發現輸出了我們設定的環境變數
        [root@k8smaster configmap]# kubectl logs env-test-pod
        
        SPECIAL_TYPE_KEY=charm
        
        UI_PROPERTIES=color.good=purple
        color.bad=yellow
        allow.textmode=true
        how.nice.to.look=fairlyNice
        
        SPECIAL_LEVEL_KEY=very
        
        log_level=INFO
        
        
  • 用 ConfigMap 設定命令列引數

    • 資源清單示例

      • apiVersion: v1
        kind: Pod
        metadata:
          name: linecommand-test-pod
        spec:
          containers:
          - name: test-container
            image: nginx
            # 在命令引數中 使用環境變數 用$(環境變數名)
            command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
            env:
            - name: SPECIAL_LEVEL_KEY
              valueFrom:
                configMapKeyRef:
                  name: special-config
                  key: special.how
            - name: SPECIAL_TYPE_KEY
              valueFrom:
                configMapKeyRef:
                  name: special-config
                  key: special.type
          restartPolicy: Never
        
      • # 建立 Pod 並檢視
        [root@k8smaster configmap]# kubectl apply -f linecommand-test-pod.yaml
        pod/linecommand-test-pod created
        [root@k8smaster configmap]# vim linecommand-test-pod.yaml
        [root@k8smaster configmap]# kubectl get pod
        NAME                            READY   STATUS      RESTARTS   AGE
        linecommand-test-pod            0/1     Completed   0          65s
        
        # 建立日誌 發現輸出了 環境變數
        [root@k8smaster configmap]# kubectl logs linecommand-test-pod
        very charm
        
        
  • 通過資料卷外掛使用ConfigMap

    • 在資料卷裡面使用這個 ConfigMap,有不同的選項。最基本的就是將檔案填入資料卷,在這個檔案中,鍵就是檔名,鍵值就是檔案內容

    • 資源清單示例

      • apiVersion: v1
        kind: Pod
        metadata:
          name: volume-test-pod
        spec:
          containers:
          - name: test-container
            image: nginx
            command: [ "/bin/sh", "-c", "cat /etc/config/special.how" ]
            # 容器掛載的資料卷
            volumeMounts:
            # 資料卷的名稱 在Pod宣告的資料卷中選擇
            - name: config-volume
              # 掛載到容器內部的路徑
              mountPath: /etc/config
          # Pod的資料卷
          volumes:
          # 資料卷的名稱
          - name: config-volume
            # 資料卷掛載的地方 此處是來源configMap 名稱是special-config 
            # 也就是說哪個容器使用的資料卷 會在容器掛載的路徑下生成多個檔案(取決於configmap中key的數量) key為檔名,value為檔案內容
            configMap:
              name: special-config
          restartPolicy: Never
        
      • # 建立Pod並檢視
        [root@k8smaster configmap]# kubectl apply -f volume-test-pod.yaml
        pod/vloume-test-pod created
        [root@k8smaster configmap]# kubectl get pod
        volume-test-pod                 0/1     Completed   0          24s
        
        # 檢視日誌 輸出了檔案內容
        [root@k8smaster configmap]# kubectl logs vloume-test-pod
        very
        
        

1.5、ConfigMap熱更新

  • 更新 ConfigMap 後

    • 使用該 ConfigMap 掛載的 Env 不會同步更新

    • 使用該 ConfigMap 掛載的 Volume 中的資料需要一段時間(實測大概10秒)才能同步更新 (這樣就可以實時修改配置檔案,比如nginx的)

    • 雖然配置檔案可以熱更新,但是能不能起作用還要看具體情況,比如nginx,啟動之後,就不會再去看配置檔案了,我們需要手動重啟nginx,來達到重新讀取配置檔案的目的,如果有的服務可以一直監測配置檔案,我們則不用手動處理(這種情況很少)

    • 更新 ConfigMap 目前並不會觸發相關 Pod 的滾動更新,可以通過修改 pod annotations 的方式強制觸發滾動更新

      • $ kubectl patch deployment hot-update-test --patch '{"spec": {"template": {"metadata": {"annotations":{"version/config": "20201010" }}}}}'
        
      • 這個例子裡我們在 .spec.template.metadata.annotations 中新增 version/config ,每次通過修改version/config 來觸發滾動更新

  • 資源清單示例

    • apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: hot-update-test
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: nginx
        template:
          metadata:
            labels:
              app: nginx
          spec:
            containers:
            - name: my-nginx
              image: nginx
              ports:
              - containerPort: 80
              # 容器使用Pod的容器卷 並掛載在自己內部
              volumeMounts:
              - name: config-volume
                mountPath: /etc/config
            # 宣告Pod的容器卷
            volumes:
            - name: config-volume
              configMap:
                name: log-config
      
    • # 建立Pod 並檢視掛載目錄下的檔案 和檔案內容
      [root@k8smaster configmap]# kubectl apply -f hot-update-test.yaml
      deployment.apps/hot-update-test created
      [root@k8smaster configmap]# kubectl get pod
      NAME                               READY   STATUS      RESTARTS   AGE
      hot-update-test-6fd96995b6-jfw2w   1/1     Running     0          100s
      
      # 檢視掛載目錄下的檔案 和檔案內容
      [root@k8smaster configmap]# kubectl exec -it hot-update-test-6fd96995b6-jfw2w -- ls /etc/config
      log_level
      [root@k8smaster configmap]# kubectl exec -it hot-update-test-6fd96995b6-jfw2w -- cat /etc/config/log_level
      INFO
      
    • 修改 ConfigMap(log-config)中的內容 (將INFO改成DEBUD)

      • [root@k8smaster configmap]# kubectl edit configmap log-config
        configmap/log-config edited
        [root@k8smaster configmap]# kubectl describe configmap log-config
        Name:         log-config
        Namespace:    default
        Labels:       <none>
        Annotations:
        Data
        ====
        log_level:
        ----
        DEBUG
        Events:  <none>
        
      • # 檢視log_level 檔案內容發生了改變
        [root@k8smaster configmap]# kubectl exec -it hot-update-test-6fd96995b6-jfw2w -- cat /etc/config/log_level
        DEBUG
        

2、Secret

  • ConfigMap將資料以明文的方式存放,不太安全,Secret可以用Base64編碼存放,比較安全
  • Secret 解決了密碼、token、金鑰等敏感資料的配置問題,而不需要把這些敏感資料暴露到映象或者 Pod Spec中。Secret 可以以 Volume 或者環境變數的方式使用
  • Secret 有三種型別
    • Service Account :用來訪問Kubernetes API,由Kubernetes自動建立,並且會自動掛載到Pod的/run/secrets/kubernetes.io/serviceaccount目錄中,比如coredns、kube-proxy可以訪問(不是什麼都可以訪問Kubernetes API)
    • Opaque :base64編碼格式的Secret,用來儲存密碼、金鑰等
    • kubernetes.io/dockerconfigjson :用來儲存私有 docker registry 的認證資訊

2.1、Service Account

  • # 查詢系統的Pod 
    [root@k8smaster secret]# kubectl get pod -n kube-system
    NAME                                READY   STATUS    RESTARTS   AGE
    coredns-7ff77c879f-494fb            1/1     Running   2          46h
    coredns-7ff77c879f-tvgrz            1/1     Running   2          46h
    etcd-k8smaster                      1/1     Running   3          6d19h
    kube-apiserver-k8smaster            1/1     Running   3          6d19h
    kube-controller-manager-k8smaster   1/1     Running   16         6d19h
    kube-flannel-ds-amd64-hflj8         1/1     Running   4          6d6h
    kube-flannel-ds-amd64-s9xhk         1/1     Running   3          6d6h
    kube-flannel-ds-amd64-wp7mp         1/1     Running   4          6d6h
    kube-proxy-5l8kb                    1/1     Running   2          47h
    kube-proxy-6n8vp                    1/1     Running   2          47h
    kube-proxy-lgcxp                    1/1     Running   2          47h
    kube-scheduler-k8smaster            1/1     Running   17         6d19h
    
    # 檢視 kube-proxy/run/secrets/kubernetes.io/serviceaccount 下的檔案
    # ca.crt 是https的證書資訊 namespace 是名稱空間 token 是訪問時攜帶的token
    [root@k8smaster secret]# kubectl exec -it -n kube-system kube-proxy-5l8kb -- ls /run/secrets/kubernetes.io/serviceaccount
    ca.crt  namespace  token
    

2.2、Opaque

  • Opaque 型別的資料是一個 map 型別,要求 value 是 base64 編碼格式

    • [root@k8smaster secret]# echo admin | base64
      YWRtaW4K
      [root@k8smaster secret]# echo 123456 | base64
      MTIzNDU2Cg==
      
      # 解碼
      [root@k8smaster secret]# echo YWRtaW4K | base64 -d
      admin
      
  • 資源清單示例

    • apiVersion: v1
      kind: Secret
      metadata:
        name: mysecret
      type: Opaque
      data:
        username: YWRtaW4=
        password: MTIzNDU2Cg==
      
    • # 建立 secret 並檢視
      [root@k8smaster secret]# kubectl apply -f secret-test.yaml
      secret/mysecret created
      
      [root@k8smaster secret]# kubectl get secret
      NAME                  TYPE                                  DATA   AGE
      default-token-99w8n   kubernetes.io/service-account-token   3      6d19h
      mysecret              Opaque                                2      8s
      
      
  • 將 Secret 掛載到 Volume 中

    • Secret中的鍵值對會以檔案的方式存在在容器掛載的目錄下 key為檔名 value為檔案值(自動解碼)

    • 資源清單示例

      • apiVersion: v1
        kind: Pod
        metadata:
          name: opaque-test
          labels:
            name: opaque-test
        spec:
          volumes:
          - name: secrets
            # 使用secret secret的名稱是mysecret
            secret:
              secretName: mysecret
          containers:
          - image: nginx
            name: opaque-nginx
            volumeMounts:
            - name: secrets
              mountPath: /etc/opaque
              # 只讀
              readOnly: true
        
      • # 建立Pod
        [root@k8smaster secret]# kubectl apply -f opaque-test.yaml
        pod/opaque-test created
        [root@k8smaster secret]# kubectl get pod
        NAME                               READY   STATUS    RESTARTS   AGE
        hot-update-test-6fd96995b6-jfw2w   1/1     Running   0          60m
        opaque-test                        1/1     Running   0          51s
        
        # 檢視掛載目錄下的檔案
        [root@k8smaster secret]# kubectl exec -it opaque-test -- ls /etc/opaque
        password  username
        
        # 檢視掛載目錄下的檔案內容 自動解碼
        [root@k8smaster secret]# kubectl exec -it opaque-test -- cat /etc/opaque/username
        admin
        
  • 將 Secret 匯出到環境變數中

    • 資源清單示例

      • apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: opaque-env
        spec:
          replicas: 2
          # 這個版本的Deployment不能省去selector
          selector:
            matchLabels:
              app: opaque-deployment
          template:
            metadata:
              labels:
                app: opaque-deployment
            spec:
              containers:
              - name: pod-1
                image: nginx
                ports:
                - containerPort: 80
                # 設定環境變數
                env:
                # 環境變數名稱
                - name: TEST_USER
                  # 環境變數值得來源為secret secret的名稱是mysecret 用的是key為username的value
                  valueFrom:
                    secretKeyRef:
                      name: mysecret
                      key: username
                - name: TEST_PASSWORD
                  valueFrom:
                    secretKeyRef:
                      name: mysecret
                      key: password
        
      • # 建立deployment 並檢視Pod
        [root@k8smaster secret]# kubectl apply -f opaque-env.yaml
        deployment.apps/opaque-env created
        [root@k8smaster secret]# kubectl get pod
        NAME                               READY   STATUS    RESTARTS   AGE
        opaque-env-54d4fd67f4-9xrrs        1/1     Running   0          11s
        opaque-env-54d4fd67f4-h7689        1/1     Running   0          11s
        
        # 檢視兩個Pod中的環境變數 均已解碼
        [root@k8smaster secret]# kubectl exec -it opaque-env-54d4fd67f4-9xrrs -- env
        
        TEST_USER=admin
        TEST_PASSWORD=123456
        
        [root@k8smaster secret]# kubectl exec -it opaque-env-54d4fd67f4-h7689 -- env
        
        TEST_USER=admin
        TEST_PASSWORD=123456
        
        

2.3、kubernetes.io/dockerconfigjson

  • 用來儲存私有 docker registry 的認證資訊

  • 使用命令建立(docker資訊換成自己的)

    • kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
      
    • # 檢視 myregistrykey 檢視具體資訊也是編碼過的
      [root@k8smaster secret]# kubectl get secret
      NAME                  TYPE                                  DATA   AGE
      default-token-99w8n   kubernetes.io/service-account-token   3      6d20h
      myregistrykey         kubernetes.io/dockerconfigjson        1      10s
      mysecret              Opaque                                2      50m
      
  • 使用docker的登入檔案建立

    • cat ~/.docker/config.json 這個docker的登入檔案登入docker的倉庫後自動生成

    • # 將登入檔案的內容進行base64編碼
      cat ~/.docker/config.json | base64
      
      # 將編碼後的結果寫入資源清單中
      cat > myregistrykey.yaml <<EOF
      apiVersion: v1
      kind: Secret
      metadata:
        name: myregistrykey
      data:
        .dockerconfigjson: docker的登入檔案內容的base64編碼
      type: kubernetes.io/dockerconfigjson
      EOF
      
      # 建立serret
      kubectl create -f myregistrykey.yaml
      
    • 資源清單示例

      • apiVersion: v1
        kind: Secret
        metadata:
          name: myregistrykey
        data:
          .dockerconfigjson: docker的登入檔案內容的base64編碼
        type: kubernetes.io/dockerconfigjson
        
  • 資源清單示例

    • apiVersion: v1
      kind: Pod
      metadata:
        name: docker-pod
      spec:
        containers:
          - name: foo
            # 這個映象需要在自己的倉庫中 需要身份認證
            image: registry.cn-hangzhou.aliyuncs.com/******/mytomcat:8.1.0
        # 使用映象拉取的secret 包含映象倉庫的地址 使用者名稱 密碼等
        imagePullSecrets:
          - name: myregistrykey
      
    • # 檢視pod 已經執行
      [root@k8smaster secret]# kubectl get pod
      NAME                               READY   STATUS    RESTARTS   AGE
      docker-pod                         1/1     Running   0          6m22s
      

相關文章