Kubernetes : Cluster init with nginx-ingress + cert-manager

Publication date 4/4/2020

A Quick K8S snippet tutorial to install nginx-ingress controller and cert-manager on a new cluster.

WARNING : This installation method will create a Loadbancer, dont forget to delete it on cloud dashboard if necessaray for a complete cleanup.

For baremetal install nginx-ingress can be configured as DaemonSet on ports 80 and 443. This avoids LoadBalancer Service fees but boring to manage (require manual DNS config updat to point to nodes public IPs)

Requirements

  • Fresh kubernetes cluste v1.6+ on a cloud provider
  • The kubectl tool installed an configured (admin)
  • Helm v3 installed on local computer

Install nginx-ingress + cert-manager

  • https://cert-manager.io/docs/installation/kubernetes
  • https://kubernetes.github.io/ingress-nginx/deploy/#using-helm

CERT_MANGER_VERSION=v0.14.3

helm repo add stable https://kubernetes-charts.storage.googleapis.com
helm repo add jetstack https://charts.jetstack.io   

helm repo update

kubectl create namespace nginx-ingress
helm install nginx-ingress stable/nginx-ingress --namespace nginx-ingress --set rbac.create=true

kubectl create namespace cert-manager
kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/$CERT_MANGER_VERSION/cert-manager.crds.yaml

helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --version $CERT_MANGER_VERSION

Configure your DNS

  1. Wait Ingress controller service creation to complete
  2. Get the ingres controller service public IP (LoadBalancer IP : kubectl get svc -n nginx-ingress)
  3. Go to your DNS provider dashboard and add A record pointing to LoadBalancer IP

Test installation

Create an expose a sample app

kubectl create namespace demo-tls
kubectl create deployment demo-tls-app --image nginx:alpine -n demo-tls
kubectl expose deployment demo-tls-app --type ClusterIP --port 80 -n demo-tls

Add certificate issuers

cat <<EOF | kubectl apply -n demo-tls -f -
apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    # The ACME server URL
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: admin@yourdomain.co
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-staging
    # Enable the HTTP-01 challenge provider
    solvers:
    - http01:
        ingress:
          class: nginx  
EOF

cat <<EOF | kubectl apply -n demo-tls -f -
apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    # The ACME server URL
    server: https://acme-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: admin@yourdomain.co
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-prod
    # Enable the HTTP-01 challenge provider
    solvers:
    - http01:
        ingress:
          class: nginx  
EOF

Create TLS Ingress to acces our application

# staging ingress
cat <<EOF | kubectl apply -n demo-tls -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: demo-tls-app
  annotations:
    kubernetes.io/ingress.class: "nginx"    
    cert-manager.io/issuer: "letsencrypt-staging"
spec:
  tls:
  - hosts:
    - demo-tls-app.do.yourdomain.co
    secretName: demo-tls-app
  rules:
  - host: demo-tls-app.do.africa-up.io
    http:
      paths:
      - path: /
        backend:
          serviceName: demo-tls-app
          servicePort: 80
EOF

# production ingress
cat <<EOF | kubectl apply -n demo-tls -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: demo-tls-app-prod
  annotations:
    kubernetes.io/ingress.class: "nginx"    
    cert-manager.io/issuer: "letsencrypt-prod"
spec:
  tls:
  - hosts:
    - demo-tls-app-prod.yourdomain.co
    secretName: demo-tls-app-prod
  rules:
  - host: demo-tls-app-prod.yourdomain.co
    http:
      paths:
      - path: /
        backend:
          serviceName: demo-tls-app
          servicePort: 80
EOF

Delete demo namespace

kubectl delete namespace demo-tls