k8s pod掛載hostPath執行寫時報錯Permission denied


關於hostPath的權限說明

最近項目中經常遇到pod中container掛載主機hostPath報錯無權限問題:

httpd@hostpath-volume:/test-volume$ touch  123
touch: cannot touch '123': Permission denied

於是又復習了一遍hostPath使用方法,發現沒有什么新知識的涌入:

行為
空字符串(默認)用於向后兼容,這意味着在掛載hostPath卷之前不會進行任何檢查
DirectoryOrCreate 如果給定的路徑沒有任何東西存在,那將根據需要在此創建一個空目錄,權限設置為0755,與kubelet擁有相同的用戶與組
Directory 指定路徑下必須存在此目錄
FileOrCreate 如果給定的路徑沒有任何東西存在,那將根據需要在此創建一個空文件,權限設置為0644,與kubelet擁有相同的用戶與組
File 給定的路徑下必須存在文件
Socket 給定的路徑下必須存在Unix套接字
CharDevice 給定的路徑下必須存在字符設備
BlockDevice 給定的路徑下必須存在塊設備

使用這種卷類型時請注意:

  • 由於每個節點上的文件不同,具有相同配置(例如從 podTemplate創建的)的pod在不同節點上的行為可能會有所不同
  • 當Kubernetes按照計划添加資源感知調度時,將無法考慮hostPath使用的資源
  • 在底層主機上創建的文件或目錄只能由root寫入。必須在特權容器中以root身份運行進程,或修改主機上文件權限以便寫入 hostPath 卷

注意幾個話術

  1. 當值為DirectoryOrCreate和FileOrCreate時,並且給定的路徑或文件不存在時,kubelet會自動創建,並且會和kubelet擁有相同的用戶與組,說白了,就是你用什么用戶起的kubelet創建出來的就是此用戶的屬主數組。
  2. 必須在特權容器中以root身份運行進程,或修改主機上文件權限以便寫入 hostPath 卷。如果你的容器不是以root用戶運行的,這一點可要注意了。

問題的根源

查看發現,容器掛載hostPath寫入時報錯Permission denied時基本都是容器運行用戶不是root的情況下,這就說明,啟動容器的用戶沒有權限在宿主機中屬主屬組為root的目錄或者文件中寫入。

這就很清晰明了,只要賦予運行容器的用戶寫權限,這個問題就解決了。

可是,我們應該賦予哪個用戶呢?在宿主機創建一個與啟動容器相同的用戶然后賦予權限嗎?顯然不行。

那么容器用戶與宿主機用戶的對應關系是什么呢?沒錯,是uid。

只要將宿主機的用戶與啟動容器用戶的uid相對應上,並且給它寫的權限,那這個問題就迎刃而解了。

做幾個測試

  1. 先創建一個普通用戶起的container

    apiVersion: v1
    kind: Pod
    metadata:
      name: hostpath-volume
      namespace: default
    spec:
      containers:
      - name: hostpath-container
        image: nginx-test:v1
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath: /test-volume
          name: dir-volume
      volumes:
      - name: dir-volume
        hostPath:
          path: /data/vfan/test/
          type: DirectoryOrCreate
    
  2. 創建這個pod,測試寫入

    ## 
    kubectl create -f hostpath-test.yaml 
    
    ##
    httpd@hostpath-volume:/$ cd /test-volume/
    httpd@hostpath-volume:/test-volume$ touch 11 22 33
    touch: cannot touch '11': Permission denied
    touch: cannot touch '22': Permission denied
    touch: cannot touch '33': Permission denied
    
  3. 查看宿主機相對應目錄的權限

    # ll -dh /data/vfan/test/
    drwxr-xr-x 2 root root 4.0K Mar 21 14:53 /data/vfan/test/
    
  4. 查看容器內用戶的uid,並查看宿主機的此uid用戶是誰

    ## 容器內
    httpd@hostpath-volume:/test-volume$ id
    uid=1000(httpd) gid=1000(httpd) groups=1000(httpd)
    
    ## 容器外
    # grep 1000 /etc/passwd
    work:x:1000:1000::/home/work:/bin/bash
    

    如果沒有相同uid的用戶,則創建一個對應用戶即可:useradd -u 1000 xxx

  5. 賦予宿主機對應uid用戶權限,再次測試

    ## 宿主機
    chown work:work test/
    
    ## 容器內
    httpd@hostpath-volume:/test-volume$ touch 11 22 33
    httpd@hostpath-volume:/test-volume$ ls
    11  22	33
    
  6. 容器內外權限分別是什么?

    ## 容器內
    httpd@hostpath-volume:/test-volume$ ls -ld /test-volume/
    drwxr-xr-x 2 httpd httpd 4096 Mar 21 07:27 /test-volume/
    
    ## 容器外
    [root@gzbh-intel002.gom vfan]# ll -dh /data/vfan/test/
    drwxr-xr-x 2 work work 4.0K Mar 21 15:27 /data/vfan/test/
    


免責聲明!

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



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