Amazon EKSでロードバランサーの失敗した健康チェックを解決するにはどうすればよいですか?

最終更新日: 2021 年 12 月 13 日

ロードバランサーが Amazon Elastic Kubernetes サービス (Amazon EKS) の健康チェックに失敗し続ける。

簡単な説明

Amazon EKS のロードバランサーに関する健康チェックの問題をトラブルシューティングするには、以下のセクションの処置を完了します:

  • ポットのステータスをチェックしてください
  • ポットとサービスラベルセレクターを確認してください
  • 不明なエンドポイントがないか確認してください
  • アプリケーションロードバランサー のサービストラフィックポリシーとクラスターセキュリティグループを確認してください
  • EKS が targetPort 用に設定されていることを確認してください。
  • AWS ロードバランサーコントローラーに正しい権限があることを確認してください。
  • アプリケーションロードバランサーに関する問題がないか、Ingress アノテーションをチェックしてください。
  • Kubernetes Service アノテーションでネットワークロードバランサーに関する問題を確認してください
  • 健康チェックを手動で確かめてください
  • ネットワークを確認してください
  • kube-proxy を再起動します。

解決方法

ポットのステータスをチェックしてください

ポットが Running ステータスで、ポット 内のコンテナが準備完了であることを確認してください。

$ kubectl get pod -n YOUR_NAMESPACE

注: YOUR_NAMESPACE を自分の名前空間に置き換えてください。

出力例:

NAME                           READY   STATUS    RESTARTS   AGE
podname                        1/1     Running   0          16s

注:ポット 内のアプリケーションコンテナが実行されていない場合、ロードバランサーの健康チェックは応答されず、失敗します。

ポットとサービスラベルセレクターを確認してください

ポットラベルの場合は、以下のコマンドを実行してください:

$ kubectl get pod -n YOUR_NAMESPACE --show-labels

出力例:

NAME                           READY   STATUS    RESTARTS   AGE     LABELS
alb-instance-6cc5cd9b9-prnxw   1/1     Running   0          2d19h   app=alb-instance,pod-template-hash=6cc5cd9b9

Kubernetes Service が ポットラベルを使用していることを確認するには、次のコマンドを実行して、その出力が ポット ラベルと一致することを確認します。

$ kubectl get svc SERVICE_NAME -n YOUR_NAMESPACE -o=jsonpath='{.spec.selector}{"\n"}'

注:SERVICE_NAME を Kubernetes サービスに置き換え、 YOUR_NAMESPACE を Kubernetes 名前空間に置き換えてください。

出力例:

{"app":"alb-instance"}

不明なエンドポイントがないか確認してください

サービスセレクターの Kubernetes コントローラーは、そのセレクターに一致する ポットを継続的にスキャンし、エンドポイントオブジェクトに更新をポストします。間違ったラベルを選択した場合、エンドポイントは表示されません。

次のコマンドを実行してください。

$ kubectl describe svc SERVICE_NAME -n YOUR_NAMESPACE

出力例:

Name:                     alb-instance
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=alb-instance-1      
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.100.44.151
IPs:                      10.100.44.151
Port:                     http  80/TCP
TargetPort:               80/TCP
NodePort:                 http  32663/TCP
Endpoints:                <none>                 
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

エンドポイントが欠落していないか確認します。

$ kubectl get endpoints SERVICE_NAME -n YOUR_NAMESPACE

出力例:

NAME           ENDPOINTS                                AGE
alb-instance   <none>                                   2d20h

サービストラフィックポリシーとクラスターセキュリティグループで、アプリケーションロードバランサーの問題がないか確認します。

アプリケーションロードバランサーのターゲットグループ内の異常なターゲットは、2 つの理由で発生します。サービストラフィックポリシー spec.externalTrafficPolicy が、クラスターではなくローカルに設定されています。または、クラスター内のノードグループには異なるクラスターセキュリティグループが関連付けられており、ノードグループ間でトラフィックが自由に流れることができない。

トラフィックポリシーが正しく設定されていることを確認してください。

$ kubectl get svc SERVICE_NAME -n YOUR_NAMESPACE -o=jsonpath='{.spec.externalTrafficPolicy}{"\n"}'

出力例:

Local

設定を [クラスタ] に変更します

$ kubectl edit svc SERVICE_NAME -n YOUR_NAMESPACE

クラスターセキュリティグループを確認する

1.    Amazon EC2 コンソールを開きます。

2.    正常なインスタンスを選択します

3.    [Security] タブを選択し、セキュリティグループの進入ルールを確認します。

4.    異常のあるインスタンスを選択します

5.    [Security] タブを選択し、セキュリティグループの進入ルールを確認します。

各インスタンスのセキュリティグループが異なる場合は、セキュリティグループコンソールでセキュリティイングレスルールを変更する必要があります。

1.    [Security] タブで、セキュリティグループ ID を選択します。

2.    イングレスルールを変更するには、 [インバウンドルールの編集] ボタンを選択します。

3.    インバウンドルールを追加して、クラスター内の他のノードグループからのトラフィックを許可します。

サービスが TargetPort 用に設定されていることを確認してください。

targetPort は、サービスがトラフィックを送信しているポットの containerPort と一致する必要があります。

targetPort はどんな設定にしたかを確認するには、以下のコマンドを実行してください:

$ kubectl get svc  SERVICE_NAME -n YOUR_NAMESPACE -o=jsonpath="{.items[*]}{.metadata.name}{'\t'}{.spec.ports[].targetPort}{'\t'}{.spec.ports[].protocol}{'\n'}"

出力例:

alb-instance 8080 TCP

上記の出力例では、 targetPort が 8080 に設定されています。ただし、 containerPort が 80 に設定されているため、 targetPort を 80 に設定する必要があります。

AWS ロードバランサーコントローラーに正しい権限があることを確認してください。

AWS Load Balancer Controller には、ロードバランサーからインスタンスまたはポッドへのトラフィックを許可するために、セキュリティグループを更新するための適切なアクセス権限が必要です。コントローラに適切な許可がない場合、エラーが表示されます。

AWS ロードバランサーコントローラーのデプロイログにエラーがないか確認してください。

$ kubectl logs deploy/aws-load-balancer-controller -n kube-system

個々のコントローラー ポットログにエラーがないか確認してください:

$ kubectl logs CONTROLLER_POD_NAME -n YOUR_NAMESPACE

注:CONTROLLER_POD_NAME はコントローラーのポッド名に YOUR_NAMESPACE は Kubernetes 名前空間に置き換えます

アプリケーションロードバランサーに関する問題がないか、Ingress アノテーションをチェックしてください。

アプリケーションロードバランサーに関する問題については、Kubernetes ingress アノテーションを確認してください:

$ kubectl describe ing INGRESS_NAME -n YOUR_NAMESPACE

注:INGRESS_NAME は Kubernetes Ingress の名前に置き換え、 YOUR_NAMESPACE は Kubernetes 名前空間に置き換えます。

出力例:

Name:             alb-instance-ingress
Namespace:        default
Address:          k8s-default-albinsta-fcb010af73-2014729787.ap-southeast-2.elb.amazonaws.com
Default backend:  alb-instance:80 (192.168.81.137:8080)
Rules:
  Host          Path  Backends
  ----          ----  --------
  awssite.cyou
                /   alb-instance:80 (192.168.81.137:8080)
Annotations:    alb.ingress.kubernetes.io/scheme: internet-facing        
                kubernetes.io/ingress.class: alb                         
Events:
  Type    Reason                  Age                  From     Message
  ----    ------                  ----                 ----     -------
  Normal  SuccessfullyReconciled  25m (x7 over 2d21h)  ingress  Successfully reconciled

ユースケースに固有の Ingress アノテーションを見つけるには、 Ingress アノテーション (Kubernetes Web サイトから) を参照してください。

Kubernetes Service アノテーションでネットワークロードバランサーに関する問題を確認してください

ネットワークロードバランサーに関する問題については、Kubernetes Service アノテーションを確認してください:

$ kubectl describe svc SERVICE_NAME -n YOUR_NAMESPACE

出力例:

Name:                     nlb-ip
Namespace:                default
Labels:                   <none>
Annotations:              service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip              
                          service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing          
                          service.beta.kubernetes.io/aws-load-balancer-type: external                   
Selector:                 app=nlb-ip
Type:                     LoadBalancer
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.100.161.91
IPs:                      10.100.161.91
LoadBalancer Ingress:     k8s-default-nlbip-fff2442e46-ae4f8cf4a182dc4d.elb.ap-southeast-2.amazonaws.com
Port:                     http  80/TCP
TargetPort:               80/TCP
NodePort:                 http  31806/TCP
Endpoints:                192.168.93.144:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

注:APPLICATION_POD_IP をメモしておきます。これは、健康チェックコマンドを実行するときに必要になります。

ユースケースに固有の Kubernetes Service アノテーションを見つけるには、Kubernetes Web サイトの「サービスアノテーション」を参照してください。

健康チェックを手動で確かめてください

アプリケーション ポット の IP アドレスを確認してください:

$ kubectl get pod -n YOUR_NAMESPACE -o wide

テスト ポットを実行して、HTTP 健康チェックについてクラスター内の健康チェックを手動でテストしてください。

$ kubectl run -n YOUR_NAMESPACE troubleshoot -it --rm --image=amazonlinux -- /bin/bash

HTTP健康チェックのため:

# curl -Iv APPLICATION_POD_IP/HEALTH_CHECK_PATH

注:APPLICATION_POD_IP をアプリケーションポッド IP に置き換え、 HEALTH_CHECK_PATH を ALB ターゲットグループのヘルスチェックパスに置き換えます。

コマンドの例:

# curl -Iv 192.168.81.137

出力例:

* Trying 192.168.81.137:80...
* Connected to 192.168.81.137 (192.168.81.137) port 80 (#0)
> HEAD / HTTP/1.1
> Host: 192.168.81.137
> User-Agent: curl/7.78.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Server: nginx/1.21.3
Server: nginx/1.21.3
< Date: Tue, 26 Oct 2021 05:10:17 GMT
Date: Tue, 26 Oct 2021 05:10:17 GMT
< Content-Type: text/html
Content-Type: text/html
< Content-Length: 615
Content-Length: 615
< Last-Modified: Tue, 07 Sep 2021 15:21:03 GMT
Last-Modified: Tue, 07 Sep 2021 15:21:03 GMT
< Connection: keep-alive
Connection: keep-alive
< ETag: "6137835f-267"
ETag: "6137835f-267"
< Accept-Ranges: bytes
Accept-Ranges: bytes

< 
* Connection #0 to host 192.168.81.137 left intact

HTTP 対応のステータスコードを確認します。対応ステータスコードが 200 OK の場合は、アプリケーションが健康チェックパスで正しく応答していることを意味します。

HTTP 対応ステータスコードが 3xx または 4xx の場合は、ヘルスチェックパスを変更できます。次の注釈は 200 OK で応答できます。

alb.ingress.kubernetes.io/healthcheck-path: /ping

- または -

Ingress リソースで次のアノテーションを使用して、正常な健康チェック対応のステータスコード範囲を追加できます。

alb.ingress.kubernetes.io/success-codes: 200-399

TCP ヘルスチェックの場合は、次のコマンドを使用して netcat コマンドをインストールします。

# yum update -y && yum install -y nc

TCP ヘルスチェックをテストします。

# nc -z -v APPLICATION_POD_IP CONTAINER_PORT_NUMBER

注:APPLICATION_POD_IP はアプリケーションポッド IP に置き換え、 CONTAINER_PORT_NUMBER はコンテナポート

コマンドの例:

# nc -z -v 192.168.81.137 80

出力例:

Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to 192.168.81.137:80.
Ncat: 0 bytes sent, 0 bytes received in 0.01 seconds.

ネットワークを確認してください

ネットワークの問題については、次の点を確認てください:

  • EKS クラスター内の複数のノードグループは相互に自由に通信できます。
  • ポットが実行されているサブネットに関連付けられているネットワークアクセスコントロールリスト (ネットワーク ACL) は、ロードバランサーのサブネット CIDR 範囲からのトラフィックを許可します。
  • ロードバランサーサブネットに関連付けられているネットワーク ACL は、ポット が実行されているサブネットからのエフェメラルポート範囲のリターントラフィックを許可する必要があります。
  • ルートテーブルでは、VPC CIDR 範囲内からのローカルトラフィックが許可されます。

kube-proxy を再起動します。

各ノードで実行される kube-proxy が正しく動作しない場合、サービスとエンドポイントの iptables ルールを更新できない可能性があります。kube-proxy を再起動して iptables ルールの再チェックと更新を強制してください。

kubectl rollout restart daemonset.apps/kube-proxy -n kube-system

出力例:

daemonset.apps/kube-proxy restarted

この記事は役に立ちましたか?


請求に関するサポートまたは技術サポートが必要ですか?