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

VPC のセットアップ
VPC の作成
専用の VPC を作成します。
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-hostnamesVPC エンドポイントを利用する場合は、必ず 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 インスタンス用のパブリックサブネットを作成します。
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 にアタッチします。
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次に、ルートテーブルを作成してインターネットゲートウェイへのデフォルトルートを追加し、パブリックサブネットに関連付けます。
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-xxxxxxxxxxxxxxxxxVPC エンドポイントの追加
EKS プライベートクラスターが AWS サービスと通信できるよう、必要な VPC エンドポイントを作成します。詳細は公式ドキュメントを参照してください。
| Type | Endpoint |
|---|---|
| Interface | com.amazonaws.region-code.ecr.api |
| Interface | com.amazonaws.region-code.ecr.dkr |
| Interface | com.amazonaws.region-code.ec2 |
| Interface | com.amazonaws.region-code.elasticloadbalancing |
| Interface | com.amazonaws.region-code.sts |
| Gateway | com.amazonaws.region-code.s3 |
VPC エンドポイント用のセキュリティグループを作成します。
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 エンドポイントを作成します。
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 エンドポイントを作成します。
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 ロールを作成します。
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インスタンスプロファイルを作成します。
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-roleSession Manager での接続を許可するため、AmazonSSMManagedInstanceCore ポリシーをアタッチします。
aws iam attach-role-policy \ --role-name eks-fargate-bastion-ec2-role \ --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCoreこの例で使う EKS、EC2、IAM、CloudFormation の操作を許可する追加ポリシーをアタッチします。本番環境では、サービス認可リファレンスに基づいて権限を絞り込んでください。
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 に置き換えてください。詳細は公式ドキュメントを参照してください。
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 アカウントに切り替えます。
sh-4.2$ sudo su - ec2-userSession Manager で接続するには、インスタンスの IAM ロールに AmazonSSMManagedInstanceCore ポリシーが必要です。
AWS CLI を更新する
踏み台インスタンスの AWS CLI を更新します。
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"unzip awscliv2.zipsudo ./aws/install --bin-dir /usr/local/bin --install-dir /usr/local/aws-cli --updateインストールを確認します。
aws --versionkubectl のインストール
EKS クラスターを管理するため、踏み台インスタンスに kubectl をインストールします。
EKS クラスターのバージョンに対応する kubectl バイナリをダウンロードします。
curl -o kubectl https://s3.us-west-2.amazonaws.com/amazon-eks/1.24.7/2022-10-31/bin/linux/amd64/kubectlバイナリを実行可能にします。
chmod +x ./kubectlkubectl を PATH に追加します。
mkdir -p $HOME/bin && cp ./kubectl $HOME/bin/kubectl && export PATH=$PATH:$HOME/binecho 'export PATH=$PATH:$HOME/bin' >> ~/.bashrcインストールを確認します。
kubectl version --short --clienteksctl のインストール
EKS クラスターを作成・管理するため、eksctl をインストールします。
eksctl をダウンロードして展開します。
curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmpバイナリを PATH が通ったディレクトリに移動します。
sudo mv /tmp/eksctl /usr/local/binインストールを確認します。
eksctl versionこれで、踏み台 EC2 インスタンスから kubectl と eksctl を使って EKS クラスターを管理できます。
EKS
EKS クラスターの作成
eksctl に --fargate オプションを指定して EKS クラスターを作成します。Fargate が Pod を実行するため、自己管理型またはマネージド型のノードグループは不要です。
詳細な手順については公式ドキュメントを参照してください。
クラスタの作成にはおよそ20分以上かかる場合があります。
eksctl create cluster \ --name eks-fargate-cluster \ --region ap-northeast-1 \ --version 1.24 \ --vpc-private-subnets subnet-xxxxxxxxxxxxxxxxx,subnet-xxxxxxxxxxxxxxxxx \ --without-nodegroup \ --fargate作成後、クラスターを確認します。
$ kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEkubernetes 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 を更新します。
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"unzip awscliv2.zipsudo ./aws/install --bin-dir /usr/local/bin --install-dir /usr/local/aws-cli --updateコマンドを再試行します。
$ kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEkubernetes 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)を更新します。
aws eks update-kubeconfig \ --region ap-northeast-1 \ --name eks-fargate-clusterコマンドを再試行します。
$ kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEkubernetes ClusterIP 10.100.0.1 <none> 443/TCP 20mIAM ユーザーとロールの追加
クラスターの管理が作成者の 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 グループに追加するには、以下のコマンドを使います。
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 と接続済みネットワーク内に制限します。
プライベートクラスタエンドポイントの有効化にはおよそ10分かかる場合があります。
aws eks update-cluster-config \ --region ap-northeast-1 \ --name eks-fargate-cluster \ --resources-vpc-config endpointPublicAccess=false,endpointPrivateAccess=trueEKS コントロールプレーンのセキュリティグループで、踏み台 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.
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 クラスター間の接続をテストします。
$ kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEkubernetes ClusterIP 10.100.0.1 <none> 443/TCP 153mFargate プロファイルの作成
アプリケーションの名前空間に対応する Fargate プロファイルを作成します。
eksctl create fargateprofile \ --region ap-northeast-1 \ --cluster eks-fargate-cluster \ --name fargate-app-profile \ --namespace fargate-appAWS Load Balancer Controller のインストール
Application Load Balancer(ALB)の背後でアプリケーションコンテナを実行するため、AWS Load Balancer Controller をインストールします。
クラスターに IAM OIDC プロバイダーがない場合は作成します。
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 \ --approveAWS Load Balancer Controller のポリシーファイルをダウンロードします。
curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.4/docs/install/iam_policy.jsonIAM ポリシーを作成します。
aws iam create-policy \ --policy-name AWSLoadBalancerControllerIAMPolicy \ --policy-document file://iam_policy.jsonIAM サービスアカウントを作成します。
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 \ --approveHelm と Load Balancer Controller のインストール
Helm v3 をインストールします。
$ 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 1v3.10.3Load Balancer Controller をインストールします。
helm repo add eks https://aws.github.io/eks-chartshelm repo updatehelm 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
2022 年当時は必要な VPC エンドポイントが提供されていないため、コマンドに enableShield=false、enableWaf=false、enableWafv2=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.
デプロイを確認します。
$ kubectl get deployment -n kube-system aws-load-balancer-controllerNAME READY UP-TO-DATE AVAILABLE AGEaws-load-balancer-controller 2/2 2 2 105sこれで、クラスターからアプリケーション用の Application Load Balancer を作成できます。
サブネットへのタグ付け
内部ロードバランサー用であることを示すため、プライベートサブネットにタグを付けます。Kubernetes と AWS Load Balancer Controller がサブネットを識別するために必要です。
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 を作成します。
アプリケーションに必要な依存関係を定義します。
anyio==3.6.2click==8.1.3fastapi==0.88.0h11==0.14.0httptools==0.5.0idna==3.4pydantic==1.10.2python-dotenv==0.21.0PyYAML==6.0sniffio==1.3.0starlette==0.22.0typing_extensions==4.4.0uvicorn==0.20.0uvloop==0.17.0watchfiles==0.18.1websockets==10.4基本的な API エンドポイントを作成します。
from fastapi import FastAPI
app = FastAPI()
@app.get('/')def read_root(): return {'message': 'Hello world!'}アプリケーションコンテナをビルドするための Dockerfile を作成します。
FROM python:3.10-alpine@sha256:d8a484baabf7d2337d34cdef6730413ea1feef4ba251784f9b7a8d7b642041b3COPY ./src ./RUN pip install --no-cache-dir -r requirements.txtCMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]イメージの ECR へのプッシュ
アプリケーションイメージをビルドし、ECR にプッシュします。
ECR リポジトリを作成します。
aws ecr create-repository --repository-name apiリポジトリ URI を取得します。
uri=$(aws ecr describe-repositories | jq -r '.repositories[] | select(.repositoryName == "api") | .repositoryUri')Docker を ECR に対して認証します。
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 000000000000.dkr.ecr.ap-northeast-1.amazonaws.comイメージをビルド、タグ付け、プッシュします。
docker build .docker tag xxxxxxxxxxxx $uri:latestdocker push $uri:latestFargate へのデプロイ
Kubernetes マニフェストファイル fargate-app.yaml を作成します。
000000000000.dkr.ecr.ap-northeast-1.amazonaws.com/api:latest を実際のイメージ URI に置き換えてください。
AWS Load Balancer Controller v2.4 の仕様は、公式ドキュメントを参照してください。
---apiVersion: v1kind: Namespacemetadata: name: fargate-app---apiVersion: apps/v1kind: Deploymentmetadata: name: fargate-app-deployment namespace: fargate-app labels: app: apispec: 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: v1kind: Servicemetadata: name: fargate-app-service namespace: fargate-app labels: app: apispec: selector: app: api ports: - protocol: TCP port: 80 targetPort: 80 type: NodePort---apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: fargate-app-ingress namespace: fargate-app annotations: alb.ingress.kubernetes.io/scheme: internal alb.ingress.kubernetes.io/target-type: ipspec: ingressClassName: alb rules: - http: paths: - path: / pathType: Prefix backend: service: name: fargate-app-service port: number: 80マニフェストファイルを適用します。
kubectl apply -f fargate-app.yamlデプロイされたリソースを確認します。
$ kubectl get all -n fargate-appNAME READY STATUS RESTARTS AGEpod/fargate-app-deployment-6db55f9b7b-4hp8z 1/1 Running 0 55s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/fargate-app-service NodePort 10.100.190.97 <none> 80:31985/TCP 6m
NAME READY UP-TO-DATE AVAILABLE AGEdeployment.apps/fargate-app-deployment 1/1 1 1 6m
NAME DESIRED CURRENT READY AGEreplicaset.apps/fargate-app-deployment-6db55f9b7b 1 1 1 6mALB のプロビジョニングには 10 分以上かかる場合があります。
API のテスト
ALB の DNS 名を取得します。
kubectl describe ingress -n fargate-app fargate-app-ingress出力例。
Name: fargate-app-ingressLabels: <none>Namespace: fargate-appAddress: internal-k8s-fargatea-fargatea-0579eb4ce2-1731550123.ap-northeast-1.elb.amazonaws.comIngress Class: albDefault 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: ipEvents: Type Reason Age From Message ---- ------ ---- ---- ------- Normal SuccessfullyReconciled 4m17s ingress Successfully reconciledAPI エンドポイントをテストします。
curl internal-k8s-fargatea-fargatea-xxxxxxxxxx-xxxxxxxxxx.ap-northeast-1.elb.amazonaws.com期待される出力。
{"message":"Hello world!"}EKS クラスターの削除
EKS クラスターと関連リソースが不要になったら、以下の手順で削除します。
デプロイしたアプリケーションを削除し、AWS Load Balancer Controller をアンインストールします。
kubectl delete -f fargate-app.yamlhelm uninstall aws-load-balancer-controller -n kube-systemAWSLoadBalancerControllerIAMPolicy の ARN を取得し、デタッチします。
arn=$(aws iam list-policies --scope Local \| jq -r '.Policies[] | select(.PolicyName == "AWSLoadBalancerControllerIAMPolicy").Arn')
aws iam detach-role-policy \ --role-name AmazonEKSLoadBalancerControllerRole \ --policy-arn $arnAWS Load Balancer Controller に関連付けたサービスアカウントを削除します。
eksctl delete iamserviceaccount \ --region ap-northeast-1 \ --cluster eks-fargate-cluster \ --namespace kube-system \ --name aws-load-balancer-controllerセットアップ時に作成した Fargate プロファイルを削除します。
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-defaultAmazonEKSFargatePodExecutionRolePolicy を取得してデタッチします。
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 $arneksctl を使ってクラスターを削除します。
eksctl delete cluster \ --region ap-northeast-1 \ --name eks-fargate-cluster付録: 削除時のトラブルシューティング
AWS Load Balancer Controller の Ingress を削除できない場合は、こちらで説明されているように、finalizer を手動で削除する必要があります。
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 で別のサービスもデプロイできます。
Related posts
Cognito User Pools と OIDC で Slack サインインを実装する
Cognito user pool を OIDC 経由で Slack と連携させ、"Sign in with Slack" を Amplify で Next.js アプリケーションに組み込みます。
Lambda Web Adapter で FastAPI を AWS Lambda にデプロイする
FastAPI で書いた API バックエンドをコンテナ化し、Lambda Web Adapter と AWS CDK を使って単一の Lambda 関数へデプロイします。
API Gateway WebSocket:モック統合の実装
バックエンドの Lambda を使わず、モック統合のみで API Gateway WebSocket API を構築し、あらかじめ用意したレスポンスを返します。
CloudFront 署名付き URL 経由で S3 にアップロードする
CloudFront の署名付き URL を使い、独自ドメイン経由で S3 にアップロードする方法を紹介します。S3 の署名付き URL を直接使えない場合に有用です。
AWS EventBridge Scheduler:スケジュールに沿って EC2 を起動・停止する
Lambda を介さず、EventBridge Scheduler から EC2 API を直接呼び出し、cron スケジュールに従って EC2 インスタンスを起動・停止します。
