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
47 changes: 45 additions & 2 deletions api/v1alpha/networkinterface_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,24 @@ const (
NetworkInterfaceReclaimPolicyRetain NetworkInterfaceReclaimPolicy = "Retain"
)

// NetworkInterfaceAttachmentMode is how the guest consumes the NIC. It is set
// by the consumer, carried by the operator, and acted on by whoever realizes
// the interface.
//
// +kubebuilder:validation:Enum=Netns;Hypervisor
type NetworkInterfaceAttachmentMode string

const (
// NetworkInterfaceAttachmentModeNetns means the interface is placed in the
// workload's network namespace, which is what an ordinary container expects.
NetworkInterfaceAttachmentModeNetns NetworkInterfaceAttachmentMode = "Netns"

// NetworkInterfaceAttachmentModeHypervisor means the interface is handed to a
// hypervisor as a device rather than placed in a namespace, which is what a
// virtual machine or microVM guest expects.
NetworkInterfaceAttachmentModeHypervisor NetworkInterfaceAttachmentMode = "Hypervisor"
)

// NetworkInterfacePhase reports whether an interface is held by a claim.
//
// +kubebuilder:validation:Enum=Available;Bound
Expand All @@ -53,8 +71,20 @@ const (
// carry is allocated and recorded in spec.
NetworkInterfaceAllocated = "Allocated"

// NetworkInterfacePrepared reports that the data plane's pre-Pod artifacts
// for this interface exist, so a workload that consumes it can be created.
//
// This is the condition to gate workload creation on. It becomes true before
// any workload exists, which is what makes waiting on it safe.
NetworkInterfacePrepared = "Prepared"

// NetworkInterfaceProgrammed reports that the data plane carries the
// interface's addresses. Traffic flows only once this is true.
//
// Never gate workload creation on this one. It becomes true when the
// interface is attached, which happens while the workload's sandbox is being
// created, so anything that withholds the workload until it is true waits for
// something its own waiting prevents.
NetworkInterfaceProgrammed = "Programmed"
)

Expand Down Expand Up @@ -213,6 +243,17 @@ type NetworkInterfaceSpec struct {
// +kubebuilder:default="eth0"
InterfaceName string `json:"interfaceName,omitempty"`

// attachmentMode is how the guest consumes this interface. It comes from the
// claim, and the operator carries it without interpreting it.
//
// Netns places the interface in the workload's network namespace. Hypervisor
// hands it to a hypervisor as a device, which is what a virtual machine or
// microVM guest needs.
//
// +kubebuilder:validation:Optional
// +kubebuilder:default="Netns"
AttachmentMode NetworkInterfaceAttachmentMode `json:"attachmentMode,omitempty"`

// mtu is the MTU, in bytes, the interface must be configured with. It is
// resolved from the network, so a provider never has to read the network to
// configure the NIC.
Expand Down Expand Up @@ -284,7 +325,8 @@ type NetworkInterfaceStatus struct {
VPC string `json:"vpc,omitempty"`

// conditions report the current state of the interface. Allocated means every
// address is held. Programmed means the data plane carries them.
// address is held. Prepared means the data plane is ready for a workload to
// consume it. Programmed means the data plane carries the addresses.
Conditions []metav1.Condition `json:"conditions,omitempty"`
}

Expand All @@ -307,6 +349,7 @@ type NetworkInterfaceStatus struct {
// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=".status.phase"
// +kubebuilder:printcolumn:name="Claim",type=string,JSONPath=".spec.claimRef.name"
// +kubebuilder:printcolumn:name="Allocated",type=string,JSONPath=`.status.conditions[?(@.type=="Allocated")].status`
// +kubebuilder:printcolumn:name="Prepared",type=string,JSONPath=`.status.conditions[?(@.type=="Prepared")].status`
// +kubebuilder:printcolumn:name="Programmed",type=string,JSONPath=`.status.conditions[?(@.type=="Programmed")].status`
type NetworkInterface struct {
metav1.TypeMeta `json:",inline"`
Expand All @@ -315,7 +358,7 @@ type NetworkInterface struct {
// +kubebuilder:validation:Required
Spec NetworkInterfaceSpec `json:"spec,omitempty"`

// +kubebuilder:default={conditions:{{type:"Allocated",status:"Unknown",reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type:"Programmed",status:"Unknown",reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}}
// +kubebuilder:default={conditions:{{type:"Allocated",status:"Unknown",reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type:"Prepared",status:"Unknown",reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type:"Programmed",status:"Unknown",reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}}
Status NetworkInterfaceStatus `json:"status,omitempty"`
}

Expand Down
38 changes: 33 additions & 5 deletions api/v1alpha/networkinterfaceclaim_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,25 @@ const (
// and every requested class, holds an address.
NetworkInterfaceClaimAllocated = "Allocated"

// NetworkInterfaceClaimPrepared reports that the data plane's pre-Pod
// artifacts for the bound interface exist, so a workload that consumes it can
// be created.
//
// This is the condition to gate workload creation on. It becomes true before
// any workload exists, which is what makes waiting on it safe.
NetworkInterfaceClaimPrepared = "Prepared"

// NetworkInterfaceClaimProgrammed reports that the data plane carries the
// claimed addresses.
//
// Never gate workload creation on this one. It becomes true when the
// interface is attached, which happens while the workload's sandbox is being
// created, so anything that withholds the workload until it is true waits for
// something its own waiting prevents.
NetworkInterfaceClaimProgrammed = "Programmed"

// NetworkInterfaceClaimReady reports that the claim is bound, allocated, and
// programmed. A workload that needs the network should wait on this one
// NetworkInterfaceClaimReady reports that the claim is bound, allocated,
// prepared, and programmed. A workload that needs the network should wait on this one
// condition rather than on the three it summarizes.
NetworkInterfaceClaimReady = "Ready"
)
Expand Down Expand Up @@ -98,6 +111,21 @@ type NetworkInterfaceClaimSpec struct {
// +kubebuilder:validation:XValidation:message="interfaceName is immutable and cannot be changed after creation",rule="self == oldSelf"
InterfaceName string `json:"interfaceName,omitempty"`

// attachmentMode is how the guest consumes this interface. Netns places it in
// the workload's network namespace, which is what an ordinary container
// expects. Hypervisor hands it to a hypervisor as a device, which is what a
// virtual machine or microVM guest needs.
//
// It is copied to the bound interface and never interpreted here. Whoever
// realizes the interface decides what each mode means on its data plane.
//
// Immutable, because the guest and the attachment are both built against it.
//
// +kubebuilder:validation:Optional
// +kubebuilder:default="Netns"
// +kubebuilder:validation:XValidation:message="attachmentMode is immutable and cannot be changed after creation",rule="self == oldSelf"
AttachmentMode NetworkInterfaceAttachmentMode `json:"attachmentMode,omitempty"`

// ipFamilies are the address families the interface must carry, in priority
// order. List [IPv6, IPv4] for a dual-stack interface. The first family
// listed holds the interface's primary address, which is the one reported in
Expand Down Expand Up @@ -198,8 +226,8 @@ type NetworkInterfaceClaimStatus struct {
ExternalAddresses []NetworkInterfaceExternalAddress `json:"externalAddresses,omitempty"`

// conditions report the current state of the claim. Wait on Ready, which is
// true once the claim is bound, its addresses are allocated, and the data
// plane carries them.
// true once the claim is bound, its addresses are allocated, the data plane
// is prepared for a workload, and the data plane carries the addresses.
Conditions []metav1.Condition `json:"conditions,omitempty"`
}

Expand Down Expand Up @@ -231,7 +259,7 @@ type NetworkInterfaceClaim struct {
// +kubebuilder:validation:Required
Spec NetworkInterfaceClaimSpec `json:"spec,omitempty"`

// +kubebuilder:default={conditions:{{type:"Bound",status:"Unknown",reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type:"Allocated",status:"Unknown",reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type:"Programmed",status:"Unknown",reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type:"Ready",status:"Unknown",reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}}
// +kubebuilder:default={conditions:{{type:"Bound",status:"Unknown",reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type:"Allocated",status:"Unknown",reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type:"Prepared",status:"Unknown",reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type:"Programmed",status:"Unknown",reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"},{type:"Ready",status:"Unknown",reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}}
Status NetworkInterfaceClaimStatus `json:"status,omitempty"`
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,26 @@ spec:
x-kubernetes-validations:
- message: Each address class may be requested at most once
rule: self.all(a, self.exists_one(b, b.class == a.class))
attachmentMode:
default: Netns
description: |-
attachmentMode is how the guest consumes this interface. Netns places it in
the workload's network namespace, which is what an ordinary container
expects. Hypervisor hands it to a hypervisor as a device, which is what a
virtual machine or microVM guest needs.

It is copied to the bound interface and never interpreted here. Whoever
realizes the interface decides what each mode means on its data plane.

Immutable, because the guest and the attachment are both built against it.
enum:
- Netns
- Hypervisor
type: string
x-kubernetes-validations:
- message: attachmentMode is immutable and cannot be changed after
creation
rule: self == oldSelf
interfaceName:
default: eth0
description: |-
Expand Down Expand Up @@ -239,6 +259,11 @@ spec:
reason: Pending
status: Unknown
type: Allocated
- lastTransitionTime: "1970-01-01T00:00:00Z"
message: Waiting for controller
reason: Pending
status: Unknown
type: Prepared
- lastTransitionTime: "1970-01-01T00:00:00Z"
message: Waiting for controller
reason: Pending
Expand Down Expand Up @@ -315,8 +340,8 @@ spec:
conditions:
description: |-
conditions report the current state of the claim. Wait on Ready, which is
true once the claim is bound, its addresses are allocated, and the data
plane carries them.
true once the claim is bound, its addresses are allocated, the data plane
is prepared for a workload, and the data plane carries the addresses.
items:
description: Condition contains details for one aspect of the current
state of this API Resource.
Expand Down
24 changes: 23 additions & 1 deletion config/crd/bases/networking.datumapis.com_networkinterfaces.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ spec:
- jsonPath: .status.conditions[?(@.type=="Allocated")].status
name: Allocated
type: string
- jsonPath: .status.conditions[?(@.type=="Prepared")].status
name: Prepared
type: string
- jsonPath: .status.conditions[?(@.type=="Programmed")].status
name: Programmed
type: string
Expand Down Expand Up @@ -136,6 +139,19 @@ spec:
== 1
- message: Only one address may be held per address family
rule: self.all(a, self.exists_one(b, b.family == a.family))
attachmentMode:
default: Netns
description: |-
attachmentMode is how the guest consumes this interface. It comes from the
claim, and the operator carries it without interpreting it.

Netns places the interface in the workload's network namespace. Hypervisor
hands it to a hypervisor as a device, which is what a virtual machine or
microVM guest needs.
enum:
- Netns
- Hypervisor
type: string
claimRef:
description: |-
claimRef is the claim currently holding this interface. It is empty while a
Expand Down Expand Up @@ -252,6 +268,11 @@ spec:
reason: Pending
status: Unknown
type: Allocated
- lastTransitionTime: "1970-01-01T00:00:00Z"
message: Waiting for controller
reason: Pending
status: Unknown
type: Prepared
- lastTransitionTime: "1970-01-01T00:00:00Z"
message: Waiting for controller
reason: Pending
Expand Down Expand Up @@ -292,7 +313,8 @@ spec:
conditions:
description: |-
conditions report the current state of the interface. Allocated means every
address is held. Programmed means the data plane carries them.
address is held. Prepared means the data plane is ready for a workload to
consume it. Programmed means the data plane carries the addresses.
items:
description: Condition contains details for one aspect of the current
state of this API Resource.
Expand Down
Loading
Loading