Skip to main content

Command Palette

Search for a command to run...

EKS with ArgoCD using Terraform

Updated
5 min read
EKS with ArgoCD using Terraform
J

Welcome to my blog where I share a few more words! No Artificial Intelligence (AI) form is harmed when writing my posts ;-) All mistakes are due to the simple and non-artificial nature of my own human mind.

Recently I wanted to try out a few things with EKS and ArgoCD. I ended up writing a bit of Terraform to make it easier for me to create and destroy the infrastructure in my test AWS account.

The code in k8-eks-argocd-terraform deploys all these👇 things.

  • VPC and the baseline networking

  • EKS cluster

  • AWS Load Balancer Controller

  • ArgoCD with Ingress

  • ArgoCD UI over 🔐 https with ACM cert

  • ArogoCD ApplicationSet (this is cool!)

  • Sample applications under ApplicationSet

I used Kubernetes Manifest files to deploy ArgoCD. This is because the existing Helm Chart for ArgoCD doesn't support the new-ish ApplicationSet feature at the moment. I wanted to try this feature instead of using the good old app of apps workaround. I used the git-dir-generator and pointed it to the same repository to keep everything in one place.

Rather than deploying from the laptop, I wanted to use Github Actions to deploy the infra 🤖. Though this made things a bit complicated, it was fun to experiment with Github Actions, and reusable workflows. I separated the code into vpc, eks and argocd for me to create/destroy parts of the infrastructure when needed.

♻️ Is This Code Reusable?

Of course 😊. I tried to keep things as generic as possible but you still need to update a few things to get this working with your AWS account.

☠️ WARNING!! ☠️

This is going to cost you a little. Please make sure to tear down everything once you are done with your testing.

Start with forking the repo jayanath/k8-eks-argocd-terraform. If you don't care about deploying the infra using Github Actions, just clone this repo instead.

1️⃣ Click-Ops bits

As with any 🐔 and 🥚 problem, there are few Click-Ops bootstrapping bits. This is needed even if you want to deploy from your laptop.

  • Create an S3 bucket for you to store terraform remote state. (yeah, the local state works too, but..)

  • Create a Hosted zone in R53 with a public domain

  • Create an ACM cert issued for yourdomain.com and *.yourdomain.com

I just created the hosted zone and ACM using click-ops 🤷‍♂️. Those cert validations take time and I don't have my domain registered with R53. It's with Google for safekeeping 🤫.

2️⃣ Github Actions bits

Skip these steps if you are deploying from your laptop.

Create an IAM role with enough permissions for Github Actions image.png
Create a Github secret AWS_CI_ROLE with the IAM role ARN image.png
Configure Open ID Connect (OIDC) for Github Actions in AWS. Just follow the docs in the reference section. image.png

3️⃣ Find/Replace bits

This is to update the bucket name, domain name etc in a few places in the code before deployment.

  • k8-eks-argo-terraform-state-jay with your S3 🪣 name

  • argo.jayforweb.com with argo.yourdomain.com

  • eksadmin with your AWS IAM user if you want to use kubectl from your laptop

  • us-west-2 with your region. ⚠️ Make sure to update aws_image_repository URL if you change the region.

4️⃣ Time to Deploy

I'm sure you already know this but we need to follow the order of vpc --> eks --> argocd when deploying all this. If you are doing it from your laptop, just follow the drill of terraform init, terraform plan and terraform apply from within vpc, eks and argocd folders. If you set up the Github Actions, all you have to do is to select the action and run it.

image.png

EKS takes about 15-20 minutes to deploy. Maybe there is a chance to fix a ☕ until the machines in the cloud do their thing 😜.

This is how long it took me to deploy everything.

image.png

5️⃣ Post Deployment Stuff

  1. Add an alias record with the Ingress Load Balancer URL. `AWS LoadBalancer Controller` dynamically deploy a new LB or add new ingress into the same LB based on the setup. I couldn't figure out a way to automagically add this record to the hosted zone as I had no way of knowing when would the LB gets created.

  2. Add alias records for sample apps, nginx1, nginx2 and nginx3 and target the same ALB.

  3. Add your IAM user (`eksadmin` in my case) to the AWS configuration. Then update the `kubeconfig` to get access to your brand new EKS cluster and grab the ArgoCD default password from the `argocd-initial-admin-secret`.

    1. `export AWS_DEFAULT_PROFILE=eksadmin`

    2. `aws sts get-caller-identity`

    3. `aws eks update-kubeconfig --name eks-demo --region us-west-2 --profile eksadmin`

    4. `kubectl get secrets -n argocd` ![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1667571895727/bxQU2HTnW.png align="left")

    5. `kubectl get secret argocd-initial-admin-secret -n argocd --template={{.data.password}} | base64 -d`

6️⃣ The End Result 🎉

image.png

image.png

Now you could experiment by adding/removing/updating the sample applications. Once you commit the code, ArgoCD will faithfully adjust the apps in the cluster.

🔥 Tear Down ☠️

This is super important! If you leave this setup running for long time, it's going to cost you an 🦾 and a 🦿before you know it. Make sure to use terraform destroy or those Github Workflows to nuke everything.

Sometimes, AWS fails to destroy certain resources.

The underlying issue is with the ENIs. This is a very old issue with AWS. Just go ahead and delete the ENI and security groups manually. image.png image.png image.png

image.png

That's about it! If you reach this far, thank you 🙇‍♂️ for your time.

As always, just let me know if you got stuck, or if you have any questions. I'm more than happy to help! 😄👍.

📚 Reference

  1. [OIDC setup instructions for AWS](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html#manage-oidc-provider-console)

  2. [OIDC setup instructions for Github](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services)

  3. [ArgoCD ApplicationSet](https://argo-cd.readthedocs.io/en/stable/user-guide/application-set/)

  4. [jayanath/k8-eks-argocd-terraform](https://github.com/jayanath/k8-eks-argocd-terraform)

M

Great! Works with a few tweacks , but I am not sure how you get the url from de lb , I can not find that dualstack.... url to point my domain.

1
J

Hi Miguel, Thanks for taking time to share your thoughts. With the AWS LB Controller, it should create the LB when we deploy the Ingress. Sometimes it takes a bit of time.

Here is what I would try:

1- Install Lens [https://k8slens.dev/] to have a greater visibility into all the resources

2- Check if the Ingress is created as expected.

3- Delete the Ingress and redeploy to trigger the LB creation.

Let me know how it goes.

1
J

Absolutely great article! I used it for my project, but it would be great to enhance stuff from it so by using the main domain (in this article argo.jayforweb.com) users from the internet can access the content of one of the apps. It would require among others creating a service for one of the apps and configuring the right routing and firewall rules I guess. What do you think about creating a second part for that article? I think for people with less experience like me it would be so useful thing. Regards!

2
J

Thanks for taking time to drop a note. It's great to hear that this was helpful to you. Since we are using AWS LB Controller as our ingress controller, it is easy to expose sample applications using their own ingress. Have a look at the latest code in the repo. There I have added ingress for all 3 sample apps. The important thing is to add the relevant records in the hosted zone. Apologies for the late response. Let me know if you have further questions. Cheers!

1
J

I am very grateful! I will let know if I will come up with some further questions. Thanks!

1