本文說明如何在 Google Distributed Cloud 的使用者叢集中,建立 Kubernetes Ingress 物件。Ingress 會與一或多個服務建立關聯,而每個服務都會與一組 Pod 建立關聯。
事前準備
取得管理工作站的 SSH 連線:
可建立部署作業
以下是部署的資訊清單。
apiVersion: apps/v1 kind: Deployment metadata: name: hello-deployment spec: selector: matchLabels: greeting: hello replicas: 3 template: metadata: labels: greeting: hello spec: containers: - name: hello-world image: "gcr.io/google-samples/hello-app:2.0" env: - name: "PORT" value: "50000" - name: hello-kubernetes image: "gcr.io/google-samples/node-hello:1.0" env: - name: "PORT" value: "8080"
針對本練習的目的,請特別注意下列幾點關於 Deployment 資訊清單的事項:
屬於 Deployment 的每個 Pod 都有
greeting: hello
標籤。每個 Pod 都有兩個容器。
env
欄位指定hello-app
容器監聽 TCP 通訊埠 50000,而node-hello
容器監聽 TCP 通訊埠 8080。如要查看PORT
環境變數的效果,請查看hello-app
的 hello-app 原始碼。
將資訊清單複製到名為「hello-deployment.yaml
」的檔案,然後建立 Deployment:
kubectl apply --kubeconfig USER_CLUSTER_KUBECONFIG -f hello-deployment.yaml
其中 USER_CLUSTER_KUBECONFIG 是指使用者叢集的 kubeconfig 檔案路徑。
使用 Service 公開 Deployment
如要為用戶端提供穩定的方式,將要求傳送至 Deployment 的 Pod,請建立 Service。
以下是 Service 的資訊清單,可向叢集內的用戶端公開 Deployment:
apiVersion: v1 kind: Service metadata: name: hello-service spec: type: ClusterIP selector: greeting: hello ports: - name: world-port protocol: TCP port: 60000 targetPort: 50000 - name: kubernetes-port protocol: TCP port: 60001 targetPort: 8080
將資訊清單儲存到名為「hello-service.yaml
」的檔案,然後建立 Service:
kubectl apply --kubeconfig USER_CLUSTER_KUBECONFIG -f hello-service.yaml
查看 Service:
kubectl --kubeconfig USER_CLUSTER_KUBECONFIG get service hello-service --output yaml
輸出內容會顯示已指派給 Service 的 clusterIP
值。
例如:
apiVersion: v1 kind: Service metadata: annotations: ... spec: clusterIP: 10.96.14.249 clusterIPs: - 10.96.14.249 ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - name: world-port port: 60000 protocol: TCP targetPort: 50000 - name: kubernetes-port port: 60001 protocol: TCP targetPort: 8080 selector: greeting: hello sessionAffinity: None type: ClusterIP status: loadBalancer: {}
在上述輸出內容中,ports
欄位是 Kubernetes ServicePort
物件的陣列:一個名為 world-port
,另一個名為 kubernetes-port
。
用戶端呼叫服務的方式如下:
使用
world-port
:在其中一個叢集節點上執行的用戶端,會將要求傳送至port
上的clusterIP
。在本範例中,為 10.96.14.249:60000。 要求會轉送至targetPort
上的成員 Pod。在本範例中,POD_IP_ADDRESS:50000。使用
kubernetes-port
:在其中一個叢集節點上執行的用戶端會將要求傳送至port
上的clusterIP
。在本範例中,靜態位址為 10.96.14.249:60001。要求會轉送至targetPort
上的成員 Pod。在本範例中,POD_IP_ADDRESS:8080。
輸入元件
以下是與 Ingress 相關的叢集元件:
istio-ingress
Deployment。這是連入 Proxy。Ingress Proxy 會根據 Ingress 物件中指定的規則,將流量轉送至內部服務。istio-ingress
服務。這項 Service 會公開istio-ingress
Deployment。istiod
Deployment。這是 Ingress 控制器。輸入控制器會監控 Ingress 物件的建立作業,並據此設定輸入 Proxy。
建立 Ingress
以下是 Ingress 的資訊清單:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress spec: rules: - http: paths: - path: /greet-the-world pathType: Exact backend: service: name: hello-service port: number: 60000 - path: /greet-kubernetes pathType: Exact backend: service: name: hello-service port: number: 60001
將資訊清單複製到名為「my-ingress.yaml
」的檔案,然後建立 Ingress:
kubectl apply --kubeconfig USER_CLUSTER_KUBECONFIG -f my-ingress.yaml
建立使用者叢集時,請在叢集設定檔中指定 loadbalancer.ingressVip
的值。這個 IP 位址是在叢集負載平衡器上設定。建立 Ingress 時,系統會將這個 VIP 做為 Ingress 的外部 IP 位址。
當用戶端將要求傳送至使用者叢集 Ingress VIP 時,要求會轉送至負載平衡器。負載平衡器會使用 istio-ingress
服務將要求轉送至 Ingress Proxy,該 Proxy 會在使用者叢集中執行。系統會設定 Ingress Proxy,根據要求網址中的路徑,將要求轉送至不同的後端。
/greet-the-world
路徑
在 Ingress 資訊清單中,您會看到路徑 /greet-the-world
與 serviceName: hello-service
和 servicePort: 60000
相關聯的規則。請注意,60000 是服務 hello-service
的 world-port
區段中 port
的值。
- name: world-port port: 60000 protocol: TCP targetPort: 50000
Ingress 服務會將要求轉送至 clusterIP
:50000。要求接著會傳送至 hello-service
Service 的其中一個成員 Pod。該 Pod 中監聽通訊埠 50000 的容器會顯示 Hello World!
訊息。
/greet-kubernetes
路徑
在 Ingress 資訊清單中,您會看到路徑 /greet-kubernetes
與 serviceName: hello-service
和 servicePort: 60001
相關聯的規則。請注意,60001 是 hello-service
服務的 kubernetes-port
區段中 port
的值。
- name: kubernetes-port port: 60001 protocol: TCP targetPort: 8080
Ingress 服務會將要求轉送至 clusterIP
: 8080。要求接著會傳送至 hello-service
Service 的其中一個成員 Pod。該 Pod 中監聽通訊埠 8080 的容器會顯示 Hello Kubernetes!
訊息。
測試 Ingress
使用 /greet-the-world
路徑測試 Ingress:
curl USER_CLUSTER_INGRESS_VIP/greet-the-world
將 USER_CLUSTER_INGRESS_VIP 替換為 Ingress 的外部 IP 位址。
輸出結果會顯示一則 Hello, world!
訊息:
Hello, world! Version: 2.0.0 Hostname: ...
使用 /greet-kubernetes
路徑測試 Ingress:
curl USER_CLUSTER_INGRESS_VIP/greet-kubernetes
輸出結果會顯示一則 Hello, Kubernetes!
訊息:
Hello Kubernetes!
為 Ingress 設定 HTTPS
如果要接受來自用戶端的 HTTPS 要求,Ingress Proxy 必須要有憑證,以向用戶端證明其身分。這個 Proxy 也必須要有私密金鑰才能完成 HTTPS 握手。
以下範例使用這些實體:
Ingress Proxy:參與 HTTPS 交握,然後將封包轉送至
hello-service
Service 的成員 Pod。hello-service
服務的網域:Example Org 中的 altostrat.com
步驟如下:
建立根憑證和私密金鑰。本範例在 Root CA Example Org 中使用
root.ca.example.com
的根憑證授權單位。openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=Root CA Example Inc./CN=root.ca.example.com' -keyout root-ca.key -out root-ca.crt
建立憑證簽署要求:
openssl req -out server.csr -newkey rsa:2048 -nodes -keyout server.key -subj "/CN=altostrat.com/O=Example Org"
為 Ingress Proxy 建立服務憑證。
openssl x509 -req -days 365 -CA root-ca.crt -CAkey root-ca.key -set_serial 0 -in server.csr -out server.crt
您現在已建立下列憑證和金鑰:
root-ca.crt
:根 CA 的憑證root-ca.key
:根 CA 的私密金鑰server.crt
:Ingress 代理伺服器的服務憑證server.key
:Ingress 代理伺服器的私密金鑰
建立包含服務憑證和金鑰的 Kubernetes 密鑰。
kubectl create secret tls example-server-creds --key=server.key --cert=server.crt --namespace gke-system
產生的 Secret 名為
example-server-creds
。
建立 Deployment 和 Service
如果您在本指南的 HTTP 部分中建立部署和服務,請保留這些項目。如果沒有,請按照為 HTTP 說明的步驟建立憑證。
建立 Ingress
為 HTTPS 建立 Ingress 與為 HTTP 建立 Ingress 類似,但 HTTPS 的 Ingress 規格包含 tls
區段,用於指定主機和密鑰。tls
部分的 hosts
必須與 rules
部分的 host
完全相符。
如果後端服務位於不同的命名空間,您需要在與 Ingress 相同的命名空間中,建立 ExternalName 類型的服務,將流量路由至後端服務。
如果您先前在 HTTP 部分建立了 Ingress,請先刪除該 Ingress,再繼續操作。
刪除 Ingress:
kubectl --kubeconfig USER_CLUSTER_KUBECONFIG delete ingress my-ingress
如要處理先前建立的 Service 流量,請建立具有 tls
區段的新 Ingress。這樣一來,用戶端與 Ingress Proxy 之間就會啟用 HTTPS。
以下是 Ingress 的資訊清單:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress-2 spec: tls: - hosts: - altostrat.com secretName: example-server-creds rules: - host: altostrat.com http: paths: - path: /greet-the-world pathType: Exact backend: service: name: hello-service port: number: 60000 - path: /greet-kubernetes pathType: Exact backend: service: name: hello-service port: number: 60001
將資訊清單儲存到名為 my-ingress-2.yaml
的檔案,然後建立 Ingress:
kubectl apply --kubeconfig USER_CLUSTER_KUBECONFIG -f my-ingress-2.yaml
請透過測試確認。
測試 /greet-the-world 路徑:
curl -v --resolve altostrat.com:443:USER_CLUSTER_INGRESS_VIP https://altostrat.com/greet-the-world --cacert root-ca.crt
輸出:
Hello, world! Version: 2.0.0 Hostname: hello-deployment-5ff7f68854-wqzp7
測試
/greet-kubernetes
路徑:curl -v --resolve altostrat.com:443:USER_CLUSTER_INGRESS_VIP https://altostrat.com/greet-kubernetes --cacert root-ca.crt
輸出:
Hello Kubernetes!
正在清除所用資源
刪除 Ingress:
kubectl --kubeconfig USER_CLUSTER_KUBECONFIG delete ingress INGRESS_NAME
將 INGRESS_NAME 替換為 Ingress 的名稱,例如 my-ingress
或 my-ingress-2
。
刪除服務:
kubectl --kubeconfig USER_CLUSTER_KUBECONFIG delete service hello-service
刪除部署作業:
kubectl --kubeconfig USER_CLUSTER_KUBECONFIG delete deployment hello-deployment