This topic shows you how to use an Istio gateway to enable HTTPS by using a secret volume to mount the certificates to the container of a sidecar proxy.

Prerequisites

Step 1: Prepare a server certificate and private key pair

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.

  1. 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
  2. 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

Step 2: Store the server certificate and private key in a secret

Run the following command to create a secret that contains the server certificate and private key:

kubectl create -n istio-system secret tls istio-ingressgateway-certs --key aliyun.com.key --cert aliyun.com.crt
Note Run the preceding command to create a secret in the kubeconfig file of the cluster to which the ingress gateway pod belongs.

Step 3: Create a volume that is mounted with the server certificate and private key on the ingress gateway

  1. Log on to the ASM console.
  2. In the left-side navigation pane, choose Service Mesh > Mesh Management.
  3. 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 of the ASM instance.
  4. On the details page of the ASM instance, click ASM Gateways in the left-side navigation pane.
  5. On the ASM Gateways page, click YAML in the Actions column of the ingress gateway that you want to manage.
  6. 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 code shows the content of the edited YAML file:

    apiVersion: istio.alibabacloud.com/v1beta1
    kind: IstioGateway
    metadata:
      name: ingressgateway
      namespace: istio-system
    spec:
      clusterIds:
        - c58638b491a5248669b59609e0a17****
      cpu: null
      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 configuration of the ingress gateway

After you edit the YAML file of the ingress gateway, the ingress gateway pod loads the server certificate and private key.

Run the following command on the cluster to which the ingress gateway pod belongs to check whether the tls.crt and tls.key files are mounted to the ingress gateway pod:

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

The following output is expected:

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 on the cluster to which the ingress gateway pod belongs to check whether the subject field of the ingress gateway certificate is correct:

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:'

Run the following command on the cluster to which the ingress gateway pod belongs to check whether the ingress gateway proxy can access Transport Layer Security (TLS) certificates:

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

Step 5: Define an internal service

The internal services in this example are implemented based on NGINX. You must create a configuration file for the NGINX server first. Take an internal service of the aliyun.com domain name as an example. Define the requested root path to directly return the sentence Welcome to 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 / {
        return 200 'Welcome to aliyun.com!';
        add_header Content-Type text/plain;
    }
  }
}
  1. Run the following command on the cluster to which the ingress gateway pod belongs 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
  2. Run the following command on the cluster to which the ingress gateway pod belongs to enable automatic sidecar injection for the namespace that is named default:
    kubectl label namespace default istio-injection=enabled
  3. Create a myexampleapp.yaml file that contains the following content. Then, run the kubectl apply -f myexampleapp.yaml command to create an internal service for the 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 6: Define an Istio gateway

  1. Log on to the ASM console.
  2. In the left-side navigation pane, choose Service Mesh > Mesh Management.
  3. 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 of the ASM instance.
  4. On the details page of the ASM instance, choose Traffic Management > Gateway in the left-side navigation pane. On the Gateway page, click Create.
  5. In the Create panel, perform the following steps to define a virtual service. Then, click OK.
    1. Select a namespace as required. In this example, the default namespace is used.
    2. In the code editor, define an Istio gateway. The following code shows a sample YAML 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
    On the Gateway page, you can view the created Istio gateway.

Step 7: Define a virtual service

  1. Log on to the ASM console.
  2. In the left-side navigation pane, choose Service Mesh > Mesh Management.
  3. 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 of the ASM instance.
  4. On the details page of the ASM instance, choose Traffic Management > VirtualService in the left-side navigation pane. On the VirtualService page, click Create.
  5. In the Create panel, perform the following steps to define a virtual service. Then, click OK.
    1. Select a namespace as required. In this example, the default namespace is used.
    2. In the code editor, define a virtual service. The following code shows a sample YAML 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
    On the VirtualService page, you can view the created virtual service.

Execution 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. For more information, see Deploy an ingress gateway service.
  • Run the following command on the cluster to which the ingress gateway pod belongs to query the IP address of the ingress gateway:
    kubectl get svc -n istio-system -l istio=ingressgateway
  • Run the following command to access the aliyun.com domain name by using HTTPS:
    curl -k -H Host:www.aliyun.com --resolve www.aliyun.com:443:{IP address of the ingress gateway}  https://www.aliyun.com

    The following output is expected:

    Welcome to aliyun.com!