コンテンツにスキップ

Minikube@開発環境

はじめに

本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。


01. Minikubeの仕組み

アーキテクチャ

▼ 仮想サーバー系のドライバーの場合

ホスト上にMinikube仮想サーバーを作成する。

このMinikube仮想サーバー上に、Nodeを持つClusterを作成する。

minikube_architecture_virtual_machine_driver

▼ Dockerドライバーの場合

ホスト上にコンテナを作成する。

このコンテナ内にMinikube仮想サーバーを作成し、仮想サーバー上にNodeを持つClusterを作成する。

minikube_architecture_docker_driver


ドライバー

▼ ドライバーとは

ゲスト (Node) 側のOSを設定する。

ホスト側のOS (Linux、MacOS、Windows) や、これらOSのバージョンによって、使用できるドライバーが異なる。

▼ ドライバーの種類

ホスト側のOS ゲスト (Node) 側のOS
Linux VirtualBox、Docker、KVM2、...
MacOS VirtualBox、Docker、HyperKit、...
Windows VirtualBox、Docker、Hyper-V、...


02. マウント

ホストとNode間マウント

▼ 標準のホストとNode間マウント

ホスト側の$MINIKUBE_HOME/filesディレクトリ配下に保存されたファイルは、ゲスト仮想環境内のNodeのルート直下にマウントされる。

$ mkdir -p ~/.minikube/files/etc

$ echo nameserver 8.8.8.8 > ~/.minikube/files/etc/foo.conf

#  /etc/foo.conf に配置される
$ minikube start

▼ 各ドライバーのホストとNode間マウント

ホスト以下のディレクトリ配下に保存されたファイルは、ゲスト仮想環境内のNodeの決められたディレクトリにマウントされる。

ドライバー名 ホスト側のOS ホスト側のディレクトリ ゲスト仮想環境内のNodeのディレクトリ
VirtualBox Linux /home /hosthome
VirtualBox macOS /Users /Users
VirtualBox Windows C://Users /c/Users
VMware Fusion macOS /Users /mnt/hgfs/Users
KVM Linux なし
HyperKit Linux なし (NFSマウントを参照)


Nodeとコンテナ間マウント

▼ 標準のNodeとコンテナ間マウント

ゲスト仮想環境内のNodeでは、以下のディレクトリからPersistentVolumeが自動的に作成される。

そのため、Podでは作成されたPersistentVolumeをPersistentVolumeClaimで指定しさえすればよく、わざわざNodeのPersistentVolumeを作成する必要がない。

ただし、MinikubeのDockerドライバーとPodmanドライバーを使用する場合は、この機能がないことに注意する。

  • /data
  • /var/lib/minikube
  • /var/lib/docker
  • /var/lib/containerd
  • /var/lib/buildkit
  • /var/lib/containers
  • /tmp/hostpath_pv
  • /tmp/hostpath-provisioner


ホスト-Nodeとコンテナ間

▼ ホストをコンテナにマウントする方法

Minikubeでは、mountコマンド、ホスト側の$MINIKUBE_HOME/filesディレクトリ、ドライバーを使用して、ホスト側のディレクトリをゲスト仮想環境内のNodeのディレクトリにマウントできる。

またNodeでは、決められたディレクトリからPersistentVolumeを自動的に作成する。

ここで作成されたPersistentVolumeを、PodのPersistentVolumeClaimで指定する。

このように、ホストからNode、NodeからPodへマウントを実行することにより、ホスト側のディレクトリをPod内のコンテナに間接的にマウントできる。

▼ HyperKitドライバーを使用する場合

*例*

(1)

HyperKitドライバーを使用する場合、ホストとNode間のマウント機能がない。そこでmountコマンドを使用して、ホスト側のディレクトリをNodeのボリュームにマウントする。

$ minikube start --driver=hyperkit --mount=true --mount-string="/Users/hiroki.hasegawa/projects/foo:/data"
(2)

NodeのボリュームをPod内のコンテナにマウントする。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: foo-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app.kubernetes.io/name: foo-pod
  template:
    metadata:
      labels:
        app.kubernetes.io/name: foo-pod
    spec:
      containers:
        - name: app
          image: app:1.0.0
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080
          volumeMounts:
            - name: app
              mountPath: /go/src
      volumes:
        - name: app
          hostPath:
            path: /data
            type: DirectoryOrCreate


03. ネットワーク

KubernetesリソースのCIDRブロック

▼ Nodeの場合

Node内でip addrコマンドを実行することにより、Nodeに割り当てられたCIDRブロックを確認できる。

*例*

CNIとしてBridgeアドオンを使用している。

CIDRブロックは、192.168.49.2/24である。

$ minikube ssh

# Nodeの中
docker@minikube:~$ ip addr | grep eth0

10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    inet 192.168.49.2/24 brd 192.168.49.255 scope global eth0

▼ Pod

Node内で/etc/cni/net.dディレクトリ配下にあるファイルを確認すると、Podに割り当てられたCIDRブロックを確認できる。

*例*

CNIとしてBridgeアドオンを使用している。

CIDRブロックは、10.85.0.0/16である。

$ minikube ssh

# 仮想環境の中
docker@minikube:~$ ls -la /etc/cni/net.d
-rw-r--r-- 1 root root  438 Nov 11  2021 100-crio-bridge.conf
-rw-r--r-- 1 root root   54 Nov 11  2021 200-loopback.conf

docker@minikube:~$ cat /etc/cni/net.d/100-crio-bridge.conf

{
    "cniVersion": "0.3.1",
    "name": "crio",
    "type": "bridge",
    "bridge": "cni0",
    "isGateway": "true",
    "ipMasq": "true",
    "hairpinMode": "true",
    "ipam": {
        "type": "host-local",
        "routes": [
            { "dst": "0.0.0.0/0" },
            { "dst": "1100:200::1/24" }
        ],
        "ranges": [
            [{ "subnet": "10.85.0.0/16" }],
            [{ "subnet": "1100:200::/24" }]
        ]
    }
}


04-02. Podへの接続

Minikubeの制約

Minikubeは、クラウドプロバイダーとは状況が異なり、Minikube仮想サーバー内にNodeが稼働している。

そのため、ホストからMinikube仮想サーバーに接続するための操作が必要である。


NodePort Serviceの場合

NodePort Serviceの場合、minikube serviceコマンドを使用して、Minikube仮想サーバー内のNodeに接続できる。

http://127.0.0.1:<自動的に発行されたトンネルポート番号>の形式でURLが発行されるため、ブラウザやcurlコマンドで接続を確認できる。

NodePort Serviceで指定した宛先ポート番号の数だけ、これに紐づくトンネルポート番号を発行する。

$ minikube service <NodePort Service名> --url -n foo-namespace

http://127.0.0.1:<自動的に発行されたトンネルポート番号1>
http://127.0.0.1:<自動的に発行されたトンネルポート番号2>
http://127.0.0.1:<自動的に発行されたトンネルポート番号3>

$ curl http://127.0.0.1:<自動的に発行されたトンネルポート番号>

psコマンドを使用して、NodePort Serviceのいずれの宛先ポート番号がトンネルポート番号に紐づいているかを確認できる。

$ ps -ef | grep docker@127.0.0.1

ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -N docker@127.0.0.1 -p 55972 -i /Users/FOO/.minikube/machines/minikube/id_rsa
-L <トンネルポート番号1>:<ClusterIP ServiceのIPアドレス>:<NodePort Serviceの宛先ポート番号1>
-L <トンネルポート番号2>:<ClusterIP ServiceのIPアドレス>:<NodePort Serviceの宛先ポート番号2>
-L <トンネルポート番号3>:<ClusterIP ServiceのIPアドレス>:<NodePort Serviceの宛先ポート番号3>

これは、Istio IngressGatewayをNodePort Serviceで作成している場合も使える。

$ minikube service istio-ingressgateway --url -n istio-ingress


LoadBalancer Serviceの場合

LoadBalancer Serviceの場合、minikube tunnelコマンドでLoadBalancer ServiceにEXTERNAL-IPが割り当てられるIPアドレスから、Minikube仮想サーバー内のNodeに接続できる。

$ minikube tunnel

$ curl http://<minikube tunnelコマンドでLoadBalancer Serviceに割り当てられるIPアドレス>:<LoadBalancer Serviceが待ち受けるポート番号>

ClusterIP Serviceの場合

▼ ClusterIP Serviceで頑張る

ClusterIP Serviceの場合、やや難易度が高くなる。

クラウドプロバイダーとは状況が異なり、Node外にロードバランサーを構築できず、別の方法でホストから仮想サーバー内のNodeに接続する必要がある。

minikubeのingressアドオン (Nginx Ingressコントローラー) を有効化し、Ingressとnginxを指定したIngressClassを作成する。

$ minikube addons enable ingress

Nginx Ingressコントローラーを含むIngressコントローラーは、Hostヘッダーにドメインが割り当てられたリクエストを受信し、NodeのIPアドレスを返却する。

これをMinikube上で再現するために名前解決するために、ingress-dnsアドオンを有効化する。

$ minikube addons enable ingress-dns

また、/etc/resolver/minikube-testファイルを以下の通りに編集する。

$ vim /etc/resolver/minikube-test

domain minikube
nameserver $(minikube ip)
search_order 1
timeout 5

あとは、minikubeというドメインで、Minikube仮想サーバー内のNodeに接続できる。

$ curl http://foo.minikube

kubectl port-forwardコマンドを使用する場合

妥協策として、Ingressを介さずに、Podに直接的に接続する。

# Podに直接的に指定する場合
$ kubectl port-forward pod/<Pod名> <ホストポート番号>:<Podのポート番号>

# Serviceの情報を使用して、Podを指定する場合
$ kubectl port-forward svc/<Service名> <ホストポート番号>:<Podのポート番号>

▼ NodePort Serviceを別途作成する場合

妥協策として、開発環境のみで使用するNodePort Serviceを作成する。