Manage Certificates With Cert Manager
This tutorial will detail how to manage secrets of ApisixTls using cert-manager.
#
Prerequisites- Prepare an available Kubernetes cluster in your workstation, we recommend you to use KIND to create a local Kubernetes cluster.
- Install Apache APISIX in Kubernetes by Helm Chart.
- Install apisix-ingress-controller.
- Install cert-manager.
In this guide, we assume that your APISIX is installed with ssl
enabled, which is not enabled by default in the Helm Chart. To enable it, you need to set gateway.tls.enabled=true
during installation.
For example, you could install APISIX and APISIX ingress controller by running:
helm install apisix apisix/apisix --set gateway.type=NodePort --set ingress-controller.enabled=true --set gateway.tls.enabled=true --set ingress-controller.config.apisix.serviceNamespace=default
Assume that the SSL port is 9443
.
#
Create IssuerFor testing purposes, we will use a simple CA issuer. All required files can be found here.
To create a CA issuer, use the following commands:
kubectl apply -f ./cert-manager/ca.yamlkubectl apply -f ./cert-manager/issuer.yaml
If the cert-manager is working correctly, we should be able to see the Ready status by running:
kubectl get issuer
It should output:
NAME READY AGEca-issuer True 50s
#
Create CertificateBefore creating ApisixTls, we should create a Certificate
resource.
apiVersion: cert-manager.io/v1kind: Certificatemetadata: name: demo-certspec: dnsNames: - local.httpbin.org issuerRef: kind: Issuer name: ca-issuer secretName: example-cert usages: - digital signature - key encipherment renewBefore: 0h55m0s duration: 1h0m0s
Note that we set the parameters duration
and renewBefore
. We want to test if the certificate rotation functionality is working well, so a shorter renewal time will help.
Like Issuer
, we could see its readiness status by running:
kubectl get certificate
It should output:
NAME READY SECRET AGEdemo-cert True example-cert 50s
Check the secrets by running:
kubectl get secret
It should output:
NAME TYPE DATA AGEexample-cert kubernetes.io/tls 3 2m20s
This means that our cert-manager is working properly.
#
Create Test ServiceWe use kennethreitz/httpbin as the service image.
Deploy it by running:
kubectl run httpbin --image kennethreitz/httpbin --expose --port 80
#
Route the ServiceCreate an ApisixRoute to route the service:
apiVersion: apisix.apache.org/v2beta3kind: ApisixRoutemetadata: name: httpserver-routespec: http: - name: httpbin match: hosts: - local.httpbin.org paths: - "/*" backends: - serviceName: httpbin servicePort: 80
Run curl command in a APISIX pod to see if the routing configuration works.
kubectl -n <APISIX_NAMESPACE> exec -it <APISIX_POD_NAME> -- curl http://127.0.0.1:9080/ip -H 'Host: local.httpbin.org'
It should output:
{ "origin": "127.0.0.1"}
#
Secure the RouteCreate an ApisixTls to secure the route, referring to the secret created by cert-manager:
apiVersion: apisix.apache.org/v2beta3kind: ApisixTlsmetadata: name: example-tlsspec: hosts: - local.httpbin.org secret: name: example-cert # the secret created by cert-manager namespace: default # secret namespace
Run curl command in a APISIX pod to see if the Ingress and TLS configuration are working.
kubectl -n <APISIX_NAMESPACE> exec -it <APISIX_POD_NAME> -- curl --resolve 'local.httpbin.org:9443:127.0.0.1' "https://local.httpbin.org:9443/ip" -k
It should output:
{ "origin": "127.0.0.1"}
#
Test Certificate RotationTo verify certificate rotation, we can add a verbose parameter -v
to curl command:
kubectl -n <APISIX_NAMESPACE> exec -it <APISIX_POD_NAME> -- curl --resolve 'local.httpbin.org:9443:127.0.0.1' "https://local.httpbin.org:9443/ip" -k -v
The verbose option will show us the handshake log, which also contains the certificate information.
Example output:
* Added local.httpbin.org:9443:127.0.0.1 to DNS cache* Hostname local.httpbin.org was found in DNS cache* Trying 127.0.0.1:9443...* Connected to local.httpbin.org (127.0.0.1) port 9443 (#0)......* Server certificate:* subject: [NONE]* start date: Sep 16 00:14:55 2021 GMT* expire date: Sep 16 01:14:55 2021 GMT* issuer: C=CN; ST=Zhejiang; L=Hangzhou; O=APISIX-Test-CA_; OU=APISIX_CA_ROOT_; CN=APISIX.ROOT_; emailAddress=test@test.com
We could see the start date and expiration date of the server certificate.
Since the Certificate
we defined requires the cert-manager to renew the cert every 5 minutes, we should be able to see the changes to the server certificate after 5 minutes.
* Added local.httpbin.org:9443:127.0.0.1 to DNS cache* Hostname local.httpbin.org was found in DNS cache* Trying 127.0.0.1:9443...* Connected to local.httpbin.org (127.0.0.1) port 9443 (#0)......* Server certificate:* subject: [NONE]* start date: Sep 16 00:19:55 2021 GMT* expire date: Sep 16 01:19:55 2021 GMT* issuer: C=CN; ST=Zhejiang; L=Hangzhou; O=APISIX-Test-CA_; OU=APISIX_CA_ROOT_; CN=APISIX.ROOT_; emailAddress=test@test.com
The certificate was rotated as expected.