Closed10

AWS EKSの環境構築とArgoCDでの継続的デプロイをIaC化する

horie-thorie-t

EKSクラスタをEKSモジュールで構築する

terraformディレクトリにEKSのクラスタを作成するコードを書いてください。EKSはt4g.mediumのスポットインスタンスを使って、リージョンはus-west-2 に作成してください。Terraform AWS modulesを使用してください。

使っているバージョンが古い点以外は問題なく作成できていそう。バージョンを更新して、以下を実行する。

terraform init
terraform apply

以下のエラーが発生。

│ Error: creating EKS Node Group (lean-saas-eks:spot-node-group-20250518014934718300000011): operation error EKS: CreateNodegroup, https response error StatusCode: 400, RequestID: 4ca4f8de-c9a5-42cd-99f3-f8b4b5609984, InvalidParameterException: [t4g.medium] is not a valid instance type for requested amiType AL2023_x86_64_STANDARD
│ 
│   with module.eks.module.eks_managed_node_group["spot_nodes"].aws_eks_node_group.this[0],
│   on .terraform/modules/eks/modules/eks-managed-node-group/main.tf line 308, in resource "aws_eks_node_group" "this":
│  308: resource "aws_eks_node_group" "this" {
│ 

弱気になって、Armインスタンスからx86インスタンス(t3a.medium)に変更して再度apply。

ここまでの結果はこちら

horie-thorie-t

クラスタの動作確認

terraforomのoutputsに以下の表示があるので、実行する。

configure_kubectl = "aws eks update-kubeconfig --region us-west-2 --name lean-saas-eks"
$ kubectl get pods -A
NAMESPACE     NAME                       READY   STATUS    RESTARTS   AGE
kube-system   aws-node-g7fq7             2/2     Running   0          4m41s
kube-system   aws-node-x6p6n             2/2     Running   0          4m39s
kube-system   coredns-5449774944-h64mz   1/1     Running   0          24m
kube-system   coredns-5449774944-tfvsg   1/1     Running   0          24m
kube-system   kube-proxy-j2n4b           1/1     Running   0          4m39s
kube-system   kube-proxy-jkj4c           1/1     Running   0          4m41s

$ eksctl get nodegroup --cluster lean-saas-eks
CLUSTER		NODEGROUP					STATUS	CREATED			MIN SIZE	MAX SIZEDESIRED CAPACITY	INSTANCE TYPE	IMAGE ID		ASG NAME						TYPE
lean-saas-eks	spot-node-group-20250518020521810000000001	ACTIVE	2025-05-18T02:05:24Z	1		3	2t3a.medium	AL2023_x86_64_STANDARD	eks-spot-node-group-20250518020521810000000001-7ccb7091-c00f-ff44-c95d-d5bd49313ef3	managed

$ kubectl get services -A
NAMESPACE     NAME                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE
default       kubernetes                  ClusterIP   172.20.0.1      <none>        443/TCP                  28m
kube-system   eks-extension-metrics-api   ClusterIP   172.20.114.10   <none>        443/TCP                  28m
kube-system   kube-dns                    ClusterIP   172.20.0.10     <none>        53/UDP,53/TCP,9153/TCP   26m

Jenieに以下を依頼する。

sample/sample-nginx ディレクトリに nginxのインスタンスをLoadBalancer経由でインターネットに公開する、Kubernetesのマニフェストファイルを作成してください。

READMEを作成してくれているので実行する

# Configure kubectl to connect to your EKS cluster
aws eks update-kubeconfig --region us-west-2 --name lean-saas-eks

# Apply the manifest
kubectl apply -f nginx.yaml

# Check the deployment status
kubectl get deployment nginx

# Check the service status and get the external IP/hostname
kubectl get service nginx
# Get the external IP/hostname
export SERVICE_IP=$(kubectl get service nginx -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')

# Access Nginx
curl http://$SERVICE_IP

実行結果は以下の通り。

$ curl http://$SERVICE_IP
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

後片付けの方法まで記載してある。

kubectl delete -f nginx.yaml

ここまでの結果はこちら

horie-thorie-t

AWS Load Balancer Controllerをインストールする

TerraformにHelmプロバイダを追加してください。

バージョンを最新化する。

TerraformでHelmチャートを使用してaws-load-balancer-controllerをインストールしてください。aws_iam_policy は https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.11.0/docs/install/iam_policy.json を使うようにしてください。

バージョンを最新化してapplyする。

以下のエラーが発生。

╷
│ Error: Invalid function argument
│ 
│   on alb_controller.tf line 14, in resource "aws_iam_policy" "aws_load_balancer_controller":
│   14:   policy      = file("${path.module}/iam_policy.json")
│     ├────────────────
│     │ while calling file(path)
│     │ path.module is "."
│ 
│ Invalid value for "path" parameter: no file exists at "./iam_policy.json"; this function works only with files that
│ are distributed as part of the configuration source code, so if this file will be created by a resource in this
│ configuration you must instead obtain this result from an attribute of that resource.
╵

terraform applyを実行すると以下のエラーが発生しました。

│ Error: Invalid function argument

│ on alb_controller.tf line 14, in resource "aws_iam_policy" "aws_load_balancer_controller":
│ 14: policy = file("${path.module}/iam_policy.json")
│ ├────────────────
│ │ while calling file(path)
│ │ path.module is "."

│ Invalid value for "path" parameter: no file exists at "./iam_policy.json"; this function works only with files that
│ are distributed as part of the configuration source code, so if this file will be created by a resource in this
│ configuration you must instead obtain this result from an attribute of that resource.

どうもdataリソースを使って定義してくれないので、自分で定義を編集する。

data "http" "aws_load_balancer_controller_policy_json" {
  url = "https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.11.0/docs/install/iam_policy.json"
}

resource "aws_iam_policy" "aws_load_balancer_controller" {
  name        = "AWSLoadBalancerControllerIAMPolicy"
  description = "IAM policy for AWS Load Balancer Controller"
  policy      = data.http.aws_load_balancer_controller_policy_json.body
}

applyしてインストール結果の確認。

$ 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           44s
$ ubectl get pods -n kube-system | grep aws-load-balancer-controller
aws-load-balancer-controller-89f854dcd-tj79h   1/1     Running   0          112s
aws-load-balancer-controller-89f854dcd-zkczx   1/1     Running   0          112s

ここまでの結果はこちら

horie-thorie-t

AWS Load Balancerを使ってコンテナを公開する。

sample/sample-nginx-alb ディレクトリに nginxのインスタンスをAWS ALB経由でインターネットに公開する、Kubernetesのマニフェストファイルを作成してください。

動作確認。

$ export ALB_ADDRESS=$(kubectl get ingress nginx-ingress -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
$ curl http://$ALB_ADDRESS
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

AWSコンソールでロードバランサーを調べるとちゃんと、ロードバランサータイプが Application になっていた。

horie-thorie-t

ArgoCDをインストールする

TerraformでHelmチャートを使用して、ArgoCDをインストールしてください。ArgoCDはALBでインターネットからHTTPSでアクセスできるようにしてください。

バージョンを最新のものに変更する。ACM証明書のドメインを指定する部分があったのでドメイン名を指定する。

# Create an ACM certificate for HTTPS
resource "aws_acm_certificate" "argocd" {
  domain_name       = "argocd.t-horie.com"  # Replace with your actual domain
  validation_method = "DNS"

applyしてもACM証明書が保留中のままになる。

ACM証明書のステータスが「保留中の検証」になっています。何を確認すれば良いですか?

Terraformに追加する内容をdocsに書いてきたのでtfファイルに追加する。

再度、applyすると発行済になった。しかし、Route53の設定されていないのでアクセスできない。

TerraformでRoute53にArgoCDのドメインを追加してください。

ALBのDNS名がわからないようなので、手動で修正。

# Create a Route53 record for the ArgoCD domain
resource "aws_route53_record" "argocd" {
# 中略
  # This is a placeholder. In a real-world scenario, you would need to get the ALB hostname dynamically.
  # For now, we're using a pattern that matches how AWS ALB Controller typically names the ALB.
  # You should replace this with the actual ALB hostname after the ALB is created.
  records = ["k8s-argocdalbgroup-dfd66c57f7-418058172.us-west-2.elb.amazonaws.com"]

terraform applyを実行したところ、以下のエラーが発生しました。

│ Error: Invalid index

│ on outputs.tf line 116, in output "argocd_route53_record_target":
│ 116: value = aws_route53_record.argocd.records[0]

│ Elements of a set are identified only by their value and don't have any separate index or key to select with, so it's
│ only possible to perform operations across all elements of the set.

修正してもらって、applyを実行。以下を実行してadminのパスワードを確認。

kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath='{.data.password}' | base64 -d

outputsのArgoCDのURLをブラウザで開いて、adminのアカウントでログイン。

ここまでの結果はこちら

horie-thorie-t

ArgoCDの動作確認

sample/sample-nginx-alb をArgoCDのアプリケーションとしてTerraformで登録してください。

リポジトリのURLを指定する。

resource "kubernetes_manifest" "nginx_alb_application" {
  manifest = {
# 中略
    spec = {
      project = "default"
      source = {
        repoURL        = "https://github.com/horie-t/lean-saas-tech.git"  # Replace with your actual repository URL

sample/sample-nginx-alb/application.yaml ファイルが不要になったので削除する。

applyを実行する。ArgoCDにアプリケーションが追加される。

nginx-ingressの部分にアプリケーションを開くためのリンクがあるのでクリックする。

ここまでの結果はこちら

horie-thorie-t

プライベートECRリポジトリからデプロイ

TerraformでECR リポジトリを作成し、EKSからアクセスできるようにしてください。

apply。

スタムのnginxのイメージを作成する。

docker run -p 8080:80 nginx:latest 

別ターミナルで動作確認。

$ curl http://localhost:8080/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
$ docker ps
CONTAINER ID   IMAGE          COMMAND                   CREATED          STATUS          PORTS                                     NAMES
5af29a47396f   nginx:latest   "/docker-entrypoint.…"   12 seconds ago   Up 12 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   gifted_gates
$ docker exec hopeful_banzai bash -c 'sed -i "s/Welcome to nginx!/Welcome to customized nginx!/" /usr/share/nginx/html/index.html'
$ curl http://localhost:8080/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to customized nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to customized nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
$ docker commit hopeful_banzai horie-t/nginx:custom1.0
$ docker tag horie-t/nginx:custom1.0 lean-saas-eks-app-repository:latest XXXXXXXXXXXX.dkr.ecr.us-west-2.amazonaws.com/lean-saas-eks-app-repository:latest
$ docker push XXXXXXXXXXXX.dkr.ecr.us-west-2.amazonaws.com/lean-saas-eks-app-repository:latest

ここまでの結果はこちら

horie-thorie-t

ECRリポジトリイメージの動作確認

イメージのURLを変更。

sample/sample-nginx-alb/nginx-alb.yaml
@@ -17,7 +17,7 @@ spec:
     spec:
       containers:
       - name: nginx
-        image: nginx:1.21
+        image: 269376826173.dkr.ecr.us-west-2.amazonaws.com/lean-saas-eks-app-repository:latest
         ports:
         - containerPort: 80
         resources:

ArgoCDのSyncボタンでsyncする。

アプリケーションの画面が変更される。

ここまでの結果はこちら

horie-thorie-t

ArgoCDのGitHubリポジトリをプライベートにする

GitHubで argocd-repo の名前のプライベートリポジトリを作成する。

このリポジトリで以下のデプロイを定義する

private-app/private-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: private-app
  namespace: default
  labels:
    app: private-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: private-app
  template:
    metadata:
      labels:
        app: private-app
    spec:
      containers:
      - name: private-app
        image: 269376826173.dkr.ecr.us-west-2.amazonaws.com/lean-saas-eks-app-repository:latest
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 200m
            memory: 256Mi
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: private-app
  namespace: default
  labels:
    app: private-app
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  selector:
    app: private-app
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: private-app-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: "alb"
    alb.ingress.kubernetes.io/scheme: "internet-facing"
    alb.ingress.kubernetes.io/target-type: "ip"
    alb.ingress.kubernetes.io/healthcheck-protocol: "HTTP"
    alb.ingress.kubernetes.io/healthcheck-port: "traffic-port"
    alb.ingress.kubernetes.io/healthcheck-path: "/"
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}]'
    alb.ingress.kubernetes.io/group.name: "private-app-alb-group"
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: private-app
            port:
              number: 80

TerraformでArgoCDがGitHubのプライベートリポジトリ horie-t/argocd-repo のアプリケーションをデプロイできるようにしてください。

Terraformのvariableに github_token が追加されたので以下のようにしてapplyする。GitHubのTokenはclassicでrepoのFull controllを与える。(Fingradeのread-onlyだとArgoCDがwriteできないとエラーになる。

export TF_VAR_github_token="your-github-token"
terraform apply

ここまでの結果はこちら

このスクラップは6ヶ月前にクローズされました