通過ASM網(wǎng)關(guān)啟用HTTPS安全服務
當您需要對外提供加密的HTTPS訪問時,可以通過ASM網(wǎng)關(guān)啟用HTTPS安全服務。ASM網(wǎng)關(guān)支持證書的動態(tài)加載,您可以實時動態(tài)地配置私鑰、服務器證書和根證書,無需重啟網(wǎng)關(guān)或依賴Secret卷掛載,降低操作復雜性并消除因重啟造成的服務中斷風險。ASM網(wǎng)關(guān)能夠監(jiān)控并管理多個證書和私鑰對,為不同的主機提供靈活且安全的通信能力,加強數(shù)據(jù)傳輸?shù)陌踩浴?/p>
前提條件
背景信息
Istio支持動態(tài)加載證書。TLS(Transport Layer Security)所需的私鑰、服務器證書以及根證書,都可以在網(wǎng)關(guān)不重啟的條件下動態(tài)配置。ASM網(wǎng)關(guān)會監(jiān)視所在命名空間中的Secret,通過Gateway CR實現(xiàn)動態(tài)加載。ASM網(wǎng)關(guān)的HTTPS協(xié)議支持有以下優(yōu)勢:
入口網(wǎng)關(guān)可以在不需要重啟的情況下,動態(tài)添加、刪除或更新所需要的證書、私鑰或者對應的根證書。
不需要Secret卷掛載。創(chuàng)建Kubernetes Secret后,ASM網(wǎng)關(guān)會捕獲該Secret,并將其包含的證書、私鑰或根證書發(fā)送到入口網(wǎng)關(guān)。
ASM網(wǎng)關(guān)可以監(jiān)視多個證書、私鑰對,只需要為多個主機創(chuàng)建Secret并更新網(wǎng)關(guān)規(guī)則。
步驟一:為多個主機準備服務器證書和私鑰
使用域名時需要備案才能正常訪問。本示例中使用aliyun.com生成證書和私鑰,并保存為Secret。
如果您已經(jīng)擁有針對aliyun.com可用的證書和私鑰,需要將密鑰命名為aliyun.com.key,證書命名為aliyun.com.crt。如果沒有,可以通過openssl,執(zhí)行以下步驟來生成證書和密鑰。
執(zhí)行以下命令,創(chuàng)建根證書和私鑰。
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
執(zhí)行以下命令,為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實例版本,創(chuàng)建Secret或證書。
ASM實例為1.17以下
在入口網(wǎng)關(guān)Pod所在的集群對應的KubeConfig環(huán)境下,執(zhí)行以下命令,在istio-system命名空間中創(chuàng)建包含證書和私鑰的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定義內(nèi)部服務
示例中的內(nèi)部服務是基于Nginx實現(xiàn)的,首先為Nginx服務器創(chuàng)建配置文件。以域名a.aliyun.com的內(nèi)部服務為例,定義請求根路徑直接返回字樣Welcome to a.aliyun.com!
及狀態(tài)碼200
。myexample-nginx.conf的具體內(nèi)容如下。
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;
}
}
}
在入口網(wǎng)關(guān)Pod所在的集群對應的KubeConfig環(huán)境下,執(zhí)行以下命令,創(chuàng)建Kubernetes ConfigMap(存儲Nginx服務器的配置)。
kubectl create configmap myexample-nginx-configmap --from-file=nginx.conf=./myexample-nginx.conf
為default命名空間啟用Sidecar網(wǎng)格代理自動注入。具體操作,請參見啟用自動注入。
創(chuàng)建并拷貝以下內(nèi)容到myexampleapp.yaml文件,執(zhí)行
kubectl apply -f myexampleapp.yaml
命令,創(chuàng)建域名a.aliyun.com的內(nèi)部服務。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定義內(nèi)部服務
本示例中的內(nèi)部服務基于httpbin實現(xiàn)。
使用以下內(nèi)容,創(chuàng)建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
在入口網(wǎng)關(guān)Pod所在的集群對應的KubeConfig環(huán)境下,執(zhí)行以下命令,創(chuàng)建域名為b.aliyun.com的內(nèi)部服務。
kubectl apply -f httpbin.example.yaml
步驟四:創(chuàng)建網(wǎng)關(guān)規(guī)則
登錄ASM控制臺,在左側(cè)導航欄,選擇 。
在網(wǎng)格管理頁面,單擊目標實例名稱,然后在左側(cè)導航欄,選擇 ,然后單擊使用YAML創(chuàng)建。
在創(chuàng)建頁面,選擇目標命名空間(本文以default為例)和任意場景模版,配置如下YAML,然后單擊創(chuàng)建。
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'
創(chuàng)建完成后,您可以在網(wǎng)關(guān)規(guī)則頁面,看到新建的網(wǎng)關(guān)。
步驟五:創(chuàng)建虛擬服務
登錄ASM控制臺,在左側(cè)導航欄,選擇 。
在網(wǎng)格管理頁面,單擊目標實例名稱,然后在左側(cè)導航欄,選擇 ,然后單擊使用YAML創(chuàng)建。
在創(chuàng)建頁面,選擇目標命名空間和任意場景模版,配置以下YAML,然后單擊創(chuàng)建。
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
創(chuàng)建完成后,在虛擬服務頁面,可以看到新建的虛擬服務。
執(zhí)行結(jié)果
獲取入口網(wǎng)關(guān)服務的地址
方式一:通過ASM控制臺查看。登錄ASM控制臺,選中對應的服務網(wǎng)格實例,在左側(cè)導航欄選擇 。在入口網(wǎng)關(guān)頁面中查看對應的信息。
方式二:通過容器服務管理控制臺查看。具體操作,請參見查看入口網(wǎng)關(guān)的服務信息。
通過命令行訪問入口網(wǎng)關(guān)服務
執(zhí)行以下命令,通過HTTPS協(xié)議訪問a.aliyun.com服務。
curl -k -H Host:a.aliyun.com --resolve a.aliyun.com:443:{替換成真實的入口網(wǎng)關(guān)IP地址} https://a.aliyun.com/hello
預期輸出:
Welcome to aliyun.com!
執(zhí)行以下命令,通過HTTPS協(xié)議訪問b.aliyun.com服務。
curl -k -H Host:b.aliyun.com --resolve b.aliyun.com:443:{替換成真實的入口網(wǎng)關(guān)IP地址} https://b.aliyun.com/status/418
預期輸出:
-=[ teapot ]=- _...._ .' _ _ `. | ."` ^ `". _, \_;`"---"`|// | ;/ \_ _/ `"""`
相關(guān)操作
更新網(wǎng)關(guān)證書
如果您要更新網(wǎng)關(guān)掛載的證書,需要在數(shù)據(jù)面新建一個Secret,然后修改Gateway資源的credentialName字段值為Secret的名稱,網(wǎng)關(guān)將自動掛載新的Secret。本文以為example.com服務器創(chuàng)建名為new-istio-ingressgateway-certs的Secret為例。
創(chuàng)建頒發(fā)者為myexample的證書。
在OpenSSL工具中執(zhí)行以下命令,創(chuàng)建根證書和私鑰。
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
執(zhí)行以下命令,為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
執(zhí)行以下命令,創(chuàng)建名為new-istio-ingressgateway-certs的Secret。
kubectl create -n istio-system secret tls new-istio-ingressgateway-certs --key example.com.key --cert example.com.crt
在集群中執(zhí)行以下命令,刪除舊的證書Secret。
kubectl delete secret istio-ingressgateway-certs -n istio-system
更新網(wǎng)關(guān)規(guī)則。
登錄ASM控制臺,在左側(cè)導航欄,選擇 。
在網(wǎng)格管理頁面,單擊目標實例名稱,然后在左側(cè)導航欄,選擇 。
在網(wǎng)關(guān)規(guī)則頁面,單擊目標規(guī)則右側(cè)操作列下的查看YAML。
在編輯對話框,修改credentialName參數(shù)值為新的證書Secret名稱new-istio-ingressgateway-certs,然后單擊確定。
驗證更新網(wǎng)關(guān)證書是否成功。
執(zhí)行以下命令,在集群中查看當前證書信息。
kubectl exec istio-ingressgateway-xxxx -n istio-system -- curl localhost:15000/config_dump > ingressgateway_dump.yaml
執(zhí)行以下命令,打印并搜索new-istio-ingressgateway-certs證書。
cat ingressgateway_dump.yaml | grep new-istio-ingressgateway-certs -A 3
預期輸出:
復制以上inline_bytes參數(shù)后的內(nèi)容,獲取Base64編碼后的證書。
在本地命令行工具中執(zhí)行以下命令,將證書進行Base64解碼。
echo <Base64編碼后的證書內(nèi)容> | base64 --decode
將Base64解碼內(nèi)容保存為test.com.crt文件。
在OpenSSL工具中執(zhí)行以下命令,查看證書的組織。
openssl x509 -in test.com.crt -text -noout
預期輸出:
可以看到組織成功更換為
myexample
,說明網(wǎng)關(guān)證書更新成功。