DEV Community

Dak Washbrook
Dak Washbrook

Posted on • Updated on • Originally published at asilearn.org

Install NGINX Ingress Controller on Kubernetes + Let's Encrypt Cert Issuer

This article is a perspective rewrite of the given sources that allowed me to get from point A to point B from my perspective.

Alt Text

Requirements:

I recommend DigitalOcean for a very affordable Kubernetes Cluster.

Click here to sign-up for Digital Ocean: https://m.do.co/c/79bf9fee3de8.

Amazon has its own Managed k8s service as well: https://aws.amazon.com/eks/.

Google (the creators of Kubernetes) has its own, very convenient and highly managed, k8s service. https://cloud.google.com/kubernetes-engine/.


Apply the latest version of the NGINX Ingress Controller

Check https://github.com/kubernetes/ingress-nginx/releases for the newest version number.

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.24.1/deploy/mandatory.yaml
Enter fullscreen mode Exit fullscreen mode

Output:

namespace/ingress-nginx created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
deployment.extensions/nginx-ingress-controller created
Enter fullscreen mode Exit fullscreen mode

Install the Cloud Generic Load Balancer for the Ingress

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.24.1/deploy/provider/cloud-generic.yaml -n ingress-nginx
Enter fullscreen mode Exit fullscreen mode

Output:

service/ingress-nginx created
// If you want all nodes to pass the health check:
$ kubectl patch svc ingress-nginx -n ingress-nginx -p '{"spec":{"externalTrafficPolicy":"Cluster"}}'
Enter fullscreen mode Exit fullscreen mode

You can check on the service with:

$ kubectl get svc --namespace=ingress-nginx
Enter fullscreen mode Exit fullscreen mode

Installing cert-manager + lets-encrypt

Apply the CRDs (Custom Resource Definitions)

$ kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.8/deploy/manifests/00-crds.yaml
Enter fullscreen mode Exit fullscreen mode

Output:

customresourcedefinition.apiextensions.k8s.io/certificates.certmanager.k8s.io created
customresourcedefinition.apiextensions.k8s.io/challenges.certmanager.k8s.io created
customresourcedefinition.apiextensions.k8s.io/clusterissuers.certmanager.k8s.io created
customresourcedefinition.apiextensions.k8s.io/issuers.certmanager.k8s.io created
customresourcedefinition.apiextensions.k8s.io/orders.certmanager.k8s.io created
Enter fullscreen mode Exit fullscreen mode

Set a label on kube-system namespace to enable advanced resource validation with a webhook.

$ kubectl label namespace kube-system certmanager.k8s.io/disable-validation="true"
Enter fullscreen mode Exit fullscreen mode

Output:

namespace/kube-system labeled
Enter fullscreen mode Exit fullscreen mode

If you do not have Helm installed on your client and k8s cluster. Before the next step, I had to install the Helm client (https://helm.sh/docs/using_helm/) and run the following command:

$ helm init
Enter fullscreen mode Exit fullscreen mode

Output:

$HELM_HOME has been configured at /Users/<User>/.helm.
Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.
Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
To prevent this, run `helm init` with the --tiller-tls-verify flag.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
Enter fullscreen mode Exit fullscreen mode

Then I had to give tiller a ServiceAccount and link everything up via roles.

$ kubectl create serviceaccount --namespace kube-system tiller
Enter fullscreen mode Exit fullscreen mode

Output:

serviceaccount/tiller created
$ kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
Enter fullscreen mode Exit fullscreen mode

Output:

clusterrolebinding.rbac.authorization.k8s.io/tiller-cluster-rule created
$ kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
Enter fullscreen mode Exit fullscreen mode

Output:

deployment.extensions/tiller-deploy patched
Enter fullscreen mode Exit fullscreen mode

Add jetstack to your Helm repositories.

$ helm repo add jetstack https://charts.jetstack.io
Enter fullscreen mode Exit fullscreen mode

Output:

"jetstack" has been added to your repositories
Enter fullscreen mode Exit fullscreen mode

Install the cert-manager helm chart.

$ helm install --name cert-manager --namespace kube-system jetstack/cert-manager --version v0.8.0
Enter fullscreen mode Exit fullscreen mode

Output:

NAME:   cert-manager
LAST DEPLOYED: Tue Jun 25 08:39:05 2019
NAMESPACE: kube-system
STATUS: DEPLOYED
RESOURCES:
==> v1/ClusterRole
NAME                                    AGE
cert-manager-edit                       3s
cert-manager-view                       3s
cert-manager-webhook:webhook-requester  3s
==> v1/Pod(related)
NAME                                     READY  STATUS             RESTARTS  AGE
cert-manager-5d669ffbd8-glqgv            0/1    ContainerCreating  0         3s
cert-manager-cainjector-79b7fc64f-bwn7t  0/1    ContainerCreating  0         3s
cert-manager-webhook-6484955794-p2jgn    0/1    ContainerCreating  0         3s
==> v1/Service
NAME                  TYPE       CLUSTER-IP      EXTERNAL-IP  PORT(S)  AGE
cert-manager-webhook  ClusterIP  ${CLUSTER_IP}  <none>       443/TCP  3s
==> v1/ServiceAccount
NAME                     SECRETS  AGE
cert-manager             1        3s
cert-manager-cainjector  1        3s
cert-manager-webhook     1        3s
==> v1alpha1/Certificate
NAME                              AGE
cert-manager-webhook-ca           3s
cert-manager-webhook-webhook-tls  2s
==> v1alpha1/Issuer
NAME                           AGE
cert-manager-webhook-ca        2s
cert-manager-webhook-selfsign  2s
==> v1beta1/APIService
NAME                                  AGE
v1beta1.admission.certmanager.k8s.io  3s
==> v1beta1/ClusterRole
NAME                     AGE
cert-manager             3s
cert-manager-cainjector  3s
==> v1beta1/ClusterRoleBinding
NAME                                 AGE
cert-manager                         3s
cert-manager-cainjector              3s
cert-manager-webhook:auth-delegator  3s
==> v1beta1/Deployment
NAME                     READY  UP-TO-DATE  AVAILABLE  AGE
cert-manager             0/1    1           0          3s
cert-manager-cainjector  0/1    1           0          3s
cert-manager-webhook     0/1    1           0          3s
==> v1beta1/RoleBinding
NAME                                                AGE
cert-manager-webhook:webhook-authentication-reader  3s
==> v1beta1/ValidatingWebhookConfiguration
NAME                  AGE
cert-manager-webhook  2s
NOTES:
cert-manager has been deployed successfully!
In order to begin issuing certificates, you will need to set up a ClusterIssuer
or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer).
More information on the different types of issuers and how to configure them
can be found in our documentation:
https://docs.cert-manager.io/en/latest/reference/issuers.html
For information on how to configure cert-manager to automatically provision
Certificates for Ingress resources, take a look at the `ingress-shim`
documentation:
https://docs.cert-manager.io/en/latest/reference/ingress-shim.html
Enter fullscreen mode Exit fullscreen mode

Create a file called issuer.yaml:

apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
  name: letsencrypt
spec:
  acme:
    # The ACME server URL
    server: https://acme-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: ${YOUR_EMAIL_ADDRESS}
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt
    # Enable the HTTP-01 challenge provider
    http01: {}
Enter fullscreen mode Exit fullscreen mode

Replace ${YOUR_EMAIL_ADDRESS} with your e-mail address.

Create the issuer with the following command:

$ kubectl create -f issuer.yaml
Enter fullscreen mode Exit fullscreen mode

Output:

clusterissuer.certmanager.k8s.io/letsencrypt created
Enter fullscreen mode Exit fullscreen mode

See this example Ingress resource using the issuer:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: echo-ingress
  annotations:  
    kubernetes.io/ingress.class: nginx
    certmanager.k8s.io/cluster-issuer: letsencrypt
spec:
  tls:
  - hosts:
    - echo1.example.com
    - echo2.example.com
    secretName: letsencrypt
  rules:
  - host: echo1.example.com
    http:
      paths:
      - backend:
          serviceName: echo1
          servicePort: 80
  - host: echo2.example.com
    http:
      paths:
      - backend:
          serviceName: echo2
          servicePort: 80
Enter fullscreen mode Exit fullscreen mode

Create as many Ingress resources as you would like. The best practice, in my opinion, is having 1 per domain, just for organizational reasons.

If you have any questions or comments please feel free to comment below!

Thanks!

Sources:

Top comments (0)