これからkubernetesを学ぶためのIBM Cloudとパソコンを使った学習環境構築

# 今回やりたいこと
IBM Cloud上の仮想マシンと手元のパソコンの両方でkubernetes(略称 k8s)を動かし、IBM Cloud上の仮想サーバーで稼働するk8s環境をコントローラーノード、パソコン上で稼働するk8s環境をワーカーノードとして、コントローラーノードからワーカーノードに、Nginxをデプロイしてサンプルページを見れるようにすること。

## きっかけ
先日、ご縁あって日本IBMの「コンテナ共創センター」の勉強会にパネリストとして出させていただきました。その際に、「自分で環境作って学ぶ」と言いまして、実際に自分で学んだものを教材として書き起こし、勤務先の講義で使っているのですが、ここは１つIBM Cloudで最も安価な「一時仮想サーバー」を使い、Raspberry Piや手元のパソコン、一般のご家庭にある自宅サーバー上のk8s環境をつなげてみよう、というわけです。

# 用意するもの
IBM Cloudと手元のパソコン、両方に仮想サーバーを用意します。
## IBM Cloud側
IBM CloudでIaaSを使う場合、柔らか層本に目を通しておくと良いです。
https://ibm.ent.box.com/v/ibmcloud-yawaraka
### IBM Cloud上に仮想サーバーを作成
IBM Cloudで最も安い、IBM Cloud Virtual Server for Classicの「一時仮想サーバー」を使用しました。動作確認や検証といった作業に向いている仮想サーバーです。
仮想CPUが2vCPU、仮想メモリが4GB、ディスク25GB、OSに**Ubuntu Linux 20.04**を指定し、1時間あたり0.03ドルです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/ab5ba57b-c16c-8607-5aec-b6131fd2e247.png)

仮想サーバーが作成されると、次のように表示されます。パブリックIPは都度異なります。あとで使うので、メモしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/dddd490e-e9e5-7556-ebaf-c8ebc0482424.png)

青字で表記されているデバイス名をクリックします。作成した仮想サーバー情報が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/7fa5a3f3-ef9e-a937-56c1-6e985e73384b.png)

### 仮想サーバーのrootパスワードを確認
画面左側の「パスワード」をクリックし、仮想サーバーのrootパスワードを確認します。目玉のアイコンをクリックすることで、rootパスワードが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/fcbfc398-eca7-b591-a202-ce5216fbb587.png)

### セキュリティグループの設定
画面左上で「デバイス」をクリックします。
次に画面左側で、「セキュリティ」>>「ネットワーク・セキュリティ」>>「セキュリティ・グループ」で、仮想サーバーへのSSH接続の許可、またTCPでポート6443番と9443番にインバウンドで接続できるにしておきます。6443と9443は、k0sで使用するポートです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/87615b68-ce8f-d9a4-2e64-5900cbbb682f.png)

## パソコン側
手元のパソコンに、VirtualBoxを入れ、Ubuntu Mate 20.04の仮想マシンを用意しました。
VirtualBox上仮想マシンには、メモリを4GB割り当てています。
またホストオンリーアダプタで、固定IPアドレスとして、192.168.125.10 を割り振っています。
ホスト名は、ubuntu1vmとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/288ec572-0abe-c516-6cc1-bc45d34e9d33.png)
VirtualBox上仮想マシンには、OpenSSH-Serverをインストールしました。
```
sudo apt install openssh-server
```

パソコンで仮想マシンをあれこれ作成していじるときは、パソコンの物理メモリとして16GB以上、CPU 4コア以上、SSD 512GB以上を推奨します。新品のノートパソコンで、大体8万円台前半あたりから買えます。

# kubernetes(略称 k8s)ディストリビューションの選定 >> k0s
今回は、軽くてインストールが簡単で、低スペック低価格な環境でも十分に使えるMirantis社の「k0s」を使います。
https://www.mirantis.com/software/k0s/
公式ドキュメント
https://docs.k0sproject.io/

「k0s」はオンプレミスでkubernetesを用いたプライベートクラウドを構築する際も使うことができます。要求スペックが低いので、エッジサーバーや10万円以下のノートパソコン、安価なサーバーでも動き、個人的には使いやすいと思っています。

## Konnectivity
k0sではKonnectivityが最初から有効になっています。
KonnectivityはTCPレベルのプロキシで、コントローラーノードからワーカーノードを含むkubernetesクラスターへの通信を行います。コントローラーノードとワーカーノードを含むkubernetesクラスターの双方で、Konnectivityが有効になっていれば、コントローラーノードからワーカーノードにNginxなどのアプリケーションを簡単にデプロイできるわけです。
有名どころのクラウドサービスでは、Microsoft AzureのAzure Kubernetes Service(AKS)やIBM CloudのIBM Cloud Kubernetes Service(IKS)などでも使われています。

# 構築作業
コントローラーノードとワーカーノードの2つの環境で作業を行います。
## コントローラーノード(IBM Cloud側)
TeraTerm（Windows用)やターミナルアプリ(Mac)から、IBM Cloud上の仮想サーバーに、rootユーザーでSSH接続を行います。
### 作業用ユーザーの作成
rootユーザーで作業するわけにもいかないので、作業用のユーザー(例 worker1)を作成します。
次のコマンドを実行します。
```
adduser worker1
```
実行結果
```
Adding user `worker1' ...
Adding new group `worker1' (1001) ...
Adding new user `worker1' (1001) with group `worker1' ...
Creating home directory `/home/worker1' ...
Copying files from `/etc/skel' ...
New password:
Retype new password:
passwd: password updated successfully
Changing the user information for worker1
Enter the new value, or press ENTER for the default
        Full Name []:
        Room Number []:
        Work Phone []:
        Home Phone []:
        Other []:
Is the information correct? [Y/n] Y
```
Linuxなので、passwordは入力しても何も表示されません。
作成した作業用ユーザーに、sudo権限を付与します.
```
usermod -aG sudo worker1
```
一度ログアウトして、作成した作業用ユーザーでSSH接続しサーバーにログインします。
### k0sのインストールとコントローラーノードとして起動
次のコマンドを実行します。
```
curl -sSLf https://get.k0s.sh | sudo sh
```
実行結果
```
k0s is now executable in /usr/local/bin
```
設定ファイルを出力し、IBM Cloud上の仮想サーバーのパブリックIPを追記します。
次のコマンドを実行します。
```
k0s config create > k0s.yaml
nano k0s.yaml
```
spec:の下のapi:に含まれる
address:の下に、externalAddress: パブリックIPアドレス を追記します。
例 externalAddress: 165.192.xxx.xxx
追記後、保存します。Ctrl + Xを押して、Yを押すと保存して終了します。

次のコマンドを実行し、コントローラーノードとして起動します。
```
sudo mkdir /etc/k0s
sudo mv k0s.yaml /etc/k0s
sudo k0s install controller -c /etc/k0s/k0s.yaml
sudo systemctl start k0scontroller
sudo systemctl enable k0scontroller
sudo k0s status
```
実行結果
```
Version: v1.25.4+k0s.0
Process ID: 2285 
Role: controller
Workloads: false
SingleNode: false
```
Process IDはk0sの起動毎に変わります。Versionもインストールした時の最新版になっています。Roleが、controllerになっていればOKです。
### ワーカーノードがコントローラーノードに接続するためのトークンファイルの作成とダウンロード
次のコマンドを実行します。
```
sudo k0s token create --role=worker > token-worker
```
作業用ユーザーのホームディレクトリ(例 /home/worker1)に、token-worker というファイルが作成されます。
SCPコマンドを使い、これをダウンロードします。例えば、TeraTermを使っている場合は、「SSH SCP」を実行することで、token-workerファイルを、パソコン上の任意の場所にダウンロードすることができます。

## ワーカーノード(パソコン上で作ったUbuntu Mate 20.04の仮想マシン側)
仮想マシン作成時に、次のように設定しました。この設定は各自で読み替えてください。
 - VirtualBox上仮想マシンの割り当て仮想メモリ 4GB
 - ホストオンリーアダプタで、固定IPアドレスとして、192.168.125.10 を設定
 - ホスト名は、ubuntu1vm
### k0sのインストール
パソコン上で作ったUbuntu Mate 20.04の仮想マシンを起動し、次のコマンドを実行します。Ubuntu Mateのデスクトップ上で作業しても構いませんが、SSH接続で作業した方が楽です。
```
curl -sSLf https://get.k0s.sh | sudo sh
```
実行結果
```
k0s is now executable in /usr/local/bin
```
### コントローラーノードへの接続
SCPコマンドを使い、token-workerファイルをアップロードします。アップロード場所は、Ubuntu Mate 20.04の仮想マシンでログインしているユーザーのホームディレクトリにします。
TeraTermを使っている場合は、SSH接続を行い「SSH SCP」を実行することで、パソコン上のtoken-workerファイルを、アップロードすることができます。
token-workerファイルをアップロード後、次のコマンドを実行します。
```
sudo mkdir /etc/k0s
sudo mv token-worker /etc/k0s
sudo k0s install worker --token-file /etc/k0s/token-worker
sudo k0s start
sudo k0s status
```
実行結果
```
Version: v1.25.4+k0s.0
Process ID: 26730
Role: worker
Workloads: true
SingleNode: false
Kube-api probing successful: true
Kube-api probing last error:
```
Process IDはk0sの起動毎に変わります。Versionもインストールした時の最新版になっています。Roleが、workerになっていればOKです。

## コントローラーノード(IBM Cloud側)からワーカーノード(パソコン上のUbuntu Mate 20.04の仮想マシン側)を確認
コントローラーノードで次のコマンドを実行します。
```
sudo k0s kubectl get nodes
```
実行結果
```
NAME        STATUS   ROLES    AGE   VERSION
ubuntu1vm   Ready    <none>   95s   v1.25.4+k0s
```

# サンプルとしてNginxをデプロイして、サンプルページをワーカーノードで起動する
## kubernetes構成ファイルの作成
コントローラーノード(IBM Cloud側)で、Nginx用のYAMLファイルを作成するため、次のコマンドを実行します。
```
sudo nano nginx.yaml
```
記述内容
```
kind: Namespace
apiVersion: v1
metadata:
  name: nginxdemo
  labels:
    name: nginxdemo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx:1.23.3
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    app: my-nginx
spec:
  type: NodePort
  ports:
  - port: 8080
    targetPort: 80
    nodePort: 30080
    protocol: TCP
  selector:
    app: my-nginx
```
## Nginxのデプロイ
次のコマンドを実行します。
```
sudo k0s kubectl apply -f nginx.yaml
```
実行結果
```
namespace/nginxdemo created
deployment.apps/nginx-deployment created
service/nginx-service created
```
起動確認として、次のコマンドを実行します。
```
sudo k0s kubectl get services
```
実行結果
```
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes      ClusterIP   10.96.0.1        <none>        443/TCP          96m
nginx-service   NodePort    10.107.136.190   <none>        8080:30080/TCP   87s
```
上記から、ワーカーノードで、http://localhost:30080 または、http://ワーカーノードの固定IPアドレス:30080 にアクセスすれば良いことがわかります。
## 起動確認
ワーカーノードで、http://localhost:30080 または、http://ワーカーノードの固定IPアドレス:30080 にアクセスします。Ngixnのサンプルページが表示されればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/055b2971-28d1-f2f9-301d-b00a4db5a6b8.png)

次は、Nginx以外もデプロイしてみましょう。

# まとめ
会社や学校にお金を払ってもらってマネージドkubernetesやOpenShift環境を用意してもらっても良いのですが、予算の都合で難しいことがあります。そんなときは、今回のように自分で環境構築して試すと良いでしょう。
コントローラーノードは、IBM Cloud以外のパブリッククラウド、プライベートクラウド、VirtualBoxで別に構築した仮想マシンに置き換えることもできますし、ワーカーノードも、Raspberry Piなどを使ったエッジサーバーや低価格サーバーに置き換えることができます。

良い、コンテナライフを。