OpenShift 4.x でのサービスのトラフィック処理、OVN および SDN の選択アルゴリズムなど
目次
免責条項: 以下に示す外部の Web サイトへのリンクは、お客様の利便性のみを目的として提供しています。Red Hat はリンクの内容を確認しておらず、そのコンテンツや有用性について責任を負わないものとします。外部の Web サイトへのリンクを含めることは、Web サイトまたはそれらの法的主体、製品またはサービスについて Red Hat が承認したことを意味するものではありません。お客様は、外部サイトまたはコンテンツの使用 (または信頼) によって生じる損失または費用について、Red Hat が責任を負わないことに同意するものとします。
この記事では、OpenShift 4 (執筆時点では OpenShift 4.15 まで) でトラフィック管理用に選択されるさまざまなバランシングアルゴリズムについて説明します。
ロードバランサータイプのサービスでセッションアフィニティーを有効にする
デフォルトでは、サービスのセッションアフィニティー (スティッキーセッション) は無効になっており、リクエストはバックエンド Pod 間でランダムに分散されます。つまり、サービスのデフォルトオプションは、サービス経由で Pod に送信されるトラフィックのセッションアフィニティー (スティッキーセッション) を無効にすることです。つまり、サービスに送信されるすべてのトラフィックは、デフォルトで毎回異なる Pod にルーティングされます。そのため、望ましくない結果が生じる可能性があります。
ただし、HTTP の Keep-Alive やセッションアフィニティーなどの要素が、リクエストの分散に影響を与えます。詳細は以下を参照してください。
-
リクエストが同じ接続から送信される限り、Keep-Alive はリクエストに影響を与えます。リクエスト間のアイドル時間が Keep-Alive のタイムアウトを超えない場合、接続は開いたままになります。
-
セッションアフィニティー (またはスティッキーセッション) は、リクエストを特定の Pod にリダイレクトすることで、リクエストの分散に影響を与えることができます。サービスの仕様
spec.sessionAffinity:ClientIPを介してセッションアフィニティーを有効にします (デフォルトはnone、つまり無効です)。これにより、リクエストを行うクライアント Pod のClientIPを介して、トラフィックが毎回同じバックエンド Pod にルーティングされるようになります。
追加の参考資料
-
kubernetes.io - Virtual IPs and Service Proxies - Session Affinity
-
docs.redhat.com OpenShift Container Platform 4.13 - Network APIs Chapter 17 - Service
OVN-Kubernetes と open-vswitch の概要
概要
OVN は OVS のアルゴリズム dp-hash を使用して、受信トラフィックリクエストを重み付けし、利用可能な一致するバケット (Pod) とマッチします。これにより、実質的にバックエンドがランダムに選択されることになります。ただし、選択方法の性質上、この選択は不完全なものです。サービス経由でルーティングすると、バックエンド間でトラフィックが不均等に分散される可能性があります (HAProxy、Nginx、Service Mesh などの "スマート" な選択サービスとは対照的です)。
詳細
OVN-Kubernetes では、open-vswitch の一部としてハッシュアルゴリズム dp-hash をデフォルトの選択方法として使用し、サービスにルーティングされる受信情報に基づいてリクエストをさまざまなバケット (バックエンド/Pod) にルーティングします。ハッシュはリクエストに重みを付けてバックエンドに分散します。これにより、分散に効率的なランダム化効果が得られます。ただし、ハッシュされるデータの性質上、選択が必ずしもバックエンド間で均等に分散されるわけではないことが予想されます。
デフォルトのハッシュフィールドには、送信元および宛先イーサネットアドレス、VLAN ID、送信元および宛先 IP アドレス、送信元および宛先 TCP/UDP ポートが含まれています。
ozlabs.org - [ovs-dev] FAQ:Explain hash function for select groups. (以下の抜粋):
+### Q: How does OVS divide flows among buckets in an OpenFlow "select" group?
+
+A: In Open vSwitch 2.3 and earlier, Open vSwitch used the destination
+ Ethernet address to choose a bucket in a select group.
+
+ Open vSwitch 2.4 and later by default hashes the source and
+ destination Ethernet address, VLAN ID, Ethernet type, IPv4/v6
+ source and destination address and protocol, and for TCP and SCTP
+ only, the source and destination ports. The hash is "symmetric",
+ meaning that exchanging source and destination addresses does not
+ change the bucket selection.
+
+ Select groups in Open vSwitch 2.4 and later can be configured to
+ use a different hash function, using a Netronome extension to the
+ OpenFlow 1.5+ group_mod message. For more information, see
+ Documentation/group-selection-method-property.txt in the Open
+ vSwitch source tree. (OpenFlow 1.5 support in Open vSwitch is still
+ experimental.)
+
ハッシュでは完全な分割は行われません。一方、分散はバックエンドの合計数の影響を受けることがあります。バックエンドの合計数が大きいほど、(Pod が多いほど) 分散比率が向上することがあります。openvswitch.org - [ovs-discuss] Hash function を参照してください。
openvswitch.org - ovs-ofctl(8) の man ページ:
dp_hash
Use a datapath computed hash value. The hash algorithm
varies across different datapath implementations.
dp_hash uses the upper 32 bits of the selec‐
tion_method_param as the datapath hash algorithm selec‐
tor. The supported values are 0 (corresponding to hash
computation over the IP 5-tuple) and 1 (corresponding to
a symmetric hash computation over the IP 5-tuple). Se‐
lecting specific fields with the fields option is not
supported with dp_hash). The lower 32 bits are used as
the hash basis.
Using dp_hash has the advantage that it does not require
the generated datapath flows to exact match any addi‐
tional packet header fields. For example, even if multi‐
ple TCP connections thus hashed to different select group
buckets have different source port numbers, generally all
of them would be handled with a small set of already es‐
tablished datapath flows, resulting in less latency for
TCP SYN packets. The downside is that the shared data‐
path flows must match each packet twice, as the datapath
hash value calculation happens only when needed, and a
second match is required to match some bits of its value.
This double-matching incurs a small additional latency
cost for each packet, but this latency is orders of mag‐
nitude less than the latency of creating new datapath
flows for new TCP connections.
すべてのセッションで、dp-hash は、カーネルデータパス (OVS DP フロー) 内で、skb_get_hash(skb) が返すものに変換されます。 ローカルで生成されたトラフィック (OVN ネットワークの Pod) の場合、skb_get_hash(skb) は、TCP sock 構造自体から取得され、ランダムな値に設定された skb->hash を返します。
同じタプルを使用する新しいセッションでは、異なる skb->l4_hash が取得される場合があります。その結果、バックエンドへのトラフィックがランダムに分散されます。
トラフィックがクラスター内から発信される (Pod からサービス、そして Pod へ送信される) 場合、重複や同じバックエンドへのトラフィックルーティングの繰り返しを回避するために、セッションには毎回ランダムなハッシュ値が割り当てられます。namespace に関係なく、セッションを開始するクライアントが Pod の場合、ハッシュがランダムになり、セッションアフィニティーが確実に無効になります。そうでない場合、内部クライアントからのセッションアフィニティーが存在する可能性があります。
Bugzilla BZ#1707513 では、dp-hashing をデフォルトとして選択することについて説明されており、github.com - openvswitch プロジェクトページ ではハッシュの順序付けを説明しています。
また、一貫性ハッシュ (dp-hash 関数) の利点と問題点について説明している medium.com の記事のハイライト (以下に抜粋) も確認する価値があります。
Then there’s consistent hashing. Consistent hashing uses a more elaborate scheme, where each server is assigned multiple hash values based on its name or ID, and each request is assigned to the server with the “nearest” hash value. The benefit of this added complexity is that when a server is added or removed, most requests will map to the same server that they did before.
Since the dp-hash function is selecting based on values that are variable on incoming request, the matched backend is going to have some variance on selection.
ここでの要点は次のとおりです。OVN-Kubernetes でサービスを使用してトラフィックをルーティングすると、使用可能なすべてのバックエンドを対象にランダムな選択順序が決定されます。使用されているハッシュサービスの性質上、一部のバックエンドが他のバックエンドよりも頻繁にアクセスされます。 OVN コアは、ハッシュ選択を dp-hash から hash に変更する機能をサポートしています (github.com - commit 5af304e を参照)。しかし、ハッシュまたは選択方法の変更は現在の OpenShift リリースではサポートされておらず、利用できません。このオプションは、Red Hat が提供するバージョンでは公開されていません。
バックエンドへのトラフィックをより均等に分散したり、RoundRobin のような管理された選択順序オプションを使用する必要がある場合は、Ingress やリバースプロキシー (HAProxy、nginx、サービスメッシュなど) などのインテリジェントルーティングソリューションを利用して、これらのバックエンドにトラフィックをより細かく制御しながらルーティングする必要があります。
OVN-Kubernetes のバランシング修正の更新
-
dp-hash の選択順序と github.com のコミット cb64234 におけるこの負荷分散の問題を解決するために、アップストリーム OVS への更新が導入されました。 -
これは RFE-4200 で確認できます。
-
以下は変更点を説明した更新内容の抜粋です。詳細は、上記の Commit を参照してください。
Approach taken in this change is to ensure that the hash space is
at least 4 times larger than the number of buckets, but not larger
than the maximum allowed (256). This provides a better distribution
while not unnecessarily exploding number of datapath flows for
services with not that many backends.
Here is some data to demonstrate why the 4 was chosen as a coefficient:
coeff. : 1 2 3 4 5 100
-------------------------------------------------------------------
AvgDiff : 43.1 % 27.1 % 18.3 % 15.1 % 13.6 % 10.9 %
MaxDiff : 50.0 % 33.3 % 25.0 % 20.0 % 20.0 % 20.0 %
AvgDev : 24.9 % 13.4 % 8.5 % 6.9 % 6.1 % 4.8 %
MaxDev : 35.4 % 20.4 % 14.4 % 11.2 % 11.2 % 11.2 %
--------+----------------------------------------------------------
16 : 1 1 1 1 1 -
32 : 17 9 6 5 4 -
64 : 33 17 11 9 7 -
128 : 65 33 22 17 13 1
256 : 129 65 43 33 26 2
--------+----------------------------------------------------------
current proposed
Table shows average and maximum load difference (Diff) between backends
across groups with 1 to 64 equally weighted backends. And it shows
average and maximum standard deviation (Dev) of load distribution for
the same. For example, with a coefficient 2, the maximum difference
between two backends will be 33% and the maximum standard deviation
will be 20.4%. With the current logic (coefficient of 1) we have
maximum difference as high as 50%, as shown with the example at the
beginning, with the standard deviation of 35.4%.
The bottom half of the table shows from how many backends we start to
use a particular number of buckets. For example, with a coeff. 3
we will have 16 hashes for 1 to 5 buckets, 32 hashes for 6-10, 64
buckets for 11-21 and so on.
According to the table, the number 4 is about where we achieve a good
enough standard deviation for the load (11.2%) while still not creating
too many hashes for cases with low number of backends. The standard
deviation also doesn't go down that much with higher coefficient.
-
上記の選択バランシングへの変更は、以下のバージョン以降で導入されています。今後は OVN-Kubernetes を実行する OpenShift のバージョンでのトラフィック分散が大幅に改善されます。
Openshift-SDN と iptables の概要
概要
OpenShift-SDN は、kube-proxy による iptables の選択処理を利用し、ClusterIP (Pod 間処理の内部デフォルトトラフィック) を使用してサービスによって選択されたバックエンドにトラフィックをルーティングします。iptables には、負荷分散ストラテジーはありませんが、負荷分散ストラテジーと同様の動作を実現できる一連のルールがあります。iptables は、リスト内の次の Pod を選択するために、統計的な選択ルールに基づいて、ランダムな選択を実質的に使用しています。
詳細
Openshift-SDN のサービスは、kube-proxy を利用して iptables と統合し、負荷分散に近いルールを作成します。サービスは、単なるリダイレクトルールであり、セレクター値によって指定されたバックエンドにリクエストをルーティングするポインターとしてのみ存在しています。
Kubernetes トラフィックの管理方法を適切に説明した記事 learnkube.com - Load balancing in Kubernetes Services を参照してください。
Does iptables use round-robin?
No, iptables is primarily used for firewalls, and it is not designed to do load balancing.
[However, you could craft a smart set of rules that could make iptables behave like a load balancer.](https://scalingo.com/blog/iptables#load-balancing)
And this is precisely what happens in Kubernetes.
If you have three Pods, kube-proxy writes the following rules:
select Pod 1 as the destination with a likelihood of 33%. Otherwise, move to the next rule
choose Pod 2 as the destination with a probability of 50%. Otherwise, move to the following rule
select Pod 3 as the destination (no probability)
The compound probability is that Pod 1, Pod 2 and Pod 3 have all have a one-third chance (33%) to be selected.
iptables rules for three Pods
Also, there's no guarantee that Pod 2 is selected after Pod 1 as the destination.
その結果、kube-proxy (openshift-sdn) を使用するサービスでは、実質的にランダムな選択方法でリクエストが処理されます。リクエストが直前の Pod の選択に基づいて重み付けされるためです。
この選択方法は変更できず、この選択ルールの変更はサポートされていないことに注意してください。よりきめ細かな制御や特定の選択処理方法を目的とする場合は、よりインテリジェントなソリューションを検討する必要があります。HAProxy、Nginx、サービスメッシュ。
Comments