こんにちはカスタマーソリューション部のこーへいです!
前回の記事にてEKSのIngressにてALBのターゲットタイプにipとinstanceがあり、ヘルスチェックの違いを検証してみました。
今回はALBのメトリクスの違いを調べてみます!
結論
- メトリクスの観点においてもIngressのターゲットはipで指定すべき
- Ingressのターゲットをipにした場合、podの数に沿って「HealthyHostCount」「UnHealthyHostCount」が安定な動きで推移するため、アラームの設定が可能
- 一方でIngressのターゲットをinstanceにした場合、一部のpodがUnhealthy状態になった際のALBのメトリクス「HealthyHostCount」「UnHealthyHostCount」が共に不安定な動きで推移するため、アラームの設定が実質不可能
前提
- EKS Cluster作成済み
- AWS Load Balancer Controllerを使用できる状態
上記を前提といたします。今回は本題ではないので省略しますが、EKS初心者の方は下記記事による構築がすごくわかりやすかったです。
事前準備
AWS Load Balancer Controllerを使用できる状態まで完了していると、残りは以下のリソース作成が必要となります。
- Ingress
- Service
- deployment
サンプルとはなってしまいますが、検証の際に自分が用いたyamlファイルを置いておきます。
ターゲットタイプがipの場合のサンプルファイル
Ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing # 外部からのトラフィックを許可
alb.ingress.kubernetes.io/target-type: ip # Ipをターゲットに設定
name: sample-ingress
spec:
ingressClassName: alb # ingressのクラス名を定義
rules:
- http: # httpルール
paths:
- path: /
pathType: Prefix
backend:
service:
name: sample-service # 接続するService
port:
number: 80
service.yaml
apiVersion: v1
kind: Service
metadata:
name: sample-service
spec:
ports: # Podへのアクセスに使用するport
- port: 80
targetPort: 80
protocol: TCP
type: ClusterIP # クラスター内Pod通信
selector:
app: nginx
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-app # 作成するリソースの名前
spec:
replicas: 2 # Deploymentが管理するPodのレプリカ数
selector: # 適用するリソースの選択
matchLabels: # ラベルの一致を条件とする
app: nginx
template: # 作成するpodの定義
metadata:
labels:
app: nginx
spec:
containers: # pod内のコンテナの仕様
- name: nginx # コンテナの名前
image: public.ecr.aws/nginx/nginx:1.23 # コンテナイメージ
ports: # コンテナが公開するポート(内部向け)
- name: tcp
containerPort: 80
ターゲットタイプがinstanceの場合のサンプルファイル
ターゲットタイプがinstanceなため、サービスタイプをNodeportにしています。
このトラフィックモードを使用するには、Kubernetes サービスで NodePort または「LoadBalancer」 タイプを指定する必要があります。
参考:https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/alb-ingress.html
Ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing # 外部からのトラフィックを許可
alb.ingress.kubernetes.io/target-type: instance # instanceをターゲットに設定
name: sample-ingress
spec:
ingressClassName: alb # ingressのクラス名を定義
rules:
- http: # httpルール
paths:
- path: /
pathType: Prefix
backend:
service:
name: sample-service # 接続するService
port:
number: 80
service.yaml
apiVersion: v1
kind: Service
metadata:
name: sample-service
spec:
ports:
- port: 80 # サービスポート
targetPort: 80 # ポッドのポート
protocol: TCP
type: NodePort # NodePortタイプのサービス
selector:
app: nginx # このサービスにトラフィックをルーティングするPodのラベルセレクター
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-app # 作成するリソースの名前
spec:
replicas: 2 # Deploymentが管理するPodのレプリカ数
selector: # 適用するリソースの選択
matchLabels: # ラベルの一致を条件とする
app: nginx
template: # 作成するpodの定義
metadata:
labels:
app: nginx
spec:
containers: # pod内のコンテナの仕様
- name: nginx # コンテナの名前
image: public.ecr.aws/nginx/nginx:1.23 # コンテナイメージ
ports: # コンテナが公開するポート(内部向け)
- name: tcp
containerPort: 80
調べる
それぞれのターゲットタイプの場合のメトリクスを見てみましょう。
ターゲットタイプがipの場合
この場合、ターゲットグループに登録されているのはpodとなります。
正常なpodを2つ立ててメトリクスを確認してみましょう。ALB(ターゲットグループ)のヘルスチェックは最初は2台ともHealthy状態です。
以下はCloudWatchのメトリクス画面です。ALBのメトリクス「HealthyHostCount」はカウント2、「UnHealthyHostCount」はカウント0と想定通りカウントされています。
その後、片方のpodのindex.htmlを削除して意図的にUnhealthy状態にします。
k get pods -n default -o wide # pod名を確認
k exec -it [pod名] -- /bin/bash # podにログイン
rm /usr/share/nginx/html/index.html # podのindex.htmlを削除
しばらくすると「HealthyHostCount」「UnHealthyHostCount」共にカウント1で安定しました。想定通りの結果となりました。
ターゲットタイプがinstanceの場合
podが2台の場合
この場合、ターゲットグループに登録されているのはノード(EC2インスタンス)となります。
正常なpodを2つ立ててメトリクスを確認してみましょう。ALB(ターゲットグループ)のヘルスチェックはインスタンス一台がHealthy状態です。
どちらのpodもHealthyの状態では「HealthyHostCount」はカウント1、「UnHealthyHostCount」はカウント0で安定していましたが、片方のpodのindex.htmlを削除すると「HealthyHostCount」「UnHealthyHostCount」それぞれのカウントが安定しなくなりました。
18分に2つ目のpodのindex.htmlを削除すると、「HealthyHostCount」が0、「UnHealthyHostCount」が1で安定しました。
この時点での私の思考の流れは以下の通りです。
- instance自体はターゲットグループでhealthyなので片方のpodのindex.htmlを削除しても「HealthyHostCount」は1のままで、両方のpodのindex.htmlを削除すると「UnHealthyHostCount」が1となると予想
- 実際に試してみると片方のpodのindex.htmlを削除した段階で、それぞれのカウントが0~1(0.5含む)の間で不安定に推移した。0.5という値があるため実態はpodのhealthy状態をカウントしている可能性が浮上(2台あるpodのうち1台という計算)
- 次はpodが3台の場合で検証して確かめよう
podが3台の場合
deployment.yamlのreplica数を2→3に変更し、検証します。
spec:
replicas: 3 # Deploymentが管理するPodのレプリカ数
selector: # 適用するリソースの選択
上記と同様の流れで、28分時点で1台目、35分時点で2台目、46分時点で全て(3台目)のpodのindex.htmlを削除しました。
予想ではCount数の小数点が0.33や0.66(全3台あるうちのpod数の1or2台の意)が記録されるかと思いましたが、実際には予想と異なり、0~0.5~1で不安定的に推移するという結果となりました。
また申し訳ないですが、なぜ0.5なのかや推移が不安定なのかの原因解明はできなかったです(分かり次第追記します)。
結論(再掲載)
- メトリクスの観点においてもIngressのターゲットはipで指定すべき
- Ingressのターゲットをipにした場合、podの数に沿って「HealthyHostCount」「UnHealthyHostCount」が安定な動きで推移するため、アラームの設定が可能
- 一方でIngressのターゲットをinstanceにした場合、一部のpodがUnhealthy状態になった際のALBのメトリクス「HealthyHostCount」「UnHealthyHostCount」が共に不安定な動きで推移するため、アラームの設定が実質不可能
まとめ
Ingressのターゲットがinstance時の、メトリクスの値や推移については謎が解けませんでした(すみません)。
しかし、前回の記事と合わせてもターゲットはipを指定することが良いことが分かったので満足しました。