k8s資源物件(二)

2023-05-24 06:00:32

Configmap和Secret資源介紹

secret和configmap資源都是通過掛載的方式將對應資料掛載到容器內部環境中去使用,兩者的使用沒有太多的不同 ,configmap資源通常用於為pod提供組態檔;secret資源主要用於為pod提供證書、使用者名稱密碼等敏感資料;

configmap資源

Configmap將非機密性資訊(如設定資訊)和映象解耦, 實現方式為將設定資訊放到configmap物件中,然後在pod的中作為Volume掛載到pod中,從而實現匯入設定的目的。

ConfigMap資源使用場景

  • 通過Configmap給pod中的容器服務提供組態檔,組態檔以掛載到容器的形式使用。
  • 通過Configmap給pod定義全域性環境變數。
  • 通過Configmap給pod傳遞命令列引數,如mysql -u -p中的賬戶名密碼可以通過Configmap傳遞。

注意事項

  • Configmap需要在pod使用它之前建立。
  • pod只能使用位於同一個namespace的Configmap,即Configmap不能跨namespace使用。
  • 通常用於非安全加密的設定場景。
  • Configmap通常是小於1MB的設定。

secret資源

Secret 的功能類似於 ConfigMap給pod提供額外的設定資訊,但是Secret是一種包含少量敏感資訊例如密碼、令牌或金鑰的物件。Secret 的名稱必須是合法的 DNS 子域名。每個Secret的大小最多為1MiB,主要是為了避免使用者建立非常大的Secret進而導致API伺服器和kubelet記憶體耗盡,不過建立很多小的Secret也可能耗盡記憶體,可以使用資源配額來約束每個名稱空間中Secret的個數。在通過yaml檔案建立secret時,可以設定data或stringData欄位,data和stringData欄位都是可選的,data欄位中所有鍵值都必須是base64編碼的字串,如果不希望執行這種 base64字串的轉換操作,也可以選擇設定stringData欄位,其中可以使用任何非加密的字串作為其取值。

Secret資源使用流程

首先使用者向apiserver提交建立secret資源的請求;apiserver收到使用者的資源建立請求,通過apiserver的認證授權、准入控制後,apiserver會將建立好的secret資訊存放在etcd中;隨後使用者在建立pod中呼叫了掛載某個secret以後,對應在pod建立時會被pause容器將對應secret資源中的data資料載入至對應pod中,從而實現讓向pod內部傳遞敏感資料的目的;

Secret資源使用場景

  • 作為掛載到一個或多個容器上的卷 中的檔案(crt檔案、key檔案)。
  • 作為容器的環境變數。
  • 由 kubelet 在為 Pod 拉取映象時使用(與映象倉庫的認證)。

Secret資源型別簡介

Kubernetes預設支援多種不同型別的secret,用於一不同的使用場景,不同型別的secret的設定引數也不一樣。

configmap資源使用範例

基於configmap給nginx pod提供自定義的server設定

1.1、建立configmap資源

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  mysite: |
    server {
       listen       80;
       server_name  www.mysite.com;
       index        index.html index.php index.htm;

       location / {
           root /data/nginx/mysite;
           if (!-e $request_filename) {
               rewrite ^/(.*) /index.html last;
           }
       }
    }

  myserver: |
    server {
       listen       80;
       server_name  www.myserver.com;
       index        index.html index.php index.htm;

       location / {
           root /data/nginx/myserver;
           if (!-e $request_filename) {
               rewrite ^/(.*) /index.html last;
           }
       }
    }  

data欄位中的mysite和myserver是用來標識不同設定資訊的,即該名稱用於pod掛載configmap資源時被參照的名稱;

應用資源設定清單

kubectl apply -f nginx-configmap-demo.yaml

驗證configmap資源

kubectl get cm

kubectl describe cm nginx-config  

1.2、建立pod使用使用掛載configmap

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: harbor.ik8s.cc/baseimages/nginx:1.20.0
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /data/nginx/mysite
          name: nginx-mysite-statics
        - mountPath: /data/nginx/myserver
          name: nginx-myserver-statics
        - name: nginx-mysite-config
          mountPath:  /etc/nginx/conf.d/mysite/
        - name: nginx-myserver-config
          mountPath:  /etc/nginx/conf.d/myserver/
      volumes:
      - name: nginx-mysite-config
        configMap:
          name: nginx-config
          items:
             - key: mysite
               path: mysite.conf
      - name: nginx-myserver-config
        configMap:
          name: nginx-config
          items:
             - key: myserver
               path: myserver.conf
      - name: nginx-myserver-statics
        nfs:
          server: 192.168.0.42
          path: /data/k8sdata/myserver
      - name: nginx-mysite-statics
        nfs:
          server: 192.168.0.42
          path: /data/k8sdata/mysite

---
apiVersion: v1
kind: Service
metadata:
  name: ng-deploy-80
spec:
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30019
    protocol: TCP
  type: NodePort
  selector:
    app: ng-deploy-80

上述設定清單主要定義了一個deploy型別的控制器和nodeport型別的service,其中deploy控制器定義了一個nginx pod 掛載使用nfs服務上的靜態資源和掛載使用configmap給nginx提供設定;service主要定義了通過標籤選擇器來匹配pod來實現將使用者請求的流量轉發至後端nginx pod;

在nfs伺服器上準備靜態資源目錄

在nfs伺服器上建立靜態資源

應用設定清單建立pod使用configmap資源和掛載nfs伺服器上的靜態資源

kubectl apply -f nginx-dep-demo.yaml

驗證,檢視pod設定資訊是否正常被pod掛載?

可以看到pod正常掛載configmap中指定的設定資訊;

在k8s叢集節點任意節點上修改hosts檔案來解析域名

在k8s的節點上將對應域名指向叢集任意節點地址上即可

存取nginx,看看對應nfs靜態資源是否能夠正常被存取到?

這裡雖然能夠正常被存取nginx主頁,但是不是我們想要的頁面,這其中的原因是,我們把nginxpod的組態檔掛載的路徑沒有在nginx.conf中匯入,導致我們掛載的設定在nginx中沒有生效;

解決辦法

  • 進入pod內部,修改nginx.conf組態檔 (臨時生效,pod重建失效,不推薦)
  • 在製作映象時,直接將主組態檔寫好,再製作好映象;(推薦)
  • 使用configmap資源將匯入nginx設定再此掛載至/etc/nginx/conf.d/目錄下;(預設nginx只匯入了/etc/nginx/conf.d/*.conf,我們只需要將匯入設定以.conf結尾的組態檔掛載至/etc/nginx/conf.d/目錄下即可)

進入nginxpod,修改主組態檔

這裡主要加上匯入/etc/nginx/conf.d/下子目錄下的.conf結尾的組態檔,讓/etc/nginx/conf.d/myserver/myserver.conf和/etc/nginx/conf.d/mysite/mysite.conf組態檔被nginx載入;

驗證:使用不同域名存取nginx看看是否能夠存取到對應不同的靜態資源?

現在使用不同域名的方式存取nginx就可以存取到不同站點的資源了;生產中會通過前端一個負載均衡器來反向代理nodeport型別的service;

基於configmap給pod提供自定義環境變數

1.1、建立configmap資源

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  host: "172.31.7.189"
  username: "user1"
  password: "12345678"

應用上述設定清單,建立configmap資源

1.2、建立pod使用configmap資源

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: harbor.ik8s.cc/baseimages/nginx:1.20.0
        env:
        - name: HOST
          valueFrom:
            configMapKeyRef:
              name: nginx-config
              key: host
        - name: USERNAME
          valueFrom:
            configMapKeyRef:
              name: nginx-config
              key: username
        - name: PASSWORD
          valueFrom:
            configMapKeyRef:
              name: nginx-config
              key: password
        ######
        - name: "password"
          value: "123456"
        ports:
        - containerPort: 80

向pod內部傳遞環境變數的方式有兩種,一種是通過env欄位來參照configmap資源,使用name欄位來指定環境變數名稱,使用valueFrom欄位來指定對應環境變數值的來源;configMapKeyRef欄位表示使用configmap資源來向對應環境變數賦值;name是指定configmap的名稱,key是用來指定configmap中對應key;另外一種就是使用env欄位,通過列表的方式直接向pod傳遞鍵值環境變數;

應用設定清單

可以看到建立的pod內部有我們再configmap中定義的環境變數,也有我們通過env直接指定鍵值的環境變數;

secret資源使用範例

基於自定義的Secret實現Nginx https認證

1、自簽名證書製作

1.1、生成自簽名CA證書

openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 3560 -nodes -subj '/CN=www.ca.com'

1.2、生成自簽名證書私鑰和CSR

openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN=www.mysite.com'

1.3、用自簽名CA證書籤發自簽名證書csr生成自簽名證書crt

openssl x509 -req -sha256 -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt

2、基於自簽名證書在k8s上建立secret資源

kubectl create secret tls myserver-tls-key --cert=./server.crt --key=./server.key

3、建立nginx設定清單使用secret

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
 default: |
    server {
       listen       80;
       server_name  www.mysite.com;
       listen 443 ssl;
       ssl_certificate /etc/nginx/conf.d/certs/tls.crt;
       ssl_certificate_key /etc/nginx/conf.d/certs/tls.key;

       location / {
           root /usr/share/nginx/html; 
           index index.html;
           if ($scheme = http ){  #未加條件判斷,會導致死迴圈
              rewrite / https://www.mysite.com permanent;
           }  

           if (!-e $request_filename) {
               rewrite ^/(.*) /index.html last;
           }
       }
    }

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myserver-myapp-frontend-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myserver-myapp-frontend
  template:
    metadata:
      labels:
        app: myserver-myapp-frontend
    spec:
      containers:
      - name: myserver-myapp-frontend
        image: harbor.ik8s.cc/baseimages/nginx:1.20.0
        ports:
          - containerPort: 80
        volumeMounts:
          - name: nginx-config
            mountPath:  /etc/nginx/conf.d/myserver
          - name: myserver-tls-key
            mountPath:  /etc/nginx/conf.d/certs
      volumes:
      - name: nginx-config
        configMap:
          name: nginx-config
          items:
             - key: default
               path: mysite.conf
      - name: myserver-tls-key
        secret:
          secretName: myserver-tls-key 


---
apiVersion: v1
kind: Service
metadata:
  name: myserver-myapp-frontend
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30018
    protocol: TCP
  - name: htts
    port: 443
    targetPort: 443
    nodePort: 30019
    protocol: TCP
  selector:
    app: myserver-myapp-frontend 

上述設定清單主要建立了一個configmap資源,用來給nginxpod提供設定資訊,然後建立了一個deploy控制器執行了一個nginx pod ,這個pod掛載使用configmap和secret資源;最後建立了一個service將對應nginx Pod服務暴露給叢集外部使用者端存取;

應用設定清單

驗證:進入pod內部,檢視對應設定資訊和證書檔案是否正常掛載?

可以看到我們建立configmap資源中的設定資訊和secret資源中的證書資訊都正常掛載至nginx pod對應指定目錄下

修改nginx主組態檔,讓其載入我們通過configmap掛載的組態檔

過載nginx pod組態檔

上述方法不推薦,正確的做法就是在打映象的時候,將對應組態檔打入映象;或者我們使用configmap將對應設定資訊建立為configmap資源物件,然後再pod中掛載對應設定資訊即可;

驗證:存取叢集任意節點30018埠和30019埠,看看對應nginx pod是否能夠正常被存取?是否是加密存取呢?

從上面的存取情況可以看到,直接存取30019,會報400,這是因為30019時一個https的埠,用http的協定去存取肯定不能正常響應;當我們存取30018時,對應頁面會進行跳轉到https://www.mysite.com,這是因為我們在nginx的設定中設定了存取http埠進行重定向https://www.mysite.com;存取30019埠時,用https協定存取30019時,也正常載入了證書;

使用configmap將nginx設定資訊匯入主組態檔

apiVersion: v1
kind: ConfigMap
metadata:
  name: include-conf
data:
 include.conf: |
    include /etc/nginx/conf.d/*/*.conf;
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
 default: |
    server {
       listen       80;
       server_name  www.mysite.com;
       listen 443 ssl;
       ssl_certificate /etc/nginx/conf.d/certs/tls.crt;
       ssl_certificate_key /etc/nginx/conf.d/certs/tls.key;

       location / {
           root /usr/share/nginx/html; 
           index index.html;
           if ($scheme = http ){  #未加條件判斷,會導致死迴圈
              rewrite / https://www.mysite.com permanent;
           }  

           if (!-e $request_filename) {
               rewrite ^/(.*) /index.html last;
           }
       }
    }

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myserver-myapp-frontend-deployment-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myserver-myapp-frontend-v1
  template:
    metadata:
      labels:
        app: myserver-myapp-frontend-v1
    spec:
      containers:
      - name: myserver-myapp-frontend-v1
        image: harbor.ik8s.cc/baseimages/nginx:1.20.0
        ports:
          - containerPort: 80
        volumeMounts:
          - name: nginx-config
            mountPath:  /etc/nginx/conf.d/myserver
          - name: myserver-tls-key
            mountPath:  /etc/nginx/conf.d/certs
          - name: include-conf
            mountPath: /etc/nginx/conf.d
      volumes:
      - name: nginx-config
        configMap:
          name: nginx-config
          items:
             - key: default
               path: mysite.conf
      - name: myserver-tls-key
        secret:
          secretName: myserver-tls-key 
      - name: include-conf
        configMap:
          name: include-conf
          items:
             - key: include.conf
               path: include.conf
---
apiVersion: v1
kind: Service
metadata:
  name: myserver-myapp-frontend-v1
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 31080
    protocol: TCP
  - name: htts
    port: 443
    targetPort: 443
    nodePort: 31443
    protocol: TCP
  selector:
    app: myserver-myapp-frontend-v1

pod掛載使用configmap時,對應pod內部必須事先不存在對應檔案,如果對應檔案存在,則對應pod會啟不起來;所以我們掛載configmap時指定掛載至/etc/nginx/conf.d即可;

應用設定清單,看看使用https存取31443是否可以正常存取?


基於自定義的Secret實現私有映象的下載認證

建立secret資源

方式一:通過命令建立

kubectl create secret docker-registry harbor.ik8s.cc-imagepull \
                                    --docker-server=harbor.ik8s.cc \
                                    --docker-username=admin \
                                    --docker-password=123456

方式二:通過docker/containerd認證檔案建立

登入harbor,生成config.json檔案

使用config.json檔案建立secret資源

kubectl create secret generic harbor.k8s.cc-registry-image-pull-key \
                --from-file=.dockerconfigjson=/root/.docker/config.json \
                --type=kubernetes.io/dockerconfigjson

在harbor上將baseimgaes倉庫設定為私有倉庫

驗證,使用docker/containerd拉取harbor.k8s.cc/baseimages下的映象,看看是否可以正常拉取?

可以看到現在更改倉庫為私有倉庫以後,對應倉庫中的映象不可以正常被拉取

驗證,使用私有倉庫映象建立pod,看看pod是否能夠正常執行起來?

apiVersion: v1
kind: Pod
metadata:
  name: "tomcat-demo"
  namespace: default
  labels:
    app: "tomcat-demo"
spec:
  containers:
  - name: tomcat-demo
    image: "harbor.ik8s.cc/baseimages/tomcat:v1"
    ports:
    - containerPort:  8080
      name:  http

應用設定清單,看看對應pod是否能夠正常跑起來?

可以看到對應pod處於ErrImagePull狀態,該狀態就是表示pod在建立時,下載映象錯誤

檢視pod詳細資訊

建立pod使用secret

apiVersion: v1
kind: Pod
metadata:
  name: "tomcat-demo"
  namespace: default
  labels:
    app: "tomcat-demo"
spec:
  containers:
  - name: tomcat-demo
    image: "harbor.ik8s.cc/baseimages/tomcat:v1"
    imagePullPolicy: Always
    ports:
    - containerPort:  8080
      name:  http
  imagePullSecrets:
    - name: harbor.k8s.cc-registry-image-pull-key

spec欄位中使用imagePullSecrets欄位來參照dockerconfigjson型別的secret資源,使用name欄位指定secret的名稱即可

驗證pod執行狀態

應用設定清單,看看對應pod是否能夠正常跑起來?

可以看到現在對應pod正常跑起來