├── .gitignore ├── go.mod ├── minikube.txt ├── go.sum ├── Dockerfile ├── main.go └── k8s-deployment.yml /.gitignore: -------------------------------------------------------------------------------- 1 | main 2 | go-kubernetes 3 | out/ 4 | vendor/ 5 | _vendor-* 6 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/callicoder/go-kubernetes 2 | 3 | require github.com/gorilla/mux v1.7.3 4 | -------------------------------------------------------------------------------- /minikube.txt: -------------------------------------------------------------------------------- 1 | Run the following command to get the service endpoint using minikube 2 | 3 | minikube service go-hello-world-service --url -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= 2 | github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 3 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Dockerfile References: https://docs.docker.com/engine/reference/builder/ 2 | 3 | # Start from the latest golang base image 4 | FROM golang:latest as builder 5 | 6 | # Add Maintainer Info 7 | LABEL maintainer="Rajeev Singh " 8 | 9 | # Set the Current Working Directory inside the container 10 | WORKDIR /app 11 | 12 | # Copy go mod and sum files 13 | COPY go.mod go.sum ./ 14 | 15 | # Download all dependancies. Dependencies will be cached if the go.mod and go.sum files are not changed 16 | RUN go mod download 17 | 18 | # Copy the source from the current directory to the Working Directory inside the container 19 | COPY . . 20 | 21 | # Build the Go app 22 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main . 23 | 24 | 25 | ######## Start a new stage from scratch ####### 26 | FROM alpine:latest 27 | 28 | RUN apk --no-cache add ca-certificates 29 | 30 | WORKDIR /root/ 31 | 32 | # Copy the Pre-built binary file from the previous stage 33 | COPY --from=builder /app/main . 34 | 35 | # Expose port 8080 to the outside world 36 | EXPOSE 8080 37 | 38 | # Command to run the executable 39 | CMD ["./main"] -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "net/http" 8 | "os" 9 | "os/signal" 10 | "syscall" 11 | "time" 12 | 13 | "github.com/gorilla/mux" 14 | ) 15 | 16 | func handler(w http.ResponseWriter, r *http.Request) { 17 | query := r.URL.Query() 18 | name := query.Get("name") 19 | if name == "" { 20 | name = "Guest" 21 | } 22 | log.Printf("Received request for %s\n", name) 23 | w.Write([]byte(fmt.Sprintf("Hello, %s\n", name))) 24 | } 25 | 26 | func healthHandler(w http.ResponseWriter, r *http.Request) { 27 | w.WriteHeader(http.StatusOK) 28 | } 29 | 30 | func readinessHandler(w http.ResponseWriter, r *http.Request) { 31 | w.WriteHeader(http.StatusOK) 32 | } 33 | 34 | func main() { 35 | // Create Server and Route Handlers 36 | r := mux.NewRouter() 37 | 38 | r.HandleFunc("/", handler) 39 | r.HandleFunc("/health", healthHandler) 40 | r.HandleFunc("/readiness", readinessHandler) 41 | 42 | srv := &http.Server{ 43 | Handler: r, 44 | Addr: ":8080", 45 | ReadTimeout: 10 * time.Second, 46 | WriteTimeout: 10 * time.Second, 47 | } 48 | 49 | // Start Server 50 | go func() { 51 | log.Println("Starting Server") 52 | if err := srv.ListenAndServe(); err != nil { 53 | log.Fatal(err) 54 | } 55 | }() 56 | 57 | // Graceful Shutdown 58 | waitForShutdown(srv) 59 | } 60 | 61 | func waitForShutdown(srv *http.Server) { 62 | interruptChan := make(chan os.Signal, 1) 63 | signal.Notify(interruptChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) 64 | 65 | // Block until we receive our signal. 66 | <-interruptChan 67 | 68 | // Create a deadline to wait for. 69 | ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 70 | defer cancel() 71 | srv.Shutdown(ctx) 72 | 73 | log.Println("Shutting down") 74 | os.Exit(0) 75 | } 76 | -------------------------------------------------------------------------------- /k8s-deployment.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment # Type of Kubernetes resource 4 | metadata: 5 | name: go-hello-world # Name of the Kubernetes resource 6 | spec: 7 | replicas: 3 # Number of pods to run at any given time 8 | selector: 9 | matchLabels: 10 | app: go-hello-world # This deployment applies to any Pods matching the specified label 11 | template: # This deployment will create a set of pods using the configurations in this template 12 | metadata: 13 | labels: # The labels that will be applied to all of the pods in this deployment 14 | app: go-hello-world 15 | spec: # Spec for the container which will run in the Pod 16 | containers: 17 | - name: go-hello-world 18 | image: callicoder/go-hello-world:1.0.0 19 | imagePullPolicy: Always 20 | ports: 21 | - containerPort: 8080 # Should match the port number that the Go application listens on 22 | livenessProbe: # To check the health of the Pod 23 | httpGet: 24 | path: /health 25 | port: 8080 26 | scheme: HTTP 27 | initialDelaySeconds: 5 28 | periodSeconds: 15 29 | timeoutSeconds: 5 30 | readinessProbe: # To check if the Pod is ready or not 31 | httpGet: 32 | path: /readiness 33 | port: 8080 34 | scheme: HTTP 35 | initialDelaySeconds: 5 36 | timeoutSeconds: 1 37 | --- 38 | apiVersion: v1 39 | kind: Service # Type of kubernetes resource 40 | metadata: 41 | name: go-hello-world-service # Name of the resource 42 | spec: 43 | type: NodePort # If you're deploying on cloud, you can use `type: LoadBalancer`. It will automatically provision a load balancer with the cloud provider that will route traffic to your application. 44 | ports: # Take incoming HTTP requests on port 9090 and forward them to the targetPort of 8080 45 | - name: http 46 | port: 9090 47 | targetPort: 8080 48 | selector: 49 | app: go-hello-world # Map any pod with name go-hello-world to this service 50 | --------------------------------------------------------------------------------