Platform Engineering の視点から考える、Kubernetes Load Balancing の比較

Sreake事業部

2024.9.13

自己紹介

井上 裕介

千葉工業大学 情報科学部 情報工学科 学部4年の井上裕介と申します。
大学では主に遺伝的アルゴリズムの改良に関する研究を行っています。
2023年のサマーインターンから引き続きSreake事業部にて技術調査を行っております。

はじめに

近年、DevOps や SRE と同じくモダンな開発手法のひとつとして Platform Engineering が注目されています。私が初めて Platform Engineering ( Platform Engineering ) という言葉を耳にしたとき、この言葉の定義について少し困惑しました。
というのも、当時私は SRE という分野を知っており、SRE と Platform Engineering の違いがイメージできませんでした。

今回は、Platform Engineering について学びつつ、技術調査として、Google Cloud 環境における Load Balancer 周りの調査と比較検証を行います。

今回比較する Load Balancer は、GCLB ( Google Cloud Load Balancing ) の NEG 、昨年10月に GA となった Gateway API 、これまで Kubernetes の Load Balancer として活躍してきた Ingress の3種類です。

検証結果をもとに、今後 Platform Engineering が開発チームにどのような影響を与えるのか考察しました。

Platform Engineering と SRE の共通点

まずは SRE と Platform Engineering がクラウドネイティブなサービスに対してどのような役割を担うのか見ていきましょう。
Platform Engineering とは、開発者に対して最適なプラットフォームの設計・構築・運用を行い、開発チーム全体の生産性と UX を向上させることで、サービスの迅速な提供とビジネス価値の創出を目的とする手法です。

プラットフォームエンジニアは目標達成のため、コンテナオーケストレーションツール・プロビジョニングツール・CI/CD ツールを活用したプラットフォームの最適化を行います。
SRE と Platform Engineering はともに DevOps の理念から出発した、インフラとアプリケーションの運用と保守に関わる分野であり、互いに異なるミッションを持って行動します。

しかし、SRE と Platform Engineering は開発チーム内で同じような役割を担うことから、両者の線引きが曖昧になりがちです。なので、まずはSREと Platform Engineering の一般的な役割について見てみましょう。

SRE ( Site Reliability Engineering )

SRE は主にシステムの運用に特化して活動します。その主な目的は、システムの可用性、信頼性、およびスケーラビリティを高水準で保証することです。そのために、監視、アラート、インシデント対応、キャパシティプランニングなどが主な業務範囲となります。

Platform Engineering

Platform Engineering は開発者の生産性を高めるプラットフォームを設計、構築、および運用することが主な目的です。この目的を達成するために、CI/CD パイプラインの設定、コンテナオーケストレーションツールの管理、開発環境の最適化などが主要な業務になります。

SRE と Platform Engineering は目的は異なるものの、両方ともシステムと開発プロセスの効率と信頼性を向上させることに貢献しています。

SREとPlatform Engineerの違いを3つのポイントで理解する

表にまとめるとこのような分類になります。

◎:非常に重視する 〇:重視する △:あまり重視しない ×:無関心

SREPlatform Engineering
システムの信頼性
開発者の生産性
システムの監視
プラットフォームの最適化
自動化によるトイルの排除
フィードバックループ
システムの継続的な改善と向上

しかし、これだけで両者の違いを理解するのは難しいかと思います。そこで、SREの関心事に関するアーキタイプについて紹介します。

一般的に、SRE は主な関心事に基づいて 4 つのタイプに分類できます。

Table.1 SRE Archetypes by Primary Concern

Admin

  • インフラのプロビジョニングと保守、サードパーティツールの契約管理とアクセス制御
  • リソースの最適化 ( FinOps ) と IaC ( Infrastructure as Code ) を用いたコーディング

Firefighter

Toolsmith

  • 開発チームの認知負荷軽減とゴールデンパス ( Golden Paths ) の実装
  • トイル ( Toil ) の自動化と開発者エクスペリエンス ( DX | Developer eXperience ) の向上

Architect

SRE Archetypes: archetypes-of-site-reliability-engineering

以上 Table.1 に示した4つの関心事を踏まえたうえで、実際に現場での SRE と Platform Engineering の役割の範囲を視覚化してみると、以下のFigure.1 のようになるかと思います。

Figure.1 を見ると、 Platform Engineering は4つの関心事のうち Toolsmith と Architect の役割を担当します。

Figure.1 SRE と Platform Engineering の役割の比較

Platform Engineering は DX 向上のため、トイル ( 創造性や問題解決スキルをあまり必要としない反復的な手作業 ) の特定と排除、及びゴールデンパスの実装を行います。

しかし、プラットフォームには SRE やアプリケーションエンジニアなど様々な開発者が携わっています。サービスを提供するにあたり彼らとの協力関係は必要不可欠です。

プラットフォームエンジニアにとって、プラットフォームに携わるすべてのチームがスムーズに、余計な手間を取られずに開発に集中できる環境を整備・保守することは、重要な任務のひとつなのです。

参考:

なぜ Platform Engineering は注目されているか?

認知負荷の増加

Daniel Bryant at PlatformCon 2022 より

DevOps が登場した 2008 年以降、アプリ開発の現場は様変わりしました。

まず、同じ時期に DevOps と相性の良いクラウドプロバイダ ( AWS, Google Cloud, Azure etc… ) が登場し普及します。これに伴うように、クラウドネイティブの登場と、モノリシックからマイクロサービスへの移行が行われました。

結果、アプリを E2E でデプロイするために必要なツールが急速に増加しました。

フロント、バック、CI/CD、プロビジョニング、コンテナ、監視 …。これらを数人のチーム ( あるいは立った一人 ) で使いこなすには、相当な訓練と時間を要します。

既に開発者一人が担うにはあまりにも広大な責任がかかっており、認知負荷は増加の一途をたどっています。

Team TopologiesPlatform Engineer

Figure.2 Platform Engineering のデザインループ

Platform Engineering に関心を抱く人の多くは、Team Topologies という用語をご存じかもしれません。

Team Topologies を導入している開発チームでは、チームの種類は4つの基本チームにコンパクトにまとまっています。各チームはそれぞれのチームタイプに応じた目的と責任を有します。

プラットフォームチーム内で Platform Engineering チーム及びプラットフォームエンジニアが担うのは、効率的な DevOps を実行するための共通のプラットフォームとツールの提供です。

開発チームを顧客と捉え、効率的にソフトウェアを開発・デリバリーできるように、開発チームのワークフローに最適化したプラットフォームを設計します。プラットフォームチームは、開発チームにゴールデンパスを提供することで、開発者の認知負荷を下げ、生産性を向上することがミッションです。

Platform Engineering と Load Balancing

Kubernetes における Load Balancing

Kubernetes をはじめとするコンテナオーケストレーションツールの多くは、複数のコンテナにサービスを展開して運用することが想定されています。特に、ユーザからのリクエストを適切にコンテナに振り分けることで、サービスにかかる負荷を分散させる必要があります。

このような Load Balancing を担うのが Load Balancer です。一言に Load Balancer と言っても様々な形態が存在し、役割も細かく異なっており、選定の際は注意深く検証する必要があります。

Load Balancer の持つ課題

Load Balancer は様々な機能を提供します。Traffic Routing や URL Map などの機能はアプリ開発チーム、プラットフォームチーム、インフラプロバイダにとって関心の高いものです。それゆえ、サービスを提供する上で、責任の所在は明確であるべきと考えます。

IaC ( Infrastructure as Code ) は、ソースコードを使用してインフラの構築・変更・破棄を行うことができます。IaC の魅力は、冪等性の確保と Git などのバージョン管理にあります。

しかし、すべての Load Balancer がこれらの要件を満たしているわけではありません。

最適な Load Balancing の提供

Load Balancing を適切に行うには、開発チームのワークフローやシステムを理解し、彼らの要求を正確に把握することが求められます。

最終的にチーム間の摩擦を減らすためには、 Load Balancer が提供する機能をよく理解し、プロダクトやサービス、プラットフォームに応じて適切な技術選定が重要です。

参考:

GKE クラスタ外へ Kubernetes アプリケーションを公開する方法

では、実際に GKE クラスタ上で実行されているアプリケーションを、外部へ公開する方法を見ていきましょう。まず初めに検証で使用するための GKE クラスタを作成します。その後、比較対象の Load Balancer である NEG, Ingress, Gateway API の使い方を説明します。

GKE クラスタの作成

クラスタに対するクラスタ管理者権限 cluster-admin が必要なので以下のコマンドを実行します。

$ kubectl create clusterrolebinding cluster-admin-binding \
  --clusterrole cluster-admin \
  --user $(gcloud config get-value account)
clusterrolebinding.rbac.authorization.k8s.io/cluster-admin-binding created

クラスタの作成をします。

gcloud container clusters create yinoue-cluster \
		--num-nodes 2 \
    --enable-ip-alias \
    --create-subnetwork="" \
    --network=default \
		--labels=team=intern \
    --zone=asia-northeast1-a

作成できたら gcloud container clusters list でクラスタの確認します。

$ gcloud container clusters list  
(中略)
NAME: yinoue-cluster
LOCATION: asia-northeast1-a
MASTER_VERSION: 1.27.8-gke.1067004
MASTER_IP: XXX.XXX.XXX.XXX
MACHINE_TYPE: e2-medium
NODE_VERSION: 1.27.8-gke.1067004
NUM_NODES: 2
STATUS: RUNNING
(中略)

では作成したクラスタに Load Balancer を実装していきましょう。

参考:

NEG (Network Endpoint Group)

Google Cloud の VPC ( Virtual Private Cloud ) ネットワークでは、 GKE 上の Kubernetes リソースに対して Network Endpoint を割り当てます。こうすることで、あたかも Kubernetes リソースである Pod や Service を Google Cloud のリソースとして扱うことが可能となります。

Network Endpoint は IP と Port からなるエンドポイントであり、 Kubernetes リソースの Pod に相当します。NEG は名前の通り、Network Endpoint を集結した集合を指します。これは、 Kubernetes リソースの Service に相当します。

それぞれの対応関係は、Google Cloud リソースの一つである NEG Controller を媒介しており、 Kubernetes と GKE の橋渡しを担います。なお、本文で述べる NEG は Zonal NEG を指すものとします。

ひとつ注意する点として、実際に Google Cloud で使用する Load Balancer が Ingress や Gateway API であった場合も、NEG は利用されます。

Ingress と NEG

  • Ingress は NEG の管理を簡素化し、コンテナネイティブのロード バランシングに適している
  • 仮想 IP アドレス、転送ルール、ヘルスチェック、ファイアウォール ルールの作成が容易

スタンドアロン NEG

  • NEG コントローラを介してデプロイ、管理される
  • 転送ルール、ヘルスチェック、ロード バランシング オブジェクトは手動でデプロイ

スタンドアロン NEG によるコンテナ ネイティブのロード バランシング

Standalone NEG ( Standalone Network Endpoint Group )

GKE における NEG とは、主に Load Balancer としての役割を期待される場面で登場することがしばしばあります ( Standalone NEG 等 ) 。

これは、コンテナネイティブ Load Balancing のメリットを指す場合であり、例えば Standalone NEG を使用することで VM 内部の iptables に頼らないルーティングが可能となります。

つまり、GCLB ( L4 Load Balancer ) から直接 Pod に対してルーティングを行うことで、負荷分散の際に発生する余分なネットワークホップを解消できるのです。

スタンドアロン NEG によるコンテナ ネイティブのロード バランシング

では、実際に Standalone NEG を使用してデプロイしてみましょう。以下の図の構成でデプロイします。

gcloud container clusters get-credentials yinoue-cluster --zone asia-northeast1-a を実行してクレデンシャルの取得します。

$ gcloud container clusters get-credentials yinoue-cluster --zone asia-northeast1-a
Fetching cluster endpoint and auth data.
kubeconfig entry generated for yinoue-cluster.

Google Cloud の NEG の生成を確認します。

$ gcloud compute network-endpoint-groups list
NAME: k8s1-bd505fd7-default-summer-svc-80-dedba7f2
LOCATION: asia-northeast1-a
ENDPOINT_TYPE: GCE_VM_IP_PORT
SIZE: 2

gcloud compute network-endpoint-groups list-network-endpoints k8s1-bd505fd7-default-summer-svc-80-dedba7f2 --zone=asia-northeast1-a を実行して Network Endpoint が Pod の個数分生成されいていることを確認します。

$ gcloud compute network-endpoint-groups list-network-endpoints k8s1-bd505fd7-default-summer-svc-80-dedba7f2 --zone=asia-northeast1-a
INSTANCE: gke-yinoue-cluster-default-pool-befecb7a-spnv
IP_ADDRESS: 10.40.0.71
PORT: 8080
FQDN:・・・・・・・・・・・・・・・・・・・

INSTANCE: gke-yinoue-cluster-default-pool-befecb7a-2f59
IP_ADDRESS: 10.40.1.85
PORT: 8080
FQDN:

マニフェストファイル

main.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: summer
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: summer
  template:
    metadata:
      labels:
        app: summer
    spec:
      containers:
      - name: summer
        image: gcr.io/google-samples/hello-app:2.0
        ports:
        - name: summer-http
          containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: summer-svc
  namespace: default
  annotations:
	  cloud.google.com/neg: '{"exposed_ports": {"80": {}}}'
    # cloud.google.com/neg: '{"Ingress": true}'
    # kubernetes.io/Ingress.class: "gce-internal"
spec: 
  type: ClusterIP
  selector:
    app: summer
  ports:
  - name: summer-port
    protocol: TCP
    port: 80
    targetPort: 8080

neg.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: neg-Ingress
  namespace: default
spec:
  rules:
  - host: Ingress-seasons.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: summer-svc
            port:
              number: 80

kubectl create -f main.yaml -f .\neg.yaml を実行してデプロイします。

次に動作確認のため、curl --resolve Ingress-seasons.com:80:34.128.163.240 -I http://Ingress-seasons.com を実行します。

$ curl --resolve Ingress-seasons.com:80:34.128.163.240 -I http://Ingress-seasons.com
HTTP/1.1 200 OK
Date: Wed, 01 May 2024 06:21:21 GMT
Content-Length: 62
Content-Type: text/plain; charset=utf-8
Via: 1.1 google

使い終わったらkubectl delete -f main.yaml -f .\neg.yaml を実行してPodを停止します。

参考:

Ingress ( Ingress-Nginx Controller )

Ingress はクラスタ内の Service に対する外部からのアクセス ( 主に HTTP ) を管理する L7 Load Balancing リソースです。

Ingress は負荷分散、SSL 終端、名前ベースの仮想ホスティングの機能を提供します。ただし、Ingress そのものはただの API オブジェクトであり、Ingress を使用するには Ingress リソースと Ingress Controller がセットで必要です。

Ingress リソースとは、マニフェストに記述された API リソースのひとつであり、いくつかの種類が存在しており、それぞれ Ingress が定める仕様を満たしつつ、様々な独自の拡張機能を提供しています。

Ingress Controller は Ingress リソースで定義した設定を反映して動作します。したがって、Ingress を使用する場合は他のアプリケーションと同様に、Ingress Controller 用の Deployment や Service を Kubernetes にデプロイする必要があります。

Ingress を使用した構成は以下の図の通りです。

Ingress-nginx controller のインストール

helm upgrade --install Ingress-nginx Ingress-nginx \
  --repo https://kubernetes.github.io/Ingress-nginx \
  --namespace Ingress-nginx --create-namespace

Kubernetes に適応させます。

kubectl apply -f https://raw.githubusercontent.com/kubernetes/Ingress-nginx/controller-v1.10.0/deploy/static/provider/cloud/deploy.yaml

Ingress nginx が動作しているか確認します。

$ kubectl get services -n Ingress-nginx
NAME                                 TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                      AGE
Ingress-nginx-controller             LoadBalancer   10.100.209.110   34.85.125.182   80:32579/TCP,443:32642/TCP   3h45m
Ingress-nginx-controller-admission   ClusterIP      10.100.220.91    <none>          443/TCP                      3h45m

マニフェストファイル

main.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: summer
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: summer
  template:
    metadata:
      labels:
        app: summer
    spec:
      containers:
      - name: summer
        image: gcr.io/google-samples/hello-app:2.0
        ports:
        - name: summer-http
          containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: summer-svc
  namespace: default
  annotations:
	  cloud.google.com/neg: '{"exposed_ports": {"80": {}}}'
    # cloud.google.com/neg: '{"Ingress": true}'
    # kubernetes.io/Ingress.class: "gce-internal"
spec: 
  type: ClusterIP
  selector:
    app: summer
  ports:
  - name: summer-port
    protocol: TCP
    port: 80
    targetPort: 8080

Ingress_nginx.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-Ingress
  namespace: default
  annotations:
    nginx.Ingress.kubernetes.io/rewrite-target: /
spec:
  IngressClassName: nginx
  rules:
    - host: Ingress-seasons.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: summer-svc
                port:
                  number: 80

kubectl create -f main.yaml -f Ingress_nginx.yaml を実行してデプロイします。

次に動作確認のため、curl --resolve Ingress-seasons.com:80:34.85.125.182 -I http://Ingress-seasons.com を実行します。

$ curl --resolve Ingress-seasons.com:80:34.85.125.182 -I http://Ingress-seasons.com
HTTP/1.1 200 OK
Date: Wed, 01 May 2024 06:18:29 GMT
Content-Length: 62
Content-Type: text/plain; charset=utf-8
Via: 1.1 google

使い終わったらkubectl delete -f main.yaml -f .\neg.yaml を実行してPodを停止します。

参考:

Gateway API

今回の目玉である Gateway API ですが、なぜ Ingress というネットワークモジュールが既に普及しているにも関わらず Gateway API は登場したのでしょうか。この疑問を解消するため、まずは Gateway API の歴史を少し紹介します。

Gateway API に関する議論は、2019年の KubeCon NA から本格的に始まったとされています。Gateway API が必要とされた理由は、Ingress がサポートする機能では実際のユースケースに耐えられなかったためです。そこで、多くの機能要求に対応できるスケーラブルな Ingress としてGateway API が実装されました。

Ingress と Gateway API の歴史や仕様比較に関する解説動画はたくさんあるので、詳細について知りたい方はこちらを参照してみて下さい。

参考:

ここからは、実際に Gateway API に触れていきましょう。 Gateway API は、Kubernetes クラスタ外部からクラスタ内のServiceへの L4/L7 でのルーティングを、3種類リソース GatewayClassGatewayRouteを用いて定義することができます。

  • GatewayClass
    • Gatewayを構成するためのテンプレートを示すリソース
    • Gatewayを構成するために使用するGateway Controllerをパラメータと共に指定する
    • このパラメータでGateway構成時に構築される Load Balancer を設定する
  • Gateway
    • リクエストをクラスタ内へルーティングするルールを定義するリソース
    • 指定したGatewayClassの定義を元に Load Balancer やプロキシ等を実際に構築する
    • クラスタ内のどこにルーティングするかはxRouteによって定義する
  • xRoute
    • GatewayからServiceに対するルーティングのルールを定義するリソース
    • Load Balancer でのパスベースのルーティングの指定等に対応
    • 対応するプロトコル毎にHTTPRouteTCPRouteTLSRouteUDPRouteが存在する

今回は使用しませんが、これまでアノテーションで定義していた機能を追加する場合は、 Custom Resource を定義することで Kubernetes API の拡張機能を扱うことができます。

では早速 Gateway API でデプロイしてみましょう。以下の図の構成で作成します。

Google Cloud Consoleにて、使用するクラスタの詳細の項目にあるGateway API を有効にします。

マニフェストファイル

main.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: summer
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: summer
  template:
    metadata:
      labels:
        app: summer
    spec:
      containers:
      - name: summer
        image: gcr.io/google-samples/hello-app:2.0
        ports:
        - name: summer-http
          containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: summer-svc
  namespace: default
  annotations:
	  cloud.google.com/neg: '{"exposed_ports": {"80": {}}}'
    # cloud.google.com/neg: '{"Ingress": true}'
    # kubernetes.io/Ingress.class: "gce-internal"
spec: 
  type: ClusterIP
  selector:
    app: summer
  ports:
  - name: summer-port
    protocol: TCP
    port: 80
    targetPort: 8080

gateway.yaml

apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: gateway
spec:
  gatewayClassName: gke-l7-rilb
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      kinds:
      - kind: HTTPRoute

route.yaml

apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: route
spec:
  parentRefs:
  - name: gateway
  hostnames:
  - "Ingress-seasons.com"
  rules:
  - matches:
    - path:
        value: /
    backendRefs:
      - name: summer-svc
        port: 80

kubectl create -f main.yaml -f .\gateway.yaml -f .\route.yaml を実行してデプロイします。

次に Gateway APIがデプロイできたことを確認するため、kubectl get gateway を実行します。

$ kubectl get gateway
NAME      CLASS         ADDRESS   PROGRAMMED   AGE
gateway   gateway                 Unknown      3m33s

使い終わったらkubectl delete -f main.yaml -f .\neg.yaml を実行してPodを停止します。

参考:

Platform Engineering の観点から考える Load Balancer の比較

ここからは、各 Load Balancer の比較を行っていきます。

① : 所掌の分離

「所掌」という普段聞きなれない言葉が出てきました。

ここで言う「所掌」とは、人・チームが特定の業務・役割・責任を担当することを指します。

例えば、アプリケーション開発者であれば、アプリの実装と管理を行います。クラスタ運用者であれば、サービスや開発プラットフォームなどすべてのクラスタを管理し最適化します。

このように、所掌の分離とは、組織やシステムにおいてそれぞれの役割や責任を明確に分けることを指します。Team Topologies は、まさにこの考え方をもとに組織設計を行うためのモデルです。

今回は実際の役割を想定して3人のペルソナを用意しました( Roles and Personasを参考 )。

  • 👷 インフラプロバイダ ( Infrastructure Providers )
  • 🧑‍🔧 クラスタ運用者 ( Cluster Operators )
  • 🧑‍💻 アプリケーション開発者 ( Application Developers )

では、先程の3つの Load Balancer は Google Cloud リソース上でどのように所掌の分離が行われるのか比較しましょう。

  • Standalone NEG の場合
    • 👷 インフラプロバイダ
      • Forwarding Rule, Target HTTP Proxy, URLMap, BackendService, NEG をユーザへ提供
    • 🧑‍🔧 クラスタ運用者
      • GUI ( Web コンソール ), CLI ( gcloud コマンド ), IaC ツールによって管理
      • 高度なルーティングやトラフィック分割はできない
    • 🧑‍💻 アプリケーション開発者
      • アプリケーションのデプロイはマニフェストによって管理
      • URLMap など一部のアプリ側で管理したいトラフィックリソースの分離は不可
  • Ingress の場合
    • 👷 インフラプロバイダ
      • Forwarding Rule, Target HTTP Proxy, URLMap, BackendService, NEG をユーザへ提供
    • 🧑‍🔧 クラスタ運用者
      • Google Cloud リソースからルーティングルールまですべてを1つのマニフェストで管理
      • トラフィック分割は不可
      • ルーティングルールに詳細な定義を追加するのは困難
    • 🧑‍💻 アプリケーション開発者
      • アプリケーションのデプロイはマニフェストによって管理
      • アプリケーションに関わるトラフィックやルーティングの管理は不可
  • Gateway API の場合
    • 👷 インフラプロバイダ
      • Gateway リソースと xRoute リソースに分離
      • GatewayClasses という負荷分散の種類を形式化したものをユーザに提供
    • 🧑‍🔧 クラスタ運用者
      • Gateway リソースと呼ばれる Load Balancer を管理
      • Namespace 間でリソースの共有が可能
    • 🧑‍💻 アプリケーション開発者
      • ルートリソースをマニフェストで管理
      • アプリケーションに応じた詳細なルーティングルールの定義が可能

② : 認知負荷

これまで扱ってきた Load Balancer は、既に実際のプロダクトで使用されている機能です。そこで、技術選定のときの参考として、導入時の学習コストをテーマにまとめます。

  • Standalone NEG
    • 🧑‍🔧 クラスタ運用者 ( Cluster Operators )
      • Web コンソール、gcloud、IaC ツール ( Terraform, Pulumi etc… ) を使用して GCLB を管理する
      • Ingress Controller を考慮せずに実装可能
      • マニフェストは Ingress 準拠のため Ingress が書き慣れている人は移行しやすい
    • 🧑‍💻 アプリケーション開発者 ( Application Developers )
      • GCLB がルーティングなどの制御を担ってくれる
      • 扱えるリソースは Pod と Service のみ
      • 複雑な構成でなければ比較的簡単にマニフェストは書ける
  • Ingress
    • 🧑‍🔧 クラスタ運用者 ( Cluster Operators )
      • Ingress に関する資料が豊富
      • 複雑なルーティングを定義する場合には外部ベンダー ( cilium, traefik, etc… ) が提供する機能に依存する
    • 🧑‍💻 アプリケーション開発者 ( Application Developers )
      • Deployment でアプリケーションを定義する
      • Service の L4 ルーティングのみ扱える
  • Gateway API
    • 🧑‍🔧 クラスタ運用者 ( Cluster Operators )
      • 複雑なルーティングであっても設計が煩雑にならない
      • Ingress からの移行作業などを考えると新たに学習する内容が多い
      • 機能について解説する資料はあるが日本語は少ない
    • 🧑‍💻 アプリケーション開発者 ( Application Developers )
      • xRoute を定義することで L7 ルーティングを扱うことができる
      • アプリケーションに関連するルーティングを管理できる
      • xRoute を使用するため、ネットワークに関する知識が要求される

③: ヘルスチェックの指定

Kubernetes にはヘルスチェックという機能があります。Liveness Probe はデッドロック状態を検知し、再起動の有無を判断します。Readiness Probe は Pod がトラフィックを受け取れない場合に Service のリソースから除外します。

Load Balancer 毎にヘルスチェックの実装は異なります。ここでは、GKE が Gateway API と Ingress に対してヘルスチェックを行う際の違いについて見ていきます。

  • Google Cloud Load Balancer
    • readinessProbelivenessProbe とは異なる、クラスタの外部で実装されるロードバランサのヘルスチェック
    • Service のexternalTrafficPolicy を設定することでヘルスチェックの動作の定義を行う
    • 実態は kube-proxy から情報を収集するプロキシであり、kube-proxy が Pod から収集したヘルスチェックプローブの情報などを扱う
  • Ingress の場合
    • Pod の readinessProbe に定義することで GCLB のヘルスチェックが設定される
      • Pod が0の場合 readinessProbe は有効にならない
    • 確実に GCLB のヘルスチェックを設定するには BackendConfig リソースでヘルスチェックプローブを指定する
  • Gateway API の場合
    • 専用のカスタムリソースで設定
    • 各種プロトコル ( http, https, udp, http2 ) についてヘルスチェックを設定可能
    • HealthCheckPolicy によるヘルスチェックの設定が推奨
      • 現状は BackendConfig でのヘルスチェックの設定もサポートされているが、いつサポート外になるかは不明

参考:

比較観点のまとめ

大きく「①所掌の分離」「②認知負荷」「③ヘルスチェック」について見てきました。 これ以外の比較については以下のにまとめました。

Standalone NEGIngressGateway API
シンプルさ
拡張性
クラウドプラットフォームGoogle Cloud Platform汎用汎用
プロトコルのサポートHTTP/HTTPS, TCP, UDPHTTP/HTTPSHTTP/HTTPS, TCP, UDP, SCTP
トラフィックの分割不可不可可能
マルチクラスタへのルーティング可能不可可能
機能の拡張不可ベンダーごとに独自のアノテーションを実装することで可能カスタムリソースを定義することで可能
Gitによるバージョン管理可能可能可能
IaC ツールの使用
( Terraform )
可能可能未対応

参考:

検証結果の考察

組織の成熟度の考慮

Gateway API が提供する強力かつ拡張性の高い Load Balancing は、必ずしもすべてのプラットフォームで要求されるスペックではありません。

所掌の分離を行うということは、Load Balancer の運用と責任は各チームに分散されます。

それゆえ、チーム内のエンジニアは新しいツールへの対応を迫られ、一時的にエンジニアへの認知負荷が大きくなることが予想されます。

それでも長期的に見ればチームの DX 向上に繋がるでしょうか。あるいは開発チームは Gateway API への移行作業を行う体力が本当にあるでしょうか。プラットフォームエンジニアはあらゆるリスクを考慮したうえで選択を行う必要があります。

私個人の意見としては、Gateway API の所掌分離は、比較的大規模かつ成熟した開発チームで効果が最も期待されると考えています。

中小規模のチームでは、まず組織全体の成熟度を客観的に分析しましょう。

スリーシェイクの元内氏は自身のブログの中で、「プラットフォームは静的なものではなく、組織の成熟度に合わせて進化していくべきものである」 ( Platform Engineering on Kubernetes を読んでCloud Native の現在地を理解する – 6 Let’s build a platform on top of Kubernetes ) と述べています。

理由なく新しいものに飛びつくのは技術選定とは呼べません。プラットフォームエンジニアには、組織やエンジニアが今必要としているものを確実に提供することが求められます。

クラウドプロバイダは味方

開発者の認知負荷を下げる取り組みのひとつとして、クラウドプロバイダが提供するリソースを活かすという手段があります。

例えば、今回使用した Google Cloud や AWS には、インスタンスリソース ( CPU, Memory, Network etc… ) を Web コンソールや CLI から確認できる機能が標準で備わっています。あるいは、今回 Load Balancer で扱った Standalone NEG は Google Cloud のリソースを使った外部接続サービスです。

これらのツールは、サービスを運用する上で強力な武器となり、開発者の助けになります。Web コンソールを利用すれば、最低限のオブザーバビリティを提供してくれますし、Standalone NEG の採用は、インフラ管理者が複雑なマニフェストを定義せずとも最適な Load Balancing を実装できます。

すべての機能を自前で用意せずとも、プロバイダが用意するサービスの恩恵を十分に得ることで、解決できるチームの問題はあるはずです。少しでも開発リソースをプロダクトへ向けるために、クラウドプロバイダを選択肢として考えてみてはいかがでしょうか。

加速する Gateway API 移行

Gateway API が GA となり間もなく1年が経ちます。Gateway API へ移行する流れは、それ以前から各所で起こっていました。特にサービスメッシュを提供するベンダーでは、トラフィック管理に関する大規模なサービスの移行が行われています。最近では Gateway API を推奨する人も増えてきており、今後 Ingress から Gateway API へ移行する事例はさらに増加していくことでしょう。

ここで疑問に思うのは、今動いているサービス、あるいはこれから作るサービスの Load Balancer を Gateway API へ移行するべきなのでしょうか。

現状、この答えはいいえです。

前述の通り、Gateway API はその拡張性の高さから Ingress の上位互換として捉えることができますが、それゆえにサービスの規模によって Gateway API の使用はオーバースペックな場合も考えられます。

Ingress の良さは、複雑なルーティング制御をシンプルに実装できることです。

GCLB であれば、グローバルスケールでの負荷分散を実現し、Google Cloudの他のサービスとのシームレスな統合が可能です。

あるいは、サービスの将来のスケールアウト・スケールアップに備えるため、技術選定の段階で Gateway API を選択するのも戦略のひとつです。

自分たちが作っているサービスの現状を知り、将来を見据えた選択を行うため、一度 Gateway API への移行を検討してみることを推奨します。

おわりに

ここまでお付き合い下さりありがとうございました。
検証を始めた当初は、これほどの長文になるとは想定しておりませんでした。

最後に、ここまで話してきた内容を振り返り、 今後の Gateway API に関する展望について紹介したいと思います。

Platform Engineering の価値

これまで話してきた通り Platform Engineer とは、ただプラットフォームを提供するだけの役割ではないのです。Platform Engineer が SRE と同様の業務をこなすのであれば、わざわざ2つを区別する必要はありません。
そもそも Platform Engineering ではなぜ KPIs を設定し、Golden Paths を作成する必要があるのでしょうか。
それは、Platform Engineering で定義される全ての工程が、開発者の生産性を高めるためにあるからです。

Platform Engineering におけるプラットフォームの構築とは、使用するツールを標準化し、面倒なインストールやテスト工程を自動化するだけでなく、一見エンジニアリングとは関係のないドキュメントの整理や、開発者へのヒアリングなど、これら全てを包括するプロセスです。そして、DevOps の思想の元、プラットフォームの現状を良しとせず、常に改善します。

これは Platform Engineer が開発チームに寄り添うことで初めて実現可能なのです。したがって、Platform Engineer はエンジニアやステークスホルダーとの継続的なコミュニケーションが欠かせません。

Platform Engineering の価値とは、技術への深い理解とチーム内での技術の統一化、そしてコミュニケーションであると思います。

今後の Gateway API

Gateway API は様々なサービスに実装され、これからますます普及することでしょう。2024年8月現在の Gateway API に関する情報をいくつか紹介します。

  • Gateway API の普及活動
    MIXI ではなんと、既に今年の新卒研修の Kubernetes ハンズオンの内容に Gateway API を採用されています。 コンテナ・K8s研修 – 後半 Kubernetes 基礎&ハンズオン【MIXI 24新卒技術研修】
  • Gateway API とその周辺の開発コミュニティ
    Gateway API の開発は活発です。認証認可の機能については、去年の年末あたりから議論が行われており、現在も活発に活動しているようです。 Add support for HTTP Basic Authentication 個人的に注目していた HTTP3 の実装は、現在プルリクエストされており、近いうちに RC されるのではと期待しています。 HTTP3 and QUIC support Add HTTP/3 support そうなると Ingress の開発は下火になってしまうのかと心配されるかと思います。ですが今の所 Ingress でも開発は続けられており、例えば HTTP3 の実装について Ingress-NGINX Controller では以前からその動向が注目されています。 [FEATURE REQUEST] HTTP/3 support
  • Gateway API への移行状況
    様々な機能を提供する各企業も Gateway API へ移行しています。Gateway API の公式サイトでは、Implementations にてそれぞれのプロジェクトの実装状況が確認できます。Istiocilium は Gateway API に対応した GA をすでにリリースしており、今後の動向にも注目したいところです。Istio では、将来的にサービスメッシュのデフォルト API として採択する予定だと公表しています。 Istio は Kubernetes Gateway APIをサポートしており、将来的にはこれをトラフィック管理のデフォルト API にする予定です。Gateway API を使用して Istio を使い始める場合は、以下の手順ではなく、将来の入門手順を参照して下さい。Ingress Gateways

Gateway API を取り巻く環境は、常に活発な議論とアイデアの応酬が繰り広げられており、今後より大きなプロジェクトとして成熟していくと思います。より多様なプロトコルへの対応することで、アプリケーションの利用にとどまらず、サービスメッシュでの需要を確実に獲得するでしょう。しかしながら、Gateway API は現在ユーザのユースケースから得られた情報を収集するフェーズです。それゆえ Gateway API の運用に関する知見は少ないです。Gateway API を今後さらに盛り上げていくため、ぜひ前向きな利用を検討してみて下さい。

参考文献

ブログ一覧へ戻る

お気軽にお問い合わせください

SREの設計・技術支援から、
SRE運用内で使用する
ツールの導入など、
SRE全般についてご支援しています。

資料請求・お問い合わせ