Amazon Elastic Kubernetes Service (Amazon EKS) で Network Load Balancers の異常なターゲットを解決したいと考えています。
簡単な説明
Network Load Balancers のターゲットが異常である一般的な理由は次のとおりです。
- ヘルスチェックが正しく設定されていない。この問題を解決するには、Amazon Virtual Private Cloud (Amazon VPC) 内で実行されているホストマシンからヘルスチェックを手動で開始します。
- ポッドから予期しない例外が発生している。この問題を解決するには、解決方法の「ポッドから予期しない例外が発生していないか確認する」のセクションのトラブルシューティング手順に従います。
- Network Load Balancers で (Kubernetes ウェブサイトから) externalTrafficPolicy が Local に設定されており、DHCP オプションにはカスタム Amazon VPC DNS が設定されている。この問題を解決するには、kube-proxy にホスト名オーバーライドフラグを付けてパッチを適用します。
注: サービスアノテーション service.beta.kubernetes.io/aws-load-balancer-nlb-target-type が存在するかどうかを確認することで、ターゲットグループタイプが IP アドレスまたはインスタンスのいずれであるかを判断できます。
解決方法
ターゲットグループが IP アドレスまたはインスタンスのいずれであるかを確認する
次のコマンドを実行してください。
kubectl get service service_name -o yaml
注: service_name を、ご利用のサービス名に置き換えてください。service.beta.kubernetes.io/aws-load-balancer-nlb-target-type アノテーションが存在しない場合、デフォルトのターゲットタイプはインスタンスになります。
ヘルスチェックが正しく設定されていることを確認する
(Kubernetes ウェブサイトから) どの Elastic Load Balancing (ELB) アノテーションがサービスに設定されているかを確認します。
`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.
前述のアノテーションが正しく設定されていない場合、ターゲットが正常でない可能性があります。
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 service
kubectl describe pod pod_name or kubectl get pod --show-labels
注: pod_name を、ご利用のポッドの名前に置き換えます。
ポッドが [Running] (実行中) ステータスであることを確認します。
kubectl get pod -o wide
ポッドのステータスで、ポッドが再起動することなく実行されていることを確認します。
kubectl get pods -o wide
再起動されている場合は、ポッドのログを収集して原因を特定します。
kubectl logs pod_name
kubectl logs pod_name --previous
ノードと通信できる Amazon VPC 内のホストマシンにログインします。
curl コマンドを NodePort とともに使用して、ポッドが想定される HTTP ステータスコードを返しているかどうかを確認します。
curl node_IP:NodePort
curl コマンドが想定される HTTP ステータスコードを返さなかった場合、バックエンドポッドも想定される HTTP ステータスコードを返していません。
同じホストマシンを使用してポッドの IP アドレスに接続し、ポッドが正しく設定されているかどうかを確認します。
curl pod_IP:pod_port
curl コマンドが想定される HTTP ステータスコードを返さなかった場合、ポッドは正しく設定されていません。
注: (Kubernetes ウェブサイトから) サービスの externalTrafficPolicy が Local に設定されている場合、サービスのバックエンドポッドが実行されているノードのみが正常なターゲットとみなされます。
IP アドレスのターゲットタイプ
(GitHub ウェブサイトから) 現在のヘルスチェック設定アノテーションのサービス仕様を確認します。
kubectl get service service_name -o yaml
Amazon VPC 内のホストマシンにログインし、curl コマンドを使用してポッドの IP アドレスと通信します。
curl pod_IP:pod_port
curl コマンドが想定される HTTP ステータスコードを返さなかった場合、ポッドは正しく設定されていません。
kube-proxy にホスト名オーバーライドフラグを付けてパッチを適用する
kube-proxy daemonset 仕様コマンドである args および env を次のように変更します。
---
spec:
template:
spec:
containers:
- name: kube-proxy
command: [ "/bin/sh" ]
args:
- -c
- |
kube-proxy --v=2 --hostname-override=$(NODE_NAME) --config=/var/lib/kube-proxy-config/config
env:
- name: NODE_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
インスタンスのターゲットタイプの場合、externalTrafficPolicy が Cluster または Local に設定されているときは、ノードセキュリティグループの NodePort 向けのデフォルトのイングレス設定は 0.0.0.0/0 です。また、externalTrafficPolicy が Local に設定されているときは、サブネット CIDR IP アドレス範囲を許可するように追加のヘルスチェック NodePort が設定されます。
NodePort のノードセキュリティグループのソース IP アドレスを制御するには、loadBalancerSourceRanges を仕様に追加し、範囲を含めます。
spec:
loadBalancerSourceRanges:
- "143.231.0.0/16"
- "xx.yy.zz.zz/24"
注: .spec.loadBalancerSourceRanges が設定されていない場合、Kubernetes は 0.0.0.0/0 からノードセキュリティグループへのトラフィックを許可します。ノードにパブリック IP アドレスがある場合、Network Load Balancer 以外のトラフィックも、変更されたセキュリティグループのすべてのインスタンスに到達できます。