Kubernetes with Rancher環境を構築し、外部からpodに接続してみる

こんにちは
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

この記事ではRancher環境を構築し、そのRancherで作ったk8s環境上に以下の環境をインプットしてcurl出来るか的な事を試してみようと思います。
※上手く表現できるかわかりませんが、私が今からやろうとしていることは「正規ではない感」があります。あくまでもこんな方法もあるんだなぁ程度に見てもらえると良いかもですm(__)m

https://qiita.com/ohtsuka-shota/items/38f74968ada4484a9c91


# Rancherとは？

以下公式サイトから引用です。
OSSなので無料で使用することができつつ、一定料金を支払うことでサポートを受けることが出来るようです。

>Rancherは、コンテナ技術を採用しているチーム向けのコンテナ管理のプラットフォームです。マルチクラウドとオンプレミス環境にKubernetesクラスターをより簡単に構築および管理できます。

https://www.rancher.co.jp/

個人的には"Run Kubernetes Everywhere"や"Kubernetes as a Service(KaaS)"等の文言を聞くと「今っぽいな・・・」と感じてしまいます。
特にKaaSという字面は本当に今っぽい。パブリッククラウドの台頭からIaaS,PaaS,SaaSみたいな言葉がうまれ（？）、そのほかにもFWaaSみたいなものもうまれ。。。"●● as a Service"多すぎ問題。

このRancherはDocker Hubにimageとして用意されているので、今回はDocker環境を作ってそこにRancherコンテナをデプロイし、使用していきたいと思います。
HWスペックは少々高めの方がよさそうです。
私はCPU 4core2socket、Memory 12GB、Disk 32GBくらいで構築しています。

# 今回構築するイメージ

Rancherコンテナをデプロイすると、そのコンテナ内が既にk8s環境っぽかったのでそこにNgixコンテナとapache2コンテナを内包したpodと、そのpodのLB的な役割を果たすNodePortをデプロイ。
ホストのIPアドレスに対して30080ポートで接続してくる通信があった場合、Rancherコンテナの30080にリダイレクトし、NodePortがそれを検知するとpodの80ポートに転送しnginxコンテナに接続。
同様にホストのIPアドレスに対して30090ポートで接続してくる通信があった場合、Rancherコンテナの30090にリダイレクトし、NodePortがそれを検知するとpodの90ポートに転送しapahce2コンテナに接続します。
![kubernetes-ページ12.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/eb243cce-9e87-8177-c6b7-f72173dfa785.png)



# Rancherコンテナのデプロイ

以下のコマンド群を使用し、Docker環境を準備します。
ESXiやProxmox VE等の仮想化基盤上でサーバを構築している場合は、docker環境構築後にsnapshotを取っておくと良いと思います。
```
root@rancher:~# apt update
root@rancher:~# apt upgrade
root@rancher:~# apt-get install apt-transport-https ca-certificates curl gnupg lsb-release
root@rancher:~# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
root@rancher:~# echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
root@rancher:~# apt-get update
root@rancher:~# apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
root@rancher:~# docker --version 
Docker version 23.0.5, build bc4487a
```

Rancherコンテナをデプロイします。
デプロイする際に80,443,30080,30090ポートを開放します。80と443はRancher用となり30080と30090はpod内のnginxとapache2にアクセスする為のポートになります。
```
root@rancher:~# docker run -d --name=rancher-server --restart=unless-stopped -p 80:80 -p 443:443 -p 30080:30080 -p 30090:30090 --privileged rancher/rancher:latest
566bb40ab063603335f6783da43e647356a8a9646be34a8306c8fffe6a3f610d
root@rancher:~# docker port 566bb40ab063603335f6783da43e647356a8a9646be34a8306c8fffe6a3f610d
80/tcp -> 0.0.0.0:80
80/tcp -> [::]:80
443/tcp -> 0.0.0.0:443
443/tcp -> [::]:443
30080/tcp -> 0.0.0.0:30080
30080/tcp -> [::]:30080
30090/tcp -> 0.0.0.0:30090
30090/tcp -> [::]:30090
```

コンテナがデプロイされていることと初期パスワードを確認します。
ここで確認したパスワードはWebブラウザでRancherにアクセスする際に必要になります。
```
root@rancher:~# docker ps
CONTAINER ID   IMAGE                    COMMAND           CREATED              STATUS              PORTS                                                                      NAMES
40d58a3d9a8d   rancher/rancher:latest   "entrypoint.sh"   About a minute ago   Up About a minute   0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   rancher-server
root@rancher:~# docker logs 40d58a3d9a8d 2>&1 | grep "Bootstrap Password:"
2023/05/02 14:11:20 [INFO] Bootstrap Password: mjrnt82n7bntgjrs8zw2fbwhgq7p2ks2w9sjs5f6c6xpxknrxgn5xp
```


WebブラウザでホストのIPアドレスに対して接続します。80ポートなのでhttp://"ホストのIPアドレス"でOKです。
※Rancherの背景が黒くなったり白くなったりしますが気にしないで頂ければ幸いです。

アクセスすると以下の様な画面が表示されます。Passwordのところに先ほど出力したパスワードを入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/51d80c99-cc3b-29fc-4dc9-d629fb6af836.png)

パスワードの変更を求められますので、任意のものに変更しましょう。
passwordみたいな文字数の少ないパスワードはダメで12文字以上である必要がありそうです。

![image11111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/118c790f-0e42-a906-e414-b0de2afa4672.png)


ログインに成功すると以下の様なUIが表示されるはずです。
localというものがあるので、それを押下します。（無い場合は再度ログインし直すと出てくる気がします。）
![image22222.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/704eb84c-cee9-06c4-c04f-940adff8eafb.png)

遷移してdashboardが表示されます。
![image33333.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/41800aa5-4a74-baca-9d79-602822955677.png)

# Kubernetes環境にアクセスして環境を構築する

先程の画像の右上のkubectl shellを押下するとk8s環境にアクセスし、kubectlコマンドなどでk8sを操作することが出来るのですが、一旦ステータスを確認します。
Nodeを押下してCPUやMEMORY、PODSの上にあるPressureの項目がとりあえず緑になっていることを確認します。その後にkubectl shellを押下しましょう。念のため。
![image44444.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/3e099720-4ff1-2454-abb4-764472d45d76.png)

kubectl shell内では以下のyamlファイルを準備し、コマンドを実行。環境をデプロイしました。
```
cat httpd-nginx.yaml
apiVersion: v1
kind: Pod
metadata:
  name: web-pod
  labels:
    app: web-app
spec:
  containers:
    - name: web-httpd
      image: shotaohtsuka/my-httpd-image
      ports:
        - name: web-httpd
          containerPort: 90
          protocol: TCP
    - name: web-nginx
      image: nginx
      ports:
        - name: web-nginx
          containerPort: 80
          protocol: TCP

apiVersion: v1
kind: Service
metadata:
  name: service-httpd-nginx
spec:
  type: NodePort
  selector:
    app: web-app
  ports:
    - name: nginx-port
      port: 80
      targetPort: 80
      nodePort: 30080
    - name: httpd-port
      port: 90
      targetPort: 90
      nodePort: 30090

kubectl create -f httpd-nginx.yaml
kubectl create -f service-httpd-nginx.yaml
```

# 接続確認

まずはPCでcmdを立ち上げ、curlをしてみます。
logは以下となりますが、接続出来ていますね。
```
C:\Users\otsuka-shota>curl 192.168.2.141:30080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
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>

C:\Users\otsuka-shota>curl 192.168.2.141:30090
<html><body><h1>It works!</h1></body></html>
```

また、Webブラウザからも接続出来ました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/7dfe9dd3-1c91-40c5-b787-7bc62b37dcd8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/b17ebd00-c958-5d97-3dec-907db682d26a.png)

# 余談：kubectl shellってどこに接続しているの？

結論、デプロイしたRancherコンテナに接続しています。
実際のログは以下です。
dockerコンテナに対してexecで入り、k8s内のpodとserviceを出力させています。

```
root@rancher:~# docker ps
CONTAINER ID   IMAGE                    COMMAND           CREATED       STATUS       PORTS                                                                                                                                                                    NAMES
b18c0143fa21   rancher/rancher:latest   "entrypoint.sh"   7 hours ago   Up 7 hours   0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp, 0.0.0.0:30080->30080/tcp, :::30080->30080/tcp, 0.0.0.0:30090->30090/tcp, :::30090->30090/tcp   rancher-server
root@rancher:~# docker exec -it b18c0143fa21 /bin/bash
b18c0143fa21:/var/lib/rancher # kubectl get all
NAME          READY   STATUS    RESTARTS       AGE
pod/web-pod   2/2     Running   2 (7h9m ago)   7h17m

NAME                          TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                     AGE
service/kubernetes            ClusterIP   10.43.0.1      <none>        443/TCP                     7h26m
service/service-httpd-nginx   NodePort    10.43.16.103   <none>        80:30080/TCP,90:30090/TCP   7h16m
```