Cycloud LoadBalancingにおけるDataPlaneのIstioからEnvoy Gatewayへの移行検証
電気通信大学の学生が、クラウドロードバランシングのデータプレーンをIstioからEnvoy Gatewayへ移行する技術検証について報告。
キーポイント
CycloudのL7ロードバランサー(CALB)のデータプレーンを、IstioからEnvoy Gatewayへ移行する検証が行われた
移行の主な理由は、North-Southトラフィック(クラスタ内外接続)に特化したEnvoy Gatewayの方が、サービスメッシュ中心のIstioよりもCALBの機能拡充に適しているため
検証では、既存機能(マルチテナント分離、IAP連携)の互換性と、新機能(ヘルスチェック)の実現可能性が確認された
CALBはKubernetes Gateway APIに準拠して設計されており、Ingressの課題を解決する最新仕様を採用している
この取り組みは、大規模クラウド環境におけるロードバランシング基盤の近代化と最適化の一環として位置付けられる
影響分析・編集コメントを表示
影響分析
この記事は、大規模クラウドサービスにおけるロードバランシング基盤の技術選定と移行プロセスの実践例を示しており、クラウドネイティブ環境でのGateway API採用とデータプレーン最適化のトレンドを反映している。特定企業の内部技術改善ではあるが、同様の課題を抱える他社やオープンソースプロジェクトにとって参考になる実装知見を提供している。
編集コメント
インターン生による実践的な技術検証レポートで、企業の基盤技術刷新プロセスの一端を窺える。Gateway APIの採用動向とデータプレーン選定のトレンドを捉えた、開発者向けの実用的な内容。
電気通信大学情報理工学研究科情報・ネットワーク工学専攻1年の平地浩一と申します。
2025年10月1日から2025年12月26日までの約3ヶ月間、CIUのCALBチームにてインターンさせていただきました。
今回は、Cycloudの中でもCycloud Application Load Balancer(CALB)というロードバランサー改良のタスクを担当し、内部で使われているミドルウェアをIstioからEnvoy Gatewayへ移行するための検証と、簡単なコントローラ実装まで行いました。
本記事ではインターン中に取り組んだCALBにおけるEnvoyGatewayへの移行の検証とコントローラ開発について紹介します。
CALBはCycloud Load Balancingの一部であるL7ロードバランサーです。CALBは、KubernetesのGateway APIと互換性を持っています。
基本的な機能として、Cycloud 上で構築しているサービスをインターネット上に公開することができます。また特徴として、Identity-Aware Proxy(IAP)の機能を提供しており、サービスを安全にインターネットに公開できるセキュリティ機能を備えています。
CALBはKubernetesのGateway APIと呼ばれる仕様に互換性を持って設計されています。今まではKubernetesで外部にサービスを公開するリソースとして、Ingressが一般的に使われてきました。しかし、IngressではリソースのSpecが管理者とアプリケーション開発者の関心領域を両方含む構造になっているということが課題でした。また、Ingressに存在しない仕様はannotationを用いてProvider独自の命令を記述するような手法が取られており、運用上の課題も残されていました。
こうしたIngressの課題から、新たに設計し直されたものがGateway APIです。Gateway APIでは関心領域ごとにリソースを分離し、さらに拡張性を向上させたものがGateway APIです。
Gateway APIはGateway、HTTPRouteといった主要なリソースと、それを実際に提供するProviderによって成り立ちます。まず、Gatewayリソースがリソースを処理するロードバランサーのインスタンスの定義です。GatewayはIngressのIngress Classと同じくGatewayClassを持ち、Gatewayを管理するコントローラを選択します。そして、HTTP RouteがGatewayリスナーからバックエンドのネットワークまでのルールを定義し、図1のようにルーティングされます。

図1 Gateway APIにおけるトラフィックの流れ *Kubernetes.ioのdocsより引用
Gateway APIは図2のようにはロール思考に沿ったリソース構造で作られています。GatewayClassをAWSやGCPなどのプラットフォーム提供者が管理し、クラスター管理者がGatewayを管理、そしてアプリケーション開発者がHTTPRouteといったリソースを管理するといった仕様になっています。

図 2 Gateway API におけるそれぞれのロール *Kubernetes.io の docs より引用
Istio から Envoy Gateway への移行
現行の CALB では、過去の経緯からデータプレーンとして Istio を採用しています。しかしながら、CALB を開発していく上でいくつかの課題があり、今回データプレーンを Istio から Envoy Gateway への移行を検討することになりました。
Istio と Envoy Gateway はどちらも Gateway API に準拠したプロバイダーで、内部的にはどちらも Envoy を利用しています。コントローラー側で、Envoy の設定を生成してそれを xDS (x Discovery Service) という仕組みを利用してコントローラから各 Envoy Proxy に配信しています。
Istio と Envoy Gateway の主な違いをまとめると以下の通りです。
サービスメッシュ (East-West 中心)
API Gateway / Ingress (North-South 中心)
VirtualService、DestinationRule 等
基本は Gateway API +
Istio は Gateway API が普及する以前から存在する歴史のあるミドルウェアであり、多種多様な独自の API を持っています。主に East-West と呼ばれる Kubernetes クラスタ内部のトラフィックを扱うことにフォーカスしています。そのため、CALB のようなクラスタの内部と外部を繋ぐような North-South の用途で利用しようとすると Istio ではまだサポートされていない機能などもあり、CALB のサービス機能を拡充する上で実装が困難といった課題がありました。
Envoy Gateway は、Gateway API 準拠で作られたミドルウェアで、いわゆる North-South といったような用途を想定して開発されています。そこで、CALB の DataPlane を置き換えることによって、今まで Istio で実現できなかった機能の実現や構成の単純化ができないかということで、移行の検証をするという流れになりました。
Envoy Gateway の検証
CALB の DataPlane として十分な機能を持っているのかを確認するため、インターンの最初では Envoy Gateway の検証を行うこととなりました。
細かい部分も多く検証したところはありますが、主に検証を行ったのは以下の 3 点です。これらの中で上の 2 つは既に CALB で提供されている機能で Envoy Gateway でも同じく提供する必要がある機能です。最後のヘルスチェックは現在の Istio で対応していないものの CALB の機能として追加したいものです。
検証は、検証用クラスタ上に Envoy Gateway を helm で導入して公式のドキュメント (https://www.envoyproxy.io/docs/envoy/latest) を参考にして実装を行いました。
現在の CALB では、Dataplane 上に複数のテナントが存在しており、それぞれのテナントを namespace で隔離しています。Envoy Gateway で同じことを実現するためには、envoy proxy のリソースをそれぞれの namespace に配置してあげる必要があります。
しかしながら、Envoy Gateway ではデフォルトでデータプレーンのリソースを envoy-gateway-system という namespace に配置します。そこで、Gateway Namespace Mode というモードを有効化し、Gateway の namespace にリソースをデプロイしてくれるようにしました。
設定は Envoy Gateway の Config で以下のように設定を追加してあげると動作しました。また、今回検証した限りだと Gateway Namespace Mode の有効化することによる不都合は特にありませんでした。
config: envoyGateway: provider: type: Kubernetes kubernetes: deploy: type: GatewayNamespace
CALB では、CycloudBackend というリソースでルーティング先の FQDN や Service を指定します。Gateway API 標準にはこうした外部にルーティングをするための API はありません。しかし、Envoy Gatewy では Backend というリソースがあり、これを用いることで非常に簡単に実現することができました。
Backend ルーティングをするためには、以下のように Envoy の設定を追加しておく必要があります。
config: envoyGateway: extensionApis: enableBackend: true
この設定をした上で以下のようにリソースを作ると、Backend Routing が機能します。
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: gateway-a
namespace: team-a
spec:
gatewayClassName: eg
listeners:
- allowedRoutes:
namespaces:
from: Same
name: http
port: 8080
protocol: HTTP
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: Backend
metadata:
name: cycloud-test
namespace: team-a
spec:
endpoints:
- ip:
address: 192.168.0.1
port: 8080
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: backend
namespace: team-a
spec:
hostnames:
- "www.example.com"
parentRefs:
- name: gateway-a
rules:
- backendRefs:
- group: gateway.envoyproxy.io
kind: Backend
name: cycloud-test
weight: 1
matches:
- path:
type: PathPrefix
value: /
Envoy Gateway では、Active Healthcheck(アクティブヘルスチェック)と Passive Healthcheck(パッシブヘルスチェック)の 2 つに対応しています。この 2 つの違いを簡単に言うと以下の通りです。
Active Healthcheck:ロードバランサ自身が定期的にエンドポイントを叩いて、ルーティング先の正常性を確認する仕組みです。
Passive Healthcheck:実際にトラフィックをルーティングし、正常でない応答が帰ってきたら別のリソースに切り替える仕組みです。
細かい部分は省きますが、以下のような BackendTrafficPolicy というリソースを HTTPRoute などに対して割り当てることによって、Health Check(ヘルスチェック)を実現できました。
kind: BackendTrafficPolicy
metadata:
name: passive-health-check
namespace: team-b
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: ha-example
healthCheck:
passive:
baseEjectionTime: 10s
interval: 2s
maxEjectionPercent: 100
consecutive5XxErrors: 1
consecutiveGatewayErrors: 0
consecutiveLocalOriginFailures: 1
splitExternalLocalOriginErrors: false
active:
type: HTTP # ヘルスチェックのタイプを指定
timeout: 1s
interval: 2s
unhealthyThreshold: 3
healthyThreshold: 1
http:
path: /healthz # ヘルスチェック用のパス
method: GET
expectedStatuses: [200]
実際にアクティブヘルスチェック(Active Healthcheck)を実行している状態では、以下のような形でトラフィックの切り替えを確認することができます。以下の例では、HTTP ルート(HTTP Route)にルーティングしたい「active」という名前のサービスと「passive」という名前のサービスの 2 つが紐づけられています。初期状態では、「active」の方にルーティングされています。
for i in {1..10}; do curl --verbose --header "Host: www.example.com" http://localhost:5000/test 2>/dev/null | jq .pod; done
"active-858c6d4d7c-cs8zm"
"active-858c6d4d7c-cs8zm"
"active-858c6d4d7c-cs8zm"
"active-858c6d4d7c-cs8zm"
"active-858c6d4d7c-cs8zm"
"active-858c6d4d7c-cs8zm"
"active-858c6d4d7c-cs8zm"
"active-858c6d4d7c-cs8zm"
"active-858c6d4d7c-cs8zm"
"active-858c6d4d7c-cs8zm"
ここで、アクティブ(active)のデプロイメント(deployment)のレプリカ数を 0 にして Pod を削除すると、アクティブに接続できなくなるため、パッシブ(passive)側に移動します。
for i in {1..10}; do curl --verbose --header "Host: www.example.com" http://localhost:5000/test 2>/dev/null | jq .pod; done
"passive-65f7cd47f9-vfv9d"
"passive-65f7cd47f9-vfv9d"
"passive-65f7cd47f9-vfv9d"
"passive-65f7cd47f9-vfv9d"
"passive-65f7cd47f9-vfv9d"
"passive-65f7cd47f9-vfv9d"
"passive-65f7cd47f9-vfv9d"
"passive-65f7cd47f9-vfv9d"
"passive-65f7cd47f9-vfv9d"
"passive-65f7cd47f9-vfv9d"
その他にも、IAP(Identity-Aware Proxy)やProxy Protocol に関する検証、およびメトリクス収集方法に関する検証を行いました。
これまでの結果から、Envoy Gateway は CALB のデータプレーンとして十分な機能を備えており、それぞれの機能が正常に動作することが検証できました。
インターンシップにおける主な目標は、Envoy Gateway が実際に利用可能かどうかの検証まででしたが、少し時間があったため、最後に Controller の実装にも軽く挑戦することになりました。
CALB のクラスタ構成は図 2 に示すような形になっており、Management クラスタと Data Plane クラスタの 2 つから構成されています。Management クラスタでは API からのリクエストを受け付けて Cycloud のリソースを定義・管理します。Dataplane Controller では、作成された Cycloud のリソースに対して、実際の Envoy Gateway のリソースを作成します。
このような実装になっている理由は、DataPlane で使用する Provider を容易に切り替えられるようにするためです。それぞれの Provider 独自のリソースを Wrap(ラップ)し、ユーザが内部の DataPlane を意識することなく利用できるようにするために、このような設計となっています。

今回は、最小構成として以下のような CALB のリソースに対して対応する Envoy Gateway のリソースを作成してくれる Controller を開発しました。
--- apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: test namespace: loadbalancing-test-project spec: gatewayClassName: application listeners: - allowedRoutes: namespaces: from: All hostname: example.com name: http port: 80 protocol: HTTP --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: test namespace: loadbalancing-test-project spec: parentRefs: - name: test hostnames: - example.com rules: - backendRefs: - name: test port: 80 --- apiVersion: loadbalancing.cycloud.jp/v1 kind: CycloudBackend metadata: name: test namespace: loadbalancing-test-project spec: endpoints: - address: 192.168.0.1 ports: - appProtocol: http name: http port: 80 protocol: TCP targetPort: 80 targetCyrn: cyrn:loadbalancing:xxx:xxx:kubernetesmanagedbackends/test
Gateway API に存在するリソースは CALB でも同じリソースを利用しており、Gateway API に存在しない Backend は CycloudBackend として CRD を定義しています。
CycloudBackend は、設定を見るとわかるように LB が転送する先のエンドポイントの情報を設定するリソースになっています。
今回は既存の Istio の実装から Envoy Gateway に対応するように Controller を開発しました。Kubernetes の Controller 開発は初めてだったので最初は挙動の理解に時間がかかりましたが、トレーナーの方から丁寧に説明していただき実装まで終わらせることができました。
今回実装した Contrller は非常にシンプルで、CALB の IAP や TLS などの機能はなく単純に HTTP で外部にトラフィックを転送する部分だけを開発しました。
以下は作成したコントローラをデプロイした際の様子です。
kubectl get Gateway NAME CLASS ADDRESS PROGRAMMED AGE test application example.com True 16h test-4wpkx eg 192.168.0.1 True 15h --- # kubectl get HTTPRoute NAME HOSTNAMES AGE test ["example.com"] 12h test-86pn6 ["example.com"] 12h --- # kubectl get CycloudBackend NAME AGE test 16h # kubectl get Backend NAME STATUS AGE test-hgpzf Accepted 16h
Gateway、HTTPRoute、Backendにおいて、実際にCALBのリソースに対して対応するリソースがControllerによって作成されAccepted状態になっていることを確認できました。
実際にリクエストを送信してみると、設定したIPアドレスに転送されて結果が返ってくることが確認できました。
curl --header "Host: example.com" http://192.168.0.1/get { "args": {}, "headers": { "Accept": "*/*", "Host": "example.com", "User-Agent": "curl/8.7.1", "X-Envoy-External-Address": "127.0.0.1" }, "origin": "10.0.0.1", "url": "http://example.com/get" }
今回の検証を通じて、CALBのDataPlane(データプレーン)としてIstioからEnvoyGatewayへの移行に向けて検証を行いました。また、実際に簡易的なコントローラの実装も行いました。これにより、今までのIstioでは実現できなかった新しい機能をCALBに導入することが可能となるとともに、構成がシンプルになることにより保守性が向上することが期待されます。
今後はコントローラの実装を進めていき、EnvoyGatewayへの移行が行われていく予定です。
3ヶ月のインターンシップを通じて、これまで利用側として使っていたクラウド内部がどのような仕組みや設計で構築されているのかを学ぶことができました。
また、CyberAgentではサービス開発者が自由にインフラ基盤を選択でき、その中の1つとしてCycloudがあるという特殊な環境において、いかにして既存サービスからの学習コストを下げるのかといった設計や考え方は他の会社にはないものであり、非常に勉強になりました。
今回のトレーナーを務めてくださった木村さんはEnvoy Gatewayのメンテナーもされており、今回の検証中に困ったところを詳しく説明いただき、デバッグ方法の知見や、EnvoyGateway / Envoyの挙動の理解が深まりました。
最後にサポートしていただいたトレーナーの木村さん、CIUチームの皆様、人事の皆様に大変お世話になりました。インターンシップを通して技術的な学びだけでなく、今後のキャリア設計において非常に参考になるお話を伺えたり、多くのことを得ることができました。ありがとうございました!
原文を表示
電気通信大学情報理工学研究科情報・ネットワーク工学専攻1年の平地浩一と申します。
2025年10月1日から2025年12月26日までの約3ヶ月間、CIUのCALBチームにてインターンさせていただきました。
今回は、Cycloudの中でもCycloud Application Load Balancer(CALB)というロードバランサー改良のタスクを担当し、内部で使われているミドルウェアをIstioからEnvoy Gatewayへ移行するための検証と、簡単なコントローラ実装まで行いました。
本記事ではインターン中に取り組んだCALBにおけるEnvoyGatewayへの移行の検証とコントローラ開発について紹介します。
CALBはCycloud Load Balancingの一部であるL7ロードバランサーです。CALBは、KubernetesのGateway APIと互換性を持っています。
基本的な機能として、Cycloud 上で構築しているサービスをインターネット上に公開することができます。また特徴として、Identity-Aware Proxy(IAP)の機能を提供しており、サービスを安全にインターネットに公開できるセキュリティ機能を備えています。
CALBはKubernetesのGateway APIと呼ばれる仕様に互換性を持って設計されています。今まではKubernetesで外部にサービスを公開するリソースとして、Ingressが一般的に使われてきました。しかし、IngressではリソースのSpecが管理者とアプリケーション開発者の関心領域を両方含む構造になっているということが課題でした。また、Ingressに存在しない仕様はannotationを用いてProvider独自の命令を記述するような手法が取られており、運用上の課題も残されていました。
こうしたIngressの課題から、新たに設計し直されたものがGateway APIです。Gateway APIでは関心領域ごとにリソースを分離し、さらに拡張性を向上させたものがGateway APIです。
Gateway APIはGateway、HTTPRouteといった主要なリソースと、それを実際に提供するProviderによって成り立ちます。まず、Gatewayリソースがリソースを処理するロードバランサーのインスタンスの定義です。GatewayはIngressのIngress Classと同じくGatewayClassを持ち、Gatewayを管理するコントローラを選択します。そして、HTTP RouteがGatewayリスナーからバックエンドのネットワークまでのルールを定義し、図1のようにルーティングされます。

図1 Gateway APIにおけるトラフィックの流れ *Kubernetes.ioのdocsより引用
Gateway API図2のようにはロール思考に沿ったリソース構造で作られています。GatewayClassをAWSやGCPなどのプラットフォーム提供者が管理し、クラスター管理者がGatewayを管理、そしてアプリケーション開発者がHTTPRouteといったリソースを管理するといった仕様になっています。

図2 Gateway APIおけるそれぞれのロール *Kubernetes.ioのdocsより引用
IstioからEnvoy Gatewayへの移行
現行のCALBでは、過去の経緯からデータプレーンとしてIstioを採用しています。しかしながら、CALBを開発していく上でいくつかの課題があり今回データプレーンをIstioからEnvoy Gatewayへの移行を検討することになりました。
IstioとEnvoy GatewayはどちらもGateway APIに準拠したProviderで、内部的にはどちらもEnvoyを利用しています。Controller側で、Envoyの設定を生成してそれをxDS (x Discovery Service)という仕組みを利用してコントローラから各Envoy Proxyに配信しています。
IstioとEnvoy Gatewayの主な違いをまとめると以下の通りです。
サービスメッシュ (East-West中心)
API Gateway / Ingress (North-South中心)
VirtualService、DestinationRule等
基本はGateway API +
IstioはGateway APIが普及する以前から存在する歴史のあるミドルウェアであり、多種多様な独自のAPIを持っています。主にEast-Westと呼ばれるKubernetesクラスタ内部のトラフィックを扱うことにフォーカスしています。そのため、CALBのようなクラスタの内部と外部を繋ぐようなNorth-Southの用途で利用しようとするとIstio ではまだサポートされていない機能などもあり、CALB のサービス機能を拡充する上で実装が困難といった課題がありました。
Envoy Gatewayは、Gateway API準拠で作られたミドルウェアで、いわゆるNorth-Southといったような用途を想定して開発されています。そこで、CALBのDataPlaneを置き換えることによって、今までIstioで実現できなかった機能の実現や構成の単純化ができないかということで、移行の検証をするという流れになりました。
Envoy Gatewayの検証
CALBのDataPlaneとして十分な機能を持っているのかを確認するため、インターンの最初ではEnvoy Gatewayの検証を行うこととなりました。
細かい部分も多く検証したところはありますが、主に検証を行ったのは以下の3点です。これらの中で上の2つは既にCALBで提供されている機能でEnvoy Gatewayでも同じく提供する必要がある機能です。最後のヘルスチェックは現在のIstioで対応していないもののCALBの機能として追加したいものです。
検証は、検証用クラスタ上にEnvoy Gatewayをhelmで導入して公式のドキュメント(https://www.envoyproxy.io/docs/envoy/latest)を参考にして実装を行いました。
現在のCALBではDataplane上に複数のテナントが存在しており、それぞれのテナントをnamespaceで隔離しています。Envoy Gatewayで同じことを実現するためには、envoy proxyのリソースをそれぞれのnamespaceに配置してあげる必要があります。
しかしながら、Envoy Gatewayではデフォルトでデータプレーンのリソースをenvoy-gateway-systemというnamespaceに配置します。そこで、Gateway Namespace Modeというモードを有効化し、Gatewayのnamepsaceにリソースをデプロイしてくれるようにしました。
設定はEnvoy GatewayのConfigで以下のように設定を追加してあげると動作しました。また、今回検証した限りだとGateway Namespace Modeの有効化することによる不都合は特にありませんでした。
config: envoyGateway: provider: type: Kubernetes kubernetes: deploy: type: GatewayNamespace
CALBでは、CycloudBackendというリソースでルーティング先のFQDNやServiceを指定します。Gateway API標準にはこうした外部にルーティングをするためのAPIはありません。しかし、Envoy GatewyではBackendというリソースがあり、これを用いることで非常に簡単に実現することができました。
Backendルーティングをするためには、以下のようにEnvoyの設定を追加しておく必要があります。
config: envoyGateway: extensionApis: enableBackend: true
この設定をした上で以下のようにリソースを作ると、Backend Routingが機能します。
apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-a namespace: team-a spec: gatewayClassName: eg listeners: - allowedRoutes: namespaces: from: Same name: http port: 8080 protocol: HTTP --- apiVersion: gateway.envoyproxy.io/v1alpha1 kind: Backend metadata: name: cycloud-test namespace: team-a spec: endpoints: - ip: address: 192.168.0.1 port: 8080 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: backend namespace: team-a spec: hostnames: - "www.example.com" parentRefs: - name: gateway-a rules: - backendRefs: - group: gateway.envoyproxy.io kind: Backend name: cycloud-test weight: 1 matches: - path: type: PathPrefix value: /
Envoy GatewayではActive HealtheckとPassive Healthcheckの2つに対応しています。2つの違いは簡単にいうと以下の通りです。
Active Healthcheck ロードバランサ自身が定期的にエンドポイントを叩いてルーティング先の正常性を確認する
Passive Healthcheck 実際にトラフィックをルーティングし、正常でない応答が帰ってきたら別のリソースに切り替えを行う
細かい部分は省きますが、以下のようなBackendTrafficPolicyというリソースをHTTPRouteなどに対して割り当ててあげることによってHelalth Checkを実現できました。
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: BackendTrafficPolicy metadata: name: passive-health-check namespace: team-b spec: targetRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: ha-example healthCheck: passive: baseEjectionTime: 10s interval: 2s maxEjectionPercent: 100 consecutive5XxErrors: 1 consecutiveGatewayErrors: 0 consecutiveLocalOriginFailures: 1 splitExternalLocalOriginErrors: false active: type: HTTP # ヘルスチェックのタイプを指定 timeout: 1s interval: 2s unhealthyThreshold: 3 healthyThreshold: 1 http: path: /healthz # ヘルスチェック用のパス method: GET expectedStatuses: [200]
実際にActive Healthcheckをしている状態だと、以下のような形でトラフィックの切り替えを確認することができます。 以下の例では、HTTP Routeにルーティングしたいactiveとpassiveという2つのserviceが紐づけられています。初期状態では、activeの方にルーティングされています。
for i in {1..10}; do curl --verbose --header "Host: www.example.com" http://localhost:5000/test 2>/dev/null | jq .pod; done "active-858c6d4d7c-cs8zm" "active-858c6d4d7c-cs8zm" "active-858c6d4d7c-cs8zm" "active-858c6d4d7c-cs8zm" "active-858c6d4d7c-cs8zm" "active-858c6d4d7c-cs8zm" "active-858c6d4d7c-cs8zm" "active-858c6d4d7c-cs8zm" "active-858c6d4d7c-cs8zm" "active-858c6d4d7c-cs8zm"
ここで、activeのdeploymentのreplicaを0にして、Podを削除するとactiveに接続できなくなるためpassiveに移動します。
for i in {1..10}; do curl --verbose --header "Host: www.example.com" http://localhost:5000/test 2>/dev/null | jq .pod; done "passive-65f7cd47f9-vfv9d" "passive-65f7cd47f9-vfv9d" "passive-65f7cd47f9-vfv9d" "passive-65f7cd47f9-vfv9d" "passive-65f7cd47f9-vfv9d" "passive-65f7cd47f9-vfv9d" "passive-65f7cd47f9-vfv9d" "passive-65f7cd47f9-vfv9d" "passive-65f7cd47f9-vfv9d" "passive-65f7cd47f9-vfv9d"
その他に細かいところでは、IAPやProxy Protocolに関する検証やメトリクスの収集方法に関する検証を行いました。
ここまでの結果から、Envoy GatewayはCALBのデータプレーンとして十分な機能を持っており、それぞれの機能が正常に動作するということが検証できました。
インターンの中での目標はEnvoy Gatewayが実際に利用できるかの検証までがメインだったのですが、少し時間があったので最後に軽くControllerの実装にも挑戦することになりました。
CALBのクラスタ構成は図2のような形になっており、ManagementとData Planeの2台のクラスタから構成されています。Managementクラスタは、APIからのリクエストを受け付けてCycloudのリソースを定義して管理します。Dataplane Controllerでは、作成されたCycloudのリソースに対して、実際のEnvoy Gatewayのリソースを作成します。
こうした実装になっている理由としては、DataPlaneで使うProviderを容易に切り替えられるようにするためです。それぞれのProvider独自のリソースをWrapして、ユーザは内部のDataPlaneを意識することなく使えるようにするためこのような設計となっています。

今回は、最小構成として以下のようなCALBのリソースに対して対応するEnvoy Gatewayのリソースを作成してくれるようなControllerを開発しました。
--- apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: test namespace: loadbalancing-test-project spec: gatewayClassName: application listeners: - allowedRoutes: namespaces: from: All hostname: example.com name: http port: 80 protocol: HTTP --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: test namespace: loadbalancing-test-project spec: parentRefs: - name: test hostnames: - example.com rules: - backendRefs: - name: test port: 80 --- apiVersion: loadbalancing.cycloud.jp/v1 kind: CycloudBackend metadata: name: test namespace: loadbalancing-test-project spec: endpoints: - address: 192.168.0.1 ports: - appProtocol: http name: http port: 80 protocol: TCP targetPort: 80 targetCyrn: cyrn:loadbalancing:xxx:xxx:kubernetesmanagedbackends/test
Gateway APIに存在するリソースはCALBでも同じリソースを利用しており、Gateway APIに存在しないBackendはCycloudBackendとしてCRDを定義しています。
CycloudBackendは、設定を見るとわかるようにLBが転送する先のエンドポイントの情報を設定するリソースになっています。
今回は既存のIstioの実装からEnvoyGatewayに対応するようにControllerを開発しました。KubernetesのController開発は初めてだったので最初は挙動の理解に時間がかかりましたが、トレーナーの方から丁寧に説明していただき実装まで終わらせることができました。
今回実装したContrllerは非常にシンプルで、CALBのIAPやTLSなどの機能はなく単純にHTTPで外部にトラフィックを転送する部分だけを開発しました。
以下は作成したコントローラをデプロイした際の様子です。
kubectl get Gateway NAME CLASS ADDRESS PROGRAMMED AGE test application example.com True 16h test-4wpkx eg 192.168.0.1 True 15h --- # kubectl get HTTPRoute NAME HOSTNAMES AGE test ["example.com"] 12h test-86pn6 ["example.com"] 12h --- # kubectl get CycloudBackend NAME AGE test 16h # kubectl get Backend NAME STATUS AGE test-hgpzf Accepted 16h
Gateway、HTTPRoute、Backendで実際にCALBのリソースに対して、対応するリソースがControllerによって作成されAcceptedになっていることが確認できました。
実際にリクエストを送ってみると、設定したIPアドレスに転送されて結果が返ってくることが確認できました。
curl --header "Host: example.com" http://192.168.0.1/get { "args": {}, "headers": { "Accept": "*/*", "Host": "example.com", "User-Agent": "curl/8.7.1", "X-Envoy-External-Address": "127.0.0.1" }, "origin": "10.0.0.1", "url": "http://example.com/get" }
今回の検証を通じて、CALBのDataPlaneとしてIstioからEnvoyGatewayに移行に向けて検証を行いました。また、実際に簡易的なコントローラの実装を行いました。これにより今までのIstioでは実現できなかった新しい機能をCALBに導入することが可能となるとともに、構成がシンプルになることにより保守性が上がることが期待されます。
今後はコントローラの実装を進めていき、EnvoyGatewayへの移行が行われていく予定です。
3ヶ月のインターンを通して、今まで使う側として使っていたクラウド内部がどのような仕組みや設計で構築されているのかというのを学ぶことができました。
また、CyberAgentではサービス開発者が自由にインフラ基盤を選択でき、その中の1つとしてCycloudがあるという特殊な環境で、いかにして既存サービスからの学習コストを下げるのかといった設計や考え方は他の会社にはないもので非常に勉強になりました。
今回のトレーナーをしてくださった木村さんはEnvoy Gatewayのメンテナーもされており、今回の検証中に困ったところを詳しく説明していただきデバッグ方法の知見や、EnvoyGateway / Envoyの挙動の理解が深まりました。
最後にサポートしていただいたトレーナーの木村さん、CIUチームの皆様、人事の皆様に大変お世話になりました。インターンを通して技術的な学びだけでなく、今後のキャリア設計において非常に参考になるお話を伺えたり、多くのことを得ることができました。 ありがとうございました!
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み