コンテナ型仮想化技術 Study05 / Pod操作

#はじめに

マニフェスト(YAML形式)を使用したKubernetesオブジェクトの管理をやってみます。ここでは主にPod関連の操作を見てみます。
※マニフェストファイルはJSONでも書けるようですが、YAMLの方が一般的っぽい。

##関連記事
[コンテナ型仮想化技術 Study01 / Docker基礎](https://qiita.com/tomotagwork/items/34b4505b90b71dcfa8ca)
[コンテナ型仮想化技術 Study02 / Docker レジストリ](https://qiita.com/tomotagwork/items/bb1df5232dec5ea7adb7)
[コンテナ型仮想化技術 Study03 / Docker Compose](https://qiita.com/tomotagwork/items/af802c3e25f594cb4a8a)
[コンテナ型仮想化技術 Study04 / Minikube & kubectl簡易操作](https://qiita.com/tomotagwork/items/79527a132d343ab8d534)
[コンテナ型仮想化技術 Study05 / Pod操作](https://qiita.com/tomotagwork/items/7b16bde0529c052a9540)
[コンテナ型仮想化技術 Study06 / ReplicaSet, Deployment, Service](https://qiita.com/tomotagwork/items/2eb36f84c7f396f51e56)
[コンテナ型仮想化技術 Study06' / Kubernetesネットワーク問題判別](https://qiita.com/tomotagwork/items/f1145f3f5656a5cd51c3)
[コンテナ型仮想化技術 Study07 / ストレージ](https://qiita.com/tomotagwork/items/eacf8629bd4889f80672)
[コンテナ型仮想化技術 Study08 / Statefulset, Ingress](https://qiita.com/tomotagwork/items/3a5589031854c702fcec)
[コンテナ型仮想化技術 Study09 / Helm](https://qiita.com/tomotagwork/items/f46a26e3437c716881dc)


#参考情報
[API Reference](https://kubernetes.io/docs/reference/#api-reference)
[DockerとKubernetesのPodのネットワーキングについてまとめました](https://foobaron.hatenablog.com/entry/k8s-pod-networking)

#復習 / Podとコンテナの関係

[Podについての概観(Pod Overview)](https://kubernetes.io/ja/docs/concepts/workloads/pods/pod-overview/)

>単一のコンテナを稼働させるPod : いわゆる「1Pod1コンテナ」 構成のモデルは、最も一般的なKubernetesのユースケースです。
このケースでは、ユーザーはPodを単一のコンテナのラッパーとして考えることができ、Kubernetesはコンテナを直接扱うというよりは、Podを管理することになります。

同一Pod内に複数コンテナを含めるパターンについて
[The Distributed System ToolKit: Patterns for Composite Containers](https://kubernetes.io/blog/2015/06/the-distributed-system-toolkit-patterns/)

#操作例

## Pod操作

nginxのコンテナを稼働させるだけの単純なPodを管理するマニフェストを作成

```yaml:nginx-pod.yml
apiVersion: v1
kind: Pod
metadata:
 name: nginx
spec:
 containers:
 - name: nginx
   image: nginx:latest
```

上のファイルを適用

```
vagrant@minikube:~/step07$ kubectl apply -f nginx-pod.yml
pod/nginx created

vagrant@minikube:~/step07$ kubectl get all
NAME              READY   STATUS      RESTARTS   AGE
pod/hello-world   0/1     Completed   0          6h22m
pod/nginx         1/1     Running     0          11s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   23h
```

Podが作成されて、実行されました。

以下のコマンドを見ると、nginxポッドが稼働しているノードとIPアドレスが分かります。

※Kubernetesでは、IPアドレスはPod単位に割り当てられるようで、同一Pod内のコンテナーの各サービスは、localhostの各ポート番号でアクセスできるようです。すなわち、同一Pod内のコンテナーはポートがバッティングしないように管理しなければなりません。Kubernetes環境だと、Podが1つの仮想マシンのような扱いになる感じですね。

参考: [Cluster Networking](https://kubernetes.io/docs/concepts/cluster-administration/networking/)

>Kubernetes IP addresses exist at the Pod scope - containers within a Pod share their network namespaces - including their IP address. This means that containers within a Pod can all reach each other’s ports on localhost. This also means that containers within a Pod must coordinate port usage, but this is no different from processes in a VM. This is called the “IP-per-pod” model.

```
vagrant@minikube:~/step07$ kubectl get  pod nginx -o wide
NAME    READY   STATUS    RESTARTS   AGE     IP           NODE       NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          3m47s   172.17.0.9   minikube   <none>           <none>
```

ただ、このIPアドレスはクラスターネットワーク上で閉じているらしく、このままだとホストOSや外部からアクセスできません。外からアクセスさせるためには、別途Kubernetesの"サービス"というオブジェクトを使用する必要があります。
ここでは、busyboxという各種コマンドを備えた軽量なコンテナを踏み台にして確認してみます。

busybox用のPodを起動してshで接続

```
vagrant@minikube:~/step07$ kubectl run busybox --image=busybox --restart=Never --rm -it sh
If you don't see a command prompt, try pressing enter.
/ #     
```

この時点で別シェルからPodの状況を確認してみます。

```
vagrant@minikube:~$ kubectl get pods -o wide
NAME          READY   STATUS      RESTARTS   AGE     IP            NODE       NOMINATED NODE   READINESS GATES
busybox       1/1     Running     0          27s     172.17.0.10   minikube   <none>           <none>
<略>
nginx         1/1     Running     0          67m     172.17.0.9    minikube   <none>           <none>
```

busyboxのシェルから、nginxにアクセスしてみます。

```
/ # wget -q -O - http://172.17.0.9/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
```

## Podのヘルスチェック機能

- **Liveness Probe**: サービスが稼働しているかどうかをチェックするためのもの。これがエラーになった場合、ポッド上のコンテナを強制終了する。RestartPolicyによって、停止されたコンテナは適宜再起動される。
- **Readiness Probe**: リクエストを受け付けられるかどうかをチェックするためのもの。これがエラーになった場合、リクエスト割り振り対象から当該Podは外れる。

※メモ
各Probeは、コンテナ単位に発行される(各コンテナでそれぞれProbeに対する実装を行う)。
restartPolicyは、Pod単位で指定することになり(spec以下に、containersと同列に指定する必要がある)、コンテナ単位での指定は出来なさそう。
んー、つまり、同一Podに含める各コンテナは、全て同じrestartPolicyが適用されるということになりそう。これはinitContainer(初期化用コンテナ)にも当てはまるようなので、ちょっと融通が効かない感じがするが...。どういう単位でPodを作成するか、という辺りの制約になってしまったりしないのだろうか...。
参考:[PodSpec v1 core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#podspec-v1-core)


### Liveness Probe / 1コンテナ in 1Pod

参考: [Configure Liveness, Readiness and Startup Probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/)

```yaml:exec-liveness.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5
```

Pod作成

```
vagrant@minikube:~/probe$ kubectl apply -f exec-liveness.yaml
pod/liveness-exec created
```

確認

```
vagrant@minikube:~/probe$ kubectl describe pod liveness-exec
Name:               liveness-exec
Namespace:          default
Priority:           0
PriorityClassName:  <none>
Node:               minikube/10.0.2.15
Start Time:         Tue, 05 Nov 2019 08:31:20 +0000
Labels:             test=liveness
Annotations:        kubectl.kubernetes.io/last-applied-configuration:
                      {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"test":"liveness"},"name":"liveness-exec","namespace":"default"},"s...
Status:             Running
IP:                 172.17.0.10
Containers:
  liveness:
    Container ID:  docker://59ea001a4f3ae228abe78c3da19f18995ea6da2a13885de6430739ebcd2d0917
    Image:         k8s.gcr.io/busybox
    Image ID:      docker-pullable://k8s.gcr.io/busybox@sha256:d8d3bc2c183ed2f9f10e7258f84971202325ee6011ba137112e01e30f206de67
    Port:          <none>
    Host Port:     <none>
    Args:
      /bin/sh
      -c
      touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    State:          Running
      Started:      Tue, 05 Nov 2019 08:31:22 +0000
    Ready:          True
    Restart Count:  0
    Liveness:       exec [cat /tmp/healthy] delay=5s timeout=1s period=5s #success=1 #failure=3
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-mw4tc (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-mw4tc:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-mw4tc
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age        From               Message
  ----    ------     ----       ----               -------
  Normal  Scheduled  <unknown>  default-scheduler  Successfully assigned default/liveness-exec to minikube
  Normal  Pulling    7s         kubelet, minikube  Pulling image "k8s.gcr.io/busybox"
  Normal  Pulled     5s         kubelet, minikube  Successfully pulled image "k8s.gcr.io/busybox"
  Normal  Created    5s         kubelet, minikube  Created container liveness
  Normal  Started    5s         kubelet, minikube  Started container liveness
```



```
Events:
  Type     Reason     Age                 From               Message
  ----     ------     ----                ----               -------
  Normal   Scheduled  <unknown>           default-scheduler  Successfully assigned default/liveness-exec to minikube
  Normal   Pulling    49s (x2 over 2m6s)  kubelet, minikube  Pulling image "k8s.gcr.io/busybox"
  Normal   Pulled     47s (x2 over 2m4s)  kubelet, minikube  Successfully pulled image "k8s.gcr.io/busybox"
  Normal   Created    47s (x2 over 2m4s)  kubelet, minikube  Created container liveness
  Normal   Started    47s (x2 over 2m4s)  kubelet, minikube  Started container liveness
  Warning  Unhealthy  4s (x6 over 89s)    kubelet, minikube  Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
  Normal   Killing    4s (x2 over 79s)    kubelet, minikube  Container liveness failed liveness probe, will be restarted
```

### Liveness Probe / 2コンテナ in 1Pod

```yaml:exec-liveness.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: con-liveness01
    image: k8s.gcr.io/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy01; sleep 30; rm -rf /tmp/healthy01; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy01
      initialDelaySeconds: 5
      periodSeconds: 5

  - name: con-liveness02
    image: k8s.gcr.io/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy02; sleep 120; rm -rf /tmp/healthy02; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy02
      initialDelaySeconds: 5
      periodSeconds: 5
```


```
Events:
  Type    Reason     Age        From               Message
  ----    ------     ----       ----               -------
  Normal  Scheduled  <unknown>  default-scheduler  Successfully assigned default/liveness-exec to minikube
  Normal  Pulling    5s         kubelet, minikube  Pulling image "k8s.gcr.io/busybox"
  Normal  Pulled     3s         kubelet, minikube  Successfully pulled image "k8s.gcr.io/busybox"
  Normal  Created    3s         kubelet, minikube  Created container con-liveness01
  Normal  Started    3s         kubelet, minikube  Started container con-liveness01
  Normal  Pulling    3s         kubelet, minikube  Pulling image "k8s.gcr.io/busybox"
  Normal  Pulled     1s         kubelet, minikube  Successfully pulled image "k8s.gcr.io/busybox"
  Normal  Created    1s         kubelet, minikube  Created container con-liveness02
  Normal  Started    1s         kubelet, minikube  Started container con-liveness02
```

```
Events:
  Type     Reason     Age        From               Message
  ----     ------     ----       ----               -------
  Normal   Scheduled  <unknown>  default-scheduler  Successfully assigned default/liveness-exec to minikube
  Normal   Pulling    39s        kubelet, minikube  Pulling image "k8s.gcr.io/busybox"
  Normal   Pulled     37s        kubelet, minikube  Successfully pulled image "k8s.gcr.io/busybox"
  Normal   Created    37s        kubelet, minikube  Created container con-liveness01
  Normal   Started    37s        kubelet, minikube  Started container con-liveness01
  Normal   Pulling    37s        kubelet, minikube  Pulling image "k8s.gcr.io/busybox"
  Normal   Pulled     35s        kubelet, minikube  Successfully pulled image "k8s.gcr.io/busybox"
  Normal   Created    35s        kubelet, minikube  Created container con-liveness02
  Normal   Started    35s        kubelet, minikube  Started container con-liveness02
  Warning  Unhealthy  4s         kubelet, minikube  Liveness probe failed: cat: can't open '/tmp/healthy01': No such file or directory
```

```
Events:
  Type     Reason     Age                From               Message
  ----     ------     ----               ----               -------
  Normal   Scheduled  <unknown>          default-scheduler  Successfully assigned default/liveness-exec to minikube
  Normal   Pulling    82s                kubelet, minikube  Pulling image "k8s.gcr.io/busybox"
  Normal   Created    80s                kubelet, minikube  Created container con-liveness02
  Normal   Started    80s                kubelet, minikube  Started container con-liveness02
  Normal   Pulled     80s                kubelet, minikube  Successfully pulled image "k8s.gcr.io/busybox"
  Warning  Unhealthy  39s (x3 over 49s)  kubelet, minikube  Liveness probe failed: cat: can't open '/tmp/healthy01': No such file or directory
  Normal   Killing    39s                kubelet, minikube  Container con-liveness01 failed liveness probe, will be restarted
  Normal   Pulling    9s (x2 over 84s)   kubelet, minikube  Pulling image "k8s.gcr.io/busybox"
  Normal   Pulled     7s (x2 over 82s)   kubelet, minikube  Successfully pulled image "k8s.gcr.io/busybox"
  Normal   Created    7s (x2 over 82s)   kubelet, minikube  Created container con-liveness01
  Normal   Started    7s (x2 over 82s)   kubelet, minikube  Started container con-liveness01
```

```
Events:
  Type     Reason     Age                 From               Message
  ----     ------     ----                ----               -------
  Normal   Scheduled  <unknown>           default-scheduler  Successfully assigned default/liveness-exec to minikube
  Normal   Pulling    2m7s                kubelet, minikube  Pulling image "k8s.gcr.io/busybox"
  Normal   Created    2m5s                kubelet, minikube  Created container con-liveness02
  Normal   Started    2m5s                kubelet, minikube  Started container con-liveness02
  Normal   Pulled     2m5s                kubelet, minikube  Successfully pulled image "k8s.gcr.io/busybox"
  Normal   Pulling    54s (x2 over 2m9s)  kubelet, minikube  Pulling image "k8s.gcr.io/busybox"
  Normal   Created    52s (x2 over 2m7s)  kubelet, minikube  Created container con-liveness01
  Normal   Started    52s (x2 over 2m7s)  kubelet, minikube  Started container con-liveness01
  Normal   Pulled     52s (x2 over 2m7s)  kubelet, minikube  Successfully pulled image "k8s.gcr.io/busybox"
  Warning  Unhealthy  9s (x6 over 94s)    kubelet, minikube  Liveness probe failed: cat: can't open '/tmp/healthy01': No such file or directory
  Normal   Killing    9s (x2 over 84s)    kubelet, minikube  Container con-liveness01 failed liveness probe, will be restarted
  Warning  Unhealthy  5s                  kubelet, minikube  Liveness probe failed: cat: can't open '/tmp/healthy02': No such file or directory
```

ちょっと見方が分かりにくいが、(Pod単位ではなく)コンテナ単位で再起動が繰り返されるっぽい。


### Liveness Probe / 2コンテナ in 1Pod / RestartPolicy: Never

```restartPolicy: Never```を指定した場合...

```
Events:
  Type     Reason     Age                   From               Message
  ----     ------     ----                  ----               -------
  Normal   Scheduled  <unknown>             default-scheduler  Successfully assigned default/liveness-exec to minikube
  Normal   Pulling    11m                   kubelet, minikube  Pulling image "k8s.gcr.io/busybox"
  Normal   Pulled     11m                   kubelet, minikube  Successfully pulled image "k8s.gcr.io/busybox"
  Normal   Created    11m                   kubelet, minikube  Created container con-liveness01
  Normal   Started    11m                   kubelet, minikube  Started container con-liveness01
  Normal   Pulling    11m                   kubelet, minikube  Pulling image "k8s.gcr.io/busybox"
  Normal   Created    11m                   kubelet, minikube  Created container con-liveness02
  Normal   Pulled     11m                   kubelet, minikube  Successfully pulled image "k8s.gcr.io/busybox"
  Normal   Started    11m                   kubelet, minikube  Started container con-liveness02
  Warning  Unhealthy  10m (x3 over 10m)     kubelet, minikube  Liveness probe failed: cat: can't open '/tmp/healthy01': No such file or directory
  Normal   Killing    10m                   kubelet, minikube  Container con-liveness01 failed liveness probe
  Warning  Unhealthy  8m51s (x3 over 9m1s)  kubelet, minikube  Liveness probe failed: cat: can't open '/tmp/healthy02': No such file or directory
  Normal   Killing    8m51s                 kubelet, minikube  Stopping container con-liveness02
```

Liveness Probeが失敗してコンテナ停止するけど、RestartPolicyがNeverなので再起動は行われず、コンテナは停止したままになっているっぽい。

## Initコンテナ

参考: [Initコンテナ(Init Containers)](https://kubernetes.io/ja/docs/concepts/workloads/pods/init-containers/)

通常のコンテナが起動する前にInitコンテナと呼ばれる、初期化用のコンテナを実行させることが可能(複数指定可)。
Initコンテナが完了した後、通常のコンテナが起動される。
Initコンテナを複数指定した場合、順番に1つずつ実行される。

以下のyamlファイルをそのまま持ってきて動かしてみます。
https://github.com/takara9/codes_for_lessons/blob/master/step07/init-container/init-sample.yml
これは、"init"という名前のInitコンテナを起動して、共有ボリュームを作成しhtmlディレクトリを作成します。
その後、"main"という名前の通常のコンテナを起動して、initコンテナで作成した共有ボリュームをマウントしています。
(ボリュームの操作についての詳細はまた後程...)

実行

```
vagrant@minikube:~/step07/init-container$ kubectl apply -f init-sample.yml
pod/init-sample created
```

状況確認

```
vagrant@minikube:~/step07/init-container$ kubectl get all
NAME                READY   STATUS      RESTARTS   AGE
pod/hello-world     0/1     Completed   0          11d
pod/init-sample     1/1     Running     0          23s
pod/liveness-exec   0/2     Error       0          5d23h
pod/nginx           1/1     Running     2          11d

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   11d

vagrant@minikube:~/step07/init-container$ kubectl get pod -o wide
NAME            READY   STATUS      RESTARTS   AGE     IP            NODE       NOMINATED NODE   READINESS GATES
hello-world     0/1     Completed   0          11d     172.17.0.9    minikube   <none>           <none>
init-sample     1/1     Running     0          43s     172.17.0.10   minikube   <none>           <none>
liveness-exec   0/2     Error       0          5d23h   172.17.0.10   minikube   <none>           <none>
nginx           1/1     Running     2          11d     172.17.0.4    minikube   <none>           <none>


vagrant@minikube:~/step07/init-container$ kubectl describe pod init-sample
Name:               init-sample
Namespace:          default
Priority:           0
PriorityClassName:  <none>
Node:               minikube/10.0.2.15
Start Time:         Mon, 11 Nov 2019 08:20:21 +0000
Labels:             <none>
Annotations:        kubectl.kubernetes.io/last-applied-configuration:
                      {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"init-sample","namespace":"default"},"spec":{"containers":[{"args":["-...
Status:             Running
IP:                 172.17.0.10
Init Containers:
  init:
    Container ID:  docker://a838edbd3a40207bbacfa6510fb2b70f45fbd35f88bef2496d3bace80ae0d6fc
    Image:         alpine
    Image ID:      docker-pullable://alpine@sha256:c19173c5ada610a5989151111163d28a67368362762534d8a8121ce95cf2bd5a
    Port:          <none>
    Host Port:     <none>
    Command:
      /bin/sh
    Args:
      -c
      mkdir /mnt/html; chown 33:33 /mnt/html
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Mon, 11 Nov 2019 08:20:28 +0000
      Finished:     Mon, 11 Nov 2019 08:20:28 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /mnt from data-vol (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-mw4tc (ro)
Containers:
  main:
    Container ID:  docker://51f3373d43aa6ab83bd6be23c3c74280e3ce30e3d7a7a9a31685c219065eae0d
    Image:         ubuntu
    Image ID:      docker-pullable://ubuntu@sha256:6e9f67fa63b0323e9a1e587fd71c561ba48a034504fb804fd26fd8800039835d
    Port:          <none>
    Host Port:     <none>
    Command:
      /bin/sh
    Args:
      -c
      tail -f /dev/null
    State:          Running
      Started:      Mon, 11 Nov 2019 08:20:36 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /docs from data-vol (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-mw4tc (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  data-vol:
    Type:    EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:
  default-token-mw4tc:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-mw4tc
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age        From               Message
  ----    ------     ----       ----               -------
  Normal  Scheduled  <unknown>  default-scheduler  Successfully assigned default/init-sample to minikube
  Normal  Pulling    76s        kubelet, minikube  Pulling image "alpine"
  Normal  Pulled     70s        kubelet, minikube  Successfully pulled image "alpine"
  Normal  Created    70s        kubelet, minikube  Created container init
  Normal  Started    70s        kubelet, minikube  Started container init
  Normal  Pulling    69s        kubelet, minikube  Pulling image "ubuntu"
  Normal  Pulled     62s        kubelet, minikube  Successfully pulled image "ubuntu"
  Normal  Created    62s        kubelet, minikube  Created container main
  Normal  Started    62s        kubelet, minikube  Started container main
```

mainコンテナに接続してみると、initコンテナで作成したディレクトリが確認できます。

```
vagrant@minikube:~/step07/init-container$ kubectl exec -it init-sample -c main bash
root@init-sample:/# ls -la /docs/
total 12
drwxrwxrwx 3 root     root     4096 Nov 11 08:20 .
drwxr-xr-x 1 root     root     4096 Nov 11 08:20 ..
drwxr-xr-x 2 www-data www-data 4096 Nov 11 08:20 html
```

お掃除。

```
vagrant@minikube:~/step07/init-container$ kubectl delete -f init-sample.yml
pod "init-sample" deleted
```

## サイドカーパターン

以下をベースに、一部カスタマイズして実行してみます。
https://github.com/takara9/codes_for_lessons/tree/master/step07/sidecar

contents-cloner, Dockerfileはそのまま使用。

これらを使用して、Dockerイメージを新たに作成して、自分用のリポジトリ名に変更してDocker HubにPushします。
contents-cloner, Dockerfileを配置したディレクトリ下で以下を実行。

```
vagrant@minikube:~/step07/sidecar$ docker build --tag tomotagwork/c-cloner:0.1 .
Sending build context to Docker daemon  4.608kB
Step 1/6 : FROM ubuntu:16.04
16.04: Pulling from library/ubuntu
e80174c8b43b: Pull complete                                                                                                                                                                                                                 d1072db285cc: Pull complete                                                                                                                                                                                                                 858453671e67: Pull complete                                                                                                                                                                                                                 3d07b1124f98: Pull complete         

<略>

Successfully built 93bd7e42920a
Successfully tagged tomotagwork/c-cloner:0.1

vagrant@minikube:~/step07/sidecar$ docker image ls tomotagwork/c-cloner
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
tomotagwork/c-cloner   0.1                 93bd7e42920a        2 minutes ago       238MB

vagrant@minikube:~/step07/sidecar$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: tomotagwork
Password:
WARNING! Your password will be stored unencrypted in /home/vagrant/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

vagrant@minikube:~/step07/sidecar$ docker push tomotagwork/c-cloner:0.1
The push refers to repository [docker.io/tomotagwork/c-cloner]
54ac2ae2c2cd: Pushed                                                                                                                                                                                                                        5f07055265ca: Pushed                                                                                                                                                                                                                        bc72fb2e7b74: Mounted from library/ubuntu                                                                                                                                                                                                   903669ee7207: Mounted from library/ubuntu                                                                                                                                                                                                   a5a5f8c62487: Mounted from library/ubuntu                                                                                                                                                                                                   788b17b748c2: Mounted from library/ubuntu                                                                                                                                                                                                   0.1: digest: sha256:c4d2acd5df3ca6d944051355facb4be380c21a404fad75f725926ec627e13b0f size: 1776

vagrant@minikube:~/step07/sidecar$ docker logout
Removing login credentials for https://index.docker.io/v1/
```

自分のGitHubのアカウント上にWebコンテンツを配置するためのリポジトリを作成し、テスト用のhtmlファイルを配置します。
https://github.com/tomotagwork/web-test01

自分用にプッシュしたDockerイメージと、Webコンテンツ配置用のGitHubリポジトリを使うように、yamlファイルを編集します。

```yml:webserver.yml
## サイドカーポッドのサンプル
#
apiVersion: v1
kind: Pod
metadata:
  name: webserver
spec:
  containers:          ## メイン コンテナ
  - name: nginx
    image: nginx
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: contents-vol
      readOnly: true

  - name: cloner       ## サイドカー コンテナ
    image: tomotagwork/c-cloner:0.1
    env:
    - name: CONTENTS_SOURCE_URL
      value: "https://github.com/tomotagwork/web-test01"
    volumeMounts:
    - mountPath: /data
      name: contents-vol

  volumes:             ## 共有ボリューム
  - name: contents-vol
    emptyDir: {}
```

これを使ってPodを作成してみます。

```
vagrant@minikube:~/step07/sidecar$ kubectl apply -f webserver.yml
pod/webserver created

vagrant@minikube:~/step07/sidecar$ kubectl get pod -o wide
NAME            READY   STATUS      RESTARTS   AGE   IP            NODE       NOMINATED NODE   READINESS GATES
hello-world     0/1     Completed   0          11d   172.17.0.9    minikube   <none>           <none>
liveness-exec   0/2     Error       0          6d    172.17.0.10   minikube   <none>           <none>
nginx           1/1     Running     2          11d   172.17.0.4    minikube   <none>           <none>
webserver       2/2     Running     0          17s   172.17.0.10   minikube   <none>           <none>

vagrant@minikube:~/step07/sidecar$ kubectl describe pod webserver
Name:               webserver
Namespace:          default
Priority:           0
PriorityClassName:  <none>
Node:               minikube/10.0.2.15
Start Time:         Mon, 11 Nov 2019 09:50:55 +0000
Labels:             <none>
Annotations:        kubectl.kubernetes.io/last-applied-configuration:
                      {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"webserver","namespace":"default"},"spec":{"containers":[{"image":"ngi...
Status:             Running
IP:                 172.17.0.10
Containers:
  nginx:
    Container ID:   docker://d72438c2634cecbb3a86684d9cf9633a4eb7c69c576c48b840fd87272abec7fe
    Image:          nginx
    Image ID:       docker-pullable://nginx@sha256:922c815aa4df050d4df476e92daed4231f466acc8ee90e0e774951b0fd7195a4
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Mon, 11 Nov 2019 09:50:58 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /usr/share/nginx/html from contents-vol (ro)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-mw4tc (ro)
  cloner:
    Container ID:   docker://b656cdab5448af24edb5230d554edb807d7db55c5a528f32a72c7c2b7b24906a
    Image:          tomotagwork/c-cloner:0.1
    Image ID:       docker-pullable://tomotagwork/c-cloner@sha256:b64346ba8772445fe53ae8bdd377f7c209332beefe0ab47796bb91d70b64d8d9
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Mon, 11 Nov 2019 09:50:59 +0000
    Ready:          True
    Restart Count:  0
    Environment:
      CONTENTS_SOURCE_URL:  https://github.com/tomotagwork/web-test01
    Mounts:
      /data from contents-vol (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-mw4tc (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  contents-vol:
    Type:    EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:
  default-token-mw4tc:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-mw4tc
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age        From               Message
  ----    ------     ----       ----               -------
  Normal  Scheduled  <unknown>  default-scheduler  Successfully assigned default/webserver to minikube
  Normal  Pulling    61s        kubelet, minikube  Pulling image "nginx"
  Normal  Pulled     58s        kubelet, minikube  Successfully pulled image "nginx"
  Normal  Created    58s        kubelet, minikube  Created container nginx
  Normal  Started    58s        kubelet, minikube  Started container nginx
  Normal  Pulled     58s        kubelet, minikube  Container image "tomotagwork/c-cloner:0.1" already present on machine
  Normal  Created    58s        kubelet, minikube  Created container cloner
  Normal  Started    57s        kubelet, minikube  Started container cloner
```

172.17.0.10でwebserverのPodが稼働したので、busyboxを使ってアクセスしてみます。

```
vagrant@minikube:~/step07/sidecar$ kubectl run busybox --image=busybox --restart=Never --rm -it sh
If you don't see a command prompt, try pressing enter.
/ # wget -q -O - http://172.17.0.10/
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<h1>テスト by tomotagwork</h1>

<p>ポッドテンプレートは、デプロイメント、レプリカセット、ジョブ、およびステートフルセットなどのコントローラに対するポッド仕様です。 これらコントローラは、ポッドテンプレートを使用して実際のポッドを作成します。</p>

<p><a href="https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/">Pod Overview</a>.</p>


</body>
</html>
```

GitHub上のindex.htmlを修正して、1分後に再度確認してみます。

```
/ # wget -q -O - http://172.17.0.10/
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<h1>テスト by tomotagwork / modified</h1>

<p>ポッドテンプレートは、デプロイメント、レプリカセット、ジョブ、およびステートフルセットなどのコントローラに対するポッド仕様です。 これらコントローラは、ポッドテンプレートを使用して実際のポッドを作成します。</p>

<p><a href="https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/">Pod Overview</a>.</p>


</body>
</html>
```

変更されたindex.htmlの内容が返されることが確認できました。意図した通りに動いてますね。