This post is a guide to setup ingress with cert-manager on kubernetes cluster (VMs based) so that the application deploy on the cluster can apply for https certificate automatically.
When we use kubernetes cluster using cloud providers, they already provide ingress mechanism based on their load balancer technology. If we want this capability on VMs or bare metal based cluster, we need to set it up ourselves.
It is part of series "Setup your own kubernetes cluster on VMs".
Prerequisite:
- A running kubernetes cluster
- A domain name with you have administration access
Note:
For those who follow along, you need to run everything on master node
Install helm
First of all, we need helm, a cluster package manager, that will help us install ingress and cert-manager.
1. Create service account and its permission
Run command.
echo 'apiVersion: v1
kind: ServiceAccount
metadata:
name: tiller
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: tiller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system' | kubectl apply -f -
2. Install helm
Run below command to install helm from official bash script.
Note: You will need to enter root password.
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get | bash
3. Initialize helm
We need to initialize helm to install server application on the cluster.
helm init --service-account tiller
4. Check installation
Run helm version
.
If things are ok, you should see.
Install Ingress
We will install nginx ingress using host network on all worker nodes (DaemonSet).
See this document to understand more about nginx ingress Bare-metal considerations
1. Install Ingress pod
Install using helm command below.
helm install --name nginx-ingress --namespace nginx-ingress stable/nginx-ingress --set controller.hostNetwork=true --set controller.kind=DaemonSet
Open one of your worker node IP address in the browser. If ingress installation successful, you will see.
2. Configure domain name
Configure your dns to point your test domain name to one of your worker node.
In my example, I point my route53 test dns record to my public IP.
I also need to configure my router to forword port 80 and 443 to one of my worker node. Let's say 192.168.1.110.
3. Deploy test application
Run this command to deploy hello world application to the cluster.
kubectl run hello-world --image=gcr.io/google-samples/node-hello:1.0 --port=8080
kubectl expose deployment hello-world --type=NodePort --name=example-service
Try access this application using node port http://<master or worker ip>:<node port>
. You should see.
4. Deploy test ingress
Run command below to install ingress for test application.
Note:
Please replace "testingress.yourdomain.com" with your real domain.
echo 'apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
kubernetes.io/tls-acme: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
tls:
- hosts:
- testingress.yourdomain.com
secretName: testingress-tls
rules:
- host: testingress.yourdomain.com
http:
paths:
- path: /
backend:
# The name of your service
serviceName: example-service
servicePort: 8080' | kubectl apply -f -
If everything is ok, open url http://testingress.yourdomain.com
and you should see.
Install cert-manager
We will install cert-manager to the cluster then create cluster issuer for letsencrypt. The cluster issuer will automatically detect our ingress with tls configure then try to acquire certificate and store keys in secret name "testingress-tls".
1. Install cert-manager
Run this command using helm.
helm install --name cert-manager --namespace kube-system stable/cert-manager
2. Create cluster issuer (use http01 protocol)
Run this command to create cluster issuer.
Note:
Please replace "yourreal@email.com" to your real email
echo 'apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
namespace: default
spec:
acme:
email: yourreal@email.com
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-prod
http01: {}' | kubectl apply -f -
Run below to update cert-manager to use cluster issuer created above.
helm upgrade cert-manager stable/cert-manager --namespace kube-system --set ingressShim.defaultIssuerName=letsencrypt-prod --set ingressShim.defaultIssuerKind=ClusterIssuer
Wait for sometimes maybe an hour. Then run kubectl get secret
. If you see secret name "testingress-tls", this mean it works. You should be able to access https://testingress.yourdomain.com
successfully.
3. Create cluster issuer (use dns01 protocol)
In case that step 2 with http02 protocol does not work, we will need a more advance protocol "dns01".
"dns01" protocol support many cloud providers, this example will be for route53.
3.1 Import IAM policy
Import this to your IAM user that you have access key.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "route53:GetChange",
"Resource": "arn:aws:route53:::change/*"
},
{
"Effect": "Allow",
"Action": "route53:ChangeResourceRecordSets",
"Resource": "arn:aws:route53:::hostedzone/*"
},
{
"Effect": "Allow",
"Action": "route53:ListHostedZonesByName",
"Resource": "*"
}
]
}
3.2 Create AWS secret
Create kubernetes secret using below.
Note:
Replace with your real secret key
kubectl create secret -n kube-system generic aws-secret --from-literal=secret-key=<IAM User Secret Key>
3.3 Create Cluster Issuer (DNS01)
Note:
Replace yourreal@email.com with your real email
Replace and and with your real data
echo 'apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
namespace: default
spec:
acme:
email: yourreal@email.com
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-prod
dns01:
providers:
- name: aws-route53
route53:
hostedZoneID: <Route53 hosted zone ID>
region: <Route53 region>
accessKeyID: <IAM User Access key>
secretAccessKeySecretRef:
name: aws-secret
key: secret-key' | kubectl apply -f -
3.4 Update test ingress to use DNS01
Note:
Replace yourdomain.com to your real domain
echo 'apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
certmanager.k8s.io/acme-challenge-type: "dns01"
certmanager.k8s.io/acme-dns01-provider: "aws-route53"
spec:
tls:
- hosts:
- testingress.yourdomain.com
secretName: testingress-tls
rules:
- host: testingress.yourdomain.com
http:
paths:
- path: /
backend:
# The name of your service
serviceName: example-service
servicePort: 8080' | kubectl apply -f -
Wait until kubectl get secret
return secret name "testingress-tls", this mean it works. You should be able to access https://testingress.yourdomain.com
successfully.
Summary
At this point, we have a kubernete cluster that we can deploy application that support https. Next, we will set up a static front-end application in the kubernetes cluster.
Top comments (1)
thanks for writing this post! this is help me a lot for almost 3 days in every night!