Using Helm to Install Applications onto Amazon EKS

Introduction

Amazon Elastic Container Service for Kubernetes (Amazon EKS), launched at AWS Re:Invent in December 2017, became generally available on June 5, 2018.

Helm is a package manager for Kubernetes that helps define, install, and upgrade even the most complex Kubernetes applications.

This blog is to demonstrate how to use Helm to install applications onto Amazon EKS.

Prerequisite

Create an EKS Control plane and at least one worker node using eksctl command.

$ eksctl create cluster --name=demo-eks-cluster --nodes=1 --region=us-west-2

Make sure the EKS cluster is ready and storage class also created by eksctl as default.

$ kubectl get nodes
NAME STATUS ROLES VERSION
ip-192-168-20-170.us-west-2.compute.internal Ready <none> v1.11.5
$ kubectl get sc
NAME PROVISIONER AGE
gp2 (default) kubernetes.io/aws-ebs 19m

Installing and Configure Helm

Helm can be downloaded from here.

Since we are using an EC2 Linux as my workstation, we are going to get a Helm binary for the Linux platform.

$ tar xvf helm-v2.10.0-rc.1-linux-amd64.tar.tar
linux-amd64/
linux-amd64/README.md
linux-amd64/LICENSE
linux-amd64/helm

Let’s begin by putting Helm in PATH

$ cd Linux-amd64
$ sudo mv helm /usr/local/bin/
$ helm version
Client: &version.Version{SemVer:"v2.10.0-rc.1", GitCommit:"aa98e7e3dd2356bce72e8e367e8c87e8085c692b", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.10.0-rc.1", GitCommit:"aa98e7e3dd2356bce72e8e367e8c87e8085c692b", GitTreeState:"clean"}

Now let’s create a tiller service account (Tiller is the Helm server-side component)

$ kubectl create serviceaccount tiller --namespace kube-system

Create the rbac-config.yaml file

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: tiller-role-binding
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system

And run apply and helm init

$ kubectl apply -f rbac-config.yaml
clusterrolebinding.rbac.authorization.k8s.io "tiller-role-binding" configured
$ helm init --service-account tiller

We can see tiller-deploy is a running pod in kube-system namespace.

$ kubectl get pods --namespace kube-system | grep tiller
tiller-deploy-fd7676c54-dvvl7 1/1 Running 0 1d

Installing a MySQL database server using Helm

Now we can use Helm to install applications on EKS

$ helm search

You should be able to see a list of applications in the Helm repo that can be installed.

Let’s first update the repo.

$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Skip local chart repository
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈ Happy Helming!⎈

Next we do an actual install of MySQL database server as an example to show how to use helm to install an application.

$ helm install stable/mysql

We get a list of outputs from this command.

NAME:   kilted-marmot
LAST DEPLOYED: Sun Jul 8 19:55:50 2018
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Secret
NAME TYPE DATA AGE
kilted-marmot-mysql Opaque 2 0s
==> v1/ConfigMap
NAME DATA AGE
kilted-marmot-mysql-test 1 0s
==> v1/PersistentVolumeClaim
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
kilted-marmot-mysql Pending gp2 0s
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kilted-marmot-mysql ClusterIP 10.100.226.235 <none> 3306/TCP 0s
==> v1beta1/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
kilted-marmot-mysql 1 1 1 0 0s
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
kilted-marmot-mysql-69ccb5947-dmgb4 0/1 Pending 0 0s
NOTES:
MySQL can be accessed via port 3306 on the following DNS name from within your cluster:
kilted-marmot-mysql.default.svc.cluster.local
To get your root password run:
MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default kilted-marmot-mysql -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echo)
To connect to your database:
1. Run an Ubuntu pod that you can use as a client:
kubectl run -i --tty ubuntu --image=ubuntu:16.04 --restart=Never -- bash -il
2. Install the mysql client:
$ apt-get update && apt-get install mysql-client -y
3. Connect using the mysql cli, then provide your password:
$ mysql -h kilted-marmot-mysql -p
To connect to your database directly from outside the K8s cluster:
MYSQL_HOST=127.0.0.1
MYSQL_PORT=3306
# Execute the following commands to route the connection:
export POD_NAME=$(kubectl get pods --namespace default -l "app=kilted-marmot-mysql" -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward $POD_NAME 3306:3306
mysql -h ${MYSQL_HOST} -P${MYSQL_PORT} -u root -p${MYSQL_ROOT_PASSWORD}

Follow the first line of instructions from the output to acquire our root password.

$ MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default kilted-marmot-mysql -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echo)
$ echo $MYSQL_ROOT_PASSWORD
whg23msmdT

Establishing a connection

To connect to your database:

1. Run an Ubuntu pod that you can use as a client:

$ kubectl run -i --tty ubuntu --image=ubuntu:16.04 --restart=Never -- bash -il
If you don't see a command prompt, try pressing enter.
root@ubuntu:/#

2. Install the mysql client:

root@ubuntu:/# apt-get update && apt-get install mysql-client -y

3. Connect using the mysql cli, then provide your password, check database is connected.

root@ubuntu:/#  mysql -h kilted-marmot-mysql -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 76
Server version: 5.7.14 MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.01 sec)