AWSの色んなサービスを意図的に使って、サンプルWebアプリを構築してみているのですが、今回は part2 ということで、「EKSでRDSにアクセスするWEB APIサーバを構築」していきたいと思います。
- part1: RDS 環境構築
- part2: EKSでRDSにアクセスするWEB APIサーバを構築(今回)
- part3: CodeBuild・CodePipelineを使ってデリバリーパイプラインを導入
本記事で対応する内容
この記事では、以下をやってみました。
- API サーバの Docker イメージを Amazon ECR にプッシュする
- Amazon EKS クラスタを作成する
- EKS クラスタに Docker コンテナをデプロイする
- Docker コンテナ(POD)から RDS にアクセスする
作業用 IAM ユーザを作成
IAM ユーザ(sample-admin
)を作成します。
-
IAM コンソール >
ユーザ
>ユーザを追加
から、以下の設定でユーザを作成する- ユーザ名:
sample-admin
- プログラムによるアクセス: チェック
- アクセス許可の設定: なし
- タグ: なし
- ユーザ名:
最初は何も権限がないですが、後で必要なポリシーをアタッチしていきます。
また、ユーザを作成した際に表示される、aws_access_key_id
とaws_secret_access_key
は後で使うのでメモおきます。
ECR に Docker イメージをプッシュ
ECR でリポジトリを作成
アプリの Docker イメージをホストするために ECR > リポジトリを作成
から、以下の設定でプライベートリポジトリを作成しました。
- 可視性設定: プライベート
- リポジトリ名:
sample-api
- タグのイミュータビリティ: 有効
- イメージスキャン: 有効
- KMS 暗号化: 有効
- 暗号化設定をカスタマイズする: チェックなし
IAM ユーザに ECR 関連の権限を付与
ECRを管理するためのポリシーを作成し、IAM ユーザにアタッチします。
-
IAM コンソール >
ポリシー
>ポリシーの作成
から、以下の設定でポリシーを作成する- アクセス許可
- サービス:
Elastic Container Registry
を選択 - アクション: 全て
- リソース:
arn:aws:ecr:*:xxx:repository/sample-api
(先ほど作ったECRのリポジトリ)
- サービス:
- タグ: なし
- ポリシー名:
manage-ecr-sample-api-policy
- アクセス許可
Docker イメージの作成
Node.js
+Express
+TypeScript
+MariaDB
という構成のシンプルな WEB API サーバで、エンドポイントは以下の二つだけです。
-
POST /comments
: コメントを新規登録する -
GET /comments/:id
: 指定されたIDのコメントを取得する
アプリ構築は本筋ではないので、別記事(Node.js with TypeScriptでDBアクセスするWebアプリを作る)にしました。
この API サーバのDockerfile
は以下の通りです。
FROM node:14.17.0
WORKDIR /usr/src/app
COPY package.json .
COPY tsconfig.json .
COPY src ./src
RUN npm install
RUN npx tsc
EXPOSE 3000
CMD ["node", "dist/index.js"]
依存関係を解決(npm install
)して、TypeScriptをコンパイル(npx tsc
)し、Node.js
でindex.js
を実行するだけのシンプルな内容です。
このDockerfile
をもとに、Docker イメージを作成したいと思います。
# イメージの作成
docker build . -t sample-api:1.0.0
ECR へプッシュ
先ほど作成した、Docker イメージを ECR にプッシュしたいと思います。
手順は 公式ドキュメント に従っています。
まずは、こちら を参考に、ECR レジストリに対して Docker クライアントを認証します。
~/.aws/credentials
に以下のようにプロファイルを追加し、
[sample-admin]
aws_access_key_id = xxxx
aws_secret_access_key = xxxx
以下のコマンドで、ECR レジストリに対して Docker クライアントを認証します。
aws ecr get-login-password --region us-west-2 --profile sample-admin | docker login --username AWS --password-stdin xxxx.dkr.ecr.us-west-2.amazonaws.com
> Login Succeeded
あとは、先ほど作成したイメージにタグをつけて、プッシュするだけです。
# タグを追加
docker tag sample-api:1.0.0 xxxx.dkr.ecr.us-west-2.amazonaws.com/sample-api:1.0.0
# ECRにプッシュ
docker push xxxx.dkr.ecr.us-west-2.amazonaws.com/sample-api:1.0.0
コンソールで確認すると、無事イメージがプッシュされていました。
EKS クラスタを作成
IAM ユーザに EKS クラスタを作成する権限を付与
少しややこしいのですが、登場人物は二人です。
- コンソールから
aws eks
コマンドを実行する IAM ユーザ - EKS サービスに
PassRole
で渡すロール
まずは、EKS サービスに渡すロール IAM ロールを作成します。
-
IAM コンソール >
ロール
>ロールの作成
から、以下の設定でロールを作成する- サービス:
EKS
- ユースケース:
EKS - Cluster
- ポリシー
AmazonEKSClusterPolicy
AmazonEKSVPCResourceController
- ポリシー
- タグ: なし
- ロール名:
manage-sample-eks-cluster-role
- サービス:
次に、IAM ユーザにアタッチするための「EKS クラスタを作成するポリシー」を作成します。
既存のAmazonEKSClusterPolicy
というポリシーはeks:CreateCluster
などの必要な権限を含まないため、新規に作成しました。
-
IAM コンソール >
ポリシー
>ポリシーの作成
から、以下の設定でポリシーを作成する。多少絞ったつもりですが、過剰に付与している部分もありそうです)- JSON
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "iam:GenerateCredentialReport", "iam:GetContextKeysForCustomPolicy", "iam:GetAccountPasswordPolicy", "iam:SimulateCustomPolicy", "iam:GetServiceLastAccessedDetailsWithEntities", "iam:GetAccountAuthorizationDetails", "iam:GetCredentialReport", "iam:GetServiceLastAccessedDetails", "iam:GetOrganizationsAccessReport", "iam:ListAttachedRolePolicies", "iam:CreateServiceLinkedRole", "iam:ListRoles", "iam:GetRole", "ec2:*" ], "Resource": "*" }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": [ "eks:ListClusters", "eks:DescribeAddonVersions", "eks:CreateCluster" ], "Resource": "*" }, { "Sid": "VisualEditor2", "Effect": "Allow", "Action": "eks:*", "Resource": [ "arn:aws:eks:*:xxx:addon/*/*/*", "arn:aws:eks:*:xxx:identityproviderconfig/*/*/*/*", "arn:aws:eks:*:xxx:fargateprofile/*/*/*", "arn:aws:eks:*:xxx:nodegroup/*/*/*", "arn:aws:eks:*:xxx:cluster/*" ] } ] }
- ポリシー名:
manage-eks-policy
- タグ: なし
- JSON
また、IAM ユーザがPassRole
できるようにするためのポリシーを作成します。
-
IAM コンソール >
ポリシー
>ポリシーの作成
から、以下の設定でポリシーを作成する- JSON
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": "iam:PassRole", "Resource": "arn:aws:iam::xxx:role/manage-sample-eks-cluster-role" } ] }
- タグ: なし
- ポリシー名:
pass-manage-sample-eks-cluster-role-policy
- JSON
最後に、IAM ユーザ(sample-admin
)には、今作った二つのポリシーをアタッチします。
manage-eks-policy
pass-manage-sample-eks-cluster-role-policy
これで IAM ユーザへの権限付与は完了しました。
public サブネットを二つ作成
一つのサブネットで EKS クラスタを作成しようとすると以下のエラーが発生します。
An error occurred (InvalidParameterException) when calling the CreateCluster operation: Subnets specified must be in at least two different AZs
異なる AZ に所属するサブネットが必要みたいです。なので、public サブネットを二つ作成したいと思います。
part1 の記事 で VPC と public サブネットを一つ作成済みなので、その続きでもう一つ作成します。
-
VPC コンソール >
サブネット
>サブネットを作成
から、以下の設定でサブネットを作成する- VPC ID: part1 の記事で作った VPC ID(
sample-vpc
) - サブネット名:
sample-public-subnet2
- AZ:
us-west-2b
(一つ目と異なるAZ) - IPv4 CIDR ブロック:
10.0.3.0/24
(一つ目と異なる範囲)
- VPC ID: part1 の記事で作った VPC ID(
- 作成したサブネットを開く >
アクション
>自動割り当てIP設定の変更
>パブリック IPv4 アドレスを自動割り当て
にチェック
EKS クラスタを作成
前準備がとても大変でしたが、やっと EKS クラスタを作成する準備ができました。
公式ドキュメントには三つの方法が紹介されています。
いずれ、CodePipeline で実行することを考え、CLIが良いのですが、eksctl
とAWS CLI
のどちらを使うかは正直迷います。
ググっていると、もともとサードパーティ製のeksctl
がメインだったところに、AWS CLI
側が同等の機能を追加提供して追いついてきたという経緯があるようなので、公式が出しているツールであるAWS CLI
を使ってみようと思います。
AWS CLI
のインストールは、こちら に従って実施します。
クラスタの作成コマンド自体は簡単で、以下の通りです。
--resources-vpc-config
で設定しているサブネットは先ほど作成した public サブネットを指定しています。また、セキュリティグループは、part1の記事 で作成したパブリックアクセス用のセキュリティグループで、RDS 用のセキュリティグループに対してアクセスできる権限を持たせてあります。
aws eks create-cluster \
--region us-west-2 \
--name sample-eks-cluster \
--kubernetes-version 1.20 \
--role-arn arn:aws:iam::xxx:role/manage-sample-eks-cluster-role \
--resources-vpc-config subnetIds=subnet-xxx,subnet-xxx,securityGroupIds=sg-xxx \
--profile sample-admin
> {
> "cluster": {
> "name": "sample-eks-cluster",
> "arn": "arn:aws:eks:us-west-2:xxx:cluster/sample-eks-cluster",
> "createdAt": "2021-07-04T12:20:16.524000+09:00",
> "version": "1.20",
> "roleArn": "arn:aws:iam::xxx:role/manage-sample-eks-cluster-role",
> "resourcesVpcConfig": {
> "subnetIds": [
> "subnet-xxx",
> "subnet-xxx"
> ],
> "securityGroupIds": [
> "sg-xxx"
> ],
> "vpcId": "vpc-xxx",
> "endpointPublicAccess": true,
> "endpointPrivateAccess": false,
> "publicAccessCidrs": [
> "0.0.0.0/0"
> ]
> },
> "kubernetesNetworkConfig": {
> "serviceIpv4Cidr": "172.xx.xx.xx/16"
> },
> "logging": {
> "clusterLogging": [
> {
> "types": [
> "api",
> "audit",
> "authenticator",
> "controllerManager",
> "scheduler"
> ],
> "enabled": false
> }
> ]
> },
> "status": "CREATING",
> "certificateAuthority": {},
> "platformVersion": "eks.1",
> "tags": {}
> }
> }
以下のコマンドで確認できます。
10分程度経過すると、無事クラスタが作成されました。
aws eks describe-cluster \
--query "cluster.status" \
--name sample-eks-cluster \
--region us-west-2 \
--profile sample-admin
> "ACTIVE"
EKS ノードグループを作成
現状、クラスタの中身は空っぽなので、ノードグループを作成したいと思います。
ノード用の IAM ロールを作成
まず、こちらに従って、 IAM ロールを作成します。
-
IAM コンソール >
ロール
>ロールの作成
から、以下の設定でロールを作成する- サービス:
EC2
- ユースケース:
EC2
- ポリシー
AmazonEKSWorkerNodePolicy
AmazonEC2ContainerRegistryReadOnly
AmazonEKS_CNI_Policy
- タグ: なし
- ロール名:
node-instance-role
- サービス:
次に、IAM ユーザが上記のロールをPassRole
できるようにするための IAM ポリシーを作成します。
-
IAM コンソール >
ポリシー
>ポリシーの作成
から、以下の設定でポリシーを作成する- JSON
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": "iam:PassRole", "Resource": "arn:aws:iam::xxx:role/node-instance-role" } ] }
- タグ: なし
- ポリシー名:
pass-node-instance-role-policy
- JSON
最後に、作成したポリシーを IAM ユーザ(sample-admin
)にアタッチします。
キーペアの作成
公式ドキュメントを参考に、SSH キーペアを事前に作成します。
-
EC2 コンソール >
キーペア
>キーペアを作成
から、以下の設定でキーペアを作成- 名前:
sample-eks-node-group-key
- Private key file format:
ppm
- 名前:
ノードグループを作成
ノードグループの作成は、以下のコマンドで実行できます。
オプションの意味は公式ドキュメントを見るとわかると思います。
- POD にセキュリティグループをアタッチできるようにするために、考慮事項に書いてあるインスタンスタイプ(
m5.large
)を選択 - EC2 にアクセスするための
ec2SshKey
に先ほど作成したキーペアを指定 - サブネットにはコントロールプレーンに割り当てたサブネットを指定(本当は良くないんだろうけど)
aws eks create-nodegroup \ --cluster-name sample-eks-cluster \ --nodegroup-name sample-eks-node-group \ --scaling-config minSize=1,maxSize=2,desiredSize=1 \ --disk-size 20 \ --subnets subnet-xxx subnet-xxx \ --instance-types m5.large \ --ami-type AL2_x86_64 \ --remote-access ec2SshKey=sample-eks-node-group-key \ --node-role arn:aws:iam::xxx:role/node-instance-role \ --region us-west-2 \ --profile sample-admin > { > "nodegroup": { > "nodegroupName": "sample-eks-node-group", > "nodegroupArn": "arn:aws:eks:us-west-2:xxx:nodegroup/sample-eks-cluster/sample-eks-node-group/xxx-xxx-xxx-xxx-xxx", > "clusterName": "sample-eks-cluster", > "version": "1.20", > "releaseVersion": "1.20.4-20210628", > "createdAt": "2021-07-04T20:05:59.695000+09:00", > "modifiedAt": "2021-07-04T20:05:59.695000+09:00", > "status": "CREATING", > "capacityType": "ON_DEMAND", > "scalingConfig": { > "minSize": 1, > "maxSize": 2, > "desiredSize": 1 > }, > "instanceTypes": [ > "m5.large" > ], > "subnets": [ > "subnet-xxx", > "subnet-xxx" > ], > "remoteAccess": { > "ec2SshKey": "sample-eks-node-group-key" > }, > "amiType": "AL2_x86_64", > "nodeRole": "arn:aws:iam::xxx:role/node-instance-role", > "diskSize": 20, > "health": { > "issues": [] > }, > "tags": {} > } > }
数分待つと、ノードグループが作成されました。
aws eks describe-nodegroup \
--cluster-name sample-eks-cluster \
--nodegroup-name sample-eks-node-group \
--region us-west-2 \
--profile sample-admin
> {
> "nodegroup": {
> "nodegroupName": "sample-eks-node-group",
> "clusterName": "sample-eks-cluster",
> "status": "ACTIVE",
> }
> }
アプリケーションコンテナのデプロイ
コンテナデプロイには、AWS CLI
ではなくkubectl
を利用する必要があるようです。
kubectl をインストール
公式ドキュメントに従って、kubectl
をインストールします。
作成したクラスタにkubectl
でアクセスするための、kubeconfig
ファイルを作成します。既存の場合は、新しいクラスタ用の定義を追加してくれます。
aws eks --region us-west-2 update-kubeconfig --name sample-eks-cluster --profile sample-admin
> Added new context arn:aws:eks:us-west-2:xxx:cluster/sample-eks-cluster to /Users/xxx/.kube/config
無事、設定できたようです。
kubectl get svc
> NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
> kubernetes ClusterIP 172.20.0.1 <none> 443/TCP 7m
POD から RDS にアクセス許可
POD(内のコンテナ) から RDS にアクセスできるようにするためには、POD に専用のセキュリティグループをアタッチして、RDS 側のセキュリティグループのインバウンド設定で、POD 側のセキュリティグループからのMYSQL/Aurora: TCP(3306)
アクセスを許可する必要があります。
-
EC2 コンソール >
セキュリティグループ
> RDS 側のセキュリティグループを選択 > インバウンドルール > Edit inbound rules- タイプ: MySQL/Aurora(TCP:3306)
- ソース: POD側のセキュリティグループ
-
partの記事で作成した
sample-public-securitygroup
を利用することにしました。
-
partの記事で作成した
POD にセキュリティグループをアタッチするポリシーを設定
こちら を参考に amazon-k8s-cni のバージョンを1.7.7以上にあげます。
# バージョン確認(事前)
kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2
> amazon-k8s-cni-init:v1.7.5-eksbuild.1
> amazon-k8s-cni:v1.7.5-eksbuild.1
# インストーラダウンロード
curl -o aws-k8s-cni.yaml https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/release-1.7/config/v1.7/aws-k8s-cni.yaml
# 適用
kubectl apply -f aws-k8s-cni.yaml
# バージョン確認(事後)
kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2
> amazon-k8s-cni-init:v1.7.10
> amazon-k8s-cni:v1.7.10
POD の ENI を有効にします。
kubectl set env daemonset aws-node -n kube-system ENABLE_POD_ENI=true
以下のコマンドで、クラスタ作成時に自動作成されたセキュリティグループのIDを取得します。
aws eks describe-cluster \
--name sample-eks-cluster \
--query "cluster.resourcesVpcConfig.clusterSecurityGroupId" \
--output text \
--region us-west-2 \
--profile sample-admin
> sg-xxx
api-sg-policy.yml
ファイルを作成し、自分で作ったPOD用のセキュリティグループと先ほど取得した自動生成されたセキュリティグループを指定します。
apiVersion: vpcresources.k8s.aws/v1beta1
kind: SecurityGroupPolicy
metadata:
name: sample-api-sg-policy
spec:
podSelector:
matchLabels:
app: sample-api-pod
securityGroups:
groupIds:
- sg-xxx # 自分でPOD用に作ったセキュリティグループ
- sg-xxx # クラスタ作成時に自動生成されたセキュリティグループ
最後に、適用します。
kubectl apply -f ./api/api-sg-policy.yml
> securitygrouppolicy.vpcresources.k8s.aws/sample-api-sg-policy created
これで、PODを作成すると、二つのセキュリティグループがアタッチされるようになります。
POD をデプロイ
api-deployment.yml
を作成します。
ポイントは、以下だと思います。
-
template
で Pod のテンプレートを定義している - Pod は
3000
ポートを露出する - 利用するイメージは ECR から取ってくる
apiVersion: apps/v1 kind: Deployment metadata: name: sample-api-deployment spec: replicas: 1 # お金がかかるので selector: matchLabels: app: sample-api-pod template: metadata: labels: app: sample-api-pod spec: containers: - name: sample-api-container image: xxx.dkr.ecr.us-west-2.amazonaws.com/sample-api:1.0.0 env: - name: DB_HOST value: sample-database.xxx.us-west-2.rds.amazonaws.com - name: DB_USER value: admin - name: DB_PASSWORD value: xxx - name: DB_DATABASE value: sampledb ports: - protocol: TCP containerPort: 3000
上記のファイルを適用します。
kubectl apply -f ./api/api-deployment.yml
> deployment.apps/sample-api-deployment created
POD の状態を確認したいときは、以下を実行します。
# 一覧確認
kubectl get pods -o wide
# 起動ログ確認
kubectl describe pods
複数の POD を一つにまとめて外部に公開
api-service.yml
を作成し、複数の POD をネットワーク的に一つに取りまとめ、ELBで外部に公開したいと思います。
POD の3000
ポートを80
ポートで公開するように設定しました。ここ に詳しく書いてあります。
apiVersion: v1
kind: Service
metadata:
name: sample-api-service
spec:
type: LoadBalancer
selector:
app: sample-api-pod
ports:
- protocol: TCP
port: 80
targetPort: 3000
ファイルを適用します。
kubectl apply -f ./api/api-service.yml
以下でエンドポイントを確認します。
# エンドポイント確認
kubectl get service sample-api-service
> NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
> sample-api-service LoadBalancer 172.xx.xx.xx xxx-xxx.us-west-2.elb.amazonaws.com 80:30613/TCP 7s
# 起動ログ確認
kubectl describe services
動作確認
最後に、公開されたAPIにアクセスして、無事動いてることを確認したいと思います。
先ほど確認したエンドポイントをcURLで叩いてみます。
curl -X POST http://xxx-xxx.us-west-2.elb.amazonaws.com/comments -H "Content-type: application/json" -d '{ "comment" : "new comment" }'
{"id":3,"comment":"new comment"}
curl http://xxx-xxx.us-west-2.elb.amazonaws.com/comments/3
{"id":3,"comment":"new comment"}
無事、APIを叩くことができました。
お掃除
検証目的だった場合はちゃんと最後にノードグループとクラスタを削除しておきましょう。
私は、一週間ほど放置していたら、16.42USDほど請求されてしまいました(涙)
# POD/サービスの削除
kubectl delete -f ./api/api-sg-policy.yml
kubectl delete -f ./api/api-deployment.yml
kubectl delete -f ./api/api-service.yml
# ノードグループの削除
aws eks delete-nodegroup \
--nodegroup-name sample-eks-node-group \
--cluster-name sample-eks-cluster \
--region us-west-2 \
--profile sample-admin
# クラスターの削除
aws eks delete-cluster \
--name sample-eks-cluster \
--region us-west-2 \
--profile sample-admin
トラブルシューティング
IAM ユーザが IAM ロールにPassRole
できない
- エラーメッセージ
error occurred (AccessDeniedException) when calling the CreateCluster operation: User: arn:aws:iam::xxx:user/sample-admin is not authorized to perform: iam:PassRole on resource: arn:aws:iam::xxx:role/sample-eks-role
- 対処
- PassRoleするための IAM ポリシーを作成して、IAM ユーザにアタッチ
ノードグループ作成時に自動的に IP アドレスがアサインできない
- エラーメッセージ
One or more Amazon EC2 Subnets of [subnet-xxx, subnet-xxx] for node group sample-eks-node-group does not automatically assign public IP addresses to instances launched into it. If you want your instances to be assigned a public IP address, then you need to enable auto-assign public IP address for the subnet. See IP addressing in VPC guide: https://docs.aws.amazon.com/vpc/latest/userguide/vpc-ip-addressing.html#subnet-public-ip
- 対処
クラスタを作成できない
- エラーメッセージ
An error occurred (InvalidParameterException) when calling the CreateCluster operation: The provided role doesn't have the Amazon EKS Managed Policies associated with it. Please ensure the following policies [arn:aws:iam::aws:policy/AmazonEKSClusterPolicy] are attached
- 対処
- クラスタマネジメント用の IAM ロールに
AmazonEKSClusterPolicy
ポリシーをアタッチする- IAM ユーザにアタッチして PassRole すればいいのかなと思ったのですが、だめでした
- クラスタマネジメント用の IAM ロールに
ノードグループ作成時にNodeCreationFailure
エラー
- エラーメッセージ
Unhealthy nodes in the kubernetes cluster
- 対処
-
こちら を参考にワーカーノード用のロール(
node-instance-role
)にAmazonEKS_CNI_Policy
をアタッチ
-
こちら を参考にワーカーノード用のロール(
kubectl apply
でエラー
- エラーメッセージ
The Pod "sample-api-pod" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)
- 対処
- 一旦、既存の pod を削除する
kubectl delete pod sample-api-pod
- 一旦、既存の pod を削除する
kubectl get svc でエラー
- エラーメッセージ
Unable to connect to the server: dial tcp: lookup xxx.gr7.us-west-2.eks.amazonaws.com on xx.xx.xx.xx:xx: no such host
- 原因
- クラスタを作り直したのに、
kubeconfig
を更新し忘れていたため
- クラスタを作り直したのに、
- 対処
- 以下を再実行する
aws eks update-kubeconfig \ --region us-west-2 \ --name sample-eks-cluster \ --profile sample-admin
- 以下を再実行する
アプリのコンテナから RDS が見えない
- エラーメッセージ
SqlError: (conn=-1, no: 45012, SQLState: 08S01) Connection timeout: failed to create socket after 10006ms at Object.module.exports.createError (/usr/src/app/node_modules/mariadb/lib/misc/errors.js:55:10) at Timeout._connectTimeoutReached [as _onTimeout] (/usr/src/app/node_modules/mariadb/lib/connection.js:1139:14) at listOnTimeout (internal/timers.js:557:17) at processTimers (internal/timers.js:498:7)
- 原因
- POD 側のセキュリティグループが、 RDS 側のセキュリティグループにアクセスする権限がないため
- 対処
- POD 用のセキュリティグループを作成し、RDS 側のセキュリティグループのインバウンド設定で、そこからの
MYSQL/Aurora: TCP(3306)
アクセスを許可する - POD に対してセキュリティグループをアタッチする。この際、二種類のセキュリティグループをアタッチする必要があったので要注意です。
- 一種類目:作成したPOD 用のセキュリティグループ
- 二種類目:クラスタ作成時に自動生成されるセキュリティグループ
- POD 用のセキュリティグループを作成し、RDS 側のセキュリティグループのインバウンド設定で、そこからの
POD にセキュリティグループをアタッチしようとするとエラーが出る
- エラーメッセージ
Insufficient vpc.amazonaws.com/pod-eni.
- 原因
- こちらの考慮事項のいずれかに違反している
- 対処
- 元々、クラスタ作成時のインスタンスのタイプに
t3.medium
を指定してたがt3
系は対象外だったので、m5.large
に変更 - クラスターを操作するロール(
manage-sample-eks-cluster-role
)に対して、AmazonEKSVPCResourceController
ポリシーをアタッチする。ノード用のロールではないことに注意
- 元々、クラスタ作成時のインスタンスのタイプに
POD 作成時にワーニングが出る
- ワーニングメッセージ
sandbox: rpc error: code = Unknown desc = [failed to set up sandbox container "xxx" network for pod "sample-api-deployment-xxx-bthc2": networkPlugin cni failed to set up pod "sample-api-deployment-xxx-bthc2_default" network: add cmd: Error received from AddNetwork gRPC call: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial tcp 127.0.0.1:50051: connect: connection refused", failed to clean up sandbox container "xxx" network for pod "sample-api-deployment-xxx-bthc2": networkPlugin cni failed to teardown pod "sample-api-deployment-xxx-bthc2_default" network: del cmd: error received from DelNetwork gRPC call: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial tcp 127.0.0.1:50051: connect: connection refused"]
- 原因
- 対処
- amazon-k8s-cni のバージョンを1.7.7以上にあげる(本文に詳細記載)
- なお、このワーニングが出ていても、PODは起動できており、問題なく動いてたので、あまり気にしなくてもいいかもしれません。
最後に
今回なるべく一つ一つ、自分で設定しながらEKSの環境を構築してみようと思ったのですが、一歩進むたびに次のエラーが発生して非常に大変でした。あと、Consoleで色々やってる部分は、AWS CloudFormation なりでコード化しないと手作業ではやってられないレベルですね。EKS を使いこなしている皆さんはすごいなーと思いました。
正直なところ、インフラに関してはフルマネージドなサービスを活用して、アプリの開発に専念したいので、スケーラブルな環境で Docker コンテナを動かしたいだけなら、ECS + Fragete で十分な気がしました。