Google Cloud Platform Kubernetes Introduction to ingress-gce controller

如果想要在 Google Cloud Platform 的 GKE 上使用 Ingress 功能,最簡單的方式就是用 GKE 本身預設提供的 ingress-gce controller。不過不知道大家在設定 ingress yaml 的時候,有沒有留意到 ingress-gce 規定 service type 只能是 NodePort,但是 ingress-nginx 卻沒有這種限制呢?

本篇文章會從 Google Cloud Platform 所提供的 load balancer 服務開始說明,並且結合 ingress-gce controller,讓大家瞭解兩者的運作方式和限制原因。

Google Cloud Platform Load Balancer

首先來說明 Google Cloud Platform 的 external load balancer 的運作流程:

source: Setting up a simple external HTTP load balancer

  1. user 向 server 發送 request 後,GCP 會將 package 的 dest. IP address 和 forwarding table 進行比對(match),並將 network packages 轉送到比對成功的 forwarding rule 所指定的 proxy server。
  2. Proxy server 取出 package 中的 URL 資訊,再根據 GCP 上設定的 URL map 來決定該將 package 轉發到哪一個 backend service。(routing)
  3. 最後,依據 backend service 的設定將 package 分配到對應 group 底下的 backend server。

而實際對應到 GCP load balancer 設定,就會是:

hugo

如果是使用 GCP cloud console 的話,也可以切換到 advanced menu,就能看到上述所提到的各細節設定,包含 target proxy 和 forwarding rule 等。

hugo

Ingress-gce with GCP Load Balancer

了解基本 GCP load balancer 運作方式之後,接著我們來看 ingress-gce 如何結合 GCP load balancer 來實現 ingress 功能。

ingress-gce 是實現 Kubernetes ingress 抽象層的 controller,而實際負責管理 traffic 的 ingress server 當然就是 GCP load balancer。另外,ingress-gce controller 目前支援建立 L7 external / internal HTTP(S) Load Balancing,所以假如是只需要 L4(TCP/UDP) 的 load Balancing,就需要指定其他 ingress controller。

hugo

因此,當使用者部署或是更新 ingress resource 時,ingress-gce ingress controller 就會 call GCP compute load balancer API 來調整相關配置。

而在第一部分已經有簡單介紹過 GCP load balancer 所需要的各設定,那麼這些設定該怎麼跟 Kubernetes 的 ingress resource 和機制做整合呢?

1. Forwarding Rules

建立 forwarding rule 需要 (1) external IP address(2) proxy server

如果在 yaml annotation 沒有設定既有的 static external IP, ingress-gce controller 就會自動建立一個 global external IP,並且根據 yaml 內的 TLS 設定來決定要選擇 HTTP 或是 HTTPS proxy server。

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: <static-address>

仔細看 static IP 的設定,它是 global-static-ip-name,Global 這字非常重要,原因是 GCP 的 HTTP(s) load balancer 是比對 global forwarding table,因此就需要使用 global static IP, 假設既有的 static IP 是 regional static IP ,那它是不能被套用在設定上的。

URL map

URL map 相對來說就簡單理解,就是把 yaml 設定檔中的 host 和 path 組成 GCP load balancer 所需要的 URL map,舉例來說:

spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: web-server
          servicePort: http
  - host: beta.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: beta-web-server
          servicePort: http

就會產生三個對應 mapping rules,分別是

  1. default
  2. example.com/*
  3. beta.example.com/*

而這三個 rules 會分別對應到各自不同的 backend service。

Backend Service

最後一步就是要將 kubernetes cluster 中的 nodes 對應到 GCP load balancer 的 backend service。Backend service 需要關聯到至少一個 Backend Group,這個 Backend Group 可以是:

  1. instance group
  2. network endpoints group

而在 GKE Ingress for HTTP(S) load balancing 有提到,如果可以的話,盡可能地使用 Network Endpoint Groups (NEGs) 以提高 package 轉送效率,因此我們就以 network endpoints group 來做說明。

service yaml 加入{"ingress": true}

apiVersion: v1
kind: Service
metadata:
  name: neg-demo-svc
  annotations:
    cloud.google.com/neg: '{"ingress": true}'
spec:
  type: NodePort
  selector:
    run: neg-demo-app
  ports:
  - port: 80
    protocol: TCP
    targetPort: 9376

source code from Using container-native load balancing

這樣 ingress-gce controller 就會根據 service selector 所選到的 pods 來組成一個 network endpoints group。示意圖如下:

hugo

每個 endpoint 是由 node ID 和 pod IP 所組成,這樣在轉送 package 的時候,就可以直接送到 pod 內,而不需要透過 node 內的 iptable 再轉發到 pod 了。

NodePort

回到文章一開始的問題,為什麼 ingress-gce controller 的 service 必須要是 NodePort type?

這原因很簡單,從上面描述可以知道 ingress server 就是 GCP load balancer,而 ingress-gce controller 根據 ingress resource 來更新 GCP load balancer 設定,但是 GCP load balancer 這個 ingress server 並不在我們 cluster 中,如果我們將 service type 設為 clusterIP,那麼外部的 ingress server 就無法解析出正確 IP 位置,也無法透過 : 方式來將 package 送到正確的 pod 中。

Recap

最後,總結幾個重點:

  1. GKE default 的 ingress controller 是 ingress-gce 而 ingress server 是 GCP load balancer。
  2. GCP load balancer 有幾個必備 components,包含:forwarding rules(static IP and proxy server)、URL map、backend service。當建立 ingress 時,controller 會根據 yaml 內容建立起對應的 load balancer component。
  3. 推薦在建立 cluster 時啟用 VPC-native 功能,並且設定 NEGs(network endpoints group),有助於提升 package 轉送效率。

References

  1. Introduction to Kubernetes Ingress (Nginx)
  2. GCP Container-native load balancing