Skip to content

Amazon EKS cluster provisioning and application deployment with Terraform.

License

Notifications You must be signed in to change notification settings

KyriakosTsalia/eks-cluster-app-provisioning

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Application provisioning on an Amazon EKS cluster with ingress and monitoring capabilities using Terraform and Helm

Technologies used

Name Version
terraform ~> 1.2.2
eks 1.22
kubectl v1.24.2
aws-cli 2.7.10
ingress-nginx helm chart 4.1.4
kube-prometheus-stack helm chart 36.6.1
kind node image kindest/node:v1.22.9
go 1.18

Go Application

The application that will be deployed, which resides in the /app directory, is a simple Go web application that scrapes the Kubernetes API server and shows a dashboard with information about all running pods in its namespace.

Amazon EKS

To provision infrastructure in the AWS cloud, the aws-cli tool is needed, in order to configure your account's credentials. Alternatively, store them in two terraform variables named AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY and use them in all terraform directories to configure the aws provider. It is important that the latest version AWS CLI version 2 is used, otherwise in following steps, the kubeconfig file comes with an error - it uses the invalid apiVersion: client.authentication.k8s.io/v1alpha1 instead of the correct apiVersion: client.authentication.k8s.io/v1beta1.

For extra safety and isolation, the EKS cluster, the ingress-nginx controller and the kube-prometheus-stack are all managed by different directories. To further experiment and explore the terraform EKS provisioning procedure, the official EKS module was not used - instead, the EKS cluster was build with simple terraform resources (e.g. aws_eks_cluster, aws_eks_node_group, etc.).

Firstly, navigate to the /eks directory and deploy the eks cluster. Upon completion, the eks service will be deployed, as well as two node groups, the monitoring and the application groups. Both have a group label, but the first one has a group=monitoring:NoSchedule taint as well, so just the pods created by the kube-prometheus-stack helm chart will be scheduled only on these nodes. The cluster configuration will be included in the ${HOME}/.kube/config file and will be updated every time the eks cluster changes.

To verify the correct cluster status, run for example:

kubectl get nodes --show-labels

Then, in the /ingress-nginx directory, deploy the ingress-nginx controller using Helm, specifying just two chart values regarding the controller update strategy.

After making sure that the ingress controller is in a stable state (for example, to avoid a failed calling webhook "validate.nginx.ingress.kubernetes.io" error), deploy the kube-prometheus-stack from the /monitoring directory, again using Helm. The file /monitoring/values.yaml contains values that create ingresses for the prometheus, grafana and alertmanager components and supply them with the node affinity rules and tolerations needed for the monitoring node group.

Lastly, the /app-manifests directory is responsible for the application deployment. Along with the usual configuration, an ingress resource is created in order for the app to be accessible from the /app route, as well as a ServiceMonitor resource for the app to be visible and monitored by the monitoring stack.

To find the hostname of the AWS ELB provisioned by the ingress controller, use the kubectl tool and execute the following command:

kubectl get svc -n ingress-nginx ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].hostname}{"\n"}'

Alternatively, this hostname can also be found in the AWS Console in the EC2 Load balancers section.

After applying all of the above steps, the following routes are exposed:

Name Type
/app Prefix
/monitor/prometheus Prefix
/monitor/grafana Prefix
/monitor/alertmanager Prefix

Local deployment with kind

To setup a local K8S cluster that mimics the one that would be deployed on AWS, navigate to the /kind directory and use the configuration to deploy a kind cluster. For all the other directories, the only change needed is to set the variable env equal to kind (instead of the default aws). Everything else stays the same and all routes will ultimately be hosted at localhost.


License

Copyright © 2022 Kyriakos Tsaliagkos

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.