※ 本記事は、Shravan Sriram, Kalaiyarasan Pによる”Achieving high availability in an OKE cluster“を翻訳したものです。
2023年2月15日
Oracle Container Engine for Kubernetes(OKE)を使用する場合、障害が発生した場合でもシステムの稼働時間を確保するには高可用性が不可欠です。Kubernetesクラスタでは、ワーカー・ノードは、マルチ可用性ドメインのOracle Cloud Infrastructure(OCI)リージョンにある複数の可用性ドメイン、または単一の可用性ドメインと複数のフォルト・ドメインを持つOCIリージョン内の複数のフォルト・ドメインにわたって実行できます。高負荷を処理し、高可用性を実現するには、デプロイメントのレプリカを異なる可用性ドメインに分散することが重要です。
このブログの主な目的は、高可用性を実現するために、OKEクラスタ内のノード間でデプロイメントのポッドを分散するために使用できる様々なKubernetesメカニズムを説明することです。ノード・ラベル、アンチアフィニティ、TopologySpreadConstraintsを使用したポッド配布など、ブログで説明する概念は、一般的に多くのKubernetesシナリオに適用されます。このブログは次のような状況で役立ちます。:
-
マルチリージョン・デプロイメント: 複数のリージョンにまたがるデプロイメントがある場合は、高可用性を実現するために、各リージョン内の異なる可用性ドメインにレプリカを分散することが重要です。
-
ステートフル・アプリケーション: Kubernetesでステートフル・アプリケーションを実行する場合は、単一障害点を回避するために、レプリカが様々なアベイラビリティ・ドメインに分散されていることを確認します。
-
継続的な統合およびデプロイメント(CI/CD)パイプライン: Kubernetesクラスタにアプリケーションの新しいバージョンをデプロイする場合は、アプリケーションの新しいバージョンが様々な可用性ドメインに分散されていることを確認して、高可用性を保証し、障害のリスクを軽減します。
主な用語
-
可用性ドメイン: 可用性ドメインは、リージョン内のデータ・センターの論理グループです。一般的なクラウド・プロバイダのインフラでは、可用性ドメインは、冗長電力、冷却およびネットワーキング・リソースを備えた、物理的に離れた場所です。リージョン内の地理的に離れたロケーションです。
複数の可用性ドメインを持つクラスタを作成すると、ノードは可用性ドメイン全体に分散されます。そのため、1つの可用性ドメインが停止しても、残りの可用性ドメインでノードは引き続き使用できます。このようにして、クラスタはまだ実行中であり、サービスを提供しています。
-
ノード・ラベル: OKEでは、ワーカー・ノードは、クラスタ内でポッドを実行する仮想または物理マシンにできます。ラベルは、ノードなどのKubernetesオブジェクトに追加して、ユーザーにとって意味があり関連のある識別属性を指定できるキーと値のペアです。ノード・ラベルを使用して、ノードが属する可用性ドメイン、そのノードが属するマシンのタイプ、実行するオペレーティング・システムなど、ノードの様々な特性を識別できます。Kubernetesでは、標準ラベルのセットがすべてのノードに自動的に割り当てられ、これらのラベルにはノードが属する可用性ドメインに関する情報を含めることができます。
ノード・ラベルを使用した可用性ドメインの識別
可用性ドメインとノード・ラベルについて知ることは、異なる可用性ドメインにワークロードを分散し、サービスの高可用性を確保する場合に役立ちます。OKEクラスタ内のノードのラベルを検査する場合は、次のコード・ブロックを参照してください。:
oci@oci-mac % kubectl describe node 10.0.10.127
Name: 10.0.10.127
Roles: node
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/instance-type=VM.Standard.E3.Flex
beta.kubernetes.io/os=linux
displayName=oke-cxeqigstkia-ndhpxqaqgsa-srp6z4k7mva-0
failure-domain.beta.kubernetes.io/region=phx
failure-domain.beta.kubernetes.io/zone=PHX-AD-1
hostname=oke-cxeqigstkia-ndhpxqaqgsa-srp6z4k7mva-0
internal_addr=10.0.10.127
kubernetes.io/arch=amd64
kubernetes.io/hostname=10.0.10.127
kubernetes.io/os=linux
last-migration-failure=get_kubesvc_failure
name=dis_oke_drcc2.0_cluster
node-role.kubernetes.io/node=
node.info.ds_proxymux_client=true
node.info/kubeletVersion=v1.24
node.kubernetes.io/instance-type=VM.Standard.E3.Flex
oci.oraclecloud.com/fault-domain=FAULT-DOMAIN-1
oke.oraclecloud.com/node.info.private_subnet=false
oke.oraclecloud.com/node.info.private_worker=true
oke.oraclecloud.com/tenant_agent.version=1.47.5-ed7c19ae8e-916
topology.kubernetes.io/region=phx
topology.kubernetes.io/zone=PHX-AD-1
次の例を含め、複数のラベルを使用して可用性ドメインを一意に識別できます:
-
topology.kubernetes.io/zone=PHX-AD-1
-
failure-domain.beta.kubernetes.io/zone=PHX-AD-1
ユース・ケースでは、topology.kubernetes.io/zoneラベルを使用できます。
可用性ドメイン間でポッドを分散するためのメカニズム
アフィニティとアンチアフィニティ
アフィニティー機能には2つのタイプがあります。ノード・アフィニティはnodeSelectorフィールドのように機能しますが、表現性が高く、ソフト・ルールを指定できます。nodeSelectorと同様に、この単純なメソッドは、一連のラベルを使用してポッドを特定のノードに制約します。
ポッド間アフィニティおよびアンチアフィニティにより、ノード・ラベルではなく、そのノードですでに実行されているポッドのラベルに基づいてポッドをスケジュールできるノードを制限できます。これらのルールは、「XがルールYを満たす1つ以上のポッドをすでに実行している場合、このポッドはXで実行する必要があります(アンチアフィニティの場合は実行しないでください)」という形式をとります。ここで、Xはクラウド・プロバイダの可用性ドメインで、YはKubernetesが満たそうとするルールです。
ユース・ケースでは、後者の機能に重点を置いています。ポッド・アンチアフィニティ・ルールは、次の方法で設定できます:
-
必須のハード・ルール: ルールが満たされないかぎり、スケジューラはポッドをスケジュールできません。このルールは、requiredDuringSchedulingIgnoredDuringExecutionキーワードで識別されます。
- ソフト・ルール(提案など): スケジューラはルールを満たすノードを検索しようとします。一致するノードが見つからない場合、ポッドは使用可能な任意のノードでスケジュールされます。このルールは、preferredDuringSchedulingIgnoredDuringExecutionキーワードで識別されます。
ハード・アフィニティ・ルール
次のコード・ブロックに従ってハード・アフィニティ・ルールを定義して、異なる可用性ドメイン内のノード間でポッドを分散できます:
apiVersion: apps/v1
kind: Deployment
metadata:
name: adtest-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 4
template:
metadata:
labels:
app: nginx
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx
topologyKey: topology.kubernetes.io/zone
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
resources:
requests:
memory: "500Mi"
この構成では、topologyKeyは使用するノード・ラベルのキーです。制約を満たすために分散すると、labelSelectorに一致するポッドがカウントされ、グループとして認識されます。ラベル・セレクタを指定するか、ポッドを照合できません。
この構成でポッドの4つのレプリカをスケジュールしようとすると、3つのレプリカが別の可用性ドメインに属するノードでスケジュールされ、4番目のレプリカは保留状態のままになります。requiredDuringSchedulingIgnoredDuringExecutionで規定されているハード・ルールは、制約が満たされないかぎりレプリカをスケジュールせず、3つの可用性ドメインのみがオープンされ、各可用性ドメインにはすでにこのデプロイメントからのポッドがスケジュールされています。

このアプローチは、3つの可用性ドメインに分散するレプリカを最大3つ持つことができるデプロイメントを操作する場合に最適です。
ソフト・アフィニティ・ルール
可用性ドメイン間で3つ以上のポッドをスケジュールするには、次のソフト・ルールを使用します:
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx
topologyKey: topology.kubernetes.io/zone
weight: 100
重みには、preferredDuringSchedulingIgnoredDuringExecutionアフィニティ・タイプのインスタンスごとに1から100までの値を指定できます。スケジューラがポッドの他のすべてのスケジューリング要件を満たすノードを検出すると、スケジューラはノードが満たすすべての優先ルールを繰り返し処理し、その式の重みの値を合計に追加します。
この構成では、3つ以上のポッドをスケジュールできます。可用性ドメイン全体にポッドが分散しています。制約を満たせない場合、ポッドは使用可能な任意のノードでスケジュールされるため、ノード間でポッドが偏っている可能性があります。

TopologySpreadConstraints
クラスタが複数のアベイラビリティ・ドメインまたはリージョンにまたがる場合、ノード・ラベルをポッド・トポロジ分散制約と組み合せて使用し、フォルト・ドメイン、リージョン、アベイラビリティ・ドメイン、さらには特定のノード間でクラスタ全体にポッドを分散する方法を制御できます。これらのヒントを使用すると、スケジューラでポッドを配置して可用性を高め、相関する障害がワークロード全体に影響するリスクを減らすことができます。どのポッドをグループ化するか、どのトポロジ・ドメインに分散するか、許容可能な偏りを指定します。制約のために分散すると、同じネームスペース内のポッドのみが一致し、グループ化されます。
複数のトポロジ分散制約を指定できますが、互いに競合しないようにできます。
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: nginx
maxSkewという用語は、ポッドを均等に分散できる程度を示します。0より大きい数値でこのフィールドを指定します。そのセマンティクスは、whenUnsatisfiable.whenUnsatisfiableの値に応じて異なり、ポッドが分散制約を満たさない場合の処理方法を指定します。
DoNotScheduleの状態がデフォルトです。設定すると、maxSkewによって、ターゲット・トポロジの一致するポッドの数とグローバル最小値(適格なドメインの一致するポッドの最小数、または適格なドメインの数がMinDomains未満の場合はゼロ)との許容される最大差異が定義されます。たとえば、2つ、2つおよび1つの一致するポッドを持つ3つの可用性ドメインがある場合、MaxSkewは1に設定され、グローバル最小は1になります。
ScheduleAnywayは、偏りの低減に役立つトポロジに対して、スケジューラにより高い優先度を与えます。

まとめ
システムの稼働時間を確保し、高負荷を処理するには、OKEクラスタで高可用性を実現することが重要です。可用性ドメイン、ノード・ラベル、アンチアフィニティおよびTopologySpreadConstraintsの概念を理解することで、OKEクラスタ内の異なる可用性ドメインまたはフォルト・ドメインにデプロイメントのポッドを分散できます。この機能は、マルチリージョン・デプロイメント、ステートフル・アプリケーションおよびCI/CDパイプラインに特に役立ちます。この知識により、単一障害点のリスクを最小限に抑え、OKEクラスタの全体的な信頼性を向上させることができます。
