EKS on speed

Welcome

Let's build some stuff. Today on AWS(EKS). Today with popular solutions and almost without coding(in YAML). Today focus on speed and simplicity. Additionally no CI/CD.

Components

I will keep it simple.

Building infrastructure

Setup

First steps. I need to build some infrastructure. As almost everyone use Terraform for building and managing resources I decided to use it too. Based on Terrafrom EKS module I've created a sample manifest. Also, I decided to add ECR and configure output in a specific way.

 1# I'd like to have control plane endpoint
 2output "cluster_endpoint" {
 3  description = "Endpoint for EKS control plane."
 4  value       = module.eks.cluster_endpoint
 5}
 6
 7# get kubectl config based on cluster_name
 8output "cluster_name" {
 9  description = "Name of created cluster"
10  value       = local.cluster_name
11}
12
13# upload to ECR with dynamic name
14output "ecr_url" {
15  description = "URL of ECR registry"
16  value       = aws_ecr_repository.ecr.repository_url
17}
18
19# also region could be dynamic
20output "region" {
21  description = "AWS region."
22  value       = var.region
23}

Variables.tf and main.tf weren't very interesting, so it will be pushed to the repo.

Commands flow

1# get modules
2terraform init
3
4# take a look at plan, if it's correct go-ahead
5terraform plan | less
6
7# this step will take some time to finish. (9:33.03 total)
8# if correct enter yes or terraform apply -auto-approve
9terraform apply

Kubectl and ECR

Is anybody there?

After successful cluster creation, we could want to check if the cluster is running. First I need to update my kubeconfig for the purpose of cluster authentication. For this event, I will AWS CLI and kubectl.

1# variables are based on Terraform outputs
2aws eks update-kubeconfig \
3    --region $(terraform output -raw region) \
4    --name $(terraform output -raw cluster_name)
1kubectl get pod

Docker login

Now I need to login into ECR and push some images.

1aws ecr get-login-password \
2    --region $(terraform output -raw region) \
3    | docker login --username AWS \
4    --password-stdin $(terraform output -raw ecr_url | cut -d'/' -f1)

Then I can push an awesome Nginx image to ECR.

1docker tag nginx:latest $(terraform output -raw ecr_url):1.0.0
2docker push $(terraform output -raw ecr_url):1.0.0

Helming

After all this preparation we can finally deploy an app. For this process I decided to use helm. It's a standard, very popular, and flexible solution. Again Helm Chart is attached to the repository. There is no hack or magic - just boring templates.

Command flow

 1# dry run
 2helm template <app name> -f <file with values> --dry-run <chart name>
 3# for example
 4# helm template example-app -f example-app.yaml --dry-run ./example-app
 5
 6# install chart
 7helm install <app name> -f <file with values> --namespace <namespace> <chart name>
 8# for example
 9# helm install example-app -f example-app.yaml --namespace example ./example-app
10
11# upgrade app
12helm upgrade <app name> <chart> --set.image=<tag>
13# for example
14# helm upgrade example-app ./example-app --set=image.tag=2.0.0

DNS

Now all I need is a DNS record change. Ah, I forgot about LoadBalancer. For this article, I'm using LoadBalancer. After adding a service ELB provides an AWS endpoint for our application. My primary domain 3sky.dev is delegated to CloudFlare, so I will add a CNAME record with API. To do that I need four commands, and sometimes (for DNS propagation).

1# token
2TOKEN=my-private-token
3ZONE=my-domain-zone
4ELB=$(kubectl get svc example-app -n example --output jsonpath='{.status.loadBalancer.ingress[0].hostname}')
5
6curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE/dns_records" \
7     -H "Authorization: Bearer $TOKEN" \
8     -H "Content-Type: application/json" \
9     --data '{"type":"CNAME","name":"app","content":"'"$ELB"'","ttl":1,"proxied":true}' | jq .

Finally, I can check my app on app.3sky.dev. Trust me It was working(the app was stopped after checks).

Summary

In case of summary. The whole setup was faster than writing this post based on the ready README.md file. ~10 minutes for EKS, 30 for DNS propagation, command execution was fast - I have a fast keyboard. What can I say more? Testing and implementing stuff is still fun. What next? I don't know. I'm starting Elixir again, so maybe some sophisticated CI/CD for functional language?