Istioにおける高速化されたオフロード接続負荷分散の使用

IstioゲートウェイでDLB接続負荷分散構成を使用して接続負荷分散を高速化します。

2023年8月8日 | Loong Dai - Intel

接続負荷分散とは?

負荷分散は、サーバーファーム内の複数のサーバーにトラフィックを分散するために使用されるコアネットワーキングソリューションです。負荷分散装置は、アプリケーションの可用性と応答性を向上させ、サーバーの過負荷を防ぎます。各負荷分散装置は、クライアントデバイスとバックエンドサーバーの間に位置し、受信リクエストを受け取って、それらを処理可能な任意の利用可能なサーバーに分散します。

一般的なWebサーバーの場合、通常、複数のワーカー(プロセッサーまたはスレッド)があります。多数のクライアントが1つのワーカーに接続すると、このワーカーはビジーになり、テールレイテンシが長くなり、他のワーカーがフリーな状態で実行されて、Webサーバーのパフォーマンスに影響を与えます。接続負荷分散は、この状況に対するソリューションであり、接続バランシングとも呼ばれます。

Istioは接続負荷分散に対して何を行いますか?

IstioはデータプレーンとしてEnvoyを使用します。

Envoyは、Exact接続バランサーと呼ばれる接続負荷分散の実装を提供します。その名前が示すように、バランシング中にロックが保持されるため、ワーカー間の接続数がほぼ完全に均衡します。接続が並行して閉じられてカウントが不正確になる可能性があるという意味で「ほぼ」正確ですが、これは次の受け入れ時に修正されるはずです。このバランサーは、精度を優先して受け入れスループットを犠牲にするため、接続数が少なく、めったにサイクルしない場合、たとえばサービスメッシュgRPCエグレスで使用する必要があります。

明らかに、イングレスゲートウェイは短時間で数千の接続を受け入れるため、イングレスゲートウェイには適していません。ロックによるリソースコストによりスループットが大幅に低下します。

現在、EnvoyはIntel® Dynamic Load Balancing(Intel®DLB)接続負荷分散を統合して、イングレスゲートウェイのような接続数の多いケースでの高速化を実現しています。

Intel®Dynamic Load BalancingがEnvoyで接続負荷分散を高速化する方法

Intel DLBは、プロデューサーとコンシューマーを接続するキューとアービターのハードウェア管理システムです。これは、サーバーCPUのアンコアに存在することを想定したPCIデバイスであり、コアで実行されているソフトウェア、および他のデバイスと対話できます。

Intel DLBは、次の負荷分散機能を実装します

負荷分散キューには3つのタイプがあります

イングレスゲートウェイは、可能な限り多くのデータを可能な限り迅速に処理することが期待されているため、Intel DLB接続負荷分散は順序なしキューを使用します。

IstioでIntel DLB接続負荷分散を使用する方法

1.17リリースで、IstioはIntel DLB接続負荷分散を正式にサポートします。

次の手順では、Kubernetesクラスターが実行されていることを前提として、SPR(Sapphire Rapids)マシンでIstioイングレスゲートウェイでIntel DLB接続負荷分散を使用する方法を示します。

ステップ1:DLB環境の準備

Intel DLBドライバ公式サイトの手順に従って、Intel DLBドライバをインストールします。

次のコマンドでIntel DLBデバイスプラグインをインストールします

$ kubectl apply -k https://github.com/intel/intel-device-plugins-for-kubernetes/deployments/dlb_plugin?ref=v0.26.0

Intel DLBデバイスプラグインの詳細については、Intel DLBデバイスプラグインのホームページを参照してください。

Intel DLBデバイスリソースを確認できます

$ kubectl describe nodes | grep dlb.intel.com/pf
  dlb.intel.com/pf:   2
  dlb.intel.com/pf:   2
...

ステップ2:Istioをダウンロードする

このブログでは、1.17.2を使用します。インストールをダウンロードしましょう

$ curl -L https://istio.dokyumento.jp/downloadIstio | ISTIO_VERSION=1.17.2 TARGET_ARCH=x86_64 sh -
$ cd istio-1.17.2
$ export PATH=$PWD/bin:$PATH

バージョンが1.17.2であることを確認できます

$ istioctl version
no running Istio pods in "istio-system"
1.17.2

ステップ3:Istioをインストールする

Istioのインストール構成を作成します。イングレスゲートウェイに4つのCPUと1つのDLBデバイスを割り当て、同時実行数をCPU数と同じ4に設定することに注意してください。

$ cat > config.yaml << EOF
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  profile: default
  components:
    ingressGateways:
    - enabled: true
      name: istio-ingressgateway
      k8s:
        overlays:
          - kind: Deployment
            name: istio-ingressgateway
        podAnnotations:
          proxy.istio.io/config: |
            concurrency: 4
        resources:
          requests:
            cpu: 4000m
            memory: 4096Mi
            dlb.intel.com/pf: '1'
          limits:
            cpu: 4000m
            memory: 4096Mi
            dlb.intel.com/pf: '1'
        hpaSpec:
          maxReplicas: 1
          minReplicas: 1
  values:
    telemetry:
      enabled: false
EOF

istioctlを使用してインストールします

$ istioctl install -f config.yaml --set values.gateways.istio-ingressgateway.runAsRoot=true -y
✔ Istio core installed
✔ Istiod installed
✔ Ingress gateways installed
✔ Installation complete                                                                                                                                                                                                                                                                       Making this installation the default for injection and validation.

Thank you for installing Istio 1.17.  Please take a few minutes to tell us about your install/upgrade experience!  https://forms.gle/hMHGiwZHPU7UQRWe9

ステップ4:バックエンドサービスのセットアップ

IstioイングレスゲートウェイでDLB接続負荷分散を使用する場合、最初にバックエンドサービスを作成する必要があります。

httpbinをテストするために、Istioが提供するサンプルを使用します。

$ kubectl apply -f samples/httpbin/httpbin.yaml
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: httpbin-gateway
spec:
  # The selector matches the ingress gateway pod labels.
  # If you installed Istio using Helm following the standard documentation, this would be "istio=ingress"
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "httpbin.example.com"
EOF
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbin
spec:
  hosts:
  - "httpbin.example.com"
  gateways:
  - httpbin-gateway
  http:
  - match:
    - uri:
        prefix: /status
    - uri:
        prefix: /delay
    route:
    - destination:
        port:
          number: 8000
        host: httpbin
EOF

/statusと/delayパスのトラフィックを許可する2つのルーティングルールを含む、httpbinサービス用の仮想サービス構成が作成されました。

ゲートウェイリストは、httpbin-gatewayを介したリクエストのみが許可されることを指定します。他のすべての外部リクエストは404応答で拒否されます。

ステップ5:DLB接続負荷分散を有効にする

$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: dlb
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      istio: ingressgateway
  configPatches:
  - applyTo: LISTENER
    match:
      context: GATEWAY
    patch:
      operation: MERGE
      value:
        connection_balance_config:
            extend_balance:
              name: envoy.network.connection_balance.dlb
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.network.connection_balance.dlb.v3alpha.Dlb
EOF

イングレスゲートウェイポッドistio-ingressgateway-xxxxのログを確認すると、次のようなログエントリが表示されることが予想されます

$ export POD="$(kubectl get pods -n istio-system | grep gateway | awk '{print $1}')"
$ kubectl logs -n istio-system ${POD} | grep dlb
2023-05-05T06:16:36.921299Z     warning envoy config external/envoy/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc:46        dlb device 0 is not found, use dlb device 3 instead     thread=35

Envoyは自動的にDLBデバイスを検出して選択します。

ステップ6:テスト

$ export HOST="<YOUR-HOST-IP>"
$ export PORT="$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')"
$ curl -s -I -HHost:httpbin.example.com "http://${HOST}:${PORT}/status/200"
HTTP/1.1 200 OK
server: istio-envoy
...

-Hフラグを使用して、Host HTTPヘッダーをhttpbin.example.comに設定することに注意してください。これは、現在、そのホストのDNSバインディングがなく、リクエストをイングレスIPに送信しているだけであるためです。

/etc/hostsにDNSバインディングを追加して、-Hフラグを削除することもできます

$ echo "$HOST httpbin.example.com" >> /etc/hosts
$ curl -s -I "http://httpbin.example.com:${PORT}/status/200"
HTTP/1.1 200 OK
server: istio-envoy
...

明示的に公開されていない他のURLにアクセスします。HTTP 404エラーが表示されるはずです

$ curl -s -I -HHost:httpbin.example.com "http://${HOST}:${PORT}/headers"
HTTP/1.1 404 Not Found
...

デバッグログレベルをオンにして、DLB関連のログをさらに表示できます

$ istioctl pc log ${POD}.istio-system --level debug
istio-ingressgateway-665fdfbf95-2j8px.istio-system:
active loggers:
  admin: debug
  alternate_protocols_cache: debug
  aws: debug
  assert: debug
  backtrace: debug
...

curlを実行して1つのリクエストを送信すると、以下のようになります

$ kubectl logs -n istio-system ${POD} | grep dlb
2023-05-05T06:16:36.921299Z     warning envoy config external/envoy/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc:46        dlb device 0 is not found, use dlb device 3 instead     thread=35
2023-05-05T06:37:45.974241Z     debug   envoy connection external/envoy/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc:269   worker_3 dlb send fd 45 thread=47
2023-05-05T06:37:45.974427Z     debug   envoy connection external/envoy/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc:286   worker_0 get dlb event 1        thread=46
2023-05-05T06:37:45.974453Z     debug   envoy connection external/envoy/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc:303   worker_0 dlb recv 45    thread=46
2023-05-05T06:37:45.975215Z     debug   envoy connection external/envoy/contrib/network/connection_balance/dlb/source/connection_balancer_impl.cc:283   worker_0 dlb receive none, skip thread=46

Istio Ingress Gatewayの詳細については、Istio Ingress Gateway公式ドキュメントを参照してください。

この投稿を共有