TechAnek

Introduction

Securing Kubernetes workloads with TLS certificates is crucial for protecting data and ensuring trust. Cert-Manager automates certificate management, and when combined with NGINX Ingress Controller, it enables easy HTTPS setup using the HTTP-01 challenge. In this blog, we’ll go through the steps to set up Cert-Manager with NGINX Ingress using the HTTP-01 challenge to obtain and manage SSL certificates from Let’s Encrypt.
Prerequisites
  • A Kubernetes cluster (e.g., Minikube, AWS EKS, GKE, AKS, etc.)
  • kubectl configured to interact with your cluster
  • Helm installed for deploying Cert-Manager
  • NGINX Ingress Controller deployed in the cluster
  • A domain name pointing to the cluster’s ingress controller (via an external Load Balancer or NodePort)
1. Install NGINX Ingress
				
					helm repo add nginx https://helm.nginx.com/stable
helm update
helm install nginx -ningress nginx/nginx-ingress -f helm-values/nginx-values.yaml --create-namespace=true
				
			
2. Install Cert-Manager
Cert-Manager can be installed using Helm. First, add the Jetstack Helm repository and then, install Cert-Manager with the required Custom Resource Definitions (CRDs):
				
					helm repo add jetstack https://charts.jetstack.io  
helm repo update
helm install cert-manager jetstack/cert-manager \  
	--namespace cert-manager --create-namespace \
	--version v1.9.1  --set installCRDs=true
				
			
Verify that Cert-Manager pods are running:
				
					kubectl get pods -n cert-manager
				
			

3. Create an Issuer or ClusterIssuer

Cert-Manager requires an Issuer or ClusterIssuer to manage certificates. We’ll create a ClusterIssuer using Let’s Encrypt.

How ClusterIssuer Works

A ClusterIssuer is a cluster-wide resource that provides certificates to multiple namespaces. It allows Cert-Manager to request and manage TLS certificates centrally, rather than requiring separate issuers in each namespace. The ClusterIssuer works by handling ACME (Automated Certificate Management Environment) challenges using HTTP-01 or DNS-01 solvers to verify domain ownership.In contrast, an Issuer is a namespace-scoped resource, meaning it can only issue certificates for workloads within its own namespace. If you need certificates across multiple namespaces, you would need to create an Issuer in each one, which can be cumbersome.
Why Use ClusterIssuer Instead of Issuer?
  • Centralized Management: With a ClusterIssuer, you only need one configuration for the entire cluster instead of defining an Issuer in each namespace.
  • Ease of Maintenance: A single ClusterIssuer simplifies administration, as all certificates use the same CA without duplicating configuration across namespaces.
  • Scalability: When deploying multiple applications that need TLS, using a ClusterIssuer avoids redundant issuers and ensures all workloads share a single certificate authority.
				
					apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: cert-issuer
spec:
  acme:
    # The ACME production api URL
    server: https://acme-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: your@email.com
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: cert-issuer-secret
    solvers:
    # An empty 'selector' means that this solver matches all domains
    - selector: {}
      http01:
        ingress:
          class: nginx

				
			
Apply the ClusterIssuer:
				
					kubectl apply -f cluster-issuer.yaml
				
			

Verify the issuer status:

				
					kubectl describe clusterissuer cert-issuer
				
			

4. Deploy a Sample Application with TLS

The sample application consists of an NGINX deployment that serves static content, exposed via a Kubernetes Service. The Ingress resource routes external traffic to the application and triggers Cert-Manager to request an SSL certificate from Let’s Encrypt. Once issued, the certificate is stored in a Kubernetes secret and automatically used by the Ingress controller to enable HTTPS.

4.1 Deploy an Application
Create a file nginx-deployment.yaml:
				
					apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
				
			
Apply the deployment:
				
					kubectl apply -f nginx-deployment.yaml
				
			
4.2 Create a Service
Create a file nginx-service.yaml:
				
					apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP
				
			

Apply the service:

				
					kubectl apply -f nginx-service.yaml
				
			
4.3 Create an Ingress Resource​

Create a file nginx-ingress.yaml

				
					apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    acme.cert-manager.io/http01-edit-in-place: "true"
    cert-manager.io/cluster-issuer: cert-issuer
  name: nginx-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: your.domain.com
    http:
      paths:
      - backend:
          service:
            name: <SERVICE-NAME>
            port:
              number: <PORT>
        path: /
        pathType: ImplementationSpecific
  tls:
  - hosts:
    - your.domain.com
    secretName: cert-issuer-secret
				
			
Apply the ingress:
				
					kubectl apply -f nginx-ingress.yaml
				
			

4.4 Verify Certificate Issuance

Check the status of the certificate:

				
					kubectl get certificate
				
			
You should see something like:
				
					NAMESPACE   NAME                 READY   SECRET               AGE
test        cert-issuer-secret   True    cert-issuer-secret   73m
				
			
To confirm the certificate details:
				
					kubectl describe certificate cert-issuer-secret
				
			

5. Test HTTPS Access

Once the certificate is issued, test HTTPS access using a browser or curl

				
					curl -v https://your.domain.com
				
			

If everything is set up correctly, your application will be served over HTTPS with a valid Let’s Encrypt certificate.

Conclusion

In this blog, we walked through setting up Cert-Manager with NGINX Ingress using the HTTP-01 challenge to obtain TLS certificates from Let’s Encrypt. This setup automates certificate issuance and renewal, ensuring secure communication for your Kubernetes applications.

Leave a Reply

Your email address will not be published. Required fields are marked *

Add Your Heading Text Here