Amazon Elastic Kubernetes Service (Amazon EKS) で Network Load Balancer の異常なターゲットを解決したいと考えています。
簡単な説明
Network Load Balancer のターゲットが異常である場合の一般的な理由は次のとおりです。
- ヘルスチェックが正しく設定されていない。
- ポッドから予期しない例外が発生している。
- Network Load Balancers で externalTrafficPolicy が Local に設定されており、DHCP オプションにはカスタム Amazon VPC DNS が設定されている。
解決策
ターゲットグループが IP アドレスであるかインスタンスであるかを確認する
以下のコマンドを実行します。
kubectl get service service_name -o yaml
**注:**service_name はお使いのサービスの名前に置き換えてください。
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type アノテーションが存在しない場合、デフォルトのターゲットタイプはインスタンスになります。
ヘルスチェックが正しく設定されていることを確認する
どの Elastic Load Balancing (ELB) アノテーションがサービスに設定されているかを確認します。詳細については、Kubernetes ウェブサイトの「Service」を参照してください。
以下のコマンドを実行してアノテーションのリストを取得します。
kubectl get service service_name -o yaml
出力例:
service.beta.kubernetes.io/aws-load-balancer-healthcheck-healthy-threshold: "2"# The number of successive successful health checks required for a backend to be considered healthy for traffic. Defaults to 2, must be between 2 and 10
service.beta.kubernetes.io/aws-load-balancer-healthcheck-unhealthy-threshold: "3"
# The number of unsuccessful health checks required for a backend to be considered unhealthy for traffic. Defaults to 6, must be between 2 and 10
service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval: "20"
# The approximate interval, in seconds, between health checks of an individual instance. Defaults to 10, must be between 5 and 300
service.beta.kubernetes.io/aws-load-balancer-healthcheck-timeout: "5"
# The amount of time, in seconds, during which no response means a failed health check. This value must be less than the service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval value. Defaults to 5, must be between 2 and 60
service.beta.kubernetes.io/aws-load-balancer-healthcheck-protocol: TCP
service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: traffic-port
# can be integer or traffic-port
service.beta.kubernetes.io/aws-load-balancer-healthcheck-path: "/"
# health check path for HTTP(S) protocols
アノテーションが正しく設定されていない場合は、ターゲットが異常になる可能性があります。
Amazon VPC で実行されているホストマシンからヘルスチェックを手動で開始する
インスタンスのターゲットタイプの場合は、NodePort で次の curl コマンドを実行します。
curl-ivk node_IP:NodePort
注: node_IP は該当するノードの IP アドレスに置き換えてください。
IP アドレスのターゲットタイプの場合は、次の curl コマンドを実行します。
curl -ivk pod_IP:pod_port
注: pod_IP は、該当するポッドの IP アドレスに置き換えてください。**pod_port ** は、アプリケーションがコンテナ内でリッスンするポートの名前に置き換えてください。
ポッドから予期しない例外が発生していないか確認する
インスタンスのターゲットタイプ
-
現在のヘルスチェック設定アノテーションの、サービス仕様を確認します。完全なリストについては、GitHub ウェブサイトのヘルスチェック設定アノテーションを参照してください。
kubectl get service service_name -o yaml
-
サービスの背後にポッドがあることを確認するために、エンドポイントがあるかを確認します。
kubectl get endpoints service_name -o yaml
-
サービスのエンドポイントが存在しない場合は、ポッドのラベルとサービスのラベルが一致していることを確認します。
kubectl describe servicekubectl describe pod pod_name or kubectl get pod --show-labels
注: pod_name をお使いのポッド名に置き換えてください。
-
ポッドが [実行中] ステータスになっているかを確認します。
kubectl get pod -o wide
-
ポッドのステータスをチェックして、ポッドが再起動なしで実行できることを確認します。
kubectl get pods -o wide
-
再起動している場合は、ポッドログを収集して原因を特定します。
kubectl logs pod_namekubectl logs pod_name --previous
-
ノードと通信できる Amazon VPC のホストマシンにログインします。その後、curl コマンドを NodePort と共に使用して、想定される HTTP ステータスコードをポッドが返すかを確認します。
curl node_IP:NodePort
curl コマンドが想定される HTTP ステータスコードを返さなかった場合、バックエンドポッドも想定される HTTP ステータスコードを返しません。
-
同じホストマシンを使用してポッドの IP アドレスに接続し、ポッドが正しく設定されているかを確認します。
curl pod_IP:pod_port
curl コマンドが想定した HTTP ステータスコードを返さなかった場合、ポッドは正しく設定されていません。
注: サービスの externalTrafficPolicy (Kubernetes ウェブサイトから) が Local に設定されている場合、サービスのバックエンドポッドが実行されているノードのみが正常なターゲットと見なされます。
**IP アドレスのターゲットタイプ **
-
現在のヘルスチェック設定アノテーションの、サービス仕様を確認します。リストについては、GitHub ウェブサイトのヘルスチェック設定アノテーションを参照してください。
kubectl get service service_name -o yaml
-
Amazon VPC 内のホストマシンにログインし、curl コマンドを使用してポッドの IP アドレスと通信します。
curl pod_IP:pod_port
curl コマンドが想定した HTTP ステータスコードを返さなかった場合、ポッドは正しく設定されていません。