This is a run through simple demonstration of deploying application using Kubectl and Kubernetes using Amazon EKS.
Kubernetes aims to run containers across many different machines and scaling up or down by adding or removing containers when demand changes.
I’ts been a while since I posted on this blog. So here it goes. 😀
I. Prerequisites
Before we can start we need to setup some accounts and command-line utilities:
1. AWS Account
2. EC2 Key Pair — Create an EC2 Key Pair if you don’t already have one.
3. AWS CLI — Amazon EKS requires at least version 1.15.32 of the AWS CLI
4. Document for EKS: https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html
II. Setup and Configure kubectl for Amazon EKS
$ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
$ sudo touch /etc/apt/sources.list.d/kubernetes.list
$ echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list
$ sudo apt-get update
$ sudo apt-get install -y kubectl
$ aws eks update-kubeconfig --name so_cluster
III. Installing aws-iam-authenticator:
$ go get -u -v github.com/kubernetes-sigs/aws-iam-authenticator/cmd/aws-iam-authenticator
$ export PATH=$HOME/go/bin:$PATH && echo 'export PATH=$HOME/go/bin:$PATH' >> ~/.bashrc
IV. Create Worker Nodes: Common Problems
1. The cluster-name should be equal to the cluster created on the Cloud Formation parameter.
2. The NodeInstanceRole value from Cloud Formation Stack Output and placing it at aws-auth-cm.yaml rolearn as value.
Filename: aws-auth-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- rolearn: <ARN of instance role (not instance profile)>
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers
- system:nodes
When everything is up and working good, we should be able to see it running:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
ip-172-30-0-28.ec2.internal Ready <none> 6m v1.11.5
ip-172-30-4-123.ec2.internal Ready <none> 6m v1.11.5
$ kubectl get svc --all-namespaces
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 32m
kube-system kube-dns ClusterIP 10.100.0.10 <none> 53/UDP,53/TCP 32m
Get some Nginx running on this cluster, create replica:
$ kubectl create deployment nginx --image=nginx
deployment.apps/nginx created
$ kubectl scale deployment --replicas 2 nginx
$ kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
default nginx-78f5d695bd-8qvmx 1/1 Running 0 28s
default nginx-78f5d695bd-fq6dc 1/1 Running 0 4m
kube-system aws-node-wc7sc 1/1 Running 0 16m
kube-system aws-node-xjrqh 1/1 Running 0 16m
kube-system coredns-7bcbfc4774-5psht 1/1 Running 0 41m
kube-system coredns-7bcbfc4774-wrmwx 1/1 Running 0 41m
kube-system kube-proxy-522bd 1/1 Running 0 16m
kube-system kube-proxy-jw2l9 1/1 Running 0 16m
Expose Nginx to the public:
$ kubectl expose deployment nginx --port=80 --type=LoadBalancer
service/nginx exposed
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 53m
nginx LoadBalancer 10.100.163.52 ac198ac591ed911e9be5812b977585b7-343561898.us-east-1.elb.amazonaws.com 80:32267/TCP 4m
The EXTERNAL IP provided is an URL where we can map as CNAME to our Route53 or DNS. We can check by hitting the URL too:
In some cases the deployment and services are bundled as JSON like this one on the sample guestbook, we can run it like:
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook/all-in-one/guestbook-all-in-one.yaml
service/redis-master created
deployment.apps/redis-master created
service/redis-slave created
deployment.apps/redis-slave created
service/frontend created
deployment.apps/frontend created
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend ClusterIP 10.100.94.40 <none> 80/TCP 1m
kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 1h
nginx LoadBalancer 10.100.163.52 ac198ac591ed911e9be5812b977585b7-343561898.us-east-1.elb.amazonaws.com 80:32267/TCP 18m
redis-master ClusterIP 10.100.36.121 <none> 6379/TCP 1m
redis-slave ClusterIP 10.100.168.28 <none> 6379/TCP 1m
Oops, there we can’t access the guestbook publicly. We need to patch because I forgot to uncomment the type=Loadbalancer, but we can easily create a patch file of that service and do the command below:
$ kubectl patch svc frontend --patch "$(cat frontend_service.patch)"
service/frontend patched
$kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend LoadBalancer 10.100.94.40 a395b01401edc11e9b7f40eb3bd0ef0f-1905156859.us-east-1.elb.amazonaws.com 80:32584/TCP 8m
kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 1h
nginx LoadBalancer 10.100.163.52 ac198ac591ed911e9be5812b977585b7-343561898.us-east-1.elb.amazonaws.com 80:32267/TCP 25m
redis-master ClusterIP 10.100.36.121 <none> 6379/TCP 8m
redis-slave ClusterIP 10.100.168.28 <none> 6379/TCP 8m
Yeah so here it goes our Guestbook.
Finally, if we want to see how the dashboard looks like, we can view that too by applying the dashboard json files and running kubectl proxy. Here’s the snapshot of the dashboard.
Go fire up Dockerized apps using Kubernetes and if you need a Kubernets guy? Please reach out. 🙂