Amazon Web Services ブログ

Amazon EKS on Fargate で ALB Ingress Controller を使用する

2019 年 12 月、Amazon Elastic Kubernetes Service を使用して AWS Fargate で Kubernetes ポッドを実行できることを発表しました。Fargate を使用すると、Kubernetes アプリケーションの EC2 インスタンスを作成または管理する必要がなくなります。ポッドが起動すると、Fargate はそれらを実行するために計算リソースをオンデマンドで自動的に割り当てます。

Fargate は、マイクロサービスの実行とスケーリングに最適です。特に、スパイクが発生し、予測できないトラフィックパターンがある場合に役立ちます。Amazon Elastic Load Balancing Application Load Balancer (ALB) は、Kubernetes クラスターで実行されているポッドなど、複数のターゲット間でのアプリケーションレイヤー (レイヤー 7) で着信トラフィックを負荷分散する人気のある AWS サービスです。マイクロサービスのようなトラフィックを取得するための優れた方法です。

このブログでは、オープンソースの ALB Ingress Controller を使用して、Fargate ポッドへの入力ベースの負荷分散のために EKS クラスターで AWS Application Load Balancer (ALB) をセットアップする方法を示します。ALB Ingress Controller を使用する Kubernetes Ingress の詳細については、こちらの投稿をご覧ください。

開始するには、Amazon EKS クラスターと Fargate プロファイル (Fargate でポッドを起動できるようにする) を作成し、クラスターのサービスアカウントに IAM ロールを実装して、Ingress Controller ポッドにきめ細かな IAM 権限を付与するために、シンプルな nginx サービスをデプロイし、ALB を使用してインターネットに公開します。

次の図は、最終的なアーキテクチャを示しています。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

前提条件

これらの手順を実行するには、EKS スタートガイドの手順通りに (クラスターを作成しないでください)、次のコンポーネントがインストールされていることを確認してください。

  • EKS CLI、eksctlbrew tap weaveworks/tap の macOS および brew install weaveworks/tap/eksctl
  • AWS CLI の最新バージョンです。
  • Kubernetes CLI、kubectl です。
    Homebrew インストールを使用して macOS に eksctl をインストールした場合、kubectl がすでにシステムにインストールされていることにご注意ください。
  • jq

すべてが環境に正しくインストールされたので、先に進んでビルドを開始できます。

 

クラスターのプロビジョニング

最初の手順は、eksctl を使用して Amazon EKS クラスターを作成することです。Amazon EKS の AWS Fargate は現在、米国東部 (バージニア北部)、米国東部 (オハイオ)、欧州 (アイルランド)、アジアパシフィック (東京) のリージョンで利用できます。これらのリージョンのいずれかでクラスターを作成していることを確認してください。
次のコマンドを実行してクラスターを作成します。

注: <aws_region> を使用しているリージョンに置き換えることを忘れないでください (例: us-east-1, us-east-2, eu-west-1, or ap-northeast-1)

AWS_REGION=<aws_region>
CLUSTER_NAME=eks-fargate-alb-demo
eksctl create cluster --name $CLUSTER_NAME --region $AWS_REGION --fargate

eksctl ツールを使用してクラスターを作成し、フラグ – fargate を渡すと、eksctl ツールはクラスターを作成するだけでなく、クラスター管理者が Fargate で実行するポッドを指定できる Fargate プロファイルも作成します。eksctl によって作成されたデフォルトプロファイルは、デフォルトおよび kube-system 名前空間のすべてを Fargate にマップします。新しい Fargate プロファイルを作成することで、実行するアプリから Controller を分離できます。これにより、ポッドが Fargate にデプロイされる方法を管理するための細かい機能が提供されます。

クラスターの作成が完了したら、次のコマンドを実行して、すべてが順調に進むことを検証できます。

kubectl get svc

次の応答が返されます。

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 16h

この応答は、クラスターが実行中であり、Kubernetes API と通信できることを意味します。
クラスターで OIDC プロバイダーを設定し、ALB Ingress Controller で使用される IAM ポリシーを作成します。

クラスターが実行されているので、AWS で OIDC ID プロバイダー (IdP) をセットアップしましょう。この手順は、サービスアカウントの IAM 機能を使用して、クラスターで実行されている Fargate ポッドに IAM 権限を付与するために必要です。次のコマンドを使用して、クラスターの OIDC プロバイダーをセットアップします。

eksctl utils associate-iam-oidc-provider --cluster $CLUSTER_NAME --approve

注: サービスアカウントの IAM ロールの詳細については、このブログ投稿を参照してください。

次の手順では、ALB Ingress Controller デプロイで使用される IAM ポリシーを作成します。このポリシーは後で Kubernetes サービスアカウントに関連付けられ、ALB Ingress Controller ポッドが AWS アカウントで ALB のリソースを作成して管理できるようにします。IAM ポリシーのサンプルドキュメントをダウンロードして作成します。

wget -O alb-ingress-iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/master/docs/examples/iam-policy.json
aws iam create-policy --policy-name ALBIngressControllerIAMPolicy --policy-document file://alb-ingress-iam-policy.json

クラスターロール、ロールバインディング、および Kubernetes サービスアカウントを作成します。

使用する環境変数のいくつかを入力しましょう。

STACK_NAME=eksctl-$CLUSTER_NAME-cluster
VPC_ID=$(aws cloudformation describe-stacks --stack-name "$STACK_NAME" | jq -r '[.Stacks[0].Outputs[] | {key: .OutputKey, value: .OutputValue}] | from_entries' | jq -r '.VPC')
AWS_ACCOUNT_ID=$(aws sts get-caller-identity | jq -r '.Account')

次に、クラスターロールとロールバインディングを作成します。

cat > rbac-role.yaml <<-EOF
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    app.kubernetes.io/name: alb-ingress-controller
  name: alb-ingress-controller
rules:
  - apiGroups:
      - ""
      - extensions
    resources:
      - configmaps
      - endpoints
      - events
      - ingresses
      - ingresses/status
      - services
    verbs:
      - create
      - get
      - list
      - update
      - watch
      - patch
  - apiGroups:
      - ""
      - extensions
    resources:
      - nodes
      - pods
      - secrets
      - services
      - namespaces
    verbs:
      - get
      - list
      - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    app.kubernetes.io/name: alb-ingress-controller
  name: alb-ingress-controller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: alb-ingress-controller
subjects:
  - kind: ServiceAccount
    name: alb-ingress-controller
    namespace: kube-system
EOF

kubectl apply -f rbac-role.yaml

これらのコマンドにより 2 つのリソースが作成され、結果は次のようになります。

 

clusterrole.rbac.authorization.k8s.io/alb-ingress-controller created
clusterrolebinding.rbac.authorization.k8s.io/alb-ingress-controller created

最後に、Kubernetes サービスアカウントを入力します。

eksctl create iamserviceaccount \
--name alb-ingress-controller \
--namespace kube-system \
--cluster $CLUSTER_NAME \
--attach-policy-arn arn:aws:iam::$AWS_ACCOUNT_ID:policy/ALBIngressControllerIAMPolicy \
--approve

この eksctl コマンドは、IAM ロールを持つ新しい CloudFormation スタックをデプロイします。続けて、次の手順を実行する前に、作業が終了するまでお待ちください。

 

ALB Ingress Controller をデプロイする

次に、ALB Ingress Controller をクラスターにデプロイします。

このブログ投稿では、ALB Ingress Controller バージョン 1.1.14 を使用しています。ALB Ingress Controller とデプロイプロセスの詳細については、公式の GitHub リポジトリを参照してください。

cat > alb-ingress-controller.yaml <<-EOF
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: alb-ingress-controller
name: alb-ingress-controller
namespace: kube-system
spec:
selector:
matchLabels:
app.kubernetes.io/name: alb-ingress-controller
template:
metadata:
labels:
app.kubernetes.io/name: alb-ingress-controller
spec:
containers:
- name: alb-ingress-controller
args:
- --ingress-class=alb
- --cluster-name=$CLUSTER_NAME
- --aws-vpc-id=$VPC_ID
- --aws-region=$AWS_REGION
image: docker.io/amazon/aws-alb-ingress-controller:v1.1.4
serviceAccountName: alb-ingress-controller
EOF
kubectl apply -f alb-ingress-controller.yaml

 

サンプルアプリケーションをクラスターにデプロイする

Ingress Controller を実行したので、アプリケーションをクラスターにデプロイし、ingress リソースを作成して公開します。

デプロイから始めましょう。

cat > nginx-deployment.yaml <<-EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: "nginx-deployment"
namespace: "default"
spec:
replicas: 3
template:
metadata:
labels:
app: "nginx"
spec:
containers:
- image: nginx:latest
imagePullPolicy: Always
name: "nginx"
ports:
- containerPort: 80
EOF

kubectl apply -f nginx-deployment.yaml

結果は次のようになります。

deployment.apps/alb-ingress-controller created

次に、NGINX ポッドを公開できるようにサービスを作成します。

cat > nginx-service.yaml <<-EOF
apiVersion: v1
kind: Service
metadata:
annotations:
alb.ingress.kubernetes.io/target-type: ip
name: "nginx-service"
namespace: "default"
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
type: NodePort
selector:
app: "nginx"
EOF

kubectl apply -f nginx-service.yaml

結果は次のようになります。

deployment.extensions/nginx-deployment created

最後に、ingress リソースを作成しましょう。

cat > nginx-ingress.yaml <<-EOF
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: "nginx-ingress"
namespace: "default"
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
labels:
app: nginx-ingress
spec:
rules:
- http:
paths:
- path: /*
backend:
serviceName: "nginx-service"
servicePort: 80
EOF

kubectl apply -f nginx-ingress.yaml

結果は次のようになります。

ingress.extensions/nginx-ingress created

すべてが完了したら、次のコマンドを実行して ALB URL を取得できます。

kubectl get ingress nginx-ingress

このコマンドの結果は次のようになります。

NAME HOSTS ADDRESS PORTS AGE
nginx-ingress * 5e07dbe1-default-ngnxingr-2e9-113757324.us-east-2.elb.amazonaws.com 80 9s

ALB URL は ADDRESS フィールドの下に表示されるのでご注意ください。ALB ヘルスチェックがすべてのポッドをヘルスとしてマークし、トラフィックの送信を開始するまで数分かかります。次のコマンドを使用すると、すべてのターゲットが正常であるかどうかを確認できます。

LOADBALANCER_PREFIX=$(kubectl get ingress nginx-ingress -o json | jq -r '.status.loadBalancer.ingress[0].hostname' | cut -d- -f1)
TARGETGROUP_ARN=$(aws elbv2 describe-target-groups | jq -r '.TargetGroups[].TargetGroupArn' | grep $LOADBALANCER_PREFIX)
aws elbv2 describe-target-health --target-group-arn $TARGETGROUP_ARN | jq -r '.TargetHealthDescriptions[].TargetHealth.State'

結果は次のようになります。

healthy
healthy
healthy

ウェブブラウザで入力アドレスにアクセスして、NGINX インターフェイスにアクセスできることを確認してください。
また、次のコマンドで AWS Fargate を使用して、すべてのポッドが実行されていることを確認できます。

kubectl get pods -o wide

アプリケーションのすべてのポッドが Fargate ホストで実行されていることにご注意ください。

NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-64fc4c755d-d7cjg 1/1 Running 0 4m23s 192.168.142.15 fargate-ip-192-168-142-15.us-east-2.compute.internal <none> <none>
nginx-deployment-64fc4c755d-gcrgv 1/1 Running 0 4m23s 192.168.121.4 fargate-ip-192-168-121-4.us-east-2.compute.internal <none> <none>
nginx-deployment-64fc4c755d-xdjng 1/1 Running 0 4m23s 192.168.117.179 fargate-ip-192-168-117-179.us-east-2.compute.internal <none> <none>

これにより、インフラストラクチャを管理したり、AWS Application Load Balancer を使用してインターネットやその他のアプリケーションに公開したりすることなく、Amazon EKS のコンテナでアプリケーションを実行できるようになります。

 

まとめ

Amazon EKS で Fargate で ALB Ingress Controller を使用するには、次の手順通りに実行する必要があります。

  1. OIDC プロバイダーをクラスターでセットアップし、適切な権限で IAM ポリシーを作成して、ALB Ingress Controller が AWS リソースを管理できるようにします。
  2. ポッドを実行している ALB Ingress Controller にアタッチされるクラスターロール、ロールバインディング、および Kubernetes サービスアカウントを作成します。
  3. アプリケーションをデプロイし、サービスと Ingress のリソースを作成します。

また、公式の製品ページから AWS Fargate に関する詳細情報と、公式の GitHub リポジトリで ALB Ingress Controller に関する情報を見つけることもできます。