Fully automated, GitOps-driven CI/CD pipeline to deploy a sample microservice application to an AWS EKS cluster.
The solution is designed to be a minimal implementation of the requirements. Using Argo as suggested atop the hard requirements of EKS and terraform.
This should be considered a proof-of-concept, not a production-ready design. Please follow DevSecOps best practices when deploying anything to the public internet.
An AWS account. With the exception of the IAM user described in the terraform setup section, all AWS resources are managed by terraform/opentofu and can be removed with terraform destroy/tofu destroy
To further cordon this demo from your other AWS resources, you can create an AWS sandbox account by following the instructions here: https://cheat.readthedocs.io/en/latest/aws/subaccounts.html
Ensure the following command-line tools are installed:
- Terraform or OpenTofu
- AWS CLI
- kubectl
- eksctl
- helm
- argocd with argo rollouts
You can install these via Homebrew: brew install opentofu awscli kubernetes-cli eksctl helm argocd argoproj/tap/kubectl-argo-rollouts
Manually bootstrap an IAM user for terraform in AWS. We will call ours "terraform" and attach the "arn:aws:iam::aws:policy/AdministratorAccess" policy.
Create an access key for the terraform user, with the "Command Line Interface" use case.
Configure the key's id and secret you received from the previous step (note: this will replace your default profile in ~/.aws/credentials; specify --profile argument if you don't want this, or edit the credentials file manually):
aws configure set aws_access_key_id "ABCDEFGHIJKLMNOP"
aws configure set aws_secret_access_key "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcd"
You can now apply the terraform module:
tofu init
tofu apply
Update your ~/.kube/config, get the initial admin password, and forward the Argo UI port:
aws eks update-kubeconfig --region us-east-1 --name eks-gitops
kubectl -n argo-cd port-forward svc/argo-cd-argocd-server 8443:443
Get the initial password for the admin user: kubectl -n argo-cd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo
Log in on the command line (replace the asterisks by the password you just obtained): argocd login localhost:8443 --username admin --password "****************" --insecure
Open http://localhost:8443 to use the web UI.
Fork this helm chart on GitHub: https://github.com/dthtvwls/helm-guestbook.
git clone https://github.com/*yourname*/helm-guestbook
argocd app create helm-guestbook \
--sync-policy automated \
--project default \
--repo https://github.com/*yourname*/helm-guestbook \
--path . \
--dest-server https://kubernetes.default.svc \
--dest-namespace default
kubectl port-forward svc/helm-guestbook 8080:80
Open http://localhost:8080 to see the Guestbook app.
Push a change to your cloned repository: on values.yaml:9, change the value of tag to 0.2, commit the change and push to GitHub.
After a few minutes, observe the Guestbook app's page header at http://localhost:8080 change to "Fancy Guestbook". (You will need to re-establish the port forwarding.)
Run kubectl argo rollouts dashboard and open http://localhost:3100 to use the Rollouts web app.
Fork this helm chart on GitHub: https://github.com/dthtvwls/helm-blue-green.
Clone the new fork and install the chart:
git clone https://github.com/*yourname*/helm-blue-green
helm install example helm-blue-green/
kubectl port-forward $(kubectl get pods --namespace default -l "app=helm-guestbook,release=example" -o jsonpath="{.items[0].metadata.name}") 8080:80
Open http://localhost:8080 to see the Guestbook app.
Next, helm upgrade example helm-blue-green/ --set image.tag=0.2
Now, two versions will exist in your cluster (and each one has an associated service). You can watch the new service cut over in the rollout: http://localhost:3100/rollouts/rollout/default/example-helm-guestbook
Re-establish the port forwarding to see "Fancy Guestbook", again.
Finally, upgrade the image tag to a version that doesn't exist: helm upgrade example helm-blue-green/ --set image.tag=0.3
The rollout will fail and revision 2 will remain in production.