By Anish Nath.
Alibaba cloud's built-in Kubernetes engine does not offer an out-of-the-box HTTPS solution or TLS/SSL certificates for your website. For this, you can set up Let's Encrypt. Let's Encrypt is a handy, non-profit Certificate Authority that provides free TLS/SSL certificates that can be used to secure websites with HTTPS encryption. In tandem with Let's Encrypt, you will also need to set up cert-manager and nginx-ingress. cert-manager is a third-party Kubernetes controller that automates getting TLS/SSL certificates from Let's Encrypt and refreshing them. Next, nginx-ingress, which is an Ingress Controller, is a daemon, deployed as a Kubernetes Pod, which watches the apiserver's /ingresses endpoint for updates to the Ingress resource. Its job is to satisfy requests for Ingresses.
The following diagram shows how all of these can work together.
So in this tutorial, you will learn how you can set up Let's Encrypt along with cert-manager and nginx-ingress on Alibaba Cloud to achieve the above architecture and secure your Kubernetes application.
For this tutorial, you will need the following items. Note that, in the below steps, I will go over how you can set up your Kubernetes cluster.
zariga.com
, that is pointing to a Kubernetes Service Type loadbalancer.If you don't have a Kubernetes cluster and want to set up a Kubernetes cluster, you can follow these steps:
Initialize the master using the following command.
master# sudo kubeadm init --pod-network-cidr=192.168.0.0/16
Execute the following commands to configure kubectl (also returned by kubeadm init
).
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Install an etcd instance.
master# kubectl apply -f \
https://docs.projectcalico.org/v3.5/getting-started/kubernetes/installation/hosted/etcd.yaml
Install Calico.
master# kubectl apply -f \
https://docs.projectcalico.org/v3.5/getting-started/kubernetes/installation/hosted/calico.yaml
Confirm that all of the pods are running with the following command.
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system calico-etcd-x2482 1/1 Running 0 2m45s
kube-system calico-kube-controllers-6ff88bf6d4-tgtzb 1/1 Running 0 2m45s
kube-system calico-node-24h85 2/2 Running 0 2m43s
kube-system coredns-846jhw23g9-9af73 1/1 Running 0 4m5s
kube-system coredns-846jhw23g9-hmswk 1/1 Running 0 4m5s
kube-system etcd-jbaker-1 1/1 Running 0 6m22s
kube-system kube-apiserver-jbaker-1 1/1 Running 0 6m12s
kube-system kube-controller-manager-jbaker-1 1/1 Running 0 6m16s
kube-system kube-proxy-8fzp2 1/1 Running 0 5m16s
kube-system kube-scheduler-jbaker-1 1/1 Running 0 5m41s
On the minion node join the cluster (also returned by kubeadm init
).
minion# kubeadm join 172.20.240.112:6443 --token 2xg5nx.zv65d9mnz4g1802b --discovery-token-ca-cert-hash sha256:1cae1effbad759b7c70572dd509936340db5cc7d38ff1951422d45b91b3de03c
Now, let's set up and install Hel. To do this, follow these steps:
Download the helm binary from the official helm repo.
root@kube-master:~# wget https://storage.googleapis.com/kubernetes-helm/helm-v2.13.0-linux-amd64.tar.gz
Extract the helm tar file.
root@kube-master:~# tar -zxvf helm-v2.13.0-linux-amd64.tar.gz
linux-amd64/
linux-amd64/LICENSE
linux-amd64/README.md
linux-amd64/helm
linux-amd64/tiller
Move the helm to your $PATH
location.
root@kube-master:~# mv linux-amd64/helm /usr/local/bin/helm
Install the Helm server-side components (Tiller) on your Alibaba Cloud cluster.
kubectl create serviceaccount -n kube-system tiller
kubectl create clusterrolebinding tiller-binding \
--clusterrole=cluster-admin \
--serviceaccount kube-system:tiller
helm init --service-account tiller
Once tiller pod becomes ready, update chart repositories:
helm repo update
Now, it's time to set up cert-manager. To do so follow these steps:
Install cert-manager using the helm chart.
root@kube-master:~# helm install --name cert-manager --version v0.5.2 --namespace kube-system stable/cert-manager
The output is as follows:
NAME: cert-manager
LAST DEPLOYED: Tue Mar 12 15:29:21 2019
NAMESPACE: kube-system
STATUS: DEPLOYED
RESOURCES:
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
cert-manager-6464494858-4lhjg 0/1 ContainerCreating 0 1s
==> v1/ServiceAccount
NAME SECRETS AGE
cert-manager 1 1s
==> v1beta1/ClusterRole
NAME AGE
cert-manager 1s
==> v1beta1/ClusterRoleBinding
NAME AGE
cert-manager 1s
==> v1beta1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
cert-manager 0/1 1 0 1s
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://cert-manager.readthedocs.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://cert-manager.readthedocs.io/en/latest/reference/ingress-shim.html
And, now, let's configure the Let's Encrypt Cluster Issuer for the staging and production environment. To start, adjust the email according to your specific needs.
root@kube-master:~# cat letsencrypt-issuer.yaml
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: 'zarigatongy@gmail.com'
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: 'zarigatongy@gmail.com'
privateKeySecretRef:
name: letsencrypt-prod
http01: {}
Apply the cluster Issuer in your Kubernetes cluster.
root@kube-master:~# kubectl apply -f letsencrypt-issuer.yaml
clusterissuer.certmanager.k8s.io/letsencrypt-staging created
clusterissuer.certmanager.k8s.io/letsencrypt-prod created
To deploy a web app on a doemain name, for testing purposes, create a NGINX deployment and exposing over clusterIP.
kubectl create deployment --image nginx my-nginx
kubectl expose deployment my-nginx --port=80 --type=ClusterIP
root@kube-master:~# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 28h
my-nginx ClusterIP 10.101.150.247 <none> 80/TCP 25h
Now, let's move on to installing the NGINX ingress control. To do this, first use helm chart stable/nginx-ingress
for the installation.
helm install stable/nginx-ingress --namespace kube-system
On successful install, the helm chart will show that nginx-ingress
is deployed.
root@kube-master:~# helm ls
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
cert-manager 1 Tue Mar 12 19:44:24 2019 DEPLOYED cert-manager-v0.5.2 v0.5.2 kube-system
nginx-ingress 1 Tue Mar 12 19:38:19 2019 DEPLOYED nginx-ingress-1.3.1 0.22.0 kube-system
Last, confirm that your LoadBalancer
IP for nginx-ingress-controller is no longer pending by using the following command.
root@kube-master:~# kubectl get svc -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
calico-etcd ClusterIP 10.96.232.136 <none> 6666/TCP 28h
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP 28h
nginx-ingress-controller LoadBalancer 10.105.8.20 172.20.240.112 80:31151/TCP,443:32087/TCP 23h
nginx-ingress-controller-stats ClusterIP 10.96.180.163 <none> 18080/TCP 23h
nginx-ingress-default-backend ClusterIP 10.99.138.158 <none> 80/TCP 23h
tiller-deploy ClusterIP 10.104.47.231 <none> 44134/TCP 27h
At this stage, you have already forwarded your domain name to the IP address where your Kubernetes cluster is running. Now, you can test your domain in your preferred browser. Note that the NGINX ingress controller has issued a fake certificate. This confirms that nginx ingress is up and running and ready to use to configure let's Encrypt issuers.
Now, let's get a staging Let's Encrypt certificate for your domain name. For this, first create the Ingress resource with the annotations and the required service.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-ingress-staging
annotations:
kubernetes.io/ingress.class: nginx
certmanager.k8s.io/cluster-issuer: letsencrypt-staging
kubernetes.io/tls-acme: 'true'
labels:
app: 'my-nginx'
spec:
rules:
- host: zariga.com
http:
paths:
- path: /
backend:
serviceName: my-nginx
servicePort: 80
tls:
- secretName: tls-staging-cert
hosts:
- zariga.com
Next, create the ingress in the Kubernetes cluster.
root@kube-master:~# kubectl create -f nginx-ingress-staging.yaml
ingress.extensions/nginx-ingress-staging created
root@kube-master:~# vim nginx-ingress-staging.yaml
You can view the Certificate
resource which was create automatically.
root@kube-master:~# kubectl get certificate
NAME AGE
tls-staging-cert 1m
After somewhere between two and ten minutes, kubectl describe certificate
should show that the Certificate has been issued successfully.
root@kube-master:~# kubectl describe certificate
Name: tls-staging-cert
Namespace: default
Labels: <none>
Annotations: <none>
API Version: certmanager.k8s.io/v1alpha1
Kind: Certificate
Metadata:
Creation Timestamp: 2019-03-12T10:17:13Z
Generation: 4
Owner References:
API Version: extensions/v1beta1
Block Owner Deletion: true
Controller: true
Kind: Ingress
Name: nginx-ingress-staging
UID: fe528f28-44af-11e9-b431-00163e005d19
Resource Version: 16843
Self Link: /apis/certmanager.k8s.io/v1alpha1/namespaces/default/certificates/tls-staging-cert
UID: 014f9299-44b0-11e9-b431-00163e005d19
Spec:
Acme:
Config:
Domains:
zariga.com
Http 01:
Ingress:
Ingress Class: nginx
Dns Names:
zariga.com
Issuer Ref:
Kind: ClusterIssuer
Name: letsencrypt-staging
Secret Name: tls-staging-cert
Status:
Acme:
Order:
URL: https://acme-staging-v02.api.letsencrypt.org/acme/order/8535504/26384081
Conditions:
Last Transition Time: 2019-03-12T10:17:51Z
Message: Certificate issued successfully
Reason: CertIssued
Status: True
Type: Ready
Last Transition Time: <nil>
Message: Order validated
Reason: OrderValidated
Status: False
Type: ValidateFailed
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal CreateOrder 103s cert-manager Created new ACME order, attempting validation...
Normal DomainVerified 69s cert-manager Domain "zariga.com" verified with "http-01" validation
Normal IssueCert 69s cert-manager Issuing certificate...
Normal CertObtained 68s cert-manager Obtained certificate from ACME server
Normal CertIssued 68s cert-manager Certificate issued successfully
The important things to note here are:
spec.secretName
: The secret in which the certificate will be stored. Usually, this will be prefixed with -tls
so it doesn't get mixed up with other secrets.spec.issuerRef.name
: The named we defined earlier for our ClusterIssuer.spec.issuerRef.kind
: This specifies that the issuer is a ClusterIssuer.spec.acme.config.http01.ingress
: The name of the ingress deployed with NGINX.Now visit the domain name again, you should notice now that a stage certificate is being issued and configured to your domain name.
Next, let's get a production Let's Encrypt certificate for your domain name. To do this, first define ingress with required annotations and service to lookup.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-ingress-prod
annotations:
kubernetes.io/ingress.class: nginx
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
kubernetes.io/tls-acme: 'true'
labels:
app: 'my-nginx'
spec:
rules:
- host: zariga.com
http:
paths:
- path: /
backend:
serviceName: my-nginx
servicePort: 80
tls:
- secretName: tls-prod-cert
hosts:
- zariga.com
Next, apply the ingress in the kubernetes cluster.
kubectl apply -f letsencrypt-nginx-prod.yaml
View the ingress.
root@kube-master:~# kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
nginx-ingress-prod zariga.com 80, 443 23h
Get the certificate.
root@kube-master:~# kubectl get certificate
NAME AGE
tls-prod-cert 23h
After somewhere between two and ten minutes, kubectl describe certificate
should show Certificate issued successfully.
root@kube-master:~# kubectl describe certs
Name: tls-prod-cert
Namespace: default
Labels: <none>
Annotations: <none>
API Version: certmanager.k8s.io/v1alpha1
Kind: Certificate
Metadata:
Creation Timestamp: 2019-03-12T10:26:58Z
Generation: 2
Owner References:
API Version: extensions/v1beta1
Block Owner Deletion: true
Controller: true
Kind: Ingress
Name: nginx-ingress-prod
UID: 5ab11929-44b1-11e9-b431-00163e005d19
Resource Version: 17687
Self Link: /apis/certmanager.k8s.io/v1alpha1/namespaces/default/certificates/tls-prod-cert
UID: 5dad4740-44b1-11e9-b431-00163e005d19
Spec:
Acme:
Config:
Domains:
zariga.com
Http 01:
Ingress:
Ingress Class: nginx
Dns Names:
zariga.com
Issuer Ref:
Kind: ClusterIssuer
Name: letsencrypt-prod
Secret Name: tls-prod-cert
Status:
Acme:
Order:
URL: https://acme-v02.api.letsencrypt.org/acme/order/53135536/352104603
Conditions:
Last Transition Time: 2019-03-12T10:27:00Z
Message: Order validated
Reason: OrderValidated
Status: False
Type: ValidateFailed
Last Transition Time: <nil>
Message: Certificate issued successfully
Reason: CertIssued
Status: True
Type: Ready
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal CreateOrder 27s cert-manager Created new ACME order, attempting validation...
Normal IssueCert 27s cert-manager Issuing certificate...
Normal CertObtained 25s cert-manager Obtained certificate from ACME server
Normal CertIssued 25s cert-manager Certificate issued successfully
Visit the URL the domain name is issued with production certificate.
Finally, let's do some cleanup. First, delete the Ingress, Service and Deployment:
kubectl delete ingress,deployment my-nginx
kubectl delete service my-nginx
Use this command to uninstall cert-manager deployment:
helm del --purge cert-manager
Use this command to uninstall Helm:
helm reset
Use this command to delete the TLS certificates:
kubectl delete secret <NAME>
The views expressed herein are for reference only and don't necessarily represent the official views of Alibaba Cloud.
2,599 posts | 764 followers
FollowAlibaba Clouder - December 6, 2017
Hironobu Ohara - June 26, 2023
Alibaba Clouder - July 31, 2018
Alibaba Clouder - August 9, 2018
Alibaba Clouder - January 25, 2018
Alibaba Cloud Vietnam - June 13, 2023
2,599 posts | 764 followers
FollowAlibaba Cloud Container Service for Kubernetes is a fully managed cloud container management service that supports native Kubernetes and integrates with other Alibaba Cloud products.
Learn MoreA secure image hosting platform providing containerized image lifecycle management
Learn MoreElastic and secure virtual cloud servers to cater all your cloud hosting needs.
Learn MoreMore Posts by Alibaba Clouder
RICKY11 September 26, 2020 at 5:45 pm
that is a lot of work to simply get ssl certificates isnt it?Also to maintain the instance may cost you more then purchasing a ssl certificate from alibaba ssl itself vs lets encrpt?