New to Voyager? Please start here.
Configure HTTP/2 and GRPC
You can configure HTTP/2 by configuring proto
or, alpn
under rules.http
section (for frontend) or, backend
section (for specific backend). If you want to use only HTTP/2.0
, then you can specify it using proto: h2
. However, if you like to use both HTTP/2.0
and HTTP/1.1
in a preferred order, then you need to specify the order using ALPN
.
Please note the followings:
- TLS needed to be configured for using
ALPN
. - A single rule/backend can’t use both
ALPN
andproto
. - Multiple rules pointing the same frontend can’t use different
ALPN
or,proto
configurations.
Example: gRPC Without TLS
First create demo namespace for this example.
$ kubectl create namespace demo
namespace/demo created
Deploy gRPC Test Server
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: grpc-server
name: grpc-server
namespace: demo
spec:
selector:
matchLabels:
run: grpc-server
template:
metadata:
labels:
run: grpc-server
spec:
containers:
- image: appscode/hello-grpc:0.1.0
args:
- run
- --v=3
name: grpc-server
imagePullPolicy: Always
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
labels:
run: grpc-server
name: grpc-server
namespace: demo
spec:
ports:
- port: 3000
targetPort: 8080
name: h2c
selector:
run: grpc-server
Create Ingress
apiVersion: voyager.appscode.com/v1
kind: Ingress
metadata:
name: test-ingress
namespace: demo
spec:
rules:
- host: "*"
http:
port: 3001
proto: h2
paths:
- path: /
backend:
service:
name: grpc-server
port:
number: 3000
proto: h2
Generated haproxy.cfg
# HAProxy configuration generated by https://github.com/appscode/voyager
# DO NOT EDIT!
global
daemon
stats socket /var/run/haproxy.sock level admin expose-fd listeners
server-state-file global
server-state-base /var/state/haproxy/
# log using a syslog socket
log /dev/log local0 info
tune.ssl.default-dh-param 2048
ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK
lua-load /etc/auth-request.lua
hard-stop-after 30s
defaults
log global
# https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#4.2-option%20abortonclose
# https://github.com/voyagermesh/voyager/pull/403
option dontlognull
option http-server-close
option http-use-htx
option logasap
# Timeout values
timeout client 50s
timeout client-fin 50s
timeout connect 5s
timeout server 50s
timeout tunnel 50s
# Configure error files
# default traffic mode is http
# mode is overwritten in case of tcp services
mode http
frontend http-0_0_0_0-3001
bind *:3001 proto h2
mode http
option httplog
option forwardfor
acl is_proxy_https hdr(X-Forwarded-Proto) https
acl is_proxy_https ssl_fc
http-request set-var(req.scheme) str(https) if is_proxy_https
http-request set-var(req.scheme) str(http) if ! is_proxy_https
acl acl_: path_beg /
use_backend grpc-server.demo:3000 if acl_:
backend grpc-server.demo:3000
server pod-grpc-server-6c7f686bbb-jhngb 172.17.0.6:8080 proto h2
Check Response
$ minikube service --url voyager-test-ingress -n demo
http://192.168.99.100:30652
Run gRPC client using docker.
$ docker run -it appscode/hello-grpc:0.1.0 client --address=192.168.99.100:30652 --name=Voyager
2019/02/05 08:01:18 192.168.99.100:30652
2019/02/05 08:01:18 intro:"hello, Voyager!"
Cleanup
$ kubectl delete ns demo
namespace "demo" deleted
Example: gRPC With TLS
First create demo namespace for this example.
$ kubectl create namespace demo
namespace/demo created
Create Secrets
Generate certs and create secret for backend server. Here we are using onessl. You can use openssl or any other tools to generate the certificates.
$ mkdir server-certs; cd server-certs
$ onessl create ca-cert
$ onessl create server-cert --domains ssl.appscode.test --ips 192.168.99.100,127.0.0.1
$ cat {server.crt,ca.crt} > bundle.crt
$ kubectl create secret tls server-secret -n demo --cert=bundle.crt --key=server.key
Generate certs and create secret for haproxy:
$ mkdir haproxy-certs; cd haproxy-certs
$ onessl create ca-cert
$ onessl create server-cert --domains ssl.appscode.test --ips 192.168.99.100,127.0.0.1
$ cat {server.crt,ca.crt} > bundle.crt
$ kubectl create secret tls haproxy-secret -n demo --cert=bundle.crt --key=server.key
Deploy gRPC Test Server
Deploy the gRPC server and mount the server-secret
.
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: grpc-server
name: grpc-server
namespace: demo
spec:
selector:
matchLabels:
run: grpc-server
template:
metadata:
labels:
run: grpc-server
spec:
volumes:
- name: secret-vol
secret:
secretName: server-secret
containers:
- image: appscode/hello-grpc:0.1.0
args:
- run
- --tls-cert-file=/etc/certs/tls.crt
- --tls-private-key-file=/etc/certs/tls.key
- --v=3
name: grpc-server
imagePullPolicy: Always
ports:
- containerPort: 8443
volumeMounts:
- name: secret-vol
mountPath: "/etc/certs"
readOnly: true
---
apiVersion: v1
kind: Service
metadata:
labels:
run: grpc-server
name: grpc-server
namespace: demo
annotations:
ingress.appscode.com/backend-tls: ssl ca-file /tmp/certs/tls.crt
spec:
ports:
- port: 3000
targetPort: 8443
name: h2
selector:
run: grpc-server
Here, ingress.appscode.com/backend-tls
will be used by voyager to configure backend TLS.
Create Ingress
Create ingress and specify the spec.tls
and spec.configVolumes
.
apiVersion: voyager.appscode.com/v1
kind: Ingress
metadata:
name: test-ingress
namespace: demo
spec:
tls:
- secretName: haproxy-secret
hosts:
- "*"
configVolumes:
- name: server-certs-vol
secret:
secretName: server-secret
mountPath: /tmp/certs
rules:
- host: "*"
http:
port: 3001
alpn:
- h2
- http/1.1
paths:
- path: /
backend:
service:
name: grpc-server
port:
number: 3000
alpn:
- h2
- http/1.1
Generated haproxy.cfg
# HAProxy configuration generated by https://github.com/appscode/voyager
# DO NOT EDIT!
global
daemon
stats socket /var/run/haproxy.sock level admin expose-fd listeners
server-state-file global
server-state-base /var/state/haproxy/
# log using a syslog socket
log /dev/log local0 info
tune.ssl.default-dh-param 2048
ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK
lua-load /etc/auth-request.lua
hard-stop-after 30s
defaults
log global
# https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#4.2-option%20abortonclose
# https://github.com/voyagermesh/voyager/pull/403
option dontlognull
option http-server-close
option http-use-htx
option logasap
# Timeout values
timeout client 50s
timeout client-fin 50s
timeout connect 5s
timeout server 50s
timeout tunnel 50s
# Configure error files
# default traffic mode is http
# mode is overwritten in case of tcp services
mode http
frontend http-0_0_0_0-3001
bind *:3001 ssl no-sslv3 no-tlsv10 no-tls-tickets crt /etc/ssl/private/haproxy/tls/ alpn h2,http/1.1
# Mark all cookies as secure
rsprep ^Set-Cookie:\ (.*) Set-Cookie:\ \1;\ Secure
# Add the HSTS header with a 6 month default max-age
http-response set-header Strict-Transport-Security max-age=15768000
mode http
option httplog
option forwardfor
acl is_proxy_https hdr(X-Forwarded-Proto) https
acl is_proxy_https ssl_fc
http-request set-var(req.scheme) str(https) if is_proxy_https
http-request set-var(req.scheme) str(http) if ! is_proxy_https
acl acl_: path_beg /
use_backend grpc-server.demo:3000 if acl_:
backend grpc-server.demo:3000
server pod-grpc-server-7578bf9696-rbq49 172.17.0.7:8443 ssl ca-file /tmp/certs/server.crt alpn h2,http/1.1
Check Response
$ minikube service --url voyager-test-ingress -n demo
http://192.168.99.100:30446
Run gRPC client using docker and specify the haproxy certs.
$ docker run -v $(pwd)/haproxy-certs:/tmp/certs -it appscode/hello-grpc:0.1.0 client --address=192.168.99.100:30446 --crt=/tmp/certs/bundle.crt --name=Voyager
2019/02/05 12:11:13 192.168.99.100:30446
2019/02/05 12:11:13 intro:"hello, Voyager!"
Cleanup
$ kubectl delete ns demo
namespace "demo" deleted