はじめに
Kubernetesでアプリケーションを外部に公開する作業は、Ingressリソースを一つ書けば終わりというわけではありません。ユーザーがブラウザにドメインを入力した瞬間からPodにパケットが届くまでには、いくつもの層が鎖のようにつながっています。ドメインのDNSレコードがクラウドロードバランサーのアドレスを指し、そのロードバランサーがクラスタノードへトラフィックを転送し、ノード上のIngressコントローラーがホストとパスを見て正しいServiceへルーティングする必要があります。
この経路のどこか一箇所でも設定を誤ると、症状はよく似た形で現れます。「ドメインに接続できません」という一行の報告の裏には、DNS伝播の問題、LoadBalancerがpendingで止まる問題、送信元IPが消えてアクセス制御が壊れる問題など、まったく異なる原因が隠れていることがあります。
この記事では、その鎖全体をたどっていきます。Ingressコントローラーを外部に公開する方法から始め、AWS・GCP・Azureのクラウドロードバランサー統合、ExternalDNSによるDNSレコードの自動化、オンプレミス環境のMetalLB、送信元IP保存のためのProxy ProtocolとexternalTrafficPolicy、マルチリージョンDNSルーティング、コスト考慮事項、そして現場で出会うトラブルシューティングまで順番に扱います。
2026年の文脈: APIの凍結と後継標準
本題に入る前に、現在のエコシステムの流れを確認しておきます。Ingress APIは安定化以降、事実上凍結(frozen)状態です。新機能はもう追加されず、Kubernetesネットワーキングの後継標準はGateway APIとして定着しました。同時に、最も広く使われてきたingress-nginxプロジェクトはメンテナンスモードに移行し、新機能よりもセキュリティパッチ中心の運用になっています。
とはいえ、この記事の内容が無意味になるわけではありません。ドメインからロードバランサーを経てクラスタへ入るトラフィック経路の原理は、IngressであろうとGateway APIであろうと同じように適用されます。ExternalDNSもすでにGateway APIのHTTPRouteをソースとしてサポートし始めており、クラウドロードバランサー統合のアノテーションの大半はServiceリソースのレベルで動作するため、上位の抽象が何であってもそのまま使えます。したがって、ここで身につける概念はGateway APIへ移行しても有効です。
トラフィック経路全体を一目で
まず、ユーザーのリクエストがPodに届くまでの経路を図で整理します。
[ユーザーのブラウザ]
| (1) app.example.com を解決
v
[DNSリゾルバ] ----> [権威DNS: Route53/Cloud DNS/Azure DNS]
| ^
| | ExternalDNS がレコードを自動生成・更新
| (2) A/CNAME 応答: LB アドレス
v
[クラウドロードバランサー (NLB/ALB/GLB)]
| (3) L4 または L7 転送
v
[クラスタノード (NodePort) または直接 Pod]
| (4) kube-proxy / 直接ルーティング
v
[Ingress コントローラー Pod (nginx/envoy など)]
| (5) Host/Path ベースのルーティング
v
[アプリケーション Service ----> Pod]
この五つの段階それぞれが別個の設定ポイントであり、この記事の各節はこの経路の一区間ずつに対応します。(1)と(2)はDNSとExternalDNS、(3)はクラウドLB統合、(4)から(5)はIngressコントローラーの公開方法と送信元IP保存に当たります。
Ingressコントローラーを外部に公開する方法
Ingressリソース自体は「どうルーティングするか」を宣言するだけで、実際にトラフィックを受ける入口はIngressコントローラーPodです。このコントローラーを外部に公開する方法は三つあり、それぞれトレードオフが異なります。
Service typeの比較
| 公開方法 | 動作 | 利点 | 欠点 | 適した環境 |
|---|---|---|---|---|
| NodePort | すべてのノードの固定ポート(30000-32767)で公開 | 追加インフラ不要、シンプル | 非標準ポート、ノードIP露出、別途LB必要 | 開発/テスト、外部LBの前段 |
| LoadBalancer | クラウドLBを自動プロビジョニング | 標準ポート、自動化、ヘルスチェック | クラウドコスト、サービスごとにLB1つ | パブリッククラウド本番 |
| hostNetwork | Podがノードネットワークを直接使用 | 最小ホップ、最高性能 | ノードごとのポート競合、スケジューリング制約 | ベアメタル、高性能要求 |
NodePort方式
最もシンプルな公開方法です。ServiceをNodePortタイプにすると、すべてのノードの特定ポートが開き、外部ロードバランサーがそのポートへトラフィックを送ります。
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
type: NodePort
selector:
app.kubernetes.io/name: ingress-nginx
ports:
- name: http
port: 80
targetPort: 80
nodePort: 30080
- name: https
port: 443
targetPort: 443
nodePort: 30443
NodePortは外部に直接公開するよりも、別途管理するロードバランサー(例: 会社標準のLBやオンプレミスのアプライアンス)の背後に置くバックエンドとしてよく使われます。
LoadBalancer方式
パブリッククラウドで最も一般的な方法です。ServiceをLoadBalancerタイプにすると、クラウドプロバイダのコントローラーが実際のロードバランサーを自動でプロビジョニングし、外部IPまたはDNS名を割り当てます。
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
type: LoadBalancer
externalTrafficPolicy: Local
selector:
app.kubernetes.io/name: ingress-nginx
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
ここでexternalTrafficPolicyは送信元IP保存に直結する重要なフィールドであり、後の独立した節で詳しく扱います。
hostNetwork方式
性能を極限まで引き上げたい場合や、ベアメタルでLB抽象なしに直接公開したい場合に使います。Podがノードのネットワーク名前空間を直接使うため、追加のネットワークホップがありません。
spec:
template:
spec:
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
containers:
- name: controller
ports:
- name: http
containerPort: 80
hostPort: 80
- name: https
containerPort: 443
hostPort: 443
ただしノードごとに80/443ポートを占有するため、1ノードに1つのコントローラーPodしかスケジューリングできず、ノードIPがそのまま露出するためノード交換時にDNS更新が必要です。
クラウドロードバランサー統合
LoadBalancerタイプのServiceを作るとき、クラウドごとにどの種類のロードバランサーをどのオプションで作るかは、Serviceに付けるアノテーションで制御します。クラウドごとにアノテーションのキーが異なるため、主要な三つのクラウドを整理します。
AWS: NLB vs ALB
AWSには大きく二種類のロードバランサーがあります。NLB(Network Load Balancer)はL4で動作し、ALB(Application Load Balancer)はL7で動作します。Ingressコントローラーの前段には通常NLBを置き、TLS終端とL7ルーティングをコントローラーに任せる構成がよく使われます。
| 項目 | NLB | ALB |
|---|---|---|
| 動作レイヤー | L4 (TCP/UDP) | L7 (HTTP/HTTPS) |
| 送信元IP保存 | デフォルトで保存可能 | X-Forwarded-Forヘッダで伝達 |
| TLS終端 | 任意(通常コントローラーで) | LBで終端 |
| 統合リソース | Service type=LoadBalancer | Ingress (AWS LB Controller) |
| コスト特性 | 時間あたり + LCU | 時間あたり + LCU |
NLBをServiceアノテーションでプロビジョニングする例です。AWS Load Balancer Controllerがインストールされている必要があります。
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: external
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: instance
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
spec:
type: LoadBalancer
externalTrafficPolicy: Local
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
ここでaws-load-balancer-proxy-protocolアノテーションは、NLBがProxy Protocol v2を通じて元のクライアント情報を伝達するようにします。これを有効にした場合、Ingressコントローラー側でもProxy Protocolを受信するように設定する必要があり、この部分は後で扱います。
ALBを使う場合は、ServiceではなくIngressリソースにアノテーションを付け、AWS Load Balancer ControllerがそのIngressを見てALBを作ります。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
alb.ingress.kubernetes.io/ssl-redirect: '443'
spec:
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-svc
port:
number: 80
GCP
GCPでは、Service type=LoadBalancerがデフォルトで外部パススルーネットワークロードバランサーを作ります。内部LBやバックエンド設定はアノテーションとBackendConfig CRDで制御します。
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
annotations:
cloud.google.com/load-balancer-type: "External"
networking.gke.io/load-balancer-type: "External"
spec:
type: LoadBalancer
externalTrafficPolicy: Local
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
内部専用LBが必要なら、cloud.google.com/load-balancer-typeの値をInternalに変えます。GKEのIngressを使うとGCE L7ロードバランサーが生成され、その場合はBackendConfigでヘルスチェック、Cloud CDN、IAPなどを細かく設定できます。
Azure
Azureでは、AKSがStandard Load Balancerをプロビジョニングします。内部LBかどうか、ヘルスプローブのパスなどをアノテーションで指定します。
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "false"
service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path: /healthz
spec:
type: LoadBalancer
externalTrafficPolicy: Local
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
内部LBが必要なら、azure-load-balancer-internalの値をtrueに設定します。ヘルスプローブのパスを明示しないとAzureはデフォルトのプローブを使いますが、externalTrafficPolicyがLocalのときはノードのヘルスチェックポートを正確に指すよう注意が必要です。
ExternalDNSでDNSレコードを自動化
ここまででロードバランサーに外部アドレスが割り当てられます。しかしユーザーはそのアドレスを直接入力せず、ドメインを入力します。したがってドメインのレコードが常に最新のLBアドレスを指すように保つ必要がありますが、これを手動で管理するとLB交換やIP変更のたびにミスが起こります。ExternalDNSはこの作業を自動化します。
ExternalDNSの動作原理
ExternalDNSはクラスタ内のServiceとIngress(およびGateway APIのHTTPRoute)リソースを監視します。ホスト名とLBアドレスの情報を読み、設定されたDNSプロバイダ(Route53、Cloud DNS、Azure DNSなど)に該当レコードを自動で生成・更新・削除します。
[Service/Ingress リソース]
- host: app.example.com
- LB アドレス: a1b2.elb.amazonaws.com
|
v
[ExternalDNS コントローラー]
| 定期的な reconcile
v
[DNS プロバイダ API]
- app.example.com CNAME a1b2.elb.amazonaws.com
- 所有権 TXT レコードを同時に生成
デプロイ例
次はRoute53をプロバイダとして使うExternalDNS Deploymentの例です。
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
namespace: external-dns
spec:
replicas: 1
selector:
matchLabels:
app: external-dns
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: registry.k8s.io/external-dns/external-dns:v0.15.0
args:
- --source=service
- --source=ingress
- --provider=aws
- --aws-zone-type=public
- --registry=txt
- --txt-owner-id=my-cluster-prod
- --policy=sync
- --domain-filter=example.com
主要な引数の説明
- sources: ExternalDNSが監視するリソースの種類です。serviceとingressを両方指定すると、両方からレコードを作ります。Gateway APIを使うならgateway-httprouteなどを追加できます。
- provider: DNSプロバイダです。aws(Route53)、google(Cloud DNS)、azureなどを指定します。
- txt-owner-id: このExternalDNSインスタンスの一意の識別子です。非常に重要な値で、後で説明します。
- policy: syncは生成・更新・削除をすべて行い、upsert-onlyは削除を行いません。運用初期はupsert-onlyで始めて安全を確認してからsyncへ切り替えるのが安全です。
- domain-filter: 管理対象ドメインを制限し、誤って別のゾーンを触らないようにします。
txtOwnerIdの重要性
ExternalDNSは自分が作ったレコードを示すために、別途TXTレコードを併せて生成します。このTXTレコードにはtxt-owner-idが入り、ExternalDNSはこの識別子が一致するレコードのみを自分の管理対象として認識します。
複数のクラスタが同じDNSゾーンを共有するとき、すべてのインスタンスのtxt-owner-idが同じだと、あるクラスタが別のクラスタの作ったレコードを自分のものと誤認して削除することがあります。したがってクラスタごと、または環境(prod/staging)ごとに一意のtxt-owner-idを必ず付与する必要があります。この一行を抜かしたために本番ドメインがまるごと消える事故は珍しくありません。
Serviceにアノテーションでホスト名を指定する例です。
apiVersion: v1
kind: Service
metadata:
name: app-svc
annotations:
external-dns.alpha.kubernetes.io/hostname: app.example.com
external-dns.alpha.kubernetes.io/ttl: "60"
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
MetalLB: オンプレミスのLoadBalancer
パブリッククラウドではなくベアメタルやオンプレミスでは、LoadBalancerタイプのServiceを作っても外部IPを自動で割り当ててくれるクラウドコントローラーがありません。その結果、Serviceは永遠にpending状態にとどまります。MetalLBはこの空白を埋め、オンプレミスでもLoadBalancerタイプを使えるようにします。
L2モードとBGPモード
MetalLBは二つのモードで動作します。
| モード | 動作 | 利点 | 欠点 |
|---|---|---|---|
| L2 (ARP/NDP) | 1ノードがVIPを所有しARPで応答 | ルーター設定不要、シンプル | 単一ノードのボトルネック、フェイルオーバー遅延 |
| BGP | ルーターとBGPピアリングしてECMP分散 | 真の負荷分散、速い収束 | BGP対応ルーターが必要、設定が複雑 |
IPプールと広告の設定
次はIPアドレスプールを定義し、L2モードで広告する例です。
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: prod-pool
namespace: metallb-system
spec:
addresses:
- 192.168.10.100-192.168.10.150
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: prod-l2
namespace: metallb-system
spec:
ipAddressPools:
- prod-pool
BGPモードを使う場合は、ルーターとのピアリングを定義します。
apiVersion: metallb.io/v1beta1
kind: BGPPeer
metadata:
name: top-of-rack
namespace: metallb-system
spec:
myASN: 64500
peerASN: 64501
peerAddress: 192.168.10.1
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
name: prod-bgp
namespace: metallb-system
spec:
ipAddressPools:
- prod-pool
L2モードは設定がシンプルですが、特定のVIPのトラフィックが常に1ノードを通過するため、そのノードがボトルネックになります。スループットが重要なら、BGPモードでECMPベースの分散を構成するほうがよいでしょう。
Proxy Protocolと送信元IPの保存
クラウドLBやMetalLBを経ると、バックエンドから見える送信元IPがクライアントの実際のIPではなく中間ノードのIPに変わることがよくあります。これはアクセス制御(IPホワイトリスト)、レート制限、監査ログ、地域ベースの処理などで問題を起こします。送信元IPを保存する方法は大きく二つです。
externalTrafficPolicy: Local vs Cluster
| 項目 | Cluster (デフォルト) | Local |
|---|---|---|
| 送信元IP | SNATで失われる | 保存される |
| 負荷分散 | すべてのノードへ再分配 | 受けたノードのPodのみ |
| 追加ホップ | ノード間ホップが発生しうる | なし |
| ヘルスチェック | すべてのノードを通過 | Podのあるノードのみ通過 |
externalTrafficPolicyがClusterの場合、トラフィックを受けたノードが別のノードのPodへ再分配することがあり、この過程でSNATが起きて送信元IPがノードIPに変わります。Localに設定すると、トラフィックを受けたノードは自ノードにあるPodへのみ転送するため、SNATがなく送信元IPが保存されます。
その代わりLocalモードでは、当該ノードにバックエンドPodがないとトラフィックが破棄されることがあるため、LBがPodの実際にあるノードへのみトラフィックを送るように、ノードのヘルスチェックが正確に動作する必要があります。
Proxy ProtocolとX-Forwarded-For
L4 LB(例: AWS NLB)ではパケットのペイロードを触らないため、送信元IPをヘッダに入れられません。代わりにProxy Protocolというプロトコルで、接続開始時に元のアドレス情報を伝達します。LBとIngressコントローラーの両方でProxy Protocolを有効にする必要があります。
ingress-nginxでProxy Protocolを受信するように設定する例です。
apiVersion: v1
kind: ConfigMap
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
data:
use-proxy-protocol: "true"
real-ip-header: "proxy_protocol"
一方、L7 LB(例: AWS ALB)はHTTPヘッダを扱えるため、X-Forwarded-ForヘッダにクライアントのIPを入れて伝達します。この場合、コントローラーはそのヘッダを信頼するように信頼プロキシ帯域を設定する必要があります。
data:
use-forwarded-headers: "true"
proxy-real-ip-cidr: "10.0.0.0/8"
注意点として、LBでProxy Protocolを有効にしたのにコントローラーで無効にすると(またはその逆だと)、コントローラーが最初のバイトをHTTPとして解釈しようとして壊れ、すべてのリクエストが失敗します。両方の設定は必ず一致させる必要があります。
マルチクラスタ・マルチリージョンDNS
一つのドメインを複数のリージョンや複数のクラスタに分散するときは、DNSレベルのルーティングポリシーが必要です。Route53を例にとると、重み付け、レイテンシベース、地理ベースのルーティングをサポートします。
ルーティングポリシーの比較
| ポリシー | 動作 | 用途 |
|---|---|---|
| 重み付け | 比率どおりにトラフィック分配 | 段階的ロールアウト、ブルー/グリーン |
| レイテンシベース | 最も速いリージョンへ | グローバル性能最適化 |
| 地理ベース | ユーザー位置ごとのリージョン | データ主権、規制遵守 |
| フェイルオーバー | ヘルスチェック失敗時にバックアップへ | 災害復旧 |
ExternalDNSはアノテーションを通じてこれらのポリシーを表現できます。重み付けルーティングの例です。
apiVersion: v1
kind: Service
metadata:
name: app-region-a
annotations:
external-dns.alpha.kubernetes.io/hostname: app.example.com
external-dns.alpha.kubernetes.io/aws-weight: "80"
external-dns.alpha.kubernetes.io/set-identifier: region-a
spec:
type: LoadBalancer
ports:
- port: 80
別のリージョンのクラスタでは、同じホスト名に別のset-identifierと重みを付与します。両クラスタのExternalDNSが同じゾーンを管理するため、先に強調したtxt-owner-idをクラスタごとに区別し、set-identifierを一貫して付与することが衝突を防ぐ鍵です。
コスト考慮事項
ロードバランサーとDNSは運用費に直接影響します。設計段階でコストモデルを理解しておけば、後で請求書を見て驚かずに済みます。
- Serviceごとにロードバランサーを作ると、LBの数だけ時間あたり料金が掛け算されます。Ingressコントローラー一つの背後に複数のサービスをホスト/パスでルーティングすればLBは一つで済むため、コストが大きく下がります。これがServiceごとにLoadBalancerタイプを作らずIngressを使う主な経済的理由です。
- AWSのLCU(Load balancer Capacity Unit)のように、スループット・接続数・ルール数に応じて課金されるモデルは、トラフィックが増えると時間あたりの固定費より大きな割合を占めることがあります。
- クロスゾーン負荷分散を有効にすると可用性は上がりますが、可用性ゾーン間のデータ転送料金が発生します。トラフィックが多ければこの料金は無視できません。
- DNSクエリ自体も百万クエリ単位で課金されます。TTLを短くしすぎるとクエリ数が増え、コストと負荷がともに増加します。ただしフェイルオーバーや頻繁な変更が必要なレコードは短いTTLが必要なので、バランスを取る必要があります。
トラブルシューティング
現場でよく出会う三つの症状と診断フローを整理します。
LoadBalancerがpending状態
ServiceがEXTERNAL-IP欄にpendingだけを表示して止まる場合です。
kubectl get svc -n ingress-nginx
kubectl describe svc ingress-nginx-controller -n ingress-nginx
kubectl get events -n ingress-nginx --sort-by=.lastTimestamp
原因の診断フローです。
LoadBalancer pending
|
+-- オンプレミスか? --はい--> クラウドコントローラーなし。MetalLB 等の導入が必要
|
+-- クラウドか?
|
+-- cloud-controller-manager は動作中? --いいえ--> コンポーネント点検
+-- LB Controller(AWS 等)は導入済み? --いいえ--> 導入/IAM 権限を確認
+-- サブネットタグ/クォータの問題? --はい--> サブネットタグ、LB クォータを確認
DNS伝播の遅延
レコードは作られたのに、ドメインがまだ古いアドレスを指している場合です。
dig +short app.example.com
dig app.example.com @8.8.8.8
kubectl logs -n external-dns deploy/external-dns | tail -50
ExternalDNSのログでレコードが実際にupsertされたかをまず確認し、その次に権威ネームサーバへ直接問い合わせます。権威ネームサーバはすでに更新されているのにクライアントが古い値を見ているなら、それはTTL分のキャッシュ残存であり、時間が経てば解消します。権威ネームサーバ自体が古い値なら、ExternalDNSの権限やゾーン設定の問題です。
送信元IPが失われる
バックエンドのログにクライアントIPではなくノードIPやLB IPだけが記録される場合です。
送信元 IP 損失
|
+-- externalTrafficPolicy=Cluster か? --はい--> Local への変更を検討
|
+-- L4 LB(NLB)で Proxy Protocol を片側だけ有効にしたか?
| --はい--> LB とコントローラーの両側を一致させる
|
+-- L7 LB(ALB)で X-Forwarded-For を非信頼? --はい--> 信頼プロキシ CIDR を設定
最もよくある罠は、Proxy ProtocolをLBだけ、またはコントローラーだけで有効にした場合です。このときは送信元IP損失を超えて接続自体が壊れるため、上のフローでは最初に両側の一致を確認すべきです。
運用チェックリスト
- Ingressコントローラーの公開方法(NodePort/LoadBalancer/hostNetwork)を環境に合わせて選んだか。
- クラウドごとのLBアノテーションが意図したLBの種類(NLB/ALBなど)とスキーム(internet-facing/internal)を正確に指しているか。
- ExternalDNSのtxt-owner-idがクラスタ・環境ごとに一意か。
- ExternalDNSのpolicyを初期はupsert-onlyにして検証後にsyncへ切り替えたか。
- domain-filterで管理対象ゾーンを制限したか。
- externalTrafficPolicyの設定と送信元IP保存の要件が一致しているか。
- Proxy Protocolを使うなら、LBとコントローラーの両側の設定が一致しているか。
- マルチリージョンならset-identifierとルーティングポリシーが一貫しているか。
- LBの数とクロスゾーン転送コストを検討したか。
- DNS TTLがフェイルオーバー要件とクエリコストの間でバランスが取れているか。
おわりに
ドメインから始まり、クラウドロードバランサー、Ingressコントローラーを経てPodまで続く経路は長く、各区間ごとに別個の設定ポイントがあります。この記事では、公開方法の選択、クラウドごとのLB統合、ExternalDNS自動化、MetalLB、送信元IP保存、マルチリージョンルーティング、コスト、トラブルシューティングまで、その経路全体をたどってきました。
要点は、各区間を独立して理解しつつ、区間どうしの約束(例: Proxy Protocolの両側一致、txt-owner-idの一意性、externalTrafficPolicyとヘルスチェックの整合)を見落とさないことです。また2026年現在、Ingress APIは凍結されGateway APIが後継標準ですが、ここで扱ったトラフィック経路の原理とExternalDNS・LB統合はGateway APIへ移行しても通用します。今この経路をしっかり理解しておけば、抽象が変わっても揺らがないでしょう。
参考資料
- ExternalDNS 公式ドキュメント: https://kubernetes-sigs.github.io/external-dns/
- Kubernetes Services and Networking: https://kubernetes.io/docs/concepts/services-networking/service/
- Kubernetes Ingress: https://kubernetes.io/docs/concepts/services-networking/ingress/
- ingress-nginx 公式ドキュメント: https://kubernetes.github.io/ingress-nginx/
- AWS Load Balancer Controller: https://kubernetes-sigs.github.io/aws-load-balancer-controller/
- MetalLB 公式ドキュメント: https://metallb.io/
- GKE ロードバランシングドキュメント: https://cloud.google.com/kubernetes-engine/docs/concepts/ingress
- Azure AKS ロードバランサードキュメント: https://learn.microsoft.com/en-us/azure/aks/load-balancer-standard
- Gateway API: https://gateway-api.sigs.k8s.io/
- Kubernetes 送信元IP保存: https://kubernetes.io/docs/tutorials/services/source-ip/
현재 단락 (1/387)
Kubernetesでアプリケーションを外部に公開する作業は、Ingressリソースを一つ書けば終わりというわけではありません。ユーザーがブラウザにドメインを入力した瞬間からPodにパケットが届くまで...