Kubernetes の学習 (3) ～ ラベル、Replication Controller の作成



#概要
今回は Replication Controller を作成しますが、それと関係のあるラベルについてもまとめます。

# ラベル

## ラベルとは？
Kubernetes 上のオブジェクト(Podなど)に付けることができる Key/Value ペアの文字列で、オブジェクトに任意のメタ情報のようなものを持たせることができる。Pod が複数ある場合にそれぞれにラベルを付けることにより、Pod をグループ化したり、特定の Pod を抽出することができる。

例えば、次のような２つの Pod の定義があるとする。

pod-with-label1.yaml ：

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod1
  labels:
    app: petshop       ← ラベル(Key = app, Value = petshop)
    env: production    ← ラベル(Key = env, Value = production)
spec:
  containers:
    - name: container1
      image: nginx
      ports:
        - containerPort: 80
```

pod-with-label2.yaml ：

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod2
  labels:
    app: petshop     ← ラベル(Key = app, Value = petshop)
    env: staging     ← ラベル(Key = env, Value = staging)
spec:
  containers:
    - name: container2
      image: nginx
      ports:
        - containerPort: 80
```

これらの Pod を作成してから、ラベルでフィルタリングしながら Pod を表示してみる。

```bash
# Pod の作成
$ kubectl create -f pod-with-label1.yaml
$ kubectl create -f pod-with-label2.yaml

# app=petshop でフィルタ。
# 両方表示される。
$ kubectl get pods -l app=petshop
NAME      READY     STATUS    RESTARTS   AGE
pod1      1/1       Running   0          14s
pod2      1/1       Running   0          12s

# env=production でフィルタ。
# pod1 だけ表示される。
$ kubectl get pods -l env=production
NAME      READY     STATUS    RESTARTS   AGE
pod1      1/1       Running   0          41s

# pod2 のラベルを更新してみる。
# app : petshop → bookstore
# env : staging → production
$ kubectl label --overwrite pods pod2 app=bookstore
$ kubectl label --overwrite pods pod2 env=production

# そして再び env=production でフィルタ。
# 今度は両方表示される。
$ kubectl get pods -l env=production
NAME      READY     STATUS    RESTARTS   AGE
pod1      1/1       Running   0          2m
pod2      1/1       Running   0          1m

# こんな指定も可能。
# app が petshop、bookstore のいずれかに一致するという意味。
$ kubectl get pods -l "app in (petshop, bookstore)"
NAME      READY     STATUS    RESTARTS   AGE
pod1      1/1       Running   0          2m
pod2      1/1       Running   0          2m

# こんな指定も可能。
# app=petshop かつ env=production という意味。
$ kubectl get pods -l app=petshop,env=production
NAME      READY     STATUS    RESTARTS   AGE
pod1      1/1       Running   0          4m

# 次に進む前に、作成した Pod をすべて削除しておく。
$ kubectl delete --all pods
```



# Replication Controller
では、本題へ。

# Replication Controllerとは？
Replication Controller は、Pod のレプリカ(複製)数を維持するための機能。

Replication Controller はテンプレートにより定義された Pod を、指定された数の分だけ作成する。そして対象の Pod 数を監視し、もしホストの障害等で Pod の数が減れば新たに作成し、逆に増えすぎた場合は削除することにより Pod を一定数に保つ。そのため、Pod が１つしかないようなアプリケーションでも、Replication Controller を使うことが推奨されている。

また、Replication Controller が監視する Pod(の集まり)は、ラベルにより定義される。イメージとしては以下の図のような感じ。この図では、app=petshop というラベルを持つ Pod を Replication Controller が監視している。

![rc.png](https://qiita-image-store.s3.amazonaws.com/0/79316/372d8951-615f-4d2b-32f3-a3d435cca988.png)

## Replication Controller の作成
では、実際に Replication Controller を作って試してみる。まず、次のような YAML を用意する。 

rc.yaml ：

```yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: rc1
spec:
  replicas: 3
  selector:
    app: petshop
  template:
    metadata:
      labels:
        app: petshop
    spec:
      containers:
      - name: container1
        image: nginx
        ports:
        - containerPort: 80
```

この YAML には以下のような情報が含まれている。

* Replication Controller は、template 以下の定義に基づき Pod を作成する（この部分が Pod のテンプレート)
* 作成される Pod は、 app=petshop というラベルを持つ
* Replication Controller は、app=petshop というラベルを持つ Pod を監視対象とする(selector で定義されている)
* Pod のレプリカ数は 3 である

なので、Pod に割り当てられるラベル(template 以下で定義)と、Replication Controller が監視対象とするラベル(selector で定義)が一致している必要がある。

では、このファイルを使って、Replication Controller を作成してみる。

```bash
# 作成
$ kubectl create -f rc.yaml

# Replication Controller が作成されたか確認
$ kubectl get rc
CONTROLLER   CONTAINER(S)   IMAGE(S)   SELECTOR      REPLICAS
rc1          container1     nginx      app=petshop   3
```

Pod を表示してみると、確かに app=petshop というラベルを持つ Pod が３つ作成されている。なお、-o wide を指定すると Pod が実行されているホストの情報が表示される。

```bash
$ kubectl get pods -l app=petshop -o wide
NAME        READY     STATUS    RESTARTS   AGE       NODE
rc1-09r4r   1/1       Running   0          2m        ip-172-20-0-13.ap-northeast-1.compute.internal
rc1-k2y95   1/1       Running   0          2m        ip-172-20-0-15.ap-northeast-1.compute.internal
rc1-pldl2   1/1       Running   0          2m        ip-172-20-0-14.ap-northeast-1.compute.internal
```

ここで、試しに rc1-pldl2 という Pod を削除してみる。 すると、新たな Pod が作成されることが分かる(rc1-jmwnc が新たに作成さらた Pod)。

```bash
# 削除
$ kubectl delete pods rc1-pldl2

# Pod を表示。新しい Pod(rc1-jmwnc) が作成されていることが分かる。
$ kubectl get pods -l app=petshop -o wide
NAME        READY     STATUS    RESTARTS   AGE       NODE
rc1-09r4r   1/1       Running   0          5m        ip-172-20-0-13.ap-northeast-1.compute.internal
rc1-jmwnc   0/1       Running   0          4s        ip-172-20-0-14.ap-northeast-1.compute.internal
rc1-k2y95   1/1       Running   0          5m        ip-172-20-0-15.ap-northeast-1.compute.internal
```

次に、わざと Pod(rc1-k2y95) のラベルを変えてみる。すると、Replication Controller は app=petshop の Pod が１つ減ったと判断して、新たに Pod を作成する。

```bash
# ラベルの変更
$ kubectl label --overwrite pods rc1-k2y95 app=bookstore

# Pod を表示。新しい Pod(rc1-zv5bw) が作成されていることが分かる。
$ kubectl get pods -l app=petshop -o wide
NAME        READY     STATUS    RESTARTS   AGE       NODE
rc1-09r4r   1/1       Running   0          10m       ip-172-20-0-13.ap-northeast-1.compute.internal
rc1-jmwnc   1/1       Running   0          4m        ip-172-20-0-14.ap-northeast-1.compute.internal
rc1-zv5bw   1/1       Running   0          23s       ip-172-20-0-14.ap-northeast-1.compute.internal
```

なお、ラベルを変更した Pod(rc1-k2y95) は Replication Controller の監視対象から外れたが、削除されたわけではないので単独で動作している。

```bash
$ kubectl get pods -l app=bookstore -o wide
NAME        READY     STATUS    RESTARTS   AGE       NODE
rc1-k2y95   1/1       Running   0          12m       ip-172-20-0-15.ap-northeast-1.compute.internal
```

このように、Replication Controller は自分が生成した Pod の死活をずっと追跡するというより、あくまで selector に一致する Pod の数を監視しているだけのように見える。

最後に、Replication Controller を削除しておく。Pod もすべて削除される。

```bash
# Replication Controller を削除
$ kubectl delete rc rc1

# Pod も削除される
$ kubectl get pods -l app=petshop -o wide
NAME      READY     STATUS    RESTARTS   AGE       NODE
```

# 参考サイト
* [Labels & Selectors](http://kubernetes.io/v1.0/docs/user-guide/labels.html)
* [Replication Controller](http://kubernetes.io/v1.0/docs/user-guide/replication-controller.html)
* [Kubernetes 201 - Labels, Replication Controllers, Services and Health Checking](http://kubernetes.io/v1.0/docs/user-guide/walkthrough/k8s201.html)