Istioにおける高速化されたオフロード接続負荷分散の使用
IstioゲートウェイでDLB接続負荷分散構成を使用して接続負荷分散を高速化します。
接続負荷分散とは?
負荷分散は、サーバーファーム内の複数のサーバーにトラフィックを分散するために使用されるコアネットワーキングソリューションです。負荷分散装置は、アプリケーションの可用性と応答性を向上させ、サーバーの過負荷を防ぎます。各負荷分散装置は、クライアントデバイスとバックエンドサーバーの間に位置し、受信リクエストを受け取って、それらを処理可能な任意の利用可能なサーバーに分散します。
一般的な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は、次の負荷分散機能を実装します
- ソフトウェアからのキュー管理のオフロード—キューイングベースのコストが高い場合に役立ちます。
- 特に、マルチプロデューサー/マルチコンシューマーシナリオと、複数の宛先へのエンキューバッチ処理に役立ちます。
- ソフトウェアの共有キューにアクセスするには、オーバーヘッドロックが必要です。Intel DLBは、共有キューへのロックフリーアクセスを実装します。
- 動的なフロー対応負荷分散と並べ替え。
- タスクの均等な分散とCPUコアのより良い利用を保証します。必要に応じて、フローベースのアトミシティを提供できます。
- パケットの順序を失うことなく、帯域幅の広いフローを多くのコアに分散します。
- より良い決定論と、過剰なキューイング遅延を回避します。
- IOメモリのフットプリントを削減し、DDR帯域幅を節約します。
- 優先キューイング(最大8レベル)— QOSを可能にします。
- レイテンシの影響を受けやすいトラフィックのレイテンシを低減します。
- パケット内のオプションの遅延測定。
- スケーラビリティ
- アプリケーションの動的なサイズ変更、シームレスなスケールアップ/ダウンを可能にします。
- 電力認識。負荷が軽い場合、アプリケーションはワーカーを低電力状態に落とすことができます。
負荷分散キューには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公式ドキュメントを参照してください。