A few months ago, I described how to deploy Ghost on Google Cloud's Kubernetes Engine (GKE), using GCP's managed SSL offering. But that setup had some limitations, both with the managed SSL certificates as well as GCP's default ingress (which is an L7 solution).
At the time, I had assumed that managing SSL certificates any other way on Kubernetes would be too complicated. Turns out, it's actually pretty straight-forward to do this without relying on a managed offering. Besides, it's cheaper and provides more features (e.g. automatic HTTP to HTTPS redirects, HSTS support and more). Read on to find out how.
First, create your cluster. I wanted to get Kubernetes 1.6+ so I went with the
rapid release channel, but that's obviously not recommended for production workloads. I also enabled automatic upgrades and configured the default node pool with E2 instances. Finally, I also enabled auto-scaling.
Next, install helm. Part of the reason I started with a new cluster with the latest k8s was that I wanted to test drive the new helm 3 – among other things, they completely got rid of tiller, making the installation and deployment significantly simpler! For Mac, a simple
brew install helm should do the trick, otherwise check the installation guide.
For certificate management, we'll use the excellent cert-manager. Installation should be as simple as:
Finally, setup both staging and production issuers (I opted for the simpler
ClusterIssuer configuration) as described here. Basically, your issuer file should look something like this:
apiVersion: cert-manager.io/v1alpha2 kind: ClusterIssuer metadata: name: letsencrypt-staging spec: acme: # You must replace this email address with your own. # Let's Encrypt will use this to contact you about expiring # certificates, and issues related to your account. email: email@example.com server: https://acme-staging-v02.api.letsencrypt.org/directory privateKeySecretRef: # Secret resource used to store the account's private key. name: letsencrypt-staging # Add a single challenge solver, HTTP01 using nginx solvers: - http01: ingress: class: nginx
For ingress, I went with ingress-nginx. With Helm, installation was trivial:
Note that unlike the GCE Ingress (which is L7), this is an L4 Ingress. And therefore, you will need to allocate a regional static IP address (as opposed to a global reservation for L7).
Now go ahead and deploy your sites. Your ingress configuration should look something like this:
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: nginx-ingress annotations: cert-manager.io/cluster-issuer: letsencrypt-prod kubernetes.io/ingress.class: "nginx" spec: rules: - host: floatingsun.net http: paths: - backend: serviceName: floatingsun-net servicePort: 80 tls: - hosts: - floatingsun.net secretName: floatingsun-net
Each new entry in the TLS section will trigger cert-manager to issue a certificate, and store the secret in the
secretName key. Cert-Manager will take care of renewing the certificates etc. For each new domain you want a certificate for, just add the corresponding entries under the rules and tls sections.
And that's it! If you found the post useful, please like / share.