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 22.04+

  • Juju 2.9+ installed via snap

  • See System requirements


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 14/stable --trust -n 3
Deployed "postgresql-k8s" from charm-hub charm "postgresql-k8s", revision <number> in channel 14/stable on ubuntu@22.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