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

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

プライベートサブネット内のEKS Fargateで、内部ALBの背後にコンテナを実行し、どの層においてもパブリックに公開しない構成にします。

Takahiro Iwasa
20 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プライベートクラスタが安全に通信できるよう、必要な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-code.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インスタンスを利用できます。パブリックアクセスが無効になっている場合でも、この踏み台ホストを使えば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、VPCサービスをセットアップ・管理するためのより広い権限が必要な場合は、追加のポリシーをアタッチします。最小権限の原則に関するベストプラクティスについては公式ドキュメントを参照してください。

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を使用していることを確認してください。最新の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 Session Managerを使用します。これによりSSHキーペアが不要になり、安全で監査可能なアクセスが実現します。

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

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

Session Manager接続のため、インスタンスのIAMロールにAmazonSSMManagedInstanceCoreポリシーがアタッチされていることを確認してください。

AWS CLIを最新バージョンに更新する

最新のAWSサービスとの互換性を確保するため、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

これで、kubectleksctlがインストールされ、踏み台EC2インスタンスからEKSクラスタを管理・操作できる状態になりました。

EKS

EKSクラスタの作成

--fargateオプションを指定したeksctlでEKSクラスタを作成します。このクラスタは、ワーカーノードを必要とせずにPodを管理するためにFargateを使用します。

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

ℹ️ 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実行時に以下のエラーが発生する場合。

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ユーザーやロールにアクセス権を付与します。デフォルトでは、クラスタを作成した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

これにより、追加のユーザーやロールが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

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

AWS Load Balancer Controllerのインストールが完了し、アプリケーションコンテナは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.

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

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

この例では、デモ用のシンプルなAPIを作成するためにFastAPIを使用します。

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

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 eks/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を構築することで、どの層でもパブリックに公開せずに、内部ALBの背後でFastAPIコンテナを実行できるようになりました。この構成全体を成り立たせているのは、eksctl create cluster--fargateフラグと、Ingressのalb.ingress.kubernetes.io/scheme: internalアノテーションです。Fargateはワーカーノードのキャパシティプランニングを完全に不要にし、内部ALBのスキームはPodのプライベートサブネット配置に合わせて、エントリーポイント自体をパブリックインターネットから遮断します。プライベートサブネットにkubernetes.io/role/internal-elb=1のタグを付ける作業は見落としがちですが必須の手順です。これがないと、Load Balancer Controllerは内部ALBの有効なターゲットとなるサブネットを判別できません。VPCエンドポイント、踏み台ホスト、コントローラーが整った後は、新しいサービスをデプロイする作業はマニフェストとkubectl applyだけで済み、ネットワークとIAMの基盤はすでにそれをカバーしています。

About the author

Takahiro Iwasa

Takahiro Iwasa

Software Developer

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