KubernetesでのVolumeの扱い

このエントリはKubernetesアドベントカレンダー2014の10日目です。

今日はクラウドの(というか情報システムの)鬼門、データストレージについてです。

Volume

4日目で紹介したとおり、dockerではデータをコンテナの管理外に出す、ホストのディレクトリをマウントする、という2つの方法でデータを外出しできます。コンテナ管理外に出したデータは他コンテナからもマウントできますが、コンテナの削除と共に消えます。

KubernetesではVolumeの種類は今のところ以下の3種類です。

  • EmptyDir : docker run するときに -v DIR した時と似た挙動をします
  • HostDir : docker run するときに -v HOSTDIR:DIR した時と同じ挙動をします
  • GCEPersistentDisk : GCE外部ディスクです。AWSで言うところのEBSですね

似た というのが気になりますね。 詳しく見てみましょう。

動作させてみる

Kubernetesでは container manifestPodServiceReplicationController を定義します。 syntaxなどは以下が参考になります。

Container-optimized Google Compute Engine images - Google Compute Engine — Google Cloud Platform

今回はnginxのコンテナを作って動作を見てみます。 このファイルを /root/volumetest.yaml として保存しておき、 kubectl に読み込ませて Pod を作成します。

apiVersion: v1beta1
kind: Pod
id: mynginx
desiredState:
  manifest:
    version: v1beta1
    id: mynginx
    containers:
      - name: nginx
        image: dockerfile/nginx
        cpu: 100
        memory: 50000000
        ports:
            - containerPort: 80
              hostPort: 8000
        volumeMounts:
          - name: tmp
            mountPath: /tmp
          - name: docroot 
            mountPath: /usr/share/nginx/html
            readOnly: true
    volumes:
      - name: tmp
        source:
          emptyDir: {}
      - name: docroot
        source:
          hostDir:
            path: /opt/kubernetes/examples/guestbook/php-redis

kubectlPod を作成します。

[root@localhost kubernetes]# cluster/kubectl.sh create pod -f /root/volumetest.yaml
mynginx
[root@localhost kubernetes]# cluster/kubectl.sh get pods
NAME                IMAGE(S)            HOST                LABELS              STATUS
mynginx             dockerfile/nginx    127.0.0.1/                              Running

起動できたら中をのぞいてみましょう。 とこんな感じになっています。

[root@localhost kubernetes]# docker ps
CONTAINER ID        IMAGE                     COMMAND             CREATED             STATUS              PORTS                  NAMES
3c06d3a4716e        dockerfile/nginx:latest   "nginx"             6 seconds ago       Up 5 seconds                               k8s_nginx.e3acd9a9_mynginx.default.etcd_e8c242d0-7d57-11e4-9f54-080027ba52c4_7d382584
1ef629d75e17        kubernetes/pause:latest   "/pause"            7 seconds ago       Up 6 seconds        0.0.0.0:8000->80/tcp   k8s_net.163f8d3c_mynginx.default.etcd_e8c242d0-7d57-11e4-9f54-080027ba52c4_5b914090
[root@localhost kubernetes]# docker inspect 3c06d3a4716e | jq '.[].Volumes'
{
  "/var/log/nginx": "/var/lib/docker/vfs/dir/4ae5ca2d3794dc0112417f53caa11352d918b641b0a6916eae65853fd2e09a56",
  "/usr/share/nginx/html": "/opt/kubernetes/examples/guestbook/php-redis",
  "/tmp": "/var/lib/kubelet/mynginx/volumes/empty/tmp",
  "/etc/nginx/sites-enabled": "/var/lib/docker/vfs/dir/2d688a570e7fdfa22df96bdb314b6efcf9a3b79558c6a37d656d867975dd1693",
  "/etc/nginx/conf.d": "/var/lib/docker/vfs/dir/4dcdb706eae6632a45552294ae1236023d7175cc85eb06f7c9c7d9472a3ae49e",
  "/etc/nginx/certs": "/var/lib/docker/vfs/dir/f1479991bfce4f14600da51d254571922818cbd0a2c30a45a2aba3d04451f9b9",
  "/dev/termination-log": "/var/lib/kubelet/mynginx/nginx/3c06d3a4716ee7465c3d0afa19072c73c7cc45de571a68fc92e286e195cae05b"
}
  1. dockerfileで指定されたVolumeはdocker本来の領域(/var/lib/docker/vfs...)に
  2. Kubernetesで指定したVolume(emptyDir)はkubelet配下(default: /var/lib/kubelet)に
  3. Kubernetesで指定したMountVolume(hostDir)は指定したディレクトリに

マッピングされています。

1,と2の違いとしては、dockerfileで指定した領域(1)のライフサイクルはコンテナと同一ですが、 Kubernetesで指定したVolumeはライフサイクルがPodになります。 そのためコンテナを不意に停止して別のコンテナが穴埋めで起動した場合に、データを引き継ぐことができます。 似た挙動、というのはこのライフサイクルの違いになります。

現状の実装はホストマシンべったりですが、 GCEPersistentDisk もあることですし、 EBSのような展開は期待できますね。 他にもGlusterFSなどを組み合わせることもできそうですし、いい感じになっていくのではないでしょうか!?


See also