本文說明如何在 Google Distributed Cloud 的使用者、混合或獨立叢集中,建立 Kubernetes Ingress 物件。Ingress 會與一或多個服務建立關聯,而每個服務都會與一組 Pod 建立關聯。
可建立部署作業
如要建立 Deployment,請按照下列步驟操作:
建立 Deployment 資訊清單:
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-deployment.yaml
的檔案。建立 Deployment:
kubectl apply --kubeconfig CLUSTER_KUBECONFIG -f hello-deployment.yaml
將
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 CLUSTER_KUBECONFIG -f hello-service.yaml
將
CLUSTER_KUBECONFIG
替換為叢集的 kubeconfig 檔案名稱。查看 Service:
kubectl --kubeconfig 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
欄位是ServicePort
物件的陣列:一個名為world-port
,另一個名為kubernetes-port
。如要進一步瞭解 Service 欄位,請參閱 Kubernetes 說明文件中的 ServiceSpec。用戶端呼叫服務的方式如下:
使用
world-port
:在其中一個叢集節點上執行的用戶端會將要求傳送至port
上的clusterIP
(例如10.96.14.249:60000
)。Ingress 控制器會將要求轉送至targetPort
上的成員 Pod (例如POD_IP_ADDRESS:50000
,其中POD_IP_ADDRESS
是成員 Pod 的 IP 位址)。使用
kubernetes-port
:在其中一個叢集節點上執行的用戶端,會將要求傳送至port
上的clusterIP
(10.96.14.249:60001
)。Ingress 控制器會將要求轉送至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。
所有這些叢內 Istio 元件都會安裝在 gke-system
命名空間中。這個命名空間不會與完整的 Istio/Cloud Service Mesh 安裝作業發生衝突。
建立 Ingress
請按照下列步驟建立 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 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 CLUSTER_INGRESS_VIP/greet-the-world
將
CLUSTER_INGRESS_VIP
替換為 Ingress 的外部 IP 位址。輸出結果會顯示一則
Hello, world!
訊息:Hello, world! Version: 2.0.0 Hostname: ...
使用
/greet-kubernetes
路徑測試 Ingress:curl CLUSTER_INGRESS_VIP/greet-kubernetes
輸出結果會顯示一則
Hello, Kubernetes!
訊息:Hello Kubernetes!
停用隨附 Ingress
Google Distributed Cloud 隨附的 Ingress 功能僅支援 Ingress 功能。您可以選擇與 Istio 或 Cloud Service Mesh 整合。這些產品提供功能齊全的服務網格,可帶來更多優勢,例如相互傳輸層安全 (mTLS)、管理服務間驗證的能力,以及工作負載可觀測性。如果您整合 Istio 或 Cloud Service Mesh,建議停用套裝組合的 Ingress 功能。
您可以使用叢集設定檔中的 spec.clusterNetwork.bundledIngress
欄位,啟用或停用套裝 Ingress。這個欄位僅適用於 1.13.0 以上版本的叢集。bundledIngress
欄位預設為 true
,且不會出現在產生的叢集設定檔中。這個欄位可變動,您可以在建立或更新 1.13.0 以上版本的叢集時變更。
如要停用隨附的 Ingress 功能,請將
bundledIngress
欄位新增至叢集設定檔的clusterNetwork
區段,並將值設為 false,如下例所示:apiVersion: v1 kind: Namespace metadata: name: cluster-hybrid-basic --- apiVersion: baremetal.cluster.gke.io/v1 kind: Cluster metadata: name: hybrid-basic namespace: cluster-hybrid-basic spec: type: hybrid profile: default anthosBareMetalVersion: 1.13.0 gkeConnect: projectID: project-fleet controlPlane: nodePoolSpec: nodes: - address: 10.200.0.2 clusterNetwork: bundledIngress: false pods: cidrBlocks: - 192.168.0.0/16 services: cidrBlocks: - 10.96.0.0/20 ...
為 Ingress 設定 HTTPS
如果要接受來自用戶端的 HTTPS 要求,Ingress Proxy 必須要有憑證,以向用戶端證明其身分。這個 Proxy 也必須要有私密金鑰才能完成 HTTPS 握手。
以下範例使用這些實體:
Ingress Proxy:參與 HTTPS 交握,然後將封包轉送至
hello-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 Proxy 的服務憑證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 類型的服務,將流量路由至後端服務。
建立 HTTPS 或 HTTP 輸入資源的整體步驟相同,但資訊清單檔案中的設定有所不同:
如果您先前在本文件的 HTTP 部分建立 Ingress,請先刪除該 Ingress 再繼續操作。
kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress my-ingress
如要處理先前建立的服務流量,請建立含有
tls
區段的新 Ingress 資訊清單:tls
設定可啟用用戶端與 Ingress Proxy 之間的 HTTPS。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 CLUSTER_KUBECONFIG -f my-ingress-2.yaml
測試並確認 Ingress 已建立且正常運作:
測試
/greet-the-world
路徑:curl -v --resolve altostrat.com:443: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:CLUSTER_INGRESS_VIP \ https://altostrat.com/greet-kubernetes --cacert root-ca.crt
輸出:
Hello Kubernetes!
建立 LoadBalancer 服務
類型為 LoadBalancer
的 Service 是另一種將工作負載公開發布至叢集外部的方式。如需建立 LoadBalancer
類型服務的操作說明和範例,請參閱「在部署應用程式中建立 LoadBalancer
類型的服務」。
正在清除所用資源
刪除 Ingress:
kubectl --kubeconfig CLUSTER_KUBECONFIG delete ingress INGRESS_NAME
將
INGRESS_NAME
替換為 Ingress 的名稱,例如my-ingress
或my-ingress-2
。刪除服務:
kubectl --kubeconfig CLUSTER_KUBECONFIG delete service hello-service
刪除部署作業:
kubectl --kubeconfig CLUSTER_KUBECONFIG delete deployment hello-deployment
刪除 LoadBalancer 服務:
kubectl --kubeconfig CLUSTER_KUBECONFIG delete service service-does-not-use-nodeports