Kubernetes(EKS)を使用したマイクロサービスを作成してみたいんだ

Kubernetes(EKS)を使用したマイクロサービスを作成してみたいんだ

Clock Icon2024.08.30

マイクロサービスに入門したい えがわ です。

今までECSでモノリスなアプリケーションしか作成したことがなかったので、単純に構築してみたいという気持ち一心で望みます。

通常マイクロサービスは「ドメイン駆動設計で分割して~」など、ビジネスロジック基づきアーキテクチャを慎重に考えます。
ですが、今回はただの自習なので作りたいように作ります。

目指すもの

今回はユーザーサービス(user-service)と製品サービス(product-service)を実装します。
コンピューティングはFargateを選択し、パスでルーティングしたいためApplication Load Balancerを使用します。

k8s-microservice

ソースはこちらに置いています。
https://github.com/Remin18/express-microservice-test/tree/master

環境

  • Ubuntu 22.04.4 LTS(WSL2)
  • kubectl: v1.31.0
  • eksctl: 0.189.0

やってみる

今回使用するプログラムはこちらです。

user-service/src/index.ts
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につきましては以下のブログを参考にしてください。

https://dev.classmethod.jp/articles/wsl2-cdk-terraform/#toc-terraformmfa
必要ない方は「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

サービスをデプロイ

イメージの準備が完了したのでサービスをデプロイしていきます。

デプロイメントファイルはこちら

k8s/user-service/deployment.yaml
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リソースを作成することで、トラフィックをアプリケーションに転送することができます。

k8s/ingress.yaml
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は難しい!」といった前評判で食わず嫌いになっている方も多いのではないでしょうか?(私がそうでした)
しかし、実際に手を動かしてみると、複雑な設定を行わないのであれば、簡単に構築を行うことができました。
次はマイクロサービスにおけるデータベースやルーティングの最適化を行っていきます。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.