Technical Blog テクニカルブログ
  1. HOME
  2. テクニカルブログ
  3. 【Amazon EKS】第二回 ALBを利用してNginx Podに負荷分散設定をしてみた!

【Amazon EKS】第二回 ALBを利用してNginx Podに負荷分散設定をしてみた!

投稿者:内堀 雄真

はじめに

こんにちは! ハイブリッドクラウド部の内堀です。
ハイブリッドクラウド部では、Amazon EKSについてのテックブログを投稿しています!

前回記事では「Amazon EKSのクラスターとノードグループの作成を行い、踏み台サーバからクラスターへの接続が出来るようになる」までを実装しました。

今回は「Nginxが起動するPodを作成し、AWS ALBを利用した負荷分散が出来るようになる」までを実装していきます。

目次

OIDCプロバイダーの作成

OIDCプロバイダーは、身元を確認したり認証情報を提供したりする役割を持っています。
今回はAWS Load Balancer Controller サービスアカウントでIAMロールを使用するため、作成が必要となります。

公式ドキュメント「クラスター用の IAM OIDC プロバイダーの作成」を参考に、OIDCプロバイダーを作成していきます。

前提条件

  • AWS CLIの有効なバージョンがインストールされていること。
  • kubectlの有効なバージョンがインストールされていること。

二つの有効なバージョンについては、上記の公式ドキュメントを参照してください。

今回はAWS CLI ver2.13.7、kubectl ver1.27.1がインストールされた環境で作成していきます。

作成

EKSコンソール > クラスター

該当のクラスター名をクリックし、
概要 > 詳細 にある「OpenID Connect プロバイダー URL」の値をコピーしておきます。

IAMコンソール > IDプロバイダ

「プロバイダを追加」をクリックします。

「プロバイダのタイプ」はOpenID Connectを選択し、
「プロバイダのURL」では先ほどコピーしたURLを貼り付けて「サムプリントを取得」を押します。

「対象者」では「sts.amazonaws.com」と入力します。

上記の入力が終わったら「プロバイダを追加」をクリックし、プロバイダを作成します。

AWS Load Balancer Controllerのインストール

AWS Load Balancer ControllerはEKS上で稼働するPodに対してAmazon Elastic Load Balancer(ELB)の設定・管理を自動化するツールです。
IngressリソースをデプロイすることでALBを作成し、Serviceリソースのtype: LoadBalancerとすることでNLBを作成します。
以前はAWS ALB Ingress Controller と呼ばれていました。

公式ドキュメント「AWS Load Balancer Controller アドオンのインストール」を参考にインストールを行います。

1. IAMポリシーの作成

IAM ポリシーを作成します。

# IAMポリシーの内容をダウンロード
$ curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.7/docs/install/iam_policy.json

# IAMポリシーの作成
$ aws iam create-policy \
    --policy-name AWSLoadBalancerControllerIAMPolicy \
    --policy-document file://iam_policy.json

2. IAMロールの作成

IAMロールを作成し、先ほど作成したIAMポリシーをアタッチしておきます。
日本語の箇所は環境に合わせて書き換えてください。

# クラスターのOIDCプロバイダーIDを取得して変数に格納する
$ oidc_id=$(aws eks describe-cluster --name (クラスター名) --query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5)

# IDを確認する
# 出力されたIDは次コマンド内で入力する
$ aws iam list-open-id-connect-providers | grep $oidc_id | cut -d "/" -f4

# 日本語箇所を書き換え、jsonファイルを作成する
$ cat >load-balancer-role-trust-policy.json <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::(アカウントID):oidc-provider/oidc.eks.(リージョンコード).amazonaws.com/id/(二つ目のコマンドで取得したID)"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "oidc.eks.(リージョン).amazonaws.com/id/(二つ目のコマンドで取得したID):aud": "sts.amazonaws.com",
                    "oidc.eks.(リージョン).amazonaws.com/id/(二つ目のコマンドで取得したID):sub": "system:serviceaccount:kube-system:aws-load-balancer-controller"
                }
            }
        }
    ]
}
EOF

# IAMロールを作成する
$ aws iam create-role \
  --role-name AmazonEKSLoadBalancerControllerRole \
  --assume-role-policy-document file://"load-balancer-role-trust-policy.json"

# IAMロールに先ほど作成したEKS管理のIAMポリシーをアタッチする
$ aws iam attach-role-policy \
  --policy-arn arn:aws:iam::(アカウントID):policy/AWSLoadBalancerControllerIAMPolicy \
  --role-name AmazonEKSLoadBalancerControllerRole

3. サービスアカウントの作成

サービスアカウント「aws-load-balancer-controller」を作成します。
名前空間はkube-systemを指定してください。

# 日本語箇所を書き換え、yamlファイルを作成する
$ cat >aws-load-balancer-controller-service-account.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: aws-load-balancer-controller
  name: aws-load-balancer-controller
  namespace: kube-system
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::(アカウントID):role/AmazonEKSLoadBalancerControllerRole
EOF

#サービスアカウントを作成する
$ kubectl apply -f aws-load-balancer-controller-service-account.yaml

4. AWS Load Balancer Controllerのインストール

Helmを使用してインストールを行います。
Helmの導入はこちらを参考にしてください。

# Helmのインストール
$ curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 > get_helm.sh
$ chmod 700 get_helm.sh
$ ./get_helm.sh

# インストール確認
$ helm version --short | cut -d + -f 1
v3.12.2

# eks-chartsリポジトリを追加する
$ helm repo add eks https://aws.github.io/eks-charts

# ローカルリポジトリの更新
$ helm repo update eks

# AWS Load Balancer Controller のインストール
$ helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  -n kube-system \
  --set clusterName=(クラスター名) \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller 

5. インストール確認

AWS Load Balancer Controllerがインストールされていることを確認します。

$ kubectl get deployment -n kube-system aws-load-balancer-controller
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
aws-load-balancer-controller   2/2     2            2           26d

アプリケーション・ALBのデプロイ

NginxのPodを起動し、ALB経由でアクセスするためのDeployment,Service,Ingressを作成します。
今回はAWS ECRのパブリックリポジトリにあるnginxイメージを使用して作成していきます。

1. Deploymentファイルの作成

Podのスケーリング設定や情報を定義します。
Deploymentを使用することで、稼働するPod数の保証や、ローリングアップデートを自動で行ってくれます。

次の内容をdeployment.yamlとして保存します。

# Deploymentリソースの定義に使用されるKubernetes APIのバージョンとグループ
apiVersion: apps/v1

# 作成するリソースの種類
kind: Deployment

# メタデータ
metadata:
  name: nlb-sample-app  # 作成するリソースの名前
  namespace: nginx  # リソースを作成する名前空間

# リソースの仕様
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

2. Serviceファイルの作成

クラスタ内のPodへのネットワーク接続設定を定義します。
NginxのPodにアクセスするためのSerivceを作成します。

次の内容をservice.yamlとして保存します。

apiVersion: v1
kind: Service
metadata:
  name: alb-sample-service
  namespace: nginx
spec:
  ports:  # Podへのアクセスに使用するport
    - port: 80
      targetPort: 80
      protocol: TCP
  type: ClusterIP  # クラスター内Pod通信
  selector:
    app: nginx

3. Ingressファイルの作成

NginxにアクセスするためのIngressを作成します。
Ingressが作成されるとIngressコントローラーによりALBが自動作成され、Nginxへのアクセスが可能となります。

次の内容を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: test-ingress
  namespace: nginx
spec:
  ingressClassName: alb  # ingressのクラス名を定義
  rules:
  - http:  # httpルール
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: alb-sample-service  # 接続するService
            port:
              number: 80

4. マニフェストファイルの適用・デプロイ確認

作成した3つのマニフェストファイル(deployment.yaml, service.yaml, ingress.yaml)を、クラスターに適用します。

$ kubectl apply -f deployment.yaml, service.yaml, ingress.yaml

適用後、リソースが正常にデプロイされているか確認します。

以下のような出力となっていれば、問題なくデプロイが完了しています。

$ kubectl get all -n nginx
NAME                                  READY   STATUS    RESTARTS   AGE
pod/nlb-sample-app-78ddc8bc75-dll7f   1/1     Running   0          3h39m
pod/nlb-sample-app-78ddc8bc75-zxkdv   1/1     Running   0          3h39m

NAME                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/alb-sample-service   ClusterIP   172.20.90.135   <none>        80/TCP    131m

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nlb-sample-app   2/2     2            2           3h39m

NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/nlb-sample-app-78ddc8bc75   2         2         2       3h39m

$ kubectl get ingress -n nginx
NAME           CLASS   HOSTS   ADDRESS                                                                    PORTS   AGE
test-ingress   alb     *       k8s-nginx-testingr-bda49c23c3-672405439.ap-northeast-1.elb.amazonaws.com   80      125m

AWS コンソールに移動し、ALBが作成されていることも確認してください。

EC2コンソール > ロードバランサー

アプリケーションへの接続

早速作成したNginxに接続してみます。

ALBの詳細情報からDNS名を取得し、ブラウザでアクセスしてみます。

http://k8s-nginx-testingr-bda49c23c3-672405439.ap-northeast-1.elb.amazonaws.com

以下のような画面が出力されれば成功です。

負荷分散の確認

ALBからのアクセスが2つのNginxのPodに負荷分散されていることを各Podのログで確認します

まずは起動しているPodの名前を調べます。

$ kubectl get pods -n nginx
NAME                              READY   STATUS    RESTARTS   AGE
nlb-sample-app-78ddc8bc75-2wd9l   1/1     Running   0          20h
nlb-sample-app-78ddc8bc75-skwcq   1/1     Running   0          20h

一つ目のPod、”nlb-sample-app-78ddc8bc75-2wd9l” のログを確認します。

$ kubectl logs nlb-sample-app-78ddc8bc75-2wd9l -n nginx
...
10.0.0.21 - - [31/Aug/2023:09:13:32 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36" "xxx.xxx.xxx.xxx, xxx.xxx.xxx.xxx"
...

クライアントから一つ目のPodへのアクセスログを確認出来ました。

続いて二つ目のPod、”nlb-sample-app-78ddc8bc75-skwcq” のログを確認してみます。

$ kubectl logs nlb-sample-app-78ddc8bc75-skwcq -n nginx
...
10.0.12.7 - - [31/Aug/2023:09:11:34 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36" "xxx.xxx.xxx.xxx, "xxx.xxx.xxx.xxx"
...

同じく、クライアントから二つ目のPodへのアクセスログを確認出来ました。

ALB経由で2つのPodに負荷分散されていることが確認できました。

まとめ

今回のブログ記事では、EKSを用いたPodにおける負荷分散設定の詳細な手順をご紹介しました。

  • OIDCプロバイダーの作成
  • AWS Load Balancer Controller のインストール
  • Nginxが起動するPodとALBのデプロイ

これらのステップにより、目標とするアプリケーションに接続した際に、負荷が複数のPodに分散されるようになりました。この記事が皆さまのEKSや負荷分散の設定に役立つ一助となれば幸いです。この機会に、皆さまもぜひEKSを触ってみてください!

第3回では、CI/CDを用いてコンテナイメージの作成からEKS上への自動デプロイに関して記事にする予定です。次回も楽しみにお待ちください!


AWS社とのAWSソリューションプロバイダープログラム契約を結び、AWSのアカウントの手配から設計、環境構築、システム運用までワンストップのソリューションを提供いたします。
コンテナ技術には特に力を入れており、Amazon EKSだけでなく、Red Hat OpenShiftのソリューションもございます。
OpenShiftのソリューションページや、運用ソリューションであるNI+C Multicloud MSPの紹介ページもありますので、一読していただけますと幸いです。

ページのトップへ