• gRPC Examples
    • With HTTP (h2c)
      • Traefik Configuration
      • Conclusion
    • With HTTPS
      • gRPC Server Certificate
      • gRPC Client Certificate
      • Traefik Configuration
      • A gRPC example in go (modify for https)

    gRPC Examples

    With HTTP (h2c)

    This section explains how to use Traefik as reverse proxy for gRPC application.

    Traefik Configuration

    Static configuration:

    1. [entryPoints]
    2. [entryPoints.web]
    3. address = ":80"
    4. [api]
    5. [providers.file]
    6. filename = "dynamic_conf.toml"
    1. entryPoints:
    2. web:
    3. address: :80
    4. providers:
    5. file:
    6. filename: dynamic_conf.yml
    7. api: {}
    1. --entryPoints.web.address=":80"
    2. --providers.file.filename=dynamic_conf.toml
    3. --api.insecure=true

    dynamic_conf.{toml,yml}:

    1. ## dynamic configuration ##
    2. [http]
    3. [http.routers]
    4. [http.routers.routerTest]
    5. service = "srv-grpc"
    6. rule = "Host(`frontend.local`)"
    7. [http.services]
    8. [http.services.srv-grpc]
    9. [http.services.srv-grpc.loadBalancer]
    10. [[http.services.srv-grpc.loadBalancer.servers]]
    11. url = "h2c://backend.local:8080"
    1. ## dynamic configuration ##
    2. http:
    3. routers:
    4. routerTest:
    5. service: srv-grpc
    6. rule: Host(`frontend.local`)
    7. services:
    8. srv-grpc:
    9. loadBalancer:
    10. servers:
    11. - url: h2c://backend.local:8080

    Warning

    For providers with labels, you will have to specify the traefik.http.services.<my-service-name>.loadbalancer.server.scheme=h2c

    Conclusion

    We don't need specific configuration to use gRPC in Traefik, we just need to use h2c protocol, or use HTTPS communications to have HTTP2 with the backend.

    With HTTPS

    This section explains how to use Traefik as reverse proxy for gRPC application with self-signed certificates.

    gRPC architecture

    gRPC Server Certificate

    In order to secure the gRPC server, we generate a self-signed certificate for service url:

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

    That will prompt for information, the important answer is:

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

    gRPC Client Certificate

    Generate your self-signed certificate for router url:

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

    with

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

    Traefik Configuration

    At last, we configure our Traefik instance to use both self-signed certificates.

    Static configuration:

    1. [entryPoints]
    2. [entryPoints.websecure]
    3. address = ":4443"
    4. [serversTransport]
    5. # For secure connection on backend.local
    6. rootCAs = [ "./backend.cert" ]
    7. [api]
    8. [provider.file]
    9. filename = "dynamic_conf.toml"
    1. entryPoints:
    2. websecure:
    3. address: :4443
    4. serversTransport:
    5. # For secure connection on backend.local
    6. rootCAs:
    7. - ./backend.cert
    8. providers:
    9. file:
    10. filename: dynamic_conf.yml
    11. api: {}
    1. --entryPoints.websecure.address=":4443"
    2. # For secure connection on backend.local
    3. --serversTransport.rootCAs=./backend.cert
    4. --providers.file.filename=dynamic_conf.toml
    5. --api.insecure=true

    dynamic_conf.{toml,yml}:

    1. ## dynamic configuration ##
    2. [http]
    3. [http.routers]
    4. [http.routers.routerTest]
    5. service = "srv-grpc"
    6. rule = "Host(`frontend.local`)"
    7. [http.services]
    8. [http.services.srv-grpc]
    9. [http.services.srv-grpc.loadBalancer]
    10. [[http.services.srv-grpc.loadBalancer.servers]]
    11. # Access on backend with HTTPS
    12. url = "https://backend.local:8080"
    13. [tls]
    14. # For secure connection on frontend.local
    15. [[tls.certificates]]
    16. certFile = "./frontend.cert"
    17. keyFile = "./frontend.key"
    1. ## dynamic configuration ##
    2. http:
    3. routers:
    4. routerTest:
    5. service: srv-grpc
    6. rule: Host(`frontend.local`)
    7. services:
    8. srv-grpc:
    9. loadBalancer:
    10. servers:
    11. # Access on backend with HTTPS
    12. - url: https://backend.local:8080
    13. tls:
    14. # For secure connection on frontend.local
    15. certificates:
    16. - certfile: ./frontend.cert
    17. keyfile: ./frontend.key

    Warning

    With some services, the server URLs use the IP, so you may need to configure insecureSkipVerify instead of the rootCAs to activate HTTPS without hostname verification.

    A gRPC example in go (modify for https)

    We use the gRPC greeter example in grpc-go

    Warning

    In order to use this gRPC example, we need to modify it to use HTTPS

    So we modify the "gRPC server example" to use our own self-signed certificate:

    1. // ...
    2. // Read cert and key file
    3. backendCert, _ := ioutil.ReadFile("./backend.cert")
    4. backendKey, _ := ioutil.ReadFile("./backend.key")
    5. // Generate Certificate struct
    6. cert, err := tls.X509KeyPair(backendCert, backendKey)
    7. if err != nil {
    8. log.Fatalf("failed to parse certificate: %v", err)
    9. }
    10. // Create credentials
    11. creds := credentials.NewServerTLSFromCert(&cert)
    12. // Use Credentials in gRPC server options
    13. serverOption := grpc.Creds(creds)
    14. var s *grpc.Server = grpc.NewServer(serverOption)
    15. defer s.Stop()
    16. pb.RegisterGreeterServer(s, &server{})
    17. err := s.Serve(lis)
    18. // ...

    Next we will modify gRPC Client to use our Traefik self-signed certificate:

    1. // ...
    2. // Read cert file
    3. frontendCert, _ := ioutil.ReadFile("./frontend.cert")
    4. // Create CertPool
    5. roots := x509.NewCertPool()
    6. roots.AppendCertsFromPEM(frontendCert)
    7. // Create credentials
    8. credsClient := credentials.NewClientTLSFromCert(roots, "")
    9. // Dial with specific Transport (with credentials)
    10. conn, err := grpc.Dial("frontend.local:4443", grpc.WithTransportCredentials(credsClient))
    11. if err != nil {
    12. log.Fatalf("did not connect: %v", err)
    13. }
    14. defer conn.Close()
    15. client := pb.NewGreeterClient(conn)
    16. name := "World"
    17. r, err := client.SayHello(context.Background(), &pb.HelloRequest{Name: name})
    18. // ...