minikube tunnelを試してみた

# 概要
minikubeの[CHANGELOG](https://github.com/kubernetes/minikube/blob/master/CHANGELOG.md)によるとVersion 0.31.0から`minikube tunnel`というコマンドが使えるようになったようなので、調査してみる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/100375/77cba493-4027-5ad8-6d71-7a174a67fea3.png)


# どんな機能なのか？

[minikube tunnel by balopat · Pull Request #3015 · kubernetes/minikube · GitHub](https://github.com/kubernetes/minikube/pull/3015)

Issueから辿れるデザインドキュメントはこちら。[minikube/tunnel.md at master · kubernetes/minikube · GitHub](https://github.com/kubernetes/minikube/blob/master/docs/tunnel.md)
説明書はないので、このデザインドキュメントが頼り

とりあえず最新のminikubeにする

```console
$ minikube version
minikube version: v0.33.1
```

何も考えずヘルプを実行してみる

```console
$ minikube tunnel --help
tunnel creates a route to services deployed with type LoadBalancer and sets their Ingress to their ClusterIP

Usage:
  minikube tunnel [flags]

Flags:
  -c, --cleanup   call with cleanup=true to remove old tunnels
  -h, --help      help for tunnel
（略）
```

Serviceのtype=LoadBalancerのものが、ホストからもアクセスできるようなことが書いてある。

# とりあえずやってみる

そういうサービスを作ってみる。

```

$ kubectl run --image=nginx nginx
kubectl run --generator=deployment/apps.v1beta1 is DEPRECATED and will be removed in a future version. Use kubectl create instead.
deployment.apps/nginx created
$ kubectl expose deployment nginx --port 80 --type=LoadBalancer
service/nginx exposed
$ kubectl get svc
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP      10.96.0.1       <none>        443/TCP        80m
nginx        LoadBalancer   10.106.99.252   <pending>     80:30037/TCP   3s
```

そして、minikube tunnelを実行

```console
$ minikube tunnel
Password:   # <-- ルーティングをいじるために、パスワードを求められる
E0122 17:40:38.807968   51021 loadbalancer_patcher.go:108] error patching nginx with IP 10.106.99.252: %!s(<nil>)
Status:
    machine: minikube
    pid: 51021
    route: 10.96.0.0/12 -> 192.168.99.101
    minikube: Running
    services: [nginx]
    errors:
        minikube: no errors
        router: no errors
        loadbalancer emulator: no errors
```

上手いこといったっぽい！
nginxのServiceのClusterIPである
http://10.98.236.108/
でブラウザからアクセスできるようになった。

またServiceを見て見るとEXTERNAL-IPとしてCLUSTER-IPと同じものが登録されていることが確認できた。

```console
$ kubectl get svc
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
kubernetes   ClusterIP      10.96.0.1       <none>          443/TCP        81m
nginx        LoadBalancer   10.106.99.252   10.106.99.252   80:30037/TCP   56m
```

これでminikubeでもLoadBalancerが使えるようになった。

これがどのように実現されているかというと、
[デザインドキュメント](https://github.com/kubernetes/minikube/blob/master/docs/tunnel.md#network-routes)にOSごとの実現方法が記載されている。
今回はMacOSXで実行しているので、このようにするとルーティングにそれっぽいエントリが追加されていることが確認できた。

```

$ netstat -nr -f inet
Routing tables

Internet:
Destination        Gateway            Flags        Refs      Use   Netif Expire
default            192.168.152.1      UGSc           65        0     en0
10.96/12           192.168.99.101     UGSc            0        0 vboxnet          # <---------これ
127                127.0.0.1          UCS             0        0     lo0
127.0.0.1          127.0.0.1          UH              6    79977     lo0
(略)
```

minikube tunnelはフォアグラウンドで実行され、Ctrl+Cで停止しようとすると、再びパスワードを求められた。（おそらくルーティングを掃除するためだと思われる。）

# いろいろ試す
## type=LoadBalancerじゃなくてもいいよね？

ルーティングを見る限りtype=LoadBalancerじゃなくても行けそう。
ということでtype=ClusterIPでも試してみる。

```console
$ kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   24m
nginx        ClusterIP   10.106.99.252   <none>        80/TCP    5s
```

これでもホストPCからアクセスできた。

## Podに直接アクセスできる？

PodはIPの範囲が違うので、アクセスできなそう

```console
$ kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
nginx-7cdbd8cdc9-br966   1/1     Running   0          24m   172.17.0.6   minikube   <none>           <none>
```

## クラスタ内DNSの名前でアクセスすることはできるか？
あまり一般的な使い方ではないかもしれないが、クラスタ内DNSでアクセスができるようにならないか？

```console
$ kubectl get svc -n kube-system
NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)         AGE
default-http-backend   NodePort    10.103.185.56   <none>        80:30001/TCP    35m
kube-dns               ClusterIP   10.96.0.10      <none>        53/UDP,53/TCP   35m
```
このkube-dnsも先ほどのルーティングでホストからアクセスできるようになっているはず。

```console
$ nslookup
> server 10.96.0.10
Default server: 10.96.0.10
Address: 10.96.0.10#53
> nginx.default.svc.cluster.local
Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   nginx.default.svc.cluster.local
Address: 10.106.99.252
>
```

ホストからクラスタ内DNSにアクセスできた。

DNSを差し替えると・・・

<img src="https://qiita-image-store.s3.amazonaws.com/0/100375/ee8902f7-d8ca-4348-82d1-98dcc3baafe9.png" width="300px">

ホストPCからクラスタ内DNSを利用してアクセスすることができた！

![image.png](https://qiita-image-store.s3.amazonaws.com/0/100375/803e1308-9f5c-a8fd-4a62-7228f38e44cf.png)

# 結論

この機能を使うとminikubeを実行しているホストPCから、type=LoadBalancerのサービスにアクセスすることができるようになった。
さらにクラスタ内のServiceのClusterIPに直接アクセスすることができる！

また、うまくDNSの設定を行うと、クラスタ内DNSを使うこともできることを確認した。