Skip to content
Merged
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
91 changes: 9 additions & 82 deletions api/v1alpha1/networking_types.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package v1alpha1

import (
corev1 "k8s.io/api/core/v1"
)

// DeletionPolicy controls what happens to managed networking resources
// and child SeiNodes when their parent is deleted.
// +kubebuilder:validation:Enum=Delete;Retain
Expand All @@ -14,83 +10,14 @@ const (
DeletionPolicyRetain DeletionPolicy = "Retain"
)

// NetworkingConfig controls how the group is exposed to traffic.
// NetworkingConfig enables public networking for the deployment.
//
// Routing uses the Kubernetes Gateway API exclusively; the platform must
// install the Gateway API CRDs (v1+) and a Gateway implementation such
// as Istio before HTTPRoute resources will take effect.
type NetworkingConfig struct {
// Service creates a non-headless Service shared across all replicas.
// Each SeiNode still gets its own headless Service for pod DNS.
// +optional
Service *ExternalServiceConfig `json:"service,omitempty"`

// Gateway provides optional annotations for generated HTTPRoute resources.
// HTTPRoutes are generated automatically when the node mode has public
// ports and the platform Gateway env vars are configured. This field is
// only needed to add custom annotations to the HTTPRoute metadata.
// +optional
Gateway *GatewayRouteConfig `json:"gateway,omitempty"`

// Isolation configures network-level access control for node pods.
// +optional
Isolation *NetworkIsolationConfig `json:"isolation,omitempty"`
}

// ExternalServiceConfig defines the shared non-headless Service.
// Ports are derived automatically from the node mode via
// seiconfig.NodePortsForMode — no manual port selection needed.
type ExternalServiceConfig struct {
// Type is the Kubernetes Service type.
// +optional
// +kubebuilder:default=ClusterIP
// +kubebuilder:validation:Enum=ClusterIP;LoadBalancer;NodePort
Type corev1.ServiceType `json:"type,omitempty"`

// Annotations are merged onto the Service metadata.
// +optional
Annotations map[string]string `json:"annotations,omitempty"`
}

// GatewayRouteConfig creates gateway.networking.k8s.io/v1 HTTPRoute resources
// targeting the platform Gateway (configured via SEI_GATEWAY_NAME and
// SEI_GATEWAY_NAMESPACE environment variables on the controller).
// When present, the controller creates a ClusterIP Service (as the
// HTTPRoute backend) and generates HTTPRoute resources on the platform
// Gateway for each protocol the node mode supports. Hostnames are
// derived automatically from the deployment name, namespace, and the
// platform domain env vars.
//
// Hostnames are derived automatically from the deployment name, protocol,
// and the platform domain (SEI_GATEWAY_DOMAIN). Which protocols get
// HTTPRoutes is determined by the node mode via seiconfig.NodePortsForMode.
type GatewayRouteConfig struct {
// Annotations are merged onto HTTPRoute metadata.
// +optional
Annotations map[string]string `json:"annotations,omitempty"`
}

// NetworkIsolationConfig defines network-level access control.
type NetworkIsolationConfig struct {
// AuthorizationPolicy creates an Istio AuthorizationPolicy
// restricting which identities can reach node pods.
// +optional
AuthorizationPolicy *AuthorizationPolicyConfig `json:"authorizationPolicy,omitempty"`
}

// AuthorizationPolicyConfig defines allowed traffic sources.
type AuthorizationPolicyConfig struct {
// AllowedSources defines who can reach this group's pods.
// The controller generates an ALLOW policy; traffic from
// sources not listed here is denied.
// +kubebuilder:validation:MinItems=1
AllowedSources []TrafficSource `json:"allowedSources"`
}

// TrafficSource identifies a set of callers by Istio identity.
// +kubebuilder:validation:XValidation:rule="has(self.principals) || has(self.namespaces)",message="at least one of principals or namespaces must be set"
type TrafficSource struct {
// Principals are SPIFFE identities (e.g.
// "cluster.local/ns/istio-system/sa/istio-ingressgateway").
// +optional
Principals []string `json:"principals,omitempty"`

// Namespaces allows all pods in these namespaces.
// +optional
Namespaces []string `json:"namespaces,omitempty"`
}
// When absent (nil), the deployment is private — only per-node headless
// Services exist for in-cluster access.
type NetworkingConfig struct{}
8 changes: 4 additions & 4 deletions api/v1alpha1/seinodedeployment_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ type SeiNodeDeploymentSpec struct {
// +optional
Genesis *GenesisCeremonyConfig `json:"genesis,omitempty"`

// Networking controls how the group is exposed to traffic.
// Networking resources are shared across all replicas.
// Networking enables public networking for the deployment.
// When present, the controller creates a ClusterIP Service and
// HTTPRoutes on the platform Gateway. When absent, the deployment
// is private with only per-node headless Services.
// +optional
Networking *NetworkingConfig `json:"networking,omitempty"`

Expand Down Expand Up @@ -303,9 +305,7 @@ type DeploymentStatus struct {
// Status condition types for SeiNodeDeployment.
const (
ConditionNodesReady = "NodesReady"
ConditionExternalServiceReady = "ExternalServiceReady"
ConditionRouteReady = "RouteReady"
ConditionIsolationReady = "IsolationReady"
ConditionServiceMonitorReady = "ServiceMonitorReady"
ConditionGenesisCeremonyComplete = "GenesisCeremonyComplete"
ConditionPlanInProgress = "PlanInProgress"
Expand Down
128 changes: 1 addition & 127 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,12 @@ func main() {
os.Exit(1)
}

controllerSA := os.Getenv("SEI_CONTROLLER_SA_PRINCIPAL")
//nolint:staticcheck // migrating to events.EventRecorder API is a separate effort
recorder := mgr.GetEventRecorderFor("seinodedeployment-controller")
if err := (&nodedeploymentcontroller.SeiNodeDeploymentReconciler{
Client: kc,
Scheme: mgr.GetScheme(),
Recorder: recorder,
ControllerSA: controllerSA,
GatewayName: platformCfg.GatewayName,
GatewayNamespace: platformCfg.GatewayNamespace,
GatewayDomain: platformCfg.GatewayDomain,
Expand Down
Loading
Loading