iT邦幫忙

2022 iThome 鐵人賽

DAY 10
0

本篇大綱

這篇將會介紹在 K8s 組出服務必備的第三元素:Storage & ConfigMap & Secret。

內文

K8s 另一個很重要的東西就是儲存了,Docker 可以用 --volume 直接連結好位置就可以永久儲存,可是 K8s 他無法像 Docker 那麼方便,他會需要 Persistent Volume & Persistent Volume Claim 來完成。

設定檔通常都是小檔案,放在 Persistent Volume 是有點大材小用,因此就會有 ConfigMap 解決這情境,那如果有些參數是不能直接在 K8s YAML 檔案上面,那該怎麼辦?Secret 就是好用的東西,那我就來一個個介紹吧!

Persistent Volume

Persistent Volume 簡稱 PV,你可以把他想像成硬碟,建立好幾組硬碟,硬碟也有分好幾種方式:

  • AWS, Azure, GCP(這種公有雲都有相對應的 Solution,這邊只會提私有雲常用的策略)
  • CephFS, RBD
  • GlusterFS
  • OpenStack Cinder CSI(後面有一篇會寫到如何跟 OpenStack 整合)
  • HostPath(官方有說明 Production 避免使用它,容易產生系統漏洞)
  • iSCSI
  • local(掛在 Node 的硬碟上儲存)
  • NFS

這裡會給予 NFS 的範例,但是 Demo 的時候不會有 NFS,因為我們沒有 NFS Server。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs
spec:
  capacity:
    storage: 1Mi
  accessModes:
    - ReadWriteOnce
  nfs:
    server: 172.17.8.101
    path: "/nfsshare"

.spec.capacity.storage 就是儲存空間大小

.spec.accessModes[] 就是這個 PV 能給 Node 掛載模式,這裡不是在指 Pod 喔!

能跟 OpenStack 整合的就 Cinder CSI,後面有篇文章會說如何讓 OpenStack 跟 PVC 動態串接。

Persistent Volume Claim

Persistent Volume Claim 簡稱 PVC (這裡的 PVC 不是聚氯乙烯),它就是要負責去提出要占用哪一顆硬碟 (Persistent Volume),根據它的需求去拿取。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  labels:
    app: wordpress
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi

PVC 只要看到有符合需求的 PV 就會顯示 Bound,代表綁定成功,但如果像現在這樣情況,需求要 20Gi,但是 PV 只有 1Mi,那他們之間就不會有綁定。

明天文章的 Demo 是不會有 PV & PVC,空間都會使用 emptydir,也就是臨時用的資料夾,emptydir 的特性就是只要 Pod 在節點上被刪除,資料就會遺失,這個要注意。

ConfigMap

顧名思義,通常會把設定檔放在 ConfigMap,可以用兩種方式 file 或 env 型態

那我使用 nginx.conf 作為示範 file:

# 1. Save as `nginx.conf`
worker_processes  1;

error_log  logs/error.log;

pid        logs/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                     '$status $body_bytes_sent "$http_referer" '
                     '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  logs/access.log  main;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;
        access_log  logs/host.access.log  main;
        location / {
            root   html;
            index  index.html index.htm;
        }
        error_page  404              /404.html;
        error_page  500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

把他儲存以後

kubectl create cm nginx-conf --from-file=./nginx.conf # cm 代表 configmap,可以直接縮寫

https://ithelp.ithome.com.tw/upload/images/20220925/20112934AhfZiMIAmM.png

把它 Describe 一下:

kubectl describe cm nginx-conf

https://ithelp.ithome.com.tw/upload/images/20220925/20112934TJbENS5KgZ.png

這樣顯示就代表設定檔有進去了。

# 1. Save as `configmap-pod.yaml`
# 2. In bash, `kubectl apply -f configmap-pod.yaml`
# 3. If you want to remove, `kubectl delete -f configmap-pod.yaml`
apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      command: [ "/bin/sh", "-c", "ls /etc/config/; cat /etc/config/nginx2.conf" ] # 列出 /etc/config 裡面的資料,並且把裡面的 nginx2.conf 內容印出來
      volumeMounts:
      - name: config-volume # mount 下面這個 config-volume
        mountPath: /etc/config # 路徑在 container 內的 /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: nginx-conf # 寫上前面建立的 ConfigMap 名稱
        items:
        - key: nginx.conf # 指定為 ConfigMap 裡面的某個 Key
          path: nginx2.conf # 映射進去後會變成 nginx2.conf
  restartPolicy: Never

那我們就來 apply 進去:

kubectl apply -f configmap-pod.yaml

最後把 Pod 的 log 結果印出來:

kubectl logs configmap-pod

https://ithelp.ithome.com.tw/upload/images/20220925/20112934WqJUkP3tBm.png

這個是把 ConfigMap 當作 Volume 去傳進 Pod 裡面,想要當作 env 參數可以去參考官方範例,這裡因為篇幅限制就讓各位知道概念。

記得把 nginx-conf ConfigMap 刪掉:

kubectl delete cm nginx-conf

Secret

Secret 都會放的是機密類的資料,只要有像是資料庫的初始產生密碼,或者公鑰私鑰,這些都不適合直接暴露在文件中都算機密類。

Secret 提供了 8 種儲存方式:

https://ithelp.ithome.com.tw/upload/images/20220925/20112934zbIz8EfcMQ.png

我實際上比較常使用的是 Opaquekubernetes.io/tls

除了上面有所說的特殊用途以外,通常都是使用 Opaque 的型態。

Opaque 是這樣建立出來:

kubectl create secret generic nginx-secret --from-file=./nginx.conf 

對,你有沒有發現,其實這跟 ConfigMap 差不多,差異是把 configmap 換成 secret generic 而已。

那我們來 describe 一下它的內容:

kubectl describe secret nginx-secret

https://ithelp.ithome.com.tw/upload/images/20220925/20112934NWUZY0P4RA.png

因為是 Secret,他不會直接顯示內容,但可以透過 Edit 方式去編輯,不過在這之前我先來介紹另一個使用情境 kubernetes.io/tls

kubernetes.io/tls 使用的方式如下:

kubectl create secret tls my-tls-secret \
  --cert=path/to/cert/file \
  --key=path/to/key/file
# 命名為 my-tls-secret
# cert 放公鑰的路徑
# key 放私鑰的路徑

需要注意的是 TLS Key 他只有吃兩個檔案,letsencrypt 的 certbot 會有四個檔案:

  1. cert.pem:本伺服器的公鑰
  2. chain.pem:中繼憑證
  3. fullchain.pem:中繼憑證 + 本伺服器的公鑰,也就是完整的驗證公鑰
  4. privkey.pem:本伺服器的私鑰

在這裡公鑰跟私鑰只需要擺上 fullchain.pemprivkey.pem 即可,公鑰如果擺上 cert.pem 會造成驗證一半的問題,瀏覽器可能會是好的,但 curl 可能結果會是驗證錯誤喔!

雖然看似 Secret 機密,但其實你只要嘗試編輯看看:

kubectl edit secret nginx-secret

https://ithelp.ithome.com.tw/upload/images/20220925/20112934qkqzolHV2O.png

如果對內容覺得很眼熟,你的直覺沒猜錯,它使用的是 Base64 編碼,並不是加密,只要有 K8s 的 etcd 權限也是可以看的到。

想要讓你的資料真的連 etcd 都看不到,也可以嘗試啟用靜態加密,連結我就給在這裡,有需要的可以啟用它去閱讀。

https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/

記得把 nginx-secret 刪除掉:

kubectl describe secret nginx-secret

下一篇我們就要來嘗試用這幾天所教的 K8s 來架設跟測試服務啦!

本系列內容也會同步貼到我的 Blog https://blog.yangjerry.tw 歡迎來我的 Blog 點一下 RSS 追蹤,那我們就下一篇文章見啦!

Source


上一篇
Day 09 Kubernetes - Namespace & Service
下一篇
Day 11 Kubernetes - 組建真正的服務吧(一)
系列文
關於我怎麼把一年內學到的新手 IT/SRE 濃縮到 30 天筆記這檔事30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言