Istio流量管理实践之(5): 使用cert-manager部署Istio自定义入口网关及进行证书管理...
Istio Gateway提供多個自定義入口網(wǎng)關(guān)的支持能力,通過開放一系列端口用于承載網(wǎng)格邊緣的進(jìn)入連接,同時可以使用不同loadbalancer來隔離不同的入口流量。cert-manager可用于使用存儲在Kubernetes Secret資源中的任意簽名密鑰對來獲取證書。本文提供了手動創(chuàng)建自定義入口網(wǎng)關(guān)的步驟說明,以及在該網(wǎng)關(guān)中如何使用cert-manager實現(xiàn)自動配置證書。
生成簽名密鑰對
CA Issuer不會自動創(chuàng)建和管理簽名密鑰對,要么用戶自己提供,要么通過諸如OpenSSL的工具生成一個自簽名CA的新簽名密鑰對。例如,通過如下命令可以生成x509類型的密鑰和證書:
# Generate a CA private key $ docker run -it -v $(pwd):/export frapsoft/openssl genrsa -out /export/ca.key 2048 # Create a self signed Certificate, valid for 10yrs with the 'signing' option set $ docker run -it -v $(pwd):/export frapsoft/openssl req -x509 -new -nodes -key /export/ca.key -subj "/CN=${COMMON_NAME}" -days 3650 -reqexts v3_req -extensions v3_ca -out /export/ca.crt這些命令的輸出將是兩個文件,ca.key以及ca.crt簽名密鑰對的密鑰和證書。如果你已經(jīng)有了自己的密鑰對,你應(yīng)該將私鑰和證書分別命名為ca.key與ca.crt。
將簽名密鑰對保存為Secret
我們將創(chuàng)建一個將使用此密鑰對生成簽名證書的頒發(fā)者Issuer,為了允許頒發(fā)者Issuer引用我們的密鑰對,我們將其存儲在Kubernetes Secret資源中。
頒發(fā)者Issuer是命名空間資源,因此他們只能在自己的命名空間中引用Secrets。因此,我們將密鑰對放入與Issuer相同的名稱空間中。當(dāng)然也可以創(chuàng)建一個面向集群范圍版本的ClusterIssuer。
以下命令將在默認(rèn)命名空間中創(chuàng)建包含簽名密鑰對的Secret:
準(zhǔn)備K8s+Istio環(huán)境
阿里云容器服務(wù)Kubernetes 1.11.5目前已經(jīng)支持 Istio 1.0.5的一鍵部署,可以通過容器服務(wù)管理控制臺非常方便地快速創(chuàng)建 Kubernetes 集群以及部署Istio。具體過程可以參考創(chuàng)建Kubernetes集群、部署Istio。
請注意,當(dāng)前部署Istio之后并不會創(chuàng)建IngressGateway。
部署Istio-init
點擊左側(cè)的應(yīng)用目錄,在右側(cè)選中ack-istio-init,在右側(cè)選擇對應(yīng)的集群,同時可以看到命名空間已設(shè)定為 istio-system ,發(fā)布名稱已設(shè)定為istio-init,然后點擊部署。幾秒鐘之后,Istio CRD在集群中被創(chuàng)建出來。
通過應(yīng)用目錄簡便部署Istio certmanager
點擊左側(cè)的應(yīng)用目錄,在右側(cè)選中ack-istio-certmanager,在打開的頁面中點擊參數(shù), 可以通過修改參數(shù)配置進(jìn)行定制化(當(dāng)前不需要進(jìn)行額外修改,保持默認(rèn)值即可),如下所示:
在右側(cè)選擇對應(yīng)的集群,同時可以看到命名空間已設(shè)定為 istio-system ,發(fā)布名稱已設(shè)定為istio-certmanager,然后點擊部署。幾秒鐘之后,Istio certmanager發(fā)布就可以創(chuàng)建出來,如下圖所示容器組certmanager的啟動日志:
可以看到certmanager已經(jīng)成功啟動。
創(chuàng)建引用Secret的Issuer
現(xiàn)在可以創(chuàng)建一個引用我們剛剛創(chuàng)建的Secret資源的頒發(fā)者Issuer:
kubectl apply -f - <<EOF apiVersion: certmanager.k8s.io/v1alpha1 kind: Issuer metadata:name: ca-issuernamespace: default spec:ca:secretName: ca-key-pair EOF接下來準(zhǔn)備獲得證書!
獲得簽名證書
現(xiàn)在可以創(chuàng)建以下證書資源,該資源指定所需的證書。為了使用Issuer獲取證書,我們必須在與Issuer相同的命名空間中創(chuàng)建Certificate資源,因為Issuer是命名空間資源,如本例所示。如果我們想要跨多個名稱空間重用簽名密鑰對,那么就可以使用一個集群ClusterIssuer。
首先通過以下命令為域名myexample.com創(chuàng)建證書:
kubectl apply -f - <<EOF apiVersion: certmanager.k8s.io/v1alpha1 kind: Certificate metadata:name: myexample-certificatenamespace: default spec:secretName: istio-myexample-customingressgateway-certsissuerRef:name: ca-issuer# 可以通過引用ClusterIssuer類型的頒發(fā)者Issuer;默認(rèn)情況使用只適用于命名空間的Issuerkind: IssuercommonName: myexample.comorganization:- MyExample CAdnsNames:- myexample.com- www.myexample.com EOF記下secretName因為接下來的步驟會需要引用它。
創(chuàng)建證書資源后,cert-manager將嘗試使用頒發(fā)者ca-issuer獲取證書。如果成功,證書將存儲在與證書資源相同的命名空間(default)中的Secret資源istio-myexample-customingressgateway-certs中。
檢查證書與密鑰
由于我們已指定commonName字段,因此myexample.com將是證書的通用名稱,并且通用名稱和dnsNames陣列的所有元素都將是主題備用名稱 (SAN)。如果我們沒有指定公共名稱,那么dnsNames列表的第一個元素 將用作公共名稱,dnsNames列表的所有元素 也將是SAN。
創(chuàng)建上述證書后,我們可以檢查是否已成功獲取,如下所示查看了證書myexample-certificate:
kubectl describe certificate myexample-certificate Name: myexample-certificate Namespace: default Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration:{"apiVersion":"certmanager.k8s.io/v1alpha1","kind":"Certificate","metadata":{"annotations":{},"name":"myexample-certificate","namespace":"... API Version: certmanager.k8s.io/v1alpha1 Kind: Certificate Metadata:Creation Timestamp: 2019-01-14T08:38:20ZGeneration: 1Resource Version: 19727Self Link: /apis/certmanager.k8s.io/v1alpha1/namespaces/default/certificates/myexample-certificateUID: bf47b776-17d7-11e9-bafe-00163e069e12 Spec:Common Name: myexample.comDns Names:myexample.comwww.myexample.comIssuer Ref:Kind: IssuerName: ca-issuerOrganization:MyExample CASecret Name: istio-myexample-customingressgateway-certs Status:Conditions:Last Transition Time: 2019-01-14T08:38:22ZMessage: Certificate issued successfullyReason: CertIssuedStatus: TrueType: Ready Events:Type Reason Age From Message---- ------ ---- ---- -------Normal IssueCert 80s cert-manager Issuing certificate...Normal CertIssued 80s cert-manager Certificate issued successfully最后一行顯示了證書成功被創(chuàng)建。
您還可以檢查Issuer是否成功,應(yīng)該看到base64編碼的簽名TLS密鑰對。
kubectl get secret istio-myexample-customingressgateway-certs -oyaml獲得證書后,cert-manager將繼續(xù)檢查其有效性,并在接近到期時嘗試更新。當(dāng)證書上的“Not After”字段小于當(dāng)前時間之后30天時,cert-manager認(rèn)為證書即將到期。對于基于CA的頒發(fā)者,cert-manager將頒發(fā)證書,其中“Not After”字段設(shè)置為當(dāng)前時間加上365天。
部署自定義網(wǎng)關(guān)
Gateway描述了在網(wǎng)格邊緣操作的負(fù)載均衡器,用于接收傳入或傳出的HTTP / TCP連接。
點擊左側(cè)的應(yīng)用目錄,在右側(cè)選中ack-istio-ingressgateway,在打開的頁面中點擊參數(shù), 將在67行附近的名為istio-ingressgateway-certs的secretName修改為上述創(chuàng)建出的 istio-myexample-customingressgateway-certs 。修改如下如下所示:
在右側(cè)選擇對應(yīng)的集群,同時選擇與保密字典istio-myexample-customingressgateway-certs相同的命名空間即上文中設(shè)定的default ,發(fā)布名稱設(shè)定為myexample-customingressgateway,然后點擊部署。幾秒鐘之后,自定義的Istio 網(wǎng)關(guān)發(fā)布就可以創(chuàng)建出來。其中網(wǎng)關(guān)配置設(shè)置代理以充當(dāng)負(fù)載平衡器,為入口公開端口80和443(https)。如下圖所示:
定義內(nèi)部服務(wù)
本示例中的內(nèi)部服務(wù)是基于nginx實現(xiàn)的,首先為 NGINX 服務(wù)器創(chuàng)建配置文件。以域名myexample.com的內(nèi)部服務(wù)為例,定義請求根路徑直接返回字樣"Welcome to myexample.com! This is one custom Istio Ingress Gateway powered by cert-manager!"及狀態(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 / {return 200 'Welcome to myexample.com! This is one custom Istio Ingress Gateway powered by cert-manager!';add_header Content-Type text/plain;}} }創(chuàng)建 Kubernetes ConfigMap 存儲 NGINX 服務(wù)器的配置:
kubectl create configmap myexample-nginx-configmap --from-file=nginx.conf=./myexample-nginx.conf設(shè)置命名空間default,啟用sidecar自動注入:
kubectl label namespace default istio-injection=enabled注意: 確保該sidecar自動注入的Label需要在IngressGateway創(chuàng)建之后再進(jìn)行標(biāo)注,以確保IngressGateway不會自動注入。或者不啟用自動注入,通過手工注入完成,具體參見手工注入。
部署 NGINX 服務(wù)器,創(chuàng)建域名myexample.com的內(nèi)部服務(wù):
kubectl apply -f - <<EOF apiVersion: v1 kind: Service metadata:name: myexampleapplabels:app: myexampleapp spec:ports:- port: 80protocol: TCPselector:app: myexampleapp --- apiVersion: apps/v1 kind: Deployment metadata:name: myexampleapp spec:selector:matchLabels:app: myexampleappreplicas: 1template:metadata:labels:app: myexampleappspec:containers:- name: nginximage: nginxports:- containerPort: 80volumeMounts:- name: nginx-configmountPath: /etc/nginxreadOnly: truevolumes:- name: nginx-configconfigMap:name: myexample-nginx-configmapEOF創(chuàng)建自定義網(wǎng)關(guān)配置對象
以域名myexample.com為例,創(chuàng)建Istio自定義網(wǎng)關(guān)配置對象,如下所示:
kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata:annotations:name: istio-myexample-customingressgatewaynamespace: default spec:selector:istio: ingressgatewayservers:- hosts:- '*.myexample.com'port:name: httpnumber: 80protocol: HTTPtls:httpsRedirect: true- hosts:- '*.myexample.com'port:name: httpsnumber: 443protocol: HTTPStls:mode: SIMPLEprivateKey: /etc/istio/ingressgateway-certs/tls.keyserverCertificate: /etc/istio/ingressgateway-certs/tls.crt EOF創(chuàng)建VirtualService
同樣地,接下來以域名myexample.com為例,創(chuàng)建鏈接到istio-myexample-customingressgateway的VirtualService:
kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata:name: istio-myexample-customvirtualservice spec:hosts:- "www.myexample.com"gateways:- istio-myexample-customingressgatewayhttp:- route:- destination:host: myexampleappport:number: 80 EOF通過網(wǎng)關(guān)訪問服務(wù)
以域名myexample.com為例,獲取對應(yīng)的自定義網(wǎng)關(guān)服務(wù)的公網(wǎng)IP地址,執(zhí)行以下命令獲取:
kubectl get svc -l istio=ingressgateway NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-ingressgateway LoadBalancer 172.19.12.75 106.14.48.121 80:31144/TCP,443:30441/TCP 11m設(shè)置INGRESS_HOST 以及 SECURE_INGRESS_PORT 這兩個環(huán)境變量,確定它們的正確取值,即替換成你實際環(huán)境的地址值:
INGRESS_HOST=106.14.48.121 SECURE_INGRESS_PORT=443檢查 istio-ingressgateway Pod 是否正確的加載了證書和私鑰:
kubectl exec -it -n default $(kubectl -n default get pods -l istio=ingressgateway -o jsonpath='{.items[0].metadata.name}') -- ls -al /etc/istio/ingressgateway-certstls.crt 和 tls.key 都應(yīng)該保存在這個目錄中。
檢查 Ingress gateway 證書中的 Subject 字段的正確性:
kubectl exec -i -n default $(kubectl get pod -l istio=ingressgateway -n default -o jsonpath='{.items[0].metadata.name}') -- cat /etc/istio/ingressgateway-certs/tls.crt | openssl x509 -text -noout | grep 'Subject:'Subject: O=MyExample CA, CN=myexample.com檢查 Ingress gateway 的代理能夠正確訪問證書:
kubectl exec -ti $(kubectl get po -l istio=ingressgateway -n default -o jsonpath={.items[0]..metadata.name}) -n default -- curl 127.0.0.1:15000/certs {"ca_cert": "","cert_chain": "Certificate Path: /etc/istio/ingressgateway-certs/tls.crt, Serial Number: c181438895a781c98759fb56b9cc1508, Days until Expiration: 364" }至此,使用cert-manager部署自定義入口網(wǎng)關(guān)的所有步驟已完成。通過 HTTPS 協(xié)議訪問 myexample.com 服務(wù),即curl 發(fā)送 https 請求到istio-myexample-customingressgateway:
curl -k -HHost:www.myexample.com --resolve www.myexample.com:443:106.14.48.121 https://www.myexample.com Welcome to myexample.com! This is one custom Istio Ingress Gateway powered by cert-manager!回顧一下,獲得證書后cert-manager將繼續(xù)檢查其有效性,并在接近到期時嘗試更新。當(dāng)證書上的“Not After”字段小于當(dāng)前時間之后30天時,cert-manager認(rèn)為證書即將到期。對于基于CA的頒發(fā)者,cert-manager將頒發(fā)證書,其中“Not After”字段設(shè)置為當(dāng)前時間加上365天。
總結(jié)
以上是生活随笔為你收集整理的Istio流量管理实践之(5): 使用cert-manager部署Istio自定义入口网关及进行证书管理...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android实现3种定位的切换,And
- 下一篇: 第十二届蓝桥杯真题-左孩 子右兄弟(df