Blog was originally published on medium (https://medium.com/goglides/ssl-certificates-using-google-managed-certificate-on-gke-c4bc43f5cbf2)

Note: Managed certificates require clusters with masters running Kubernetes 1.12.6-gke.7 or higher.

In goglides.com we started allowing users to map custom domain names to Tenants URL also. One of the challenges we were facing initially when we started implementing solutions is how to issue an SSL certificate for the custom domain name automatically so that we can establish a secure connection for Tenants.

Issuing and managing a certificate is not a trivial task, especially if you are trying to build the solutions from scratch. Luckily, Goglides is running on Kubernetes so it became trivial to implement a solution.

There are so many ways we can issue certificates, in this blog we are focusing on K8S cluster running on Google (GKE) using a custom resource called ManagedCertificate and ingress rules.

Clarifying Terms

Before we jump into solutions, let’s start with explaining some of the technology we are using here,

Ingress

As per the official definition,

Ingress is an, API object that manages external access to the services in a cluster, typically HTTP. Ingress can provide load balancing, SSL termination, and name-based virtual hosting.

One of the main use cases of ingress is, it allows users to access Kubernetes services from outside the Kubernetes cluster.

Ingress has 2 parts, ingress controller (there are many controllers) and ingress rules. We create ingress rules and we need a controller that satisfies and process those rules. Only applying ingress rules does not affect the cluster.

Google-managed SSL certificate

Managed Certificate is a Custom Resource object created by google. This CRD allows users to automatically acquire an SSL certificate from a Certificate Authority, configure certificate on the load balancer and auto-renew it on time when it’s expired.

The process is super simple and users only need to provide a domain for which they want to obtain a certificate.

Prerequisites

  • You must own the domain name and name must be no longer than 63 characters. In this example, we are going to use a subdomain (gke.goglides.com)
  • Create a reserved (static) external IP address using the following command, or use google console. Here I am using gke-goglides-static-ip as IP address identifier which we are going to use later. It can be anything.
gcloud compute addresses create gke-goglides-static-ip --global
gcloud compute addresses \
  describe gke-goglides-static-ip --global \
  --format='value(address)'

Add DNS A-record with static IP address

Create DNS record ahead so that google certificate authority can validate ownership of the domain, issue certificates and attached it to load balancer using managed certificate features.

Setting up the managed certificate in GKE

Now, let’s start with creating Kubernetes resources.

  • Create Managed Certificate
cat <<EOF | kubectl apply -f - 
---
apiVersion: networking.gke.io/v1beta1
kind: ManagedCertificate
metadata:
  name: gke-goglides-certificate
spec:
  domains:
    - gke.goglides.com 
EOF

You can check the status of a certificate using the following command

kubectl describe managedcertificate gke-goglides-certificate

  • Create Deployment
cat <<EOF | kubectl apply -f -
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: gke-goglides
  name: hello-world
spec:
  selector:
    matchLabels:
      run: gke-goglides
  replicas: 1
  template:
    metadata:
      labels:
        run: gke-goglides
    spec:
      containers:
      - name: hello-world
        image: nginx:1.15.8
        ports:
        - containerPort: 80
          protocol: TCP
EOF

Create a Service Object

cat<<EOF | kubectl apply -f -
---
apiVersion: v1
kind: Service
metadata:
  labels:
    run: gke-goglides
  name: hello-world-service
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: gke-goglides
  type: NodePort
EOF

Create Ingress

cat <<EOF | kubectl apply -f -
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: gke-goglides-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: gke-goglides-static-ip
    networking.gke.io/managed-certificates: gke-goglides-certificate
spec:
  backend:
    serviceName: hello-world-service
    servicePort: 80
EOF

This took ~10–20min to become active. Verify that SSL is working by visiting your domain using the https:// prefix.

curl https://gke.goglides.com

You should see the following outputs.

</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>