StatefulSet をデプロイしてディスクボリュームをマウントする際に、アベイラビリティゾーンの構成ミスや互換性のないディスクタイプなどの問題により、アプリケーションの起動に失敗することがあります。このトピックでは、これらのインフラストラクチャの問題を防ぎ、リリースの 中断を最小限に抑えるための、マルチアベイラビリティゾーンデプロイメントの推奨構成について説明します。
背景情報
Kubernetes の強力なコンテナオーケストレーション機能により、大規模なステートフルアプリケーション (StatefulSet) の構築が容易になります。しかし、Kubernetes はデプロイメントを簡素化する一方で、基盤となるハードウェアを抽象化します。この抽象化は、基盤となるインフラストラクチャのトポロジーや制限に精通していない場合、予期しない動作を引き起こす可能性があります。
-
複数のアベイラビリティゾーンにまたがるクラスターで、アベイラビリティゾーン A を対象とする Pod がアベイラビリティゾーン B のノードにスケジュールされます。
-
ディスクボリュームの作成時にエラーが発生します。たとえば、動的 PV のプロビジョニングに失敗し、InvalidDataDiskCatagory.NotSupported エラーが発生するなどです。
-
Pod がボリュームのマウントに失敗し、
The instanceType of the specified instance does not support this disk categoryというエラーが返されます。 -
Pod のスケジューリングに失敗し、
0/x node are available, x nodes had volume node affinity conflictというエラーが返されます。
これらの問題は、アプリケーションのリリースを中断またはブロックする可能性があります。このトピックでは、これらの障害のリスクを低減するための高可用性の推奨構成について説明します。
構成
構成の目標
-
StatefulSet では、永続ストレージとしてディスクを使用することを推奨します。NAS と比較して、ディスクはより高い安定性と優れたデータ転送帯域幅を提供します。
-
クラスターが複数のアベイラビリティゾーンにまたがり、需要を満たすのに十分なコンピューティングリソースとストレージリソースがあることを確認します。
-
アベイラビリティゾーン全体が利用できなくなった場合、クラスターは自動的にノードをスケールアウトして、スケジューリングの需要を満たすことができます。
-
高可用性の StorageClass を使用して、ディスクのマウント失敗を防ぎます。
-
Pod がノードとアベイラビリティゾーンに均等に分散されるようにします。
ノードプールの構成
-
各ノードプールに単一のアベイラビリティゾーンを使用します。
-
アベイラビリティゾーンを追加する際は、そのための新しいノードプールを作成します。詳細については、「ノードプールの作成と管理」をご参照ください。
-
ノードプールを作成する際は、各ノードプールが異なるアベイラビリティゾーンにマッピングされるようにします。ノードプール名を使用して、アベイラビリティゾーンを区別します。
-
-
ノードプールで auto scaling を有効にします。詳細については、「ノードの auto scaling の有効化」をご参照ください。
アベイラビリティゾーンに利用可能なノードがない場合、システムは自動的にそのゾーンに新しいノードを作成して Pod をスケジュールします。次のログにその様子が示されています。
Warning FailedScheduling 3m26s xxx 0/2 nodes are available: 2 node(s) had volume node affinity conflict. Warning FailedScheduling 3m26s xxx 0/2 nodes are available: 2 node(s) had volume node affinity conflict. Normal Scheduled 14s xxx Successfully assigned default/web-csi-available-test4-1 to cn-wulanchabu.172.xxx Warning FailedScheduling 86s xxx 0/3 nodes are available: 1 node(s) had taint {node.kubernetes.io/not-ready: }, that the pod didn't tolerate, 2 node(s) had volume node affinity conflict. Warning FailedScheduling 76s xxx 0/3 nodes are available: 1 node(s) had taint {node.kubernetes.io/not-ready: }, that the pod didn't tolerate, 2 node(s) had volume node affinity conflict. Warning FailedScheduling 25s xxx 0/3 nodes are available: 3 node(s) had volume node affinity conflict. Normal TriggeredScaleUp 3m8s cluster-autoscaler pod triggered scale-up: [xxx 0->1 (max: 10)}] Normal NotTriggerScaleUp 2m39s cluster-autoscaler pod didn't trigger scale-up (it wouldn't fit if a new node is added): 1 can't increase node group size Normal TriggeredScaleUp 37s cluster-autoscaler pod triggered scale-up: [{xxx 1->2 (max: 10)}] Normal SuccessfulAttachVolume 15s attachdetach-controller AttachVolume.Attach succeeded for i3uqre" Warning FailedMount 9s (x3 over 11s) kubelet MountVolume.MountDevice failed for volume "xxx" : rpc error: code = Aborted desc = NodeStageVolume: Attach volume: d-xxx with error: rpc error: code = Aborted desc = NodeStageVolume: Previous attach action is still in process: d xxx Normal Pulling 3s kubelet Pulling image "nginx" -
すべてのアベイラビリティゾーンで同じ ECS インスタンスタイプを使用します。これが不可能な場合は、すべてが同じブロックストレージカテゴリをサポートするインスタンスタイプを使用してください。
一部のディスクタイプは、特定の ECS インスタンスタイプにマウントできません。Pod が正しいアベイラビリティゾーン内にスケジュールされたとしても、ノードがリクエストされたディスクタイプをサポートしていない場合、ディスクのマウントエラーにより起動に失敗する可能性があります。
-
すべてのノードプールに Taint を構成して、意図しないワークロードがこれらのノードにスケジュールされ、アプリケーションに影響を与えるのを防ぎます。ノードプールを作成する際、[Taints] セクションでそのノードの Taint を構成できます。たとえば、キーを
app、値をsts、効果を NoSchedule に設定します。これにより、一致する Toleration を持たない Pod がこのノードプールのノードにスケジュールされるのを防ぎます。
クラスターの構成
-
クラスターのバージョンが 1.20 以降であることを確認します。
-
CSI プラグインのバージョンが 1.22 以降であることを確認してください。詳細については、「CSI プラグインを管理する」をご参照ください。
-
高可用性の StorageClass を使用します。
次の例は YAML 構成を示しています:
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: alicloud-disk-topology-alltype parameters: type: cloud_essd,cloud_ssd,cloud_efficiency provisioner: diskplugin.csi.alibabacloud.com reclaimPolicy: Delete volumeBindingMode: WaitForFirstConsumer allowVolumeExpansion: true allowedTopologies: - matchLabelExpressions: - key: topology.diskplugin.csi.alibabacloud.com/zone values: - cn-beijing-a - cn-beijing-b主要なパラメーター:
-
type: cloud_essd,cloud_ssd,cloud_efficiency:フォールバックメカニズムのために、ディスクタイプの優先順位リストを指定します。CSI プラグインは、指定されたタイプを ESSD、標準 SSD、Ultra ディスクの順に試行してディスクを作成しようとします。このアプローチにより、特定のタイプのディスク在庫が不足することによる Pod の起動失敗を防ぎます。 -
volumeBindingMode: WaitForFirstConsumer:Pod が特定のノードにスケジュールされるまでディスクの作成を遅延させます。これにより、ディスクがノードと同じアベイラビリティゾーンに作成されることが保証され、ゾーンの不一致による Pod の起動失敗を防ぎます。 -
allowedTopologies:ボリュームのプロビジョニングを特定のアベイラビリティゾーンに制限します。volumeBindingModeがWaitForFirstConsumerに設定されている場合、スケジューラは Pod を指定されたアベイラビリティゾーンのいずれかに配置し、ディスクが正常にプロビジョニングされることを保証します。
-
アプリケーションの構成
次のテンプレートは、標準的な StatefulSet の構成を示しています。必要に応じてカスタマイズできます。
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: "mysql"
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
topologySpreadConstraints:
- labelSelector:
matchLabels:
app: mysql
maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
containers:
- image: mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "mysql"
volumeMounts:
- name: disk-csi
mountPath: /var/lib/mysql
tolerations:
- key: "app"
operator: "Exists"
effect: "NoSchedule"
volumeClaimTemplates:
- metadata:
name: disk-csi
spec:
accessModes: [ "ReadWriteMany" ]
storageClassName: alicloud-disk-topology-alltype
resources:
requests:
storage: 40Gi
主要なパラメーター:
-
topologySpreadConstraints: Pod を異なる可用性ゾーンに可能な限り均等に分散配置します。詳細については、「トポロジー分散制約」をご参照ください。 -
volumeClaimTemplates:レプリカ数に基づいて必要な数のディスクを自動的に作成し、スケーリングを簡素化します。
PV が動的にプロビジョニングされると、その YAML 定義にはノードのアベイラビリティゾーンが含まれます。その結果、PV とそれにバインドされた PVC は、同じアベイラビリティゾーンにスケジュールされた Pod によってのみ使用でき、マウントが正常に行われることが保証されます。
参考資料
-
ディスクボリュームのデータセキュリティを向上させるには、「ディスクボリュームのデータセキュリティのベストプラクティス」をご参照ください。
-
ディスク使用率をリアルタイムでモニターするには、「コンテナストレージモニタリングの概要」をご参照ください。
-
ディスクがいっぱいになった場合や、サイズを増やす必要がある場合は、「ディスク ボリュームを拡張する」をご参照ください。
-
その他のディスクマウントの問題については、ディスクボリュームに関するよくある質問をご参照ください。