作った2つのコンテナをRancherでk8sにLB付きでデプロイする～EHW2018「アプリ⑦」 

# 概要

このエントリは、「Enterprise "hello, world" 2018 Advent Calendar 2018」の12/22向けのものです。このAdvent Calendarでは、複数個のエントリにまたがる話の流れも鑑みつつ、なるべく1エントリで1つのトピックをカバーできるようにする予定です。

このエントリで記載するトピックは、作ったコンテナをRancherでk8sにデプロイすることです。このエントリの中で、下図のようなセットが出来上がります。

|![Service_V1(1).png](https://qiita-image-store.s3.amazonaws.com/0/65002/3c926379-e825-4608-f1d0-abd77d9ad20c.png)|
|:--:|



# 前提

## おことわり

- このEnterpfise "hello, world"シリーズは、ネタのためのエントリです。実環境でそのまま利用ことを目的とはしていません。
- 動かしやすさを優先してセキュリティを意図的に低くする設定など入れてありますのでご注意ください。

## 想定読者

「Enterprise "hello, world" 2018」的なネタとしては、下記のような状況を想定しています。

> Rancherの準備も、コンテナもできたし、そろそろデプロイしないとコマ数が足りない。

# 前提

## Rancherのバージョンアップ

Enterprise Hello WorldのAdvent Calendarを書いている間に、Rancherのバージョンが2.1.5に上がっていました。こちらをアップデートした結果が、下記のとおりです。

```yml
  rancher:
    image: 'rancher/rancher:v2.1.5'
    restart: unless-stopped
    networks:
      - extnet
    ports:
      - "${RANCHER_ADDR}:8080:80"
      - "${RANCHER_ADDR}:8443:443"
      - "${HOST1_ADDR}:38443:443"
    volumes:
      - '${CONF_DIR}/rancher/mysql:/var/lib/mysql'
    links:
      - samba
      - gitlab
      - jenkins
      - registry
    extra_hosts:
      - "localdc.ehw2018.local:192.168.3.222"
    environment:
      - CATTLE_AGENT_IP=${HOST1_ADDR}
```

## Rancherのnode内のdockerイメージ

以下のように、シリーズの中で作ったリポジトリをPrivate Registryに登録してあるものを、ノード側にpullしておきます。

まず、自己証明書で運用しているPrivate Registryからイメージをpullできるように、ノードのdockerに対し証明書を登録しておきます。下記ファイルに、10.0.2.15のホストの証明書をコピーしておきます。

```
# ls /etc/docker/certs.d/10.0.2.15\:5443/ca.crt 
/etc/docker/certs.d/10.0.2.15:5443/ca.crt
```

イメージをpullします。

```shell-session
# docker pull 10.0.2.15:5443/test/greetings-server
# docker pull 10.0.2.15:5443/test/front-test
```

ここで「X.509〜」などのエラーでpullできない場合は、証明書の指定を見直すとよいでしょう。

# Rancherでコンテナをデプロイ

## Workloadを登録

ActiveDirectoryのユーザでRancherにログインします。
このエントリでは、これまでのシリーズで作成したユーザ「john」を使用します。

メニューから、「ehw2018」クラスタの「Default」を選択します。

![Screenshot_2019-01-06_12-13-19.png](https://qiita-image-store.s3.amazonaws.com/0/65002/b2ce5490-3ca9-e9fb-6529-e5e1cc51950f.png)

### Front

まず、フロント側を登録します。

「Workload」で「Deploy」ボタンを押下し、登録したコンテナを対象に、下図のように指定し、「Launch」を押します。WEBサーバで公開しているポート番号80を指定します。「Cluster IP」を使用することに注意してください。

![Screenshot_2019-01-06_12-11-24.png](https://qiita-image-store.s3.amazonaws.com/0/65002/f5315810-fe35-8cd4-b911-53fa6efa5d05.png)

### Back

続けて、API側のコンテナを登録します。APIサーバ側で公開しているポート番号8080を指定します。

![Screenshot_2019-01-06_12-16-54.png](https://qiita-image-store.s3.amazonaws.com/0/65002/95474733-9086-9c49-1b25-0d3e2c14fe33.png)

2つのコンテナを登録して少し待つと、一覧画面で「Active」になるはずです（下図）。

![Screenshot_2019-01-06_12-19-02.png](https://qiita-image-store.s3.amazonaws.com/0/65002/2bcc5cc7-c6fd-a785-006e-13e1cc548aa1.png)

## ロードバランサの指定

Rancherで標準で使える、L7のLoad Balancerを作ります。

上記で使った「Workload」のとなりの「Load Balancing」メニューから、「Add Ingress」を選び、下図のように指定します。名前解決には、ローカル音アドレスを名前解決してくれるサービス「.xip.io」（Rancherで標準で連携されている）を使っています。

![Screenshot_2019-01-06_12-38-10.png](https://qiita-image-store.s3.amazonaws.com/0/65002/366231fe-40dc-d1ee-bf7b-512f1b6e12e6.png)

「Save」を押して確定します。しばらく待つと、下図のように「Active」になります。

![Screenshot_2019-01-06_12-43-18.png](https://qiita-image-store.s3.amazonaws.com/0/65002/9ade582b-c522-be0a-0a6d-d839c7dc16e2.png)

## 動作確認

前述の内容で出来上がったサイトに、ブラウザからアクセスしてみます。

![Screenshot_2019-01-06_12-46-05.png](https://qiita-image-store.s3.amazonaws.com/0/65002/466a1010-4249-bb41-6671-d5eef1bde2f3.png)

ブラウザに、これまでのエントリ([開発時にwebpack-dev-serverを使ってフロントからAPIサーバを呼ぶ(mithrilのテストも更新)～EHW2018「アプリ⑤」 ](https://qiita.com/hrkt/items/cd6afeea59ac7ad5643d))で確認したのと同じ画面が表示されました。

Rancherからログを確認すると、フロント側に下記のログが出ています。

![Screenshot_2019-01-06_12-48-53.png](https://qiita-image-store.s3.amazonaws.com/0/65002/57ec9a1f-774f-9e89-4e90-e8e4d5d40b70.png)


バック側もアクセスログが出ています。

![Screenshot_2019-01-06_12-51-33.png](https://qiita-image-store.s3.amazonaws.com/0/65002/9ff900bf-6b8c-a519-d7e3-3cc14a290595.png)


## (参考)設定ファイル等

このエントリでは、Rancherから操作しているためk8sのyamlファイルを記述する必要はありませんが、出来上がった設定を参考として転記しておきます。

### フロント

```yaml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
    field.cattle.io/creatorId: user-bsplf
    field.cattle.io/publicEndpoints: '[{"addresses":["10.0.2.7"],"port":80,"protocol":"HTTP","serviceName":"default:ingress-8294985a8b39f212d87b564b94349011","ingressName":"default:website","hostname":"website.default.10.0.2.7.xip.io","path":"/","allNodes":true}]'
  creationTimestamp: 2019-01-06T02:46:53Z
  generation: 4
  labels:
    cattle.io/creator: norman
    workload.user.cattle.io/workloadselector: deployment-default-front-test
  name: front-test
  namespace: default
  resourceVersion: "14695"
  selfLink: /apis/apps/v1beta2/namespaces/default/deployments/front-test
  uid: 535cfade-115d-11e9-987b-080027367588
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      workload.user.cattle.io/workloadselector: deployment-default-front-test
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      annotations:
        cattle.io/timestamp: 2019-01-06T02:46:53Z
        field.cattle.io/ports: '[[{"containerPort":80,"dnsName":"front-test","kind":"ClusterIP","name":"80tcp02","protocol":"TCP","sourcePort":0}]]'
      creationTimestamp: null
      labels:
        workload.user.cattle.io/workloadselector: deployment-default-front-test
    spec:
      containers:
      - image: 10.0.2.15:5443/test/front-test:latest
        imagePullPolicy: Always
        name: front-test
        ports:
        - containerPort: 80
          name: 80tcp02
          protocol: TCP
        resources: {}
        securityContext:
          allowPrivilegeEscalation: false
          capabilities: {}
          privileged: false
          readOnlyRootFilesystem: false
          runAsNonRoot: false
        stdin: true
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        tty: true
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  availableReplicas: 1
  conditions:
  - lastTransitionTime: 2019-01-06T02:46:57Z
    lastUpdateTime: 2019-01-06T02:46:57Z
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  - lastTransitionTime: 2019-01-06T02:46:54Z
    lastUpdateTime: 2019-01-06T02:46:57Z
    message: ReplicaSet "front-test-78db9b795b" has successfully progressed.
    reason: NewReplicaSetAvailable
    status: "True"
    type: Progressing
  observedGeneration: 4
  readyReplicas: 1
  replicas: 1
  updatedReplicas: 1
```

### API

```yaml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
    field.cattle.io/creatorId: user-bsplf
    field.cattle.io/publicEndpoints: '[{"addresses":["10.0.2.7"],"port":80,"protocol":"HTTP","serviceName":"default:ingress-7868f24b4854e04816594aba5314d7a7","ingressName":"default:website","hostname":"website.default.10.0.2.7.xip.io","path":"/api","allNodes":true}]'
  creationTimestamp: 2019-01-06T02:47:29Z
  generation: 4
  labels:
    cattle.io/creator: norman
    workload.user.cattle.io/workloadselector: deployment-default-greetings-server
  name: greetings-server
  namespace: default
  resourceVersion: "14696"
  selfLink: /apis/apps/v1beta2/namespaces/default/deployments/greetings-server
  uid: 68c53a32-115d-11e9-987b-080027367588
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      workload.user.cattle.io/workloadselector: deployment-default-greetings-server
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      annotations:
        cattle.io/timestamp: 2019-01-06T02:47:28Z
        field.cattle.io/ports: '[[{"containerPort":8080,"dnsName":"greetings-server","kind":"ClusterIP","name":"8080tcp02","protocol":"TCP","sourcePort":0}]]'
      creationTimestamp: null
      labels:
        workload.user.cattle.io/workloadselector: deployment-default-greetings-server
    spec:
      containers:
      - image: 10.0.2.15:5443/test/greetings-server:latest
        imagePullPolicy: Always
        name: greetings-server
        ports:
        - containerPort: 8080
          name: 8080tcp02
          protocol: TCP
        resources: {}
        securityContext:
          allowPrivilegeEscalation: false
          capabilities: {}
          privileged: false
          readOnlyRootFilesystem: false
          runAsNonRoot: false
        stdin: true
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        tty: true
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  availableReplicas: 1
  conditions:
  - lastTransitionTime: 2019-01-06T02:47:33Z
    lastUpdateTime: 2019-01-06T02:47:33Z
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  - lastTransitionTime: 2019-01-06T02:47:29Z
    lastUpdateTime: 2019-01-06T02:47:33Z
    message: ReplicaSet "greetings-server-54c977cc8c" has successfully progressed.
    reason: NewReplicaSetAvailable
    status: "True"
    type: Progressing
  observedGeneration: 4
  readyReplicas: 1
  replicas: 1
  updatedReplicas: 1

```

### ロードバランサ

```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    field.cattle.io/creatorId: user-bsplf
    field.cattle.io/ingressState: '{"d2Vic2l0ZS9kZWZhdWx0L3hpcC5pby8vLzgw":"deployment:default:front-test","d2Vic2l0ZS9kZWZhdWx0L3hpcC5pby8vYXBpLzgwODA=":"deployment:default:greetings-server"}'
    field.cattle.io/publicEndpoints: '[{"addresses":["10.0.2.7"],"port":80,"protocol":"HTTP","serviceName":"default:ingress-7868f24b4854e04816594aba5314d7a7","ingressName":"default:website","hostname":"website.default.10.0.2.7.xip.io","path":"/api","allNodes":true},{"addresses":["10.0.2.7"],"port":80,"protocol":"HTTP","serviceName":"default:ingress-8294985a8b39f212d87b564b94349011","ingressName":"default:website","hostname":"website.default.10.0.2.7.xip.io","path":"/","allNodes":true}]'
  creationTimestamp: 2019-01-06T03:41:15Z
  generation: 2
  labels:
    cattle.io/creator: norman
  name: website
  namespace: default
  resourceVersion: "14595"
  selfLink: /apis/extensions/v1beta1/namespaces/default/ingresses/website
  uid: eb8bc0a8-1164-11e9-987b-080027367588
spec:
  rules:
  - host: website.default.10.0.2.7.xip.io
    http:
      paths:
      - backend:
          serviceName: ingress-7868f24b4854e04816594aba5314d7a7
          servicePort: 8080
        path: /api
      - backend:
          serviceName: ingress-8294985a8b39f212d87b564b94349011
          servicePort: 80
        path: /
status:
  loadBalancer:
    ingress:
    - ip: 10.0.2.7
```


# まとめ

このエントリでは、「Enterprise "hello, world" 2018 Advent Calendar 2018」(EHW2018)の22日目として、作ったコンテナをRancherでk8sにデプロイすることをトピックとして取り上げました。

EHW2018のネタとしては、このあと、デプロイ周りをもう少し取り扱うことを考えています。