プライベートサブネット内の EKS Fargate で ALB 配下にコンテナをデプロイする

プライベートサブネット内の EKS Fargate で ALB 配下にコンテナをデプロイする

プライベートサブネット内の EKS Fargate でコンテナを実行し、アプリケーションを内部 ALB 経由でのみ公開します。

Takahiro Iwasa
19 min read

プライベートサブネット内の EKS Fargate でコンテナを実行し、Application Load Balancer(ALB)の背後に配置します。クラスターの Pod をパブリックインターネットから遮断しながら、制御されたエントリーポイントを提供できます。

VPC のセットアップ

VPC の作成

専用の VPC を作成します。

Terminal window
aws ec2 create-vpc \
--cidr-block 192.168.0.0/16 \
--tag-specifications "ResourceType=vpc,Tags=[{Key=Name,Value=eks-fargate-vpc}]"
aws ec2 modify-vpc-attribute \
--vpc-id vpc-xxxxxxxxxxxxxxxxx \
--enable-dns-hostnames
Important

VPC エンドポイントを利用する場合は、必ず DNS ホスト名を有効にしてください。詳細は公式ドキュメントを参照してください。

If you use custom DNS domain names defined in a private hosted zone in Amazon Route 53, or use private DNS with interface VPC endpoints (AWS PrivateLink), you must set both the enableDnsHostnames and enableDnsSupport attributes to true.

サブネットの追加

Fargate Pod 用のプライベートサブネットと、踏み台 EC2 インスタンス用のパブリックサブネットを作成します。

Terminal window
aws ec2 create-subnet \
--vpc-id vpc-xxxxxxxxxxxxxxxxx \
--availability-zone ap-northeast-1a \
--cidr-block 192.168.0.0/20 \
--tag-specifications "ResourceType=subnet,Tags=[{Key=Name,Value=eks-fargate-private-subnet-1a}]"
aws ec2 create-subnet \
--vpc-id vpc-xxxxxxxxxxxxxxxxx \
--availability-zone ap-northeast-1c \
--cidr-block 192.168.16.0/20 \
--tag-specifications "ResourceType=subnet,Tags=[{Key=Name,Value=eks-fargate-private-subnet-1c}]"
aws ec2 create-subnet \
--vpc-id vpc-xxxxxxxxxxxxxxxxx \
--availability-zone ap-northeast-1a \
--cidr-block 192.168.32.0/20 \
--tag-specifications "ResourceType=subnet,Tags=[{Key=Name,Value=eks-fargate-public-subnet-1a}]"

インターネットゲートウェイの追加

パブリックサブネット内のリソースにインターネットアクセスを提供するため、インターネットゲートウェイを作成し、VPC にアタッチします。

Terminal window
aws ec2 create-internet-gateway \
--tag-specifications "ResourceType=internet-gateway,Tags=[{Key=Name,Value=igw-eks-fargate}]"
aws ec2 attach-internet-gateway \
--internet-gateway-id igw-xxxxxxxxxxxxxxxxx \
--vpc-id vpc-xxxxxxxxxxxxxxxxx

次に、ルートテーブルを作成してインターネットゲートウェイへのデフォルトルートを追加し、パブリックサブネットに関連付けます。

Terminal window
aws ec2 create-route-table \
--vpc-id vpc-xxxxxxxxxxxxxxxxx \
--tag-specifications "ResourceType=route-table,Tags=[{Key=Name,Value=rtb-eks-fargate-public}]"
aws ec2 create-route \
--route-table-id rtb-xxxxxxxx \
--destination-cidr-block 0.0.0.0/0 \
--gateway-id igw-xxxxxxxxxxxxxxxxx
aws ec2 associate-route-table \
--route-table-id rtb-xxxxxxxx \
--subnet-id subnet-xxxxxxxxxxxxxxxxx

VPC エンドポイントの追加

EKS プライベートクラスターが AWS サービスと通信できるよう、必要な VPC エンドポイントを作成します。詳細は公式ドキュメントを参照してください。

TypeEndpoint
Interfacecom.amazonaws.region-code.ecr.api
Interfacecom.amazonaws.region-code.ecr.dkr
Interfacecom.amazonaws.region-code.ec2
Interfacecom.amazonaws.region-code.elasticloadbalancing
Interfacecom.amazonaws.region-code.sts
Gatewaycom.amazonaws.region-code.s3

VPC エンドポイント用のセキュリティグループを作成します。

Terminal window
aws ec2 create-security-group \
--description "VPC endpoints" \
--group-name eks-fargate-vpc-endpoints-sg \
--vpc-id vpc-xxxxxxxxxxxxxxxxx \
--tag-specifications "ResourceType=security-group,Tags=[{Key=Name,Value=eks-fargate-vpc-endpoints-sg}]"
aws ec2 authorize-security-group-ingress \
--group-id sg-xxxxxxxxxxxxxxxxx \
--protocol tcp \
--port 443 \
--cidr 192.168.0.0/16

インターフェイス型 VPC エンドポイントを作成します。

Terminal window
for name in com.amazonaws.<REGION>.ecr.api com.amazonaws.<REGION>.ecr.dkr com.amazonaws.<REGION>.ec2 com.amazonaws.<REGION>.elasticloadbalancing com.amazonaws.<REGION>.sts; do \
aws ec2 create-vpc-endpoint \
--vpc-id vpc-xxxxxxxxxxxxxxxxx \
--vpc-endpoint-type Interface \
--service-name $name \
--security-group-ids sg-xxxxxxxxxxxxxxxxx \
--subnet-ids subnet-xxxxxxxxxxxxxxxxx subnet-xxxxxxxxxxxxxxxxx;
done;

S3 用のゲートウェイ型 VPC エンドポイントを作成します。

Terminal window
aws ec2 create-vpc-endpoint \
--vpc-id vpc-xxxxxxxxxxxxxxxxx \
--service-name com.amazonaws.<REGION>.s3 \
--route-table-ids rtb-xxxxxxxxxxxxxxxxx

これらのエンドポイントにより、プライベートクラスターは ECR、S3、Elastic Load Balancing などの AWS サービスへアクセスできます。

踏み台 EC2 インスタンス

EKS プライベートクラスターには、踏み台 EC2 インスタンスからアクセスします。パブリックエンドポイントを無効にした後も、VPC 内の踏み台から Kubernetes API サーバーへ接続できます。

https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html#private-access

If you have disabled public access for your cluster’s Kubernetes API server endpoint, you can only access the API server from within your VPC or a connected network.

インスタンス IAM ロールの作成

踏み台インスタンス用の IAM ロールを作成し、Session Manager で接続するための AmazonSSMManagedInstanceCore マネージドポリシーをアタッチします。

IAM ロールを作成します。

Terminal window
echo '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}' > policy.json
aws iam create-role \
--role-name eks-fargate-bastion-ec2-role \
--assume-role-policy-document file://./policy.json

インスタンスプロファイルを作成します。

Terminal window
aws iam create-instance-profile \
--instance-profile-name eks-fargate-bastion-ec2-instance-profile
aws iam add-role-to-instance-profile \
--instance-profile-name eks-fargate-bastion-ec2-instance-profile \
--role-name eks-fargate-bastion-ec2-role

Session Manager での接続を許可するため、AmazonSSMManagedInstanceCore ポリシーをアタッチします。

Terminal window
aws iam attach-role-policy \
--role-name eks-fargate-bastion-ec2-role \
--policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

この例で使う EKS、EC2、IAM、CloudFormation の操作を許可する追加ポリシーをアタッチします。本番環境では、サービス認可リファレンスに基づいて権限を絞り込んでください。

Terminal window
echo '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cloudformation:CreateStack",
"cloudformation:DeleteStack",
"cloudformation:DescribeStacks",
"cloudformation:DescribeStackEvents",
"cloudformation:ListStacks",
"ec2:*",
"eks:*",
"iam:AttachRolePolicy",
"iam:CreateOpenIDConnectProvider",
"iam:CreateRole",
"iam:DetachRolePolicy",
"iam:DeleteOpenIDConnectProvider",
"iam:GetOpenIDConnectProvider",
"iam:GetRole",
"iam:ListPolicies",
"iam:PassRole",
"iam:PutRolePolicy",
"iam:TagOpenIDConnectProvider"
],
"Resource": "*"
}
]
}' > policy.json
aws iam put-role-policy \
--role-name eks-fargate-bastion-ec2-role \
--policy-name eks-cluster \
--policy-document file://./policy.json

踏み台 EC2 インスタンスの起動

IAM ロールを設定したら、EC2 インスタンスを起動します。例の AMI ID は、使用するリージョンで利用可能な Amazon Linux AMI に置き換えてください。詳細は公式ドキュメントを参照してください。

Terminal window
instanceProfileRole=$( \
aws iam list-instance-profiles-for-role \
--role-name eks-fargate-bastion-ec2-role \
| jq -r '.InstanceProfiles[0].Arn')
aws ec2 run-instances \
--image-id ami-0bba69335379e17f8 \
--instance-type t2.micro \
--iam-instance-profile "Arn=$instanceProfileRole" \
--subnet-id subnet-xxxxxxxxxxxxxxxxx \
--associate-public-ip-address \
--tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=eks-fargate-bastion-ec2}]"

Session Manager でインスタンスに接続する

踏み台 EC2 インスタンスには、AWS Systems Manager Session Manager で接続します。SSH キーペアが不要になり、セッションを監査できます。

接続後、ec2-user アカウントに切り替えます。

Terminal window
sh-4.2$ sudo su - ec2-user
Important

Session Manager で接続するには、インスタンスの IAM ロールに AmazonSSMManagedInstanceCore ポリシーが必要です。

AWS CLI を更新する

踏み台インスタンスの AWS CLI を更新します。

Terminal window
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install --bin-dir /usr/local/bin --install-dir /usr/local/aws-cli --update

インストールを確認します。

Terminal window
aws --version

kubectl のインストール

EKS クラスターを管理するため、踏み台インスタンスに kubectl をインストールします。

EKS クラスターのバージョンに対応する kubectl バイナリをダウンロードします。

Terminal window
curl -o kubectl https://s3.us-west-2.amazonaws.com/amazon-eks/1.24.7/2022-10-31/bin/linux/amd64/kubectl

バイナリを実行可能にします。

Terminal window
chmod +x ./kubectl

kubectl を PATH に追加します。

Terminal window
mkdir -p $HOME/bin && cp ./kubectl $HOME/bin/kubectl && export PATH=$PATH:$HOME/bin
echo 'export PATH=$PATH:$HOME/bin' >> ~/.bashrc

インストールを確認します。

Terminal window
kubectl version --short --client

eksctl のインストール

EKS クラスターを作成・管理するため、eksctl をインストールします。

eksctl をダウンロードして展開します。

Terminal window
curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp

バイナリを PATH が通ったディレクトリに移動します。

Terminal window
sudo mv /tmp/eksctl /usr/local/bin

インストールを確認します。

Terminal window
eksctl version

これで、踏み台 EC2 インスタンスから kubectleksctl を使って EKS クラスターを管理できます。

EKS

EKS クラスターの作成

eksctl--fargate オプションを指定して EKS クラスターを作成します。Fargate が Pod を実行するため、自己管理型またはマネージド型のノードグループは不要です。

詳細な手順については公式ドキュメントを参照してください。

ℹ️ Note

クラスタの作成にはおよそ20分以上かかる場合があります。

Terminal window
eksctl create cluster \
--name eks-fargate-cluster \
--region ap-northeast-1 \
--version 1.24 \
--vpc-private-subnets subnet-xxxxxxxxxxxxxxxxx,subnet-xxxxxxxxxxxxxxxxx \
--without-nodegroup \
--fargate

作成後、クラスターを確認します。

Terminal window
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 20m

付録: クラスタアクセスのトラブルシューティング

問題 1:認証情報エラー

kubectl get svc の実行時に以下のエラーが発生する場合は、AWS CLI を更新します。

Unable to connect to the server: getting credentials: decoding stdout: no kind "ExecCredential" is registered for version "client.authentication.k8s.io/v1alpha1" in scheme "pkg/client/auth/exec/exec.go:62"

AWS CLI を更新します。

Terminal window
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install --bin-dir /usr/local/bin --install-dir /usr/local/aws-cli --update

コマンドを再試行します。

Terminal window
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 20m

問題 2:接続拒否

以下のエラーが表示される場合。

The connection to the server localhost:8080 was refused - did you specify the right host or port?

Kubernetes の設定ファイル(~/.kube/config)を更新します。

Terminal window
aws eks update-kubeconfig \
--region ap-northeast-1 \
--name eks-fargate-cluster

コマンドを再試行します。

Terminal window
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 20m

IAM ユーザーとロールの追加

クラスターの管理が作成者の IAM ID だけに依存しないよう、追加の IAM ユーザーやロールにアクセス権を付与します。デフォルトでは、クラスターを作成した IAM エンティティだけが管理者アクセス権を持ちます。

ベストプラクティスについては公式ドキュメントを参照してください。

The IAM user or role that created the cluster is the only IAM entity that has access to the cluster. Grant permissions to other IAM users or roles so they can access your cluster.

IAM ユーザーを system:masters グループに追加するには、以下のコマンドを使います。

Terminal window
eksctl create iamidentitymapping \
--cluster eks-fargate-cluster \
--region ap-northeast-1 \
--arn arn:aws:iam::000000000000:user/xxxxxx \
--group system:masters \
--no-duplicate-arns

追加した IAM ID に EKS クラスターの管理者アクセス権が付与されます。

プライベートクラスタエンドポイントの有効化

プライベートエンドポイントを有効にし、パブリックエンドポイントを無効にして、Kubernetes API へのアクセスを VPC と接続済みネットワーク内に制限します。

ℹ️ Note

プライベートクラスタエンドポイントの有効化にはおよそ10分かかる場合があります。

Terminal window
aws eks update-cluster-config \
--region ap-northeast-1 \
--name eks-fargate-cluster \
--resources-vpc-config endpointPublicAccess=false,endpointPrivateAccess=true

EKS コントロールプレーンのセキュリティグループで、踏み台 EC2 インスタンスからポート 443 への受信トラフィックが許可されていることを確認してください。

https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html#private-access

You must ensure that your Amazon EKS control plane security group contains rules to allow ingress traffic on port 443 from your bastion host.

Terminal window
sgId=$(aws eks describe-cluster --name eks-fargate-cluster | jq -r .cluster.resourcesVpcConfig.clusterSecurityGroupId)
aws ec2 authorize-security-group-ingress \
--group-id $sgId \
--protocol tcp \
--port 443 \
--cidr 192.168.0.0/16

踏み台 EC2 インスタンスと EKS クラスター間の接続をテストします。

Terminal window
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 153m

Fargate プロファイルの作成

アプリケーションの名前空間に対応する Fargate プロファイルを作成します。

Terminal window
eksctl create fargateprofile \
--region ap-northeast-1 \
--cluster eks-fargate-cluster \
--name fargate-app-profile \
--namespace fargate-app

AWS Load Balancer Controller のインストール

Application Load Balancer(ALB)の背後でアプリケーションコンテナを実行するため、AWS Load Balancer Controller をインストールします。

クラスターに IAM OIDC プロバイダーがない場合は作成します。

Terminal window
oidc_id=$(aws eks describe-cluster --name eks-fargate-cluster --query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5)
aws iam list-open-id-connect-providers | grep $oidc_id
# If no response is returned, run the following:
eksctl utils associate-iam-oidc-provider \
--region ap-northeast-1 \
--cluster eks-fargate-cluster \
--approve

AWS Load Balancer Controller のポリシーファイルをダウンロードします。

Terminal window
curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.4/docs/install/iam_policy.json

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

Terminal window
aws iam create-policy \
--policy-name AWSLoadBalancerControllerIAMPolicy \
--policy-document file://iam_policy.json

IAM サービスアカウントを作成します。

Terminal window
eksctl create iamserviceaccount \
--region ap-northeast-1 \
--cluster=eks-fargate-cluster \
--namespace=kube-system \
--name=aws-load-balancer-controller \
--role-name "AmazonEKSLoadBalancerControllerRole" \
--attach-policy-arn=arn:aws:iam::111122223333:policy/AWSLoadBalancerControllerIAMPolicy \
--approve

Helm と Load Balancer Controller のインストール

Helm v3 をインストールします。

Terminal window
$ 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.10.3

Load Balancer Controller をインストールします。

Terminal window
helm repo add eks https://aws.github.io/eks-charts
helm repo update
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set region=ap-northeast-1 \
--set vpcId=vpc-xxxxxxxxxxxxxxxxx \
--set image.repository=602401143452.dkr.ecr.ap-northeast-1.amazonaws.com/amazon/aws-load-balancer-controller \
--set clusterName=eks-fargate-cluster \
--set serviceAccount.create=false \
--set serviceAccount.name=aws-load-balancer-controller \
--set enableShield=false \
--set enableWaf=false \
--set enableWafv2=false
ℹ️ Note

2022 年当時は必要な VPC エンドポイントが提供されていないため、コマンドに enableShield=falseenableWaf=falseenableWafv2=false を追加します。詳細は公式ドキュメントを参照してください。

When deploying it, you should use command line flags to set enable-shield, enable-waf, and enable-wafv2 to false. Certificate discovery with hostnames from Ingress objects isn’t supported. This is because the controller needs to reach AWS Certificate Manager, which doesn’t have a VPC interface endpoint.

デプロイを確認します。

Terminal window
$ 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 105s

これで、クラスターからアプリケーション用の Application Load Balancer を作成できます。

サブネットへのタグ付け

内部ロードバランサー用であることを示すため、プライベートサブネットにタグを付けます。Kubernetes と AWS Load Balancer Controller がサブネットを識別するために必要です。

Terminal window
aws ec2 create-tags \
--resources subnet-xxxxxxxxxxxxxxxxx subnet-xxxxxxxxxxxxxxxxx \
--tags Key=kubernetes.io/role/internal-elb,Value=1

詳細については公式ドキュメントを参照してください。

Must be tagged in the following format. This is so that Kubernetes and the AWS load balancer controller know that the subnets can be used for internal load balancers.

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

アプリケーションのビルド

この例では、FastAPI を使って小さなデモ用 API を作成します。

アプリケーションに必要な依存関係を定義します。

requirements.txt
anyio==3.6.2
click==8.1.3
fastapi==0.88.0
h11==0.14.0
httptools==0.5.0
idna==3.4
pydantic==1.10.2
python-dotenv==0.21.0
PyYAML==6.0
sniffio==1.3.0
starlette==0.22.0
typing_extensions==4.4.0
uvicorn==0.20.0
uvloop==0.17.0
watchfiles==0.18.1
websockets==10.4

基本的な API エンドポイントを作成します。

main.py
from fastapi import FastAPI
app = FastAPI()
@app.get('/')
def read_root():
return {'message': 'Hello world!'}

アプリケーションコンテナをビルドするための Dockerfile を作成します。

Dockerfile
FROM python:3.10-alpine@sha256:d8a484baabf7d2337d34cdef6730413ea1feef4ba251784f9b7a8d7b642041b3
COPY ./src ./
RUN pip install --no-cache-dir -r requirements.txt
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]

イメージの ECR へのプッシュ

アプリケーションイメージをビルドし、ECR にプッシュします。

ECR リポジトリを作成します。

Terminal window
aws ecr create-repository --repository-name api

リポジトリ URI を取得します。

Terminal window
uri=$(aws ecr describe-repositories | jq -r '.repositories[] | select(.repositoryName == "api") | .repositoryUri')

Docker を ECR に対して認証します。

Terminal window
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 000000000000.dkr.ecr.ap-northeast-1.amazonaws.com

イメージをビルド、タグ付け、プッシュします。

Terminal window
docker build .
docker tag xxxxxxxxxxxx $uri:latest
docker push $uri:latest

Fargate へのデプロイ

Kubernetes マニフェストファイル fargate-app.yaml を作成します。

000000000000.dkr.ecr.ap-northeast-1.amazonaws.com/api:latest を実際のイメージ URI に置き換えてください。

AWS Load Balancer Controller v2.4 の仕様は、公式ドキュメントを参照してください。

fargate-app.yaml
---
apiVersion: v1
kind: Namespace
metadata:
name: fargate-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: fargate-app-deployment
namespace: fargate-app
labels:
app: api
spec:
replicas: 1
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/arch
operator: In
values:
- amd64
containers:
- name: api
image: 000000000000.dkr.ecr.ap-northeast-1.amazonaws.com/api:latest
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
nodeSelector:
kubernetes.io/os: linux
---
apiVersion: v1
kind: Service
metadata:
name: fargate-app-service
namespace: fargate-app
labels:
app: api
spec:
selector:
app: api
ports:
- protocol: TCP
port: 80
targetPort: 80
type: NodePort
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: fargate-app-ingress
namespace: fargate-app
annotations:
alb.ingress.kubernetes.io/scheme: internal
alb.ingress.kubernetes.io/target-type: ip
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: fargate-app-service
port:
number: 80

マニフェストファイルを適用します。

Terminal window
kubectl apply -f fargate-app.yaml

デプロイされたリソースを確認します。

Terminal window
$ kubectl get all -n fargate-app
NAME READY STATUS RESTARTS AGE
pod/fargate-app-deployment-6db55f9b7b-4hp8z 1/1 Running 0 55s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/fargate-app-service NodePort 10.100.190.97 <none> 80:31985/TCP 6m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/fargate-app-deployment 1/1 1 1 6m
NAME DESIRED CURRENT READY AGE
replicaset.apps/fargate-app-deployment-6db55f9b7b 1 1 1 6m
ℹ️ Note

ALB のプロビジョニングには 10 分以上かかる場合があります。

API のテスト

ALB の DNS 名を取得します。

Terminal window
kubectl describe ingress -n fargate-app fargate-app-ingress

出力例。

Name: fargate-app-ingress
Labels: <none>
Namespace: fargate-app
Address: internal-k8s-fargatea-fargatea-0579eb4ce2-1731550123.ap-northeast-1.elb.amazonaws.com
Ingress Class: alb
Default backend: <default>
Rules:
Host Path Backends
---- ---- --------
*
/ fargate-app-service:80 (192.168.4.97:80)
Annotations: alb.ingress.kubernetes.io/scheme: internal
alb.ingress.kubernetes.io/target-type: ip
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfullyReconciled 4m17s ingress Successfully reconciled

API エンドポイントをテストします。

Terminal window
curl internal-k8s-fargatea-fargatea-xxxxxxxxxx-xxxxxxxxxx.ap-northeast-1.elb.amazonaws.com

期待される出力。

{"message":"Hello world!"}

EKS クラスターの削除

EKS クラスターと関連リソースが不要になったら、以下の手順で削除します。

デプロイしたアプリケーションを削除し、AWS Load Balancer Controller をアンインストールします。

Terminal window
kubectl delete -f fargate-app.yaml
helm uninstall aws-load-balancer-controller -n kube-system

AWSLoadBalancerControllerIAMPolicy の ARN を取得し、デタッチします。

Terminal window
arn=$(aws iam list-policies --scope Local \
| jq -r '.Policies[] | select(.PolicyName == "AWSLoadBalancerControllerIAMPolicy").Arn')
aws iam detach-role-policy \
--role-name AmazonEKSLoadBalancerControllerRole \
--policy-arn $arn

AWS Load Balancer Controller に関連付けたサービスアカウントを削除します。

Terminal window
eksctl delete iamserviceaccount \
--region ap-northeast-1 \
--cluster eks-fargate-cluster \
--namespace kube-system \
--name aws-load-balancer-controller

セットアップ時に作成した Fargate プロファイルを削除します。

Terminal window
aws eks delete-fargate-profile \
--cluster-name eks-fargate-cluster \
--fargate-profile-name fargate-app-profile
aws eks delete-fargate-profile \
--cluster-name eks-fargate-cluster \
--fargate-profile-name fp-default

AmazonEKSFargatePodExecutionRolePolicy を取得してデタッチします。

Terminal window
arn=$(aws iam list-policies --scope AWS \
| jq -r '.Policies[] | select(.PolicyName == "AmazonEKSFargatePodExecutionRolePolicy").Arn')
aws iam detach-role-policy \
--role-name eksctl-eks-fargate-cluster-FargatePodExecutionRole-xxxxxxxxxxxxx \
--policy-arn $arn

eksctl を使ってクラスターを削除します。

Terminal window
eksctl delete cluster \
--region ap-northeast-1 \
--name eks-fargate-cluster

付録: 削除時のトラブルシューティング

AWS Load Balancer Controller の Ingress を削除できない場合は、こちらで説明されているように、finalizer を手動で削除する必要があります。

Terminal window
kubectl patch ingress fargate-app-ingress -n fargate-app -p '{"metadata":{"finalizers":[]}}' --type=merge

このコマンドにより、Kubernetes が Ingress リソースの削除を完了できるようになります。

まとめ

プライベートサブネットの VPC、EKS Fargate クラスター、AWS Load Balancer Controller を使い、FastAPI コンテナを内部 ALB の背後で実行できます。eksctl create cluster--fargate オプションによってワーカーノードの管理が不要になり、Ingress の alb.ingress.kubernetes.io/scheme: internal アノテーションによってアプリケーションのエントリーポイントをパブリックインターネットから遮断できます。

Load Balancer Controller が内部 ALB 用のサブネットを検出できるよう、プライベートサブネットには kubernetes.io/role/internal-elb=1 タグが必要です。

VPC エンドポイント、踏み台ホスト、コントローラーを構築した後は、同じネットワークと IAM の基盤を再利用し、マニフェストと kubectl apply で別のサービスもデプロイできます。

About the author

Takahiro Iwasa

Takahiro Iwasa

Software Developer

This blog shares technical notes from hands-on projects—architecture, implementation, and AWS service integrations.