Istio Gatewayは、Kubernetesクラスタの外から来る通信をサービスメッシュへ入れる入口の設定です。この記事では、ingress gatewayのHelmインストールから、GatewayとVirtualServiceのYAML、credentialNameを使うTLS終端、Kubernetes Gateway APIで同じ公開をする書き方までを、Istio 1.31系の公式ドキュメントに沿ってコマンド付きでまとめました。404やEXTERNAL-IPのpendingで止まったときの確認手順と、新規構築でどちらのAPIを選ぶかの判断も扱います。
まとめ:Istio Gatewayは待ち受け定義で、振り分けは別リソースに書く
Istio APIでは、Gatewayリソースに「どのホストとポートで受けるか」だけを書き、受けた通信をどのServiceへ送るかはVirtualServiceに書きます。実際に通信をさばくのはEnvoyが動くingress gatewayのPodで、Gatewayリソースはそこへ配られる設定にすぎません。
新規構築なら、Kubernetes Gateway API(GatewayとHTTPRoute)が第一候補です。Istioは公式ドキュメントでGateway APIを将来の既定APIにする方針を示しており、Gatewayを作るだけでゲートウェイのDeploymentとServiceが自動で作られます。VirtualServiceで重み付けやリトライを組んだ環境は、Istio APIのままで差し支えありません。
TLS終端は、証明書のSecretをゲートウェイのPodと同じnamespaceに置き、Gatewayから名前で参照する形が基本です。更新を自動にするなら、cert-managerのCertificateも同じnamespaceに置きます。
Istio GatewayとIngress Gatewayの役割と2つの設定APIの関係
「Istio Gateway」は、通信を受けるPodと、そこへ渡す設定リソースの両方を指す語です。書き方も2系統あるため、先に切り分けが要ります。仕組みの全体像はIstioとは?サービスメッシュの仕組みとサイドカー/アンビエント方式・導入判断を解説を参照してください。
Envoyが動くIngress Gateway本体とGatewayリソースの関係
ingress gatewayは、サイドカーを持たない単独のEnvoyプロキシとして動くDeploymentです。前段にLoadBalancer型のServiceが付き、クラウドのロードバランサーから通信を受けます。
Istio APIのGatewayリソースは、selectorのラベルでこのPodを選び、待ち受けるポート・プロトコル・ホスト名・TLS設定を渡します。Istio公式のGatewayリファレンスによると、selectorは既定で全namespaceからワークロードを探す仕様です。ルーティング規則はGatewayに書けず、VirtualServiceがgateways欄でGatewayを名指しして初めて通信が流れます。
Istio APIとGateway APIの対応関係と1.31系での位置づけ
同じ公開を2つのAPIで書けます。対応関係は次のとおりです。
| 役割 | Istio API | Kubernetes Gateway API |
|---|---|---|
| 待ち受けの定義 | Gateway | Gateway |
| HTTPの振り分け | VirtualService | HTTPRoute |
| Podの用意 | Helm等で事前に導入 | Gateway作成時に自動 |
| CRDの導入 | Istio本体に同梱 | 別途インストール |
IstioのKubernetes Gateway APIのページは、Gateway APIを将来の既定のトラフィック管理APIにする意図を明記しています。VirtualServiceが1リソースに全プロトコルを書くのに対し、Gateway APIはHTTPRouteやTCPRouteとプロトコルごとに分かれる点も違いです。Istioのサポート表では、2026年10月時点で1.31系(8月27日公開・Kubernetes 1.32〜1.37対応)と1.30系がサポート中で、1.29系は10月15日に終了しました。版ごとの差分はIstioの最新バージョンは1.31|1.28〜1.31の新機能・サポート期限とアップグレード手順にまとめています。
Ingress Gatewayを専用namespaceへHelmでインストールする手順
Istio APIで公開する場合は、ゲートウェイのPodを自分で用意します。istioctlの既定プロファイルでも入りますが、本番ではコントロールプレーンと切り離して入れる形が公式の推奨です。
Helmのgateway chartでistio-ingressへ入れるコマンド
公式のInstalling Gatewaysは、セキュリティ上の理由からゲートウェイをコントロールプレーンと別のnamespaceに置くよう勧めています。istiodを入れた後に、公式のHelmインストール手順と同じ次のコマンドで導入します。チャートの配布元はblob.istio.ioです。
kubectl create namespace istio-ingress
helm repo add istio https://blob.istio.io/istio-release/charts
helm repo update
helm install istio-ingress istio/gateway -n istio-ingress --wait
# Gatewayのselectorに書くラベルと、外部IPを確認する
kubectl get pods -n istio-ingress --show-labels
kubectl get svc -n istio-ingress
注意点は2つです。ゲートウェイのnamespaceにistio-injection=disabledラベルが付いていると、Podが起動に失敗します。もう1つはselectorに書くラベルの値で、公式のIngress Gatewaysの手順は、istioctlの既定ゲートウェイならistio: ingressgateway、Helmの標準手順ならistio: ingressと注記しています。推測で書かず、上の--show-labelsで実際の値を見てからGatewayに写してください。
共有ゲートウェイと専用ゲートウェイの配置方式とIPの数の違い
公式ドキュメントは配置方式を2つ挙げています。1つの中央ゲートウェイを多数のアプリとnamespaceで共有する方式と、アプリのnamespaceごとに専用のゲートウェイを置く方式です。
共有型は、ドメインやワイルドカード証明書を1か所で管理したい場合に向く方式です。専用型は要件の厳しいアプリを隔離できる一方、前段に別のロードバランサーが無ければアプリの数だけ外部IPが要り、DNSの管理が増えます。社内システムを数本公開する程度なら共有型1つで十分です。
GatewayとVirtualServiceでHTTPを公開するYAMLの例
ここからは公式タスクのhttpbinを例に、80番でHTTPを受けてServiceへ流す最小構成を作ります。apiVersionはnetworking.istio.io/v1です。日本語の解説記事にはv1alpha3のままのものが残るので、写すときは注意してください。
selectorとhostsで待ち受けを定義するGatewayマニフェスト
公式のIngress Gatewaysタスクと同じ形です。selectorは前の手順で確認したラベルに合わせます。
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: httpbin-gateway
spec:
selector:
istio: ingress # 実際のPodのラベルに合わせる
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "httpbin.example.com"
hostsにはnamespace/ホスト名の形で、どのnamespaceのVirtualServiceを受け入れるかも書けます。リファレンスによれば、接頭辞を省くと全namespaceが対象です。共有ゲートウェイではprod/*.example.comのように絞ると、別チームのVirtualServiceが同じホスト名を奪う事故を防げます。
VirtualServiceのgateways指定で振り分けを結び付ける設定
Gatewayで受けた通信の行き先は、VirtualServiceで指定します。gatewaysにGateway名を書き、hostsをGatewayと一致させます。
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- "httpbin.example.com"
gateways:
- httpbin-gateway
http:
- match:
- uri:
prefix: /status
- uri:
prefix: /delay
route:
- destination:
host: httpbin
port:
number: 8000
このVirtualServiceは/statusと/delayだけを公開します。それ以外のパスは404です。GatewayとVirtualServiceが別のnamespaceにある場合は、gatewaysをistio-ingress/httpbin-gatewayのようにnamespace付きで書きます。重み付けやリトライの書き方は、VirtualServiceのリファレンスに項目の一覧があります。重み付けによるカナリアやtimeout・retriesの具体的なYAMLは、Istio VirtualServiceの書き方:DestinationRuleとカナリア・リトライのYAML例で解説しています。
外部IPの取得とHostヘッダー付きcurlによる疎通確認の手順
DNSを設定する前でも、Hostヘッダーを付ければ動作を確かめられます。Service名とnamespaceは、Helmで入れた場合は前の手順の値に置き換えてください。
export INGRESS_NS=istio-ingress
export INGRESS_NAME=istio-ingress
export INGRESS_HOST=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl -n "$INGRESS_NS" get service "$INGRESS_NAME" -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
curl -s -I -HHost:httpbin.example.com "http://$INGRESS_HOST:$INGRESS_PORT/status/200"
200が返れば成功です。AWSのNLBのようにロードバランサーがIPではなくホスト名を返す環境では、jsonpathのipをhostnameに変えます。
credentialNameとcert-managerで設定するTLS終端の手順
HTTPSで公開するには、ゲートウェイで証明書を提示してTLSを終端します。証明書をアプリのPodに持たせる必要はありません。
Secret作成とSIMPLEモードで443番を受けるHTTPS Gateway
公式のSecure Gatewaysタスクの流れです。証明書と秘密鍵からSecretを作り、GatewayのcredentialNameに同じ名前を書きます。
kubectl create -n istio-ingress secret tls httpbin-credential \
--key=httpbin.example.com.key \
--cert=httpbin.example.com.crt
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: httpbin-gateway
spec:
selector:
istio: ingress
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: httpbin-credential
hosts:
- "httpbin.example.com"
SecretはゲートウェイのPodと同じnamespaceに作ります。公式タスクは既定ゲートウェイのあるistio-systemに作っており、Helmでistio-ingressへ入れた場合はそちらが置き場所です。自己署名の証明書で試すときは、SAN(subjectAltName)を必ず入れてください。公式タスクは、SANが無い証明書はChromeなどのブラウザに拒否されると注記しています。
httpsRedirectと最小TLSバージョンで平文を受けない構成
HTTPで来た通信をHTTPSへ寄せるには、80番のserverにhttpsRedirect: trueを付けます。リファレンスでは、これを有効にすると全HTTP接続に301リダイレクトを返すと定義されています。
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "httpbin.example.com"
tls:
httpsRedirect: true
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- "httpbin.example.com"
tls:
mode: SIMPLE
credentialName: httpbin-credential
minProtocolVersion: TLSV1_3
minProtocolVersionの既定値はTLSV1_2で、TLSV1_3へ上げるのは取引先の古いクライアントを切ってよいと確かめてからです。modeにはSIMPLEのほか、クライアント証明書を必須にするMUTUAL、終端せずSNIで振り分けるPASSTHROUGH、Istio発行の証明書で相互認証するISTIO_MUTUALなどがあります。MUTUALのSecretはgeneric型で作り、ca.crtを足す形です。相互認証の考え方はmTLSとは?相互TLS認証の仕組みとクライアント証明書・導入判断を実装目線で解説で扱っています。
cert-managerのCertificateはゲートウェイと同じnamespaceへ
証明書の更新を自動にするなら、cert-managerにSecretを作らせます。Istio公式のcert-manager連携ページは、Certificateをingress gatewayのDeploymentと同じnamespaceに作るよう明記しています。Secretはゲートウェイと同じnamespaceからしか読まれないためです。
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: httpbin-cert
namespace: istio-ingress
spec:
secretName: httpbin-credential # GatewayのcredentialNameと一致させる
dnsNames:
- httpbin.example.com
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
issuerRefは作成済みのIssuerに合わせます。アプリのnamespaceにCertificateを置き、Secretはあるのにゲートウェイが証明書を返さない、というのが典型的な詰まり方です。
Gateway APIのGatewayとHTTPRouteで同じ公開をする書き方
同じhttpbinの公開をGateway APIで書きます。ゲートウェイのPodを事前に入れる必要はなく、ingress-nginxからの移行先にもなる形です。退役の経緯はNGINX Ingressとは?退役したingress-nginxとF5版の違い・移行判断を参照してください。
Gateway API CRDの導入とgatewayClassNameの指定
Gateway APIのCRDは多くのクラスタに既定では入っていません。Istio 1.31系の公式手順は、v1.6.0のCRDを入れるコマンドを示しています。Gateway APIのリリース一覧では、2026年10月時点の最新安定版はv1.6.3です。
kubectl get crd gateways.gateway.networking.k8s.io || \
kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.6.0/experimental-install.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: httpbin-gateway
spec:
gatewayClassName: istio
listeners:
- name: http
hostname: "httpbin.example.com"
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Same
- name: https
hostname: "httpbin.example.com"
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: httpbin-credential
TLSはcertificateRefsでSecretを参照する仕組みです。Gatewayを置いたnamespaceにSecretが無い場合、Gateway APIのTLS設定ガイドのとおり、Secret側のnamespaceにReferenceGrantを作らないと参照は無効になります。作成後はkubectl wait --for=condition=programmed gtw httpbin-gatewayで準備完了を待ちます。
HTTPRouteのparentRefsとsectionNameでHTTPSへ寄せる例
Gateway APIにはhttpsRedirect欄が無く、HTTPRouteのフィルターで書きます。Gateway APIのリダイレクトのガイドと同じ構成で、sectionNameによりhttpリスナーだけに付けます。
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httpbin-redirect
spec:
parentRefs:
- name: httpbin-gateway
sectionName: http
hostnames: ["httpbin.example.com"]
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httpbin
spec:
parentRefs:
- name: httpbin-gateway
sectionName: https
hostnames: ["httpbin.example.com"]
rules:
- matches:
- path:
type: PathPrefix
value: /status
backendRefs:
- name: httpbin
port: 8000
2本のHTTPRouteに分けるのは、httpリスナーにはリダイレクトだけ、httpsリスナーには転送だけを付けるためです。1本にまとめるとHTTPのままバックエンドへ届く経路が残ります。
自動作成されるDeploymentとServiceの名前と調整方法
Gateway APIのGatewayを作ると、Istioは「Gateway名-GatewayClass名」の名前でDeploymentとServiceを自動作成します。上の例ならhttpbin-gateway-istioで、外部IPはkubectl get gtw httpbin-gatewayのstatus.addressesに出ます。
内部ロードバランサーにする指定のようなクラウド固有のアノテーションは、Gatewayのspec.infrastructureのannotationsに書くと生成物へコピーされます。レプリカ数やHPAまで変えるなら、parametersRefで同じnamespaceのConfigMapを参照する形です。生成されたServiceを手で編集せず、調整はGateway側に書くのが公式の手段です。
Istio Gatewayで詰まる典型と新規構築でどちらのAPIを選ぶかの判断
最後に、疎通しないときの確認順と、APIの選び方を条件付きで示します。
404やEXTERNAL-IPがpendingのまま進まないときの確認順
公式タスクのトラブルシューティングに沿うと、次の順で見るのが早道です。
kubectl get svc -n istio-ingressでEXTERNAL-IPを見る。pendingのままならクラウドのロードバランサーが作れていないkubectl get gateway --all-namespacesで、同じポートに別のGatewayが無いか確かめるkubectl get ingress --all-namespacesで、同じIPとポートを使うIngressが無いか確かめるistioctl analyze -n NAMESPACEでselectorやhostsの不一致を検出する
404はゲートウェイまで届いている証拠で、VirtualServiceやHTTPRouteのhostsかパスが一致していない場合がほとんどです。ロードバランサーが使えない検証環境なら、NodePortでゲートウェイへ直接当てる方法に切り替えてください。Service種別の違いはKubernetesネットワーク設計|Service・Ingress・Pod間通信とCNI選定の実装判断で整理しています。
新規構築はGateway APIを選びIstio APIは既存資産向け
これから入口を作るなら、Gateway APIを選んでください。Istioが将来の既定と位置づけており、アンビエントモードのwaypointもistio-waypointというGatewayClassのGatewayで表すため、後からアンビエントへ移る場合も書き直しが要りません。
VirtualServiceで重み付けのカナリアリリースやリトライ、フォールト注入を既に運用しているなら、入口だけをGateway APIに替える移行は見送ってよい場面です。2つのAPIが混在すると、障害時にどちらの設定が効いているかを追う手間が増えます。サービスが数本で、TLS終端とパス振り分けしか使わないなら、Istioを入れずにGateway APIの別実装やクラウドのロードバランサーで済ませる選択も残ります。
入口の設計は、ロードバランサー・DNS・証明書の更新・ゲートウェイのアップグレードまでがひと続きです。社内に担える人が少ない場合は、AWS・Google Cloud・Azureのインフラ構築支援のように、クラウド側のロードバランサーと合わせて設計を任せる方法もあります。
Istio Gatewayの設定と運用で挙がるよくある質問への回答集
Istio Gatewayの設定作業でよく出る疑問に、公式ドキュメントの記述をもとに答えます。
Istio GatewayとKubernetesのIngressは何が違いますか?
KubernetesのIngressは待ち受けとルーティングを1つのリソースに書きます。Istio APIのGatewayは待ち受け(ポート・ホスト・TLS)だけを受け持ち、ルーティングはVirtualServiceの役目です。分けたことで、入口の管理者と各アプリのチームが別々のリソースを持てます。IstioはIngressリソースも解釈できますが、重み付けなどIstioの機能を使うならGatewayとVirtualServiceか、Gateway APIを使います。
Istio Gatewayだけでルーティングまで設定できますか?
できません。Istio APIのGatewayにはルーティング規則を書く欄が無く、VirtualServiceがgatewaysでGatewayを名指ししない限り、通信はどこへも流れません。Gatewayだけ作ってcurlすると404になるのはこのためです。Gateway APIでも同じで、Gatewayの後にHTTPRouteが必要です。
ingress gatewayのPodは何台にすべきですか?
本番では最低2台にし、別々のノードに散らしてください。1台だとノードの保守やゲートウェイの更新のたびに入口が止まります。Helmの場合はhelm show values istio/gatewayでHPAやPodDisruptionBudgetの設定項目を確認できます。Gateway APIの自動デプロイなら、parametersRefのConfigMapに同じ上書きを書く方法です。
Istioのバージョンを上げるときゲートウェイも更新が要りますか?
必要です。ゲートウェイのEnvoyもIstioのバージョンに合わせて入れ替える対象で、公式ドキュメントはリビジョンを使った段階的な更新方法を示しています。ゲートウェイのDeploymentにistio.io/revラベルを付けると、そのリビジョンのコントロールプレーンへ切り替わり、ローリング再起動が走ります。ゲートウェイをコントロールプレーンと別に入れておくのは、この更新を独立して行うためです。
証明書を更新したのにゲートウェイに反映されません。どうすればよいですか?
まずkubectl -n istio-ingress get secretsで、Secretがゲートウェイと同じnamespaceにあるかを確かめます。別のnamespaceにある場合、ゲートウェイからは読めません。namespaceが正しいのに反映されないときは、ゲートウェイのPodのログでSecretの配信を確認します。公式タスクは、認証情報を変えるときにSecretを削除して作り直す手順を示しています。
関連記事
- Istioとは?サービスメッシュの仕組みとサイドカー/アンビエント方式・導入判断を解説:Istio全体の仕組みと導入判断
- Istioの最新バージョンは1.31|1.28〜1.31の新機能・サポート期限とアップグレード手順:ゲートウェイを含むアップグレードの手順
- NGINX Ingressとは?退役したingress-nginxとF5版の違い・移行判断:Ingressからの移行を検討するときの前提
- サービスメッシュとは?サイドカー方式の仕組みとAPIゲートウェイとの違い・導入判断を解説:APIゲートウェイとサービスメッシュの役割の違い
- Cloud Service Meshとは?GKEでの構築手順・料金と2028年ISTIODサポート終了への移行判断:GKEでIstio互換のマネージドメッシュを使う場合