はじめに
k3s
を使った検証環境の構築中に、Traefik
やIngress
を設定しても外部からアクセスできない(502 Bad Gateway) という問題に直面しました。結論から言うと、原因はfirewalld
による通信遮断でした。
事象
- k3s をインストールし、HelmChart により Traefik(Ingress Controller)をインストール
- Ingress / Service / Pod の設定を完了
- kubectl get ingress, kubectl get svc, kubectl get pods など、全て正常
- しかし、外部端末から http://<ホストIP> にアクセスすると 502 Bad Gateway
原因
firewalld
が、k3s の仮想NIC(例:cni0, flannel.1)からの通信をブロックしていたため。
その結果、Traefik が Pod へルーティングしようとしても通信が遮断され、外部からのリクエストに対して 502 が返されていた。
対策
firewalldのゾーン設定を見直しました。
内部通信を許可するために、以下のようにゾーンを設定しました。
# デフォルトゾーンを trusted に変更(内部通信をすべて許可)
sudo firewall-cmd --set-default-zone=trusted
# 外部NIC(例:enp0s3)を public に設定(外部からの制限は継続)
sudo firewall-cmd --zone=public --change-interface=enp0s3 --permanent
# 設定を反映
sudo firewall-cmd --reload
※本番では適切なゾーン・ポート設定を。
補足:ルーティングの流れとfirewalldの影響
今回の構成は以下です。
外部クライアント
↓
ホストマシン (publicゾーンのNIC)
↓
Traefik (Ingress Controller)
↓
Service → Pod
このうち、「Traefik → Pod」や「Service → Pod」の通信が firewalld により遮断されていました。その結果、Traefik は「バックエンドに接続できない」と判断し、502 Bad Gateway を返しました。
振り返り
今回の502 Bad Gateway
は、ゲートウェイ(ここでは Traefik)がバックエンドから有効な応答を受け取れなかった」ことを示します。
エラー内容から、リクエスト自体はTraefikに届いていると判断できたため、当初はアプリケーション寄りの設定ミスを疑い、上位レイヤから調査を進めてしまいました。
- TraefikのHelmChart設定(entryPoints、servicePorts)
- Ingressのルーティング設定
- Serviceのselectorやportの不整合
- Railsアプリのlistenポートやhost設定
- TLS証明書のミスやSSL終端の誤設定
結果としてこれらは問題なく、原因は、 ネットワーク層での通信制御(firewalld) でした。
教訓
「分からない技術=怪しい」と思い込み、いきなり上位レイヤー(アプリ層)から調べ始めてしまったことが遠回りの原因でした。
特に Kubernetes のような多層構造のある技術では、下位レイヤー(OS、ネットワーク)から順に切り分ける意識が非常に重要だと感じました。
以上です!
参考にした記事