【初心者向け】無料Kubernetesでwordpressを構築してみたon IBM Cloud

こんにちは。torippy1024です。
はじめてQiitaを書きます。
今日は、コンテナって使ってみたいけど複雑でいまいちよくわからん・・・・・・という人向けに、無料で試せるコンテナオーケストレーションサービス Kubernetes on IBM Cloudの初心者向けお試し手順をご紹介します。
本手順では、IBM Cloud上でKubernetesサービスをデプロイし、その上でwordpressを動作させるまでを実行します。
対象読者としては、Kubernetesの概要について聞いたことはあるが、実機を操作した経験はなく、PodやServiceといった用語がどのようなもので、どのように動作しているかまでは知らない、というレベルの人を対象にしています。

## Kubernetes on IBM Cloudについて
Kubernetesについての説明はここでは省きます。
IBM Cloudでは、30日間という期間限定ながら(30日を超えると課金対象移行でなく強制削除)、Kubernetesを無料で使用することができます。
今日は、この無料Kubernetesを使用して30日間限定のwordpressを立ち上げることによって、コンテナとはどういうものか、どのように動作しているのか、を実感してみます。

## 今回構築する環境
今回構築する環境は、wordpressアプリケーション1PodとDBのコンテナ1Podを動作させるだけの極めて簡単な構成です。
しかし、Kubernetes初心者でPodって何？Serviceって何？という方にとっては、そもそも何をやっているか分からなくなってくる可能性もありますので、以下に今回構築する環境のアーキテクチャーを示します。
![20200802_k8sonIBMCloud.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684500/0df97dc9-3ad4-90ad-1d55-8aaf68230e8b.jpeg)

Kubernetesを構成する土台となるサーバーにはMaster NodeとWorker Nodeがあります。
ユーザーはAPI/CLIを通してMaster Nodeに指示を行い、Master NodeがWorker Nodeを管理します。Worker Nodeは、通常冗長化のため複数台用意しますが、無償Kubernetesでは2vCPU 4GBメモリーのサーバー1台のみです。
この上にKubernetesというコンテナオーケストレーションツールが動作しており、その上でPod(コンテナ機能を実装したもの)が作成され、Pod内のアプリケーションが動作しているという構成です。
Pod同士が通信を行う際は、Serviceによって通信ポリシーの制限を行います。
またServiceは、Pod上で動作しているアプリケーションApp(wordpress)を外部に公開するときにも使用します。

IBM CloudのKubernetes Serviceは、このMaster NodeやWorker Nodeの構築や設定を一通り終えた状態でユーザーに提供してくれるサービスです。ユーザーは、Kubernetesの構築作業に時間をかけることなく、すぐにKubernetes上でアプリケーションを動作させることに集中することができます。

## 前提条件
必要なものは以下です。
- IBM Cloudのアカウント
- クレジットカード(無料Kubernetesクラスター作成のために登録のみ必要)
- git、Docker、IBM Cloud CLIが使用できる作業端末

IBM Cloudのサイトを見ると、IBM Cloud CLIが使用できるOSは、Windows 10 ProまたはMacまたはLinuxと書かれています。
Windows 10 Homeは動作対象とされていませんが、私の環境では問題なく動作しました。

またIBM Cloud CLIをインストールする際、前提ソフトウェアとして以下も一緒にインストールされます。
- git
- Docker Desktop

#### ～ちょっと余談～
> Windows 10 Homeが動作確認対象とされていないのは、IBM Cloud CLIが前提条件としているDocker DesktopがWindows 10 Homeで未サポートだったことが理由だと考えられます。
> ただ2020年8月現在、Windows 10 HomeでもDocker Desktopは動作する見込みです。
> Docker Desktop for Windowsがバックエンドで使用しているWSL2が、これまでWindows 10 Homeでは未サポートだったがサポートされるように変更されたためです。

## IBMアカウント作成
まずIBM Cloudアカウントを以下から作成してください。
パスワードは8文字以上で、大文字アルファベット、小文字アルファベット、数字を全て含む必要があります。後でCLIログインする際に手動入力するので、自分で覚えきれないような複雑で長いパスワードを設定してしまうと後で大変かもしれません。
https://cloud.ibm.com/registration
![pic_01.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684500/2ef2e616-4b1b-19e3-f510-8f06379d5a91.jpeg)

アカウントの作成が終わったら、クレジットカード情報を登録します。
ログイン後のダッシュボード画面から「管理」-「アカウント」-「アカウント設定」を選択して「クレジット・カードの追加」を選択してください。
クレジットカード情報を登録し、アカウント・タイプが「従量課金」になると、無償のKubernetesが使用可能となります。

![pic02.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684500/c8f31dbb-7be1-56b9-9469-a94b45f28b09.jpeg)

クレジットカード情報登録はためらわれるところがあるのですが、30日間の無償期間が終了した後は自動削除されるため、通常請求が行われることはありません。
また「従量課金プラン」になると、登録から30日間限定で$200分の無償クレジットが付与されるので、これも覚えておきましょう。

## IBM Cloud CLIインストール
次に、IBM Cloudのサイトに書かれているコマンドを実行してIBM Cloud CLIをインストールします。
Windowsと、MacまたはLinuxでコマンドが異なります。
gitとDockerがインストールされていない場合、このIBM Cloud CLIのインストール中に自動でインストールされます。

MacまたはLinuxの場合のコマンド：

```
$ curl -sL https://ibm.biz/idt-installer | bash
```

Windowsの場合のコマンド(Powershellを管理者権限で開いて実行してください)：

```
$ [Net.ServicePointManager]::SecurityProtocol = "Tls12, Tls11, Tls, Ssl3"; iex(New-Object Net.WebClient).DownloadString('https://ibm.biz/idt-win-installer')
```


※Windows 10 Homeの場合、Docker Desktopのインストール中にWSL2をインストールされていないとエラーが表示されることがあります。
その場合、以下URLからWSL2をインストールし、OS再起動するとDocker Desktopのインストールが継続されます。
https://docs.microsoft.com/ja-jp/windows/wsl/wsl2-kernel

※※IBM Cloud CLIとDockerを同時にインストールする場合、Dockerインストールの途中でOSが再起動が発生します。その場合、IBM Cloud CLIインストールは途中で中断してしまいますので、OS再起動後、再度IBM　Cloud CLIコマンドを実行するようにしてください。


IBM Cloud CLIインストール後、OS再起動を求められるので、再起動します。

再起動後、以下のコマンドを実行してヘルプが表示されればインストールは完了です。

```
$ ibmcloud dev help
```

## 無償Kubernetesクラスターの作成
無事にアカウントを作成し、IBM Cloud CLIを端末にインストールすることができたら、無償Kubernetesクラスターを作成してみましょう。
IBM CloudのGUIで操作します。
https://cloud.ibm.com/login

IBM Cloudにログインし、ダッシュボード画面から「カタログ」-「サービス」を選択し、「カテゴリー」内の「コンテナ」にチェックを入れます。
Kubernetes Serviceが表示されるので、これを選択します。

![pic03.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684500/e9984ff1-c4df-4c7b-926b-9a06adb167b8.jpeg)


Kubernetes作成のためのパラメーターを入力する画面に遷移します。といっても、プランを「無料」と選択すれば、あとはデフォルトで作成してしまって構いません。

|  項目名  |  値  |
| ---- | ---- |
|  プランの選択  |  無料  |
|  オーケストレーション・サービス  |  kubernetes  |
|  クラスター名  |  mycluster-free  |
|  リソースグループ  |  Default  |

![pic007.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684500/7768cc44-c267-0413-554f-6f0c9f97ca02.jpeg)

作成後、準備中画面に遷移するのでしばらく待機します。最短数分～最長数十分くらいで作成は完了すると思います。気長に待ちましょう。
遷移先の画面にIBM Cloud CLIツールに関する説明が表示されますが、すでにインストールしているため作業は不要です。


## IBMCloudログイン
ターミナル(又はコマンドプロンプト)を開き、以下のコマンドを実行してCLIでログインします。実行後、メールアドレスとパスワードの入力が求められるので、認証情報を入力します。

```
$ ibmcloud login -a cloud.ibm.com -r us-south -g Default

Email> yourmailladdress@sample.com

Password>
認証中です...
OK
```

-rオプションで指定するのはKubernetesが動作するリージョン(地域)です。基本的にus-southに作成されるはずですが、もしus-southリージョンにKubernetesが存在しない場合、IBM Cloudのリソース・リスト画面でKubernetesが動作しているロケーションを特定し、そのロケーションがどのリージョンに属しているかを調べてみてください。

以下のコマンドを実行して、Kubernetesコンフィグ情報を取得します。

```
$ ibmcloud ks cluster config -c mycluster-free
:
(メッセージが表示されることがあるが記載を省略)
:
OK
mycluster-free の構成は正常にダウンロードされました。

mycluster-free のコンテキストを現在の kubeconfig ファイルに追加しました。
これで、クラスターに対して「kubectl」コマンドを実行できます。例えば、「kubectl get nodes」を実行します。
$
```
上記のように表示されれば成功です。
Kubernetesコンフィグ情報について詳しく知りたい場合は以下を参照してください。
https://cloud.ibm.com/docs/containers?topic=containers-cli-plugin-kubernetes-service-cli#cs_cluster_config


## Kubernetes情報取得
まず、以下コマンドを実行して、Kubernetesのクラスター情報が取得できることを確認します。

```
$ ibmcloud ks cluster get -c mycluster-free
```

クラスター名やIDの他、Kubernetesが動作しているロケーションやステータス、リソースグループなどが表示されることを確認します。

続いて、以下コマンドを実行して、Worker Nodeの情報を取得します。

```
$ ibmcloud ks worker ls --cluster mycluster-free
ID                                        パブリック IP     プライベート IP   フレーバー  状態     状況    ゾーン  バージョン
kube-XXXXXX-myclusterfr-default-00000012  184.173.46.245  10.76.216.46     free      normal   Ready   hou02  1.17.9_1532
```

IDのXにはランダムな小文字アルファベットや数字が入ります。
上記で表示された<b>「パブリックIP」</b>はどこかにメモしておきます。外部からKubernetes内のアプリケーションに接続する際に指定するIPアドレスとなります。

## wordpressアプリケーションのデプロイ
それでは、Kubernetes上にwordpressをデプロイしてみましょう。
デプロイ対象となるのはアプリケーションが動いているコンテナである「Pod」と、Podの通信ポリシーを設定する「Service」です。
冗長化した複数のPodをまとめてデプロイするためのデプロイ単位を「Deployment」と言います。

仮想化の世界で例えると、PodがVM、ServiceがVLAN、DeploymentがVMクラスターのようなイメージで考えるとよいと思います。(厳密には異なりますが・・・・・・)

以下のコマンドを実行して、wordpressが入ったコンテナ(Pod)「wordpress」、MariaDBが入ったコンテナ(Pod)「mariadb」をデプロイし、それぞれのアプリケーションを接続するためのServiceをデプロイします。

```
$ kubectl run wordpress --image=wordpress:latest
deployment.apps/wordpress created
```
上記を実行すると、上記コマンドは後日削除されるため非推奨であるとエラーメッセージが出力されますが、ここでは無視してください。

```
$ kubectl run mariadb --image=mariadb:latest --env MYSQL_ROOT_PASSWORD=P@ssw0rd --env MYSQL_DATABASE=wordpress --env MYSQL_USER=wpuser --env MYSQL_PASSWORD=wppassword
deployment.apps/mariadb created
```
同じくエラーメッセージが出力されますが、無視してください。データベース名やMYSQLユーザ名、パスワード等は自分で変更しても構いません。

```
$ kubectl expose deployment wordpress --type=NodePort --port=80 --target-port=80 --name=wordpress --labels="app=wp"
service/wordpress exposed
```

```
$ kubectl expose deployment mariadb --type=ClusterIP --port=3306 --target-port=3306 --name=mariadb --labels="app=wp"
service/mariadb exposed
```

問題なくデプロイが完了したか、コマンドを実行して状態を確認します。

Deploymentの確認コマンド

```
$ kubectl get deploy
NAME        READY  UP-TO-DATE  AVAILABLE  AGE
maridb      1/1    1           1          4m8s
wordpress   1/1    1           1          4m25s
```
「wordpress」と「mariadb」のDeploymentが動作していることを確認します。

Podの確認コマンド

```
$ kubectl get pod
NAME                       READY  STATUS   RESTARTS  AGE
mariadb-XXXXXXXXX-XXXXX     1/1    Running  0         5m6s
wordpress-XXXXXXXXX-XXXXX   1/1    Running  0         5m16s
```
「wordpress-XXXXXXXXX-XXXXX」と「mariadb-XXXXXXXXX-XXXXX」のPodが動作していることを確認します。

Serviceの確認コマンド

```
$ kubectl get svc
NAME        TYPE          CLUSTER-IP      EXTERNAL-IP  PORTS(S)       AGE
kubernetes  Cluster-IP    172.21.0.1      <none>       443/TCP        61m
mariadb     Cluster-IP    172.21.224.113  <none>       3306/TCP       7m10s
wordpress   NodePort      172.21.196.71   <none>       80:32049/TCP   7m17s
```
「kubernetes」、「wordpress」、「mariadb」のServiceが動作していることを確認します。
ここで、「wordpress」、「mariadb」が先程コマンドを実行して作成したServiceです。「Kubernetes」はデフォルトで稼働しているServiceです。

「wordpress」の「PORT(S)」のみ、2つのポートが表示されていることが確認できます。
:で区切られた右のポートが外部公開されているポート、左のポートがポート変換されてwordpressに接続されるときに使用するポートを表しています。

上記で出力された<b>「wordpress」の「PORT(S)」と「mariadb」の「Cluster-IP」</b>はメモしておきます。後で、インターネット接続を行うときや、wordpressの初期設定を行う際に使用します。

どうやら問題なくデプロイされているようです。
では、実際にwordpressが使えることを外部から接続して試してみましょう！

## 外部からの接続確認
「Kubernetes情報取得」で確認した「パブリックIP」、「wordpressアプリケーションのデプロイ」で確認した「PORT(S)」をブラウザで指定して、インターネットからwordpressアプリケーションに接続してみます。
以下が例です。

```
http://184.173.46.245:32049
```

![pic04.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684500/d5f951c4-121c-bc48-462f-ee074a231ce7.jpeg)


wordpressの初期設定画面が表示されました。
これだけだと「wordpress」コンテナだけの確認にしかなっていませんので、「mariadb」コンテナも動作し接続できるのか確認します。

「日本語」を指定して「Continue」を選択し、次の画面で「さあ、始めましょう！」を選択します。
wordpress初期設定画面で以下を入力して「送信」を選択し、wordpressとmariadbが通信できることを確認します。

|  項目名  |  値  |
| ---- | ---- |
|  データベース名  |  wordpress  |
|  ユーザー名  |  wpuser  |
|  パスワード  |  wppassword  |
|  データベースのホスト名  |  「kubectl get svc」で確認した「mariadb」ServiceのCluster-IP  |
|  テーブル接頭辞  |  wp_  |

![pic05.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684500/5727be04-17d4-e6e3-ccf8-fe81b10a94b3.jpeg)

問題なく通信ができれば以下の画面が表示されるはずです。

![pic06.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684500/497da323-a141-8964-633e-c12867169e1e.jpeg)


以上で動作確認は完了しました。引き続き「インストール実行」を選択し、ブログタイトルやパスワードを設定し、ブログが開設できるか確認してみてもよいと思います。
ただし、この無償Kubernetesは30日間で自動削除されるため、実際にブログサイトとして運用することは困難です。

## DeploymentやServiceの削除
作業が終わった後は、作成したDeploymentとServiceを削除します。
放っておいても30日後に自動削除されますが、安易なパスワードを設定したwordpressをインターネット上に公開しておくのは推奨されません。

以下を入力してwordpressとmariadbを削除します。

```
$ kubectl delete deploy wordpress
deployment.apps "wordpress" deleted
```

```
$ kubectl delete deploy mariadb
deployment.apps "mariadb" deleted
```

```
$ kubectl delete svc wordpress
service "wordpress" deleted
```

```
$ kubectl delete svc mariadb
service "mariadb" deleted
```


実行後、以下コマンドでDeploymentとServiceが削除されたことを確認します。

```
$ kubectl get deploy
No resource found in default namespace.
```

```
$ kubectl get svc
NAME        TYPE          CLUSTER-IP      EXTERNAL-IP  PORTS(S)       AGE
kubernetes  Cluster-IP    172.21.0.1      <none>       443/TCP        70m
```

Deploymentが表示されず、kubernetes用のService1行しかServiceが出力されなければ作業完了です。
お疲れさまでした。

## 最後に
今回実行したのは、wordpressをデプロイして使える状態にする本当に単純な作業です。
podレプリカを作成して冗長化したり、デプロイパラメータをyamlファイルに記載したりすることはあえて手順としては入れませんでした。
興味を持った方は、せっかく30日間の$200無償クレジットもあることですし、色々試してみることをお勧めします。