Published on

Sử dụng Gateway API trên Kubernetes

Giới thiệu

Gateway API trong Kubernetes là một dự án do Kubernetes SIGs xây dựng nhằm cải thiện và chuẩn hóa việc kết nối dịch vụ trong Kubernetes, nó tập trung vào chức năng định tuyến L4 và L7. Dự án này đại diện cho thế hệ tiếp theo của Kubernetes Ingress, Load Balancing và Service Mesh API.

Kubernetes SIGs (Special Interest Groups) là những nhóm chuyên môn trong dự án Kubernetes. Hãy tưởng tượng chúng như các đội công việc, mỗi đội tập trung vào một khía cạnh cụ thể của Kubernetes, tương tự như các phòng ban chuyên môn trong một tập đoàn lớn.

Điểm khác biệt giữa Ingress và Gateway API có thể xem dưới bảng so sánh dưới đây:

Key differencesIngressGateway API
Protocol supportHTTP/HTTPSL4 & L7
Traffic managementLimited, vendor extensions requiredBuild-in advanced support
PortabilityVendor specific dèinitionsStandardized across implementations
Resource objectsIngress resource onlyGatewayClass, Gateway, HTTPRoute, ...
Resource rulesHost/path-based onlyHeader-based also supported
Extending capabilitiesCustom annotations neededBuilt-in advanced funtionality

Về cấu trúc của Gateway API trên Kubernets như hình dưới đây, chúng ta có thể thấy có sự phân cấp, phân quyền khá rõ ráng, ứng với mỗi nhóm công việc, họ sẽ được quản lý các thành phần tương ứng của Gateway.

GatewayClass

GatewayClass trong Kubernetes là một tài nguyên có phạm vi cluster được định nghĩa bởi nhà cung cấp hạ tầng. Tài nguyên này đại diện cho một lớp Gateways có thể được khởi tạo. Lưu ý rằng GatewayClass thực hiện chức năng tương tự như tài nguyên networking.IngressClass

Gateway

Gateway mô tả cách chuyển lưu lượng truy cập sang các Service trong Kubernetes. Một Gateway có thể được tạo trực tiếp bởi người vận hành hoặc có thể được tạo bởi thông qua một GatewayClass.

Routes

Thành phần này có nhiệm vụ xác định các quy tắc để định tuyến traffic theo các giao thức (protocol) từ Gateway đên các Service tương ứng trong Kubernetes. Một số loại phổ biến bao gồm: HTTPRoute, GRPCRoute, TLSRoute, ... Cụ thể hơn có thể xem thêm trên Gateway API

Tiếp theo đây mình sẽ giới thiệu một ví dụ đơn giản dùng Gateway API để điều hướng traffic vào dứng dụng được triển khai trên Kubernetes.

Sử dụng Gateway API

Cài đặt Gateway API

Hiện tại, Kubernetes mặc định chưa được cài Gateway API, chúng ta phải cài đặt bằng lệnh sau:

kubectl apply -f "https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml"

Kiểm tra xem Gateway CRD mới đã được cài thành công hay chưa thì có thể chạy command kubectl get crd | grep .networking.k8s.io, kết quả trả về:

kubectl get crd | grep .networking.k8s.io
gatewayclasses.gateway.networking.k8s.io              2024-03-02T14:43:22Z
gateways.gateway.networking.k8s.io                    2024-03-02T14:43:22Z
httproutes.gateway.networking.k8s.io                  2024-03-02T14:43:22Z
referencegrants.gateway.networking.k8s.io             2024-03-02T14:43:22Z

Cài đặt GatewayClass istio

Như đã nói ở trên, chúng ta cần có một GatewayClass để tạo Gateway, ở đây mình sử dụng istio. Danh sách các Gateway controller có thể tham khảo Gateway Controller Implementation Status

Cách cài đặt istio mình đã đề cập trong bài viết Triển khai Istio trên Kubernetes bằng Argo CD

Sau khi cài đặt xong chúng ta có thể kiểm tra xem gateway class đã có hay chưa kubectl get gatewayclass

kubectl get gatewayclass
NAME           CONTROLLER                    ACCEPTED   AGE
istio          istio.io/gateway-controller   True       14d
istio-remote   istio.io/unmanaged-gateway    True       14d

Cài đặt app demo httpbin

Chúng ta deploy ứng dụng demo trên một namespace test-istio

kubectl create ns test-istio
kubectl -n test-istio apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/httpbin/httpbin.yaml

Kiểm tra xem mọi thứ đã thành công hay chưa

kubectl -n test-istio get all
NAME                           READY   STATUS    RESTARTS      AGE
pod/httpbin-65975d4c6f-zdn77   1/1     Running   1 (38h ago)   14d

NAME              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/httpbin   ClusterIP   10.101.187.131   <none>        8000/TCP   14d

NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/httpbin   1/1     1            1           14d

NAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/httpbin-65975d4c6f   1         1         1       14d

Tạo một Gateway

Đầu tiên chúng ta tạo một manifest khai báo 1 gateway mới

istio-gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: istio-gateway
  namespace: istio-ingress
spec:
  gatewayClassName: istio
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      hostname: "httpbin.yourdomain.com"
      allowedRoutes:
        namespaces:
          from: All

Sau đó, triển khai nó trên cluster

kubectl create ns istio-ingress
kubectl apply -f istio-gateway.yaml

Kiểm tra xem gateway mới đã được deploy thành công hay chưa, kết quả sẽ như vậy

kubectl -n istio-ingress get gateway
NAME            CLASS   ADDRESS        PROGRAMMED   AGE
istio-gateway   istio   192.168.1.50   True         19h

Một lưu ý quan trọng là cluster của bạn phải có LoadBalancer, với mình cluster sử dụng Mettalb.

Thiết lập HTTPRoute

httproute.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: httpbin
  namespace: test-istio
spec:
  parentRefs:
  - group: gateway.networking.k8s.io	
    kind: Gateway	
    name: istio-gateway
    namespace: istio-ingress
    sectionName: http
  hostnames: ["httpbin.yourdomain.com"]
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /headers
    backendRefs:
    - name: httpbin
      port: 8000
      group: ''	
      kind: Service
      weight: 1

Bây giờ chúng ta sẽ tạo HTTPRoute trỏ đến service httpbin đã được deploy trước đó

kubectl apply -f httproute.yaml

Bây giờ chúng ta sẽ test xem bằng lệnh curl curl http://httpbin.yourdomain.com/headers thì kết quả trả về

curl http://httpbin.yourdomain.com/headers
{
  "headers": {
    "Accept": "*/*",
    "Host": "httpbin.yourdomain.com",
    "User-Agent": "curl/7.81.0",
    "X-B3-Sampled": "0",
    "X-B3-Spanid": "47ff5d85afe9d9a",
    "X-B3-Traceid": "bb2f6d79efee6a27b47ff285ae9d9a",
    "X-Envoy-Attempt-Count": "1",
    "X-Envoy-Decorator-Operation": "httpbin.test-istio.svc.cluster.local:8000/*",
    "X-Envoy-Internal": "true",
    "X-Envoy-Peer-Metadata": "ChQKDkFQUF9DT05UQUlORVJTEgIaAAoaCg....==",
    "X-Envoy-Peer-Metadata-Id": "router~10.244.133.198~istio-gateway-istio-6cb5879dd6-wwtvw.istio-ingress~istio-ingress.svc.cluster.local"
  }
}

Như vậy chúng ta có thể truy cập vào app được deploy trên Kubernetes thông qua Gateway API.

Chúc thành công,

ANH NGUYỄN