Ubuntu server 20.04 に Rancher で Kubernetes (シングルノードk3s) + Ingress 環境を構築し、ウェブアプリをホストする


現在の最新版のRancher 2.5.2 を使った所、1年前のものと違った点で環境構築に躓いた所があったので書きます。

Rancher 添付の K3S のシングルノードクラスタで、Ingress で外部リクエストにレスポンスする所まで行います。

1. Docker エンジンのインストール

curl 'https://releases.rancher.com/install-docker/19.03.13.sh' | bash
sudo usermod -aG docker <yourname>

Ubuntu Server 20.04 のインストーラは、途中でチェックボックスでDocker をインストールできるうようになっていますが、このインストーラ途中での Docker のインストールはしないでください

Ubuntuのインストーラでインストールする Docker は、snap のものです。この snap版 Docker は、ストレージのマウントができないため、今回の Rancher の中で起動するシングルノードクラスタの中でホストのストレージをマウントさせることができません。(できそうな気がしますがわかりません)

なので、snap 版の Docker は使わず、Rancher が提供しているインストールスクリプトで Docker をインストールします。

github の https://github.com/rancher/install-docker を見ると、バージョンごとのdocker インストールスクリプトがありますので、それを使います。README にある通り、これらのスクリプトは releases.rancher.com でホストされてますので、bash で実行します。

curl 'https://releases.rancher.com/install-docker/19.03.13.sh' | bash

インストール完了時、ユーザーを docker グループに追加させるコマンドが表示されるので、実行しておきます。

sudo usermod -aG docker <yourname>

2. Rancher の実行

docker run -d --restart=unless-stopped -p 80:30080 -p 443:30443 -p 32080:80 -p 32443:443 -v /data/rancher:/var/lib/rancher -v /data:/data --privileged rancher/rancher

Rancher は、Docker コンテナとして実行するだけなので、明示的なインストールは不要です。

まず参考にするドキュメントは、Github の README が良いでしょう。 https://github.com/rancher/rancher

ここに書いてある起動スクリプト

sudo docker run -d --restart=unless-stopped -p 80:80 -p 443:443 --privileged rancher/rancher

これは、ただ起動する分には問題ありませんが、Pod の中でホストボリュームをマウントしたり、Ingress でホストリクエストを受けたりする場合に不足を感じます。

ポイントとして、k3s のシングルノードクラスタも、このコンテナ内で作られるため、Rancher起動時にホストボリュームのマウントやポート転送をしておく必要があります。

rancher イメージで指定しているポート 80 および 443 は、Rancherの Web UI および Kuberntes の API に使われるポートです。このポートを他のホストポートに逃し、80 と 443 は Ingress で受けれるようにします。

-p 32080:80 -p 32443:443 -p 80:30080 -p 443:30443

ホストの 32080と32443 を Rancherの 80, 443 へ、ホストの 80,443 を Ingress の NodePort 32080, 32443 へ転送する設定です。

また、上記のまま起動すると、コンテナ削除時に Rancher (Kubernetes) の設定が消えてしまいますので、永続化させるためにホストのボリュームをマウントします。

ホストの /data ディレクトリをすべて、Kubernetes 用とします。/data/rancher ディレクトリを作り、 -v /data/rancher:/var/lib/rancher でマウント。

さらに、ホストの /data/ をその他の Podでも使う想定のため、 -v /data:/data で Rancher コンテナにマウントしておきます。

コマンド全体としてはこのようになります。

docker run -d --restart=unless-stopped -p 80:30080 -p 443:30443 -p 32080:80 -p 32443:443 -v /data/rancher:/var/lib/rancher -v /data:/data --privileged rancher/rancher

追記: docker-compose.yml

実運用を考えると、docker-compose を作るのが良いと思います。rancher のバージョンも固定したほうが良いでしょう。実際に TORICOで使っている docker-compose.yml はこのようなものです。

rancher.docker-compose.yml
version: '3'
services:
rancher:
image: rancher/rancher
container_name: rancher
networks:
- default
ports:
- "80:30080"
- "443:30443"
- "32080:80"
- "32443:443"
volumes:
- /data/rancher:/var/lib/rancher
- /data:/data
- /home/ubuntu/.docker:/var/lib/rancher/.docker
- /var/run/docker.sock:/var/run/docker.sock
restart: always
privileged: true

起動するには

docker-compose -f rancher.docker-compose.yml up -d

3. kubeconfig の取得

起動できたら、ウェブブラウザで rancherのホストの 32443 ポートへリクエストします。

https://<your-rancher-host>:32443/

Adminパスワードを設定し、Webコンソールのデフォルトビューがどっちがいいか聞かれるのでどちらかを答えます。どっちでも良いですが、シングルノードの場合は Cluster Exproler のほうが見やすいと思うので右側を選択します。なお、どちらのビューでも、クリックするだけでもう一方のビューに切り替えができます。

起動したら、一旦 Cluster Manager に移動し、

Cluster を選択します。そうすると、右上に Kubeconfig file とありますので、そこをクリックします。

クリックすると Kubeconfig ファイルが表示されるので、それをコピペして、mac に .kube/config-my-cluster みたいな名前で 保存します。ファイル名の部分は適当に変更してください。

ちなみに、kubectl はすべて mac から操作すると思いますので、 Rancher 起動ホストにこの kubeconfig を保存する必要は無いと思います。

4. mac から kubectl を実行 (試しにネームスペースを作る)

kubectl が無い場合は、brew でインストールしておきます。

#!/usr/bin/env zsh
export KUBECONFIG=${HOME}/.kube/config-my-cluster
kubectl create namespace <my-namespace-name>

これを実行し、 created が表示されればOKです。 my-namespace-name は適当に決めてください。今後も出てきます。(自分の github や twitter のアカウント名で良いと思います。)

5. Ingress Controller の作成

イングレスコントローラを起動します。

普通に起動するだけなら https://github.com/kubernetes/ingress-nginx ここにあるマニフェスト

https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.41.2/deploy/static/provider/baremetal/deploy.yaml

これを、kubectl で実行するだけなのですが、これだと 80, 443 でリッスンするため Rancher コンテナ内のシングルノードクラスタでは応答できません。なので、NodePort を開けます。(もっと良い方法あるかも。ベストプラクティスがわかりませんでした)

上記 yaml マニフェストファイルをダウンロードして、270 行目あたりにある ingress-nginx-controller

サービスの項目の ports nodePort  に、30080 と 30443 を追加します。

---
# Source: ingress-nginx/templates/controller-service.yaml
apiVersion: v1
kind: Service
metadata:
annotations:
labels:
helm.sh/chart: ingress-nginx-3.10.1
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.41.2
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
nodePort: 30080 # 追加
- name: https
port: 443
protocol: TCP
targetPort: https
nodePort: 30443 # 追加
selector:

そして、このマニフェストを mac から apply します。

#!/usr/bin/env zsh
export KUBECONFIG=${HOME}/.kube/config-my-cluster
kubectl apply -f ingress.yml

これで、80,443 ポートをレスポンスする準備ができました。

6. SSL(TLS)証明書があれば入れとく

#!/usr/bin/env zsh
export KUBECONFIG=${HOME}/.kube/config-my-cluster
kubectl -n <my-namespace-name> create secret tls cert-wildcard-mydomain \
  --key wildcard.mydomain.key \
  --cert wildcard.mydomain.crt

SSL 証明書の key ファイルと crt ファイルを、tls secret 「cert-wildcard-mydomain 」として 登録します。

この証明書を Ingress から使えるようになります。無ければ不要です。
(例では wildcard と書いてありますが特にワイルドカード証明書でなければいけないわけではありません)

7. 適当にサービスを作る

alpine nginx で、適当にサービスしてみます。

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: <my-namespace-name>
name: test-alpine-deployment
spec:
selector:
matchLabels:
app: test-alpine

strategy:
type: Recreate
template:
metadata:
labels:
app: test-alpine
spec:
containers:
- image: nginx:stable-alpine
name: test-alpine
volumeMounts:
- name: test-volume
mountPath: /data/test
volumes:
- name: test-volume
hostPath:
path: /data/test  

検証用に /data/test ディレクトリをマウントしています。予め、ホスト上に /data/test ディレクトリを作っておいてください。

service.yaml
apiVersion: v1
kind: Service
metadata:
name: test-alpine-service
namespace: <my-namespace-name>
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
name: test-alpine-http
selector:
app: test-alpine
ingress.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: test-alpine-ingress
namespace: <my-namespace-name>
spec:
# 先程 SSL(TLS) 証明書をインポートした場合はここで指定
#tls:
# - hosts:
# - myhost.example.com
# secretName: cert-wildcard-mydomain
rules:
- host: myhost.example.com
http:
paths:
- path: /
backend:
serviceName: test-alpine-service
servicePort: 80

applyします

#!/usr/bin/env zsh
export KUBECONFIG=${HOME}/.kube/config-my-cluster
kubectl apply -f deployment.yaml
kubectl apply -f service.yml
kubectl apply -f ingress.yml

検証

httpサービスを検証

Rancherホストに対して、httpリクエストすると Nginxのデフォルトページが見れます。

ホストボリュームのマウントを検証

Pod にログインします。

#!/usr/bin/env zsh
export KUBECONFIG=${HOME}/.kube/config-my-cluster
podname=$(kubectl -n <my-namespace-name> get pod -l app=test-alpine -o jsonpath="{.items[0].metadata.name}")
kubectl -n <my-namespace-name> exec -it ${podname} -- /bin/ash

ログインしたら、/data/test に移動し、ファイルを作るなどしてホストの /data/test ボリュームがマウントされていることを確認します。

現在未評価

コメント

コメントを投稿
コメントするには TORICO-ID にログインしてください。
ログイン コメント利用規約