How to deploy on EKS

k8s

The Amazon Elastic Kubernetes Service (EKS) is a popular, fully automated Kubernetes service.

EKS web interface: console.aws.amazon.com/eks/home

Prerequisites

  • A physical or virtual machine running Ubuntu 24.04+

  • Juju 3.6+ installed via snap


Install EKS tooling

Install the Amazon EKS CLI by following the official eksctl documentation .

Install the Amazon Web Services CLI by following the official AWS documentation

Install the kubectl CLI tools via snap:

user@host:~$
sudo snap install kubectl --classic

To check they are correctly installed, run

user@host:~$
eksctl info
eksctl version: 0.159.0
kubectl version: v1.28.2
user@host:~$
aws --version
aws-cli/2.13.25 Python/3.11.5 Linux/6.2.0-33-generic exe/x86_64.ubuntu.23 prompt/off
user@host:~$
kubectl version --client
Client Version: v1.28.2
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3

Authenticate

Create an IAM account or use legacy access keys to operate AWS:

user@host:~$
aws configure
AWS Access Key ID [None]: SECRET_ACCESS_KEY_ID
AWS Secret Access Key [None]: SECRET_ACCESS_KEY_VALUE
Default region name [None]: eu-west-3
Default output format [None]:
user@host:~$
aws sts get-caller-identity
{
    "UserId": "1234567890",
    "Account": "1234567890",
    "Arn": "arn:aws:iam::1234567890:root"
}

Create a new EKS cluster

Export the deployment name for later use:

user@host:~$
export JUJU_NAME=aks-$USER-$RANDOM

Example cluster.yaml:

user@host:~$
cat <<-EOF > cluster.yaml
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
    name: ${JUJU_NAME}
    region: <region-name>
    version: "1.27"
iam:
  withOIDC: true

addons:
- name: aws-ebs-csi-driver
  wellKnownPolicies:
    ebsCSIController: true

nodeGroups:
    - name: ng-1
      minSize: 3
      maxSize: 5
      iam:
        attachPolicyARNs:
        - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
        - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
        - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
        - arn:aws:iam::aws:policy/AmazonS3FullAccess
      instancesDistribution:
        maxPrice: 0.15
        instanceTypes: ["m5.xlarge", "m5.2xlarge"] # At least two instance types should be specified
        onDemandBaseCapacity: 0
        onDemandPercentageAboveBaseCapacity: 50
        spotInstancePools: 2
EOF

Create a new Kubernetes cluster on EKS with the following command:

user@host:~$
eksctl create cluster -f cluster.yaml
...
2023-10-12 11:13:58 [ℹ]  using region <region-name>
2023-10-12 11:13:59 [ℹ]  using Kubernetes version 1.27
...
2023-10-12 11:40:00 [✔]  EKS cluster "eks-taurus-27506" in "<region-name>" region is ready

Bootstrap Juju on EKS

Add a Juju K8s cloud:

user@host:~$
juju add-k8s <k8s-cloud-name>

Bootstrap a Juju controller:

user@host:~$
juju bootstrap <controller-name>

See also: Juju | Amazon EKS and Juju

Deploy charms

Create a Juju model (K8s namespace):

user@host:~$
juju add-model <model-name>

The following command deploys 3 nodes of PostgreSQL on Kubernetes:

user@host:~$
juju deploy postgresql-k8s --channel 16/stable --trust -n 3
Deployed "postgresql-k8s" from charm-hub charm "postgresql-k8s", revision <number> in channel 16/stable on ubuntu@24.04/edge

Display deployment information

Display information about the current deployments with kubectl and eksctl:

user@host:~$
kubectl cluster-info
Kubernetes control plane is running at https://AAAAAAAAAAAAAAAAAAAAAAA.gr7.<region-name>.eks.amazonaws.com
CoreDNS is running at https://AAAAAAAAAAAAAAAAAAAAAAA.gr7.<region-name>.eks.amazonaws.com/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
user@host:~$
eksctl get cluster -A
NAME			        REGION		    EKSCTL   CREATED
eks-taurus-27506	<region-name>	True
user@host:~$
kubectl get node
NAME                                               STATUS   ROLES    AGE   VERSION
ip-192-168-14-61.<region-name>.compute.internal    Ready    <none>   19m   v1.27.5-eks-43840fb
ip-192-168-51-96.<region-name>.compute.internal    Ready    <none>   19m   v1.27.5-eks-43840fb
ip-192-168-78-167.<region-name>.compute.internal   Ready    <none>   19m   v1.27.5-eks-43840fb

Clean up

Always clean cloud resources that are no longer necessary; they could be costly!

See all controllers in your machine with

user@host:~$
juju controllers
Controller         Model         User   Access     Cloud/Region                Models  Nodes    HA  Version
<controller-name>  <model-name>  admin  superuser  <cloud-name>/<region-name>  1       1      none  3.6.1

The following command will destroy the Juju controller and remove the cloud instance - meaning all your data will be permanently removed:

user@host:~$
juju destroy-controller <controller-name> --destroy-all-models --destroy-storage --force

To delete the Juju cloud, run

user@host:~$
juju remove-cloud <k8s-cloud-name>

List all services and then delete those that have an associated EXTERNAL-IP value (e.g. load balancers):

user@host:~$
kubectl get svc --all-namespaces
(...)
user@host:~$
kubectl delete svc <service-name>

Next, delete the EKS cluster:

user@host:~$
eksctl get cluster -A
user@host:~$
eksctl delete cluster <cluster-name> --region <region-name> --force --disable-nodegroup-eviction

See also: Amazon documentation | Delete an EKS cluster

Finally, remove AWS CLI user credentials (to avoid forgetting and leaking):

user@host:~$
rm -f ~/.aws/credentials