【IBM Cloud k8s検証メモ】Kubernetesクラスタ Liteプラン(無料)へ自作アプリをデプロイ


bx ic として利用していた単一コンテナーとスケーラブル・コンテナーのサービスは終了しました(1)ので、 無料版のKubernetesのサービスから Dockerコンテナを起動する方法についてメモです。

![スクリーンショット 2017-08-31 10.14.54.png](https://qiita-image-store.s3.amazonaws.com/0/42829/9c086476-934d-70eb-b1d7-6f5467088d82.png "スクリーンショット 2017-08-31 10.14.54.png")


## ローカル環境の起動

Bluemix CLI や Docker の環境を何も無い処からセットアップするのは、大変なので、ここでは予め準備した Vagrantfile でセットアップ済みの開発環境を起動します。このファイルは、GitHub https://github.com/takara9/bluemix-dev にありますので、詳しくは README.md を参照願います。

~~~
git clone https://github.com/takara9/bluemix-dev bluemix-k8s
~~~

ディレクトリを移動して、仮想マシンを起動します。 この仮想マシンは、Docker環境, ndenv, Bluemix CLI, kebectl等がインストールされた状態で起動します。

~~~
cd bluemix-k8s/
vagrant up
~~~



## Bluemix CLIでログイン

無事に起動したら、ログインして Bluemix にログインして、コンテナサービスのプラグインをインストールします。 新しいプラグインは、bx ic に変わって、 bx cs になります。 

~~~
vagrant ssh
~~~

Bluemix CLI で、北米南部のBluemixへログインします。

~~~
vagrant@vagrant-ubuntu-trusty-64:~$ bx login

API endpoint> api.ng.bluemix.net

Email> [your IBMid]

Password> 
Authenticating...
OK

Select an account (or press enter to skip):
1. [your name]'s Account (************************)
Enter a number> 1
Targeted account Maho Takara's Account (************************)

Targeted org [your IBMid]

Select a space (or press enter to skip):
1. dev
2. prod
Enter a number> 1
Targeted space dev


A new version of Bluemix CLI is available. Do you want to update? (yes/no) [yes]> yes

Installing version '0.5.6'...
Downloading...
12555559 bytes downloaded
Saved in /home/vagrant/.bluemix/tmp/bx_020372816/Bluemix_CLI_0.5.6_amd64.tar.gz
Do you want to launch CLI installer? (yes/no) [yes]> yes

Copying files ...
The Bluemix Command Line Interface (Bluemix CLI) is installed successfully.
To get started, open a new Linux terminal and enter "bluemix help", or enter "bx help" as short name.

With Bluemix CLI 0.4.0 or later, the CLI can automatically collect diagnostic and usage information and send it to Bluemix for analysis.
This information will help us better understand current client usage and plan for future use. No personally identifiable data is collected.

To stop collecting information, you can run the following command:
        'bluemix config --usage-stats-collect false'

                   
API endpoint:   https://api.ng.bluemix.net (API version: 2.75.0)   
Region:         us-south   
User:           [your IBMid]   
Account:        [your name]'s Account (************************)   
Org:            [your org]   
Space:          dev   
~~~



## プラグインのインストール

kubernetes（以下 k8s とする) のコンテナ・サービスのプラグインをインストールします。

~~~
bx plugin install container-service -r Bluemix
~~~


## フリー版のk8sクラスタを作成

次のコマンドで、Kubernetes のクラスタを起動します。 フリー版なので、ハードウェアは共有、ワーカーノードは１つまで、ロードバランサーは利用不可の条件になります。

~~~
bx cs cluster-create --name mycluster1 --hardware shared
~~~

今回は、k8sのクラスタを起動するのに、約47分かかりました。 起動の様子は下記に記録してありますので、参考にしてください。




## 起動の様子

何時で完了するか解らない処理を、ただ待っているのは、ちょっと辛いので、次のシェルコマンドで、1分間隔で状態を確認してみました。

~~~
while /bin/true; do date; bx cs workers mycluster1; sleep 60; done
~~~


クラスタ起動のコマンド実行から約４分後です。 ペンディング状態です。

~~~
Wed Aug 30 22:34:08 UTC 2017
OK
ID                                                 Public IP   Private IP   Machine Type   State               Status   
kube-hou02-paeee5dab8309043bfba51397815699c25-w1   -           -            free           provision_pending   Waiting for master to be deployed   
~~~


約11分後 プロビジョニングが始まりました。

~~~
Wed Aug 30 22:41:33 UTC 2017
OK
ID                                                 Public IP   Private IP   Machine Type   State          Status   
kube-hou02-paeee5dab8309043bfba51397815699c25-w1   -           -            free           provisioning   -   
~~~

約15分後 ワーカーノードに、Public IPアドレスが付与されました。

~~~
Wed Aug 30 22:44:44 UTC 2017
OK
ID                                                 Public IP         Private IP      Machine Type   State          Status   
kube-hou02-paeee5dab8309043bfba51397815699c25-w1   184.172.250.175   10.77.155.109   free           provisioning   Waiting for transactions to complete: Service setup   
~~~

約32分後 dockerがインストール

~~~
Wed Aug 30 23:01:49 UTC 2017
OK
ID                                                 Public IP         Private IP      Machine Type   State           Status   
kube-hou02-paeee5dab8309043bfba51397815699c25-w1   184.172.250.175   10.77.155.109   free           bootstrapping   Installing docker  
~~~

約42分後 kubectl の環境が設定

~~~
Wed Aug 30 23:11:27 UTC 2017
OK
ID                                                 Public IP         Private IP      Machine Type   State           Status   
kube-hou02-paeee5dab8309043bfba51397815699c25-w1   184.172.250.175   10.77.155.109   free           bootstrapping   Configuring Kubectl CLI 
~~~

約43分後 Calico ネットワークの設定実行

~~~
Wed Aug 30 23:13:35 UTC 2017
OK
ID                                                 Public IP         Private IP      Machine Type   State           Status   
kube-hou02-paeee5dab8309043bfba51397815699c25-w1   184.172.250.175   10.77.155.109   free           bootstrapping   Configuring Calico Networking   
~~~

約45分後 ワーカーノード デプロイ終了

~~~
Wed Aug 30 23:15:42 UTC 2017
OK
ID                                                 Public IP         Private IP      Machine Type   State      Status   
kube-hou02-paeee5dab8309043bfba51397815699c25-w1   184.172.250.175   10.77.155.109   free           deployed   Deploy Automation Successful 
~~~

約47分後 利用可能状態

~~~
Wed Aug 30 23:16:46 UTC 2017
OK
ID                                                 Public IP         Private IP      Machine Type   State    Status   
kube-hou02-paeee5dab8309043bfba51397815699c25-w1   184.172.250.175   10.77.155.109   free           normal   Ready   
~~~

起動が完了すると、Bluemix のコンソール画面でも、準備完了と表示される様になります。

![スクリーンショット 2017-08-31 9.20.26.png](https://qiita-image-store.s3.amazonaws.com/0/42829/323f82a9-cd77-fe96-76fc-7f7f81eec40a.png "スクリーンショット 2017-08-31 9.20.26.png")


## kubectlコマンドの実行環境設定

k8sのクラスタ環境を操作するために、設定をダウンロードして環境変数をセットします。 次のコマンドで設定情報をダウンロードします。

~~~
bx cs cluster-config mycluster1
~~~

実行結果として、次の様な表示があるので、コピペして、環境変数を設定します。これで、kubectlコマンドは、BluemixのK8sクラスタのmycluster1に対して操作できる様になります。 

~~~
export KUBECONFIG=/home/vagrant/.bluemix/plugins/container-service/clusters/mycluster1/kube-config-hou02-mycluster1.yml
~~~


kubectl の 動作を確認してみます。 次の様にワーカーノードが、1個表示されていれば、作業成功です。 フリー版ではワーカーノード数は１に制限されているので追加できません。

~~~
kubectl get nodes
NAME            STATUS    AGE
10.77.155.109   Ready     21m
~~~


## 既成Dockerコンテナのデプロイ

kybectl を使うと、Docker Hub に登録されている Dockerコンテナイメージを利用する事ができます。 そこで、Nginxのウェブサーバーを起動してみます。

~~~
kubectl run nginx --image=nginx:1.11.3
~~~


デプロイされているか、次のコマンドで確認します。

~~~
kubectl get deployment
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx     1         1         1            1           1m
~~~

PODの状態を確認します。 STATUSは Running　ですから、起動しているのが解ります。 問題があれば、STAUSが Errorなどと表示されます。

~~~
kubectl get pod
NAME                    READY     STATUS    RESTARTS   AGE
nginx-752720876-8kk21   1/1       Running   0          1m
~~~

この時点でサービスとしては、nginxは、まだ提供されていない事が、次のコマンドで確認できます。

~~~
kubectl get services
NAME         CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   10.10.10.1   <none>        443/TCP   1h
~~~


## 外部への公開

外部へ公開するために、次のコマンドを実行します。 フリー版k8sでは、NodePortを指定します。

~~~
kubectl expose deployment nginx --port 80 --type NodePort
service "nginx" exposed
~~~

サービスとして、公開されていることを確認します。 下記の結果から、nginx の EXTERNAL-IP は、<nodes> となっており、nodeのパブリックIPアドレスが、外部向けのIPアドレスである事が解ります。 また、 PORTは、80:32209 となっており、nginxコンテナの80ポートを 32209に変換している事が解ります。

~~~
kubectl get services
NAME         CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes   10.10.10.1     <none>        443/TCP        1h
nginx        10.10.10.243   <nodes>       80:32209/TCP   8s
~~~


nodeのパブリックIPアドレスは、次のコマンドで確認できます。

~~~
bx cs workers mycluster1
OK
ID                                                 Public IP         Private IP      Machine Type   State    Status   
kube-hou02-paeee5dab8309043bfba51397815699c25-w1   184.172.250.175   10.77.155.109   free           normal   Ready  
~~~

curlコマンドで、ワーカーノードのパブリックIP をアクセスすることで、nginxコンテナのサービスにアクセスする事ができます。

~~~
curl http://184.172.250.175:32209/
<!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>
~~~



# 自作したDockerコンテナをk8sクラスタ環境へデプロイする方法

今度は、自分のDocker開発環境で、作ったアプリをk8sのクラスタ環境へデプロイしてみます。イメージを図にすると次の様になります。 ローカル環境では、dockerコマンドを利用して、Bluemix k8s のリモートへデプロイする場合は、kubectl コマンドを利用します。


![スクリーンショット 2017-08-31 13.07.46.png](https://qiita-image-store.s3.amazonaws.com/0/42829/4adf0188-3168-5305-788b-e0c8095e0fde.png "スクリーンショット 2017-08-31 13.07.46.png")


## Node.jsのサンプリアプリの開発
サンプル・アプリとして node の アプリケーション・ジェネレーターで作った雛形アプリを利用します。

最初に、ジェネレーターをインストールして、パスを有効にします。

~~~
npm install express-generator -g
ndenv rehash
~~~

アプリを生成するディレクトリを作成して、移動します。

~~~
mkdir k8s-docker-deploy
cd k8s-docker-deploy
~~~

次のコマンドで、もっともシンプルなアプリを生成します。

~~~
vagrant@vagrant-ubuntu-trusty-64:~/k8s-docker-deploy$ express --view=pug myapp

   create : myapp
   create : myapp/package.json
   create : myapp/app.js
   create : myapp/public
   create : myapp/routes
   create : myapp/routes/index.js
   create : myapp/routes/users.js
   create : myapp/views
   create : myapp/views/index.pug
   create : myapp/views/layout.pug
   create : myapp/views/error.pug
   create : myapp/bin
   create : myapp/bin/www
   create : myapp/public/javascripts
   create : myapp/public/images
   create : myapp/public/stylesheets
   create : myapp/public/stylesheets/style.css
~~~


## ロカール環境でnodeアプリを起動

次のコマンドを実行することで、ディレクトリを移動して必要なモジュールをイントールします。

~~~
$ cd myapp  &&  npm install
~~~

デバックモードで起動します。

~~~
$ DEBUG=myapp:* npm start
~~~

これで、nodeのアプリが、自分のOSの上動作していますから、curl http://localhost:3000/ とすることで、このアプリのウェブページへアクセスする事ができます。
仮想マシンの外からアクセスする場合には、次の部分にVagrantfile にスタティックにIPアドレスを設定しているので、そのアドレスを使ってアクセスします。

~~~file:Vagrantfile
     4	Vagrant.configure("2") do |config|
     5	  config.vm.box = "ubuntu/trusty64"
     6	  config.vm.network "public_network", ip: "192.168.1.88", bridge: "en0: Ethernet"
~~~


## コンテナのビルド
コンテナをビルドするためのDockerfileを作成します。 

~~~file:Dockerfile
FROM ubuntu
RUN apt-get update
RUN apt-get install curl -y
RUN curl -sL https://deb.nodesource.com/setup_6.x | /bin/bash -
RUN apt-get install nodejs -y
ADD ./myapp /app
ENV NODE_ENV development
EXPOSE 3000
CMD ["node", "/app/bin/www"]
~~~

次のコマンドで、コンテナをビルドします。

~~~
docker build -t express-app . 
~~~

ビルドしたコンテナは、ローカルのリポジトリへ登録されます。このイメージは後に、Bluemixのレジストリへ登録します。

~~~
docker images
REPOSITORY                                       TAG                 IMAGE ID            CREATED             SIZE
express-app                                      latest              a4b2d6930e8b        38 seconds ago      265MB
~~~



## コンテナでの実行

レジストリへ登録する前に、ローカル環境のDockerコンテナとしてテストします。 このコマンドで、ロカール環境に 3000番ポートでサービスがオープンします。

~~~
docker run -p 3000:3000 -t express-app
~~~

先ほどと同様に、curl http://localhost:3000/ でコンテナのアプリへアクセスする事ができます。


## Bluemixのリポジトリへ登録

リポジトリへ登録するために、Bluemix CLI コマンドのプラグインを追加します。

~~~
bx plugin install container-registry -r Bluemix
~~~

インストールしたプラグインを確認するには、次のコマンドです。 応答結果の最後の行のプラグインのサービスは終了しました。

~~~
bx plugin list

Listing installed plug-ins...

Plugin Name          Version   
container-registry   0.1.183   
container-service    0.1.292   
IBM-Containers       1.0.1058   
~~~


登録する前に、レジストリに自分用のネームスペースを確保します。 全体で一意の必要があるので、失敗したらネームスペース名を変更して再チャレンジします。

~~~
bx cr namespace-add [your namespace]
~~~

成功したら、次の様に確認しておきます。

~~~
bx cr namespace-list
Listing namespaces...

Namespace   
maho  <--- 登録した自分のネームスペース
~~~


ここから、ローカルのDockerイメージにタグをつけて、Bluemixのリポジトリサービスへ登録します。
レジストリの名前は、registry.[loacation].bluemix.net/[your namespace]/[your application] となります。 固有の名前に置き換えてタグ付けします。

~~~
docker tag express-app registry.ng.bluemix.net/maho/express-app
~~~

Bluemixリポジトリサービスへ登録

~~~
docker push registry.ng.bluemix.net/maho/express-app
~~~

登録されたイメージの確認です。 結果のVULNERABILITY STATUSは、最初は、unknown になっていますが、時期にスキャンが実行されて結果を表示する様になります。

~~~
$ bx cr image-list
Listing images...

REPOSITORY                                     NAMESPACE   TAG      DIGEST         CREATED       SIZE     VULNERABILITY STATUS   
registry.ng.bluemix.net/maho/express-app       maho        latest   e39032a741f8   1 hour ago    110 MB   OK   
~~~


## Bluemix k8s環境で実行

リポジトリのコンテナ・イメージをデプロイします。

~~~
$ kubectl run express-app --image=registry.ng.bluemix.net/maho/express-app
deployment "express-app" created
~~~

デプロイ結果の確認です。

~~~
$ kubectl get deployment
NAME          DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
express-app   1         1         1            1           33s
~~~

ポッドの状態確認で、Running と動作している事がわかります。

~~~
$ kubectl get pod
NAME                           READY     STATUS    RESTARTS   AGE
express-app-3391203924-pnl6p   1/1       Running   0          40s
~~~

この時点では、サービスとして、外部へ公開されていません。

~~~
$ kubectl get services
NAME         CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes   10.10.10.1     <none>        443/TCP        5h
~~~

外部から参照できる様にするために、expose サブ・コマンドを実行します。

~~~
$ kubectl expose deployment express-app --port 3000 --type NodePort
service "express-app" exposed
~~~

これで、インターネットからアクセスできる様になりました。

~~~
$ kubectl get services
NAME          CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
express-app   10.10.10.2     <nodes>       3000:32016/TCP   1m
kubernetes    10.10.10.1     <none>        443/TCP          5h
~~~



## 外部からのアクセステスト

ワーカーノードのIPアドレスをメモっておきます。

~~~
$ bx cs workers mycluster1
OK
ID                                                 Public IP         Private IP      Machine Type   State    Status   
kube-hou02-paeee5dab8309043bfba51397815699c25-w1   184.172.250.175   10.77.155.109   free           normal   Ready   
~~~

curlコマンドで、インターネットからアクセスして確認する事ができます。

~~~
$ curl http://184.172.250.175:32016/;echo
<!DOCTYPE html><html><head><title>Express</title><link rel="stylesheet" href="/stylesheets/style.css"></head><body><h1>Express</h1><p>Welcome to Express</p></body></html>
~~~


## k8sダッシュボード画面の起動

Kubernetes v1.8 以降では、ダッシュボードにアクセスするために認証が必要になりました。 認証の方法は[【IBM Cloud k8s】WebUI (Dashboard)への認証方法のメモ](https://qiita.com/MahoTakara/items/fc2e3758d0418001b0a2)を参照してください。


仮想マシン上で kubectl proxy を起動します。 仮想マシンの設定ファイル Vagrantfile の中で、8001 と 3000　ポートをフォワードしているため、仮想マシンのホストとなっているパソコンからアクセスする事ができます。

~~~
kubectl proxy --address='0.0.0.0'
~~~

http://127.0.0.1:8001/ui でアクセスすると、次の画面が表示されます。

![スクリーンショット 2017-08-31 14.39.46.png](https://qiita-image-store.s3.amazonaws.com/0/42829/c5915ac3-79c8-1b93-ad77-246a7fc4b9d5.png "スクリーンショット 2017-08-31 14.39.46.png")



# 参考資料
(1) IBM Bluemix Container Service での単一コンテナーとスケーラブル・コンテナーの管理用 CLI リファレンス https://console.bluemix.net/docs/containers/container_cli_reference_cfic.html#container_cli_reference_cfic_deprecated