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

k8s gateway cluster names #10357

Open
wants to merge 39 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
f50602f
ggv2: make cluster names parseable
stevenctl Oct 30, 2024
00cde61
Update projects/gloo/pkg/plugins/kubernetes/uds_convert.go
stevenctl Nov 5, 2024
ba3db15
fix usage in krt eds code
stevenctl Nov 5, 2024
2669e0e
consolidate usage of env var
stevenctl Nov 5, 2024
89015c7
changelog: add based on pr
nfuden Nov 6, 2024
812d1ec
static checks linter
nfuden Nov 6, 2024
a2a093f
Merge branch 'main' into feat/stevenctl/cls-name
nfuden Nov 6, 2024
69d5290
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 6, 2024
9bc63c4
Adding changelog file to new location
Nov 6, 2024
860037a
Deleting changelog file from old location
Nov 6, 2024
f9194ca
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 6, 2024
2bfe6d0
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 7, 2024
c6ae76d
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 7, 2024
724da4a
Merge branch 'main' of github.com:solo-io/gloo into feat/stevenctl/cl…
jenshu Nov 8, 2024
69eaf3e
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 8, 2024
69365a8
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 8, 2024
3a8f494
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 8, 2024
4bfdd7e
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 8, 2024
491edf0
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 8, 2024
bec59d2
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 8, 2024
c762a89
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 8, 2024
c52cb7a
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 9, 2024
9c37284
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 11, 2024
7349b97
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 11, 2024
6f2e0ba
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 11, 2024
08381e5
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 11, 2024
8ea9e6a
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 12, 2024
a383be1
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 12, 2024
90bffe7
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 12, 2024
47e46c4
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 12, 2024
d0a4656
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 12, 2024
a9f32bb
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 12, 2024
b7d259c
Merge refs/heads/main into feat/stevenctl/cls-name
soloio-bulldozer[bot] Nov 13, 2024
bc9bdbc
Adding changelog file to new location
Nov 13, 2024
3222c3f
Deleting changelog file from old location
Nov 13, 2024
9b1ad1a
typos
jenshu Nov 13, 2024
9a10a7d
Merge branch 'feat/stevenctl/cls-name' of github.com:solo-io/gloo int…
jenshu Nov 13, 2024
1597a96
Merge branch 'main' of github.com:solo-io/gloo into feat/stevenctl/cl…
jenshu Nov 15, 2024
48bf067
Merge branch 'main' of github.com:solo-io/gloo into feat/stevenctl/cl…
jenshu Nov 18, 2024
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
7 changes: 7 additions & 0 deletions changelog/v1.18.0-beta35/cluster_names.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
changelog:
- type: NEW_FEATURE
issueLink: https://github.com/solo-io/solo-projects/issues/7105
resolvesIssue: false
description: >-
Kubernetes gateway cluster names for kubernetes services will have a new more parsable format.
This behavior for kubernetes gateway can be reverted for now via GG_K8S_GW_LEGACY_CLUSTER_NAMES.
8 changes: 1 addition & 7 deletions projects/gateway2/krtcollections/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,12 +226,6 @@ func transformK8sEndpoints(ctx context.Context, inputs EndpointsInputs) func(kct
return nil
}

if len(endpointSlices) == 0 {
warnsToLog = append(warnsToLog, fmt.Sprintf("EndpointSlices not found for service %v/%v", svcNs, svcName))
logger.Debug("EndpointSlices not found for service")
return nil
}

// Initialize the returned EndpointsForUpstream
settings := krt.FetchOne(kctx, inputs.EndpointsSettings.AsCollection())
enableAutoMtls := settings.EnableAutoMtls
Expand Down Expand Up @@ -397,7 +391,7 @@ func findPortInEndpointSlice(endpointSlice *discoveryv1.EndpointSlice, singlePor

// TODO: use exported version from translator?
func GetEndpointClusterName(upstream *v1.Upstream) string {
clusterName := translator.UpstreamToClusterName(upstream.GetMetadata().Ref())
clusterName := translator.KubeGatewayUpstreamToClusterName(upstream)
endpointClusterName, err := translator.GetEndpointClusterName(clusterName, upstream)
if err != nil {
panic(err)
Expand Down
9 changes: 7 additions & 2 deletions projects/gateway2/proxy_syncer/kube_gw_translator_syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1"
v1snap "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/gloosnapshot"
"github.com/solo-io/gloo/projects/gloo/pkg/plugins"
"github.com/solo-io/gloo/projects/gloo/pkg/translator"
"github.com/solo-io/gloo/projects/gloo/pkg/xds"
"github.com/solo-io/solo-kit/pkg/api/v1/control-plane/cache"

Expand Down Expand Up @@ -63,7 +64,12 @@ func (s *ProxyTranslator) buildXdsSnapshot(
Messages: map[*core.ResourceRef][]string{},
}

xdsSnapshot, reports, proxyReport := s.translator.NewTranslator(ctx, settings).Translate(params, proxy)
tx := s.translator.NewTranslator(
ctx,
settings,
translator.ForKubeGatewayAPI(),
)
xdsSnapshot, reports, proxyReport := tx.Translate(params, proxy)

// Messages are aggregated during translation, and need to be added to reports
for _, messages := range params.Messages {
Expand Down Expand Up @@ -107,7 +113,6 @@ func (s *ProxyTranslator) syncXds(
// a default initial fetch timeout
snap.MakeConsistent()
s.xdsCache.SetSnapshot(proxyKey, snap)

}

func (s *ProxyTranslator) syncStatus(
Expand Down
1 change: 1 addition & 0 deletions projects/gateway2/validation/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ var _ = Describe("Kube Gateway API Policy Validation Helper", func() {
settings,
pluginRegistry,
translator.EnvoyCacheResourcesListToFnvHash,
translator.ForKubeGatewayAPI(),
)
vc = gloovalidation.ValidatorConfig{
Ctx: context.Background(),
Expand Down
1 change: 1 addition & 0 deletions projects/gloo/constants/gloo_gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ package constants

const (
GlooGatewayEnableK8sGwControllerEnv = "GG_K8S_GW_CONTROLLER"
GlooGatewayKubeStyleClusterNames = "GG_K8S_GW_LEGACY_CLUSTER_NAMES"
)
44 changes: 43 additions & 1 deletion projects/gloo/pkg/plugins/kubernetes/uds_convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"reflect"
"strconv"

"github.com/solo-io/gloo/projects/gloo/pkg/plugins/kubernetes/serviceconverter"
"github.com/solo-io/go-utils/contextutils"
Expand All @@ -20,6 +21,39 @@ import (
corev1 "k8s.io/api/core/v1"
)

// these labels are used to propagate internal data
// on synthetic Gloo resources generated from other Kubernetes
// resources (generally Service).
// The `~` is an invalid character that prevents these labels from ending up
// on actual Kubernetes resources.
const (
// KubeSourceResourceLabel indicates the kind of resource that the synthetic
// resource is based on.
KubeSourceResourceLabel = "~internal.solo.io/kubernetes-source-resource"
Copy link
Author

Choose a reason for hiding this comment

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

getting errors like: "caller":"discovery/discovery.go:151","msg":"failed reconciling upstreams","version":"1.0.0-ci1","discovered_by":"kubernetesplugin","upstreams":14,"error":"reconciling resource kube-system-kube-dns-53: creating kube resource kube-system-kube-dns-53: Upstream.gloo.solo.io \"kube-system-kube-dns-53\" is invalid: [metadata.labels: Invalid value: \"~internal.solo.io/kubernetes-name\": prefix part a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*'), when running this in a cluster

// KubeSourceResourceLabel indicates the original name of the resource that
// the synthetic resource is based on.
KubeNameLabel = "~internal.solo.io/kubernetes-name"
// KubeSourceResourceLabel indicates the original namespace of the resource
// that the synthetic resource is based on.
KubeNamespaceLabel = "~internal.solo.io/kubernetes-namespace"
// KubeSourceResourceLabel indicates the service port when applicable.
KubeServicePortLabel = "~internal.solo.io/kubernetes-service-port"
)

// ClusterNameForKube builds the cluster name based on _internal_ labels.
// All of the kind, name, namespace and port must be provided.
func ClusterNameForKube(us *v1.Upstream) (string, bool) {
labels := us.GetMetadata().GetLabels()
kind, kok := labels[KubeSourceResourceLabel]
name, nok := labels[KubeNameLabel]
ns, nsok := labels[KubeNamespaceLabel]
port, pok := labels[KubeServicePortLabel]
if !(kok && nok && nsok && pok) {
return "", false
}
return fmt.Sprintf("%s_%s_%s_%s", kind, name, ns, port), true
}

type UpstreamConverter interface {
UpstreamsForService(ctx context.Context, svc *corev1.Service) v1.UpstreamList
}
Expand Down Expand Up @@ -48,7 +82,15 @@ func (uc *KubeUpstreamConverter) CreateUpstream(ctx context.Context, svc *corev1
coremeta.ResourceVersion = ""
coremeta.Name = UpstreamName(meta.Namespace, meta.Name, port.Port)
labels := coremeta.GetLabels()
coremeta.Labels = make(map[string]string)
coremeta.Labels = map[string]string{
// preserve parts of the source service in a structured way
// so we don't rely on string parsing to recover these
// this is more extensible than relying on casting Spec to Upstream_Kube
KubeSourceResourceLabel: "kube-svc",
KubeNameLabel: meta.Name,
KubeNamespaceLabel: meta.Namespace,
KubeServicePortLabel: strconv.Itoa(int(port.Port)),
}

us := &v1.Upstream{
Metadata: coremeta,
Expand Down
3 changes: 2 additions & 1 deletion projects/gloo/pkg/syncer/setup/translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ type TranslatorFactory struct {
PluginRegistry plugins.PluginRegistryFactory
}

func (tf TranslatorFactory) NewTranslator(ctx context.Context, settings *v1.Settings) translator.Translator {
func (tf TranslatorFactory) NewTranslator(ctx context.Context, settings *v1.Settings, opts ...translator.Option) translator.Translator {
return translator.NewTranslatorWithHasher(
sslutils.NewSslConfigTranslator(),
settings,
tf.PluginRegistry(ctx),
translator.EnvoyCacheResourcesListToFnvHash,
opts...,
)
}

Expand Down
9 changes: 7 additions & 2 deletions projects/gloo/pkg/translator/clusters.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func (t *translatorInstance) computeClusters(
}

// This function is intented to be used when translating a single upstream outside of the context of a full snapshot.
// This happens in GGv2 krt implementation.
// This happens in the kube gateway krt implementation.
func (t *translatorInstance) TranslateCluster(
params plugins.Params,
upstream *v1.Upstream,
Expand Down Expand Up @@ -138,9 +138,14 @@ func (t *translatorInstance) initializeCluster(
errorList = append(errorList, err)
}

clusterName := UpstreamToClusterName(upstream.GetMetadata().Ref())
if t.opts.kubeGatewayAPI {
clusterName = KubeGatewayUpstreamToClusterName(upstream)
}

circuitBreakers := t.settings.GetGloo().GetCircuitBreakers()
out := &envoy_config_cluster_v3.Cluster{
Name: UpstreamToClusterName(upstream.GetMetadata().Ref()),
Name: clusterName,
Metadata: new(envoy_config_core_v3.Metadata),
CircuitBreakers: getCircuitBreakers(upstream.GetCircuitBreakers(), circuitBreakers),
LbSubsetConfig: createLbConfig(upstream),
Expand Down
26 changes: 21 additions & 5 deletions projects/gloo/pkg/translator/translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,11 @@ type ClusterTranslator interface {
) (*envoy_config_cluster_v3.Cluster, []error)
}

var (
_ Translator = new(translatorInstance)
)
var _ Translator = new(translatorInstance)

// translatorInstance is the implementation for a Translator used during Gloo translation
type translatorInstance struct {
opts translatorOpts
lock sync.Mutex
pluginRegistry plugins.PluginRegistry
settings *v1.Settings
Expand All @@ -68,15 +67,25 @@ type translatorInstance struct {
shouldEnforceNamespaceMatch bool
}

func NewDefaultTranslator(settings *v1.Settings, pluginRegistry plugins.PluginRegistry) *translatorInstance {
return NewTranslatorWithHasher(utils.NewSslConfigTranslator(), settings, pluginRegistry, EnvoyCacheResourcesListToFnvHash)
type Option func(o *translatorOpts)

func ForKubeGatewayAPI() Option {
return func(o *translatorOpts) {
o.kubeGatewayAPI = true
}
}

type translatorOpts struct {
// kubeGatewayAPI should only be set for translating kubeGatewayAPI proxies.
kubeGatewayAPI bool
}

func NewTranslatorWithHasher(
sslConfigTranslator utils.SslConfigTranslator,
settings *v1.Settings,
pluginRegistry plugins.PluginRegistry,
hasher func(resources []envoycache.Resource) (uint64, error),
opts ...Option,
) *translatorInstance {
shouldEnforceStr := os.Getenv(api_conversion.MatchingNamespaceEnv)
shouldEnforceNamespaceMatch := false
Expand All @@ -87,13 +96,20 @@ func NewTranslatorWithHasher(
// TODO: what to do here?
}
}

o := translatorOpts{}
for _, opt := range opts {
opt(&o)
}

return &translatorInstance{
lock: sync.Mutex{},
pluginRegistry: pluginRegistry,
settings: settings,
hasher: hasher,
listenerTranslatorFactory: NewListenerSubsystemTranslatorFactory(pluginRegistry, sslConfigTranslator, settings),
shouldEnforceNamespaceMatch: shouldEnforceNamespaceMatch,
opts: o,
}
}

Expand Down
20 changes: 15 additions & 5 deletions projects/gloo/pkg/translator/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,27 @@ import (
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/any"
"github.com/solo-io/gloo/pkg/utils/envutils"
"github.com/solo-io/gloo/projects/gloo/constants"
v1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1"
"github.com/solo-io/gloo/projects/gloo/pkg/plugins/kubernetes"
"github.com/solo-io/gloo/projects/gloo/pkg/utils"
"github.com/solo-io/solo-kit/pkg/api/v1/resources/core"
)

// returns the name of the cluster created for a given upstream
func UpstreamToClusterName(upstream *core.ResourceRef) string {
// used only for kube gateway api (aka ggv2) proxies.
func KubeGatewayUpstreamToClusterName(upstream *v1.Upstream) string {
legacyClusterNames := envutils.IsEnvTruthy(constants.GlooGatewayKubeStyleClusterNames)
clusterName, ok := kubernetes.ClusterNameForKube(upstream)
if !ok || legacyClusterNames {
return UpstreamToClusterName(upstream.GetMetadata().Ref())
}
return clusterName
}

// returns the name of the cluster created for a given upstream
func UpstreamToClusterName(upstream *core.ResourceRef) string {
// For non-namespaced resources, return only name
if upstream.GetNamespace() == "" {
return upstream.GetName()
Expand All @@ -30,7 +44,6 @@ func UpstreamToClusterName(upstream *core.ResourceRef) string {

// returns the ref of the upstream for a given cluster
func ClusterToUpstreamRef(cluster string) (*core.ResourceRef, error) {

split := strings.Split(cluster, "_")
if len(split) > 2 || len(split) < 1 {
return nil, errors.Errorf("unable to convert cluster %s back to upstream ref", cluster)
Expand All @@ -47,7 +60,6 @@ func ClusterToUpstreamRef(cluster string) (*core.ResourceRef, error) {
}

func NewFilterWithTypedConfig(name string, config proto.Message) (*envoy_config_listener_v3.Filter, error) {

s := &envoy_config_listener_v3.Filter{
Name: name,
}
Expand Down Expand Up @@ -107,14 +119,12 @@ func IsIpv4Address(bindAddress string) (validIpv4, strictIPv4 bool, err error) {
if bindIP == nil {
// If bindAddress is not a valid textual representation of an IP address
return false, false, errors.Errorf("bindAddress %s is not a valid IP address", bindAddress)

} else if bindIP.To4() == nil {
// If bindIP is not an IPv4 address, To4 returns nil.
// so this is not an acceptable ipv4
return false, false, nil
}
return true, isPureIPv4Address(bindAddress), nil

}

// isPureIPv4Address checks the string to see if it is
Expand Down
Loading