Setting Up Nginx Ingress, Letsencrypt in Kubernetes without LoadBalancers
Deploying services using Docker containers are all in the rage nowadays and Kubernetes provides a good way to manage them. Also, majority of the cloud providers have kubernetes as a service. So there's that too.
Before we begin
I assume that you have setup Kubernetes and have Kubectl configured on your local machine.
If not, i suggest you yo go and set those up before starting.
Now lets get started :D
Installing Helm
What is helm and why do i need it?
- Helm is a package manager for kubernetes.
- Since we are going to install some services and their dependencies into the cluster, we need helm to make sure we can install them with simple set of commands.
- Alternatively, you can install these packages without helm. Just go their respective github repos and find the yaml files and install them using
kubectl apply
Spin up your terminal and fire up the following commands to install helm.
kubectl --namespace kube-system create sa tiller
# create a cluster role binding for tiller
kubectl create clusterrolebinding tiller \
--clusterrole cluster-admin \
--serviceaccount=kube-system:tiller
echo "initialize helm"
# initialized helm within the tiller service account
helm init --service-account tiller
# updates the repos for Helm repo integration
helm repo update
echo "verify helm"
# verify that helm is installed in the cluster
kubectl get deploy,svc tiller-deploy -n kube-system
Basically what the above commands does is as follows
- Creates a service account called
tiller
in the namespacekube-system
which is the system namespace that kubernetes creates after the cluster creation - Assigns the
cluster-admin
role to the namespace so that we can install other charts via helm without any problems - Install
helm
to the cluster.
Installing nginx ingress controller
Now that we've got helm setup and going, we need to install nginx ingress controller in the cluster using helm
To do this, we run
helm install stable/nginx-ingress \
--namespace=kube-system \
--name nginx-ingress \
--set controller.kind=DaemonSet \
--set controller.daemonset.useHostPort=true \
--set controller.service.enabled=false
Basically what we are doing here is installing nginx with some specific settings so that it doesn't spin up loadbalancers during the actual creation of ingress.
- You can read more about DaemonSets here
useHostPort
basically tells the controller to use host network of the cluster nodes and allows us to access 80 and 443 ports from outside the cluster.
Installing certmanager
We need a way to issue certificates to the cluster and this is done by using certmanager.
Install it using helm by
helm install --name cert-manager --version v0.5.2 \
--namespace kube-system stable/cert-manager
Now that we have installed certmanger, we need someone to issue the certificate for us, lets use LetsEncrypt for it.
Installing Letencrypt as certificate issuer
Open a text editor and enter the below
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: "<YOUR_EMAIL>"
privateKeySecretRef:
name: letsencrypt-staging
http01: {}
---
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: "<YOUR_EMAIL>"
privateKeySecretRef:
name: letsencrypt-prod
http01: {}
save the above file as lets_encrpyt.yml
and then run kubectl apply -f lets_encrypt.yml
Run an ingress
Now that we have setup letsencrypt as cluster issuer, we need to setup an ingress to handle the incoming connections.
Open another editor and enter the following
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/ssl-redirect: "true"
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
certmanager.k8s.io/acme-http01-edit-in-place: "true"
kubernetes.io/ingress.class: "nginx"
name: custom-ingress-nginx
spec:
rules:
- host: <YOUR-HOSTNAME>
http:
paths:
- path: /
backend:
serviceName: "<SERVICE-NAME>"
servicePort: <SERVICE-PORT>
tls:
- secretName: test-eng-secret
hosts:
- <YOUR-HOSTNAME>
- we specify the cluster issuer name in the annotation to issue us certificates. Use
letsencrypt-staging
to see if your setup is working and then use the production one. - And we specify the ingress class as
nginx
to use the nginx ingress controller. - the
<SERVICE-NAME>
and<SERVICE-PORT>
are the names and ports in theNodePort
services exposed above.
Thanks for reading and look forward to my future struggles.