アンマネージドモードでの CoreDNS の停止を防ぐために、Pod 数、リソース、スケジューリング、およびノードの隔離を設定します。
アンマネージドモードでは、CoreDNS の可用性とパフォーマンスは、Pod 数、リソース制限、スケジューリング、およびノード分散に依存します。デフォルト設定は小規模なクラスターに適していますが、本番ワークロードではチューニングが必要です。
潜在的リスク
CoreDNS の設定ミスやリソース不足は、以下の 2 種類の問題を引き起こします:
-
可用性:スケジューリングが不適切な場合、ノードレベルまたはゾーンレベルで単一障害点が発生します。リソースが不足すると、Pod のエビクションや DNS の停止が発生します。
-
パフォーマンス:共有ノードでのリソースの競合は、レスポンスレイテンシーを増加させます。ノードの負荷が高いと、I/O パケット損失や DNS リクエストの失敗が発生します。
CoreDNS Pod 数の調整
UDP には再送メカニズムがないため、CoreDNS のスケールインや再起動を行うと (特に IPVS の不具合によってパケット損失が発生する場合)、クラスター全体で最大 5 分間の DNS 名前解決のタイムアウトや失敗が発生する可能性があります。詳細については、「DNS 名前解決の問題のトラブルシューティング」をご参照ください。
CoreDNS には Horizontal Pod Autoscaling (HPA) や CronHPA を使用しないでください。頻繁なスケールインは、名前解決の失敗を引き起こします。
DNS 負荷の評価
レプリカ数を調整する前に、DNS 負荷を評価します。DNSPerf などのツールを使用して、DNS 負荷を測定できます。
DNS 負荷を直接測定できない場合は、以下のガイドラインに従ってください:
-
少なくとも 2 つの CoreDNS Pod を実行し、リソース制限を 1 コア、1 GB メモリ以上に設定してください。
-
DNS 名前解決の 1 秒あたりのクエリ数 (QPS) は、CPU 使用量に比例して増加します。NodeLocal DNSCache を使用すると、各 CPU コアは 1 秒あたり 10,000 を超えるクエリ数 (QPS) を処理できます。ワークロードによって QPS の要件は大きく異なるため、各 CoreDNS Pod のピーク時の CPU 使用量を監視してください。いずれかの Pod がピーク時に 1 コアを超えた場合は、レプリカをスケールアウトしてください。
-
負荷データがない場合は、ベースラインとしてノード 8 台あたり 1 Pod から開始してください。
スケールアウトが有効なのは、ノードに十分なリソースがある場合のみです。ノードのメモリが不足している場合は、代わりにノードを追加するか、ノードごとのリソースを増やしてください。
目標のレプリカ数が決まったら、自動調整 (推奨) を使用するか、手動でスケーリングしてください。
自動調整の設定 (推奨)
cluster-proportional-autoscaler は、クラスターのサイズに基づいて CoreDNS のレプリカを調整します。HPA とは異なり、CPU メトリクスに依存したり、中断を伴うスケールインを実行したりすることはありません。デフォルトの比率:ノード 8 台あたり 1 Pod。
レプリカ数の計算式: replicas = max(ceil(cores × 1/coresPerReplica), ceil(nodes × 1/nodesPerReplica))。min および max パラメーターは、カウントを 2~100 に制限します。
オートスケーラーをデプロイします:
apiVersion: apps/v1
kind: Deployment
metadata:
name: dns-autoscaler
namespace: kube-system
labels:
k8s-app: dns-autoscaler
spec:
selector:
matchLabels:
k8s-app: dns-autoscaler
template:
metadata:
labels:
k8s-app: dns-autoscaler
spec:
serviceAccountName: admin
containers:
- name: autoscaler
image: registry.cn-hangzhou.aliyuncs.com/acs/cluster-proportional-autoscaler:1.8.4
resources:
requests:
cpu: "200m"
memory: "150Mi"
command:
- /cluster-proportional-autoscaler
- --namespace=kube-system
- --configmap=dns-autoscaler
- --nodelabels=type!=virtual-kubelet
- --target=Deployment/coredns
- --default-params={"linear":{"coresPerReplica":64,"nodesPerReplica":8,"min":2,"max":100,"preventSinglePointFailure":true}}
- --logtostderr=true
- --v=9
手動でのスケーリング
特定のレプリカ数を設定するには:
kubectl scale --replicas=<target> deployment/coredns -n kube-system # <target> を Pod の目標数に置き換えます。
CoreDNS Pod 仕様の調整
ACK Pro マネージドクラスターでは、デフォルトの CoreDNS Pod 設定は次のとおりです:
| リソース | デフォルトの制限 |
|---|---|
| CPU | 制限なし |
| メモリ | 2 GiB |
観測されたピーク使用量に基づいて、CPU 制限を 4096 m (最小 1024 m) に設定してください。
CoreDNS Pod の仕様を変更すると Pod が再起動し、DNS レイテンシーの一時的な急増や失敗が発生する可能性があります。この操作はオフピーク時に実行してください。
-
ACK コンソールにログインします。左側メニューで、[クラスター] をクリックします。
-
[クラスター] ページで、対象のクラスター名をクリックします。左側メニューで、[アドオン] をクリックします。
-
[ネットワーク] タブで [CoreDNS] を見つけて、[設定] をクリックします。
-
CoreDNS の設定を変更して、[OK] をクリックします。
[CoreDNS パラメーター設定] ダイアログボックスで、次のパラメーターを設定します:
-
[MemoryRequest]:メモリリクエスト。例:
100 Mi。 -
[CpuRequest]:CPU リクエスト。例:
100 m。 -
[MemoryLimit]:メモリ制限。例:
2 Gi。メモリ制限が低すぎると、Pod が OOMKilled される可能性があります。 -
[CpuLimit]:CPU 制限。CpuRequest の値の 2 倍に設定することを推奨します。
-
[NodeSelector]:ノードセレクターのラベル。例:キーを
kubernetes.io/osに、値をlinuxに設定します。
-
専用ノードプールへのデプロイ
専用ノードプールは、CoreDNS を他のワークロードから隔離し、リソースの競合を防ぎます。
CoreDNS Pod を再スケジューリングすると Pod が再起動し、DNS レイテンシーの一時的な急増や失敗が発生する可能性があります。この操作はオフピーク時に実行してください。
専用ノードプールの作成
ノードプールを作成する際は、以下のガイドラインに従ってください:
-
CoreDNS はコンピューティング集約型ではなく、ネットワーク集約型です。推奨サイズが 4 コア、8 GB メモリのネットワーク強化型インスタンスを使用してください。
-
CoreDNS はデフォルトで 2 つの Pod を実行するため、ノードプールには少なくとも 2 つのノードが必要です。
-
他のポッドがこれらのノードで実行されないように、テイントとラベルを追加します。たとえば、テイントのキーと値のペアとラベルの両方として
system-addon: system-addonを使用し、EffectをNoScheduleに設定します。
詳細については、「ノードプールの作成と管理」をご参照ください。
CoreDNS Pod のノードプールへのスケジューリング
-
[アドオン] ページで [CoreDNS] カードを見つけて、[設定] をクリックします。
-
[NodeSelector] セクションで、専用ノードプールのラベルを追加します。
既存の NodeSelector ラベルは削除しないでください。
-
[Tolerations] セクションで、ノードプールの Taint に一致する Toleration を追加します。
[Tolerations] に Toleration エントリを追加します: [effect] を
NoScheduleに、[key] をsystem-addonに、[operator] をEqualに、[value] をsystem-addonに設定します。 -
[OK] をクリックして、CoreDNS Pod が専用ノードで実行されていることを確認します:
kubectl -n kube-system get pod -o wide --show-labels | grep coredns
高可用性のためのスケジューリングポリシーの使用
DNS の可用性を保護するため、CoreDNS はデフォルトで 2 つのスケジューリングポリシーを使用します:
-
Pod アンチアフィニティ (ノードレベル):2 つの CoreDNS Pod が同じノードで実行されないようにします。あるノードで障害が発生しても、他のノードで DNS は利用可能なままです。
-
トポロジーを意識したスケジューリング (ゾーンレベル):CoreDNS Pod を複数のアベイラビリティーゾーンに分散させ、Pod アンチアフィニティだけでは対処できないゾーンレベルの単一障害点を防ぎます。
これらのポリシーは、初期スケジューリング中にのみ適用されます。ノードまたはゾーンの設定が変更された場合は、ACK コンソールで coredns デプロイメントを見つけ、[再デプロイ] をクリックします。
Pod アンチアフィニティ
CoreDNS は、requiredDuringSchedulingIgnoredDuringExecution アンチアフィニティルールを使用して、2 つの CoreDNS ポッドがノードを共有しないようにします。これには、以下を除き、十分なリソースを持つノードが少なくとも 2 つ必要です。
-
k8s.aliyun.com: true— ノードの自動スケーリングが有効になっているノード (優先度低下) -
type: virtual-kubelet— 仮想ノード (除外) -
alibabacloud.com/lingjun-worker: true— Lingjun ノード (除外)
デフォルトのアフィニティ設定は次のとおりです:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
# 仮想ノードにはこのラベルがあります
- key: type
operator: NotIn
values:
- virtual-kubelet
# lingjun ワーカーノードにはこのラベルがあります
- key: alibabacloud.com/lingjun-worker
operator: NotIn
values:
- "true"
preferredDuringSchedulingIgnoredDuringExecution:
- preference:
matchExpressions:
# 自動スケーリングされたノードにはこのラベルがあります
- key: k8s.aliyun.com
operator: NotIn
values:
- "true"
weight: 100
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: k8s-app
operator: In
values:
- kube-dns
topologyKey: kubernetes.io/hostname
トポロジーを意識したスケジューリング
デフォルトでは、CoreDNS は トポロジー対応スケジューリングを使用して、ポッドをゾーン間に分散させます。 whenUnsatisfiable: DoNotSchedule 設定はこれを強制します。この設定により、ゾーンバランス条件が満たされない場合、ポッドはスケジューリングされません。
これを確実に機能させるには:
-
クラスターには、少なくとも 2 つの異なるアベイラビリティーゾーンにノードが必要で、各アベイラビリティーゾーンには CoreDNS 用の十分なリソースを持つノードが少なくとも 1 つ必要です。
-
すべてのノードには
topology.kubernetes.io/zoneラベルが付いている必要があります (デフォルトで適用されます)。ラベルがないか、一貫性がない場合、スケジューリングの失敗や不均一な分散が発生します。 -
クラスターを v1.27 以降に、CoreDNS を v1.12.1.3 以降にアップグレードしてください。以前のクラスターバージョンは matchLabelKeys をサポートしていないため、CoreDNS のローリングアップデートを行うと、Pod がゾーン間で不均等に分散されたり、一部のゾーンがカバーされないままになったりする可能性があります。以下で説明する
matchLabelKeysの設定をご参照ください。
v1.12.1.3 より前のバージョンの CoreDNS は、次のトポロジースプレッド制約を使用します:
topologySpreadConstraints:
- labelSelector:
matchLabels:
k8s-app: kube-dns
maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
任意の 2 つのゾーン間のポッド数の差は、 maxSkew (デフォルトは 1) を超えることはできません。
labelSelector は新旧両方の ReplicaSet のポッドをカウントするため、 maxSkew=1 を満たすように、スケジューラは合計ポッド数が少ないゾーンを優先します。 古いポッドが終了すると、新しいポッドが一部のゾーンに集中する可能性があります。
CoreDNS v1.12.1.3 以降では、matchLabelKeys (Kubernetes v1.27 以降) を使用してこの問題を修正しています:
topologySpreadConstraints:
- labelSelector:
matchLabels:
k8s-app: kube-dns
matchLabelKeys:
- pod-template-hash
nodeTaintsPolicy: Honor
maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
matchLabelKeys: [pod-template-hash] を追加すると、制約が現在の ReplicaSet に限定されるため、ローリングアップデートによってポッドがゾーン全体に均等に分散されます。