Kubernetes サイドカーの作り方とファイル共有


ポッドの中で二つのコンテナが動作して、ストレージを共有しながら動作するポッドを指して、サイドカー(Sidecar) と呼ぶ様です。 
この様なサイドカーの主な用途として、ログを転送する目的や、ウェブ・アプリのコンテンツを共有する目的があります。この様な目的の場合、外部の永続ディスクを利用するとディスクアクセスのためのiSCSIがボトルネックとなる恐れがあります。 一方、ポッドを収容するノードの仮想サーバーのストレージはSSDが使われている（IBM Cloudのケース)ため、永続ストレージを利用せず、ノードのストレージを利用する事が得策と思います。



### 比較の図

![スクリーンショット 2018-02-07 1.29.25.png](https://qiita-image-store.s3.amazonaws.com/0/42829/6b361113-2aeb-3a11-e4ab-91bef07bf262.png "スクリーンショット 2018-02-07 1.29.25.png")


### IBM Cloud のワーカーノードは Local Disk(SSD)が利用される


![スクリーンショット 2018-02-07 1.32.57.png](https://qiita-image-store.s3.amazonaws.com/0/42829/6b905d01-054d-6bc3-958e-74758e732d71.png "スクリーンショット 2018-02-07 1.32.57.png")


そこで、サイドカーを構成する方法について、そして、特徴について確認しました。


## サイドカー構成のポッド作成

一つのポッドに２つのコンテナを設定するYAMLで、ストレージの持ち方が、それぞれ異なっています。前者はノードのストレージのパスを指定する方法、後者は専用に確保する方法です。

### ノードのストレージをパス指定で利用

ノードのディスクのパスを指定してマウントします。
次の様に、hostPathを設定します。　ノードのパスを指定しているので、同一ノードにポッドのレプリカが存在する場合、それらともストレージが共有されます。

~~~yaml
  volumes:
  - name: host-volume
    hostPath:
      path: /www
      type: DirectoryOrCreate
~~~

コンテナで、それぞれ volumeMounts を指定します。 ここでは、ログインした時に判別できる様に、意図的にマウント先を変えてあります。 tc-1 は /var/www1、 tc-2 は /var/www2 としています。

~~~t080_host_vol.yml
apiVersion: v1
kind: Pod
metadata:
  name: test-pod-1
spec:
  containers:
  - image: ubuntu:latest
    name: tc-1
    volumeMounts:
    - mountPath: /var/www1
      name: host-volume
    command: ["tail",  "-f", "/dev/null"]    
  - image: ubuntu:latest
    name: tc-2
    volumeMounts:
    - mountPath: /var/www2
      name: host-volume
    command: ["tail",  "-f", "/dev/null"]    
  volumes:
  - name: host-volume
    hostPath:
      path: /www
      type: DirectoryOrCreate
~~~


### 専用の一時的なディレクトリを利用する方法

こちらは、emptyDirを利用して、ポッド専用のディレクトを利用します。　前述の様なノードで共有にはなりません。

~~~yaml
  volumes:
  - name: cache-volume
    emptyDir: {}
~~~

１ポッドに２つのコンテナを動作させるYAMLファイルの全体です。

~~~t081_host_vol.yml
apiVersion: v1
kind: Pod
metadata:
  name: test-pod-2
spec:
  containers:
  - image: ubuntu:latest
    name: tc-1
    volumeMounts:
    - mountPath: /var/www1
      name: cache-volume
    command: ["tail",  "-f", "/dev/null"]    
  - image: ubuntu:latest
    name: tc-2
    volumeMounts:
    - mountPath: /var/www2
      name: cache-volume
    command: ["tail",  "-f", "/dev/null"]    
  volumes:
  - name: cache-volume
    emptyDir: {}
~~~


## ポッド内のコンテナを指定してコマンドを実行する方法

ポッド内のコンテナを指定してログインするには、`-c` オプションで、コンテナ名を指定します。
二つのポッドは、同じIPアドレスを共有して、ホスト名も同じになります。　しかし、プロセス空間は異なります。

### コンテナを指定してログインする例

~~~
$ kubectl exec -c tc-1 -it test-pod-1 bash
root@test-pod-1:/# df -h
Filesystem               Size  Used Avail Use% Mounted on
overlay                   99G  6.7G   87G   8% /
tmpfs                    2.0G     0  2.0G   0% /dev
tmpfs                    2.0G     0  2.0G   0% /sys/fs/cgroup
/dev/xvda2                24G  4.7G   20G  20% /var/www1
/dev/mapper/docker_data   99G  6.7G   87G   8% /etc/hostname
shm                       64M     0   64M   0% /dev/shm
tmpfs                    2.0G   12K  2.0G   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs                    2.0G     0  2.0G   0% /sys/firmware
~~~

~~~
$ kubectl exec -c tc-2 -it test-pod-1 bash
root@test-pod-1:/# df -h
Filesystem               Size  Used Avail Use% Mounted on
overlay                   99G  6.7G   87G   8% /
tmpfs                    2.0G     0  2.0G   0% /dev
tmpfs                    2.0G     0  2.0G   0% /sys/fs/cgroup
/dev/xvda2                24G  4.7G   20G  20% /var/www2
/dev/mapper/docker_data   99G  6.7G   87G   8% /etc/hostname
shm                       64M     0   64M   0% /dev/shm
tmpfs                    2.0G   12K  2.0G   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs                    2.0G     0  2.0G   0% /sys/firmware
~~~


### プロセス空間が独立していることを確認
プロセス番号が異なっていることに注目してください。

~~~
$ kubectl exec -c tc-1 -it test-pod-1 bash
root@test-pod-1:/# ps -ax
  PID TTY      STAT   TIME COMMAND
    1 ?        Ss     0:00 tail -f /dev/null
   62 pts/0    Ss     0:00 bash
   71 pts/0    R+     0:00 ps -ax
root@test-pod-1:/# exit

$ kubectl exec -c tc-2 -it test-pod-1 bash
root@test-pod-1:/# ps -ax
  PID TTY      STAT   TIME COMMAND
    1 ?        Ss     0:00 tail -f /dev/null
   56 pts/0    Ss     0:00 bash
   65 pts/0    R+     0:00 ps -ax
~~~   


### ホスト名とIPが同じことを確認
プロセス空間は異なるのですが、ホスト名とIPアドレスは、ポッド内のコンテナで同じです。 これは２つで一つとして利用されることを前提にしていると言っても良いでしょう。

~~~
$ kubectl exec -c tc-1 -it test-pod-1 bash
root@test-pod-1:/# hostname
test-pod-1
root@test-pod-1:/# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1
    link/ipip 0.0.0.0 brd 0.0.0.0
4: eth0@if55779: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1480 qdisc noqueue state UP group default 
    link/ether b2:32:c0:5c:d7:cc brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.30.170.194/32 scope global eth0
       valid_lft forever preferred_lft forever
root@test-pod-1:/# exit

$ kubectl exec -c tc-2 -it test-pod-1 bash
root@test-pod-1:/# hostname
test-pod-1
root@test-pod-1:/# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1
    link/ipip 0.0.0.0 brd 0.0.0.0
4: eth0@if55779: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1480 qdisc noqueue state UP group default 
    link/ether b2:32:c0:5c:d7:cc brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.30.170.194/32 scope global eth0
       valid_lft forever preferred_lft forever
~~~

## 参考資料

* emptyDir Volumes https://kubernetes.io/docs/concepts/storage/volumes/#emptydir
* hostPath https://kubernetes.io/docs/concepts/storage/volumes/#hostpath
* Configure a Pod to Use a Volume for Storage https://kubernetes.io/docs/tasks/configure-pod-container/configure-volume-storage/