Table of Content
Google cloud hands-on guide: Kubernetes
qwiklabs GCP notes.
- replicated application running on Kubernetes
- Hello World node.js app
Kubernetes
- open source project kubernetes.io
- run on many diff env, vm or bare metal, public or private cloud
tasks
- Create a Node.js server
- Create a Docker container image
- Create a container cluster
- Create a Kubernetes pod
- Scale up your services
node.js app
- vi server.js on cloud shell vm
var http = require('http'); var handleRequest = function(request, response) { response.writeHead(200); response.end("Hello World!"); } var www = http.createServer(handleRequest); www.listen(8080);
- start node.js server on cloud shell vm
node server.js https://8080-dot-3285694-dot-devshell.appspot.com/?authuser=0# Ctrl-c to stop it, let's build this app in docker container.
create a docker container image
vi Dockerfile on cloud shell vm
FROM node:6.9.2 EXPOSE 8080 COPY server.js . CMD node server.js
build docker image
google151663_student@qwiklabs-gcp-f7768c03b9259cda:~$ docker build -t gcr.io/qwiklabs-gcp-f7768c03b9259cda/hello-node:v1 . Sending build context to Docker daemon 13.31kB Step 1/4 : FROM node:6.9.2 6.9.2: Pulling from library/node 75a822cd7888: Pull complete 57de64c72267: Pull complete 4306be1e8943: Pull complete 871436ab7225: Pull complete 0110c26a367a: Pull complete 1f04fe713f1b: Pull complete ac7c0b5fb553: Pull complete Digest: sha256:2e95be60faf429d6c97d928c762cb36f1940f4456ce4bd33fbdc34de94a5e043 Status: Downloaded newer image for node:6.9.2 ---> faaadb4aaf9b Step 2/4 : EXPOSE 8080 ---> Running in df36e9a28c4e ---> f7d130eb9c86 Removing intermediate container df36e9a28c4e Step 3/4 : COPY server.js . ---> 562110970e29 Removing intermediate container e040e091103c Step 4/4 : CMD node server.js ---> Running in a77b262268b0 ---> bc2cd1a7c5ec Removing intermediate container a77b262268b0 Successfully built bc2cd1a7c5ec Successfully tagged gcr.io/qwiklabs-gcp-f7768c03b9259cda/hello-node:v1 it uses Dockerfile to build image on cloud shell vm
run container as background daemon
docker run -d -p 8080:8080 gcr.io/qwiklabs-gcp-f7768c03b9259cda/hello-node:v1 google151663_student@qwiklabs-gcp-f7768c03b9259cda:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES aa06050f45a4 gcr.io/qwiklabs-gcp-f7768c03b9259cda/hello-node:v1 "/bin/sh -c 'node ..." 11 seconds ago Up 9 seconds 0.0.0.0:8080->8080/tcp zen_thompson
web preview from cloud shell or in cli
curl http://localhost:8080 google151663_student@qwiklabs-gcp-f7768c03b9259cda:~$ curl http://localhost:8080 Hello World!
stop running container
docker ps docker stop google151663_student@qwiklabs-gcp-f7768c03b9259cda:~$ docker stop aa06 aa06 google151663_student@qwiklabs-gcp-f7768c03b9259cda:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
push image to Google Container Registry
gcloud docker -- push gcr.io/qwiklabs-gcp-f7768c03b9259cda/hello-node:v1 The push refers to a repository [gcr.io/qwiklabs-gcp-f7768c03b9259cda/hello-node] c178021f499d: Pushed 381c97ba7dc3: Pushed 604c78617f34: Pushed fa18e5ffd316: Pushed 0a5e2b2ddeaa: Layer already exists 53c779688d06: Layer already exists 60a0858edcd5: Layer already exists b6ca02dfe5e6: Layer already exists v1: digest: sha256:70bbb1caf4c26ec98cd90b25b927da436de6ea23a21f4cd38402b8280fa69eb3 size: 2002
verify from Console
Tools -> Container Registry
create Kubernetes container cluster
create a cluster
gcloud container clusters create hello-world \ --num-nodes 2 \ --machine-type n1-standard-1 \ --zone us-central1-f Creating cluster hello-world...done. Created [https://container.googleapis.com/v1/projects/qwiklabs-gcp-f7768c03b9259cda/zones/us-central1-f/clusters/hello-world]. kubeconfig entry generated for hello-world. NAME ZONE MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS hello-world us-central1-f 1.7.8-gke.0 35.193.19.169 n1-standard-1 1.7.8-gke.0 2 RUNNING
you also can create this cluster through the Console:
Kubernetes Engine -> Kubernetes clusters -> Create cluster
create a pod
pod is a group of containers tied together for administration and networking purposes.
kubectl run hello-node \ --image=gcr.io/qwiklabs-gcp-f7768c03b9259cda/hello-node:v1 \ --port=8080 deployment "hello-node" created kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-node 1 1 1 0 17s kubectl get pods NAME READY STATUS RESTARTS AGE hello-node-4050909237-ztcvg 1/1 Running 0 1m kubectl cluster-info Kubernetes master is running at http://localhost:8080 To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. kubectl config view apiVersion: v1 clusters: [] contexts: [] current-context: "" kind: Config preferences: {} users: [] kubectl get events The connection to the server localhost:8080 was refused - did you specify the right host or port? kubectl logs
allow external traffic
by default pod only accessible by internal ip, so need to expose as Kubernetes service
kubectl expose deployment hello-node --type="LoadBalancer" service "hello-node" exposed
it exposes deployment object instead of pod directly,
kubectl get services google151663_student@qwiklabs-gcp-f7768c03b9259cda:~$ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-node LoadBalancer 10.3.244.236 35.194.21.36 8080:30671/TCP 47s kubernetes ClusterIP 10.3.240.1 443/TCP 11m
then yo can access external ip and port
http://35.194.21.36:8080
until now we finish Kubernetes master node
Scale up your service
easy to scale app by changing replicas number,
kubectl scale deployment hello-node --replicas=4 deployment "hello-node" scaled kubectl get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-node 4 4 4 2 8m kubectl get pods NAME READY STATUS RESTARTS AGE hello-node-4050909237-kpqp9 1/1 Running 0 25s hello-node-4050909237-ksb38 0/1 ContainerCreating 0 25s hello-node-4050909237-w8mm9 0/1 ContainerCreating 0 25s hello-node-4050909237-ztcvg 1/1 Running 0 8m
Roll out an upgrade to your service
- sometimes need to fix bug
- add new features
- Kubernetes can deploy new version without impacting services
demo steps:
change app
vi server.js # update app
response.end("Hello Kubernetes World!");
build and push new version of image after change
docker build -t gcr.io/qwiklabs-gcp-f7768c03b9259cda/hello-node:v2 . Sending build context to Docker daemon 104.4kB Step 1/4 : FROM node:6.9.2 6.9.2: Pulling from library/node 75a822cd7888: Pull complete 57de64c72267: Pull complete 4306be1e8943: Pull complete 871436ab7225: Pull complete 0110c26a367a: Pull complete 1f04fe713f1b: Pull complete ac7c0b5fb553: Pull complete Digest: sha256:2e95be60faf429d6c97d928c762cb36f1940f4456ce4bd33fbdc34de94a5e043 Status: Downloaded newer image for node:6.9.2 ---> faaadb4aaf9b Step 2/4 : EXPOSE 8080 ---> Running in 32a14049d7cb ---> 5aae102add3c Removing intermediate container 32a14049d7cb Step 3/4 : COPY server.js . ---> 44cf9d145313 Removing intermediate container f1aa3ac42dad Step 4/4 : CMD node server.js ---> Running in 49fcd42943bb ---> 07fccb268d7c Removing intermediate container 49fcd42943bb Successfully built 07fccb268d7c Successfully tagged gcr.io/qwiklabs-gcp-f7768c03b9259cda/hello-node:v2 gcloud docker -- push gcr.io/qwiklabs-gcp-f7768c03b9259cda/hello-node:v2 The push refers to a repository [gcr.io/qwiklabs-gcp-f7768c03b9259cda/hello-node] 3ccc24225f2f: Pushed 381c97ba7dc3: Pushed 604c78617f34: Pushed fa18e5ffd316: Pushed 0a5e2b2ddeaa: Layer already exists 53c779688d06: Layer already exists 60a0858edcd5: Layer already exists b6ca02dfe5e6: Layer already exists v2: digest: sha256:26ba16fde72700f5caeb6c30e7c681f5e3af3d0b507952710a4bdf7432beead1 size: 2002
Kubernetes update for new app version
kubectl edit deployment hello-node it goes to vi edit mode, change version from v1 to v2, from image: gcr.io/PROJECT_ID/hello-node:v1 to image: gcr.io/PROJECT_ID/hello-node:v2
kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-node 4 5 4 3 13m
Kubernetes dashboard
You can configure access to the Kubernetes cluster dashboard on cloud shell,
gcloud container clusters get-credentials hello-world \ --zone us-central1-f --project qwiklabs-gcp-f7768c03b9259cda kubectl proxy --port 8081
launch dashboard from web preview on cloud shell, change to below format,
https://8080-dot-3285694-dot-devshell.appspot.com/ui