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

Introduce virtual servers as a concrete type. #101

Closed
wants to merge 2 commits 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
125 changes: 55 additions & 70 deletions api/v1alpha1/gateway_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,61 @@ type GatewaySpec struct {
// Listeners associated with this Gateway. Listeners define what addresses,
// ports, protocols are bound on this Gateway.
Listeners []Listener `json:"listeners"`
// Routes associated with this Gateway. Routes define protocol-specific
// routing to backends (e.g. Services). Typically the resource is
// "httproute" or "tcproute" in group "networking.x.k8s.io", or an
// implementation may support other resources.
Routes []RouteObjectReference `json:"routes"`

// Servers binds virtual servers that are hosted by the gateway
// to listeners.
//
// An implementation must validate that Dedicated listeners have no
// more than 1 server binding.
//
// An implementation must validate that all the servers bound to the
// same combined listener have a compatible discriminator.
// TODO(jpeach): describe consequences of this validating failing.
Servers []ServerBinding `json:"servers"`
}

const (
// HTTPProcotol constant.
HTTPProcotol = "HTTP"
// HTTPSProcotol constant.
HTTPSProcotol = "HTTPS"
)
// ServerBinding specifies which listener a virtual server should
// be attached to. A server can be bound to 1 or more listeners.
type ServerBinding struct {
// ListenerName is the unique name of a listener.
//
// TODO(jpeach): We could let an empty name mean all listeners, but
// there are trade-offs to that. For now this field must not be empty.
//
// +required
ListenerName `json:"listenerName"`
// Server is a reference to the virtual server to be attached.
//
// +required
Server ServerObjectReference `json:"server"`
}

type ListenerProtocolType string

const ListenerProtocolTCP ListenerProtocolType = "TCP"
const ListenerProtocolUDP ListenerProtocolType = "UDP"

type Listenertype string
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo here...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Doh!


// DedicatedListenerType describes a listener with exactly on attached server.
Copy link
Contributor

Choose a reason for hiding this comment

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

s/on/one/

// All traffic received by this listener is terminated by this server.
const DedicatedListenerType ListenerType = "Dedicated"

// CombinedListenerType describes a listener what may have multiple attached
Copy link
Contributor

Choose a reason for hiding this comment

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

s/what/that/

// servers. The protocol recognized by this listener must have a discriminator
// that can be used to select the appropriate server for the incoming request.
// In the case of a streaming data over TLS, the ALPN protocol name can sepect
Copy link
Contributor

Choose a reason for hiding this comment

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

sepect... do you mean inspect?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think I meant to say "the ALPN protocol name can be used to select".

// between different StreamServer specification. In the case of HTTP traffic,
// the HTTP Host (i.e. H2 authority) provides the discriminator.
Copy link
Contributor

Choose a reason for hiding this comment

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

Is "HTTP Host" the Host header? If so, please add the word header.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is SNI server_name considered a discriminator for TLS?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, this is the Host header (aka HTTP/2 authority header).

Right, SNI would be the TLS discriminator.

const CombinedListenerType ListenerType = "Combined"

// Listener defines a
type Listener struct {
// Type specifies the server binding semantics of this listener.
//
// +required
Type ListenerType `json:"type"`

// Name is the listener's name and should be specified as an
// RFC 1035 DNS_LABEL [1]:
//
Expand All @@ -98,18 +137,11 @@ type Listener struct {
// Support:
// +optional
Port *int32 `json:"port,omitempty"`
// Protocol to use.
// Protocol is the network layer protocol this listener accepts.
//
// Support:
// +optional
Protocol *string `json:"protocol,omitempty"`
// TLS is the TLS configuration for the Listener. If unspecified,
// the listener will not support TLS connections.
//
// Support: Core
//
// +optional
TLS *ListenerTLS `json:"tls,omitempty"`
Protocol ListenerProtocolType `json:"protocol,omitempty"`
// Extension for this Listener. The resource may be "configmap" (use
// the empty string for the group) or an implementation-defined resource
// (for example, resource "mylistener" in group "networking.acme.io").
Expand Down Expand Up @@ -153,54 +185,6 @@ const (
TLS1_3 = "TLS1_3"
)

// ListenerTLS describes the TLS configuration for a given port.
//
// References
// - nginx: https://nginx.org/en/docs/http/configuring_https_servers.html
// - envoy: https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/auth/cert.proto
// - haproxy: https://www.haproxy.com/documentation/aloha/9-5/traffic-management/lb-layer7/tls/
// - gcp: https://cloud.google.com/load-balancing/docs/use-ssl-policies#creating_an_ssl_policy_with_a_custom_profile
// - aws: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies
// - azure: https://docs.microsoft.com/en-us/azure/app-service/configure-ssl-bindings#enforce-tls-1112
type ListenerTLS struct {
// Certificates is a list of references to Kubernetes objects that each
// contain an identity certificate that is bound to the listener. The
// host name in a TLS SNI client hello message is used for certificate
// matching and route host name selection. The SNI server_name must
// match a route host name for the Gateway to route the TLS request. If
// an entry in this list specifies the empty string for both the group
// and the resource, the resource defaults to "secret". An
// implementation may support other resources (for example, resource
// "mycertificate" in group "networking.acme.io").
//
// Support: Core (Kubernetes Secrets)
// Support: Implementation-specific (Other resource types)
//
// +required
Certificates []CertificateObjectReference `json:"certificates,omitempty"`
// MinimumVersion of TLS allowed. It is recommended to use one of
// the TLS_* constants above. Note: this is not strongly
// typed to allow implementation-specific versions to be used without
// requiring updates to the API types. String must be of the form
// "<protocol><major>_<minor>".
//
// Support: Core for TLS1_{1,2,3}. Implementation-specific for all other
// values.
//
// +optional
MinimumVersion *string `json:"minimumVersion"`
// Options are a list of key/value pairs to give extended options
// to the provider.
//
// There variation among providers as to how ciphersuites are
// expressed. If there is a common subset for expressing ciphers
// then it will make sense to loft that as a core API
// construct.
//
// Support: Implementation-specific.
Options map[string]string `json:"options"`
}

// LocalObjectReference identifies an API object within a known namespace.
type LocalObjectReference struct {
// Group is the group of the referent. The empty string represents
Expand Down Expand Up @@ -233,10 +217,11 @@ type CertificateObjectReference = LocalObjectReference
// +k8s:deepcopy-gen=false
type ListenerExtensionObjectReference = LocalObjectReference

// RouteObjectReference identifies a route object within a known namespace.
// ServerObjectReference identifies a virtual server object in the same
// namespace as the Gateway.
//
// +k8s:deepcopy-gen=false
type RouteObjectReference = LocalObjectReference
type ServerObjectReference = LocalObjectReference

// GatewayStatus defines the observed state of Gateway.
type GatewayStatus struct {
Expand Down
65 changes: 24 additions & 41 deletions api/v1alpha1/httproute_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,21 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// HTTPRouteSpec defines the desired state of HTTPRoute
type HTTPRouteSpec struct {
// Hosts is a list of Host definitions.
Hosts []HTTPRouteHost `json:"hosts,omitempty"`

// Default is the default host to use. Default.Hostnames must
// be an empty list.
//
// +optional
Default *HTTPRouteHost `json:"default"`
}

// HTTPRouteHost is the configuration for a given host.
type HTTPRouteHost struct {
// Hostname is the fully qualified domain name of a network host,
// as defined by RFC 3986. Note the following deviations from the
// "host" part of the URI as defined in the RFC:
// HTTPServerSpec defines the desired state of HTTPServer.
type HTTPServerSpec struct {
// Hostnames are the set of domain name that refers to this
// HTTPServer. These names must be unique across the Listener.
Hostnames []string `json:"hostnames,omitempty"`

// If this host has multiple names, each name should be present in the
// server certificate as a DNS SAN.
//
// 1. IPs are not allowed.
// 2. The `:` delimiter is not respected because ports are not allowed.
//
// Incoming requests are matched against Hostname before processing HTTPRoute
// rules. For example, if the request header contains host: foo.example.com,
// an HTTPRoute with hostname foo.example.com will match. However, an
// HTTPRoute with hostname example.com or bar.example.com will not match.
// If Hostname is unspecified, the Gateway routes all traffic based on
// the specified rules.
//
// Support: Core
//
// +optional
Hostname string `json:"hostname,omitempty"`
// The ALPNProtocols field in this TLSAcceptor must contain only valid
// HTTP protocol identifiers, i.e. "http/0.9", "http/1.0", "http/1.1",
// "h2". Implementations may accept only a subset of these values if
// the underlying proxy implementation does not implement the
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove "proxy".

// corresponding HTTP protocol version.
TLS *TLSAcceptor

// Rules are a list of HTTP matchers, filters and actions.
Rules []HTTPRouteRule `json:"rules"`
Expand Down Expand Up @@ -243,8 +226,8 @@ type RouteActionExtensionObjectReference = LocalObjectReference
// +k8s:deepcopy-gen=false
type RouteHostExtensionObjectReference = LocalObjectReference

// HTTPRouteStatus defines the observed state of HTTPRoute.
type HTTPRouteStatus struct {
// HTTPServerStatus defines the observed state of HTTPServer.
type HTTPServerStatus struct {
Gateways []GatewayObjectReference `json:"gateways"`
}

Expand All @@ -262,24 +245,24 @@ type GatewayObjectReference struct {

// +kubebuilder:object:root=true

// HTTPRoute is the Schema for the httproutes API
type HTTPRoute struct {
// HTTPServer is a virtual HTTP server, hosted by a Gateway.
type HTTPServer struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec HTTPRouteSpec `json:"spec,omitempty"`
Status HTTPRouteStatus `json:"status,omitempty"`
Spec HttpHostSpec `json:"spec,omitempty"`
Status HttpHostStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

// HTTPRouteList contains a list of HTTPRoute
type HTTPRouteList struct {
// HTTPServerList contains a list of HTTPServer
type HTTPServerList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []HTTPRoute `json:"items"`
Items []HTTPServer `json:"items"`
}

func init() {
SchemeBuilder.Register(&HTTPRoute{}, &HTTPRouteList{})
SchemeBuilder.Register(&HTTPServer{}, &HTTPServerList{})
}
46 changes: 30 additions & 16 deletions api/v1alpha1/tcproute_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,41 +19,55 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// StreamServerSpec defines the desired state of StreamServer
type StreamServerSpec struct {
jpeach marked this conversation as resolved.
Show resolved Hide resolved
// Hostnames are the set of domain name that refers to this
// StreamServer. These names must be unique across the Listener.
Hostnames []string `json:"hostnames,omitempty"`

// TcpRouteSpec defines the desired state of TcpRoute
type TcpRouteSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// If this host has multiple names, each name should be present in the
// server certificate as a DNS SAN.
//
// If this server does not have a TLS configuration, or the TLS
// configuration does not specify any ALPN protocol names, it must
// be attached to a Dedicated listener.
TLS *TLSAcceptor

// Rules are a list of HTTP matchers, filters and actions.
Rules []StreamRouteRule `json:"rules"`
}

// StreamrouteRule describes how a byte stream is forwarded to its destination.
type StreamRouteRule struct {
}

// TcpRouteStatus defines the observed state of TcpRoute
type TcpRouteStatus struct {
// StreamServerStatus defines the observed state of StreamServer
type StreamServerStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
}

// +kubebuilder:object:root=true

// TcpRoute is the Schema for the tcproutes API
type TcpRoute struct {
// StreamServer is a virtual server that accepts a stream of bytes and forwards
// it to a subsequent destination.
type StreamServer struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec TcpRouteSpec `json:"spec,omitempty"`
Status TcpRouteStatus `json:"status,omitempty"`
Spec StreamServerSpec `json:"spec,omitempty"`
Status StreamServerStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

// TcpRouteList contains a list of TcpRoute
type TcpRouteList struct {
// StreamServerList contains a list of StreamServer
type StreamServerList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []TcpRoute `json:"items"`
Items []StreamServer `json:"items"`
}

func init() {
SchemeBuilder.Register(&TcpRoute{}, &TcpRouteList{})
SchemeBuilder.Register(&StreamServer{}, &StreamServerList{})
}
Loading