How to deploy an Echo app with HTTPS in GKE?
Using Echo framework developed a web app. Set https://<DOMAIN> feature with its Auto TLS.
package main
import (
"net/http"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"golang.org/x/crypto/acme/autocert"
)
func main() {
e := echo.New()
env := os.Getenv("ENV")
if env == "prod" {
e.AutoTLSManager.HostPolicy = autocert.HostWhitelist("arealdomain.com")
e.AutoTLSManager.Cache = autocert.DirCache("/var/www/cert")
e.Pre(middleware.HTTPSWWWRedirect())
}
e.GET("/healthcheck", func(c echo.Context) error {
return c.JSON(http.StatusOK, {"ok"})
})
switch env {
case "prod":
e.Logger.Fatal(e.StartAutoTLS(":8443"))
case "dev":
e.Logger.Fatal(e.Start(":9000"))
default:
e.Logger.Fatal(e.Start(":9000"))
}
}
Deployed it in Kubernetes.
development.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: testapp
spec:
selector:
matchLabels:
app: testapp
replicas: 3
template:
metadata:
labels:
app: testapp
spec:
containers:
- name: testapp
image: gcr.io/<PROJECT_ID>/testapp
ports:
- containerPort: 9000
- containerPort: 8443
livenessProbe:
initialDelaySeconds: 10
periodSeconds: 10
exec:
command:
- "true"
readinessProbe:
initialDelaySeconds: 5
periodSeconds: 20
httpGet:
path: /healthcheck
port: 9000
service.yml
apiVersion: v1
kind: Service
metadata:
name: testapp
spec:
type: NodePort
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9000
selector:
app: testapp
ingress.yml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: testingress
annotations:
kubernetes.io/ingress.global-static-ip-name: testip // a real IP
networking.gke.io/managed-certificates: testcertificate
kubernetes.io/ingress.class: "gce"
spec:
backend:
serviceName: testapp
servicePort: 80
managedcertificate.yml
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: testcertificate
spec:
domains:
- arealdomain.com // a real domain
After deployed these resources, access domain arealdomain.com, got 502 error:
Error: Server Error
The server encountered a temporary error and could not complete your request.
Please try again in 30 seconds.
From GCP's network loadbalancer, got one service is unhealthy.

Maybe firewall issue: https://cloud.google.com/load-balancing/docs/https/ext-http-lb-simple#firewall
Check kubernetes's deployment pod, found this error:
Readiness probe failed: HTTP probe failed with statuscode: 400
Since want to deploy this web app can be used by https, so deployed it with 8443 port only. Use site like: https://arealdomain.com But if do healthcheck, does GCP need other port? What's the best practice to do this deployment to GCP? Is it necessary to use Nginx to serve both 9000 and 8443 port inside app?
When change to use 80 port in Ingress, also deployed application on 9000 port, the pod can start but neg check seems can't pass.
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal LoadBalancerNegNotReady 115s neg-readiness-reflector Waiting for pod to become healthy in at least one of the NEG(s): [k8s1-173zho00-default-testapp-80-l4cadn29]
Normal Scheduled 115s default-scheduler Successfully assigned default/testapp-2c6f02f021-afjls to gke-<project_name>-default-pool-asfjo2c5-afjl
Normal Pulling 114s kubelet, gke-<project_name>-default-pool-asfdl0-asl3 Pulling image "gcr.io/<project_name>/testapp"
Normal Pulled 109s kubelet, gke-<project_name>-default-pool-asfdl0-asl3 Successfully pulled image "gcr.io/<project_name>/testapp"
Normal Created 109s kubelet, gke-<project_name>-default-pool-asfdl0-asl3 Created container testapp
Normal Started 109s kubelet, gke-<project_name>-default-pool-asfdl0-asl3 Started container testapp
Normal LoadBalancerNegWithoutHealthCheck 94s neg-readiness-reflector Pod is in NEG "Key{\"k8s1-173zho00-default-testapp-80-l4cadn29\", zone: \"southamerica-east1-c\"}". NEG is not attached to any BackendService with health checking. Marking condition "cloud.google.com/load-balancer-neg-ready" to True.
I found this article, how to set cloud.google.com/load-balancer-neg-ready to True?
The GCP network's Load balancer details still showing unhealthy.

From Health Check details, the path didn't been set to /healthcheck but /. Where is wrong?

If you are just starting with GKE I recommend you to just create the service and deployment and use the UI to create the ingress and the managed certs
I created and deploy a sample application:
Code in main.go
package main
import (
"log"
"net/http"
)
func main() {
// change this handlers for echo handlers
http.HandleFunc("/", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(http.StatusOK)
rw.Write([]byte("Hello World..."))
}))
http.HandleFunc("/health", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(http.StatusOK)
}))
log.Panic(http.ListenAndServe(":8080", nil))
}
Dockerfile
FROM golang:alpine AS builder
RUN apk add --no-cache git
WORKDIR /go/src/app
COPY . .
RUN go build -o bin main.go
#final stage
FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY --from=builder /go/src/app/bin /app
ENTRYPOINT ./app
EXPOSE 8080
k8s-artifacts.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: testapp
spec:
selector:
matchLabels:
app: testapp
replicas: 3
template:
metadata:
labels:
app: testapp
spec:
containers:
- name: testapp
image: gcr.io/<ACCOUNT>/test
ports:
- containerPort: 8080
livenessProbe:
initialDelaySeconds: 10
periodSeconds: 10
exec:
command:
- "true"
readinessProbe:
initialDelaySeconds: 5
periodSeconds: 20
httpGet:
path: /health
port: 8080
---
apiVersion: v1
kind: Service
metadata:
name: testapp
spec:
type: NodePort
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080
selector:
app: testapp
---
apiVersion: "extensions/v1beta1"
kind: "Ingress"
metadata:
name: "lb-2"
namespace: "default"
spec:
backend:
serviceName: "testapp"
servicePort: 80
With that in place, you will have at least an http ingress which you can access through the internet. After that, and when you have validated that your service is up and running, you can edit the front-end of the load balancer to add the https rules and your managed cert
Update
After verifying that the lb is up and running

To edit the load balancer go to the ingress details
At the bottom of the page there are links to the load balancers managed by GCE 
Select the load balancer and edit it 
Go to front end configuration and configure a new front end and port for https

Update 2
You can also create directly the new ingress with the managed cert. For example: First, create the managed cert
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: test-cert
spec:
domains:
- test-domain.com
After that, just create a new ingress in the services and ingresses section of GKE

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With