Amazon Web Services ブログ

Amazon EKS が Amazon Application Recovery Controller のサポートを開始

この記事は Amazon EKS now supports Amazon Application Recovery Controller (記事公開日: 2024 年 11 月 8 日) を翻訳したものです。

はじめに

Amazon Elastic Kubernetes Service (Amazon EKS) が Amazon Application Recovery Controller (ARC) のサポートを開始しました。ARC は AWS リージョンまたはアベイラビリティゾーン (AZ) の障害に対する準備と復旧を可能にする AWS サービスです。

ARC には、ゾーンシフトとゾーンオートシフトを含むマルチ AZ リカバリと、ルーティングコントロールと準備状況チェックを含むマルチリージョンリカバリの 2 つの機能があります。今回のリリースにより、以前は Application Load Balancer (ALB) と Network Load Balancer (NLB) でのみ利用可能だったゾーンシフトとゾーンオートシフトが Amazon EKS をサポートしました。

ARC のゾーンシフトとゾーンオートシフトは、障害のある AZ から他の正常な AZ に ingress トラフィックをシフトすることで、サポートされている AWS リソースのマルチ AZ リカバリを実現します。シフトが終了すると、ARC は ingress トラフィックを再び受信できるように以前に影響を受けた AZ を戻します。

Amazon EKS コンソール、AWS コマンドラインインターフェイス (AWS CLI)AWS CloudFormation、または eksctl を使用して、EKS クラスターのゾーンシフトを有効にできます。有効にすると、ARC コンソール、AWS CLI、またはゾーンシフトとゾーンオートシフト API を使用して、EKS クラスターのゾーンシフトを開始したり、ゾーンオートシフトを有効にしたりできます。

EKS クラスターでゾーンシフトをトリガーするには、まず AZ を選択し、次に EKS クラスター (バージョン 1.28 以降) を選択し、ゾーンシフトを有効にする有効期限を指定します。すると、ARC はゾーンシフトを開始し、選択した AZ からトラフィックを切り離します。ARC は、有効期限が切れるか、ユーザーがキャンセルした場合にゾーンシフトを終了します。ゾーンシフトが終了すると、トラフィックは EKS クラスターに接続されているすべての正常な AZ に戻ります。

EKS クラスターのゾーンオートシフトを有効にすると、AZ が異常であることを ARC が検出したときに、AWS がユーザーに代わってトラフィックを切り離すことを許可することになります。ARC は内部テレメトリを使用して、AWS ネットワーク、Amazon Elastic Compute Cloud (Amazon EC2)Elastic Load Balancing (ELB)サービスなど、さまざまなソースからの重要なヘルスメトリクスを監視しています。ARC は、影響を受けた AZ が再び正常状態になったことがテレメトリで示されると、ゾーンオートシフトを終了します。これにより、EKS クラスターに接続されているすべての正常な AZ にトラフィックが返されます。

ARC ゾーンシフトとゾーンオートシフトを利用する理由

AWS グローバルクラウドインフラストラクチャは、各 AWS リージョンが完全に分離された複数の AZ で構成されているため、耐障害性とレジリエンスを提供します。このマルチ AZ アーキテクチャを活用することは、リージョンに高可用性アプリケーションを実装するために不可欠です。Amazon EKS では、複数の AZ にデプロイすることで可用性の高いアプリケーションを迅速に開発できますが、スケーラブルでパフォーマンスが高く、信頼性の高い方法で AZ の障害に対処するには、構築と保守に多大な労力を要するカスタムソリューションを実装する必要があります。

もう 1 つの課題は、シミュレーションが難しいことが多い AZ 障害シナリオのテストです。テストが不十分だと、環境内の AZ で異常が生じたとき、予期せぬワークロードの動作に陥る可能性があります。

ARC ゾーンシフトまたはゾーンオートシフトを用いると、障害のある AZ で実行されているクラスターワーカーノードと Pod を一時的に隔離し、クラスター内のネットワークトラフィックをそれらから自動的に切り離して、ワークロードの耐障害性と可用性を向上させることができます。

さらに、ゾーンシフトとゾーンオートシフト機能を使用することで、AZ 障害の計画と対応に伴うチームのオペレーションオーバーヘッドを削減できます。

仕組み

EKS クラスターを ARC リソースとして登録すると、ARC を使用してクラスターのゾーンシフトをトリガーしたり、もしくはクラスターのゾーンオートシフトを有効にしたりできます。ARC がゾーンシフトを実行すると、クラスターは次のような変更を受けます。

  • Kubernetes スケジューラ が異常な AZ のノードに新しい Pod をスケジュールできないように、影響を受けた AZ のノードは cordon (スケジュール対象外としてマーク) されます。マネージドノードグループ(MNG) を使用している場合、アベイラビリティゾーンの再調整は一時停止され、Auto Scaling グループ(ASG) が更新されて、新しい Amazon EKS のデータプレーンノードが正常な AZ でのみ起動されるようになります。Karpenter と Kubernetes の Cluster Autoscaler は、ARC ゾーンシフトとゾーンオートシフトをネイティブでサポートしていません。正常に動作している AZ のみに新しいノードをプロビジョニングするよう自動スケーリングツールを再構成する必要があります。新しいノードの起動に特定の AZ のみを使用するように KarpenterCluster Autoscaler を設定する方法については、Amazon EKS ベストプラクティスガイドを参照してください。
  • 異常な AZ のノードは終了されません。したがって、影響を受けた AZ の Pod は削除されません。これは、ゾーンシフトの期限が切れたりキャンセルされたときに、トラフィックがフルキャパシティーの状態の AZ に安全に戻るようにするためです。
  • EndpointSlice controller は、障害のある AZ 内のPod の Endpoint を検出し、それらを関連するEndpointSlice リソースから削除します。これにより、ネットワークトラフィックが正常な AZ の Pod の Endpoint のみを対象とすることが保証されます。Endpoint slice controller は、ゾーンシフトがキャンセルまたは期限切れになると、復元された AZ の Endpoint を含むように Endpoint slice を更新します。

次の図は、Amazon EKS 環境における AZ の異常が生じた場合の east-to-west (クラスター内部) のトラフィックフローを示しています。このようなシナリオでは、ネットワークパケットのドロップやネットワーク遅延が発生する可能性があります。

次の図は、障害のある AZ からトラフィックを切り離した場合の Amazon EKS 環境を示しています。

ゾーンシフトとゾーンオートシフトのための EKS クラスターとワークロードの準備

Amazon EKS でゾーンシフトとゾーンオートシフトが正常に動作するようにするには、事前に AZ 障害に強いクラスター環境を準備する必要があります。以下は、 EKS クラスターに実装する必要がある重要なステップのリストです。これらのステップについては、Amazon EKS のドキュメントで詳しく説明されています。

  • クラスター内のワーカーノードを複数の AZ に分散します。
  • 単一の AZ の削除に耐えられるだけの十分なコンピューティングキャパシティをプロビジョニングしてください。AZ 障害に耐えられるアプリケーションの構築方法の詳細については、静的安定性に関する AWS のドキュメントを参照してください。
  • すべての AZ で、Pod を事前にスケーリングしてください。これらの Pod には、アプリケーション Pod と、CoreDNS、Cluster Autoscaler、AWS Load Balancer Controller などのコントローラー Pod が含まれます。これを実現する方法の詳細については、Amazon EKS のドキュメントを参照してください。
  • Pod レプリカを複数の AZ をまたいで分散させて、単一の AZ を切り離しても十分な容量が残るようにします。これを実現するには、Topology spread constraints が役立ちます。
  • クラスターで実行されているコントローラーやその他のアプリケーションの高可用性 (HA) をサポートするためにリーダーの選出が必要な場合は、ポッドの数が奇数であるか、ポッドが 2 つ以上であるなどの基準が、AZ 障害イベント中および発生後に一貫して満たされていることを確認してください。
  • ロードバランサーを使用して外部トラフィックを Kubernetes の Service にルーティングする場合は、ALB と NLB のみを使用することをお勧めします。AWS Load Balancer Controller を使用してロードバランサーを管理することもお勧めします。AWS Load Balancer Controller はインスタンスと IP トラフィックモードをサポートしていますが、そのうちの IP モードが推奨されます。インスタンスと IP モードの詳細については、AWS Load Balancer Controller のドキュメントを参照してください。

Amazon EKS のゾーンシフトによってアプリケーションとクラスター環境が正常に回復するには、前述のステップが不可欠です。さらに、AZ 障害を効果的に管理するには、以下のベストプラクティスをお勧めします。

  • Topology Aware Routing などの Kubernetes 機能を使用するか、サービスメッシュと統合することで、Pod 間の通信を同じ AZ 内に限定します。
  • 同じ AZ 内に、相互に依存するアプリケーションとサービスを配置します。これは Pod Affinity rule で実現できます。
  • マルチ AZ オブザーバビリティを実装します。
  • アプリケーションでは、データベース、サービスなどの外部依存関係に対するタイムアウト値を適切に設定し、再試行を実装してください。障害を正常に処理するには、エクスポネンシャルバックオフパターンを備えたサーキットブレーカーを実装してください。

ゾーンシフトとゾーンオートシフトをサポートするようにクラスターとワークロードを準備する方法、およびゾーンシフトとゾーンオートシフトに関するその他のベストプラクティスの詳細については、Amazon EKS ドキュメントを参照してください。

さらに、ワークロードが AZ 障害を処理できることを定期的にテストして検証することを強くお勧めします。ゾーンシフトを手動でトリガーするか、ゾーンオートシフトを有効にして、クラスター環境の AZ を 1 つ減らしてワークロードが期待どおりに機能することを確認することで、AZ 障害をテストできます。

始めてみよう

ARC ゾーンシフト機能の説明に使用するサンプルアプリケーションを準備しました。このウォークスルーでは、既存の EKS クラスターを使用するか、新しいクラスターを作成できます。クラスターとそのクラスターに設定されているノードグループは、3 つの AZ にまたがり、各 AZ に少なくとも 1 つのノードが必要です。

1. サンプルアプリケーションをデプロイする

a. まず、EKS クラスターにサンプルアプリケーションをデプロイします。Kubernetes Secret を作成するときは、必ず有効なユーザー名とパスワードを指定してください。この Secret は、MySQL データベースとそれに接続するアプリケーションの両方で使用されます。

kubectl create secret generic catalog-db --from-literal=username=<<有効なユーザー名で置換>> --from-literal=password=<<有効なパスワードで置換>>
cat << EOF > catalog_deploy.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: catalog
data:
  DB_ENDPOINT: catalog-mysql-0.catalog-mysql:3306
  DB_READ_ENDPOINT: catalog-mysql-0.catalog-mysql:3306
  DB_NAME: catalog
---
apiVersion: v1
kind: Service
metadata:
  name: catalog-mysql
  labels:
    helm.sh/chart: catalog-0.0.1
    app.kubernetes.io/name: catalog
    app.kubernetes.io/instance: catalog
    app.kubernetes.io/component: mysql
spec:
  clusterIP: None
  ports:
    - port: 3306
      targetPort: mysql
      protocol: TCP
      name: mysql
  selector:
    app.kubernetes.io/name: catalog
    app.kubernetes.io/instance: catalog
    app.kubernetes.io/component: mysql
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: catalog
  labels:
    helm.sh/chart: catalog-0.0.1
    app.kubernetes.io/name: catalog
    app.kubernetes.io/instance: catalog
    app.kubernetes.io/component: service
    app.kuberneres.io/owner: retail-store-sample
    app.kubernetes.io/managed-by: Helm
---
apiVersion: v1
kind: Service
metadata:
  name: catalog
  labels:
    helm.sh/chart: catalog-0.0.1
    app.kubernetes.io/name: catalog
    app.kubernetes.io/instance: catalog
    app.kubernetes.io/component: service
    app.kuberneres.io/owner: retail-store-sample
    app.kubernetes.io/managed-by: Helm
spec:
  type: ClusterIP
  ports:
    - port: 80
      targetPort: http
      protocol: TCP
      name: http
  selector:
    app.kubernetes.io/name: catalog
    app.kubernetes.io/instance: catalog
    app.kubernetes.io/component: service
    app.kuberneres.io/owner: retail-store-sample
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: catalog
  labels:
    helm.sh/chart: catalog-0.0.1
    app.kubernetes.io/name: catalog
    app.kubernetes.io/instance: catalog
    app.kubernetes.io/component: service
    app.kuberneres.io/owner: retail-store-sample
    app.kubernetes.io/managed-by: Helm
spec:
  replicas: 3
  strategy:
    rollingUpdate:
      maxUnavailable: 1
    type: RollingUpdate
  selector:
    matchLabels:
      app.kubernetes.io/name: catalog
      app.kubernetes.io/instance: catalog
      app.kubernetes.io/component: service
      app.kuberneres.io/owner: retail-store-sample
  template:
    metadata:
      annotations:
        prometheus.io/path: /metrics
        prometheus.io/port: "8080"
        prometheus.io/scrape: "true"
      labels:
        app.kubernetes.io/name: catalog
        app.kubernetes.io/instance: catalog
        app.kubernetes.io/component: service
        app.kuberneres.io/owner: retail-store-sample
    spec:
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: ScheduleAnyway
          labelSelector:
            matchLabels:
              app.kubernetes.io/name: catalog
      serviceAccountName: catalog
      securityContext:
        fsGroup: 1000
      containers:
        - name: catalog
          env:
            - name: DB_USER
              valueFrom:
                secretKeyRef:
                  name: catalog-db
                  key: username
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: catalog-db
                  key: password
          envFrom:
            - configMapRef:
                name: catalog
          securityContext:
            capabilities:
              drop:
                - ALL
            readOnlyRootFilesystem: true
            runAsNonRoot: true
            runAsUser: 1000
          image: public.ecr.aws/aws-containers/retail-store-sample-catalog:0.8.1
          imagePullPolicy: IfNotPresent
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 30
            periodSeconds: 3
          resources:
            limits:
              memory: 256Mi
            requests:
              cpu: 128m
              memory: 256Mi
          volumeMounts:
            - mountPath: /tmp
              name: tmp-volume
      volumes:
        - name: tmp-volume
          emptyDir:
            medium: Memory
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: catalog-mysql
  labels:
    helm.sh/chart: catalog-0.0.1
    app.kubernetes.io/name: catalog
    app.kubernetes.io/instance: catalog
    app.kubernetes.io/component: mysql
    app.kubernetes.io/managed-by: Helm
spec:
  replicas: 3
  serviceName: catalog-mysql
  selector:
    matchLabels:
      app.kubernetes.io/name: catalog
      app.kubernetes.io/instance: catalog
      app.kubernetes.io/component: mysql
  template:
    metadata:
      labels:
        app.kubernetes.io/name: catalog
        app.kubernetes.io/instance: catalog
        app.kubernetes.io/component: mysql
    spec:
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: ScheduleAnyway
          labelSelector:
            matchLabels:
              app.kubernetes.io/name: catalog
              app.kubernetes.io/component: mysql
      containers:
        - name: mysql
          image: public.ecr.aws/docker/library/mysql:8.0
          imagePullPolicy: IfNotPresent
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: catalog-db
                  key: password
            - name: MYSQL_DATABASE
              value: catalog
            - name: MYSQL_USER
              valueFrom:
                secretKeyRef:
                  name: catalog-db
                  key: username
            - name: MYSQL_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: catalog-db
                  key: password
          volumeMounts:
            - name: data
              mountPath: /var/lib/mysql
          ports:
            - name: mysql
              containerPort: 3306
              protocol: TCP
      volumes:
        - name: data
          emptyDir: {}
---
EOF
kubectl apply -f catalog_deploy.yaml

b. Kubernetes マニフェストファイルをクラスターに適用すると、それぞれ catalog と catalog-mysql という名前の 2 つのアプリケーションが作成され、 catalog-mysql は MySQL データベースになります。次のステップに進む前に、Pod が実行状態であることを確認します (これには数分かかる場合があります)。

2. クラスターのゾーンシフトを有効にする

a. Amazon EKS コンソールを開いてクラスターを選択し、次の図に示すように、概要 (Overview)ゾーンシフト (Zonal Shift) セクションに移動します。

b. 管理 (Manage) を選択し、有効化 (Enabled) を選択し、変更を保存します。

3. アプリケーションを検証する

a) default Namespace で利用可能な Service を一覧表示します。

kubectl get svc 
NAME            TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
catalog         LoadBalancer   XX.XXX.XXX.XXX   <pending>     80:31932/TCP   41m
catalog-mysql   ClusterIP      None             <none>        3306/TCP       41m

b) catalog Service への kubectl port-forward をバックグラウンドモードで実行します。プロセスのプロセス ID を書き留めておきます。

kubectl port-forward svc/catalog 8090:80 > /dev/null &
[1] 42306

c) curl を使用して catalog Service を呼び出すと、以下に示すように、いくつかのアイテム ID を返すことを確認します。

curl -s localhost:8090/catalogue | jq -r '.[0,1].id'
510a0d7e-8e83-4193-b483-e27e09ddc34d
6d62d909-f957-430e-8689-b5129c0bb75e
# port-forward プロセスを終了 (42306)
kill -9 <<kubectl port-forward プロセスのプロセスID>>

4. クラスター・トポロジーを理解する

アプリケーションが正常に動作していることを確認できたので、ゾーンシフトを実行する準備が整いました。ただし、ゾーンシフトをトリガーする前に、クラスターのトポロジーを理解する必要があります。これには、Pod が稼働している AZ を特定することが含まれます。

a. リージョンの AZ ID を一覧表示します。この例では、リージョンは us-west-2 なので、us-west-2 の AZ ID を確認できます。

aws ec2 describe-availability-zones --query 'AvailabilityZones[*].[ZoneName, ZoneId]' --output text
us-west-2a      usw2-az2
us-west-2b      usw2-az1
us-west-2c      usw2-az3
us-west-2d      usw2-az4

b. 次のコマンドを使用して、クラスター内の各ノードとそれが動作している AZ を特定する必要があります。次のコマンドを入力すると、ノード名とノードが実行されている AZ のリストが出力されるはずです。この例では、3 つのノードが 3 つの AZ (us-west-2b、us-west-2b、us-west-2c) に分散しています。

kubectl get nodes -o=jsonpath='{range .items[*]}"{.metadata.name}"{"\t"}"{.metadata.labels.topology\.kubernetes\.io/zone}"{"\n"}{end}' | sort -k 1 > nodes-info.txt
cat nodes-info.txt
"ip-XXX-XXX-XXX-XXX.us-west-2.compute.internal"      "us-west-2a"
"ip-YYY-YYY-YYY-YYY.us-west-2.compute.internal"      "us-west-2b"
"ip-ZZZ-ZZZ-ZZZ-ZZZ.us-west-2.compute.internal"     "us-west-2c"

c. 次のコマンドを使用して、各 Pod が現在実行されているノードと AZ を特定する必要があります。コマンドを入力すると、Pod 名、AZ、および Pod が実行されているノードを示す出力が生成されます。この場合、3 つの AZ の 3 つのノードに分散されたカタログアプリケーションポッドがあります。

kubectl get pods -l "app.kubernetes.io/component"=service -o=jsonpath='{range .items[*]}"{.metadata.name}"{"\t"}"{.spec.nodeName}"{"\n"}{end}' | sort -k 2 > pods-info.txt
join -1 1 -2 2  nodes-info.txt pods-info.txt 
"ip-XXX-XXX-XXX-XXX.us-west-2.compute.internal" "us-west-2b" "catalog-74957c74ff-xxxxx"
"ip-YYY-YYY-YYY-YYY.us-west-2.compute.internal" "us-west-2c" "catalog-74957c74ff-yyyyy"
"ip-ZZZ-ZZZ-ZZZ-ZZZ.us-west-2.compute.internal" "us-west-2a" "catalog-74957c74ff-zzzzz"

5. ゾーンシフトをトリガーする

これで、クラスター・トポロジーを十分に理解できたはずです。次に、ゾーンシフトをトリガーしてトラフィックを AZ から切り離し、ゾーンシフト機能をテストします。

a. 次の図に示すように、ARC コンソールを開き、ゾーンレベルの移行 (Zonal Shift) を選択します。

b. 次の図に示すように、ゾーンシフトを開始するために、トラフィックを切り離す AZ (us-west-2b)、ゾーンシフトを実行する EKS クラスタ、有効期限 (10 分) を選択して、そして開始 (Start) を選択します。

ゾーンシフトは、トリガーしてから完了するまでに数分かかります。そのため、数分待ってからテストすることをお勧めします。

c. アプリケーションの Endpoint へのトラフィックを生成してアプリケーションを検証し、トラフィックを切り離した AZ で実行されている Pod に対して呼び出しが行われていないことを確認します。そのためには、まず Kubernetes Job を実行してアプリケーションへのトラフィックを生成し、次にトラフィックを処理する Pod とそれらが属する AZ をログから特定します。次のコマンドを入力すると、catalog Service へのトラフィックが 2 つの Pod に分散されていることがわかります。

kubectl create job curl-job --image=curlimages/curl -- /bin/sh -c "while true; do curl -s catalog.default/catalogue; sleep 1; done"
start_time=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# 20-30秒間待つ
kubectl logs -l "app.kubernetes.io/component"=service --prefix --since-time=$start_time --tail=50 | grep -i "/catalogue" | cut -d '/' -f 2 | sort | uniq -c > pod-logs.txt
cat pod-logs.txt
5 catalog-78679df9c4-xxxx
6 catalog-78679df9c4-zzzz

d. Pod の位置を確認すると、どの Pod も AZ us-west-2b (ゾーンシフトによってトラフィックが迂回された AZ) で稼働していないことがわかります。

join -1 1 -2 2  nodes-info.txt pods-info.txt | tr -d \" | sort -k 3  > pods-nodes-az.txt
join -1 3 -2 2  pods-nodes-az.txt pod-logs.txt
catalog-74957c74ff-xxxx ip-XXX-XXX-XXX-XXX.us-west-2.compute.internal us-west-2a 5
catalog-74957c74ff-zzzz ip-ZZZ-ZZZ-ZZZ-ZZZ.us-west-2.compute.internal us-west-2c 6

e. 先に進む前に、トラフィックを生成するために作成した Kubernetes Job を削除します。

kubectl delete job curl-job

6. ゾーンシフトをキャンセルする

a. 次の図に示すように、以前に作成したゾーンシフトを選択し、ゾーンシフトをキャンセル (Cancel zonal shift) を選択して、ゾーンシフトのキャンセルをテストします。

ゾーンシフトのキャンセルは、トリガーしてから完了するまでに数分かかります。そのため、数分待ってからテストすることをお勧めします。

b. アプリケーションへのトラフィックを生成し、AZ で動作している Pod がトラフィックを受信していることを確認できます。

kubectl create job curl-job --image=curlimages/curl -- /bin/sh -c "while true; do curl -s catalog.default/catalogue; sleep 1; done"
start_time=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# 20-30秒間待つ
kubectl logs -l "app.kubernetes.io/component"=service --prefix --since-time=$start_time --tail=50 | grep -i "/catalogue" | cut -d '/' -f 2 | sort | uniq -c > pod-logs.txt
cat pod-logs.txt
9 catalog-78679df9c4-xxxx
7 catalog-78679df9c4-yyyy
5 catalog-78679df9c4-zzzz
join -1 1 -2 2  nodes-info.txt pods-info.txt | tr -d \" | sort -k 3  > pods-nodes-az.txt                                           
join -1 3 -2 2  pods-nodes-az.txt pod-logs.txt
catalog-74957c74ff-xxxx ip-XXX-XXX-XXX-XXX.us-west-2.compute.internal us-west-2a 9
catalog-74957c74ff-yyyy ip-YYY-YYY-YYY-YYY.us-west-2.compute.internal us-west-2b 7
catalog-74957c74ff-zzzz ip-ZZZ-ZZZ-ZZZ-ZZZ.us-west-2.compute.internal us-west-2c 5
# kubernetes job を削除する
kubectl delete job curl-job

7. クラスターのゾーンオートシフトを設定します

a. ゾーンオートシフトを設定する前に、ARC が練習実行が成功のうちに完了したかどうかを検査するために用いる Amazon CloudWatch アラームを設定する必要があります。ARC ゾーンオートシフトの練習実行の詳細については、このドキュメントを参照してください。

b. 次の図に示すように、ARC コンソールを開き、ゾーンオートシフトを設定 (Configure zonal autoshift) を選択します。

c. ゾーンオートシフトの設定するリソース (Resource to configure) として EKS クラスターを選択し、ゾーンオートシフトのステータス (Zonal autoshift status) で有効化 (Enable) を選択し、CloudWatch アラーム ARN を入力して作成 (Create) を選択します。次の図に示すように、コンソールのオプションセクションはそのままにしておきます。

d. ARCは、練習実行の一環として、週に1回、ゾーンオートシフトを実施します。Amazon EventBridge との統合を用いて、ゾーンオートシフトと練習実行の通知を受け取ることができます。練習実行中に、ゾーンシフトの検証に使用したのと同じ検証手順をゾーンオートシフトに適用できます。

ゾーンシフトとオートシフトにより、AZ 障害からの迅速な回復と Amazon EKS ワークロードの信頼性の向上が可能になります。AZ 障害に対して真に回復力を発揮するには、ワークロードがゾーンシフトやゾーンオートシフト機能を使用するだけでなく、「クラスターとワークロードの準備」セクションで概説されているプラクティスを遵守して AZ 障害からの回復も行う必要があります。

後片付け

今後のコストを避けるため、この演習用に作成された EKS クラスターなどのリソースをすべて削除してください。次のコマンドは、ゾーンシフトをテストするために以前にインストールしたアプリケーションを削除します。

kubectl delete -f catalog_deploy.yaml
kubectl detelet secret catalog-db
rm nodes-info.txt pods-info.txt pod-logs.txt pods-nodes-az.txt

価格と提供リージョン

Amazon EKS の ARC ゾーンシフトおよびゾーンオートシフト機能の対応は、中国と GovCloud リージョンを除くすべての AWS リージョンで利用できます。EKS クラスターでゾーンシフトを有効にしてゾーンシフトをトリガーしても、追加のコストは発生しません。ただし、Pod やクラスターノードの事前スケーリングなど、ワークロードが AZ 障害を確実に処理できるようにするために、追加のコストがかかる場合があります。

まとめ

この投稿では、ARC ゾーンシフトおよびゾーンオートシフト機能を使用して、単一の AZ 障害から回復する方法を説明しました。入念な計画と実装を行うことで、ゾーンシフトとゾーンオートシフトの可能性を最大限に活用して、単一の AZ 障害から Amazon EKS クラスターで実行されているアプリケーションとデータソースを保護できます。

Amazon EKS のゾーンシフトとゾーンオートシフトの詳細については、Amazon EKS のドキュメントを参照してください。

GitHub でホストされている AWS Containers Roadmap にコメントを残したり、Issue を投稿したりすることで、EKS クラスターの ARC ゾーンシフト機能に関するフィードバックを提供できます。今後も機能を進化させ、ユーザーがクラスターの耐障害性と可用性を向上させるのに役立つさまざまな方法を模索していきますので、ご期待ください。

翻訳はシニアパートナーソリューションアーキテクトの市川が担当しました。原文はこちらです。