全部產品
Search
文件中心

Alibaba Cloud Service Mesh:通過ASM網關啟用HTTPS安全服務

更新時間:Jan 13, 2025

當您需要對外提供加密的HTTPS訪問時,可以通過ASM網關啟用HTTPS安全服務。ASM網關支援認證的動態載入,您可以即時動態地配置私密金鑰、伺服器憑證和根憑證,無需重啟網關或依賴Secret卷掛載,降低操作複雜性並消除因重啟造成的服務中斷風險。ASM網關能夠監控並管理多個認證和私密金鑰對,為不同的主機提供靈活且安全的通訊能力,加強資料轉送的安全性。

前提條件

背景資訊

Istio支援動態載入認證。TLS(Transport Layer Security)所需的私密金鑰、伺服器憑證以及根憑證,都可以在網關不重啟的條件下動態配置。ASM網關會監視所在命名空間中的Secret,通過Gateway CR實現動態載入。ASM網關的HTTPS協議支援有以下優勢:

  • 入口網關可以在不需要重啟的情況下,動態添加、刪除或更新所需要的認證、私密金鑰或者對應的根憑證。

  • 不需要Secret卷掛載。建立Kubernetes Secret後,ASM網關會捕獲該Secret,並將其包含的認證、私密金鑰或根憑證發送到入口網關。

  • ASM網關可以監視多個認證、私密金鑰對,只需要為多個主機建立Secret並更新網關規則。

步驟一:為多個主機準備伺服器憑證和私密金鑰

使用網域名稱時需要備案才能正常訪問。本樣本中使用aliyun.com產生認證和私密金鑰,並儲存為Secret。

如果您已經擁有針對aliyun.com可用的認證和私密金鑰,需要將密鑰命名為aliyun.com.key,認證命名為aliyun.com.crt。如果沒有,可以通過openssl,執行以下步驟來產生認證和密鑰。

  1. 執行以下命令,建立根憑證和私密金鑰。

    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. 執行以下命令,為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
  3. 按照ASM執行個體版本,建立Secret或認證。

    • ASM執行個體為1.17以下

      在入口網關Pod所在的叢集對應的KubeConfig環境下,執行以下命令,在istio-system命名空間中建立包含認證和私密金鑰的Secret。

      kubectl create -n istio-system secret tls myexample-credential --key=aliyun.com.key --cert=aliyun.com.crt
      重要

      Secret名稱不能以istio或prometheus開頭,且不能包含token欄位。

    • ASM執行個體為1.17及以上

      1. 登入ASM控制台,在左側導覽列,選擇服務網格 > 網格管理

      2. 網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇ASM網關 > 認證管理

      3. 認證管理頁面,單擊建立,然後在認證資訊面板,配置相關資訊,單擊確定

        配置項

        說明

        名稱

        輸入認證的名稱,本樣本為myexample-credential

        密鑰憑證

        步驟2產生的aliyun.com.crt內容。

        私密金鑰

        步驟2產生的aliyun.com.key內容。

步驟二:為a.aliyun.com定義內部服務

樣本中的內部服務是基於Nginx實現的,首先為Nginx伺服器建立設定檔。以網域名稱a.aliyun.com的內部服務為例,定義請求根路徑直接返回字樣Welcome to a.aliyun.com!及狀態代碼200myexample-nginx.conf的具體內容如下。

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;
    }
  }
}
  1. 在入口網關Pod所在的叢集對應的KubeConfig環境下,執行以下命令,建立Kubernetes ConfigMap(儲存Nginx伺服器的配置)。

    kubectl create configmap myexample-nginx-configmap --from-file=nginx.conf=./myexample-nginx.conf
  2. 為default命名空間啟用Sidecar網格代理自動注入。具體操作,請參見啟用自動注入

  3. 建立並拷貝以下內容到myexampleapp.yaml檔案,執行kubectl apply -f myexampleapp.yaml命令,建立網域名稱a.aliyun.com的內部服務。

    展開查看YAML

    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

步驟三:為b.aliyun.com定義內部服務

本樣本中的內部服務基於httpbin實現。

  1. 使用以下內容,建立httpbin.example.yaml檔案。

    展開查看YAML內容

    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: 80
  2. 在入口網關Pod所在的叢集對應的KubeConfig環境下,執行以下命令,建立網域名稱為b.aliyun.com的內部服務。

    kubectl apply -f httpbin.example.yaml

步驟四:建立網關規則

  1. 登入ASM控制台,在左側導覽列,選擇服務網格 > 網格管理

  2. 網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇ASM網關 > 網關規則,然後單擊使用YAML建立

  3. 建立頁面,選擇目標命名空間(本文以default為例)和任意情境模版,配置如下YAML,然後單擊建立

    展開查看YAML內容

    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'
                                    

    建立完成後,您可以在網關規則頁面,看到建立的網關。

步驟五:建立虛擬服務

  1. 登入ASM控制台,在左側導覽列,選擇服務網格 > 網格管理

  2. 網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇流量管理中心 > 虛擬服務,然後單擊使用YAML建立

  3. 建立頁面,選擇目標命名空間和任意情境模版,配置以下YAML,然後單擊建立

    展開查看YAML內容

    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      

    重複此步驟,為b.aliyun.com定義相應的虛擬服務。

    展開查看YAML內容

    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        

    建立完成後,在虛擬服務頁面,可以看到建立的虛擬服務。

執行結果

擷取入口網關服務的地址

通過命令列訪問入口網關服務

  • 執行以下命令,通過HTTPS協議訪問a.aliyun.com服務。

    curl -k -H Host:a.aliyun.com --resolve a.aliyun.com:443:{替換成真實的入口網關IP地址}  https://a.aliyun.com/hello

    預期輸出:

    Welcome to aliyun.com!
  • 執行以下命令,通過HTTPS協議訪問b.aliyun.com服務。

    curl -k -H Host:b.aliyun.com --resolve b.aliyun.com:443:{替換成真實的入口網關IP地址}  https://b.aliyun.com/status/418  

    預期輸出:

        -=[ teapot ]=-
    
           _...._
         .'  _ _ `.
        | ."` ^ `". _,
        \_;`"---"`|//
          |       ;/
          \_     _/
            `"""`

相關操作

更新網關認證

如果您要更新網關掛載的認證,需要在資料面建立一個Secret,然後修改Gateway資源的credentialName欄位值為Secret的名稱,網關將自動掛載新的Secret。本文以為example.com伺服器建立名為new-istio-ingressgateway-certs的Secret為例。

  1. 建立頒發者為myexample的認證。

    1. OpenSSL工具中執行以下命令,建立根憑證和私密金鑰。

      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
    2. 執行以下命令,為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
    3. 擷取叢集KubeConfig並通過kubectl工具串連叢集

    4. 執行以下命令,建立名為new-istio-ingressgateway-certs的Secret。

      kubectl create -n istio-system secret tls new-istio-ingressgateway-certs --key example.com.key --cert example.com.crt
  2. 在叢集中執行以下命令,刪除舊的認證Secret。

    kubectl delete secret  istio-ingressgateway-certs -n istio-system
  3. 更新網關規則。

    1. 登入ASM控制台,在左側導覽列,選擇服務網格 > 網格管理

    2. 網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇ASM網關 > 網關規則

    3. 網關規則頁面,單擊目標規則右側操作列下的查看YAML

    4. 編輯對話方塊,修改credentialName參數值為新的認證Secret名稱new-istio-ingressgateway-certs,然後單擊確定

  4. 驗證更新網關認證是否成功。

    1. 執行以下命令,在叢集中查看當前認證資訊。

      kubectl exec istio-ingressgateway-xxxx -n istio-system -- curl localhost:15000/config_dump  > ingressgateway_dump.yaml
    2. 執行以下命令,列印並搜尋new-istio-ingressgateway-certs認證。

      cat ingressgateway_dump.yaml | grep new-istio-ingressgateway-certs -A 3

      預期輸出:

      認證

      複製以上inline_bytes參數後的內容,擷取Base64編碼後的認證。

    3. 在本地命令列工具中執行以下命令,將認證進行Base64解碼。

      echo <Base64編碼後的認證內容> | base64 --decode
    4. 將Base64解碼內容儲存為test.com.crt檔案。

    5. 在OpenSSL工具中執行以下命令,查看認證的組織。

      openssl x509 -in test.com.crt -text -noout

      預期輸出:

      組織

      可以看到組織成功更換為myexample,說明網關認證更新成功。