实现多集群gRPC服务的路由转发

ACK One ALB多集群网关支持后端服务为gRPC服务,本文介绍如何通过ALB多集群网关实现gRPC服务的路由转发。

前提条件

  • 已开通负载均衡ALB服务

  • 已开启舰队管理功能。具体操作,请参见开启舰队管理功能

  • ACK One舰队已关联2个与Fleet实例相同VPC的ACK集群。具体操作,请参见管理关联集群

  • 已从ACK One控制台获取Fleet实例的KubeConfig,并通过kubectl连接至Fleet实例。

  • 已安装grpccurl工具

  • 已获取到可信的数字证书。您可以从以下几个途径获取数字证书。

    • 从阿里云数字证书中心购买证书。具体操作,请参见购买SSL证书

    • 从其他CA购买证书。

    • 按照本文步骤一生成自签名证书。

      重要

      由于缺乏可靠的CA认证,自签名证书在浏览器和客户端中默认不受信任,通常会导致客户访问时收到安全警告。本文中生成的自签名证书仅作为示例,请勿在生产环境中使用。若您已购买证书,请跳转至步骤二

步骤一:生成自签名证书(可选)

如果您暂未拥有证书,您可参照此步骤生成自签名证书,示例中使用grpc.example.com作为证书的域名。关于对ALB实例配置证书的方式,请参见配置HTTPS证书以实现加密通信,本文以其文中Secret证书方式为例

  1. 创建并拷贝以下内容至/tmp/openssl.cnf文件中。

    [ req ]
    #default_bits           = 2048
    #default_md             = sha256
    #default_keyfile        = privkey.pem
    distinguished_name      = req_distinguished_name
    attributes              = req_attributes
    req_extensions          = v3_req
    
    [ req_distinguished_name ]
    countryName                     = Country Name (2 letter code)
    countryName_min                 = 2
    countryName_max                 = 2
    stateOrProvinceName             = State or Province Name (full name)
    localityName                    = Locality Name (eg, city)
    0.organizationName              = Organization Name (eg, company)
    organizationalUnitName          = Organizational Unit Name (eg, section)
    commonName                      = Common Name (eg, fully qualified host name)
    commonName_max                  = 64
    emailAddress                    = Email Address
    emailAddress_max                = 64
    
    [ req_attributes ]
    challengePassword               = A challenge password
    challengePassword_min           = 4
    challengePassword_max           = 20
    
    [v3_req]
    # Extensions to add to a certificate request
    basicConstraints = CA:FALSE
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment
    subjectAltName = @alt_names
    
    [alt_names]
    DNS.1 = grpc.example.com
  1. 执行以下命令签署证书请求。

    openssl req -new -nodes -keyout grpc.key -out grpc.csr -config /tmp/openssl.cnf -subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=AlibabaCloud/OU=ContainerService/CN=grpc.example.com"
  2. 执行以下命令签署证书。

    openssl x509 -req -days 3650 -in grpc.csr -signkey grpc.key -out grpc.crt -extensions v3_req -extfile /tmp/openssl.cnf

    命令执行成功后,可得到证书grpc.crt与私钥文件grpc.key

  3. 执行以下命令,将证书通过grpc-secret添加到集群中gateway-demo Namespace下。

    kubectl create secret tls grpc-secret --key grpc.key --cert grpc.crt -ngateway-demo   # grpc.key替换为您的证书文件,grpc.crt替换为您的私钥文件。

步骤二:部署gRPC服务到多个集群

ACK One支持多集群GitOps和多集群应用资源分发两种方式,方便您将应用部署到多个集群,详情请参见GitOps快速入门创建多集群应用应用分发快速入门。本文以GitOps的多集群应用分发为例。

  1. 登录ACK One控制台,在左侧导航栏选择舰队 > 多集群应用

  2. 多集群应用页面左上角,单击舰队名称后的Dingtalk_20231226104633.jpg按钮,在下拉列表中选择目标舰队。

  3. 单击创建多集群应用 > GitOps进入创建多集群应用 - GitOps页面。

  4. YAML创建页签,将以下部YAML内容复制到控制台,然后单击确定进行创建和部署应用。

    说明
    • 以下YAML内容是将部署到所有关联集群中gateway-demo namespace下,您也可以通过快捷创建选择集群,变化会同步到YAML创建的内容。

    • 若集群中没有gateway-demo Namespace,则需您手动创建。

    apiVersion: argoproj.io/v1alpha1
    kind: ApplicationSet
    metadata:
      name: appset-grpc-demo
      namespace: argocd
    spec:
      template:
        metadata:
          name: '{{.metadata.annotations.cluster_name}}-grpc'
          namespace: argocd
        spec:
          destination:
            name: '{{.name}}'
            namespace: gateway-demo
          project: default
          source:
            repoURL: https://github.com/ivan-cai/gitops-demo.git
            path: manifests/directory/grpc
            targetRevision: main
          syncPolicy:
            automated: {}
            syncOptions:
              - CreateNamespace=true
      generators:
        - clusters:
            selector:
              matchExpressions:
                - values:
                    - cluster
                  key: argocd.argoproj.io/secret-type
                  operator: In
                - values:
                    - in-cluster
                  key: name
                  operator: NotIn
      goTemplateOptions:
        - missingkey=error
      syncPolicy:
        preserveResourcesOnDeletion: false
      goTemplate: true

步骤三:创建ALB多集群网关并创建Ingress

通过在ACK One 舰队中创建AlbConfig对象来创建一个ACK One ALB多集群网关,并为ALB多集群网关添加关联集群。对于gRPC服务,必须使用HTTPS协议,所以在listeners中需要添加HTTPS端口,本文以443端口为例。

  1. 从ACK One舰队所在VPC,获取两个虚拟交换机ID。

  2. 使用以下内容,创建gateway.yaml文件。

    说明
    • 请将${vsw-id1}${vsw-id2}替换为您上一步获取的交换机ID,${cluster1}${cluster2}替换为您待添加的关联集群ID。

    • 子集群${cluster1}${cluster2}的安全组的入方向需要允许该交换机网段的IP和所有端口通过。

    apiVersion: alibabacloud.com/v1
    kind: AlbConfig
    metadata:
      name: ackone-gateway-demo
      annotations:
        # 添加要处理流量的关联集群到ALB多集群实例。
        alb.ingress.kubernetes.io/remote-clusters: ${cluster1},${cluster2}
    spec:
      config:
        name: one-alb-demo
        addressType: Internet
        addressAllocatedMode: Fixed
        zoneMappings:
        - vSwitchId: ${vsw-id1}
        - vSwitchId: ${vsw-id2}
      listeners:
      - port: 8001
        protocol: HTTP
      - port: 443
        protocol: HTTPS
    ---
    apiVersion: networking.k8s.io/v1
    kind: IngressClass
    metadata:
      name: alb
    spec:
      controller: ingress.k8s.alibabacloud/alb
      parameters:
        apiGroup: alibabacloud.com
        kind: AlbConfig
        name: ackone-gateway-demo
  3. 使用以下内容,创建Ingress。

    说明

    Ingress中必须指定annotation:alb.ingress.kubernetes.io/backend-protocol: grpc,以及对应的alb.ingress.kubernetes.io/listen-ports。并且引用步骤一中的Secret证书。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      annotations:
        alb.ingress.kubernetes.io/listen-ports: |
         [{"HTTPS": 443}]
        alb.ingress.kubernetes.io/backend-protocol: grpc
      name: grpc-ingress
      namespace: gateway-demo
    spec:
      ingressClassName: alb
      rules:
      - host: grpc.example.com
        http:
          paths:
          - backend:
              service:
                name: grpc-service
                port:
                  number: 50051
            path: /
            pathType: Prefix
      tls:
      - hosts:
        - grpc.example.com
        secretName: grpc-secret

步骤四:验证流量转发效果

  1. 执行以下命令,查看Ingress信息。

    kubectl get ingress -ngateway-dmeo

    预期输出:

    NAME           CLASS   HOSTS              ADDRESS         PORTS     AGE
    grpc-ingress   alb     grpc.example.com   alb-*****       80, 443   3m51s
  2. 使用grpcurl连接服务。

    # <ADDRESS>替换为上一步中记录的ALB域名。
    grpcurl -insecure -authority grpc.example.com <ADDRESS>:443 list 

    输出如下,表明流量被Ingress成功转发到后端gRPC服务:

    grpc.reflection.v1alpha.ServerReflection
    helloworld.Greeter