succi0303 blog

This is my personal blog. All posts are my own.

STRRL/cloudflare-tunnel-ingress-controllerを使ってKubernetesのアプリケーションをインターネットへ公開してみた

Kubernetes上のアプリケーションを外部に公開する方法を調べています。以前から自宅サーバのアプリケーションをCloudflare Tunnelを使って公開しているので同じことができないか調べたところ、STRRL/cloudflare-tunnel-ingress-controllerを見つけました。Cloudflare公式の仕組みではありませんが、名前の通りCloudflare Tunnelでサービスを公開するためのIngress Controllerです。今回はこちらの仕組みを実際に使ってみました。

Service、IngressIngress Controller

Kubernetes上のアプリケーションを外部へ公開する基本的な仕組みとしてサービス (Service) があります。サービスはClusterIP、NodePort、LoadBalancerの3つのタイプに分かれます。ClusterIPはクラスタ内でIPアドレスを割り当てクラスタ内部にアプリケーションを公開するh仕組み、NodePortはアプリケーションをさらにホストのポートに割り当てクラスタ外部へアプリケーションを公開する仕組み、LoadBalancerはクラスタ外部のロードバランサーを介してクラスタ外部へアプリケーションを公開する仕組みです。一般的にクラウドプロバイダのマネージドKubernetesでLoadBalancer Serviceを作ると自動的に各サービスのロードバランサーと関連付けがなされます。一方、ベアメタル環境でLoadBalancer Serviceを利用するには別途ロードバランサーを準備する必要があり、MetalLBが主要な選択肢であるようです。

サービスとは別にアプリケーションを外部へ公開する仕組みとしてIngressがあります。Ingressはアプリケーション層のリソースでクラスタ外部からのHTTP/HTTPS通信をクラスタ内へルーティングできます。Ingressを利用するにはIngress Controllerが動作している必要があり、Nginx Ingress Controller、Traefk kubernetes Ingress Provisionerといった実装があります。

今回利用するcloudflare-tunnel-ingress-controllerはIngress Controllerに該当し、Cloudflare TunnelをIngressとしてHTTP/HTTPSでアプリケーションをインターネットへ公開できます。Ingress (Cloudflare Tunnel) -> Service (ClusterIP) -> Podの流れで通信するため外部ロードバランサーは不要です。

前提条件と事前準備

Cloudflareのアカウントを作成すること、CloudflareのDNSドメインを管理していいることが必要です。また、cloudflare-tunnel-ingress-controllrのインストールにHelmを使います。

事前準備としてCloudflareのアカウントAPIトークンとアカウントIDを取得します。アカウントAPIトークンを取得するにはCloudflareダッシュボードの「アカウントの管理」-「アカウントAPIトークン」から「トークンを作成する」を選択します。アクセス許可を次の画像のように設定します。

アカウントIDはダッシュボードのウェブサイトメニューでアプリケーション公開に利用するドメインを選択したページの右下に記載されています。

Helmリポジトリを追加してcloudflare-tunnel-ingress-controllerをインストールします。インストールコマンドの中で事前に取得したAPIトークンとアカウントIDを指定します。また任意のトンネル名を指定します。

helm repo add strrl.dev https://helm.strrl.dev
helm repo update

helm upgrade --install --wait \
  -n cloudflare-tunnel-ingress-controller --create-namespace \
  cloudflare-tunnel-ingress-controller \
  strrl.dev/cloudflare-tunnel-ingress-controller \
  --set=cloudflare.apiToken="<cloudflare-api-token>",cloudflare.accountId="<cloudflare-account-id>",cloudflare.tunnelName="<your-favorite-tunnel-name>" 

サンプルアプリケーションをCloudflare Tunnelで公開

Deploymentを作成してテスト用のechoserverアプリケーションをデプロイします。

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: echoserver
  name: echoserver
spec:
  replicas: 3
  selector:
    matchLabels:
      app.kubernetes.io/name: echoserver
  template:
    metadata:
      labels:
        app.kubernetes.io/name: echoserver
    spec:
      containers:
      - image: gcr.io/google-containers/echoserver:1.10
        name: echoserver
kubectl apply -f deployment.yaml

ClusterIPのサービスを作成してクラスタ内部にechoserverを公開します。

---
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: echoserver
  name: echoserver
  annotations:
    loadbalancer.openstack.org/x-forwarded-for: "true"
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
    name: http
  selector:
    app.kubernetes.io/name: echoserver
  type: ClusterIP
kubectl apply -f service.yaml

最後にcloudflare-tunnel-ingress-controllerを使ってIngressを作成します。rulesの中で公開に利用したいホスト名(echo.example.comなど)を指定し、ターゲットとして事前に作成したサービスを指定します。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: echoserver-ingress
spec:
  ingressClassName: "cloudflare-tunnel"
  rules:
  - host: <your app domain>
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: echoserver
            port:
              number: 80
kubectl apply -f ingress.yaml

動作確認

ブラウザを開いてIngressで指定したホスト名をアドレスバーに入力します。「Hostname:」で始まるechoserverのレスポンスが表示され、アプリケーションがインターネットへ公開されたことが確認できました。

まとめと感想

STRRL/cloudflare-tunnel-ingress-controllerを使ってKubernetesのアプリケーションをCloudflare Tunnel経由でインターネットへ公開しました。とても簡単にアプリケーションを公開できました。また、Cloudflare Tunnelの設定がIngressの設定ファイルで完結するので初期設定だけすれば都度Cloudflareのダッシュボードをぼちぼちする必要がないところも便利だと思いました。公開したアプリケーションに対しては、Cloudflareの機能で認証とアクセス制限をかけることも可能です。Cloudflareで独自ドメイン保有している必要がありますが、それさえ満たしていれば使い勝手の良い選択肢になると思います。

参考リンク