☸️ Kubernetes - Go Example
Updated at 2018-12-31 02:57
This note shows how to host a simple Go web server using Kubernetes.
brew update
brew install go
Create hello.go
:
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":3000", nil))
}
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello from Go!")
}
# Test that it works:
go run hello.go
# Navigate to http://localhost.local:3000/
# Compile to Linux binary:
CGO_ENABLED=0 GOOS=linux go build -o hello -a -tags netgo -ldflags '-w' .
Define Dockerfile
:
FROM scratch
ADD hello /
CMD ["/hello"]
Setup Docker your registry:
# Install Docker Toolbox
# https://www.docker.com/products/docker-toolbox
# Start Docker Quickstart Terminatel
docker --version
# => Docker version 1.10.2, build c3959b1
# Setup DockerHub repository
# https://hub.docker.com/ > Create Repository > gobernetes > ruksi/gobernetes
# https://hub.docker.com/r/ruksi/gobernetes/
docker build -t ruksi/gobernetes:v1 .
docker run --rm -p 3000:3000 ruksi/gobernetes:v1
# Navigate to http://dockerhost:3000/ (IP of the Docker VM)
# Resulting Docker iamge is something like 5MB, crazy!
docker login
docker push ruksi/gobernetes:v1
Setup Google Cloud SDK:
# Install Google Cloud SDK (gcloud)
# https://cloud.google.com/sdk/downloads#interactive
# Make sure you have Python 2.7 as `python --version`
curl https://sdk.cloud.google.com | bash
# Restart shell
gcloud init
gcloud components update kubectl
# Create new project here: https://console.cloud.google.com/project?pli=1
# Name: gobernetes, you get the ID
# Compute Engine > Get Started > Enable Billing
gcloud config set project gobernetes
gcloud compute zones list
gcloud config set compute/zone us-central1-a
gcloud config list # see current configuration
Managing a Kubernetes cluster:
# Creates VM instance group with 3 instances:
gcloud container clusters create gobernetes-app
# To inspect clusters:
gcloud container clusters list
gcloud container clusters describe gobernetes-app
# To delete the cluster:
gcloud container clusters delete gobernetes-app
Load Balancer
Load balancer service distributes your traffic to all underlying pods. At least one pod must be running at initialization.
Define balancer.yaml
:
apiVersion: "v1"
kind: "Service"
metadata: name: "gobernetes-balancer"
labels: name: "gobernetes-balancer"
spec: type: "LoadBalancer"
ports: - name: "http"
port: 80
targetPort: 3000
selector: name: "gobernetes"
kubectl create -f balancer.yaml
kubectl get services
kubectl describe services gobernetes-balancer
# Rerun until you see "LoadBalancer Ingress" value in the summary.
# Use that to connect to the load balancer e.g. http://104.197.91.49/
# To delete it:
kubectl delete service gobernetes-balancer
Replication Controller
A replication controller ensures that a specified number of pod "replicas" are running at any one time.
Define rc.yaml
to tell replication controller what a pod looks like. Note that all the -v1
definitions after controller name are important as each new release mush have different identifier.
apiVersion: "v1"
kind: "ReplicationController"
metadata:
name: "gobernetes-rc-v1"
labels:
name: "gobernetes-rc-v1"
spec:
replicas: 3
selector:
name: "gobernetes"
version: "v1"
template:
metadata:
labels:
name: "gobernetes"
version: "v1"
spec:
containers:
- name: "gobernetes"
image: "ruksi/gobernetes:v1"
ports:
- name: "http"
containerPort: 3000
protocol: "TCP"
kubectl get pods
kubectl delete pods gobernetes
kubectl get pods
kubectl create -f rc.yaml
kubectl get pods
kubectl get rc
kubectl describe rc gobernetes-rc-v1
# You can try out the replication by deleting a pod and quickly list pods:
kubectl delete pods gobernetes-rc-v1-875xg
kubectl get pods
# You can modify the scale:
kubectl scale --replicas=5 -f rc.yaml
kubectl get pods
# To delete:
kubectl delete rc gobernetes-rc-v1
Releasing New Versions
Create a new version of the application:
rm hello
# Edit the Go file...
CGO_ENABLED=0 GOOS=linux go build -o hello -a -tags netgo -ldflags '-w' .
docker build -t ruksi/gobernetes:v2 .
docker push ruksi/gobernetes:v2
The best approach is to update the YAML specification:
apiVersion: "v1"
kind: "ReplicationController"
metadata:
name: "gobernetes-rc-v2"
labels:
name: "gobernetes-rc-v2"
spec:
replicas: 3
selector:
name: "gobernetes"
version: "v2"
template:
metadata:
labels:
name: "gobernetes"
version: "v2"
spec:
containers:
- name: "gobernetes"
image: "ruksi/gobernetes:v2"
ports:
- name: "http"
containerPort: 3000
protocol: "TCP"
kubectl rolling-update gobernetes-rc-v1 -f rc.yaml
# Kubernetes starts switching 1 pod at a time to the new version
# so you are momentarily serving two versions.
# The new controller will be named `gobernetes-rc-v2` per rc.yaml
# If you navigate to the load balancer URL, you can see that it has updated.