アプリケーションをKubernetes環境にデプロイする(GUI)

# はじめに
ローカルPC(mac)で開発したJavaコードのアプリを，サーバー環境(Kubernetes)にデプロイする手順を追ってみます。

**注意:**
DockerやKubernetesを触った経験のある方にとっては "当たり前の内容" です

知識のある方は，本投稿はさっと読み飛ばして，[Microservice Builderの活用記事](https://qiita.com/capsmalt/items/3a03d1f01534aece1b0c)を参照してみてください。
CI/CDを開発時点で組込み，Kubernetes環境に継続的にデプロイし続けることを支援する面白いツールです。


# 環境
## 開発端末(mac)
- OS
    - macOS High Sierra V10.13.1
- Docker
    - [Docker for Mac](https://store.docker.com/editions/community/docker-ce-desktop-mac) V17.09.1
- Terminal <== なんでもOK
    - [iTerm2](https://www.iterm2.com) V3.0.15
- 開発ツール
    - bxコマンド ([IBM Cloud CLI Installer](https://console.bluemix.net/docs/cli/reference/bluemix_cli/all_versions.html#ibm-cloud-cli-installer-all-versions))
    - devプラグイン (bxコマンド導入後に `$ bx plugin install dev` でOK)

## デプロイ先環境(Kubernetes)
- OS
    - Ubuntu Server 16.04 LTS
- Kubernetes
    - IBM Cloud Private V2.1.0 (Community Edition, シングルインスタンス)
    - (参考) ["IBM Cloud Private: Kubernetesをオンプレミス(IaaS)に導入してみる"](https://qiita.com/capsmalt/items/d15055ab3cb423d2d7ae)

以降，IBM Cloud PrivateをICPと呼びます

# アプリケーションの開発
開発環境(mac)で実施します。
この項目のゴールは， **アプリケーションを組込んだDockerイメージを作成すること** です。
※既にDockerイメージの用意がある場合は，*アプリケーションのデプロイ* に進んでください。

必要な作業は，次の2ステップです。
1) アプリを開発
2) Java EEランタイムと合わせてDockerイメージを作成する


今回はMicroservice Builderというツールを使ってコマンドを数回叩くだけで作成してみます。

**以下の3つのコマンド実行します。**

```text
先にDocker for Macを起動させておく

$ bx dev create  // インタラクティブにアプリタイプを選択しながら雛形プロジェクトを作成
$ bx dev build   // アプリのビルド
$ bx dev run     // Dockerコンテナでアプリ動作 (このタイミングでDockerイメージが作成される)
```

(手順の簡単な説明と，スクリーンショットを確認したい場合は，[こちら](https://qiita.com/capsmalt/items/3a03d1f01534aece1b0c#新規アプリを作る-bx-dev-createbuildrun)を参照ください。)

コンテナ上で稼働中のアプリを確認
http://localhost:9080/APPLICATION_NAME/v1/example

私の場合は，capsmaltapp2という名前でアプリを作成したので，以下のURLです。
http://localhost:9080/capsmaltapp2/v1/example

**アプリ動作を確認したら，`Ctrl + c` でフォアグラウンドプロセスをkillします。**

# アプリケーションのデプロイ
この項目のゴールは，**DockerイメージをKubernetes環境にデプロイし，外部からアクセスできるようにすること** です。

以下，適宜スクリーンショットを使って順に説明します。

1) DockerイメージをICP上にpush
2) Deploymentを作成
3) Serviceを作成


## 1) DockerイメージをICP上にpush
ICPのprivate image repository(Dockerイメージを保管するプライベートリポジトリ)を使用するためのフォーマットは以下です。

Dockerイメージのフォーマット:  `<cluster_CA_domain>:8500/namespace/imagename`
(参考) [Pushing and pulling images](https://www.ibm.com/support/knowledgecenter/SSBS6K_2.1.0/manage_images/using_docker_cli.html)

※cluster_CA_domainのデフォルト値は，`mycluster.icp`
※namespaceや，imagenameは任意でOK
(今回は，`namespace = capsmaltorg`，`imagename = capsmaltapp2:v1`とします)

(補足) namespaceの指定でロールベースアクセス制御が可能です。つまり，ここで指定したnamespaceへのアクセス権限があるUser(Team)のみがイメージ操作ができるように構成できます。

**ローカル環境(mac)のhostsにmycluster.icpを設定します。**

```text
$ vi /etc/hosts

以下を追記
10.132.75.83    mycluster.icp  // ICPのインストール環境のIP
```

**Dockerイメージに対してフォーマットに沿った名前とタグを設定します。**


```text
$ docker tag capsmaltapp2 mycluster.icp:8500/capsmaltorg/capsmaltapp2:v1
```

確認します。


```text
$ docker images

REPOSITORY                                             TAG                 IMAGE ID            CREATED             SIZE
capsmaltapp2                                           latest              07eab9252b01        7 minutes ago       420MB
mycluster.icp:8500/capsmaltorg/capsmaltapp2            v1                  07eab9252b01        7 minutes ago       420MB
```

bx dev create/build/runで作ったアプリのDockerイメージは，`capsmaltapp2:latest`でしたが，
同じIMAGE IDで，`mycluster.icp:8500/capsmaltorg/capsmaltapp2:v1`を用意できたことが分かります。

**private image repositoryにログインします。**

```text
$ docker login mycluster.icp:8500

※ログイン情報の初期設定は，admin/adminです。(ICPインストール時にPW変更している場合は読み替えてください)
```

**Dockerイメージをpushします。**

```text
$ docker push mycluster.icp:8500/capsmaltorg/capsmaltapp2:v1
```


## 2) Deploymentを作成
コンテナをまとめたPodを管理するDeploymentを作成します。

**ICPコンソールにログインします。**
https://10.132.75.83:8443
※ICPインストール時に設定したログイン情報を使用します。デフォルト値は，admin/adminです。

**[メニュー] > [Workloads] > [Deployments] > [Create Deployment] をクリックします。**

<img width="721" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/69447/8592277f-e30b-a1e4-d4fb-c821a126ee2c.png">


図のようなポップアップが表示されます。
<img width="501" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/69447/6bcbc253-5312-fb53-243d-8be5d48e1288.png">

**以下項目の値を入れていきます。(他はデフォルト値)**

|Deployment作成時の項目|値|説明|
|:--|:--|:--|
|[General] > [Name]|capsmaltapp2-deployment|任意のDeployment名|
|[Container settings] > [Name]|capsmaltapp2-container|任意のコンテナ名|
|[Container settings] > [Image]|mycluster.icp:8500/capsmaltorg/capsmaltapp2:v1|private image repository内のイメージ名|

**ポップアップ下部の [Create] をクリックします。**
<img width="98" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/69447/c97d0152-e413-15d7-569b-72c89576325e.png">


## 3) Serviceを作成
外部からのアクセスを可能にするServiceを作成します。

**ICPコンソールにログインします。**

**[メニュー] > [Workloads] > [Services] > [Create Service] をクリックします。**

<img width="630" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/69447/4da45f05-24ff-2c5d-a7a4-836d5766265b.png">


図のようなポップアップが表示されます。
<img width="503" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/69447/089d94bc-2ea5-bbbc-48e7-4731fd1c2540.png">

**以下項目の値を入れていきます。(他はデフォルト値)**

|Serivice作成時の項目|値|説明|
|:--|:--|:--|
|[General] > [Name]|capsmaltapp2-service|任意のService名|
|[General] > [Type]|NodePort|WorkerノードのIPを使ってアクセス可能にする設定|
|[Ports] > [Name]|port|任意のPort設定名|
|[Ports] > [Port]|9080|ローカルからPod接続する際のポート|
|[Ports] > [Target Port]|9080|Pod内の規定ポート(Java EEランタイムが稼働)|
|[Selectors] > [Selector]|app|DeploymentのLabelのKey(未設定の場合のデフォルトはapp)|
|[Selectors] > [Value]|capsmaltapp2-deployment|DeploymentのLabelのValue(未設定の場合のデフォルトはDeployment名)|

(補足) ServiceのSelectorでDeploymentのLabelのKey/Valueを指定することで，ルーティングを制御できます
(補足) Deploymentで，nodeSelectorを設定することで，特定のHostでPodを動作するように制御できます

**ポップアップ下部の [Create] をクリックします。**
<img width="98" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/69447/d4ccbce6-03f5-e47c-d9bb-8f5517d13d5a.png">

以上で，Kubernetes上に外部からアクセスできる形でアプリケーションをデプロイできました。

# GUIでアプリケーション稼働確認
ICPのコンソール画面から，リンクを辿ってアプリケーション稼働を確認します。

**ICPコンソールにログインします。**

**[メニュー] > [Workloads] > [Services] > [capsmaltapp2-service] をクリックします。**
<img width="572" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/69447/f081ad9b-86a7-c2a2-e864-478bba3a62a8.png">

**図の [Node port欄のリンク] をクリックします。**
`port 32507/TCP` の部分です。(※port番号は実施者ごとに異なる)
<img width="901" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/69447/8309f114-896b-e28c-040f-d8dc4685e7b8.png">

WebSphere Liberty (Java EEアプリケーション・サーバー)のWelcome画面が開きます。
<img width="643" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/69447/148e5b64-cf64-c5f6-d8c0-850bcfc64e57.png">

**WebSphere Liberty上で稼働するアプリケーション(capsmaltapp2)を確認します。**
URLのパスに，`capsmaltapp2/v1/example`と付加します。
例) `http://10.132.75.83:32507/capsmaltapp2/v1/example`
<img width="712" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/69447/cfacb396-9395-af44-ee35-6d808b21d2fa.png">



# まとめ
ローカル環境(mac)でアプリを含んだDockerイメージを用意して，Kubernetes環境にデプロイする手順を紹介しました。
もちろん，GUI操作はコンソールによって違います。

Kubernetesでコンテナを管理する最もベーシックな方法は，
**Dockerイメージつくって，Deployment作って，Service作る** ということを理解して頂ければと思います。

これでとりあえずはサービス公開ができます。


今回はド基本なので面白みはまったく無かったと思いますが，
いくつか記事を投稿しているので，何らかの形で誰かのお役に立てれば幸いです。