gateway

package
v0.0.0-...-5e5ceee Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 20, 2024 License: Apache-2.0 Imports: 65 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ParentErrorNotAccepted       = ParentErrorReason(k8s.RouteReasonNoMatchingParent)
	ParentErrorNotAllowed        = ParentErrorReason(k8s.RouteReasonNotAllowedByListeners)
	ParentErrorNoHostname        = ParentErrorReason(k8s.RouteReasonNoMatchingListenerHostname)
	ParentErrorParentRefConflict = ParentErrorReason("ParentRefConflict")
	ParentNoError                = ParentErrorReason("")
)
View Source
const (
	// ControllerVersionAnnotation is an annotation added to the Gateway by the controller specifying
	// the "controller version". The original intent of this was to work around
	// https://github.com/istio/istio/issues/44164, where we needed to transition from a global owner
	// to a per-revision owner. The newer version number allows forcing ownership, even if the other
	// version was otherwise expected to control the Gateway.
	// The version number has no meaning other than "larger numbers win".
	// Numbers are used to future-proof in case we need to do another migration in the future.
	ControllerVersionAnnotation = "gateway.istio.io/controller-version"
	// ControllerVersion is the current version of our controller logic. Known versions are:
	//
	// * 1.17 and older: version 1 OR no version at all, depending on patch release
	// * 1.18+: version 5
	//
	// 2, 3, and 4 were intentionally skipped to allow for the (unlikely) event we need to insert
	// another version between these
	ControllerVersion = 5
)
View Source
const NamespaceNameLabel = "kubernetes.io/metadata.name"

NamespaceNameLabel represents that label added automatically to namespaces is newer Kubernetes clusters

Variables

View Source
var SupportedFeatures = features.AllFeatures

Functions

func GetClassStatus

func GetClassStatus(existing *k8sv1.GatewayClassStatus, gen int64) k8sv1.GatewayClassStatus

func IsManaged

func IsManaged(gw *k8s.GatewaySpec) bool

IsManaged checks if a Gateway is managed (ie we create the Deployment and Service) or unmanaged. This is based on the address field of the spec. If address is set with a Hostname type, it should point to an existing Service that handles the gateway traffic. If it is not set, or refers to only a single IP, we will consider it managed and provision the Service. If there is an IP, we will set the `loadBalancerIP` type. While there is no defined standard for this in the API yet, it is tracked in https://github.com/kubernetes-sigs/gateway-api/issues/892. So far, this mirrors how out of clusters work (address set means to use existing IP, unset means to provision one), and there has been growing consensus on this model for in cluster deployments.

Currently, the supported options are: * 1 Hostname value. This can be short Service name ingress, or FQDN ingress.ns.svc.cluster.local, example.com. If its a non-k8s FQDN it is a ServiceEntry. * 1 IP address. This is managed, with IP explicit * Nothing. This is managed, with IP auto assigned

Not supported: Multiple hostname/IP - It is feasible but preference is to create multiple Gateways. This would also break the 1:1 mapping of GW:Service Mixed hostname and IP - doesn't make sense; user should define the IP in service NamedAddress - Service has no concept of named address. For cloud's that have named addresses they can be configured by annotations,

which users can add to the Gateway.

func ManagedGatewayControllerVersion

func ManagedGatewayControllerVersion(gw gateway.Gateway) (existing string, takeOver bool, manage bool)

ManagedGatewayControllerVersion determines the version of the controller managing this Gateway, and if we should manage this. See ControllerVersionAnnotation for motivations.

func NewUntypedWrapper

func NewUntypedWrapper[T controllers.ComparableObject](c kclient.Client[T]) getter

Types

type AllowedReferences

type AllowedReferences map[Reference]map[Reference]*Grants

func (AllowedReferences) BackendAllowed

func (refs AllowedReferences) BackendAllowed(
	k config.GroupVersionKind,
	backendName k8s.ObjectName,
	backendNamespace k8s.Namespace,
	routeNamespace string,
) bool

func (AllowedReferences) SecretAllowed

func (refs AllowedReferences) SecretAllowed(resourceName string, namespace string) bool

type ClassController

type ClassController struct {
	// contains filtered or unexported fields
}

ClassController is a controller that creates the default Istio GatewayClass(s). This will not continually reconcile the full state of the GatewayClass object, and instead only create the class if it doesn't exist. This allows users to manage it through other means or modify it as they wish. If it is deleted, however, it will be added back. This controller intentionally does not do leader election for simplicity. Because we only create and not update there is no need; the first controller to create the GatewayClass wins.

func NewClassController

func NewClassController(kc kube.Client) *ClassController

func (*ClassController) Reconcile

func (c *ClassController) Reconcile(types.NamespacedName) error

func (*ClassController) Run

func (c *ClassController) Run(stop <-chan struct{})

type ConfigError

type ConfigError struct {
	Reason  ConfigErrorReason
	Message string
}

ConfigError represents an invalid configuration that will be reported back to the user.

type ConfigErrorReason

type ConfigErrorReason = string
const (
	// InvalidRefNotPermitted indicates a route was not permitted
	InvalidRefNotPermitted ConfigErrorReason = ConfigErrorReason(k8s.RouteReasonRefNotPermitted)
	// InvalidDestination indicates an issue with the destination
	InvalidDestination ConfigErrorReason = "InvalidDestination"
	InvalidAddress     ConfigErrorReason = ConfigErrorReason(k8s.GatewayReasonUnsupportedAddress)
	// InvalidDestinationPermit indicates a destination was not permitted
	InvalidDestinationPermit ConfigErrorReason = ConfigErrorReason(k8s.RouteReasonRefNotPermitted)
	// InvalidDestinationKind indicates an issue with the destination kind
	InvalidDestinationKind ConfigErrorReason = ConfigErrorReason(k8s.RouteReasonInvalidKind)
	// InvalidDestinationNotFound indicates a destination does not exist
	InvalidDestinationNotFound ConfigErrorReason = ConfigErrorReason(k8s.RouteReasonBackendNotFound)
	// InvalidParentRef indicates we could not refer to the parent we request
	InvalidParentRef ConfigErrorReason = "InvalidParentReference"
	// InvalidFilter indicates an issue with the filters
	InvalidFilter ConfigErrorReason = "InvalidFilter"
	// InvalidTLS indicates an issue with TLS settings
	InvalidTLS ConfigErrorReason = ConfigErrorReason(k8s.ListenerReasonInvalidCertificateRef)
	// InvalidListenerRefNotPermitted indicates a listener reference was not permitted
	InvalidListenerRefNotPermitted ConfigErrorReason = ConfigErrorReason(k8s.ListenerReasonRefNotPermitted)
	// InvalidConfiguration indicates a generic error for all other invalid configurations
	InvalidConfiguration ConfigErrorReason = "InvalidConfiguration"
	InvalidResources     ConfigErrorReason = ConfigErrorReason(k8s.GatewayReasonNoResources)
	DeprecateFieldUsage                    = "DeprecatedField"
)

type Controller

type Controller struct {
	// contains filtered or unexported fields
}

Controller defines the controller for the gateway-api. The controller acts a bit different from most. Rather than watching the CRs directly, we depend on the existing model.ConfigStoreController which already watches all CRs. When there are updates, a new PushContext will be computed, which will eventually call Controller.Reconcile(). Once this happens, we will inspect the current state of the world, and transform gateway-api types into Istio types (Gateway/VirtualService). Future calls to Get/List will return these Istio types. These are not stored in the cluster at all, and are purely internal; they can be seen on /debug/configz. During Reconcile(), the status on all gateway-api types is also tracked. Once completed, if the status has changed at all, it is queued to asynchronously update the status of the object in Kubernetes.

func NewController

func NewController(
	kc kube.Client,
	c model.ConfigStoreController,
	waitForCRD func(class schema.GroupVersionResource, stop <-chan struct{}) bool,
	credsController credentials.MulticlusterController,
	options controller.Options,
) *Controller

func (*Controller) Create

func (c *Controller) Create(config config.Config) (revision string, err error)

func (*Controller) Delete

func (c *Controller) Delete(typ config.GroupVersionKind, name, namespace string, _ *string) error

func (*Controller) Get

func (c *Controller) Get(typ config.GroupVersionKind, name, namespace string) *config.Config

func (*Controller) HasSynced

func (c *Controller) HasSynced() bool

func (*Controller) List

func (c *Controller) List(typ config.GroupVersionKind, namespace string) []config.Config

func (*Controller) Patch

func (c *Controller) Patch(orig config.Config, patchFn config.PatchFunc) (string, error)

func (*Controller) QueueStatusUpdates

func (c *Controller) QueueStatusUpdates(r GatewayResources)

func (*Controller) Reconcile

func (c *Controller) Reconcile(ps *model.PushContext) error

Reconcile takes in a current snapshot of the gateway-api configs, and regenerates our internal state. Any status updates required will be enqueued as well.

func (*Controller) RegisterEventHandler

func (c *Controller) RegisterEventHandler(typ config.GroupVersionKind, handler model.EventHandler)

func (*Controller) Run

func (c *Controller) Run(stop <-chan struct{})

func (*Controller) Schemas

func (c *Controller) Schemas() collection.Schemas

func (*Controller) SecretAllowed

func (c *Controller) SecretAllowed(resourceName string, namespace string) bool

func (*Controller) SetStatusWrite

func (c *Controller) SetStatusWrite(enabled bool, statusManager *status.Manager)

func (*Controller) Update

func (c *Controller) Update(config config.Config) (newRevision string, err error)

func (*Controller) UpdateStatus

func (c *Controller) UpdateStatus(config config.Config) (newRevision string, err error)

type DeploymentController

type DeploymentController struct {
	// contains filtered or unexported fields
}

DeploymentController implements a controller that materializes a Gateway into an in cluster gateway proxy to serve requests from. This is implemented with a Deployment and Service today. The implementation makes a few non-obvious choices - namely using Server Side Apply from go templates and not using controller-runtime.

controller-runtime has a number of constraints that make it inappropriate for usage here, despite this seeming to be the bread and butter of the library: * It is not readily possible to bring existing Informers, which would require extra watches (#1668) * Goroutine leaks (#1655) * Excessive API-server calls at startup which have no benefit to us (#1603) * Hard to use with SSA (#1669) While these can be worked around, at some point it isn't worth the effort.

Server Side Apply with go templates is an odd choice (no one likes YAML templating...) but is one of the few remaining options after all others are ruled out.

  • Merge patch/Update cannot be used. If we always enforce that our object is *exactly* the same as the in-cluster object we will get in endless loops due to other controllers that like to add annotations, etc. If we chose to allow any unknown fields, then we would never be able to remove fields we added, as we cannot tell if we created it or someone else did. SSA fixes these issues
  • SSA using client-go Apply libraries is almost a good choice, but most third-party clients (Istio, MCS, and gateway-api) do not provide these libraries.
  • SSA using standard API types doesn't work well either: https://github.com/kubernetes-sigs/controller-runtime/issues/1669
  • This leaves YAML templates, converted to unstructured types and Applied with the dynamic client.

func NewDeploymentController

func NewDeploymentController(client kube.Client, clusterID cluster.ID, env *model.Environment,
	webhookConfig func() inject.WebhookConfig, injectionHandler func(fn func()), tw revisions.TagWatcher, revision string,
) *DeploymentController

NewDeploymentController constructs a DeploymentController and registers required informers. The controller will not start until Run() is called.

func (*DeploymentController) HandleTagChange

func (d *DeploymentController) HandleTagChange(newTags sets.String)

func (*DeploymentController) Reconcile

func (d *DeploymentController) Reconcile(req types.NamespacedName) error

Reconcile takes in the name of a Gateway and ensures the cluster is in the desired state

func (*DeploymentController) Run

func (d *DeploymentController) Run(stop <-chan struct{})

type GatewayContext

type GatewayContext struct {
	// contains filtered or unexported fields
}

GatewayContext contains a minimal subset of push context functionality to be exposed to GatewayAPIControllers

func NewGatewayContext

func NewGatewayContext(ps *model.PushContext, cluster cluster.ID) GatewayContext

func (GatewayContext) GetService

func (gc GatewayContext) GetService(hostname, namespace string) *model.Service

func (GatewayContext) ResolveGatewayInstances

func (gc GatewayContext) ResolveGatewayInstances(
	namespace string,
	gwsvcs []string,
	servers []*networking.Server,
) (internal, internalIP, external, pending, warns []string, allUsable bool)

ResolveGatewayInstances attempts to resolve all instances that a gateway will be exposed on. Note: this function considers *all* instances of the service; its possible those instances will not actually be properly functioning gateways, so this is not 100% accurate, but sufficient to expose intent to users. The actual configuration generation is done on a per-workload basis and will get the exact set of matched instances for that workload. Four sets are exposed: * Internal addresses (eg istio-ingressgateway.istio-system.svc.cluster.local:80). * Internal IP addresses (eg 1.2.3.4). This comes from ClusterIP. * External addresses (eg 1.2.3.4), this comes from LoadBalancer services. There may be multiple in some cases (especially multi cluster). * Pending addresses (eg istio-ingressgateway.istio-system.svc), are LoadBalancer-type services with pending external addresses. * Warnings for references that could not be resolved. These are intended to be user facing.

type GatewayResources

type GatewayResources struct {
	GatewayClass   []config.Config
	Gateway        []config.Config
	HTTPRoute      []config.Config
	GRPCRoute      []config.Config
	TCPRoute       []config.Config
	TLSRoute       []config.Config
	ReferenceGrant []config.Config
	ServiceEntry   []config.Config
	// Namespaces stores all namespace in the cluster, keyed by name
	Namespaces map[string]*corev1.Namespace
	// Credentials stores all credentials in the cluster
	Credentials credentials.Controller

	// Domain for the cluster. Typically, cluster.local
	Domain  string
	Context GatewayContext
}

GatewayResources stores all gateway resources used for our conversion.

func (GatewayResources) FuzzValidate

func (kr GatewayResources) FuzzValidate() bool

type Grants

type Grants struct {
	AllowAll     bool
	AllowedNames sets.String
}

type IstioResources

type IstioResources struct {
	Gateway        []config.Config
	VirtualService []config.Config
	// AllowedReferences stores all allowed references, from Reference -> to Reference(s)
	AllowedReferences AllowedReferences
	// ReferencedNamespaceKeys stores the label key of all namespace selections. This allows us to quickly
	// determine if a namespace update could have impacted any Gateways. See namespaceEvent.
	ReferencedNamespaceKeys sets.String

	// ResourceReferences stores all resources referenced by gateway-api resources. This allows us to quickly
	// determine if a resource update could have impacted any Gateways.
	// key: referenced resources(e.g. secrets), value: gateway-api resources(e.g. gateways)
	ResourceReferences map[model.ConfigKey][]model.ConfigKey
}

IstioResources stores all outputs of our conversion

type ParentError

type ParentError struct {
	Reason  ParentErrorReason
	Message string
}

ParentError represents that a parent could not be referenced

type ParentErrorReason

type ParentErrorReason string

type Reference

type Reference struct {
	Kind      config.GroupVersionKind
	Namespace k8s.Namespace
}

Reference stores a reference to a namespaced GVK, as used by ReferencePolicy

type RouteParentResult

type RouteParentResult struct {
	// OriginalReference contains the original reference
	OriginalReference k8s.ParentReference
	// DeniedReason, if present, indicates why the reference was not valid
	DeniedReason *ParentError
	// RouteError, if present, indicates why the reference was not valid
	RouteError *ConfigError
}

RouteParentResult holds the result of a route for a specific parent

type TemplateInput

type TemplateInput struct {
	*gateway.Gateway
	DeploymentName            string
	ServiceAccount            string
	Ports                     []corev1.ServicePort
	ServiceType               corev1.ServiceType
	ClusterID                 string
	KubeVersion               int
	Revision                  string
	ProxyUID                  int64
	ProxyGID                  int64
	CompliancePolicy          string
	InfrastructureLabels      map[string]string
	InfrastructureAnnotations map[string]string
	GatewayNameLabel          string
}

type UntypedWrapper

type UntypedWrapper[T controllers.ComparableObject] struct {
	// contains filtered or unexported fields
}

UntypedWrapper wraps a typed reader to an untyped one, since Go cannot do it automatically.

func (UntypedWrapper[T]) Get

func (u UntypedWrapper[T]) Get(name, namespace string) controllers.Object

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL