Introduction
In today’s cloud-native world, container orchestration has become a must for scaling applications reliably. Kubernetes (K8s), an open-source orchestration platform, is the de facto standard for managing containers in production. But managing the control plane, networking, and high availability? That’s not something you want to handle manually.
That’s where Amazon EKS (Elastic Kubernetes Service) comes in. EKS is a managed Kubernetes service by AWS. It takes care of provisioning the control plane, automating upgrades, and integrating deeply with other AWS services like IAM, VPC, CloudWatch, and Load Balancers.
To simplify you and your team’s work, we can use GitHub Actions to automate build, test, and deployment for your applications that you want to run in Kubernetes.
Prerequisites
- IAM Role – to manage AWS resource used by AWS CLI.
- ECR Repository – to save your container image.
- AWS CLI – to access AWS services from the command line.
- kubectl – to interact with the Kubernetes cluster.
- eksctl – to simplify EKS cluster creation and management.
- helm – to install Kubernetes applications.
- GitHub Account – to use GitHub Actions.
Workflow
Steps
Configure AWS CLI
We start by configuring AWS CLI so that your local machine can communicate with AWS using your access credentials.
aws configureYou’ll be prompted to input your AWS credentials and default region:
AWS Access Key ID [None]: YOUR_ACCESS_KEY AWS Secret Access Key [None]: YOUR_SECRET_KEY Default region name [None]: us-east-1 Default output format [None]: json
Creating AWS EKS Cluster via eksctl
- This command uses
eksctlto provision an entire Kubernetes cluster on AWS, including the control plane and worker nodes.eksctl create cluster --name my-cluster --region us-east-1
Configure Load Balancer IngressClass
Associate the IAM OIDC provider so service accounts can assume roles.
eksctl utils associate-iam-oidc-provider --region us-east-1 --cluster my-cluster --approveDownload the IAM policy for the AWS Load Balancer Controller.
curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/refs/heads/main/docs/install/iam_policy.jsonCreate the IAM policy in AWS using the downloaded JSON file.
aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy --policy-document file://iam-policy.jsonGet your current AWS account ID.
aws sts get-caller-identity --query "Account" --output textCreate a Kubernetes service account and attach the IAM policy to it.
eksctl create iamserviceaccount --cluster=my-cluster --namespace=kube-system --name=aws-load-balancer-controller --attach-policy-arn=arn:aws:iam::<AWSAccountNumber>:policy/AWSLoadBalancerControllerIAMPolicy --override-existing-serviceaccounts --region us-east-1 --approveAdd the EKS Helm chart repo.
helm repo add eks https://aws.github.io/eks-chartsUpdate your Helm repositories.
helm repo update eksGet your VPC ID associated with the EKS cluster.
aws ec2 describe-vpcs --filters "Name=tag:eksctl.cluster.k8s.io/v1alpha1/cluster-name,Values=my-cluster" --query "Vpcs[0].VpcId" --output textInstall the AWS Load Balancer Controller via Helm.
helm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName=my-cluster --set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller --set region=us-east-1 --set vpcId=<yourVPCID>
Deploying WebApp using GitHub Actions
First thing first, you need an application that you wanna deploy to EKS. Here I’m deploying a simple tetris game Canvas Tetris.
To create an automated deployment, you need a workflow file placed in the
.github/workflowsdirectory in your repo with a.yamlextension. The workflow below builds and deploys the app to EKS on every push to themasterbranch.name: Deploy to Amazon EKS on: push: branches: - master env: AWS_REGION: ${{ vars.AWS_REGION }} ECR_REPOSITORY: ${{ vars.ECR_REPOSITORY }} EKS_CLUSTER_NAME: ${{ vars.EKS_CLUSTER_NAME }} permissions: id-token: write contents: read jobs: build: name: Build Image runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Set short git commit SHA id: commit uses: prompt/actions-commit-hash@v2 - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }} aws-region: ${{ env.AWS_REGION }} - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v1 - name: Build, tag, and push image to Amazon ECR id: build-image env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} IMAGE_TAG: ${{ steps.commit.outputs.short || 'latest' }} run: | docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG - name: End Build run: echo "Build Success" deploy: name: Deploy Application needs: build runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Set short git commit SHA id: commit uses: prompt/actions-commit-hash@v2 - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }} aws-region: ${{ env.AWS_REGION }} - name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v1 - name: Update kube config run: aws eks update-kubeconfig --name $EKS_CLUSTER_NAME --region $AWS_REGION - name: Deploy to EKS env: ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} IMAGE_TAG: ${{ steps.commit.outputs.short || 'latest' }} run: | sed -i "s|DOCKER_IMAGE|$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG|g" manifests/deployment.yaml && \ kubectl apply -f manifests/deployment.yaml kubectl apply -f manifests/service.yaml kubectl apply -f manifests/ingress.yamlAs seen above, we also use environment variables (
envandsecrets) to keep the workflow dynamic and secure. For more info on setting those, check GitHub’s official docs.