こたつ&&みかん&&でーたべーす

DB 関連の話を中心に技術っぽい記事を書きます。

同一ホスト上の 2つの minikube 間で通信できるようにしたい

タイトルにも記載していますが、お仕事で以下のような検証を実施したいというお話がありました。

  • マルチ Kubernetes cluster 構成での検証を実施したい
  • Kubernetes cluster 間で通信できるようにしたい
  • ローカルの端末上で minikube を使ってお手軽に検証できるようにしたい (minikube に慣れてるので minikube でやりたい)

いろいろ模索してみた結果、先週リリースされた minikube v1.29.0 で追加されている --static-ip を使うといい感じにできそうだったので、検証結果を備忘録として残します。

環境

今回は以下の環境/バージョンで検証しています。

概要

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-1test-net 上に作成します。この時 --static-ipminikube-1 のコンテナに割り当てられる IP 172.25.0.2 を明示的に指定します。

$ minikube start -p minikube-1 --network=test-net --driver=docker --static-ip=172.25.0.2

同様に、minikube-2test-net 上に作成します。こちらも同様に --static-ipminikube-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.230080 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 間の通信ができるようになると嬉しい気がします。

わりと手探りで模索した感じなので、他に良い方法を知ってる方がいたらコメントいただけると嬉しいです。