Cloudflare TunnelでKubernetesのサービスを公開

# Cloudflare Tunnelって何？
TunnelはパブリックIPやポート解放を必要とせず、外部からサービスにアクセスできる便利なサービスです。
これはCloudflare ZeroTrustのサービスで、無料で利用できます。
# PagesとTunnelの比較
| | 料金 | リクエスト制限 | サーバーレス | 柔軟性 | 難しさ |
| :---: | :---: | :---: | :---: | :---: | :---: |
| Pages | Free ~ | 100,000 /day | ⚪︎ | △ | 低 |
| Tunnel | Free | 無制限 | × | ⚪︎ | 高 |
- **Pages**
Pagesはサーバーレス重視な代わり柔軟性が低い印象。
大量のリクエストを捌くAPIとかは従量課金のためおすすめできない。
- **Tunnel**
Tunnelはサーバーが必要だが、柔軟性が高い印象。
完全無料のため、サーバーさえ確保できていればこちらの方がおすすめ。
ただし、インフラ等のプログラミング以外の知識もある程度必要。

# Kubernetesにデプロイ
-> [Cloudflareの公式ドキュメント](https://developers.cloudflare.com/cloudflare-one/tutorials/many-cfd-one-tunnel/)
-> [k8sのマニフェストの例](https://github.com/cloudflare/argo-tunnel-examples/tree/master/named-tunnel-k8s)

```bash
# パッケージマネージャーは適宜変更
brew install cloudflared

# 使いたいドメインを選択 （ここではexample.comを選んだものとします。）
cloudflared tunnel login

# トンネル名
export CF_TUNNEL_NAME=tunnel-dev

# ドメイン指定
export CF_TUNNEL_DOMAIN=tunnel-test.example.com

# Tunnel作成
cloudflared tunnel create $CF_TUNNEL_NAME
cloudflared tunnel route dns $CF_TUNNEL_NAME $CF_TUNNEL_DOMAIN

# 注： `<Tunnel ID>`は適宜変更
kubectl -n default create secret generic ${CF_TUNNEL_NAME}-credentials \
  --from-file=credentials.json=/Users/$USER/.cloudflared/<Tunnel ID>.json

cat <<EOF | kubectl apply -n default -f -
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cloudflared
spec:
  selector:
    matchLabels:
      app: cloudflared
  replicas: 2
  template:
    metadata:
      labels:
        app: cloudflared
    spec:
      containers:
      - name: cloudflared
        image: cloudflare/cloudflared:2022.3.0
        args:
        - tunnel
        - --config
        - /etc/cloudflared/config/config.yaml
        - run
        livenessProbe:
          httpGet:
            path: /ready
            port: 2000
          failureThreshold: 1
          initialDelaySeconds: 10
          periodSeconds: 10
        volumeMounts:
        - name: config
          mountPath: /etc/cloudflared/config
          readOnly: true
        - name: creds
          mountPath: /etc/cloudflared/creds
          readOnly: true
      volumes:
      - name: creds
        secret:
          secretName: ${CF_TUNNEL_NAME}-credentials
      - name: config
        configMap:
          name: cloudflared
          items:
          - key: config.yaml
            path: config.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: cloudflared
data:
  config.yaml: |
    tunnel: $CF_TUNNEL_NAME
    credentials-file: /etc/cloudflared/creds/credentials.json
    metrics: 0.0.0.0:2000
    no-autoupdate: true
    ingress:
    - hostname: $CF_TUNNEL_DOMAIN
      service: http://app:80
    - service: http_status:404
---
EOF

# 確認用のデプロイ
## 作成
cat <<EOF | kubectl apply -n default -f -
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin-test
spec:
  selector:
    matchLabels:
      app: httpbin-test
  replicas: 2
  template:
    metadata:
      labels:
        app: httpbin-test
    spec:
      containers:
      - name: httpbin-test
        image: kennethreitz/httpbin:latest
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: app
spec:
  selector:
    app: httpbin-test
  ports:
    - protocol: TCP
      port: 80
---
EOF
## 削除
kubectl delete deploy/httpbin-test svc/app
```

# まとめ
cloudflareがコンテナイメージを提供していて、kubernetes用のドキュメントとサンプルマニフェストをしっかり用意してくれているため、
Kubernetesを使い慣れてる人からするとかなり使いやすくなっているのではないかと思います。
是非これを機にCloudflare ZeroTrustに入門してみてはどうでしょうか！
以上！