Use Kubernetes Certificate Manager to automatically add SSL/TLS certificates to ingresses

Written by Pim on Tuesday October 16, 2018 - Comment - Permalink
Categories: devops, technology, howto - Tags: kubernetes, lets-encrypt, certificates, helm, tiller, kubernetes-ingress, SSL, TLS, security

Kubernetes Certificate Manager (cert-manager) is a native Kubernetes controller helping you to issue certificates from a variety of sources, such as Let's Encrypt, HashiCorp Valut, a signing keypair and self-signed. The Certificate Manager ensures certificates are valid and up-to-date, and attempt to renew certificates at a configured time before expiry.

The Kubernetes Certificate Manager is installed on the Kubernetes cluster using the Helm Chart. The Helm Chart is the recommended approach to install the Certificate Manager on Kubernetes.

Helm

"Helm is a tool for managing Kubernetes charts. Charts are packages of pre-configured Kubernetes resources." and "Helm is a tool that streamlines installing and managing Kubernetes applications. Think of it like apt/yum/homebrew for Kubernetes." - Source: https://github.com/helm/helm

Helm is the client-side component and is required to install Helm on a Kubernetes cluster. Tiller is the server-side component which is installed using Helm.

Install Helm

  1. Go to the Helm releases page and download the latest binary file: https://github.com/helm/helm/releases
    $ curl https://storage.googleapis.com/kubernetes-helm/helm-v2.11.0-linux-amd64.tar.gz -o ~/helm.tar.gz
  2. Extract the gzipped tar archive file to /usr/local/bin
    $ sudo tar -xzf ~/helm.tar.gz -C /usr/local/bin --strip-components=1

  3. Check if Helm is installed correctly by checking the version.

    $ helm version
    
    Client: &version.Version{SemVer:"v2.11.0", GitCommit:"2e55dbe1fdb5fdb96b75ff144a339489417b146b", GitTreeState:"clean"}
    Error: could not find tiller

    The error is there because we didn't install Tiller yet on our Kubernetes platform.

When you've installed the Helm client correctly, we need to install the server component on the Kubernetes platform. The server component is named "Tiller" and is controlled using the "Helm" client.

  1. Create a service account for the Tiller component that has cluster-admin privileges on the platform
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: tiller
      namespace: kube-system
    ---
    apiVersion: rbac.authorization.k8s.io/v1beta1
    kind: ClusterRoleBinding
    metadata:
      name: tiller
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster-admin
    subjects:
      - kind: ServiceAccount
        name: tiller
        namespace: kube-system
    EOF

  2. Install the server component "Tiller" on your Kubernetes platform
    $ helm init --service-account tiller
    
    # Or upgrade tiller
    $ helm init --upgrade --service-account tiller

  3. Check if Helm is installed correctly by checking the version
    $ helm version
    
    Client: &version.Version{SemVer:"v2.11.0", GitCommit:"2e55dbe1fdb5fdb96b75ff144a339489417b146b", GitTreeState:"clean"}
    Server: &version.Version{SemVer:"v2.11.0", GitCommit:"2e55dbe1fdb5fdb96b75ff144a339489417b146b", GitTreeState:"clean"}

Certificate Manager

  1. Install the Certificate Manager in the kube-system namespace using Helm

    $ helm install \
        --name cert-manager \
        --namespace kube-system \
        stable/cert-manager

  2. Create a (Cluster)Issues (more docs @ https://cert-manager.readthedocs.io/en/latest/tutorials/acme/http-validation.html)
    Staging environment

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

    Production environment

    apiVersion: certmanager.k8s.io/v1alpha1
    kind: ClusterIssuer
    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: support@hotflo.net
        # Name of a secret used to store the ACME account private key
        privateKeySecretRef:
          name: letsencrypt-prod
        # Enable the HTTP-01 challenge provider
        http01: {}

  3. Create a service in Kubernetes which needs a ingress

  4. Create an ingress for this service and add the certmanager.k8s.io/cluster-issuer annotation

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      annotations:
        # add an annotation indicating the issuer to use.
        certmanager.k8s.io/cluster-issuer: letsencrypt-prod
      name: myIngress
      namespace: myIngress
    spec:
      rules:
      - host: myingress.com
        http:
          paths:
          - backend:
              serviceName: myservice
              servicePort: 80
            path: /
      tls: # < placing a host in the TLS config will indicate a cert should be created
      - hosts:
        - myingress.com
        secretName: myingress-cert # < cert-manager will store the created certificate in this secret

  5. That's it ! Check if the certificate is requested using kubectl

    $ kubectl get certificate
    $ kubectl describe certificate $certificate-name

You are now capable to secure all ingress endpoints without any more hassle!