全部產品
Search
文件中心

Container Service for Kubernetes:使用Gateway API訪問服務

更新時間:Jun 19, 2024

Gateway API是Kubernetes中用於對服務網路流量進行建模的一系列資源。它的目標是建立一套表現力強、易擴充、面向角色的服務網路模型。本文介紹如何使用Gateway API訪問服務。

前提條件

  • 確保叢集為1.24及以上版本。

  • 已安裝Gateway API組件。具體操作,請參見管理組件

    說明

    1.24及以上版本的叢集已預設安裝Gateway API組件。

背景資訊

ACK 1.24及以上版本叢集預設安裝Gateway API組件相關的CRD資源。您可以通過安裝支援Gateway API的網關來使用Gateway API的相關特性。關於Gateway API的更多說明,請參見Gateway API

使用流程

流程

準備工作

  1. 擷取叢集KubeConfig並通過kubectl工具串連叢集

  2. 建立測試應用go-httpbin。

    1. 使用以下內容,建立httpbin.yaml

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: go-httpbin
        namespace: default
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: go-httpbin
        template:
          metadata:
            labels:
              app: go-httpbin
              version: v1
          spec:
            containers:
              - image: specialyang/go-httpbin:v3
                args:
                  - "--port=8090"
                  - "--version=v1"
                imagePullPolicy: Always
                name: go-httpbin
                ports:
                  - containerPort: 8090
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: go-httpbin
        namespace: default
      spec:
        ports:
          - port: 80
            targetPort: 8090
            protocol: TCP
        selector:
          app: go-httpbin
    2. 執行以下命令,建立go-httpbin應用。

      kubectl apply -f httpbin.yaml
  3. 安裝Kong Kubernetes Ingress Controller。

    ACK中未提供支援Gateway API的網關組件,本文以kubernetes-ingress-controller網關為例。

    1. 執行以下命令,安裝Kong Kubernetes Ingress Controller。

      說明

      Kong Kubernetes Ingress Controller會使用LoadBalancer類型的kong-proxy Service向外暴露服務,建立的CLB執行個體會產生額外的費用。關於CLB執行個體的計費說明,請參見CLB計費概述

      kubectl create -f https://raw.githubusercontent.com/Kong/kubernetes-ingress-controller/v2.8.0/deploy/single/all-in-one-dbless.yaml

      建立完成的資源將會放置在kong命名空間下。

    2. 驗證Kong Kubernetes Ingress Controller是否安裝成功。

      1. 執行以下命令,查看Service的LoadBalancer IP。

        kubectl get svc -n kong kong-proxy

        預期輸出:

        NAME         TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)                      AGE
        kong-proxy   LoadBalancer   172.16.19.238   47.14.**.**  80:31611/TCP,443:30936/TCP     10s

        在返回結果中擷取EXTERNAL IP

      2. 執行以下命令,訪問Kong Kubernetes Ingress Controller。

        curl http://<EXTERNAL-IP>

        預期輸出:

        {"message":"no Route matched with those values"}

      訪問Kong Kubernetes Ingress Controller時,返回{"message":"no Route matched with those values"},表明安裝Kong Kubernetes Ingress Controller成功。

  4. 建立GatewayClass和Gateway。

    1. 使用以下內容,建立gateway.yaml

      apiVersion: gateway.networking.k8s.io/v1beta1
      kind: GatewayClass
      metadata:
        name: kong
        annotations:
          konghq.com/gatewayclass-unmanaged: 'true'
      spec:
        controllerName: konghq.com/kic-gateway-controller
      ---
      apiVersion: gateway.networking.k8s.io/v1beta1
      kind: Gateway
      metadata:
        name: kong
      spec:
        gatewayClassName: kong
        listeners:
        - name: proxy
          port: 80
          protocol: HTTP
        - name: proxy-ssl
          port: 443
          protocol: HTTPS
    2. 執行以下命令,建立GatewayClass和Gateway。

      kubectl apply -f gateway.yaml
    3. 執行以下命令,查看Gateway外部端點。

      kubectl get gateway kong

      預期輸出:

      NAME   CLASS   ADDRESS        PROGRAMMED   AGE
      kong   kong    47.14.**.**              68s

      返回以上結果,表明建立GatewayClass和Gateway成功。

使用HTTPRoute

以下介紹如何使用HTTPRoute,

功能一:建立首碼匹配路由

使用HTTPRoute的首碼匹配路由能力,使僅首碼正確的請求路由到應用。

  1. 使用以下內容,建立demo-route.yaml

    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: HTTPRoute
    metadata:
      name: demo-route
    spec:
      parentRefs: # 引用Gateway資源。
        - group: gateway.networking.k8s.io
          kind: Gateway
          name: kong
      hostnames:
        - example.com # host設定為example.com
      rules:
        - matches: # 匹配規則為首碼匹配路徑。
            - path:
                type: PathPrefix
                value: /
          backendRefs: # 後端為類型為Service,名稱go-httpbin,連接埠80。
            - kind: Service
              name: go-httpbin
              port: 80
  2. 執行以下命令,建立HTTPRoute資源。

    kubectl apply -f demo-route.yaml
  3. 執行以下命令,訪問go-httpbin應用。

    curl http://example.com/version --resolve example.com:80:<EXTERNAL-IP>

    預期輸出:

    version:v1

    返回以上結果,表明訪問go-httpbin應用成功,建立首碼匹配路由成功。

功能二:建立權重路由

使用HTTPRoute的權重路由能力,使流量按照權重比例路由到應用。

  1. 建立測試應用new-nginx和old-nginx。

    1. 使用以下內容,建立nginx.yaml

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: old-nginx
      spec:
        replicas: 1
        selector:
          matchLabels:
            run: old-nginx
        template:
          metadata:
            labels:
              run: old-nginx
          spec:
            containers:
            - image: registry.cn-hangzhou.aliyuncs.com/acs-sample/old-nginx
              imagePullPolicy: Always
              name: old-nginx
              ports:
              - containerPort: 80
                protocol: TCP
            restartPolicy: Always
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: old-nginx
      spec:
        ports:
        - port: 80
          protocol: TCP
          targetPort: 80
        selector:
          run: old-nginx
        sessionAffinity: None
        type: NodePort
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: new-nginx
      spec:
        replicas: 1
        selector:
          matchLabels:
            run: new-nginx
        template:
          metadata:
            labels:
              run: new-nginx
          spec:
            containers:
            - image: registry.cn-hangzhou.aliyuncs.com/acs-sample/new-nginx
              imagePullPolicy: Always
              name: new-nginx
              ports:
              - containerPort: 80
                protocol: TCP
            restartPolicy: Always
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: new-nginx
      spec:
        ports:
        - port: 80
          protocol: TCP
          targetPort: 80
        selector:
          run: new-nginx
        sessionAffinity: None
        type: NodePort
    2. 執行以下命令,建立new-nginx和old-nginx。

      kubectl apply -f nginx.yaml
  2. 建立HTTPRoute資源。

    1. 執行以下命令,建立demo-weight.yaml

      apiVersion: gateway.networking.k8s.io/v1beta1
      kind: HTTPRoute
      metadata:
        name: demo-weight
      spec:
        parentRefs: # 引用Gateway資源。
          - group: gateway.networking.k8s.io
            kind: Gateway
            name: kong
        hostnames:
          - weight.example.com # host設定為weight.example.com
        rules:
          - matches: # 匹配規則為首碼匹配路徑。
              - path:
                  type: PathPrefix
                  value: /
            backendRefs:
              # 設定後端以及對應權重,權重不為百分比形式,無需等於100。
              - kind: Service
                name: old-nginx
                port: 80
                weight: 1 # 設定old-nginx的權重為1。
              - kind: Service
                name: new-nginx
                port: 80
                weight: 1 # 設定new-nginx的權重為1。

      weight:權重比例,例如本文設定old-nginx的weight1,new-nginx的weight1,表明流量按照1∶1的比例路由到old-nginx和new-nginx。

    2. 執行以下命令,建立HTTPRoute資源。

      kubectl apply -f demo-weight.yaml
  3. 多次執行以下命令,訪問new-nginx和old-nginx應用。

    curl http://weight.example.com/ --resolve weight.example.com:80:<EXTERNAL-IP>

    預期輸出:

    old
    new
    old
    new
    old
    new

    可以看到流量按照1∶1的比例路由到new-nginx和old-nginx兩個應用中,表明建立權重路由成功。

功能三:修改要求標頭

使用HTTPRoute的filter能力,可以在請求或者回複階段對要求標頭進行額外處理。本文以給發送到後端的請求添加要求標頭為例。關於filter能力的更多介紹,請參見HTTPRoute

  1. 建立HTTPRoute資源。

    1. 執行以下命令,建立demo-filter.yaml

      apiVersion: gateway.networking.k8s.io/v1beta1
      kind: HTTPRoute
      metadata:
        name: demo-filter
      spec:
        parentRefs: # 引用Gateway資源。
          - group: gateway.networking.k8s.io
            kind: Gateway
            name: kong
        hostnames:
          - filter.example.com # host設定為filter.example.com。
        rules:
          - matches: # 匹配規則為首碼匹配路徑。
              - path:
                  type: PathPrefix
                  value: /
            filters:
              - type: RequestHeaderModifier # 添加要求標頭my-header: foo。
                requestHeaderModifier:
                  add:
                    - name: my-header
                      value: foo
            backendRefs: # 後端為類型為Service,名稱go-httpbin,連接埠80。
              - kind: Service
                name: go-httpbin
                port: 80
    2. 執行以下命令,建立HTTPRoute資源。

      kubectl apply -f demo-filter.yaml
  2. 執行以下命令,訪問go-httpbin應用。

    curl http://filter.example.com/ --resolve filter.example.com:80:<EXTERNAL-IP>

    預期輸出:

    headers: {
        // ...
        "My-Header": [
          "foo"
        ],
        // ...
    }

    可以看到訪問go-httpbin應用時,返回結果中包含My-Header:foo要求標頭,表明修改要求標頭成功。

配置TLS認證

  1. 執行以下命令,通過OpenSSL建立自我簽署憑證。

    openssl req -subj '/CN=example.com' -new -newkey rsa:2048 -sha256 \
      -days 365 -nodes -x509 -keyout server.key -out server.crt \
      -addext "subjectAltName = DNS:example.com" \
      -addext "keyUsage = digitalSignature" \
      -addext "extendedKeyUsage = serverAuth" 2> /dev/null;
      openssl x509 -in server.crt -subject -noout

    產生的認證和私密金鑰位於目前的目錄的server.crtserver.key檔案中。

  2. 執行以下命令,使用server.crtserver.key檔案建立TLS Secret。

    kubectl create secret tls example.com --key server.key --cert server.crt

    預期輸出:

    secret/example.com created
  3. 將認證配置到Gateway。

    1. 執行以下命令,建立gateway1.yaml

      apiVersion: gateway.networking.k8s.io/v1beta1
      kind: Gateway
      metadata:
        name: kong
      spec:
        gatewayClassName: kong
        listeners:
        - name: proxy
          port: 80
          protocol: HTTP
        - name: proxy-ssl
          port: 443
          protocol: HTTPS
          tls: # 配置TLS。
            mode: Terminate
            certificateRefs: # 引用所建立的secret。
              - kind: Secret
                name: example.com
    2. 執行以下命令,將認證配置到Gateway。

      kubectl apply -f gateway1.yaml
  4. 執行以下命令,驗證配置TLS認證是否成功。

    openssl s_client -servername example.com -connect <EXTERNAL-IP>:443

    返回結果中包含CN = example.com,表明配置TLS認證成功。

相關文檔