Deploy on Kubernetesをやってみる

# Deploy on Kubernetesをやってみる

Deploy on Kubernetes のサイトを参考に環境を用意していきます。
https://docs.docker.com/docker-for-mac/kubernetes/

この内容を進めるには、事前に[Docker Desktop for Mac > Getting started](https://docs.docker.com/docker-for-mac/#kubernetes)をやっておく必要があります。
上記内容については、Qiitaの記事[Get started with Docker Desktop for Macをやってみる](https://qiita.com/You_name_is_YU/items/2c2790ecd0b4114389de)でも実践してますので、参考までに。

## 1. docker-compose.ymlを作成

```yaml
version: '3.3'

services:
  web:
    image: dockersamples/k8s-wordsmith-web
    ports:
     - "80:80"

  words:
    image: dockersamples/k8s-wordsmith-api
    deploy:
      replicas: 5
      endpoint_mode: dnsrr
      resources:
        limits:
          memory: 50M
        reservations:
          memory: 50M

  db:
    image: dockersamples/k8s-wordsmith-db
```

## 2. mystackという名前でスタックをデプロイ

`docker stack deploy`コマンドで作成した`docker-compose.yml`ファイルを指定して何やらやるらしい。
`docker stack deploy`コマンドが何をするものなのか、わからなかったので調べてみました。

https://docs.docker.com/engine/reference/commandline/stack_deploy/

> Deploy a new stack or update an existing stack
> 新しいスタックをデプロイまたは既存のスタックを更新する

ここで指定しているコマンドのオプションについても理解しておきたいと思います。

| オプション       |       デフォルト |    説明    |
|:-----------------|:------------------|:------------------|
| --namespace||Kubernetesで利用される名前空間|
| --compose-file , -c||docker-compose.ymlファイルのパスまたは'-'（stdin（標準入力）からの入力）を指定|
| --orchestrator||利用するオーケストレータを指定する。（kubernetes/swarm/all）|

```shell-session
$ docker stack deploy --compose-file docker-compose.yml --orchestrator=kubernetes mystack
Waiting for the stack to be stable and running...
web: Ready		[pod status: 1/1 ready, 0/1 pending, 0/1 failed]
words: Ready		[pod status: 5/5 ready, 0/5 pending, 0/5 failed]
db: Ready		[pod status: 1/1 ready, 0/1 pending, 0/1 failed]

Stack mystack is stable and running

$ docker stack services --orchestrator kubernetes mystack
ID                  NAME                MODE                REPLICAS            IMAGE                             PORTS
7a516f2b-250        mystack_db          replicated          1/1                 dockersamples/k8s-wordsmith-db    
7a5850d1-250        mystack_web         replicated          1/1                 dockersamples/k8s-wordsmith-web   *:80->80/tcp
7a765a71-250        mystack_words       replicated          5/5                 dockersamples/k8s-wordsmith-api   
```

`--namespace`オプションを使ったところ以下のメッセージが出たため、とりあえず使わないことにしました。

```
namespaces "my-app" not found
```

## 3. 起動したので動きを確認する

[Deploy on Kubernetes](https://docs.docker.com/docker-for-mac/kubernetes/)には、deployしたあとのことについて触れられていませんでした。

なので実際に使い方が合っているのかは分かりませんが、とりあえず試した内容を記録します。

```yaml
  web:
    image: dockersamples/k8s-wordsmith-web
    ports:
     - "80:80"
```

にあるように、80ポートを使用したWebサーバーがあるので、ここにアクセスしてみます。

http://localhost

以下のような画面が表示されます。

![screencapture-localhost-2019-12-23-07_24_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246556/a03ce429-2ce1-f274-d218-2142a4f5289b.png)

画面には特にボタンやリンクなどが無い。。。。

## 4. dockersampleをどうやって使ったらいいのか確認してみる

どうやら、画面をリロードする度に、WebAPIを実行して単語（word）を取得し、レゴブロックのような見た目のところにバインドして画面に表示しているようです。

`/words/noun`や`/words/adjective`,`/words/verb`というAPIが用意されているみたいです。

```html
<!DOCTYPE html>
<html lang="en" ng-app="lab">
<head>
  <meta charset="utf-8">
  <title>dockercon EU 18</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div class="logo"><img src="images/logo.svg" style="width:50%"/></div>

<div class="sentence" ng-controller="LabCtrl">
  <div class="line line1 slide-in">
  <span class="result adjective slide-in">
    <span class="word slide-in" ng-bind="adjective1.word"></span>
    <span class="hostname" ng-bind="adjective1.hostname"></span>
  </span>
  <span class="result noun slide-in">
    <span class="word" ng-bind="noun1.word"></span>
    <span class="hostname" ng-bind="noun1.hostname"></span>
  </span>
  </div>
  <div class="line line2 slide-in">
  <span class="result verb slide-in">
    <span class="word" ng-bind="verb.word"></span>
    <span class="hostname" ng-bind="verb.hostname"></span>
  </span>
  </div>
  <div class="line line3 slide-in">
  <span class="result adjective slide-in">
    <span class="word" ng-bind="adjective2.word"></span>
    <span class="hostname" ng-bind="adjective2.hostname"></span>
  </span>
  <span class="result noun slide-in">
    <span class="word" ng-bind="noun2.word"></span>
    <span class="hostname" ng-bind="noun2.hostname"></span>
  </span>
  </div>
</div>

<div class="footer"><img src="images/homes.png" /></div>
</body>

<script src="angular.min.js"></script>
<script src="app.js"></script>
</html>
```

```javascript
"use strict";

var lab = angular.module('lab', []);

lab.controller('LabCtrl', function ($scope, $http, $timeout) {
  $scope.noun1 = "";
  $scope.noun2 = "";
  $scope.adjective1 = "";
  $scope.adjective2 = "";
  $scope.verb = "";

  getWord($http, $timeout, '/words/noun', function(resp) {
    $scope.noun1 = word(resp);
  });
  getWord($http, $timeout, '/words/noun', function(resp) {
    $scope.noun2 = word(resp);
  });
  getWord($http, $timeout, '/words/adjective', function(resp) {
    var adj = word(resp);
    adj.word = adj.word.charAt(0).toUpperCase() + adj.word.substr(1)
    $scope.adjective1 = adj;
  });
  getWord($http, $timeout, '/words/adjective', function(resp) {
    $scope.adjective2 = word(resp);
  });
  getWord($http, $timeout, '/words/verb', function(resp) {
    $scope.verb = word(resp);
  });
});

function getWord($http, $timeout, url, callback) {
  $http.get(url).then(callback, function(resp) {
    $timeout(function() {
      console.log("Retry: " + url);
      getWord($http, $timeout, url, callback);
    }, 500);
  });
}

function word(resp) {
  return {
    word: resp.data.word,
    hostname: resp.headers()["source"]
  };
}
```

## 5. 使い終わったらコンテナを停止する

```shell-session
$ docker stack rm --orchestrator=kubernetes mystack
Removing stack: mystack
```

以上で[Deploy on Kubernetes](https://docs.docker.com/docker-for-mac/kubernetes/)のお試しは終了です。