add NEG naming to namer

This commit is contained in:
Minhan Xia 2017-10-03 13:53:25 -07:00
parent fb4cc1cbeb
commit b1d33e7a1f
2 changed files with 138 additions and 0 deletions

View file

@ -17,6 +17,7 @@ limitations under the License.
package utils package utils
import ( import (
"crypto/md5"
"fmt" "fmt"
"net/http" "net/http"
"regexp" "regexp"
@ -90,6 +91,13 @@ const (
ProtocolHTTP AppProtocol = "HTTP" ProtocolHTTP AppProtocol = "HTTP"
// ProtocolHTTPS protocol for a service // ProtocolHTTPS protocol for a service
ProtocolHTTPS AppProtocol = "HTTPS" ProtocolHTTPS AppProtocol = "HTTPS"
// MaxNsNamePortLength is the max length for namespace, name and port for neg name.
// 63 - 4 (k8s prefix) - 16 (cluster id) - 8 (suffix hash) - 4 (hyphen connector) = 31
MaxNsNamePortLength = 31
// NetworkEndpointGroupAlphaAnnotation is the annotation to enable GCE NEG feature for ingress backend services
NetworkEndpointGroupAlphaAnnotation = "alpha.cloud.google.com/load-balancer-neg"
) )
// ControllerContext holds // ControllerContext holds
@ -307,6 +315,40 @@ func (n *Namer) LBName(key string) string {
return n.Truncate(fmt.Sprintf("%v%v%v", scrubbedName, clusterNameDelimiter, clusterName)) return n.Truncate(fmt.Sprintf("%v%v%v", scrubbedName, clusterNameDelimiter, clusterName))
} }
// NEGName returns the gce neg name based on the service namespace, name and target port.
// NEG naming convention: k8s-{clusterid}-{namespace}-{name}-{target port}-{hash}
// Output name is at most 63 characters. NEGName tries to keep as much information as possible.
// WARNING: Do not modify this funciton
func (n *Namer) NEGName(namespace, name, port string) string {
var trimedNamespace string
var trimedName string
var trimedPort string
totalLength := len(namespace) + len(name) + len(port)
exceeds := totalLength - MaxNsNamePortLength
if exceeds <= 0 {
trimedNamespace = namespace
trimedName = name
trimedPort = port
} else {
portSubtract := exceeds * len(port) / totalLength
trimedPort = port[:len(port)-portSubtract]
nameSubtract := exceeds * len(name) / totalLength
trimedName = name[:len(name)-nameSubtract]
trimedNamespace = namespace[:len(namespace)-(exceeds-portSubtract-nameSubtract)]
}
return fmt.Sprintf("%s-%s-%s-%s-%s", n.NEGPrefix(), trimedNamespace, trimedName, trimedPort, negSuffix(namespace, name, port))
}
func (n *Namer) NEGPrefix() string {
return fmt.Sprintf("k8s-%s", n.GetClusterName())
}
// negSuffix returns hash code with 8 characters
func negSuffix(namespace, name, port string) string {
return fmt.Sprintf("%x", md5.Sum([]byte(namespace+name+port)))[:8]
}
// GCEURLMap is a nested map of hostname->path regex->backend // GCEURLMap is a nested map of hostname->path regex->backend
type GCEURLMap map[string]map[string]*compute.BackendService type GCEURLMap map[string]map[string]*compute.BackendService
@ -399,3 +441,11 @@ func GetNamedPort(port int64) *compute.NamedPort {
// TODO: move port naming to namer // TODO: move port naming to namer
return &compute.NamedPort{Name: fmt.Sprintf("port%v", port), Port: port} return &compute.NamedPort{Name: fmt.Sprintf("port%v", port), Port: port}
} }
func NEGEnabled(annotations map[string]string) bool {
v, ok := annotations[NetworkEndpointGroupAlphaAnnotation]
if ok && v == "true" {
return true
}
return false
}

View file

@ -0,0 +1,88 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package utils
import (
"testing"
)
const (
ClusterId = "0123456789abcdef"
)
func TestNEGName(t *testing.T) {
testCases := []struct {
namespace string
name string
port string
expect string
}{
// simple case
{
"namespace",
"name",
"80",
"k8s-0123456789abcdef-namespace-name-80-1e047e33",
},
// 63 characters
{
"0123456789a",
"0123456789",
"0123456789",
"k8s-0123456789abcdef-0123456789a-0123456789-0123456789-49c9993e",
},
// long namespace
{
"01234567890123456789012345678901234567890123456789",
"0",
"0",
"k8s-0123456789abcdef-01234567890123456789012345678-0-0-44255b67",
},
// long name
{
"0",
"01234567890123456789012345678901234567890123456789",
"0",
"k8s-0123456789abcdef--012345678901234567890123456789-0-8a22658c",
},
// long name and namespace
{
"01234567890123456789012345678901234567890123456789",
"01234567890123456789012345678901234567890123456789",
"0",
"k8s-0123456789abcdef-01234567890123-0123456789012345-0-525cce3d",
},
// long name, namespace and port
{
"01234567890123456789012345678901234567890123456789",
"0123456789012345678901234567890123456789",
"012345678901234567890123456789",
"k8s-0123456789abcdef-012345678901-01234567890-01234567-71877a60",
},
}
namer := NewNamer(ClusterId, "")
for _, tc := range testCases {
res := namer.NEGName(tc.namespace, tc.name, tc.port)
if len(res) > 63 {
t.Errorf("NEG name is longer than 63 charaters: %v", len(res))
}
if res != tc.expect {
t.Errorf("Expect NEG name to be %q, but got %q.", tc.expect, res)
}
}
}