Infrastructure Guy

Aha moments in the life of an Infrastructure Guy

Terraform Twilio Golang Oh-my

Want to get your feet wet with a little Terraform, Twilio, EKS, and Golang? I created a super simple app that will allow you to text the number of friends you are with and reply back with a fun activity.

The app is built on top of AWS’s Kubernetes (EKS). I wanted an easy setup that I could quickly destroy and not incure costs beyond the Free AWS Tier so leveraged Terraform to do so.

The Bored API doesn’t require an authentication so it’s super easy to make rest calls against it. The reason behind using Terraform was so that I could tear down the infrastructure and build it back identically. The only “gotcha” I found was that the Terraform wouldn’t remove all of the service accounts created so you gotta clear those out with a script. I’m happy to throw something together if you hit me up on LinkedIn.

Here’s the tutorial if you want to give it a shot or the repo if you’d rather skip my rambling and go strait to the code.

Prerequisites

#install Go
brew install go

#install Terraform
brew install terraform

#install Docker
brew cask install docker

#install minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64
sudo install minikube-darwin-amd64 /usr/local/bin/minikube

#install Kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl"

To run locally

go run app.go

Push to Docker Hub

APP_TAG=josephglaspie/bored:v0.0.5
docker build . -t $APP_TAG
docker push $APP_TAG

To deploy to minikube

kubectl apply -f deployments/mini-deployment.yaml
# The following will return the port
minikube service web

Setup Twilio sms number

  1. Go to Twilio.com and setup a free trial account
  2. Get a phone number
  3. Go to that phone number and setup a webhook
  4. Check out this tutorial for details

Make available online with ngrok

ngrok http http://127.0.0.1:56952

Take the return from ngrok and add it to the twilio webhook

EKS

provider "aws" {
  region     = "us-east-2"
  access_key = ""
  secret_key = ""
}
cd terraform
terraform init
terraform plan
terraform apply #Go make some tea or coffee this will take around 10 minutes to build out
cd ..

# Connect your kubectl to the cluster
aws configure #paste your keys into the correct places
aws eks --region us-east-2 update-kubeconfig --name mycluster
# Will return something like: Updated context arn:aws:eks:us-east-2:244172242562:cluster/mycluster in /Users/name/.kube/config

Ingress

#Create IAM Policy
aws iam create-policy \
--policy-name AWSLoadBalancerControllerIAMPolicy \
--policy-document file://iam_policy.json

#Create service account
myaccount=244172242562
clustername=mycluster
eksctl create iamserviceaccount \
--cluster=$clustername \
--namespace=kube-system \
--name=aws-load-balancer-controller \
--attach-policy-arn=arn:aws:iam::$myaccount:policy/AWSLoadBalancerControllerIAMPolicy \
--override-existing-serviceaccounts \
--approve

eksctl utils associate-iam-oidc-provider --region=us-east-2 --cluster=mycluster --approve

# Install cert-manager to inject certificate configuration into the webhooks.
kubectl apply \
--validate=false \
-f https://github.com/jetstack/cert-manager/releases/download/v1.5.4/cert-manager.yaml

# Download and replace default cluster name with your own
curl -Lo deployments/loadbalancer.yaml https://github.com/kubernetes-sigs/aws-load-balancer-controller/releases/download/v2.3.0/v2_3_0_full.yaml
# Apply ALB with correct cluster name
kubectl apply -f deployments/loadbalancer.yaml

# Check on ALB deployment
kubectl get deployment -n kube-system aws-load-balancer-controller
kubectl logs -n kube-system   deployment.apps/aws-load-balancer-controller

  1. Log into console and tage subnets with the following: Key – kubernetes.io/role/elb Value – 1
  2. Also, download the sample app and change out the settings with your own AND add your subnets to the ingress annotation:
curl -Lo deployments/web-deployment.yaml https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.3.0/docs/examples/2048/2048_full.yaml
alb.ingress.kubernetes.io/subnets: subnet-0213058ab09c17cca, subnet-003c36f6f9c457619, subnet-00a17755b8471dbd5
# Test connection
k get pods -n kube-system
# Deploy app with service and ingress
k apply -f deployments/web-deployment.yaml
# Check ingress
kubectl get ingress/ingress-bored -n bored

#get external public ip
k get svc
NAME                       TYPE           CLUSTER-IP       EXTERNAL-IP                                                               PORT(S)          AGE
kubernetes                 ClusterIP      10.100.0.1       <none>                                                                    443/TCP          10m
web                        NodePort       10.100.130.96    <none>                                                                    8080:31317/TCP   10s
web-service-cluster-ip     ClusterIP      10.100.231.227   <none>                                                                    8080/TCP         10s
web-service-loadbalancer   LoadBalancer   10.100.121.221   a93868263dcf34d12b029f8c080c8951-1996062109.us-east-2.elb.amazonaws.com   8080:30061/TCP   10s
web-service-nodeport       NodePort       10.100.143.240   <none>                                                                    80:31549/TCP     10s

curl --location --request POST 'http://k8s-bored-ingressb-a7cccb6576-1355983709.us-east-2.elb.amazonaws.com/bored' \
--header 'Content-Type: text/plain' \
--data-raw '5'

terraform destroy

References: