Kubernetes-存儲(一)


前言

本篇是Kubernetes第十二篇,大家一定要把環境搭建起來,看是解決不了問題的,必須實戰。

Kubernetes系列文章:
  1. Kubernetes介紹
  2. Kubernetes環境搭建
  3. Kubernetes-kubectl介紹
  4. Kubernetes-Pod介紹(-)
  5. Kubernetes-Pod介紹(二)-生命周期
  6. Kubernetes-Pod介紹(三)-Pod調度
  7. Kubernetes-Pod介紹(四)-Deployment
  8. Kubernetes-Service介紹(一)-基本概念
  9. Kubernetes-Service介紹(二)-服務發現
  10. Kubernetes-Service介紹(三)-Ingress(含最新版安裝踩坑實踐)
  11. Kubernetes-網絡

為什么需要存儲

對於這個問題其實很簡單,容器中持久化的文件生命周期是短暫的,如果容器中程序崩潰宕機,kubelet 就會重新啟動,容器中的文件將會丟失,所以對於有狀態的應用容器中持久化存儲是至關重要的一個環節;另外很多時候一個 Pod 中可能包含多個 Docker 鏡像,在 Pod 內數據也需要相互共享,Kubernetes 中 Pod 也可以增加副本數量,遇到故障時 Pod 可以轉移到其它節點,為了浮動節點都能夠訪問統一的持久化存儲以及容器間共享數據,Kubernetes 中定義了 Volume 來解決這些問題 ,從本質上講,Volume 只是一個目錄,可能包含一些數據,Pod 中的容器可以訪問它。該目錄是何種形式,是由所使用的 Volume 類型決定的。

Volume介紹

Kubernetes 支持很多 Volume類型,可以分為以下類型:

img
img

我們重點介紹下資源對象映射為存儲卷、Node本地存儲卷和持久卷。

資源對象映射為存儲卷

在 Kubernetes中ConfigMap、Serect、DownwardAPI和ServiceAccountToken四種存儲卷,存在的意義不是為了存放容器里的數據,也不是用來進行容器和宿主機之間的數據交換,是為容器提供預先定義好的數據。從容器的角度來看,這些 Volume里的信息就是被映射到容器當中的。

ConfigMap

ConfigMap用於保存應用程序的配置信息,可以通過Volume的形式掛載到容器內部文件系統中,供容器內的應用程序讀取。

使用
  1. 創建configMap文件;
apiVersion: v1
kind: ConfigMap
metadata:
  name: env-config
data:
  env-key: test
  1. 創建Pod文件,在Pod使用configMap配置信息;
apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
  - name: configmap-pod
    image: busybox:1.28.3
    command: [ "/bin/sh", "-c", "env" ]
    env:
     - name: ENV
       valueFrom:
         configMapKeyRef:
           name: env-config
           key: env-key 
  restartPolicy: Never
  1. 啟動configMap和Pod;
kubectl apply -f env-configMap.yaml
kubectl apply -f configmap-pod.yaml
  1. 查看啟動日志;
kubectl logs configmap-pod
image.png
image.png

Secret

Secret功能與ConfigMap類似,它與ConfigMap的區別在於,Secret保存的是需要加密的、應用所需的配置信息。Secret與ConfigMap用法完全相同:你可以使用 kubectl create secret從文件或者目錄創建 Secret,也可以直接編寫Secret對象的YAML文件。

Downward API

Downward API的作用是讓Pod里的容器能夠直接獲取到這個Pod API對象本身的元數據信息。

使用
  1. 創建Pod,該Pod聲明了一個projected類型的Volume,Volume的數據來源為Downward API,而這個 Downward API Volume,要暴露Pod的metadata.labels 信息給容器,容器啟動以后,則是不斷打印出 /etc/podinfo/labels 里的內容;
apiVersion: v1
kind: Pod
metadata:
  name: downwardapi-demo-pod
  labels:
    cluster: demo-test
spec:
  containers:
    - name: downwardapi-demo
      image: busybox:1.28.3
      command: ["sh", "-c"]
      args:
      - while true; do
          if [[ -e /etc/podinfo/labels ]]; then
            echo -en '\n\n'; cat /etc/podinfo/labels; fi;
          sleep 5;
        done;
      volumeMounts:
        - name: podinfo
          mountPath: /etc/podinfo
          readOnly: false
  volumes:
    - name: podinfo
      projected:
        sources:
        - downwardAPI:
            items:
              - path: "labels"
                fieldRef:
                  fieldPath: metadata.labels
  1. 啟動Pod和查看日志;
kubectl apply -f downwardapi-demo-pod.yaml
kubectl logs downwardapi-demo-pod
image.png
image.png

Service Account Token

Service Account Token是一種針對Pod的賬號,它是Kubernetes進行權限分配的對象。比如Service Account A,可以只被允許對 Kubernetes API 進行 GET 操作,而 Service Account B,則可以有 Kubernetes API 的所有操作權限。Service Account的授權信息和文件,實際上保存在它所綁定的一個特殊的 Secret 對象里的,對於Service Account Token可以理解為一種特殊的Secret對象。

Kubernetes對所有的Pod都提供了一個default Service Account,任何一個運行在 Kubernetes的Pod,都可以直接使用這個默認的 Service Account,而無需顯示地聲明掛載它。

原理探索

實現方式還是靠Projected Volume機制

  1. 查看該Pod的詳細信息,可以看到該Po的默認掛載一個serviceaccount的路徑;
kubectl describe pod downwardapi-demo-pod
image.png
image.png
  1. 我們進入容器內部查看下serviceaccount具體內容,我們可以看到包括3方面內容,分別是token、ca.crt、namespace;
#進入容器
kubectl exec -it downwardapi-demo-pod -- /bin/sh
#查看具體內容
ls /var/run/secrets/kubernetes.io/serviceaccount
image.png
image.png
  1. 接下來我們看下系統中的Service Account對象,可以看到有一個default-token-q4qts的Secret對象,該對象是一個Mountable secrets對象,說明此對象需要被掛載的;
image.png
image.png
  1. 接下來我們看下default-token-q4qts包含什么東西,我們可以看到包含了token、ca.crt、namespace三類對象;
image.png
image.png

通過Mountable secrets標識、Pod內容對象以及Secrets包含的對象,我們可以證明每個命名空間下面都會有一個名為default默認的Service Account,在Pod啟動的時候,Secret對象會自動掛載到Pod指定的目錄下,幫助Pod來完成API Server的身份鑒權。

使用
  1. 創建Service Account資源;
#創建Service Account資源
kubectl create serviceaccount sa-demo
#查看Service Account資源
kubectl get sa
image.png
image.png
  1. 查看下是否創建Secret;
#查看是否創建Secret
kubectl describe sa sa-demo、
#查看具體的Secret內容
kubectl describe secret sa-demo-token-k4t96
image.png
image.png
  1. 創建使用sa-demo的Pod;
apiVersion: v1
kind: Pod
metadata:
  name: sa-demo-pod
spec:  
  serviceAccountName: sa-demo
  containers:
  - image: nginx          
    name: sa-demo-pod               
    resources:                      
      limits:
        cpu: 100m
        memory: 200Mi
      requests:
        cpu: 100m
        memory: 200Mi
  1. 啟動該Pod;
#創建pod資源
kubectl create -f sa-demo-pod.yaml
#查看Pod資源
kubectl get pods
#查看pod是否掛載serviceaccount
kubectl describe pod sa-demo-pod
image.png
image.png
image.png
image.png
  1. 進入容器內部訪問kubernetes服務的API,在Kubernetes集群中,默認為API Server創建了一個名為kubernetes的Service,通過這個Service可以訪問API Server,使用curl命令直接訪問會得到如下返回信息,表示並沒有權限;
#查看服務列表
kubectl get svc
#進入容器內部
kubectl exec -it sa-demo-pod -- /bin/sh
#訪問kubernetes服務
curl https://kubernetes
image.png
image.png
image.png
image.png
  1. 使用ca.crt和Token做認證,先將ca.crt放到CURL_CA_BUNDLE這個環境變量中,curl命令使用CURL_CA_BUNDLE指定證書;再將Token的內容放到TOKEN中,然后帶上TOKEN訪問API Server;
#聲明變量
export CURL_CA_BUNDLE=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
#攜帶token訪問服務
curl -H "Authorization: Bearer $TOKEN" https://kubernetes
image.png
image.png

Node本地存儲卷

Kubernetes管理Node本地存儲卷有是那種類型:

  1. EmptyDir: 與Pod同生命周期,Node臨時存儲;

  2. HostPath: Node目錄;

  3. Local: 基於持久卷PV管理的Node目錄;

EmptyDir

當Pod被調度到某個節點上時,在Node上創建的是一個emptyDir卷,此卷剛開始是一個空目錄,並且只要 Pod在該節點上運行,卷就一直存在,與Pod生命周期相同, 當Pod被銷毀的時候,Node上的目錄也會被銷毀。同一個Pod的多個容器都可以掛載到改卷上。

emptyDir可以在以下幾種場景下使用:

  1. 臨時空間,例如基於磁盤的合並排序;

  2. 設置檢查點以從崩潰事件中恢復未執行完畢的長計算;

  3. 保存內容管理器容器從Web服務器容器提供數據時所獲取的文件;

使用
  1. 創建一個使用emptyDir volume的Pod;
apiVersion: v1
kind: Pod
metadata:
  name: emptydir-pod
spec:
  containers:
  - image: busybox:1.28.3
    name: emptydir-pod
    command: [ "sleep", "3600" ]
    volumeMounts:
    - mountPath: /data
      name: data-volume
  volumes:
  - name: data-volume
    emptyDir: {}
  1. 創建完成之后我們通過describe命令查看該Pod的詳情,我們可以看到上面創建的Pod Volumes 類型是:EmptyDir;
kubectl describe pod emptydir-pod
image.png
image.png
  1. 進入容器中查看掛載情況;
kubectl exec -it emptydir-pod /bin/sh
image.png
image.png

HostPath

hostPath類型則是映射Node節點文件系統中的文件或者目錄到Pod里。在使用hostPath類型的存儲卷時,也可以設置type字段,支持的類型有文件、目錄、File、Socket、CharDevice和BlockDevice。

hostPath可以在以下幾種場景使用:

  1. 容器應用中關鍵的數據需要持久化到宿主機上;

  2. 需要使用運行一個訪問 Docker內部數據Pod, 可以將主機的/var/lib/docker目錄掛載到容器內;

  3. 監控系統,例如在容器中運行cAdvisor需要以hostPath方式掛載/sys;

  4. Pod啟動需要依賴宿主機某個目錄或者文件信息;

使用
  1. 創建一個使用hostPath volume的Pod;
apiVersion: v1
kind: Pod
metadata:
  name: hostpath-pod
spec:
  containers:
  - image: busybox:1.28.3
    name: hostpath-pod
    command: [ "sleep", "3600" ]
    volumeMounts:
    - mountPath: /test-data
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # directory location on host
      path: /data
      # this field is optional
      type: Directory
  1. 創建完成之后我們通過describe命令查看該Pod的詳情,我們可以看到上面創建的Pod Volumes 類型是:HostPath,如果發現有個hostPath type check failed: /data is not a directory的告警,你需要在每個節點創建/data目錄;
kubectl describe pod hostpath-pod
image.png
image.png
image.png
image.png
  1. 接下來我們進入容器,在容器中創建文件;
#進入容器
kubectl exec -it hostpath-pod /bin/sh
#編輯文件
vi 123.txt
#輸出文件
cat 123.txt
image.png
image.png
  1. 查看Pod被調度到那個節點;
kubectl get pods -o wide
image.png
image.png
  1. 進入demo-slave-2查看/data目錄下是否增加文件;
image.png
image.png
  1. 銷毀hostpath-pod,檢查文件是否存在,我們會發現Pod已經被刪除了,volume卷中的數據仍然還在;
kubectl delete -f hostpath-pod.yaml
image.png
image.png

emptyDir和hostPath都可以實現本地存儲卷的功能、但是二者在功能上還是有異同的:

  1. 二者都是node節點的本地存儲卷方式;

  2. emptyDir可以選擇把數據存到tmpfs類型的本地文件系統中去,hostPath並不支持這一點;

  3. hostPath除了支持掛載目錄外,還支持File、Socket、CharDevice和BlockDevice,既支持把已有的文件和目錄掛載到容器中,也提供了“如果文件或目錄不存在,就創建一個”的功能;

  4. emptyDir是臨時存儲空間,完全不提供持久化支持;

  5. hostPath的卷數據是持久化在Node節點的文件系統中的,即便pod已經被刪除了,volume卷中的數據還會留存在Node節點上;

結束

歡迎大家點點關注,點點贊!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM