Kubernetes on Google Cloud Platform: Nginx-Ingress and TLS from letsencrypt with cert-manager (using helm)


NOTE: 1 year after i wrote this, I found it in my “drafts”. I don’t recall why i haven’t published it. Since 1 year has passed, I decided to publish AS-IS.

There are only guides but it took forever (aka more than 1 day) to set everything up and working. Here a list of the things I did to make everything working.

The result is that:

  • Nginx is used as ingress, (nginx-ingress) and an ingress resource is used to route to your service
  • TLS for the connection, issued by letsencrypt
  • static IP and DNS set up to your domain

Let’s go step by step.

0. Assumptions:

It’s assumed that you have a Kubernetes cluster with services running, Helm installed and working.

Setup a static IP and DNS

From the Google console create a static IP (give a name you like), not it down somewhere.
Create a DNS record that points to that IP, in my case it’s api.k8s.chino.io

Helm Templates

The tricky part is to have a correct helm configuration (then generate Kubernetes instructions correctly). In the templates folder, I’ve this ingress.yaml file


{{- if .Values.ingress.enabled -}}
{{- $serviceName := include "fullname" . -}}
{{- $servicePort := .Values.service.targetPort -}}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{ template "fullname" . }}
labels:
app: {{ template "fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
annotations:
{{- range $key, $value := .Values.ingress.annotations }}
{{ $key }}: {{ $value }}
{{- end }}
spec:
rules:
– host: "{{ .Values.ingress.dnsNames }}"
http:
paths:
– path: /
backend:
serviceName: {{ $serviceName }}
servicePort: {{ $servicePort }}
{{- if .Values.ingress.tls }}
tls:
{{ toYaml .Values.ingress.tls | indent 4 }}
{{- end -}}
{{- end -}}

view raw

ingress.yaml

hosted with ❤ by GitHub

(note that your deployment must use ClusterIP and the port is the targetPort, in my case is 8000 and not 80)

then I created a certificate.yaml


apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
name: {{.Values.certificate.secretName}}
spec:
secretName: {{.Values.certificate.secretName}}
issuerRef:
name: {{.Values.certificate.certIssuer}}
dnsNames:
– {{.Values.certificate.dnsNames}}
acme:
config:
– http01:
ingressClass: {{.Values.certificate.ingressClass}}
domains:
{{- range .Values.certificate.domains }}
– {{ . }}
{{- end }}

and this in values.yaml


certificate:
secretName: chino-io-tls-prod
certIssuer: letsencrypt-prod
dnsNames: api.k8s.chino.io
ingressClass: nginx
domains:
– api.k8s.chino.io
ingress:
dnsNames: api.k8s.chino.io
enabled: true
annotations:
kubernetes.io/ingress.class: nginx
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
tls:
– secretName: chino-io-tls-prod
hosts:
– api.k8s.chino.io

view raw

values.yaml

hosted with ❤ by GitHub

Briefly, this will create an ingress for the service that resolves the url set in the values. Plus creates a certificate, using the letsencrypt prod system (you can use staging for test environment, we go on this later on).

Install nginx-ingress

First of all install nginx-ingress using helm, set it to use your static ip.

helm install --name nginx-ingress --set controller.service.loadBalancerIP=YOURSTATICIP stable/nginx-ingress

Install cert-manager

First, create the issuer by using this yaml file


apiVersion: certmanager.k8s.io/v1alpha1
kind: Issuer
metadata:
name: letsencrypt-prod
namespace: default
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: email@example.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-prod
# Enable the HTTP-01 challenge provider
http01: {}

(the value letsencrypt-prod is used in the values.yaml and links to this one)

Then launch the cert manager with helm

helm install --name cert-manager stable/cert-manager

this will take care of generating the certificate.

Launch your helm

launch the helm that you updated at the beginning. everything should be working and having the TLS enabled.