同一ホスト上の 2つの minikube 間で通信できるようにしたい
タイトルにも記載していますが、お仕事で以下のような検証を実施したいというお話がありました。
- マルチ Kubernetes cluster 構成での検証を実施したい
- Kubernetes cluster 間で通信できるようにしたい
- ローカルの端末上で minikube を使ってお手軽に検証できるようにしたい (minikube に慣れてるので minikube でやりたい)
いろいろ模索してみた結果、先週リリースされた minikube v1.29.0 で追加されている --static-ip
を使うといい感じにできそうだったので、検証結果を備忘録として残します。
環境
今回は以下の環境/バージョンで検証しています。
- Ubuntu : 20.04 (WSL2)
- Docker : 20.10.22
- Minikube : 1.29.0 (Kubernetes 1.26.1)
概要
minikube の docker driver を使って以下のような構成の環境を構築しました。同一の Docker Network 上に 2つの minikube をコンテナとして起動するので、この 2つのコンテナ間で通信ができるようになります。
+--------------+ +--------------+ | minikube-1 | | minikube-2 | | (172.25.0.2) | | (172.25.0.3) | +------+-------+ +------+-------+ | | *--------+-------------------+---------* (Docker network: test-net)
環境構築
まず、Docker Network test-net
を作成します。subnet の値はお好みに合わせて適当なプライベートアドレスの範囲を指定します。
$ docker network create -d bridge test-net --subnet=172.25.0.0/24 --gateway=172.25.0.1
次に minikube-1
を test-net
上に作成します。この時 --static-ip
で minikube-1
のコンテナに割り当てられる IP 172.25.0.2
を明示的に指定します。
$ minikube start -p minikube-1 --network=test-net --driver=docker --static-ip=172.25.0.2
同様に、minikube-2
も test-net
上に作成します。こちらも同様に --static-ip
に minikube-2
のコンテナに割り当てられる IP 172.25.0.3
を指定します。
$ minikube start -p minikube-2 --network=test-net --driver=docker --static-ip=172.25.0.3
これで、以下のような感じの環境が構築できました。
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e288888db363 gcr.io/k8s-minikube/kicbase:v0.0.37 "/usr/local/bin/entr…" 2 minutes ago Up 2 minutes 127.0.0.1:32787->22/tcp, 127.0.0.1:32786->2376/tcp, 127.0.0.1:32785->5000/tcp, 127.0.0.1:32784->8443/tcp, 127.0.0.1:32783->32443/tcp minikube-2 232e4710da78 gcr.io/k8s-minikube/kicbase:v0.0.37 "/usr/local/bin/entr…" 4 minutes ago Up 4 minutes 127.0.0.1:32782->22/tcp, 127.0.0.1:32781->2376/tcp, 127.0.0.1:32780->5000/tcp, 127.0.0.1:32779->8443/tcp, 127.0.0.1:32778->32443/tcp minikube-1
test-net
上に作成した 2つの minikube コンテナに、--static-ip
で指定した IP がそれぞれ割り当てられていることが確認できます。
$ docker network inspect test-net | jq .[].Containers { "232e4710da782e1dcf7bde6254c738f66ccdcf7b461c8e4ca168fd53b4bcb9a9": { "Name": "minikube-1", "EndpointID": "5a7c80d74ded5d850277ea72a0cea1db869a7811ba5f72b0737581bdf4a82889", "MacAddress": "02:42:ac:19:00:02", "IPv4Address": "172.25.0.2/24", "IPv6Address": "" }, "e288888db363fb7e982914f4f887281ece739718e7e9fa151c290d17551d666b": { "Name": "minikube-2", "EndpointID": "d662015b22ef9df77065d77ad0406c41ba0942e0365caa8c694924f2ab21af79", "MacAddress": "02:42:ac:19:00:03", "IPv4Address": "172.25.0.3/24", "IPv6Address": "" } }
$ minikube ip -p minikube-1 172.25.0.2
$ minikube ip -p minikube-2 172.25.0.3
動作確認
動作確認のために、minikube-1
上に NGINX の Pod と Service (type: NodePort) をデプロイし、minikube-2
上の Pod から HTTP リクエストが実行可能かを確認してみます。
まず、minikube-1
上に以下のマニフェストを使って NGINX の Pod と Service をデプロイします。Service の .spec.ports.nodePort
には 30080
を指定しておきます。
apiVersion: apps/v1 kind: Deployment metadata: name: my-nginx spec: selector: matchLabels: run: my-nginx replicas: 1 template: metadata: labels: run: my-nginx spec: containers: - name: my-nginx image: nginx ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: my-nginx labels: run: my-nginx spec: type: NodePort ports: - port: 80 targetPort: 80 nodePort: 30080 protocol: TCP selector: run: my-nginx
$ minikube profile minikube-1
$ kubectl apply -f ./nginx.yaml
$ kubectl get pod,svc NAME READY STATUS RESTARTS AGE pod/my-nginx-754c4d44b4-cwq6h 1/1 Running 0 56s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6m12s service/my-nginx NodePort 10.96.223.147 <none> 80:30080/TCP 56s
次に、minikube-2
上にクライアント用の Pod (curl を実行する Pod) を作成します。
$ minikube profile minikube-2
$ kubectl run client --image=yauritux/busybox-curl:latest -it --rm -- /bin/sh
作成した「minikube-2
上にあるクライアント用の Pod」から「minikube-1
上にある NGINX Pod」に (type: NodePort の Service を経由して) HTTP リクエストを実行してみます。minikube-1
の IP 172.25.0.2
と 30080
port を指定します。
/home # curl -IXGET http://172.25.0.2:30080/ HTTP/1.1 200 OK Server: nginx/1.23.3 Date: Thu, 02 Feb 2023 10:25:41 GMT Content-Type: text/html Content-Length: 615 Last-Modified: Tue, 13 Dec 2022 15:53:53 GMT Connection: keep-alive ETag: "6398a011-267" Accept-Ranges: bytes
上記の通り、「minikube-2
上の Pod」から「minikube-1
上の NGINX Pod」に対して HTTP リクエストを実行できました。
また、Docker 側の機能でいい感じにコンテナ名の名前解決を実施してくれるので、IP ではなく minikube-1
をホスト名として指定しても HTTP リクエストを実行可能です。
/home # curl -IXGET http://minikube-1:30080/ HTTP/1.1 200 OK Server: nginx/1.23.3 Date: Thu, 02 Feb 2023 10:27:47 GMT Content-Type: text/html Content-Length: 615 Last-Modified: Tue, 13 Dec 2022 15:53:53 GMT Connection: keep-alive ETag: "6398a011-267" Accept-Ranges: bytes
おまけ
--static-ip
を指定せずに 2つの minikube を起動しようとすると、IP がコンフリクトして以下のようなエラーが発生しました。そのため、--static-ip
が利用できない minikube v1.28.0 以前のバージョンでは上記方法 (同一 Docker Network 上に 2つの minikube を作成) は利用できないと思われます。
$ minikube start -p minikube-2 --network=test-net --driver=docker 😄 [minikube-2] minikube v1.29.0 on Ubuntu 20.04 ✨ Using the docker driver based on user configuration 📌 Using Docker driver with root privileges 👍 Starting control plane node minikube-2 in cluster minikube-2 🚜 Pulling base image ... 🔥 Creating docker container (CPUs=2, Memory=6300MB) ... ❌ Exiting due to GUEST_PROVISION: Failed to start host: can't create with that IP, address already in use ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │ 😿 If the above advice does not help, please let us know: │ │ 👉 https://github.com/kubernetes/minikube/issues/new/choose │ │ │ │ Please run `minikube logs --file=logs.txt` and attach logs.txt to the GitHub issue. │ │ │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯
まとめ
minikube v1.29.0 で追加された --static-ip
を使うと、複数の minikube を 1つの Docker Network 上に (IP をコンフリクトさせることなく) 作成できました。ひとまず type: NodePort
で通信できるようにはなったので最低限の検証はできるのですが、NodePort
ではデフォルトだと 30000-32767
の範囲の番号の port を使う感じになるので、できれば type: LoadBalancer
とかでも Kubernetes 間の通信ができるようになると嬉しい気がします。
わりと手探りで模索した感じなので、他に良い方法を知ってる方がいたらコメントいただけると嬉しいです。