Photon OS は、VMware が OSS として開発しており、クラウド環境に最適化され、非常に軽量で、ミニマリストな Linux OS です。
最近の新しめな VMware 製品でも、OS 部分に Photon OS が使われていたりします。
一方で、kind とは、Kubernetes クラスタを Docker のコンテナとしてデプロイするツールです。
元々は、Kubernetes 自身の開発におけるテストの目的で設計されたものようですが、アプリ開発者が自身のローカルマシン上で Kubernetes 環境を持つためのツールとしても活用されています。
むしろ、Kubernetes のユーザーとしては、そっちがメインかも知れません。
このままでも良いのですが、デフォルト設定で kind を動かしただけでは、外部からのアクセスのために Service (type=LoadBalancer) を使うことができません。
そこで kind の公式ドキュメントでは、MetalLB を使って、LB を構築方法が紹介されています。
この MetalLB は、外部の LB 製品を用いずに、Kubernetes クラスタ上で上手くやりくりすることで、外部アクセスのための Service (type=LoadBalancer) を動かすことを目的に実装されています。
ただ、執筆時点で Beta 扱いのプロジェクトであることや、Kubernetes クラスタ単位の運用となるため、実際の運用に載せるには考慮すべき事項があります。
しかし、kind のようなお手元の Kubernetes 環境向けには、非常にお手軽です。
今回は、この kind と MetalLB を Photon OS 上で動かす方法をご紹介します。
前提
執筆時点で、Photon OS 4.0 を利用しています。
# cat /etc/photon-release
VMware Photon OS 4.0
PHOTON_BUILD_NUMBER=2f5aad892
また kind は sigs.k8s.io/kind@v0.17.0
を利用しており、MetalLB は kind の公式ドキュメントに従って v0.13.7
を利用します。
手順
(事前準備) Docker サービスの起動
Photon OS では、Docker がデフォルトでインストールされていますが、まだサービスを有効化していない場合には、事前に有効かしておきます。
下記の例では、Docker サービスが動いていません。
# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor pr
eset: disabled)
Active: inactive (dead)
TriggeredBy: ● docker.socket
Docs: https://docs.docker.com
サービスを有効化していきます。--now
オプションを付けることで、有効化と起動を同時に行うことができます。
systemctl enable docker --now
kind のインストール
公式のガイドにも、いくつかの方法がありますが、バイナリからのインストールと Go 言語によるインストールの大きく2つを紹介します。
方法1: バイナリからのインストール (簡単)
バイナリからのインストールは非常に簡単で、curl
でバイナリをダウンロードし、実行権限を付けたものを、パスの通ったディレクトリに配置するのみです。
公式のガイドにもある通り、/usr/local/bin
配下が一般的でしょうか。
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.17.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
方法2: Go 言語によるインストール
少し凝った(?)方法として、Go 言語をインストールし、go install
コマンドで kind をインストールすることもできます。
まず、Go 言語を Photon OS にインストールします。
tdnf install -y go
root ユーザーの場合、既に GOPATH が環境変数として設定されています。
# go env
...(snip)...
GOPATH="/root/go"
...(snip)...
しかし、個別に作成したユーザーの場合、GOPATH
を環境変数として設定する必要があります。
私は検証の目的毎に、ユーザーを分けていたりするので、その場合に、設定し忘れると、あれ?ということになりました。
例えば、今回の kind の検証ためには kind
というユーザーを作成しています。
Photon OS においては、~/.bash_profile
に設定するので、ご注意ください。
vi ~/.bash_profile
設定例としては、こんな感じです。
# Begin ~/.bash_profile
# Written for Beyond Linux From Scratch
# by James Robertson <jameswrobertson@earthlink.net>
# updated by Bruce Dubbs <bdubbs@linuxfromscratch.org>
# Personal environment variables and startup programs.
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
# ...(snip)...
一旦、シェルと開き直すか、現在のシェルにも、環境変数を反映しておきます。
source .bash_profile
これで Go 言語の準備は整ったので、公式ガイドの通り、go install
コマンドを実行します。
go install sigs.k8s.io/kind@v0.17.0
これで、$GOPATH/bin
配下に kind が配置され、上記の設定でパスが通っていれば、kind が実行できます。
# kind version
kind v0.17.0 go1.19.3 linux/amd64
kind クラスタの作成/起動
下記のコマンドを実行すると、kind
という名前で Kubernetes クラスタが作成されます。
kind create cluster
初回は、コンテナイメージの取得があるので、少し長めですが、非常に簡単に Kubernetes クラスタが作成されます。
デフォルトでは、シングルノードの Kubernetes クラスタが Docker コンテナとして作成されます。
# kind get clusters
kind
# kind get nodes
kind-control-plane
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4e94a151bed0 kindest/node:v1.25.3 "/usr/local/bin/entr…" About a minute ago Up About a minute 127.0.0.1:38959->6443/tcp kind-control-plane
kubeconfig
ファイルも、自動で配置されます。
# ls .kube/config
.kube/config
kind クラスタへのアクセス
もし、まだ kubectl
をインストールしていなければ、Kubernetes の公式ドキュメントに従ってインストールし、Kubernetes クラスタにアクセスしていきましょう。
まずは、最新版のバイナリをダウンロードします。
curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl"
取得したバイナリに実行権限を付与します。
chmod +x ./kubectl
あとはお好みで PATH の通った場所に配置します。
大抵は /usr/local/bin
でしょうか。
mv ./kubectl /usr/local/bin/kubectl
下記のように、kubectl
側のクライアントと kind 側のサーバーのバージョンが表示されることを確認します。
# kubectl version
WARNING: This version information is deprecated and will be replaced with the output from kubectl version --short. Use --output=yaml|json to get the full version.
Client Version: version.Info{Major:"1", Minor:"26", GitVersion:"v1.26.1", GitCommit:"8f94681cd294aa8cfd3407b8191f6c70214973a4", GitTreeState:"clean", BuildDate:"2023-01-18T15:58:16Z", GoVersion:"go1.19.5", Compiler:"gc", Platform:"linux/amd64"}
Kustomize Version: v4.5.7
Server Version: version.Info{Major:"1", Minor:"25", GitVersion:"v1.25.3", GitCommit:"434bfd82814af038ad94d62ebe59b133fcb50506", GitTreeState:"clean", BuildDate:"2022-10-25T19:35:11Z", GoVersion:"go1.19.2", Compiler:"gc", Platform:"linux/amd64"}
MetalLB のインストール
冒頭で述べた通り、このままでも良いのですが、せっかくなので Service (type=LoacBalancer) が使えるように MetalLB をインストールします。
kind の公式ドキュメントにある MetalLB のインストール手順 に従って、まずは MetalLB のインストール用のマニフェストを適用していきますが、後からどんなマニフェストを適用したのか記録する意味で、一旦、マニフェストをダウンロードします。
curl -OL https://raw.githubusercontent.com/metallb/metallb/v0.13.7/config/manifests/metallb-native.yaml
そして、このマニフェストを適用します。
kubectl apply -f metallb-native.yaml
数分、このまま待機でも良いですが、ドキュメントにあるコマンドで、MetalLB の準備ができるのを確認します。
kubectl wait --namespace metallb-system \
--for=condition=ready pod \
--selector=app=metallb \
--timeout=90s
↓こんな感じで、condition met
が返ってくれば、OK です。
# kubectl wait --namespace metallb-system \
> --for=condition=ready pod \
> --selector=app=metallb \
> --timeout=90s
pod/controller-84d6d4db45-grfv9 condition met
pod/speaker-jpzx5 condition met
次に、MetalLB の設定ファイルを作成していきますが、MetalLB が Service 用に使っても良い IP アドレス帯を指定する必要があります。
その際、Docker が kind を構築する際に、どの IP アドレス帯を使って Bridge ネットワークを作成しているのか確認しておく必要があります。
docker network inspect -f '{{.IPAM.Config}}' kind
私の手元の環境では、↓こんな感じの結果だったので、172.18.0.0/16
のネットワークから、MetalLB が使うアドレス帯を指定すれば良いことが分かります。
# docker network inspect -f '{{.IPAM.Config}}' kind
[{172.18.0.0/16 172.18.0.1 map[]} {fc00:f853:ccd:e793::/64 map[]}]
ここでは、172.18.255.200-172.18.255.250
を MetalLB に割り当てることにしていますが、必要に応じて、割り当てを変更してください。
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: example
namespace: metallb-system
spec:
addresses:
- 172.18.255.200-172.18.255.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: empty
namespace: metallb-system
作成した設定ファイルを適用してきます。
kubectl apply -f metallb-config.yaml
参考までに、適当な Service を作成して、MetalLB の動作を確認します。
# kubectl create service loadbalancer my-lbs --tcp=80:8080
service/my-lbs created
# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 18m
my-lbs LoadBalancer 10.96.93.40 172.18.255.200 80:32467/TCP 6s
アプリの実体を伴わない、空のサービスなので、実際にアクセスしても確認できませんが、指定したアドレス帯から、EXTERNAL-IP
が振られていることが確認できます。
クラスタの停止/削除
使い終わったクラスタは、下記のコマンドで簡単に削除できます。
kind delete cluster
こんな感じで、簡単に使い捨てできちゃうのが、実にコンテナらしいですよね。