cert-manager is a certificate lifecycle management system that can be used to issue
and deploy certificates. You can use cert-manager to issue certificates for Alibaba
Cloud Service Mesh (ASM) gateways. This way, you can use the ASM gateways to access
services over HTTPS. This ensures data transmission security. This topic describes
how to use cert-manager to manage certificates for ASM gateways.
Background information
cert-manager allows you to issue self-signed certificates and DNS certificates. You
can load the certificates on ASM gateways and use the ASM gateways to access services
over HTTPS. The two types of certificates have the following differences:
- Self-signed certificate: Self-signed certificates can be used only for encryption.
They cannot be used for authentication. You can use an ASM gateway on which a self-signed
certificate is loaded to access services over HTTPS in command-line tools. However,
a self-signed certificate is not trusted by web browsers. A web browser marks HTTPS
connections that use a self-signed certificate and displays an error message indicating
that the connections have potential risks. Therefore, you cannot use an ASM gateway
on which a self-signed certificate is loaded to access services over HTTPS in web
browsers.
- DNS certificate: DNS certificates are issued by Certificate Authorities (CAs) and
can be used for both encryption and authentication. Compared with self-signed certificates,
DNS certificates provide higher security and are trusted by web browsers. You can
use an ASM gateway on which a DNS certificate is loaded to access services over HTTPS
in both command-line tools and web browsers.
Install cert-manager in your cluster
- Install Helm on your computer. For more information, see Helm.
- Use kubectl to connect to your cluster. For more information, see Connect to ACK clusters by using kubectl.
- Run the following command to create the cert-manager namespace:
kubectl create namespace cert-manager
- Run the following command to add the cert-manager chart:
helm repo add jetstack https://charts.jetstack.io
- Run the following command to obtain the latest information about the cert-manager
chart:
- Run the following command to install cert-manager:
Notice The version of cert-manager must be compatible with the Kubernetes version. For more
information about the mapping between cert-manager versions and Kubernetes versions,
see
Supported Releases.
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--version v1.1.0 \
--set installCRDs=true
Scenario 1: Use cert-manager to issue a self-signed certificate
Step 1: Create a self-signed certificate in your cluster
- Create the issuer.yaml file and add the following content to the file:
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: selfsigned
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: istio-ingressgateway-certs
spec:
isCA: true
duration: 2160h # 90d
secretName: istio-ingressgateway-certs
commonName: istio-ingressgateway-certs
subject:
organizations:
- cluster.local
- cert-manager
issuerRef:
name: selfsigned
kind: Issuer
group: cert-manager.io
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: istio-ingressgateway-certs
spec:
ca:
secretName: istio-ingressgateway-certs
- Run the following command to create a self-signed CA and issue a certificate for workloads:
kubectl apply -f issuer.yaml -n istio-system
- Run the following command to view the certificate:
kubectl get secret -n istio-system
Expected output:
NAME TYPE DATA AGE
istio-ingressgateway-certs kubernetes.io/tls 3 68m
Step 2: Create a volume that is mounted with the certificate and private key on an
ingress gateway
- Log on to the ASM console.
- In the left-side navigation pane, choose .
- On the Mesh Management page, find the ASM instance that you want to configure. Click the name of the ASM
instance or click Manage in the Actions column.
- On the details page of the ASM instance, click ASM Gateways in the left-side navigation pane.
- On the ASM Gateways page, click YAML in the Actions column of the ingress gateway that you want to manage.
- Edit the YAML file of the ingress gateway by adding the following content to the
spec
field: secretVolumes:
- mountPath: /etc/istio/ingressgateway-certs
name: ingressgateway-certs
secretName: istio-ingressgateway-certs
The following sample code provides an example of the edited YAML file:
apiVersion: istio.alibabacloud.com/v1beta1
kind: IstioGateway
metadata:
name: ingressgateway
namespace: istio-system
spec:
clusterIds:
- c58638b491a5248669b59609e0a17****
cpu: {}
externalTrafficPolicy: Local
maxReplicas: 1
minReplicas: 1
ports:
- name: status-port
port: 15020
targetPort: 15020
- name: http2
nodePort: 31380
port: 80
targetPort: 80
- name: https
nodePort: 31390
port: 443
targetPort: 443
- name: tls
port: 15443
targetPort: 15443
replicaCount: 1
secretVolumes:
- mountPath: /etc/istio/ingressgateway-certs
name: ingressgateway-certs
secretName: istio-ingressgateway-certs
serviceAnnotations:
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-spec: slb.s1.small
serviceType: LoadBalancer
Step 3: Check the configurations of the ingress gateway in the cluster
After you create a volume that is mounted with the certificate and private key on
an ingress gateway, the ingress gateway loads the certificate and private key.
- Run the following command to check whether the tls.crt and tls.key files are loaded
in the pod of the ingress gateway:
kubectl exec -it -n istio-system $(kubectl -n istio-system get pods -l istio=ingressgateway -o jsonpath='{.items[0].metadata.name}') -- ls -al /etc/istio/ingressgateway-certs
Expected output:
lrwxrwxrwx 1 root root 14 May 9 01:14 tls.crt -> ..data/tls.crt
lrwxrwxrwx 1 root root 14 May 9 01:14 tls.key -> ..data/tls.key
- Run the following command to check whether the value of the
Subject
field is correct in the certificate loaded on the ingress gateway: kubectl exec -it -n istio-system $(kubectl -n istio-system get pods -l istio=ingressgateway -o jsonpath='{.items[0].metadata.name}') -- cat /etc/istio/ingressgateway-certs/tls.crt | openssl x509 -text -noout | grep 'Subject:'
Expected output:
Subject: O = cert-manager + O = cluster.local, CN = istio-ingressgateway-certs
- Run the following command to check whether the proxy of the ingress gateway can access
the certificate:
kubectl exec -it -n istio-system $(kubectl -n istio-system get pods -l istio=ingressgateway -o jsonpath='{.items[0].metadata.name}') -- curl 127.0.0.1:15000/certs
Expected output:
{
"certificates": [
{
"ca_cert": [
{
"path": "\u003cinline\u003e",
"serial_number": "4edcf3",
"subject_alt_names": [],
"days_until_expiration": "7251",
"valid_from": "2022-01-06T06:17:00Z",
"expiration_time": "2042-01-01T06:22:03Z"
}
],
...........
Step 4: Verify that you can access a service over HTTPS
- Create a service in the cluster.
- Create the myexample-nginx.conf file and add the following content to the file.
In this example, a service whose domain name is aliyun.com is implemented based on
NGINX. You need to create a configuration file for the NGINX server. The following
content specifies that the message
Welcome to aliyun.com!
and the status code
200
are returned for requests to the root path of the service.
events {
}
http {
log_format main '$remote_addr - $remote_user [$time_local] $status '
'"$request" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log;
server {
listen 80;
location / {
return 200 'Welcome to aliyun.com!';
add_header Content-Type text/plain;
}
}
}
- Run the following command to create a ConfigMap for the NGINX server:
kubectl create configmap myexample-nginx-configmap --from-file=nginx.conf=./myexample-nginx.conf
- Run the following command to enable automatic sidecar injection for the default namespace:
kubectl label namespace default istio-injection=enabled
- Create the myexampleapp.yaml file and add the following content to the file:
apiVersion: v1
kind: Service
metadata:
name: myexampleapp
labels:
app: myexampleapp
spec:
ports:
- port: 80
protocol: TCP
selector:
app: myexampleapp
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myexampleapp
spec:
selector:
matchLabels:
app: myexampleapp
replicas: 1
template:
metadata:
labels:
app: myexampleapp
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx
readOnly: true
volumes:
- name: nginx-config
configMap:
name: myexample-nginx-configmap
- Run the following command to create an internal service whose domain name is aliyun.com:
kubectl apply -f myexampleapp.yaml
- Use kubectl to connect to your ASM instance. For more information, see Use kubectl to connect to an ASM instance.
- Create a gateway in the ASM instance.
- Create istio-myexample-customingressgateway.yaml file and add the following content to the file:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-myexample-customingressgateway
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- '*.aliyun.com'
port:
name: http
number: 80
protocol: HTTP
tls:
httpsRedirect: true
- hosts:
- '*.aliyun.com'
port:
name: https
number: 443
protocol: HTTPS
tls:
mode: SIMPLE
privateKey: /etc/istio/ingressgateway-certs/tls.key
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
- Run the following command to create a gateway:
kubectl apply -f istio-myexample-customingressgateway.yaml
- Create a virtual service in the ASM instance.
- Create the istio-myexample-customvirtualservice.yaml file and add the following content to the file:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: istio-myexample-customvirtualservice
spec:
hosts:
- "www.aliyun.com"
gateways:
- istio-myexample-customingressgateway
http:
- route:
- destination:
host: myexampleapp.default.svc.cluster.local
port:
number: 80
- Run the following command to create a virtual service:
kubectl apply -f istio-myexample-customvirtualservice.yaml
- Run the following command to obtain the IP address of the ingress gateway in the cluster:
kubectl get svc -n istio-system -l istio=ingressgateway
- Run the following command to access aliyun.com over HTTPS:
curl -k -H Host:www.aliyun.com --resolve www.aliyun.com:443:{IP address of the ingress gateway} https://www.aliyun.com
Expected output:
Welcome to aliyun.com!
Scenario 2: Use cert-manager to issue a DNS certificate
Prerequisites
- An Alibaba Cloud domain name with an Internet Content Provider (ICP) filing is available.
- A webhook is configured in your cluster to add DNS records.
You can use
alidns-webhook to configure a webhook. In this example, run the following command in your cluster
to configure a webhook:
https://gitee.com/godu/helminit/raw/master/cert-manager/alidns-cm-webhook.yaml
Step 1: Create a Secret for the webhook
- Create a RAM user.
- Log on to the RAM console by using your Alibaba Cloud account.
- In the left-side navigation pane of the RAM console, choose .
- On the Users page, click Create User.
- On the Create User page, set the Logon Name and Display Name parameters, select OpenAPI Call, and then click OK.
Record the AccessKey ID and AccessKey secret of the RAM user.
- Attach the AliyunDNSFullAccess policy to the RAM user.
- On the Users page, find the RAM user to which you want to attach the policy and click Add Permissions in the Actions column.
- In the Add Permissions panel, enter AliyunDNSFullAccess in the search box on the System Policy tab, click the AliyunDNSFullAccess policy, and then click OK.
- Attach a custom policy to the RAM user.
- In the left-side navigation pane of the RAM console, choose .
- On the Policies page, click Create Policy.
- On the Create Policy page, click the JSON tab, enter the following content, and then click Next Step:
{
"Version": "1",
"Statement": [
{
"Action": "*",
"Resource": "acs:alidns:*:*:domain/#domain-name",
"Effect": "Allow"
},
{
"Action": [
"alidns:DescribeSiteMonitorIspInfos",
"alidns:DescribeSiteMonitorIspCityInfos",
"alidns:DescribeSupportLines",
"alidns:DescribeDomains",
"alidns:DescribeDomainNs",
"alidns:DescribeDomainGroups"
],
"Resource": "acs:alidns:*:*:*",
"Effect": "Allow"
}
]
}
Replace #domain-name
with your own domain name, such as example.com.
- Enter a policy name and click OK.
- Run the following commands to use Base64 to encode the AccessKey ID and AccessKey secret that are generated in Step 1:
echo -n <AccessKey ID> | base64
echo -n <AccessKey Secret> | base64
- Create a Secret in the cluster.
- Create the alidns-secret.yaml file and add the following content to the file:
apiVersion: v1
kind: Secret
metadata:
name: alidns-secret
namespace: cert-manager
data:
access-key: YOUR_ACCESS_KEY_BASE64 # The Base64-encoded AccesssKey ID.
secret-key: YOUR_SECRET_KEY_BASE64 # The Base64-encoded AccesssKey secret.
- Create a Secret.
kubectl apply -f alidns-secret.yaml
Step 2: Create a ClusterIssuer and a certificate in the cluster
- Create a ClusterIssuer.
- Create the letsencrypt-staging.yaml file and add the following content to the file:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-staging-account-key
solvers:
- dns01:
webhook:
groupName: acme.yourcompany.com
solverName: alidns
config:
region: ""
accessKeySecretRef:
name: alidns-secret
key: access-key
secretKeySecretRef:
name: alidns-secret
key: secret-key
- Run the following command to create a ClusterIssuer:
kubectl apply -f letsencrypt-staging.yaml
- Create a certificate.
- Create the example-tls.yaml file and add the following content to the file:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-tls
namespace: istio-system
spec:
# The secretName will store certificate content
secretName: istio-ingressgateway-certs
commonName: istio-ingressgateway-certs
dnsNames:
# Replace to your real DNS name
- example.com
- "*.example.com"
issuerRef:
name: letsencrypt-staging
kind: ClusterIssuer
- Run the following command to create a certificate:
kubectl apply -f example-tls.yaml
After the ClusterIssuer and certificate are created, cert-manager issues the certificate
and private key to the istio-ingressgateway-certs Secret.
Step 3: Create a volume that is mounted with the certificate and private key on an
ingress gateway
- Log on to the ASM console.
- In the left-side navigation pane, choose .
- On the Mesh Management page, find the ASM instance that you want to configure. Click the name of the ASM
instance or click Manage in the Actions column.
- On the details page of the ASM instance, click ASM Gateways in the left-side navigation pane.
- On the ASM Gateways page, click YAML in the Actions column of the ingress gateway that you want to manage.
- Edit the YAML file of the ingress gateway by adding the following content to the
spec
field: secretVolumes:
- mountPath: /etc/istio/ingressgateway-certs
name: ingressgateway-certs
secretName: istio-ingressgateway-certs
The following sample code provides an example of the edited YAML file:
apiVersion: istio.alibabacloud.com/v1beta1
kind: IstioGateway
metadata:
name: ingressgateway
namespace: istio-system
spec:
clusterIds:
- c58638b491a5248669b59609e0a17****
cpu: {}
externalTrafficPolicy: Local
maxReplicas: 1
minReplicas: 1
ports:
- name: status-port
port: 15020
targetPort: 15020
- name: http2
nodePort: 31380
port: 80
targetPort: 80
- name: https
nodePort: 31390
port: 443
targetPort: 443
- name: tls
port: 15443
targetPort: 15443
replicaCount: 1
secretVolumes:
- mountPath: /etc/istio/ingressgateway-certs
name: ingressgateway-certs
secretName: istio-ingressgateway-certs
serviceAnnotations:
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-spec: slb.s1.small
serviceType: LoadBalancer
Step 4: Check the configurations of the ingress gateway in the cluster
- Run the following command to check whether the tls.crt and tls.key files are loaded
in the pod of the ingress gateway:
kubectl exec -it -n istio-system $(kubectl -n istio-system get pods -l istio=ingressgateway -o jsonpath='{.items[0].metadata.name}') -- ls -al /etc/istio/ingressgateway-certs
Expected output:
lrwxrwxrwx 1 root root 14 May 9 01:14 tls.crt -> ..data/tls.crt
lrwxrwxrwx 1 root root 14 May 9 01:14 tls.key -> ..data/tls.key
- Run the following command to check whether the value of the
Subject
field is correct in the certificate loaded on the ingress gateway: kubectl exec -it -n istio-system $(kubectl -n istio-system get pods -l istio=ingressgateway -o jsonpath='{.items[0].metadata.name}') -- cat /etc/istio/ingressgateway-certs/tls.crt | openssl x509 -text -noout | grep 'Subject:'
Expected output:
Subject: O = cert-manager + O = cluster.local, CN = istio-ingressgateway-certs
- Run the following command to check whether the proxy of the ingress gateway can access
the certificate:
kubectl exec -it -n istio-system $(kubectl -n istio-system get pods -l istio=ingressgateway -o jsonpath='{.items[0].metadata.name}') -- curl 127.0.0.1:15000/certs
Expected output:
{
"certificates": [
{
"ca_cert": [
{
"path": "\u003cinline\u003e",
"serial_number": "4edcf3",
"subject_alt_names": [],
"days_until_expiration": "7251",
"valid_from": "2022-01-06T06:17:00Z",
"expiration_time": "2042-01-01T06:22:03Z"
}
],
...........
Step 5: Verify that you can access a service over HTTPS
- Create a service in the cluster.
- Create the myexample-nginx.conf file and add the following content to the file.
In this example, a service whose domain name is example.com is implemented based on
NGINX. You need to create a configuration file for the NGINX server. The following
content specifies that the message
Welcome to aliyun.com!
and the status code 200 are returned for requests to the root path of the service.
events {
}
http {
log_format main '$remote_addr - $remote_user [$time_local] $status '
'"$request" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log;
server {
listen 80;
location / {
return 200 'Welcome to aliyun.com!';
add_header Content-Type text/plain;
}
}
}
- Run the following command to create a ConfigMap for the NGINX server:
kubectl create configmap myexample-nginx-configmap --from-file=nginx.conf=./myexample-nginx.conf
- Run the following command to enable automatic sidecar injection for the default namespace:
kubectl label namespace default istio-injection=enabled
- Create the myexampleapp.yaml file and add the following content to the file:
apiVersion: v1
kind: Service
metadata:
name: myexampleapp
labels:
app: myexampleapp
spec:
ports:
- port: 80
protocol: TCP
selector:
app: myexampleapp
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myexampleapp
spec:
selector:
matchLabels:
app: myexampleapp
replicas: 1
template:
metadata:
labels:
app: myexampleapp
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx
readOnly: true
volumes:
- name: nginx-config
configMap:
name: myexample-nginx-configmap
- Run the following command to create an internal service whose domain name is example.com:
kubectl apply -f myexampleapp.yaml
- Use kubectl to connect to your ASM instance. For more information, see Use kubectl to connect to an ASM instance.
- Create a gateway in the ASM instance.
- Create istio-myexample-customingressgateway.yaml file and add the following content to the file:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-myexample-customingressgateway
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- '*.example.com'
port:
name: http
number: 80
protocol: HTTP
tls:
httpsRedirect: true
- hosts:
- '*.example.com'
port:
name: https
number: 443
protocol: HTTPS
tls:
mode: SIMPLE
privateKey: /etc/istio/ingressgateway-certs/tls.key
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
- Run the following command to create a gateway:
kubectl apply -f istio-myexample-customingressgateway.yaml
- Create a virtual service in the ASM instance.
- Create the istio-myexample-customvirtualservice.yaml file and add the following content to the file:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: istio-myexample-customvirtualservice
spec:
hosts:
- "www.example.com"
gateways:
- istio-myexample-customingressgateway
http:
- route:
- destination:
host: myexampleapp.default.svc.cluster.local
port:
number: 80
- Run the following command to create a virtual service:
kubectl apply -f istio-myexample-customvirtualservice.yaml
- Visit example.com in a web browser.
If the following page appears, you can access the service over HTTPS.
