Use HTTPS for Kubernetes nginx-ingress

9/11/2019

I want to use HTTPS for my Kubernetes on Azure (AKS). For that I use nginx-ingress (https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md#azure). All of the ressources, which I created by this tutorial, are using the namespace ingress-nginx. That's why I continue using this namespace instead of default. My Ingress is working like expected. Now I want to use HTTPS instead of HTTP.

For that I created an CSR:

openssl req -new -newkey rsa:2048 -nodes -keyout private.key -out example.csr -subj "/CN=domain.com"

I send the CSR to a signing provider (QuoVadis) who send me the following files back:

  • domain_com(chain).crt
  • domain_com.crt
  • QuoVadis_Global_SSL_ICA_G2.crt
  • QuoVadis_Root_CA_2.crt

I'm a little bit confused because in all tutorials I found only one crt is mentioned. The chain looks like an combination of all other three files. That's why I continued with the chain:

sudo kubectl create secret tls ssl-secret-test --cert domain_com(chain).crt --key private.key -n ingress-nginx

I added the secret to my ingress:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-ingress
  namespace: ingress-nginx
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  tls:
  - hosts:
    - domain.com
    secretName: ssl-secret-test
  rules:
  - host: domain.com
  - http:
      paths:
      - path: /app1(/|$)(.*)
        backend:
          serviceName: app1-service
          servicePort: 80
      - path: /app2(/|$)(.*)
        backend:
          serviceName: app2-service
          servicePort: 80

My deployments app1 & app2 are not available by the domain anymore. If I use the IP it is still working:

domain.com/app1:

404 Not Found - openresty/1.15.8.1

52.xxx.xxx.xx/app1:

Hello World

In both cases, I still get the warning of an unsecured connection. Here an overview of my services:

$ sudo kubectl get svc --all-namespaces
NAMESPACE       NAME                             TYPE           CLUSTER-IP     EXTERNAL-IP                                  PORT(S)                      AGE
default         kubernetes                       ClusterIP      10.0.0.1       <none>                                       443/TCP                      57d
ingress-nginx   app1-service                     NodePort       10.0.229.109   <none>                                       80:31343/TCP                 22h
ingress-nginx   app2-service                     NodePort       10.0.175.201   <none>                                       80:31166/TCP                 22h
ingress-nginx   ingress-nginx                    LoadBalancer   10.0.40.172    52.xxx.xxx.xx                                80:32564/TCP,443:32124/TCP   22h
kube-system     healthmodel-replicaset-service   ClusterIP      10.0.233.181   <none>                                       25227/TCP                    5d10h
kube-system     heapster                         ClusterIP      10.0.214.146   <none>                                       80/TCP                       57d
kube-system     kube-dns                         ClusterIP      10.0.0.10      <none>                                       53/UDP,53/TCP                57d
kube-system     kubernetes-dashboard             ClusterIP      10.0.160.230   <none>                                       80/TCP                       57d
kube-system     metrics-server                   ClusterIP      10.0.170.103   <none>                                       443/TCP                      57d

$ sudo kubectl get ingress --all-namespaces
NAMESPACE       NAME            HOSTS              ADDRESS         PORTS     AGE
ingress-nginx   nginx-ingress   domain.com         52.xxx.xxx.xx   80, 443   37m

$ sudo kubectl get deployments --all-namespaces
NAMESPACE       NAME                       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
ingress-nginx   app1                       2         2         2            2           22h
ingress-nginx   app2                       2         2         2            2           22h
ingress-nginx   nginx-ingress-controller   1         1         1            1           57d
kube-system     coredns                    2         2         2            2           58d
kube-system     coredns-autoscaler         1         1         1            1           58d
kube-system     heapster                   1         1         1            1           5d10h
kube-system     kubernetes-dashboard       1         1         1            1           58d
kube-system     metrics-server             1         1         1            1           58d
kube-system     omsagent-rs                1         1         1            1           58d
kube-system     tunnelfront                1         1         1            1           58d

What I'm doing wrong?

Update with cert-manager

I followed the following tutorial:

https://docs.cert-manager.io/en/latest/getting-started/install/kubernetes.html

and confirmed everything by the example test-resources.yaml.

Now I followed the steps for setting up a CA ISSUER.

apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
  name: domain-com
  namespace: default
spec:
  secretName: domain-com-tls
  issuerRef:
    name: ca-issuer
    kind: ClusterIssuer
  commonName: domain.com
  organization:
  - QuoVadis
  dnsNames:
  - domain.com
  - www.domain.com
-----
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
  name: ca-issuer
  namespace: default
spec:
  ca:
    secretName: ssl-secret-test

But it seems that it is not working:

$ kubectl describe certificate domain-com
...
Status:
  Conditions:
    Last Transition Time:  2019-09-12T07:48:19Z
    Message:               Certificate does not exist
    Reason:                NotFound
    Status:                False
    Type:                  Ready
  Not After:               2021-09-11T07:46:00Z
Events:
  Type     Reason          Age                 From          Message
  ----     ------          ----                ----          -------
  Warning  IssuerNotReady  8s (x9 over 4h51m)  cert-manager  Issuer ca-issuer not ready

And on the troubleshooting page, I found an additional uncertainty:

$ kubectl --namespace cert-manager get secret cert-manager-webhook-webhook-tls
Error from server (NotFound): secrets "cert-manager-webhook-webhook-tls" not found
-- Nico Schuck
https
kubernetes
nginx
nginx-ingress
ssl-certificate

1 Answer

9/12/2019

I answered in the comments but will just add the Answer here:

Cert Manager is the easiest way to handle TLS with nginx ingress, after setting it up here https://docs.cert-manager.io/en/latest/getting-started/install/kubernetes.html when you define your ingress it would look similar to:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-ingress
  namespace: ingress-nginx
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    kubernetes.io/ingress.class: "nginx" <-- This is very important to define which ingress controller to use
    certmanager.k8s.io/cluster-issuer: letsencrypt-staging <-- defines the cert manager issuer
spec:
  tls:
  - hosts:
    - domain.com
    secretName: ssl-secret-test
  rules:
  - host: domain.com
  - http:
      paths:
      - path: /app1(/|$)(.*)
        backend:
          serviceName: app1-service
          servicePort: 80
      - path: /app2(/|$)(.*)
        backend:
          serviceName: app2-service
          servicePort: 80

Cert manager will then setup the TLS for your service

-- Spazzy757
Source: StackOverflow