Kubernetes(EKS)を使用したマイクロサービスを作成してみたいんだ
マイクロサービスに入門したい えがわ です。
今までECSでモノリスなアプリケーションしか作成したことがなかったので、単純に構築してみたいという気持ち一心で望みます。
通常マイクロサービスは「ドメイン駆動設計で分割して~」など、ビジネスロジック基づきアーキテクチャを慎重に考えます。
ですが、今回はただの自習なので作りたいように作ります。
目指すもの
今回はユーザーサービス(user-service)と製品サービス(product-service)を実装します。
コンピューティングはFargateを選択し、パスでルーティングしたいためApplication Load Balancerを使用します。
ソースはこちらに置いています。
環境
- Ubuntu 22.04.4 LTS(WSL2)
- kubectl: v1.31.0
- eksctl: 0.189.0
やってみる
今回使用するプログラムはこちらです。
import express, { Request, Response } from 'express';
const app = express();
const port = 3000;
app.get('/users', (req: Request, res: Response) => {
res.json([{ id: 1, name: 'John Doe' }, { id: 2, name: 'Tom Jelly' }]);
});
app.get('/healthz', (req, res) => {
res.status(200).send('OK');
});
app.listen(port, () => {
console.log(`User Server running at port:${port}`);
});
※製品サービスは省略
どちらもサービスもデータベースは使用せず、固定の値を返すようにしています。
データベース周りの実装は次回以降で行う予定です。
また、環境構築はCLIで行います。
aws-vaultを使用することで認証情報を指定します。
aws-vaultにつきましては以下のブログを参考にしてください。
必要ない方は「aws-vault exec personal --」を省略して実行してください。
EKSクラスターの作成
eksctlでcreate clusterでクラスターを作成します。
eksctl create cluster \
--name eks-microservice-test \
--region us-east-1 \
--fargate
約20分ほどでクラスターは作成できます。
egawa@HL01559:~/eks-micro-demo$ aws-vault exec personal -- eksctl create cluster --name eks-microservice-test --region us-east-1 --fargate
2024-08-29 13:30:30 [ℹ] eksctl version 0.189.0
2024-08-29 13:30:30 [ℹ] using region us-east-1
2024-08-29 13:30:31 [ℹ] setting availability zones to [us-east-1a us-east-1c]
2024-08-29 13:30:31 [ℹ] subnets for us-east-1a - public:192.168.0.0/19 private:192.168.64.0/19
2024-08-29 13:30:31 [ℹ] subnets for us-east-1c - public:192.168.32.0/19 private:192.168.96.0/19
2024-08-29 13:30:31 [ℹ] using Kubernetes version 1.30
... 中略
2024-08-29 13:47:46 [✔] all EKS cluster resources for "eks-microservice-test" have been created
2024-08-29 13:47:46 [✔] created 0 nodegroup(s) in cluster "eks-microservice-test"
2024-08-29 13:47:46 [✔] created 0 managed nodegroup(s) in cluster "eks-microservice-test"
2024-08-29 13:47:54 [ℹ] kubectl command should work with "/home/egawa/.kube/config", try 'kubectl get nodes'
2024-08-29 13:47:54 [✔] EKS cluster "eks-microservice-test" in "us-east-1" region is ready
EKSクラスターの設定
EKSでALBを使用するにはIAMなどの設定が必要になります。
IAM OIDCプロバイダーの設定
EKSクラスターがAWSリソースへアクセスするため、IAM OIDCプロバイダーを設定する必要があります。
eksctl utils associate-iam-oidc-provider \
--region=us-east-1 \
--cluster=eks-microservice-test \
--approve
egawa@HL01559:~/eks-micro-demo$ aws-vault exec personal -- eksctl utils associate-iam-oidc-provider --region=us-east-1 --cluster=eks-microservice-test --approve
2024-08-30 10:55:42 [ℹ] will create IAM Open ID Connect provider for cluster "eks-microservice-test" in "us-east-1"
2024-08-30 10:55:43 [✔] created IAM Open ID Connect provider for cluster "eks-microservice-test" in "us-east-1"
IAMロールを作成
EKSクラスター用のIAMロールを作成します。
クラスタ内でALB等の管理を行うため必要になってきます。
IAMロールを作成して
curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json
aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy --policy-document file://iam_policy.json
クラスターへ適応します。
eksctl create iamserviceaccount \
--cluster eks-microservice-test \
--namespace kube-system \
--name aws-load-balancer-controller \
--attach-policy-arn arn:aws:iam::<your-account-id>:policy/AWSLoadBalancerControllerIAMPolicy \
--approve
EKSクラスターへAWS Load Balancer Controllerのインストール
Helmリポジトリを追加
helm repo add eks https://aws.github.io/eks-charts
helm repo update
VPC_IDを取得
aws ec2 describe-vpcs --query 'Vpcs[*].{VpcId:VpcId, Name:Tags[?Key==`Name`].Value | [0]}' --output table
AWS Load Balancer Controllerをインストール
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=eks-microservice-test \
--set serviceAccount.create=false \
--set region=us-east-1 \
--set vpcId=<your-vpc-id> \
--set serviceAccount.name=aws-load-balancer-controller
実行例
egawa@HL01559:~/eks-micro-demo$ aws-vault exec personal -- eksctl create iamserviceaccount \
--cluster eks-microservice-test \
--namespace kube-system \
--name aws-load-balancer-controller \
--attach-policy-arn arn:aws:iam:: <your-aws-id>:policy/AWSLoadBalancerControllerIAMPolicy \
--approve
2024-08-30 10:56:05 [ℹ] 1 iamserviceaccount (kube-system/aws-load-balancer-controller) was included (based on the include/exclude rules)
2024-08-30 10:56:05 [!] serviceaccounts that exist in Kubernetes will be excluded, use --override-existing-serviceaccounts to override
2024-08-30 10:56:05 [ℹ] 1 task: {
2 sequential sub-tasks: {
create IAM role for serviceaccount "kube-system/aws-load-balancer-controller",
create serviceaccount "kube-system/aws-load-balancer-controller",
} }2024-08-30 10:56:05 [ℹ] building iamserviceaccount stack "eksctl-eks-microservice-test-addon-iamserviceaccount-kube-system-aws-load-balancer-controller"
2024-08-30 10:56:06 [ℹ] deploying stack "eksctl-eks-microservice-test-addon-iamserviceaccount-kube-system-aws-load-balancer-controller"
2024-08-30 10:56:06 [ℹ] waiting for CloudFormation stack "eksctl-eks-microservice-test-addon-iamserviceaccount-kube-system-aws-load-balancer-controller"
2024-08-30 10:56:37 [ℹ] waiting for CloudFormation stack "eksctl-eks-microservice-test-addon-iamserviceaccount-kube-system-aws-load-balancer-controller"
2024-08-30 10:56:37 [ℹ] created serviceaccount "kube-system/aws-load-balancer-controller"
# インストール
egawa@HL01559:~/eks-micro-demo$ aws-vault exec personal -- helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=eks-microservice-test \
--set serviceAccount.create=false \
--set region=us-east-1 \
--set vpcId=vpc-xxxxxxx \
--set serviceAccount.name=aws-load-balancer-controller
NAME: aws-load-balancer-controller
LAST DEPLOYED: Fri Aug 30 11:30:34 2024
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
AWS Load Balancer controller installed!
EKSの設定が完了しました!
コンテナイメージ
ここからはアプリケーションをデプロイのための準備を行っていきます。
デプロイするコンテナイメージを作成し、ECRにプッシュします。
# ログイン
aws-vault exec personal -- aws ecr get-login-password --region us-west-1 | docker login --username AWS --password-stdin <your-account-id>.dkr.ecr.us-west-1.amazonaws.com
Login Succeeded
# ECRリポジトリ作成
aws-vault exec personal -- aws ecr create-repository --repository-name user-service
aws-vault exec personal -- aws ecr create-repository --repository-name product-service
# イメージビルド
docker build -t user-service ./user-service/
docker build -t product-service ./product-service/
# タグ付け
docker tag user-service:latest <your-account-id>.dkr.ecr.us-west-1.amazonaws.com/user-service:latest
docker tag product-service:latest <your-account-id>.dkr.ecr.us-west-1.amazonaws.com/product-service:latest
# プッシュ
docker push <your-account-id>.dkr.ecr.us-west-1.amazonaws.com/user-service:latest
docker push <your-account-id>.dkr.ecr.us-west-1.amazonaws.com/product-service:latest
サービスをデプロイ
イメージの準備が完了したのでサービスをデプロイしていきます。
デプロイメントファイルはこちら
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 2
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: <your-aws-id>.dkr.ecr.us-east-1.amazonaws.com/user-service:latest
ports:
- containerPort: 3000
env:
---
apiVersion: v1
kind: Service
metadata:
name: user-service
spec:
selector:
app: user-service
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: ClusterIP
製品サービスは省略
デプロイ実行
kubectl apply -f ./k8s/user-service/deployment.yaml
kubectl apply -f ./k8s/product-service/deployment.yaml
egawa@HL01559:~/eks-micro-demo$ aws-vault exec personal -- kubectl apply -f ./k8s/user-service/deployment.yaml
deployment.apps/user-service created
service/user-service created
egawa@HL01559:~/eks-micro-demo$ aws-vault exec personal -- kubectl apply -f ./k8s/product-service/deployment.yaml
deployment.apps/product-service created
service/product-service created
Ingressリソースの作成
Ingressは、HTTPをサービスにルーティングするためのリソースです。
Ingressリソースを作成することで、トラフィックをアプリケーションに転送することができます。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: eks-microservice-ingress
namespace: default
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/backend-protocol: HTTP
alb.ingress.kubernetes.io/healthcheck-path: /healthz
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 80
- path: /products
pathType: Prefix
backend:
service:
name: product-service
port:
number: 80
Ingressリソースを作成
kubectl apply -f ./k8s/user-service/ingress.yaml
egawa@HL01559:~/eks-micro-demo$ aws-vault exec personal -- kubectl apply -f ./k8s/user-service/ingress.yaml
ingress.networking.k8s.io/user-service-ingress created
環境構築はこれで完了です!
動作確認
ALBへアクセスして動作を確認します。
egawa@HL01559:~/eks-micro-demo$ curl http://k8s-default-userserv-xxxxxxxx.us-east-1.elb.amazonaws.com/users
[{"id":1,"name":"John Doe"},{"id":2,"name":"Tom Jelly"}]
egawa@HL01559:~/eks-micro-demo$ curl http://k8s-default-eksmicro-xxxxxxxx.us-east-1.elb.amazonaws.com/products
[{"id":1,"name":"Product A"},{"id":2,"name":"Product B"}]
想定通りのレスポンスを受け取れました!
さいごに
EKSを使用したマイクロサービスモドキを構築してみました。
「Kubernetesは難しい!」といった前評判で食わず嫌いになっている方も多いのではないでしょうか?(私がそうでした)
しかし、実際に手を動かしてみると、複雑な設定を行わないのであれば、簡単に構築を行うことができました。
次はマイクロサービスにおけるデータベースやルーティングの最適化を行っていきます。