Deploying our application
In this part we will:
- generate the kubernetes manifest files with hive
- show that their automation is done by the hive variable system
- create a docker hub account
- push our server docker image to docker.hub
- deploy our server into our cluster
- make some scaling operations
Generate the kubernetes manifests
We need to generate two files:
- A replicationController manifest to manage our container in the cluster
- A service manifest to make our server accessible in the kubernetes environment
./hive template kubernetes myProjectName mySubProjectName --rc --svc
Look to your subproject, you will have a kubernetes folder with two yaml files:
- replicationController:
hive.rc.yml
apiVersion: v1
kind: ReplicationController
metadata:
name: "<% mySubProjectName.name="" %="">-<% mySubProjectName.major="" %="">-<% mySubProjectName.minor="" %="">-<% cli.id="" %="">"
labels:
name: "<% mySubProjectName.name="" %="">"
major: "<% mySubProjectName.major="" %="">"
minor: "<% mySubProjectName.minor="" %="">"
build: "<% cli.id="" %="">"
spec:
replicas: 1
selector:
name: "<% mySubProjectName.name="" %="">"
major: "<% mySubProjectName.major="" %="">"
minor: "<% mySubProjectName.minor="" %="">"
build: "<% cli.id="" %="">"
template:
metadata:
labels:
name: "<% mySubProjectName.name="" %="">"
major: "<% mySubProjectName.major="" %="">"
minor: "<% mySubProjectName.minor="" %="">"
build: "<% cli.id="" %="">"
spec:
containers:
- name: "<% mySubProjectName.name="" %="">"
image: "<% mySubProjectName.image="" %="">:<% mySubProjectName.major="" %="">.<% mySubProjectName.minor="" %="">.<% cli.id="" %="">"
imagePullPolicy: Always
- service:
hive.svc.yml
apiVersion: v1
kind: Service
metadata:
name: "<% mySubProjectName.name="" %="">"
labels:
name: "<% mySubProjectName.name="" %="">"
major: "<% mySubProjectName.major="" %="">"
spec:
selector:
name: "<% mySubProjectName.name="" %="">"
major: "<% mySubProjectName.major="" %="">"
ports:
- port: 80
targetPort: 80
name: "http"
You can see that most of the elements are linked to our configuration file hive.yml.
The port is not linked to configuration element and is bind to 80. It's easy to update 80 to <% mySubprojectName.port %> and to do the same in the nginx configuration. That's where hive variable system start to remove pain of all this devops stuff.
Expose the service to the internet
Open the hive.svc.yml and add spec.type: "LoadBalancer" :
apiVersion: v1
kind: Service
metadata:
name: "<% mySubProjectName.name="" %="">"
labels:
name: "<% mySubProjectName.name="" %="">"
major: "<% mySubProjectName.major="" %="">"
spec:
selector:
name: "<% mySubProjectName.name="" %="">"
major: "<% mySubProjectName.major="" %="">"
ports:
- port: 80
targetPort: 80
name: "http"
type: "LoadBalancer"
That new parameter will ask the google cluster to link mySubProjectName service to a PUBLIC IP.
Push our container to docker.hub
Go to docker hub and create an account.
Then loggin the docker client with your new credentials:
$ ./hive docker cli login
Username: tdeheurles
Password: xxxxxxxxx
Email: [email protected]
WARNING: login credentials saved in /root/.docker/config.json
Login Succeeded
Your login are now saved in a data container named hive_docker.
Update your subproject image name to match your account in the hive.yml file. The image need to match login/subprojectname:
apiVersion: v0
kind: HiveConfig
spec:
configuration:
project: myProjectName
maintainer: [email protected]
mySubProjectName:
image: tdeheurles/mysubprojectname
major: 0
minor: 0
base: nginx:1.9.7
name: mysubprojectname
Build with the new image name:
$ ./hive do build myProjectName mySubProjectName id 0
Sending build context to Docker daemon 8.192 kB
Step 1 : FROM nginx:1.9.7
---> ef2443712c5b
Step 2 : MAINTAINER [email protected]
---> Using cache
---> 5b1464e74220
Step 3 : COPY index.html /usr/share/nginx/html/index.html
---> Using cache
---> 35ec10fb5140
Successfully built 35ec10fb5140
And Push our project image:
$ ./hive do push myProjectName mySubProjectName id 0
The push refers to a repository [docker.io/tdeheurles/mysubprojectname]
b9d0b6d06bee: Pushed
5f70bf18a086: Pushed
0b3fbb980e2d: Pushed
40f240c1cbdb: Pushed
673cf6d9dedb: Pushed
ebfc3a74f160: Pushed
031458dc7254: Pushed
12e469267d21: Pushed
0.0: digest: sha256:14cc73daf69eafbe445df41278e7695c1a842da67a2a9df8c6012e0881e24fa8 size: 8127
The push refers to a repository [docker.io/tdeheurles/mysubprojectname]
b9d0b6d06bee: Layer already exists
5f70bf18a086: Layer already exists
0b3fbb980e2d: Layer already exists
40f240c1cbdb: Layer already exists
673cf6d9dedb: Layer already exists
ebfc3a74f160: Layer already exists
031458dc7254: Layer already exists
12e469267d21: Layer already exists
0.0.0: digest: sha256:02ff3a4f0370a12f3783302be2171ad2a09085a099b13e28bff6bd5f13cc3f4a size: 8129
Let's deploy it
First control that our kubectl cli is linked to our cluster:
$ ./hive kubernetes cli get nodes
NAME LABELS STATUS AGE
gke-mycluster-7dd21d65-node-c5g4 kubernetes.io/hostname=gke-mycluster-7dd21d65-node-c5g4 Ready 28m
gke-mycluster-7dd21d65-node-lolq kubernetes.io/hostname=gke-mycluster-7dd21d65-node-lolq Ready 39m
Then, deploy the id 0 of our application in the environment test:
$ ./hive kubernetes deploy myProjectName test 0
namespace "test" created
==================
service "mysubprojectname" created
==================
replicationcontroller "mysubprojectname-0-0-0" created
- control its status with:
$ ./hive kubernetes namespaces
NAME LABELS STATUS AGE
default <none> Active 57m
kube-system <none> Active 57m
test project=myProjectName Active 1m
Here we can see that our test environment is deployed. default and kube-system are environment used by the kubernetes cluster.
- and:
$ ./hive kubernetes status test
==================== SERVICES ====================
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE
mysubprojectname 10.19.255.185 80/TCP major=0,name=mysubprojectname 37s
======================= RC =======================
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS AGE
mysubprojectname-0-0-0 mysubprojectname tdeheurles/mysubprojectname:0.0.0 build=0,major=0,minor=0,name=mysubprojectname 1 37s
====================== PODS ======================
NAME READY STATUS RESTARTS AGE
mysubprojectname-0-0-0-bcf1p 1/1 Running 0 38s
====================== NODES =====================
NAME LABELS STATUS AGE
gke-mycluster-7dd21d65-node-c5g4 kubernetes.io/hostname=gke-mycluster-7dd21d65-node-c5g4 Ready 58m
gke-mycluster-7dd21d65-node-lolq kubernetes.io/hostname=gke-mycluster-7dd21d65-node-lolq Ready 1h
We can see:
- our service
mysubprojectnamerunning on CLUSTER_IP 10.19.255.185 and exposingport 80 - the EXTERNAL_IP is blank as we need to wait around one minute for it to appear (re run the command in a minute to see it)
- our replicationController
mysubprojectname-0-0-0. It runs the imagetdeheurles/mysubprojectname:0.0.0with1 REPLICAS - the pod
mysubprojectname-0-0-0-bcf1p. A pod is the kubernetes unit, it can host multiple container at once. Here it only host our container.
Run the command again to obtain your EXTERNAL_IP:
$ ./hive kubernetes status test
==================== SERVICES ====================
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE
mysubprojectname 10.19.255.185 104.155.76.170 80/TCP major=0,name=mysubprojectname 4m
======================= RC =======================
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS AGE
mysubprojectname-0-0-0 mysubprojectname tdeheurles/mysubprojectname:0.0.0 build=0,major=0,minor=0,name=mysubprojectname 1 4m
====================== PODS ======================
NAME READY STATUS RESTARTS AGE
mysubprojectname-0-0-0-bcf1p 1/1 Running 0 4m
====================== NODES =====================
NAME LABELS STATUS AGE
gke-mycluster-7dd21d65-node-c5g4 kubernetes.io/hostname=gke-mycluster-7dd21d65-node-c5g4 Ready 1h
gke-mycluster-7dd21d65-node-lolq kubernetes.io/hostname=gke-mycluster-7dd21d65-node-lolq Ready 1h
And control that it work:
$ curl 104.155.76.170
Hello from the Hive
GREAT ^^ JOB DONE !
SCALING
It's now really easy to scale up our application (as this application just require more pods).
Just run the following command giving the environment test, the replication controller name mysubprojectname-0-0-0 and the targeted number of replicas 5:
$ ./hive kubernetes scale test mysubprojectname-0-0-0 5
replicationcontroller "mysubprojectname-0-0-0" scaled
Look at the updated status:
$ ./hive kubernetes status test
==================== SERVICES ====================
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE
mysubprojectname 10.19.255.185 104.155.76.170 80/TCP major=0,name=mysubprojectname 11m
======================= RC =======================
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS AGE
mysubprojectname-0-0-0 mysubprojectname tdeheurles/mysubprojectname:0.0.0 build=0,major=0,minor=0,name=mysubprojectname 5 11m
====================== PODS ======================
NAME READY STATUS RESTARTS AGE
mysubprojectname-0-0-0-2gu73 1/1 Running 0 1m
mysubprojectname-0-0-0-bcf1p 1/1 Running 0 11m
mysubprojectname-0-0-0-exfnj 1/1 Running 0 1m
mysubprojectname-0-0-0-j3rq6 1/1 Running 0 1m
mysubprojectname-0-0-0-lamgr 1/1 Running 0 1m
====================== NODES =====================
NAME LABELS STATUS AGE
gke-mycluster-7dd21d65-node-c5g4 kubernetes.io/hostname=gke-mycluster-7dd21d65-node-c5g4 Ready 1h
gke-mycluster-7dd21d65-node-lolq kubernetes.io/hostname=gke-mycluster-7dd21d65-node-lolq Ready 1h
We have now 5 replicas (5 PODS) of our application. The replicationController REPLICAS is now set to 5.
Cleanup
We can stop the application (not the cluster) by running:
# don't do if you want to continue
./hive kubernetes delete test
Updating the application
Let's look at how to update our application
Billing
To stop the billing, you need to shutdown the cluster by running, do it if you don't want to continue the tutorial:
./hive gcloud delete mycluster