當您需要對外提供加密的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,執行以下步驟來生成證書和密鑰。
執行以下命令,創建根證書和私鑰。
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
執行以下命令,為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
按照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及以上
步驟二:為a.aliyun.com定義內部服務
示例中的內部服務是基于Nginx實現的,首先為Nginx服務器創建配置文件。以域名a.aliyun.com的內部服務為例,定義請求根路徑直接返回字樣Welcome to a.aliyun.com!
及狀態碼200
。myexample-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;
}
}
}
在入口網關Pod所在的集群對應的KubeConfig環境下,執行以下命令,創建Kubernetes ConfigMap(存儲Nginx服務器的配置)。
kubectl create configmap myexample-nginx-configmap --from-file=nginx.conf=./myexample-nginx.conf
為default命名空間啟用Sidecar網格代理自動注入。具體操作,請參見啟用自動注入。
創建并拷貝以下內容到myexampleapp.yaml文件,執行
kubectl apply -f myexampleapp.yaml
命令,創建域名a.aliyun.com的內部服務。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實現。
使用以下內容,創建httpbin.example.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
在入口網關Pod所在的集群對應的KubeConfig環境下,執行以下命令,創建域名為b.aliyun.com的內部服務。
kubectl apply -f httpbin.example.yaml
步驟四:創建網關規則
登錄ASM控制臺,在左側導航欄,選擇 。
在網格管理頁面,單擊目標實例名稱,然后在左側導航欄,選擇 ,然后單擊使用YAML創建。
在創建頁面,選擇目標命名空間(本文以default為例)和任意場景模版,配置如下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'
創建完成后,您可以在網關規則頁面,看到新建的網關。
步驟五:創建虛擬服務
登錄ASM控制臺,在左側導航欄,選擇 。
在網格管理頁面,單擊目標實例名稱,然后在左側導航欄,選擇 ,然后單擊使用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定義相應的虛擬服務。
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
創建完成后,在虛擬服務頁面,可以看到新建的虛擬服務。
執行結果
獲取入口網關服務的地址
方式一:通過ASM控制臺查看。登錄ASM控制臺,選中對應的服務網格實例,在左側導航欄選擇 。在入口網關頁面中查看對應的信息。
方式二:通過容器服務管理控制臺查看。具體操作,請參見查看入口網關的服務信息。
通過命令行訪問入口網關服務
執行以下命令,通過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為例。
創建頒發者為myexample的證書。
在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
執行以下命令,為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
執行以下命令,創建名為new-istio-ingressgateway-certs的Secret。
kubectl create -n istio-system secret tls new-istio-ingressgateway-certs --key example.com.key --cert example.com.crt
在集群中執行以下命令,刪除舊的證書Secret。
kubectl delete secret istio-ingressgateway-certs -n istio-system
更新網關規則。
登錄ASM控制臺,在左側導航欄,選擇 。
在網格管理頁面,單擊目標實例名稱,然后在左側導航欄,選擇 。
在網關規則頁面,單擊目標規則右側操作列下的查看YAML。
在編輯對話框,修改credentialName參數值為新的證書Secret名稱new-istio-ingressgateway-certs,然后單擊確定。
驗證更新網關證書是否成功。
執行以下命令,在集群中查看當前證書信息。
kubectl exec istio-ingressgateway-xxxx -n istio-system -- curl localhost:15000/config_dump > ingressgateway_dump.yaml
執行以下命令,打印并搜索new-istio-ingressgateway-certs證書。
cat ingressgateway_dump.yaml | grep new-istio-ingressgateway-certs -A 3
預期輸出:
復制以上inline_bytes參數后的內容,獲取Base64編碼后的證書。
在本地命令行工具中執行以下命令,將證書進行Base64解碼。
echo <Base64編碼后的證書內容> | base64 --decode
將Base64解碼內容保存為test.com.crt文件。
在OpenSSL工具中執行以下命令,查看證書的組織。
openssl x509 -in test.com.crt -text -noout
預期輸出:
可以看到組織成功更換為
myexample
,說明網關證書更新成功。