Kubernetes上のアプリケーションを外部に公開する方法を調べています。以前から自宅サーバのアプリケーションをCloudflare Tunnelを使って公開しているので同じことができないか調べたところ、STRRL/cloudflare-tunnel-ingress-controllerを見つけました。Cloudflare公式の仕組みではありませんが、名前の通りCloudflare Tunnelでサービスを公開するためのIngress Controllerです。今回はこちらの仕組みを実際に使ってみました。
Service、Ingress、Ingress 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で独自ドメインを保有している必要がありますが、それさえ満たしていれば使い勝手の良い選択肢になると思います。