In Alibaba Cloud Service Mesh (ASM), you can use Secret Discovery Service (SDS) to
improve the security of Istio gateways with HTTPS security support and dynamic certificate
loading. This topic shows you how to use SDS to configure a Transport Layer Security
(TLS) ingress gateway.
Background information
Istio provides SDS for dynamic certificate loading. You can use SDS to configure
the private key, server certificate, and root certificate that are required for TLS.
An ingress gateway proxy runs in the same pod as the ingress gateway and listens to
the secret that is created in the namespace of the ingress gateway. You can obtain
the following benefits by enabling SDS for an ingress gateway:
- The ingress gateway can dynamically add, delete, and update the server certificate
and private key or the root certificate as required without the need to restart the
service.
- No secret volume is required to be mounted. After a Kubernetes secret is created,
the ingress gateway proxy can obtain the secret and send the server certificate and
private key or the root certificate to the ingress gateway.
- If you create secrets for multiple servers and update the ingress gateway, the ingress
gateway proxy can listen to multiple server certificates and private key pairs.
Step 1: Prepare server certificates and private key pairs for multiple servers
Generate a server certificate and private key pair for the aliyun.com
domain name and store the pair in a secret.
If you have an available server certificate and private key pair for the aliyun.com
domain name, rename the private key to aliyun.com.key
and the server certificate to aliyun.com.crt
. Alternatively, run the following openssl commands to create a server certificate and private key pair for aliyun.com.
- Run the following command to create a root certificate and a private key:
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=myexample Inc./CN=aliyun.com' -keyout aliyun.root.key -out aliyun.root.crt
- Run the following commands to generate a server certificate and private key pair for
the server of
aliyun.com
: openssl req -out aliyun.com.csr -newkey rsa:2048 -nodes -keyout aliyun.com.key -subj "/CN=aliyun.com/O=myexample organization"
openssl x509 -req -days 365 -CA aliyun.root.crt -CAkey aliyun.root.key -set_serial 0 -in aliyun.com.csr -out aliyun.com.crt
- Run the following command in the cluster to which the ingress gateway pod belongs
to create a secret that contains the server certificate and private key pair in the
istio-system namespace:
kubectl create -n istio-system secret tls myexample-credential --key=aliyun.com.key --cert=aliyun.com.crt
Notice The name of the secret cannot start with istio or prometheus and cannot contain the
token field.
Step 2: Define an internal service for a.aliyun.com
The internal services in this example are implemented based on NGINX. You must create
a configuration file for the NGINX server first. In this example, an internal service
of the a.aliyun.com
domain name is used. Define the requested root path to directly return the sentence
Welcome to a.aliyun.com! and status code 200. The myexample-nginx.conf file contains the following content:
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 /hello {
return 200 'Welcome to a.aliyun.com!';
add_header Content-Type text/plain;
}
}
}
- In the cluster to which the ingress gateway pod belongs, run the following command
to create a ConfigMap for storing the configuration of the NGINX server:
kubectl create configmap myexample-nginx-configmap --from-file=nginx.conf=./myexample-nginx.conf
- In the ASM console, click the corresponding ASM instance. In the left-side navigation
pane, click Namespace. Enable automatic sidecar injection for the default namespace.
- Create a myexampleapp.yaml file that contains the following code. Then, run the
kubectl apply -f myexampleapp.yaml
command to create an internal service for the a.aliyun.com domain name. 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
Step 3: Define an internal service for b.aliyun.com
The internal services in this example are implemented based on HTTPBin. Create a httpbin.example.yaml
file that contains the following code. Then, run the kubectl apply -f httpbin.example.yaml
command in the cluster to which the ingress gateway pod belongs to create an internal
service for the b.aliyun.com
domain name.
apiVersion: v1
kind: Service
metadata:
name: httpbin
labels:
app: httpbin
spec:
ports:
- name: http
port: 8000
selector:
app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
version: v1
template:
metadata:
labels:
app: httpbin
version: v1
spec:
containers:
- image: docker.io/citizenstig/httpbin
imagePullPolicy: IfNotPresent
name: httpbin
ports:
- containerPort: 8000
Step 4: Define an Istio 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, choose in the left-side navigation pane. On the Gateway page, click Create from YAML.
- On the Create page, perform the following steps to define an Istio gateway. Then,
click Create.
- Select a namespace as required. In this example, the default namespace is used.
- In the code editor, define an Istio gateway by using the following YAML template:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: mysdsgateway
spec:
selector:
istio: ingressgateway # use istio default ingress gateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: myexample-credential # must be the same as secret
hosts:
- '*.aliyun.com'
On the Gateway page, you can view the defined Istio gateway.
Step 5: Define a virtual service
- 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, choose in the left-side navigation pane. On the VirtualService page, click Create from YAML.
- On the Create page, perform the following steps to define a virtual service. Then,
click Create.
- Select a namespace as required. In this example, the default namespace is used.
- In the code editor, define a virtual service by using the following YAML template:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: mysdsgateway-myexamplevs
spec:
hosts:
- "a.aliyun.com"
gateways:
- mysdsgateway
http:
- match:
- uri:
exact: /hello
route:
- destination:
host: myexampleapp.default.svc.cluster.local
port:
number: 80
Define a virtual service for httpbin.example.com in a similar way.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: mysdsgateway-httpbinvs
spec:
hosts:
- "b.aliyun.com"
gateways:
- mysdsgateway
http:
- match:
- uri:
prefix: /status
- uri:
prefix: /delay
route:
- destination:
port:
number: 8000
host: httpbin.default.svc.cluster.local
On the VirtualService page, you can view the defined virtual service.
View the result
Use one of the following methods to query the IP address of the ingress gateway:
- View the IP address of the ingress gateway in the ASM console: In the ASM console,
click the corresponding ASM instance. In the left-side navigation pane, click ASM
Gateways. On the ASM Gateways page, view the IP address of the ingress gateway.
- View the IP address of the ingress gateway in the ACK console. For more information,
see Deploy an ingress gateway service.
Run the following commands to access the ingress gateway service:
- Run the following command to access the aliyun.com domain name over HTTPS:
curl -k -H Host:a.aliyun.com --resolve a.aliyun.com:443:{IP address of the ingress gateway} https://a.aliyun.com/hello
Expected output:
Welcome to aliyun.com!
- Run the following command to access the httpbin.example.com domain name over HTTPS:
curl -k -H Host:b.aliyun.com --resolve b.aliyun.com:443:{IP address of the ingress gateway} https://b.aliyun.com/status/418
Expected output:
-=[ teapot ]=-
_...._
.' _ _ `.
| ."` ^ `". _,
\_;`"---"`|//
| ;/
\_ _/
`"""`
Update gateway certificates
After you recreate a secret that is used to load a certificate on the data plane,
you must manually modify the credentialName parameter to the new secret name for a gateway to update the gateway certificate.
In this following example, the secret named new-istio-ingressgateway-certs for the
server of example.com is created.
- Create a certificate whose issuer is myexample.
- Run the following openssl command to create a root certificate and a private key:
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=myexample Inc./CN=example.com' -keyout example.root.key -out example.root.crt
- Run the following commands to generate a server certificate and private key pair for
the server of example.com:
openssl req -out example.com.csr -newkey rsa:2048 -nodes -keyout example.com.key -subj "/CN=example.com/O=myexample organization"
openssl x509 -req -days 365 -CA example.root.crt -CAkey example.root.key -set_serial 0 -in example.com.csr -out example.com.crt
- Connect to ACK clusters by using kubectl.
- Run the following command to create a secret named new-istio-ingressgateway-certs:
kubectl create -n istio-system secret tls new-istio-ingressgateway-certs --key example.com.key --cert example.com.crt
- Run the following command in the cluster to delete the earlier secret:
kubectl delete secret istio-ingressgateway-certs -n istio-system
- Update a 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, choose in the left-side navigation pane.
- On the Gateway page, find the gateway that you want to update and click YAML in the Actions column.
- In the Edit panel, change the value of the credentialName parameter to new-istio-ingressgateway-certs, and click OK.
- Verify that the gateway certificate is updated.
- Run the following command in the cluster to view the current certificate information:
kubectl exec istio-ingressgateway-xxxx -n istio-system -- curl localhost:15000/config_dump > ingressgateway_dump.yaml
- Run the following command to search for and display the new-istio-ingressgateway-certs
certificate:
cat ingressgateway_dump.yaml | grep new-istio-ingressgateway-certs -A 3
The following figure shows the expected output.

Copy the content of the inline_bytes parameter to obtain the Base64-encoded certificate.
- Run the following command in an on-premises command-line tool to decode the Base64-encoded
certificate:
echo <Base64-encoded certificate> | base64 --decode
- Save the decoded content as the test.com.crt file.
- Run the following openssl command to view the organization of the certificate:
openssl x509 -in test.com.crt -text -noout
The following figure shows the expected output.

The organization is changed to myexample. This indicates that the gateway certificate
is updated.