Skip to content

Commit

Permalink
Merge pull request #118 from vultr/CLOUD-2025
Browse files Browse the repository at this point in the history
add backend protocol support (via annotation)
  • Loading branch information
happytreees committed Sep 28, 2022
2 parents f6fae43 + da60144 commit b31719a
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 7 deletions.
1 change: 1 addition & 0 deletions docs/load-balancers.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The annotations are listed below. Please note that all annotations listed below
| Annotation (Suffix) | Values | Default | Description |
|------------------------------------|-----------------------------------|---------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `protocol` | `tcp`, `http` | `tcp` | This is used to specify the protocol to be used for your LoadBalancer protocol. |
| `backend-protocol` | `http`, `https`, or `tcp` | `http`, `https`, or `tcp` depending on `protocol` | This is used to set the backend protocol from load balancer to application(s). Note: Only certain protocols can be set here; anything out of scope will be defaulted to `protocol` |
| `https-ports` | string | | Defines which ports should be used for HTTPS. You can pass in a comma separated list: 443,8443 |
| `ssl` | string | | The string you provide should be the name of a Kubernetes TLS Secret which store your cert + key |
| `ssl-pass-through` | `true`, `false` | `false` | If you want SSL termination to happen on your `pods` or `ingress` then this must be enabled. This is to be used with the `https-ports` annotation |
Expand Down
65 changes: 58 additions & 7 deletions vultr/loadbalancers.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ const (
// which TLS secret you want to be used for your load balancers SSL
annoVultrLBSSL = "service.beta.kubernetes.io/vultr-loadbalancer-ssl"

// annoVultrLBBackendProtocol backend protocol
annoVultrLBBackendProtocol = "service.beta.kubernetes.io/vultr-loadbalancer-backend-protocol"

annoVultrHealthCheckPath = "service.beta.kubernetes.io/vultr-loadbalancer-healthcheck-path"
annoVultrHealthCheckProtocol = "service.beta.kubernetes.io/vultr-loadbalancer-healthcheck-protocol"
annoVultrHealthCheckPort = "service.beta.kubernetes.io/vultr-loadbalancer-healthcheck-port"
Expand Down Expand Up @@ -262,7 +265,6 @@ func (l *loadbalancers) lbByName(ctx context.Context, lbName string) (*govultr.L
}

func (l *loadbalancers) buildLoadBalancerRequest(service *v1.Service, nodes []*v1.Node) (*govultr.LoadBalancerReq, error) {

stickySession, err := buildStickySession(service)
if err != nil {
return nil, err
Expand Down Expand Up @@ -571,17 +573,46 @@ func buildForwardingRules(service *v1.Service) ([]govultr.ForwardingRule, error)

for _, port := range service.Spec.Ports {
// default the port
protocol := defaultProtocol
frontendProtocol := defaultProtocol
backendProtocol := getBackendProtocol(service)

if httpsPorts[port.Port] {
if getSSLPassthrough(service) {
protocol = protocolTCP
frontendProtocol = protocolTCP
} else {
protocol = protocolHTTPs
frontendProtocol = protocolHTTPs
}
}

// Check frontend/backend port combinations (listed below what is acceptable)
// frontend = tcp: backend must be tcp
// frontend = https: backend can be http(s)
// frontend = http: backend can be http(s)
switch frontendProtocol {
case "tcp":
if backendProtocol != "tcp" {
klog.Infof("When frontend proto is tcp, backend default is tcp, %q is out of supported range, setting backend to tcp", backendProtocol)
backendProtocol = "tcp"
}
case "http":
if backendProtocol != "http" && backendProtocol != "https" {
klog.Infof("When frontend proto is http, backend default is http, %q is out of supported range, setting backend to http", backendProtocol)
backendProtocol = "http" // http is default
}
case "https":
if backendProtocol != "http" && backendProtocol != "https" {
klog.Infof("When frontend proto is https, backend default is https, %q is out of supported range, setting backend to https", backendProtocol)
backendProtocol = "https" // https is default
}
}

rule, err := buildForwardingRule(&port, protocol)
// unset backend should be same as frontend
if backendProtocol == "" {
backendProtocol = frontendProtocol
}
klog.Infof("Frontend: %q, Backend: %q", frontendProtocol, backendProtocol)

rule, err := buildForwardingRule(&port, frontendProtocol, backendProtocol)
if err != nil {
return nil, err
}
Expand All @@ -592,15 +623,17 @@ func buildForwardingRules(service *v1.Service) ([]govultr.ForwardingRule, error)
return rules, nil
}

func buildForwardingRule(port *v1.ServicePort, protocol string) (*govultr.ForwardingRule, error) {
func buildForwardingRule(port *v1.ServicePort, protocol, backendProtocol string) (*govultr.ForwardingRule, error) {
var rule govultr.ForwardingRule

if port.Protocol == portProtocolUDP {
return nil, fmt.Errorf("TCP protocol is only supported: recieved %s", port.Protocol)
}

rule.FrontendProtocol = protocol
rule.BackendProtocol = protocol
rule.BackendProtocol = backendProtocol

klog.V(3).Infof("Rule: %+v\n", rule)

rule.FrontendPort = int(port.Port)
rule.BackendPort = int(port.NodePort)
Expand Down Expand Up @@ -796,3 +829,21 @@ func getVPC(service *v1.Service) (string, error) {

return pnID, nil
}

func getBackendProtocol(service *v1.Service) string {
proto, ok := service.Annotations[annoVultrLBBackendProtocol]
if !ok {
return ""
}

switch proto {
case "http":
return protocolHTTP
case "https":
return protocolHTTPs
case "tcp":
return protocolTCP
default:
return ""
}
}

0 comments on commit b31719a

Please sign in to comment.