Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Application Load Balancer Support for End-to-End HTTP/2 #458

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions aws/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ type Adapter struct {
denyInternalRespBody string
denyInternalRespContentType string
denyInternalRespStatusCode int
targetGroupProtocolVersion string
}

type manifest struct {
Expand Down Expand Up @@ -121,8 +122,9 @@ const (
DefaultCustomFilter = ""
// DefaultNLBCrossZone specifies the default configuration for cross
// zone load balancing: https://docs.aws.amazon.com/elasticloadbalancing/latest/network/network-load-balancers.html#load-balancer-attributes
DefaultNLBCrossZone = false
DefaultNLBHTTPEnabled = false
DefaultNLBCrossZone = false
DefaultNLBHTTPEnabled = false
DefaultTargetGroupProtocolVersion = "HTTP1"

nameTag = "Name"
LoadBalancerTypeApplication = "application"
Expand Down Expand Up @@ -225,6 +227,7 @@ func NewAdapter(clusterID, newControllerID, vpcID string, debug, disableInstrume
nlbCrossZone: DefaultNLBCrossZone,
nlbHTTPEnabled: DefaultNLBHTTPEnabled,
customFilter: DefaultCustomFilter,
targetGroupProtocolVersion: DefaultTargetGroupProtocolVersion,
}

adapter.manifest, err = buildManifest(adapter, clusterID, vpcID)
Expand Down Expand Up @@ -466,6 +469,13 @@ func (a *Adapter) WithInternalDomainsDenyResponseContenType(contentType string)
return a
}

// WithTargetGroupProtocolVersion returns the receiver
// adapter after setting targetGroupProtocolVersion config.
func (a *Adapter) WithTargetGroupProtocolVersion(pv string) *Adapter {
a.targetGroupProtocolVersion = pv
return a
}

// ClusterID returns the ClusterID tag that all resources from the same Kubernetes cluster share.
// It's taken from the current ec2 instance.
func (a *Adapter) ClusterID() string {
Expand Down Expand Up @@ -671,6 +681,7 @@ func (a *Adapter) CreateStack(certificateARNs []string, scheme, securityGroup, o
statusCode: a.denyInternalRespStatusCode,
contentType: a.denyInternalRespContentType,
},
targetGroupProtocolVersion: a.targetGroupProtocolVersion,
}

return createStack(a.cloudformation, spec)
Expand Down Expand Up @@ -726,6 +737,7 @@ func (a *Adapter) UpdateStack(stackName string, certificateARNs map[string]time.
statusCode: a.denyInternalRespStatusCode,
contentType: a.denyInternalRespContentType,
},
targetGroupProtocolVersion: a.targetGroupProtocolVersion,
}

return updateStack(a.cloudformation, spec)
Expand Down
1 change: 1 addition & 0 deletions aws/cf.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ type stackSpec struct {
denyInternalDomainsResponse denyResp
internalDomains []string
tags map[string]string
targetGroupProtocolVersion string
}

type healthCheck struct {
Expand Down
6 changes: 5 additions & 1 deletion aws/cf_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"crypto/sha256"
"sort"

cloudformation "github.com/mweagle/go-cloudformation"
cloudformation "github.com/o11n/go-cloudformation"
)

const (
Expand Down Expand Up @@ -447,14 +447,17 @@ func newTargetGroup(spec *stackSpec, targetPortParameter string) *cloudformation
protocol := "HTTP"
healthCheckProtocol := "HTTP"
healthyThresholdCount, unhealthyThresholdCount := spec.albHealthyThresholdCount, spec.albUnhealthyThresholdCount
protocolVersion := cloudformation.String("HTTP1")
if spec.loadbalancerType == LoadBalancerTypeNetwork {
protocol = "TCP"
healthCheckProtocol = "HTTP"
// For NLBs the healthy and unhealthy threshold count value must be equal
healthyThresholdCount, unhealthyThresholdCount = spec.nlbHealthyThresholdCount, spec.nlbHealthyThresholdCount
protocolVersion = nil
} else if spec.targetHTTPS {
protocol = "HTTPS"
healthCheckProtocol = "HTTPS"
protocolVersion = cloudformation.String(spec.targetGroupProtocolVersion)
}

targetGroup := &cloudformation.ElasticLoadBalancingV2TargetGroup{
Expand All @@ -472,6 +475,7 @@ func newTargetGroup(spec *stackSpec, targetPortParameter string) *cloudformation
UnhealthyThresholdCount: cloudformation.Integer(int64(unhealthyThresholdCount)),
Port: cloudformation.Ref(targetPortParameter).Integer(),
Protocol: cloudformation.String(protocol),
ProtocolVersion: protocolVersion,
VPCID: cloudformation.Ref(parameterTargetGroupVPCIDParameter).String(),
}

Expand Down
39 changes: 38 additions & 1 deletion aws/cf_template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"testing"
"time"

cloudformation "github.com/mweagle/go-cloudformation"
cloudformation "github.com/o11n/go-cloudformation"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -301,6 +301,8 @@ func TestGenerateTemplate(t *testing.T) {
attributes := []cloudformation.ElasticLoadBalancingV2LoadBalancerLoadBalancerAttribute(*properties.LoadBalancerAttributes)
require.Equal(t, attributes[1].Key.Literal, "routing.http2.enabled")
require.Equal(t, attributes[1].Value.Literal, "true")
tg := template.Resources["TG"].Properties.(*cloudformation.ElasticLoadBalancingV2TargetGroup)
require.Equal(t, cloudformation.String("HTTP1"), tg.ProtocolVersion)
},
},
{
Expand All @@ -315,6 +317,8 @@ func TestGenerateTemplate(t *testing.T) {
attributes := []cloudformation.ElasticLoadBalancingV2LoadBalancerLoadBalancerAttribute(*properties.LoadBalancerAttributes)
require.Equal(t, attributes[1].Key.Literal, "routing.http2.enabled")
require.Equal(t, attributes[1].Value.Literal, "false")
tg := template.Resources["TG"].Properties.(*cloudformation.ElasticLoadBalancingV2TargetGroup)
require.Equal(t, cloudformation.String("HTTP1"), tg.ProtocolVersion)
},
},
{
Expand Down Expand Up @@ -533,6 +537,7 @@ func TestGenerateTemplate(t *testing.T) {
require.Equal(t, cloudformation.Ref(parameterTargetGroupTargetPortParameter).Integer(), tg.Port)
require.Equal(t, cloudformation.String("TCP"), tg.Protocol)
require.Equal(t, cloudformation.String("HTTP"), tg.HealthCheckProtocol)
require.Empty(t, tg.ProtocolVersion)

validateTargetGroupListener(t, template, "TG", "HTTPSListener", 443, "TLS")
validateTargetGroupOutput(t, template, "TG", "TargetGroupARN")
Expand Down Expand Up @@ -614,6 +619,38 @@ func TestGenerateTemplate(t *testing.T) {
require.NotEqual(t, cloudformation.Integer(3), tg.UnhealthyThresholdCount)
},
},
{
name: "target port http2 when https listener and configured",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@universam1 should be there a test case for GRPC as well?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gRPC is using H2, so I guess this test is good enough, no?

spec: &stackSpec{
loadbalancerType: LoadBalancerTypeApplication,
http2: true,
targetHTTPS: true,
targetGroupProtocolVersion: "HTTP2",
},
validate: func(t *testing.T, template *cloudformation.Template) {
require.NotNil(t, template.Resources["LB"])
properties := template.Resources["LB"].Properties.(*cloudformation.ElasticLoadBalancingV2LoadBalancer)
attributes := []cloudformation.ElasticLoadBalancingV2LoadBalancerLoadBalancerAttribute(*properties.LoadBalancerAttributes)
require.Equal(t, attributes[1].Key.Literal, "routing.http2.enabled")
require.Equal(t, attributes[1].Value.Literal, "true")
tg := template.Resources["TG"].Properties.(*cloudformation.ElasticLoadBalancingV2TargetGroup)
require.Equal(t, cloudformation.String("HTTP2"), tg.ProtocolVersion)
},
},
{
name: "For Nlbs target protocol is undefined",
spec: &stackSpec{
loadbalancerType: LoadBalancerTypeNetwork,
http2: true,
targetGroupProtocolVersion: "HTTP2",
targetHTTPS: true,
},
validate: func(t *testing.T, template *cloudformation.Template) {
require.NotNil(t, template.Resources["LB"])
tg := template.Resources["TG"].Properties.(*cloudformation.ElasticLoadBalancingV2TargetGroup)
require.Nil(t, tg.ProtocolVersion)
},
},
} {
t.Run(test.name, func(t *testing.T) {
generated, err := generateTemplate(test.spec)
Expand Down
2 changes: 1 addition & 1 deletion aws/cloudwatch.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"encoding/json"

"github.com/ghodss/yaml"
cloudformation "github.com/mweagle/go-cloudformation"
cloudformation "github.com/o11n/go-cloudformation"
log "github.com/sirupsen/logrus"
)

Expand Down
2 changes: 1 addition & 1 deletion aws/cloudwatch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package aws
import (
"testing"

cloudformation "github.com/mweagle/go-cloudformation"
cloudformation "github.com/o11n/go-cloudformation"
"github.com/stretchr/testify/assert"
)

Expand Down
10 changes: 9 additions & 1 deletion controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ var (
denyInternalRespContentType string
denyInternalRespStatusCode int
defaultInternalDomains = fmt.Sprintf("*%s", kubernetes.DefaultClusterLocalDomain)
targetGroupProtocolVersion string
)

var metrics = struct {
Expand Down Expand Up @@ -280,6 +281,8 @@ func loadSettings() error {
Default("text/plain").StringVar(&denyInternalRespContentType)
kingpin.Flag("deny-internal-domains-response-status-code", "Defines the response status code for a request identified as to an internal domain when -deny-internal-domains is set.").
Default("401").IntVar(&denyInternalRespStatusCode)
kingpin.Flag("target-group-protocol-version", "Defines the target group protocol version for ALB. Specify GRPC to send requests to targets using gRPC. Specify HTTP2 to send requests to targets using HTTP/2. The default is HTTP1, which sends requests to targets using HTTP/1.1. Note the compatibility chart in https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-target-groups.html#target-group-protocol-version.").
Default("HTTP1").StringVar(&targetGroupProtocolVersion)
kingpin.Parse()

blacklistCertArnMap = make(map[string]bool)
Expand Down Expand Up @@ -321,6 +324,10 @@ func loadSettings() error {
return fmt.Errorf("invalid max number of certificates per ALB: %d. AWS does not allow more than %d", maxCertsPerALB, aws.DefaultMaxCertsPerALB)
}

if !strings.Contains("HTTP1 HTTP2 GRPC", targetGroupProtocolVersion) {
return fmt.Errorf("invalid target group protocol version: %s. must be one of HTTP1, HTTP2, GRPC", targetGroupProtocolVersion)
}

if cwAlarmConfigMap != "" {
loc, err := kubernetes.ParseResourceLocation(cwAlarmConfigMap)
if err != nil {
Expand Down Expand Up @@ -410,7 +417,8 @@ func main() {
WithDenyInternalDomains(denyInternalDomains).
WithInternalDomainsDenyResponse(denyInternalRespBody).
WithInternalDomainsDenyResponseStatusCode(denyInternalRespStatusCode).
WithInternalDomainsDenyResponseContenType(denyInternalRespContentType)
WithInternalDomainsDenyResponseContenType(denyInternalRespContentType).
WithTargetGroupProtocolVersion(targetGroupProtocolVersion)

log.Debug("certs.NewCachingProvider")
certificatesProvider, err := certs.NewCachingProvider(
Expand Down
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,15 @@ require (
github.com/aws/aws-sdk-go v1.42.16
github.com/ghodss/yaml v1.0.0
github.com/go-playground/universal-translator v0.17.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.6
github.com/google/uuid v1.3.0
github.com/leodido/go-urn v1.2.1 // indirect
github.com/linki/instrumented_http v0.3.0
github.com/mweagle/go-cloudformation v0.0.0-20210117063902-00aa242fdc67
github.com/o11n/go-cloudformation v0.0.0-20211209093817-f39f874a873a
github.com/prometheus/client_golang v1.11.0
github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.0
gopkg.in/alecthomas/kingpin.v2 v2.2.6
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
gopkg.in/go-playground/validator.v9 v9.31.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
14 changes: 5 additions & 9 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,8 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
Expand Down Expand Up @@ -83,10 +81,10 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mweagle/go-cloudformation v0.0.0-20210117063902-00aa242fdc67 h1:LX4BE6D2CnqgLjh05gAOlok9nEt78wvSF1Bj4pUOkYY=
github.com/mweagle/go-cloudformation v0.0.0-20210117063902-00aa242fdc67/go.mod h1:ZkuUgvDIuRW0sYTRfCz7VmL3IodhIufcb8HNdI6b6AI=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/o11n/go-cloudformation v0.0.0-20211209093817-f39f874a873a h1:LtRfd3Ra8EHvTjFkRvIMU9yW1r7vxTT+Yq5pHgksNh4=
github.com/o11n/go-cloudformation v0.0.0-20211209093817-f39f874a873a/go.mod h1:XjqKQN76wMyOXjYp4joytbSjabK9+kzehqjzsGq51Oc=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand Down Expand Up @@ -170,9 +168,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1 h1:7QnIQpGRHE5RnLKnESfDoxm2dTapTZua5a0kS0A+VXQ=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand All @@ -187,8 +184,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
2 changes: 1 addition & 1 deletion worker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"testing"
"time"

cloudformation "github.com/mweagle/go-cloudformation"
cloudformation "github.com/o11n/go-cloudformation"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zalando-incubator/kube-ingress-aws-controller/aws"
Expand Down