kubernetesにngrokをデプロイしてルーター的に使う

#はじめに
ngrokの有料プラン($10/月)でサブドメインを取得しているので、おうちkubernetes上にngrokをデプロイしてkubernetesのサービスを外部公開しました。
ngrokは同時接続数の制限もありますが、https化できるのでBASIC認証をかけるだけで簡易的な外部公開が楽にできます。

#前提環境
ngrokのサブドメインを設定してる状態です。
![スクリーンショット 2021-05-05 0.39.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410957/9d189e25-e334-80d6-747e-67277aba45c6.png)

kubernetesのバージョンはv1.20.0〜5くらいです。(揃えてません)

```shell-session:
# kubectl get nodes -o wide
NAME    STATUS   ROLES           AGE    VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                       KERNEL-VERSION   CONTAINER-RUNTIME
chino   Ready    control-plane   233d   v1.20.5   10.0.0.1      <none>        Debian GNU/Linux 10 (buster)   5.4.83-v8+       docker://20.10.5
chiya   Ready    worker          233d   v1.20.0   10.0.0.5      <none>        Debian GNU/Linux 10 (buster)   5.4.65-v8+       docker://20.10.1
cocoa   Ready    worker          227d   v1.20.0   10.0.0.2      <none>        Debian GNU/Linux 10 (buster)   5.4.65-v8+       docker://20.10.1
maya    Ready    worker          90d    v1.20.1   10.0.0.7      <none>        Debian GNU/Linux 10 (buster)   5.4.65-v8+       cri-o://1.20.0
megu    Ready    worker          125d   v1.20.1   10.0.0.8      <none>        Debian GNU/Linux 10 (buster)   5.4.83-v8+       cri-o://1.20.0
rize    Ready    worker          227d   v1.20.0   10.0.0.3      <none>        Debian GNU/Linux 10 (buster)   5.4.65-v8+       docker://20.10.1
syaro   Ready    worker          227d   v1.20.0   10.0.0.4      <none>        Debian GNU/Linux 10 (buster)   5.4.65-v8+       docker://20.10.1
```

#構築

##ngrokコンテナの作成
ngrokのような強力なソフトウェアを動かす場合は、素性の通ったコンテナを使いたいので、自作します。
結構無駄がありますが、以下のようなDockerfileでコンテナを作成します。
※最新バージョンにしたい場合はそのままbuildすれば良いので、これくらいでちょうどいいと思います。

```:Dockerfile
FROM ubuntu
RUN apt update && \
 apt -y install wget unzip && \
 wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-arm64.zip && \
 unzip ngrok-stable-linux-arm64.zip
```

podman | docker でbuildしてpushします。
私の環境ではkubernetes内にregistryをNodePortで立てているので、kubernetesのnodeでは「localhost:30500」で使えるようにしています。
registryをどこにも持ってない方は各ノードにイメージをコピーしまくってください。

```
# podman build -t localhost:30500/ngrok:latest .
# podman push --tls-verify=false localhost:30500/ngrok:latest
```

##ConfigMapの作成
以下を参考にしてngrok.ymlを作成し、ConfigMapにします。

https://ngrok.com/docs#config-examples

「addr:」に指定するサービスはkubernetesのPodから名前解決できるサービスで「<サービス名>.<ネームスペース名>:<コンテナ内のポート番号>」で指定します。

```yaml:ngrok-configmap.yaml
apiVersion: v1
data:
  ngrok.yml: |
    authtoken: *****************************
    region: jp
    console_ui: false
    tunnels:
      k8s-elasticsearch:
        proto: http
        bind_tls: true
        addr: elasticsearch.elastic:9200
        subdomain: *****
kind: ConfigMap
metadata:
  name: ngrok-config
  namespace: default
```

```
# kubectl apply -f ngrok-configmap.yaml
```

##Deploymentの作成
作成したConfigMapを「/root/.ngrok2/ngrok.yml」にvolumeMountsさせて、「ngrok start 〜」するだけです。


```yaml:ngrok.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ngrok
  labels:
    app: ngrok
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ngrok
  template:
    metadata:
      labels:
        app: ngrok
    spec:
      containers:
      - name: ngrok
        image: localhost:30500/ngrok:latest
        command: ['sh','-c']
        args:
        - |
          /ngrok start k8s-elasticsearch
        volumeMounts:
        - name: ngrok-config
          mountPath: /root/.ngrok2/ngrok.yml
          subPath: ngrok.yml
      volumes:
      - name: ngrok-config
        configMap:
          name: ngrok-config
```

```
# kubectl apply -f ngrok.yaml
```

#確認
実際にngrok.io経由でアクセスして確認します。
ちゃんとhttpsで認証が入っているので、そこそこ問題ないと思います。

```shell-session:
# curl -XGET -u elastic https://<サブドメイン>.jp.ngrok.io
Enter host password for user 'elastic':
{
  "name" : "elasticsearch-0.elasticsearch.elastic.svc.cluster.local",
  "cluster_name" : "elasticsearch_cluster",
  "cluster_uuid" : "sYhYCwr7TeSeGGJ0hCe1vw",
  "version" : {
    "number" : "7.12.1",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "3186837139b9c6b6d23c3200870651f10d3343b7",
    "build_date" : "2021-04-20T20:56:39.040728659Z",
    "build_snapshot" : false,
    "lucene_version" : "8.8.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
```

#おわりに
ふと思ったのですが、ingressのエンドポイントをngrokで公開したらOpenShiftのrouterのようなものになりそうですね。
ただ、kubernetes内のIngress定義やサービスの設定は事前によく考える必要がありそうです。

冒頭で書いたように最大接続数に制限があるので、Kibanaなどのような豊富な画面情報があるセッションを多く貼るようなサービスは向かないと思います。