" Real coders don't blog, or at least not very often! " A.R.

Tutorial Kubernetes - 1ere partie


Ce tutorial illustre comment démarrer avec Kubernetes (au minimum version 1.2) en mode pas à pas. Il est basé sur l'utilisation de Google Container Engine, mais peut facilement être suivi sur un autre environnement.


Initial configuration


create new project in Cloud Console (optional)

start Cloud Shell

configure Project environment variable
$ export PROJ="xtrav42kubnormal"

create work folder
$ mkdir mykubeapp
$ cd mykubeapp



Application creation


create source file
$ vi app.go
package main
import (
    "fmt"
    "net/http"
    "os"
    "time"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
    currenttime:=time.Now().Local()
    name,err:=os.Hostname()
    if err !=nil {
        panic(err)
    }
    fmt.Printf("server: %s received request from: %s\n",name,r.RemoteAddr)
    fmt.Fprintf(w, "server: %s\n\n",name)
    fmt.Fprintf(w, "request: %s %s\n",r.Host,r.URL.Path)
    fmt.Fprintf(w, "Hello World from Go!  current local time: %s\n", currenttime.Format("20060102 15:04:05"))
    res:=dowork(30000)
    fmt.Fprintf(w, "result: %d  duration: %s\n",res,time.Since(currenttime))
}

func dowork(max int) int{
    var k int
    for i:=0; i<max; i++ {
        for j:=0; j<max; j++ {
            k=k+i*j;
        }
    }
    return k
}

func main() {
    http.HandleFunc("/", helloHandler)
    fmt.Println("serving on port 8080")
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        panic("ListenAndServe: " + err.Error())
    }
}


build application
$ go build

run application and test it from Cloud Shell with Web Preview (ctrl-c to stop the app)
$ ./mykubeapp


Docker image preparation


recompile app to be statically linked
$ CGO_ENABLED=0 go build -ldflags '-extldflags "-static"'

check the binary doesn't have any dynamic dependencies
$ ldd mykubeapp
not a dynamic executable

create simple Dockerfile
$ vi Dockerfile
FROM alpine
RUN apk add --no-cache bash
ADD mykubeapp /mykubeapp
CMD  ["/mykubeapp"]

build Docker image
$ sudo docker build -t areg/mykubeapp:1 .
Sending build context to Docker daemon 7.596 MB
Step 1 : FROM alpine
latest: Pulling from library/alpine
31b45a1205be: Pull complete
Digest: sha256:023c4a98e02ff523c38e830299bbe64f3a0c1cdde7dbd4ecacaf46986e264c94
Status: Downloaded newer image for alpine:latest
---> 31b45a1205be
Step 2 : RUN apk add --no-cache bash
---> Running in 7c510d0b6a7f
fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.4/community/x86_64/APKINDEX.tar.gz
(1/5) Installing ncurses-terminfo-base (6.0-r7)
(2/5) Installing ncurses-terminfo (6.0-r7)
(3/5) Installing ncurses-libs (6.0-r7)
(4/5) Installing readline (6.3.008-r4)
(5/5) Installing bash (4.3.42-r3)
Executing bash-4.3.42-r3.post-install
Executing busybox-1.24.2-r9.trigger
OK: 13 MiB in 16 packages
---> 45680305244f
Removing intermediate container 7c510d0b6a7f
Step 3 : ADD mykubeapp /mykubeapp
---> 44ea11cc5564
Removing intermediate container bca9116980af
Step 4 : CMD /mykubeapp
---> Running in 113da1f22c2f
---> 59dacfcbd8f8
Removing intermediate container 113da1f22c2f
Successfully built 59dacfcbd8f8

check image was successfully built
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
areg/mykubeapp 1 59dacfcbd8f8 About a minute ago 15.83 MB
alpine latest 31b45a1205be 10 weeks ago 4.799 MB

test docker image locally using Web Preview
$ sudo docker run -p 8080:8080 areg/mykubeapp:1
serving on port 8080
server: 419c0565b1a0 received request from: 172.18.0.1:39734
^C



tag image to prepare it for Google Container Registry
$ sudo docker tag areg/mykubeapp:1 gcr.io/$PROJ/mykubeapp:1

check docker images
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
areg/mykubeapp 1 59dacfcbd8f8 25 minutes ago 15.83 MB
gcr.io/xtrav42kubnormal/mykubeapp 1 59dacfcbd8f8 25 minutes ago 15.83 MB
alpine latest 31b45a1205be 10 weeks ago 4.799 MB

push image to Google Container Registry
$ gcloud docker push gcr.io/$PROJ/mykubeapp:1
The push refers to a repository [gcr.io/xtrav42kubnormal/mykubeapp] (len: 1)
59dacfcbd8f8: Pushed
44ea11cc5564: Pushed
45680305244f: Pushed
31b45a1205be: Image already exists
1: digest: sha256:10b59055e6c9e0f94f6576c4904bff00f76476baa960d1693a6ccdc3bc6ce326 size: 6088



Cluster creation on GKE


configure zone
$ gcloud config set compute/zone us-central1-a

create cluster with 3 machines of type n1-standard-1 (may take several minutes to complete)
$ gcloud container clusters create knormal --num-nodes 3 --machine-type n1-standard-1
Creating cluster knormal...done.
Created [https://container.googleapis.com/v1/projects/xtrav42kubnormal/zones/us-central1-a/clusters/knormal].
kubeconfig entry generated for knormal.
NAME ZONE MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS
knormal us-central1-a 1.3.6 23.251.157.118 n1-standard-1 1.3.6 3 RUNNING


check created nodes
$ kubectl get nodes
NAME STATUS AGE
gke-knormal-default-pool-3edb1986-gh00 Ready 12m
gke-knormal-default-pool-3edb1986-xljo Ready 12m
gke-knormal-default-pool-3edb1986-y90h Ready 12m

get credentials
$ gcloud container clusters get-credentials knormal


Application deployment as pods


create a simple 1 pod deployment with default settings
$ kubectl run mydeploy --image=gcr.io/$PROJ/mykubeapp:1 --port=8080

check created deployment
$ kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
mydeploy 1 1 1 1 10s

check created pods
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
mydeploy-2057093778-ns1mu 1/1 Running 0 6m 10.0.2.3 gke-knormal-default-pool-3edb1986-y90h

check pod logs
$ kubectl logs mydeploy-2057093778-ns1mu
serving on port 8080

create service to allow external traffic
$ kubectl expose deployment mydeploy --type="LoadBalancer"
service "mydeploy" exposed

check created service (external ip may take a while to show up)
$ kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.3.240.1 <none> 443/TCP 43m
mydeploy 10.3.249.220 <pending> 8080/TCP 22s
$ kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.3.240.1 <none> 443/TCP 43m
mydeploy 10.3.249.220 104.154.32.162 8080/TCP 1m

test access from external web browser using the service external IP http://104.154.32.162:8080


check pod logs
$ kubectl logs mydeploy-2057093778-ns1mu
serving on port 8080
server: mydeploy-2057093778-ns1mu received request from: 10.128.0.2:64558
server: mydeploy-2057093778-ns1mu received request from: 10.128.0.2:64558
server: mydeploy-2057093778-ns1mu received request from: 10.128.0.2:64558
server: mydeploy-2057093778-ns1mu received request from: 10.128.0.2:64558


September 5, 2016
784 words


Categories
Tags
cloud container kubernetes docker rkt GKE GCP

Connect. Socialize.