<p>How to deploy an Echo app with HTTPS in GKE?</p>
<p>Using <a href="https://echo.labstack.com/" rel="nofollow noreferrer">Echo</a> framework developed a web app. Set <code>https://&lt;DOMAIN&gt;</code> feature with its <a href="https://echo.labstack.com/cookbook/auto-tls" rel="nofollow noreferrer">Auto TLS</a>.</p>
<pre><code>package main

import (
    &quot;net/http&quot;

    &quot;github.com/labstack/echo/v4&quot;
    &quot;github.com/labstack/echo/v4/middleware&quot;
    &quot;golang.org/x/crypto/acme/autocert&quot;
)

func main() {
    e := echo.New()
    env := os.Getenv(&quot;ENV&quot;)
    if env == &quot;prod&quot; {
        e.AutoTLSManager.HostPolicy = autocert.HostWhitelist(&quot;arealdomain.com&quot;)
        e.AutoTLSManager.Cache = autocert.DirCache(&quot;/var/www/cert&quot;)
        e.Pre(middleware.HTTPSWWWRedirect())
    }

    e.GET(&quot;/healthcheck&quot;, func(c echo.Context) error {
        return c.JSON(http.StatusOK, {&quot;ok&quot;})
    })

    switch env {
    case &quot;prod&quot;:
        e.Logger.Fatal(e.StartAutoTLS(&quot;:8443&quot;))
    case &quot;dev&quot;:
        e.Logger.Fatal(e.Start(&quot;:9000&quot;))
    default:
        e.Logger.Fatal(e.Start(&quot;:9000&quot;))
    }
}
</code></pre>
<p>Deployed it in Kubernetes.</p>
<p>development.yml</p>
<pre><code>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/&lt;PROJECT_ID&gt;/testapp
      ports:
      - containerPort: 9000
      - containerPort: 8443
      livenessProbe:
        initialDelaySeconds: 10
        periodSeconds: 10
        exec:
          command:
            - &quot;true&quot;
      readinessProbe:
        initialDelaySeconds: 5
        periodSeconds: 20
        httpGet:
          path: /healthcheck
          port: 9000
</code></pre>
<p>service.yml</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: testapp
spec:
  type: NodePort
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 9000
  selector:
    app: testapp
</code></pre>
<p>ingress.yml</p>
<pre><code>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: &quot;gce&quot;
spec:
  backend:
    serviceName: testapp
    servicePort: 80
</code></pre>
<p>managedcertificate.yml</p>
<pre><code>apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
  name: testcertificate
spec:
  domains:
    - arealdomain.com  // a real domain
</code></pre>
<p>After deployed these resources, access domain <code>arealdomain.com</code>, got 502 error:</p>
<pre><code>Error: Server Error
The server encountered a temporary error and could not complete your request.
Please try again in 30 seconds.
</code></pre>
<p>From GCP's <a href="https://console.cloud.google.com/net-services/loadbalancing/loadBalancers" rel="nofollow noreferrer">network loadbalancer</a>, got one service is unhealthy.</p>
<p><a href="https://i.stack.imgur.com/BlszA.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/BlszA.png" alt="enter image description here" /></a></p>
<p>Maybe firewall issue: <a href="https://cloud.google.com/load-balancing/docs/https/ext-http-lb-simple#firewall" rel="nofollow noreferrer">https://cloud.google.com/load-balancing/docs/https/ext-http-lb-simple#firewall</a></p>
<p>Check kubernetes's deployment pod, found this error:</p>
<pre><code>Readiness probe failed: HTTP probe failed with statuscode: 400
</code></pre>
<p>Since want to deploy this web app can be used by https, so deployed it with 8443 port only. Use site like: <a href="https://arealdomain.com" rel="nofollow noreferrer">https://arealdomain.com</a>
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?</p>
<hr />
<h1>Update</h1>
<p>When change to use <code>80</code> port in Ingress, also deployed application on 9000 port, the pod can start but <code>neg</code> check seems can't pass.</p>
<pre><code>  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-&lt;project_name&gt;-default-pool-asfjo2c5-afjl
  Normal  Pulling                            114s   kubelet, gke-&lt;project_name&gt;-default-pool-asfdl0-asl3  Pulling image &quot;gcr.io/&lt;project_name&gt;/testapp&quot;
  Normal  Pulled                             109s   kubelet, gke-&lt;project_name&gt;-default-pool-asfdl0-asl3  Successfully pulled image &quot;gcr.io/&lt;project_name&gt;/testapp&quot;
  Normal  Created                            109s   kubelet, gke-&lt;project_name&gt;-default-pool-asfdl0-asl3  Created container testapp
  Normal  Started                            109s   kubelet, gke-&lt;project_name&gt;-default-pool-asfdl0-asl3  Started container testapp
  Normal  LoadBalancerNegWithoutHealthCheck  94s    neg-readiness-reflector                               Pod is in NEG &quot;Key{\&quot;k8s1-173zho00-default-testapp-80-l4cadn29\&quot;, zone: \&quot;southamerica-east1-c\&quot;}&quot;. NEG is not attached to any BackendService with health checking. Marking condition &quot;cloud.google.com/load-balancer-neg-ready&quot; to True.
</code></pre>
<p>I found this <a href="https://cloud.google.com/kubernetes-engine/docs/concepts/container-native-load-balancing#pod_readiness" rel="nofollow noreferrer">article</a>, how to set <code>cloud.google.com/load-balancer-neg-ready</code> to <code>True</code>?</p>
<p>The GCP network's <code>Load balancer details</code> still showing unhealthy.</p>
<p><a href="https://i.stack.imgur.com/rwcD2.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/rwcD2.png" alt="enter image description here" /></a></p>
<p>From <code>Health Check</code> details, the path didn't been set to <code>/healthcheck</code> but <code>/</code>. Where is wrong?</p>
<p><a href="https://i.stack.imgur.com/1cDXl.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/1cDXl.png" alt="enter image description here" /></a></p>

<p>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</p>
<p>I created and deploy a sample application:</p>
<p>Code in main.go</p>
<pre><code>package main

import (
    &quot;log&quot;
    &quot;net/http&quot;
)

func main() {
    // change this handlers for echo handlers
    http.HandleFunc(&quot;/&quot;, http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
        rw.WriteHeader(http.StatusOK)
        rw.Write([]byte(&quot;Hello World...&quot;))
    }))
    http.HandleFunc(&quot;/health&quot;, http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
        rw.WriteHeader(http.StatusOK)
    }))
    log.Panic(http.ListenAndServe(&quot;:8080&quot;, nil))
}

</code></pre>
<p>Dockerfile</p>
<pre><code>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

</code></pre>
<p>k8s-artifacts.yaml</p>
<pre><code>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/&lt;ACCOUNT&gt;/test  
          ports:
            - containerPort: 8080
          livenessProbe:
            initialDelaySeconds: 10
            periodSeconds: 10
            exec:
              command:
                - &quot;true&quot;
          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: &quot;extensions/v1beta1&quot;
kind: &quot;Ingress&quot;
metadata:
  name: &quot;lb-2&quot;
  namespace: &quot;default&quot;
spec:
  backend:
    serviceName: &quot;testapp&quot;
    servicePort: 80
</code></pre>
<p>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</p>
<p><strong>Update</strong></p>
<p>After verifying that the lb is up and running
<a href="https://i.stack.imgur.com/a3pV2.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/a3pV2.png" alt="lb veryfication" /></a>
<a href="https://i.stack.imgur.com/ElUdh.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ElUdh.png" alt="access web site" /></a></p>
<p>To edit the load balancer go to the ingress details<a href="https://i.stack.imgur.com/SlNwk.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/SlNwk.png" alt="kubernetes engine services and ingress" /></a></p>
<p>At the bottom of the page there are links to the load balancers managed by GCE <a href="https://i.stack.imgur.com/tDLjh.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/tDLjh.png" alt="managed load balancers" /></a></p>
<p>Select the load balancer and edit it <a href="https://i.stack.imgur.com/NSLPv.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/NSLPv.png" alt="edit load balancer" /></a></p>
<p>Go to front end configuration and configure a new front end and port for https
<a href="https://i.stack.imgur.com/IR8hl.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/IR8hl.png" alt="enter image description here" /></a></p>
<p><strong>Update 2</strong></p>
<p>You can also create directly the new ingress with the managed cert. For example: First, create the managed cert</p>
<pre><code>apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
  name: test-cert
spec:
  domains:
    - test-domain.com
</code></pre>
<p>After that, just create a new ingress in the services and ingresses section of GKE
<a href="https://i.stack.imgur.com/BRYah.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/BRYah.png" alt="create ingress" /></a></p>
