Kubernetes技術分析之存儲

概述

Docker的流行激活了一直不溫不火的PaaS,隨着而來的是各類Micro-PaaS的出現,Kubernetes是其中最具代表性的一員,它是Google多年大規模容器管理技術的開源版本。本系列文章將逐一分析Kubernetes,本文詳細介紹如何使用Kubernetes支持的幾種Volume。

Kubernetes存儲

衆所周知,使用Docker的時候,容器中的數據是臨時,即當容器銷燬時,其中的數據時丟失。如果需要持久化數據,需要使用Docker Volume掛載宿主機上的文件目錄到容器中。Kubernetes中的Volume則是基於Docker進行擴展,支持更加豐富的功能,Kubernetes支持以下類型的Volume:

emptyDir

如果Pod配置了emptyDir類型Volume, Pod 被分配到Node上時候,會創建emptyDir,只要Pod運行在Node上,emptyDir都會存在(容器掛掉不會導致emptyDir丟失數據),但是如果Pod從Node上被刪除(Pod被刪除,或者Pod發生遷移),emptyDir也會被刪除,並且永久丟失。
現在創建一個Pod使用emptyDir, busybox-pod.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    name: busybox
spec:
  containers:
    - image: busybox
      command:
        - sleep
        - "3600"
      imagePullPolicy: IfNotPresent
      name: busybox
      volumeMounts:
        - mountPath: /busybox-data
          name: data
  volumes:
    - name: data
      emptyDir: {}

Pod運行後,docker inspect它的容器:

    "Volumes": {
        "/busybox-data": "/var/lib/kubelet/pods/da47d6b1-374c-11e5-ad0f-005056817c3e/volumes/kubernetes.io~empty-dir/data",
        "/dev/termination-log": "/var/lib/kubelet/pods/da47d6b1-374c-11e5-ad0f-005056817c3e/containers/busybox/4f4c540ea667e78fca68886d5b5700abb652523dc39d3ca36bb2573ea016be21"
    },
    "VolumesRW": {
        "/busybox-data": true,
        "/dev/termination-log": true
    },
    "VolumesRelabel": {
        "/busybox-data": "",
        "/dev/termination-log": ""
    }

可以看到容器掛載配置的emptyDir:

/var/lib/kubelet/pods/<id>/volumes/kubernetes.io~empty-dir/data =》 /busybox-data

hostPath

hostPath允許掛載Node上的文件系統到Pod裏面去。如果Pod有需要使用Node上的東西,可以使用hostPath,不過不過建議使用,因爲理論上Pod不應該感知Node的。
busybox-pod.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    name: busybox
spec:
  containers:
    - image: busybox
      command:
        - sleep
        - "3600"
      imagePullPolicy: IfNotPresent
      name: busybox
      volumeMounts:
        - mountPath: /busybox-data
          name: data
  volumes:
  - hostPath:
      path: /tmp/data
    name: data

docker inspect:

   "Volumes": {
        "/busybox-data": "/tmp/data",
        "/dev/termination-log": "/var/lib/kubelet/pods/522b7dd3-374f-11e5-ad0f-005056817c3e/containers/busybox/d6b5adcaf869ad290a3c4602313fc813451eabcc47d4583ee6dd4f6ba9fd8009"
    },
    "VolumesRW": {
        "/busybox-data": true,
        "/dev/termination-log": true
    },
    "VolumesRelabel": {
        "/busybox-data": "",
        "/dev/termination-log": ""
    }

emptyDir和hostPat很多場景是無法滿足持久化需求,因爲在Pod發生遷移的時候,數據都無法進行轉移的,這就需要分佈式文件系統的支持。

nfs

NFS 是Network File System的縮寫,即網絡文件系統。Kubernetes中通過簡單地配置就可以掛載NFS到Pod中,而NFS中的數據是可以永久保存的,同時NFS支持同時寫操作。
下面的例子將在Kubernetes上部署一個NFS服務端,然後部署一個Pod使用該NFS服務端
nfs-server-pod.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: nfs-server
  labels:
    role: nfs-server
spec:
  containers:
    - name: nfs-server
      image: jsafrane/nfs-data
      ports:
        - name: nfs
          containerPort: 2049
      securityContext:
        privileged: true

注意:運行nfs-server-pod需要kubelet開啓privileged

nfs-service.yaml:

kind: Service
apiVersion: v1
metadata:
  name: nfs-server
spec:
  clusterIP: 10.254.234.223
  ports:
    - port: 2049
  selector:
    role: nfs-server

創建完可以查看下NFS的配置:

$ kubectl exec nfs-server cat /etc/exports  
/mnt/data *(rw,sync,no_root_squash,insecure,fsid=0)

$ kubectl exec nfs-server cat /mnt/data/index.html
Hello world!

可以看到export了/mnt/data最爲/, 並且/mnt/data下有個index.html

NFS 服務端安裝完成後,需要在Kubernetes的每個Node安裝NF客戶端:

$ yum install nfs-utils

現在創建一個Pod使用NFS:

apiVersion: v1
kind: Pod
metadata:
  name: nfs-web
spec:
  containers:
    - name: web
      image: nginx 
      ports:
        - name: web
          containerPort: 80
      volumeMounts:
          # name must match the volume name below
          - name: nfs
            mountPath: "/usr/share/nginx/html"
  volumes:
    - name: nfs
      nfs:
        # FIXME: use the right hostname
        server: 10.254.234.223
        path: "/"

該Pod啓動一個nginx,然後掛載NFS Server的/到/usr/share/nginx/html, 即使用其中的index.html。

查看Pod的容器,可以看到容器掛載
/var/lib/kubelet/pods/<id>/volumes/kubernetes.io~nfs/nfs=> /usr/share/nginx/html

而實際上/var/lib/kubelet/pods//volumes/kubernetes.io~nfs/nfs掛載到NFS Server,效果如以下命令:

mount -t nfs 10.254.234.223:/ /var/lib/kubelet/pods/<id>/volumes/kubernetes.io~nfs/nfs

glusterfs

GlusterFS是一個開源的分佈式文件系統,具有強大的橫向擴展能力,通過擴展能夠支持數PB存儲容量和處理數千客戶端。同樣地,Kubernetes支持Pod掛載到GlusterFS,這樣數據將會永久保存。
首先需要一個GlusterFS環境,本文使用2臺機器(CentOS7)安裝GlusterFS服務端,在2臺機器的 /etc/hosts配置以下信息:

192.168.3.150    gfs1
192.168.3.151    gfs2

在2臺機器上安裝:

$ wget http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm
$ rpm -ivh epel-release-7-5.noarch.rpm
$ wget -P /etc/yum.repos.d http://download.gluster.org/pub/gluster/glusterfs/LATEST/EPEL.repo/glusterfs-epel.repo
$ yum install glusterfs-server
$ service glusterd start

注意: GlusterFS服務端需要關閉SELinux:修改/etc/sysconfig/selinux中SELINUX=disabled。然後清空iptables: iptables -F

安裝後查詢狀態:

$ service glusterd status

添加集羣:
在gfs1上操作:

$ gluster peer probe gfs2

在gfs2上操作:

$ gluster peer probe gfs1

創建volume :
在gfs1上操作:

$ mkdir /data/brick/gvol0
$ gluster volume create gvol0 replica 2 gfs1:/data/brick/gvol0 gfs2:/data/brick/gvol0
$ gluster volume start gvol0
$ gluster volume info

安裝成功的話可以掛載試驗下:

$ mount -t glusterfs gfs1:/gvol0 /mnt
GlusterFS服務端安裝成功後,需要在每個Node上安裝GlusterFS客戶端:
$ yum install glusterfs-client

接着創建GlusterFS Endpoint,gluasterfs-endpoints.json:

{
  "kind": "Endpoints",
  "apiVersion": "v1",
  "metadata": {
    "name": "glusterfs-cluster"
  },
  "subsets": [
    {
      "addresses": [
        {
          "IP": "192.168.3.150"
        }
      ],
      "ports": [
        {
          "port": 1
        }
      ]
    },
    {
      "addresses": [
        {
          "IP": "192.168.3.151"
        }
      ],
      "ports": [
        {
          "port": 1
        }
      ]
    }
  ]
}

最後創建一個Pod掛載GlusterFS Volume, busybox-pod.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    name: busybox
spec:
  containers:
    - image: busybox
      command:
        - sleep
        - "3600"
      imagePullPolicy: IfNotPresent
      name: busybox
      volumeMounts:
        - mountPath: /busybox-data
          name: data
  volumes:
  - glusterfs:
      endpoints: glusterfs-cluster
      path: gvol0
    name: data

查看Pod的容器,可以看到容器掛載

/var/lib/kubelet/pods/<id>/volumes/kubernetes.io~glusterfs/data => /busybox-data

在kubernetes.io~glusterfs/data目錄下執行查詢:

$ mount | grep gvol0
192.168.3.150:gvol0 on /var/lib/kubelet/pods/<id>/volumes/kubernetes.io~glusterfs/data type fuse.glusterfs (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other,max_read=131072)

參考

作者簡介

吳龍輝,現任網宿科技高級運營工程師,致力於雲計算PaaS的研究和實踐,活躍於CloudFoundry,Docker,Kubernetes等開源社區,貢獻代碼和撰寫技術文檔。
郵箱:[email protected]/[email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章