gRPC Examples

With HTTP (h2c)

本节说明如何将Traefik用作gRPC应用程序的反向代理.

Traefik Configuration

静态配置:

[entryPoints]
  [entryPoints.web]
    address = ":80"

[api]

[providers.file]
  directory = "/path/to/dynamic/config"
entryPoints:
  web:
    address: :80

providers:
  file:
    directory: /path/to/dynamic/config

api: {}
--entryPoints.web.address=:80
--providers.file.directory=/path/to/dynamic/config
--api.insecure=true

/path/to/dynamic/config/dynamic_conf.{toml,yml}:

## dynamic configuration ##

[http]

  [http.routers]
    [http.routers.routerTest]
      service = "srv-grpc"
      rule = "Host(`frontend.local`)"

  [http.services]
    [http.services.srv-grpc]
      [http.services.srv-grpc.loadBalancer]
        [[http.services.srv-grpc.loadBalancer.servers]]
          url = "h2c://backend.local:8080"
## dynamic configuration ##

http:
  routers:
    routerTest:
      service: srv-grpc
      rule: Host(`frontend.local`)

  services:
    srv-grpc:
      loadBalancer:
        servers:
        - url: h2c://backend.local:8080

Warning

对于带有标签的提供程序,您将必须指定traefik.http.services.<my-service-name>.loadbalancer.server.scheme=h2c

Conclusion

我们不需要特定的配置即可在Traefik中使用gRPC,我们只需要使用h2c协议,或使用HTTPS通信就可以在后端使用h2c .

With HTTPS

本节说明如何使用Traefik作为带有自签名证书的gRPC应用程序的反向代理.

gRPC architecture

gRPC Server Certificate

为了保护gRPC服务器,我们为服务网址生成了一个自签名证书:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./backend.key -out ./backend.cert

这将提示您提供信息,重要的答案是:

Common Name (e.g. server FQDN or YOUR name) []: backend.local

gRPC Client Certificate

生成路由器网址的自签名证书:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./frontend.key -out ./frontend.cert

with

Common Name (e.g. server FQDN or YOUR name) []: frontend.local

Traefik Configuration

最后,我们将Traefik实例配置为使用两个自签名证书.

静态配置:

[entryPoints]
  [entryPoints.websecure]
    address = ":4443"


[serversTransport]
  # For secure connection on backend.local
  rootCAs = [ "./backend.cert" ]

[api]

[provider.file]
  directory = "/path/to/dynamic/config"
entryPoints:
  websecure:
    address: :4443

serversTransport:
  # For secure connection on backend.local
  rootCAs:
    - ./backend.cert

providers:
  file:
    directory: /path/to/dynamic/config

api: {}
--entryPoints.websecure.address=:4443
# For secure connection on backend.local
--serversTransport.rootCAs=./backend.cert
--providers.file.directory=/path/to/dynamic/config
--api.insecure=true

/path/to/dynamic/config/dynamic_conf.{toml,yml}:

## dynamic configuration ##

[http]

  [http.routers]
    [http.routers.routerTest]
      service = "srv-grpc"
      rule = "Host(`frontend.local`)"

  [http.services]
    [http.services.srv-grpc]
      [http.services.srv-grpc.loadBalancer]
        [[http.services.srv-grpc.loadBalancer.servers]]
          # Access on backend with HTTPS
          url = "https://backend.local:8080"

[tls]

  # For secure connection on frontend.local
  [[tls.certificates]]
    certFile = "./frontend.cert"
    keyFile = "./frontend.key"
## dynamic configuration ##

http:
  routers:
    routerTest:
      service: srv-grpc
      rule: Host(`frontend.local`)
  services:
    srv-grpc:
      loadBalancer:
        servers:
        # Access on backend with HTTPS
        - url: https://backend.local:8080
tls:
  # For secure connection on frontend.local
  certificates:
  - certfile: ./frontend.cert
    keyfile: ./frontend.key

Warning

对于某些服务,服务器URL使用IP,因此您可能需要配置insecureSkipVerify而不是rootCAs来激活HTTPS,而无需验证主机名.

A gRPC example in go (modify for https)

我们在grpc-go中使用gRPC greeter示例

Warning

为了使用此gRPC示例,我们需要对其进行修改以使用HTTPS

因此,我们修改了" gRPC服务器示例"以使用我们自己的自签名证书:

// ...

// Read cert and key file
backendCert, _ := ioutil.ReadFile("./backend.cert")
backendKey, _ := ioutil.ReadFile("./backend.key")

// Generate Certificate struct
cert, err := tls.X509KeyPair(backendCert, backendKey)
if err != nil {
  log.Fatalf("failed to parse certificate: %v", err)
}

// Create credentials
creds := credentials.NewServerTLSFromCert(&cert)

// Use Credentials in gRPC server options
serverOption := grpc.Creds(creds)
var s *grpc.Server = grpc.NewServer(serverOption)
defer s.Stop()

pb.RegisterGreeterServer(s, &server{})
err := s.Serve(lis)

// ...

接下来,我们将修改gRPC Client以使用我们的Traefik自签名证书:

// ...

// Read cert file
frontendCert, _ := ioutil.ReadFile("./frontend.cert")

// Create CertPool
roots := x509.NewCertPool()
roots.AppendCertsFromPEM(frontendCert)

// Create credentials
credsClient := credentials.NewClientTLSFromCert(roots, "")

// Dial with specific Transport (with credentials)
conn, err := grpc.Dial("frontend.local:4443", grpc.WithTransportCredentials(credsClient))
if err != nil {
    log.Fatalf("did not connect: %v", err)
}

defer conn.Close()
client := pb.NewGreeterClient(conn)

name := "World"
r, err := client.SayHello(context.Background(), &pb.HelloRequest{Name: name})

// ...