はじめに
本記事では、Terraform でEKSのGitOps パイプラインのデモ環境を構築する手順とデモした内容について、記載しています。
GitOps について学習する時の参考になれば幸いです。
GitOps とは
引用:
GitOpsは、次の2つに要約できます。
1. Kubernetesおよびその他のクラウドネイティブテクノロジーのオペレーティングモデル。コンテナ化されたクラスターとアプリケーションのGitのデプロイ、管理、モニタリングを統合する一連のベストプラクティスを提供します。
2. アプリケーションを管理するための開発者エクスペリエンスへの道。ここでは、エンドツーエンドのCICDパイプラインとGitワークフローが操作と開発の両方に適用されます。
Terraform で構築する全体構成図
GitOps パイプライン
EKS クラスター
構成の概要
GitOps は、下記のコンポーネントで構成しています。
機能 | コンポーネント名 | 説明 |
---|---|---|
ソースの管理 | CodeCommit | アプリのソースとKubernetes のマニフェストを管理します。 |
イメージの管理 | ECR | アプリのイメージを管理します。 |
CI | CodePipeline + CodeBuild | アプリのソースの変更をトリガーにして、イメージをビルドし、ECR にプッシュします。プッシュ後、イメージの差し替えをマニフェストのリポジトリにプルリクエストします。 |
CD | Argo CD | マニフェストの変更を監視し、変更を検出すると、Kubernetes の実行環境に反映します。 |
Terraform のコードと構成
$ tree aws-tf-eks-gitops-demo aws-tf-eks-gitops-demo ├── eks-gitops-demo-app │ ├── Dockerfile │ └── index.html ├── eks-gitops-demo-k8s │ ├── deployment.yaml │ └── service.yaml ├── main.tf ├── modules │ └── ci │ ├── buildspec.yml │ ├── cloudwatch_event.tf │ ├── cloudwatch_logs.tf │ ├── codebuild.tf │ ├── codecommit.tf │ ├── codepipeline.tf │ ├── ecr.tf │ ├── iam.tf │ ├── iam_https_user.tf │ ├── outputs.tf │ ├── s3.tf │ └── variables.tf ├── outputs.tf ├── provider.tf └── versions.tf
デモ環境を構築するメインのファイル
main.tf
locals { aws_profile = "YOUR AWS ACCOUNT PROFILE NAME" aws_region = "ap-northeast-1" } module "ci" { source = "./modules/ci" # PREFIX prefix = "eks-gitops" # ENVIRONMENT PREFIX env = "demo" # IMAGE CODECOMMIT REPOSITORY NAME codecommit_repository_for_image = "eks-gitops-demo-app" # BRANCH NAME branch_name = "master" # ECR REPOSITORY NAME ecr_name = "eks-gitops-demo-app" # K8S CODECOMMIT REPOSITORY NAME codecommit_repository_for_k8s = "eks-gitops-demo-k8s" } module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "3.14.2" # VPC NAME name = "eks-gitops-demo-vpc" # VPC CIDR cidr = "10.0.0.0/16" # SUBNET azs = ["ap-northeast-1a", "ap-northeast-1c"] public_subnets = ["10.0.1.0/24", "10.0.2.0/24"] private_subnets = ["10.0.3.0/24", "10.0.4.0/24"] # NAT GATEWAY enable_nat_gateway = true single_nat_gateway = true # DNS enable_dns_hostnames = true } module "eks" { source = "terraform-aws-modules/eks/aws" version = "18.26.0" # EKS CONTROL PLANE cluster_name = "eks-gitops-demo" cluster_version = "1.22" cluster_endpoint_private_access = false cluster_endpoint_public_access = true # EKS CLUSTER VPC AND SUBNETS vpc_id = module.vpc.vpc_id subnet_ids = module.vpc.private_subnets # EKS MANAGED NODE GROUPS eks_managed_node_groups = { gitops-demo = { desired_size = 2 instance_types = ["t3.small"] } } node_security_group_additional_rules = { admission_webhook = { description = "Admission Webhook" protocol = "tcp" from_port = 0 to_port = 65535 type = "ingress" source_cluster_security_group = true } ingress_node_communications = { description = "Ingress Node to node" protocol = "tcp" from_port = 0 to_port = 65535 type = "ingress" self = true } egress_node_communications = { description = "Egress Node to node" protocol = "tcp" from_port = 0 to_port = 65535 type = "egress" self = true } } } data "aws_eks_cluster" "cluster" { name = module.eks.cluster_id } data "aws_eks_cluster_auth" "cluster" { name = module.eks.cluster_id }
GitOps パイプラインのデモ環境の構築
前提条件
- Terraform がセットアップされていること
- kubectl がセットアップされていること
- AWS CLI がセットアップされていること
- Argo CDのCLI がセットアップされていること
動作確認環境
$ terraform version Terraform v1.1.9 $ aws --version aws-cli/2.7.12 Python/3.9.11 Darwin/19.6.0 exe/x86_64 prompt/off $ kubectl version --client --short Client Version: v1.21.2 $ argocd version argocd: v2.4.3+471685f.dirty
EKS クラスターのセットアップ
Terraform を実行します。
$ terraform init $ terraform plan $ terraform apply 結果: Apply complete! Resources: 72 added, 0 changed, 0 destroyed.
下記コマンドを実行し、Terraform のoutput を控えておきます。
$ terraform output 結果: CODECOMMIT_IMAGE_REPOSITORY_URL = "https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/eks-gitops-demo-app" CODECOMMIT_INFRA_REPOSITORY_URL = "https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/eks-gitops-demo-k8s" ECR_REPOSITORY_URL = "[AWSアカウントID].dkr.ecr.ap-northeast-1.amazonaws.com/eks-gitops-demo-app" app_name = "eks-gitops-demo-app" argocd_sync_password = <sensitive> argocd_sync_username = <sensitive> eks_cluster_name = "eks-gitops-demo"
構築したEKSクラスターに接続できることを確認します。
$ aws eks update-kubeconfig \ --region ap-northeast-1 \ --name eks-gitops-demo \ --profile [YOUR AWS ACCOUNT PROFILE NAME] 結果: Added new context arn:aws:eks:ap-northeast-1:[AWSアカウントID]:cluster/eks-gitops-demo to /Users/*****/.kube/config
マニフェストファイルをリポジトリにプッシュ
下記2つのマニフェストファイルを terraform output
のCODECOMMIT_INFRA_REPOSITORY_URL
先(マニフェストのリポジトリ)にプッシュします。
※[AWSアカウントId]
を自環境に変更します。
deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: eks-gitops-demo-app spec: replicas: 2 selector: matchLabels: app: eks-gitops-demo-app template: metadata: labels: app: eks-gitops-demo-app spec: containers: - name: eks-gitops-demo-app image: [AWSアカウントId].dkr.ecr.ap-northeast-1.amazonaws.com/eks-gitops-demo-app:latest ports: - name: http containerPort: 80
service.yaml
apiVersion: v1 kind: Service metadata: name: eks-gitops-demo-app spec: type: LoadBalancer selector: app: eks-gitops-demo-app ports: - port: 80 targetPort: http
Argo CDのセットアップ
kubectl コマンドを使って、Argo CDをデプロイします。
$ kubectl create namespace argocd 結果: namespace/argocd created $ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
Argo CDのPod が稼働していることを確認します。
$ kubectl get pod -n argocd 結果: NAME READY STATUS RESTARTS AGE argocd-application-controller-0 1/1 Running 0 25s argocd-applicationset-controller-5f7d8fffb7-s2n6n 1/1 Running 0 26s argocd-dex-server-c6dcf7fdb-6qqll 1/1 Running 0 26s argocd-notifications-controller-544ff7766d-pljxl 1/1 Running 0 26s argocd-redis-75bdb869bf-8b2tv 1/1 Running 0 26s argocd-repo-server-649b4b66bd-4g22t 0/1 Running 0 26s argocd-server-5df946ff78-zq5tl 0/1 Running 0 26s
下記コマンドで、Argo CDの管理者用のデフォルトのパスワードを取得します。
$ kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo 結果: Argo CDの管理者用のデフォルトのパスワード
下記コマンドで、ローカルポートをArgo CDサーバーにポートフォワードします。
$ kubectl port-forward svc/argocd-server -n argocd 8080:443 結果: Forwarding from 127.0.0.1:8080 -> 8080 Forwarding from [::1]:8080 -> 8080
下記コマンドで、Argo CDサーバーにログインします。
$ argocd login localhost:8080 \ --username admin \ --password [Argo CD管理者用のデフォルトのパスワード] \ --insecure \ --port-forward-namespace argocd 結果: 'admin:login' logged in successfully Context 'localhost:8080' updated
下記コマンドで、Argo CDからマニフェストのリポジトリにHTTPS 接続する時に使用するIAMの情報を参照します。
$ terraform output argocd_sync_username 結果: ユーザー名 $ terraform output argocd_sync_password 結果: パスワード
下記コマンドで、マニフェストのリポジトリをArgo CDサーバーに追加します。
$ CODECOMMIT_INFRA_REPOSITORY_URL=https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/eks-gitops-demo-k8s $ argocd repo add ${CODECOMMIT_INFRA_REPOSITORY_URL} \ --username ユーザー名 \ --password パスワード 結果: Repository 'https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/eks-gitops-demo-k8s' added
Argo CDのアプリケーションとマニフェストのリポジトリを同期させる設定をします。
$ kubectl create namespace eks-gitops-demo-app 結果: namespace/eks-gitops-demo-app created $ argocd app create eks-gitops-demo-app \ --repo ${CODECOMMIT_INFRA_REPOSITORY_URL} \ --revision master \ --path ./ \ --dest-server https://kubernetes.default.svc \ --dest-namespace eks-gitops-demo-app \ --sync-policy automated \ --auto-prune 結果: application 'eks-gitops-demo-app' created
アプリケーションの同期設定が登録されていることを確認します。
$ argocd app list NAME CLUSTER NAMESPACE PROJECT STATUS HEALTH SYNCPOLICY CONDITIONS REPO PATH TARGET eks-gitops-demo-app https://kubernetes.default.svc eks-gitops-demo-app default Synced Healthy Auto-Prune <none> https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/eks-gitops-demo-k8s ./ master
ブラウザでhttps://localhost:8080
にアクセスして、Argo CDのGUIに接続します。
項目 | 入力内容 |
---|---|
username | admin |
Password | Argo CDの管理者用のデフォルトのパスワード |
ログイン画面
GUI上でもアプリケーションが表示されていることを確認します。
これで、GitOps パイプラインのデモ環境の構築が完了です。
GitOps パイプラインのデモ環境の実行
構築したデモ環境で、アプリケーションをデプロイします。
アプリのソースをリポジトリにプッシュ
下記2つのファイルを terraform output
のCODECOMMIT_INFRA_REPOSITORY_URL
先(アプリのソースのリポジトリ)にプッシュします。
Dockerfile
FROM nginx:latest WORKDIR /usr/share/nginx/html COPY index.html index.html
index.html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>GitOps Demo</title> </head> <body> <h1>GitOps Demo App v1</h1> </body> </html>
CodeBuild の実行
アプリのソースのリポジトリの変更をトリガーにCodePipeline が開始され、CodeBuild が実行されます。
イメージをECR をプッシュ
CodeBuild で、イメージがビルドされ、ECRにプッシュされます。
マニフェストのリポジトリにプルリクエスト
CodeBuild で、ECRにプッシュされたイメージを差し替えするためのプルリクエストをマニフェストのリポジトリに送信します。
マージ
マニフェストのリポジトリへのプルリクエストの内容を確認して、マージします。
デプロイ
Argo CDが、マニフェストのリポジトリの変更を検知すると、Kubernetes の実行環境に反映します。
$ kubectl get pod,svc,deploy -n eks-gitops-demo-app NAME READY STATUS RESTARTS AGE pod/eks-gitops-demo-app-7f54cfd78-cpcqm 1/1 Running 0 101s pod/eks-gitops-demo-app-7f54cfd78-wmbcj 1/1 Running 0 98s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/eks-gitops-demo-app LoadBalancer 172.20.232.32 a3114a987111542a2affe40c67071c69-111111111.ap-northeast-1.elb.amazonaws.com 80:30146/TCP 17m NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/eks-gitops-demo-app 2/2 2 2 17m
動作確認
下記コマンドで出力されたEXTERNAL-IP のLaoadBalancer のDNS名を確認します。
% kubectl get svc -n eks-gitops-demo-app NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE eks-gitops-demo-app LoadBalancer 172.20.232.32 a3114a987111542a2affe40c67071c69-111111111.ap-northeast-1.elb.amazonaws.com 80:30146/TCP 18m
ブラウザでLaoadBalancer のDNS名にHTTPアクセスして、アプリケーションがデプロイされたことを確認します。
Argo CDのGUI上でも確認できます。
Node
NetWork
これで、GitOps パイプラインを使ったアプリケーションのデプロイが完了です。
リソースのクリーンアップ
マニフェストファイルのリポジトリのservice.yaml
を削除して、Kubernetes の環境からELBを削除し、下記コマンドで確認します。
$ kubectl get svc -n eks-gitops-demo-app No resources found in eks-gitops-demo-app namespace.
下記のコマンドで、すべてのリソースを削除します。
$ terraform destroy Destroy complete! Resources: 72 destroyed.
さいごに
GitOps パイプラインの入門的な内容ですが、参考になれば幸いです。
元記事はこちら
Terraform で EKS の GitOps パイプラインを構築する
著者:@okubot55
アイレットなら、AWS で稼働するサーバーを対象とした監視・運用・保守における煩わしい作業をすべて一括して対応し、経験豊富なプロフェッショナルが最適なシステム環境を実現いたします。AWS プレミアコンサルティングパートナーであるアイレットに、ぜひお任せください。
AWS 運用・保守サービスページ
その他のサービスについてのお問合せ、お見積り依頼は下記フォームよりお気軽にご相談ください。
https://www.iret.co.jp/contact/service/form/