Skip to content

Gardener certification manager

The cert-manager controller is usually used to manage TLS certificates in Kubernetes clusters.

In a multi-cluster environment like Gardener, it becomes cumbersome to use existing open source projects, such as cert-manager, for managing the certificates. Therefore OSC provides an extension for the Shoots, which allows the usage of cert-manager's CRDs without the need to install and configure cert-manager itself.

Architecture overview of extension
Architecture overview of extension

Note

The cert-manager provided by OSC project uses a different approach compared to the Gardener project' cert-manager. The OSC implementation uses the standard cert-manager implementation deployed as a Gardener Extension.

Deploying the extension

Warning

It is not supported to deploy the upstream cert-manager to a Shoot cluster where the extension is enabled.

Such setup won't function correctly, and the issues will remain even after removing one of the cert-managers. Please either enable the extension or deploy your own cert-manager, never both.

The extension is activated for a Shoot by defining it in its manifest in the extensions section. This can be done either at the Shoot's creation, or later, by editing and re-applying an existing Shoot's manifest. The extension is deployed when the Shoot is reconciled.

apiVersion: core.gardener.cloud/v1beta1
kind: Shoot
metadata:
  name: <name of the shoot>
  namespace: garden-<name of the project where shoot needs to be located>
spec:
  extensions:
    # enable the cert-manager extension
    - type: osc-cert-manager-service

To change it through the Gardener dashboard, click on the YAML section on the Shoot's status page, and edit the manifest:

Editing Shoot manifest using the Dashboard
Editing Shoot manifest using the Dashboard

The Shoot will be reconciled after pressing the SAVE button on the bottom of page.

Disabling the extension

The extension can be explicitly disabled, which may be needed in case the cert-manager extension is globally enabled.

kind: Shoot
spec:
  extensions:
  - type: osc-cert-manager-service
    disabled: true

Usage

The cert-manager Custom Resource Definitions (CRDs) are available on the Shoot clusters. The CRDs have the same definition as those of the upstream cert-manager's.

Users can use the extension with their own Certification Authority (CA) certificate. This has to be uploaded to the Shoot as a Secret, and referenced in the Issuer object.

Each Gardener stack has a self-signed CA certificate, available to all Shoots of the stack. To create certificates issued by the predefined extension-provided ClusterIssuer, define the issuerRef in the following way:

 issuerRef:
    group: cert-manager.osc.extensions.gardener.cloud
    kind: ClusterIssuer
    name: Gardener
  secretName: ca-cert-inbuild

If needed, users can create an Issuer which will generate certificates issued by Let's Encrypt using ACME.

Example: Generating Ingress certificate by annotation

This example shows how to deploy a cert-manager Issuer and use it to issue an Ingress certificate by annotating the Ingress. The predefined stack CA certificate will be used as the issuing certificate. All actions are performed directly on Shoot cluster.

  • Option 1: obtain a certificate secret using the OSC provided ClusterIssuer
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: ca-cert
      namespace: kube-system
    spec:
      isCA: true
      dnsNames:
        - somedomain.live
      issuerRef:
        group: cert-manager.osc.extensions.gardener.cloud
        kind: ClusterIssuer
        name: Gardener
      secretName: ca-cert
    
  • Option 2: deploy a Secret with a custom certificate/private key pair
    apiVersion: v1
    kind: Secret
    metadata:
      name: ca-cert
      namespace: kube-system
    type: kubernetes.io/tls
    data:
      tls.crt: <Base-64 encoded PEM of the certificate>
      tls.key: <Base-64 encoded PEM of the private key>
    

    In both cases a Secret named ca-cert will be present, containing the certificate/key pair.

  • The next step is to create an Issuer in the same Namespace, referencing the Secret.
    apiVersion: cert-manager.io/v1
    kind: Issuer
    metadata:
      name: gardener-issuer
      namespace: kube-system
    spec:
      ca:
        secretName: ca-cert
    
  • When an Ingress is created with the correct annotation and TLS section,

    the cert-manager extension will create a new certificate/key pair for the Ingress, based on the Issuer and the ca-cert from the previous step.

    Let's consider that we already have:

    - a service `my-service` in the kube-system namespace
    - a deployed nginx-ingress-controller
    - a DNS record  `*.somedomain.live` in the
      [DNS provider extension][dnsext]
      connected to the ingress controller's public IP.
    
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: application-ingress
      namespace: kube-system
      annotations:
        cert-manager.io/issuer: gardener-issuer
    spec:
      ingressClassName: nginx
      rules:
      - host: ingresstest.somedomain.live
        http:
          paths:
          - pathType: Prefix
            path: "/"
            backend:
              service:
                name: my-service
                port:
                  number: 8080
        # placing a host in the TLS config will determine what ends up
        # in the cert's subjectAltNames
        tls:
          - hosts:
            - ingresstest.somedomain.live
            secretName: application-ingress-cert
    

    The following objects are created on the cluster:

    kubectl get ingress -n kube-system
    NAME                  CLASS   HOSTS                         ADDRESS        PORTS     AGE
    application-ingress   nginx   ingresstest.somedomain.live   80.158.33.50   80, 443   47s
    
    kubectl get certificate -n kube-system
    NAME                       READY   SECRET                     AGE
    application-ingress-cert   True    application-ingress-cert   55s
    
     kubectl get secret/application-ingress-cert -n kube-system
    NAME                       TYPE                DATA   AGE
    application-ingress-cert   kubernetes.io/tls   3      87s
    

Example: Using Let's Encrypt with ACME

This example shows how to use cert-manager with ACME to obtain certificates from Let's Encrypt. The ACME plugin is included in the cert-manager extension.

  • Create a new Issuer based on Let's Encrypt:
    apiVersion: cert-manager.io/v1
    kind: Issuer
    metadata:
      name: letsencrypt-staging
      namespace: kube-system
    spec:
      acme:
        server: https://acme-staging-v02.api.letsencrypt.org/directory
        email: some.mail@mailprovider.com
        privateKeySecretRef:
          name: letsencrypt-staging
        solvers:
          - http01:
              ingress:
                class: nginx
    

    The ACME plugin can contain more solvers (methods to confirm the owner of the domain). For demonstration purposes the http solver is used.

    !!! tip Learn more about the supported solvers.

  • Create the Ingress with new Issuer:
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: application-ingress
      namespace: kube-system
      annotations:
        cert-manager.io/issuer: letsencrypt-staging
        acme.cert-manager.io/http01-edit-in-place: "true"
    spec:
      ingressClassName: nginx
      rules:
      - host: ingresstest.somedomain.live
        http:
          paths:
          - pathType: Prefix
            path: "/"
            backend:
              service:
                name: my-service
                port:
                  number: 8080
      # placing a host in the TLS config will determine what ends up
      # in the cert's subjectAltNames
      tls:
      - hosts:
        - ingresstest.somedomain.live
        secretName: application-ingress-cert
    
  • In addition to the Ingress, a Certificate and 2 Secrets are created (one containing the private key for certificate and one with the TLS certificate):
    kubectl get ingress -n kube-system
    NAME                  CLASS   HOSTS                         ADDRESS       PORTS     AGE
    application-ingress   nginx   ingresstest.somedomain.live   80.158.33.50  80, 443   47s
    
    kubectl get secret application-ingress-cert -n kube-system
    NAME                       TYPE                DATA   AGE
    application-ingress-cert   kubernetes.io/tls   2      7m32s
    

Warning

The kube-system namespace is used in both examples. It is strongly discouraged to use it to deploy application load, as it is primarily designed for system components of the cluster.

Warning

In the cert-manager extension is not possible to use an user-defined ClusterIssuer due to the s because of system how extension is deployed through the seed cluster. Therefore cluster issuer will fail that he is not able to find certificate which is a base of cluster issuer (he is looking for it in seed cluster).