Cloudflare Zero Trust × CoreDNS で実現するKubernetes Pod 通信の効率化

メディア統括本部 サービスリライアビリティグループ(SRG)の石川 雲(@ishikawa_kumo)です。
#SRG(Service Reliability Group)は、主に弊社メディアサービスのインフラ周りを横断的にサポートしており、既存サービスの改善や新規立ち上げ、OSS貢献などを行っているグループです。
本記事は、Kubernetes 上で稼働するアプリケーションの「外向き公開」と「内向き接続」まわりに潜む構造的な課題を、Cloudflare Zero Trust と CoreDNS を活用してどのように解決できるかを、実際の運用視点を交えながら整理したものです。
Kubernetes は非常にパワフルなプラットフォームですが、使い続けるうちに、ある種の「ちょうど面倒な部分」が徐々に浮かび上がってきます。
それは、ある日突然クラスタが壊れるタイプの事故ではなく、
  • 気づかないうちにコストをじわじわ押し上げる仕組み
  • 開発者に“儀式”的な作業を強いるフロー
  • セキュリティと利便性のバランスを崩しやすい構成
といった形で、静かに効いてくる類の問題です。
本記事は、そういった 「日常運用で積もっていくつらみ」を、ネットワーク設計とアクセス制御のレイヤーから解きほぐし、構成レベルで解消することを狙っています。

なぜ今「Pod 通信」を見直す必要があるのか


Kubernetes を使い始めた当初は、とりあえずこれでなんとかなります。
  • 外向きの公開は Ingress + ALB/GCLB
  • 内向きのアクセスは kubectl port-forward
  • 認証も必要なら Basic Auth か OAuth2 Proxy あたりで追加する
どれもドキュメントやブログでよく見る構成で、それ自体は間違いではありません。
ただし、サービスとクラスタの数が増え始めたころから、違和感が現れます。
  • LB の台数が増えすぎて、固定費がじわじわと積み上がる
  • 開発用ツールへの認証導入が難しく、Basic Auth まみれになる
  • Port Forward が乱立し、「今どのターミナルが何につながっているのか」 状態になる
  • マルチクラスタ / マルチアカウントが当たり前になると、開発環境への接続が儀式化する
どれも、特定の機能が壊れるわけではありません。
しかし、じわじわ開発者体験を悪化させ、セキュリティと運用の境界も曖昧にします。
このように蓄積してきた “つらみ” を、Cloudflare Zero Trust を軸に再構成したのが今回の話です。

全体構成の整理:外向き公開と内向き接続


この記事で扱う課題は次の 2 つに分類できます。
  1. Pod の外向き公開の複雑さ
      • Load Balancer のコスト問題
      • 認証レイヤーの設計問題
  1. Pod への内向き接続の面倒さ
      • Port Forward の限界
      • マルチクラスタ / マルチアカウント環境での開発のしづらさ
本記事では、「外向き」 → 「内向き」 の順に課題を整理し、その上で Cloudflare Zero Trust + CoreDNS でどう再設計したかを見ていきます。

課題①:Pod の外向き公開がつらい


伝統方式:Ingress + ALB / GCLB の強さと弱さ

Kubernetes で外向きに HTTP を公開するとき、もっともよく使われる方式は Ingress + マネージド LB(ALB/GCLB)です。
これ自体は機能的にも安定性にも優れていますが、現場で困り始めるのは次の2点です。

Load Balancer のコストが高い

開発チームが成長し、アプリケーションが増えるにつれ、LB の台数が爆速で増えていきます。
  • 設定 UI(内部ツール)
  • 検証用アプリ
  • メトリクスダッシュボード
  • API の Staging
など、公開したい Service が増えるほど、LB が単純に増えていくのです。少人数しか使わないツールにも毎回 ALB が生まれると、やがて環境を跨いで数十台以上規模になります。LB 1 台のコストは大きくなくても、数の掛け算で効くタイプの固定費です。
節約しようとして、
  • Listener Rule 集約
  • ALB を使わず Port Forward 運用
  • NodePort の直接公開
などの案が出ますが、どれも運用やUXに副作用が強く、本質的な解決になりません。

認証レイヤーをどこに置く問題

もう一つ厄介なのは、「認証をどこでやるか」です。
認証レイヤーがない例:
 
認証レイヤーの置く場所例1: アプリ自身の認証
認証レイヤーの置く場所例2: Pod前段(ALB)
認証レイヤーの置く場所例3: Pod前段(OAuth2 Proxy)
実は開発・内部用アプリにおける認証は非常に難しいです。
  • アプリに認証機能を付けるのは技術負債の兼ね合いで難しいことが多い
  • ALB に OIDC 認証を仕込むのも一見便利だが、OIDCの設定とロール管理、あとIaCなどが複雑化しがち
  • OAuth2 Proxy を入れると構成が一段層増える
さらに、公開中のアプリにおいて、利用者が社外の協力会社である場合も多いため、SSO に統一できない環境も珍しくありません。
その結果として「Basic Auth 運用」が蔓延し、内部アプリでもセキュリティレベルが不健康な状態に陥りがちです。

課題②:Pod の内向き接続がつらい


Port Forward の便利さと闇

はとても便利です。ローカルから指定した Pod / Service にすぐ繋げます。特別な VPN なしでも、踏み台さえあればつなげて、その場しのぎのデバッグにはとても相性がいいです。
しかし、それを多用し始めた瞬間に開発者のワークフローは破綻し始めます。
  • ターミナルが切れた瞬間に接続も消える
  • マルチクラスタでは複数セッションの維持が必要、どのターミナルがどの Pod につながっているのかを、頭で管理する必要がある
  • 同じポート番号は衝突するので管理が地味に難しい
「開発する前に、まず 複数のPort Forward を貼るところから始まる」ような状態になると、それはもうツールではなく儀式になってしまいます。

マルチクラスタ / マルチアカウントはさらに地獄

組織が大きくなり、クラスタ数・アカウント数が増えると、話はさらに複雑になります。
  • Dev / Stg / Prod が別クラスタ
  • プロダクト単位で AWS アカウントも別
  • SaaS 連携の都合で「この機能だけ Stg にしかない」などのパターンも出る
結果として、開発者はVPN の切り替え、アカウントの切り替え、context の切り替え…を繰り返すことになります。気づいたときには、開発をする前にネットワークとターミナルの儀式が始まるのです。これが積み重なっていくと、「マルチクラスタ・マルチアカウントのローカル開発はほぼ無理」と感じる人が出てきても不思議ではありません。

解決:Cloudflare Zero Trustの活用


Cloudflare Zero Trust は本来、SaaS や内部 Web アプリの保護用途で語られがちですが、Kubernetes と組み合わせると “Pod 通信の根本的な再設計” ができます。
Cloudflare のキーとなる機能は次の通りです。
  • Access:認証+ゼロトラストアクセス
    • Access Application: DNS Record ごとにアクセスコントロールを行う単位
    • Access Policy: Access Application と連携し、実際のアクセス制御を行うポリシー
    • Tunnel:内部ネットワーク → Cloudflare への安全な接続経路を張る仕組み
    • WARP:Tunnelに繋ぐClient
  • Gateway:Secure Web Gatewayをベースとなる様々なコントロール機能
    • Resolver Policy:DNS の経路制御
    • Network Policy:L4レイヤーの経路制御

外向き公開の解決:Access Application + Tunnel

Cloudflare Tunnel をクラスタ内から張り、Cloudflare Access で公開アプリケーションを保護する構成にすると、
  • LB を作らず Pod を公開できる
  • DNS / 証明書 / 認証を Cloudflare 側に集約できる
  • 認証方式をアプリから切り離し統一可能
というメリットがあります。
この構成が強いのは、「公開したいアプリ数が増えても、LB が増えない」という点です。増えていくのは ALB ではなく、Cloudflare 上の Access Application です。
Auth の方式も Access に統一されるので、Basic Auth乱立も停止できます。人間ユーザ向けのAccess Loginだけではなく、Http Headersを指定すれば素通りできるAPI Key方式も提供されています。

設定例

例えば、ArgoCD UIをALB通らずにそのままインターネット公開したい場合、以下の手順があります。
  1. ArgoCD が動いている Kubernetes クラスタに cloudflared を配置し、Tunnel を作成する
  1. Cloudflare 上で ArgoCDのドメインを用意する。ArgoCDのFQDNを とする
  1. ArgoCDの K8s Service を Tunnel 上で公開し、DNS Record を登録
  1. Access Application / Access Policy を作成し、 に対して認証を必須にする
Cloudflare の DNS Proxy 内や Access までは、TLS 証明書は Cloudflare 側が自動で管理してくれます。 Tunnel の内側(Cloudflare → cloudflared → Pod 間)は HTTP のままでもよいので、HTTPS 化のハードルがかなり低くなる点も魅力です。

設計上の注意点

1. cloudflared の設置場所
cloudflared は、対象 Pod に到達可能なネットワークに配置する必要があります。
  • 到達できない場合、Cloudflare Edge → Pod 間の通信は当然ながら成立しません
  • 逆に、cloudflared に Network Policy をきちんと設定すれば、
    • 「この Tunnel はこのネットワークだけにアクセス可能」 といった多段のネットワーク制御も実現できます
2. Tunnel のデフォルト状態は「認証なし」
  • Tunnel 上で対象 Pod への通信を開けると、cfargotunnel.com 配下に DNS Record が作成されます。この時点では 認証が一切かかっておらず、誰でもアクセス可能 な状態です。
  • そのため、Terraform 等で IaC 化する際には、の順番でリソースを作成することを強くおすすめします。Terraformでは、depends_on を使えばこの順序をきちんと表現できます。

ALBとの比較

観点伝統方式Cloudflare 方式
コスト各 App で LB 必要LB 不要,50 人まで無料
認証レイヤ配置前段配置必須Access で一元管理
設定の複雑さ各レイヤーで IaCCloudflare 関連 Iac
証明書/DNS 運用ACM/Domain Service の管理が必要Cloudflare が自動管理

内向き接続の解決:Tunnel + WARP + Resolver Policy + CoreDNS

Port Forward の限界を突破するには、「ローカルから Pod / Service に直接到達できる環境」 を作る必要があります。
方法は大きく 2 ステップです。

1. Pod / Service の IP に到達できるようにする(Tunnel + WARP)

ユーザー端末に WARP を入れ、Cloudflare Tunnel を介して Pod ネットワーク(VPC 内)を Cloudflare Edge に接続すると、VPN のように Private IP へ直接トラフィックを通せるようになります。
ここには一つの注意点があります。
AWSでは、Pod IP は問題ありませんが、Service CIDR は VPC 外なので、WARP からは Service IP に直接到達できません。Pod へ直接アクセスしたい場合は、Headless Service を利用する必要があります。

2. Service FQDN を DNS で解決できるようにする(CoreDNS 固定 IP + Resolver Policy)

Kubernetes Service の FQDN()は CoreDNS が返します。
つまり、ローカルから CoreDNS に問い合わせできれば、Pod / Service の位置は FQDN に統一されるということです。
そこで、
  • CoreDNS を Internal NLB で固定 IP 化
  •  の DNS Query を Cloudflare Gateway → Resolver Policy → CoreDNS へ転送する
という構成を作ります。
すると、WARP ON の端末は、
と URL を叩くだけで、そのクラスタの Pod へアクセスできます。

CoreDNSの固定IP化

AWS の場合、AWS Load Balancer Controller を使うと、タイプかつ 持ちの Network Load Balancer を作成できます。
これを利用して、
  • 従来の はクラスタ内部用
  • 新たに を作成し、Internal NLB + 固定 Private IP を割り当て
といった構成をとります。

Split Tunnel

次に、 の DNS Query を Cloudflare Edge にルーティングするため、WARP 側で Split Tunnel を設定します。
これにより、 への DNS Query はローカルから直接インターネットへ出ていくのではなく、Cloudflare 経由で処理されるようになります。

Resolver Policy

最後に、Cloudflare Gateway の Resolver Policy で、
  • への DNS Query が来たら
  • CoreDNS NLB の固定 IP を NameServer として指定し
  • Query をそのままフォワードする
というルールを設定します。
すべての要素を 1 つのシーケンス図で表すと、次のようなイメージです。
 
この仕組みにより、WARP ON の端末は、といった URL をそのまま叩くだけで、クラスタ内の該当 Pod / Service に到達できます。

マルチクラスタ対応:Virtual Network × 環境名つき FQDN

クラスタ数が増えるほど、「どのクラスタか」を URL に含めると明快です。
例:
Cloudflare の Virtual Network と Resolver Policy の組み合わせで、これらの URL を 正しいクラスタの CoreDNS にルーティングできます。
Resolver Policy では正規表現が使えるため、単一クラスタの だけでなく、
といったパターンにも柔軟に対応できます。
実際の Terraform 例は次のようになります。
 
これにより、マルチクラスタ・マルチアカウントでもルールは変わらず、開発者は FQDN だけで世界を切り替えられるようになります。

Port Forward との比較:構造的にどれだけ違うのか

観点Port ForwardCloudflare Zero Trust 構成
継続性Terminal と運命共同体WARP が生きていれば安定
マルチクラスタcontext / terminal 管理地獄FQDN で統一アクセス
開発体験ポート貼り直し祭りURL 叩くだけ
Port Forward を便利にしようとするのではなく、Port Forward という概念を避ける方向に構成を変えるのが肝です。

終わりに


この構成のいちばん気に入っているポイントは、
Cloudflare を CDN や DDoS 対策ツールとしてではなく、「Kubernetes の通信制御基盤」として活用しているところです。
ゼロトラストは、単なる「社外から社内へのゲート」をつくる仕組みではありません。
  • Pod 通信のパターンを整理し直す
  • 開発者のアクセス経路を統一する
  • 認証・認可・暗号化を 1 箇所に寄せる
といった観点で見直すことで、Kubernetes の「外向き公開」と「内向き接続」の両方を、構成レベルでスリムにできると感じています。
Cloudflare Zero Trust をこのような形で利用すると、
Ingress や VPN の「単なる置き換え」を超えて、新しい運用アーキテクチャの選択肢として機能してくれます。
この方法が、みなさんの Kubernetes 運用や開発者体験の改善のヒントになれば嬉しいです。
SRGにご興味ありましたらぜひこちらからご連絡ください。