Add network egress resource (#357)

This change adds a new import resource which enables exposing Netbird
resources as Kubernetes services. This remove the need to add sidecars
to every pod.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a new `NetworkEgress` custom resource (`netbird.io/v1alpha1`)
with CRD, schema validation, and status/conditions.
* Extended controller functionality to create egress services and
translate egress rules into import `EndpointSlice` resources; egress
pods now include a kube-egress-forwarder sidecar.
* **Bug Fixes**
* Added missing deep-copy and declarative apply support for the new
`NetworkEgress` API types.
* **Documentation**
* Updated README/API reference and added example manifests for
`NetworkEgress` (including IP/FQDN target usage).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Signed-off-by: Philip Laine <philip.laine@gmail.com>
This commit is contained in:
Philip Laine
2026-07-17 08:06:53 +02:00
committed by GitHub
parent 3c1c6675d9
commit ea2dafd5a3
31 changed files with 2220 additions and 83 deletions
@@ -0,0 +1,200 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.20.1
name: networkegresses.netbird.io
spec:
group: netbird.io
names:
kind: NetworkEgress
listKind: NetworkEgressList
plural: networkegresses
singular: networkegress
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .status.conditions[?(@.type=="Ready")].status
name: Ready
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: NetworkEgress is the Schema for the networkegresses API.
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: NetworkEgressSpec defines the desired state of NetworkEgress.
properties:
networkRouterRef:
description: NetworkRouterRef is a reference to the network and router
where the resource will be created.
properties:
name:
description: Name of the referent.
type: string
namespace:
description: Namespace of the referent.
type: string
required:
- name
- namespace
type: object
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
ports:
description: Ports to the resource to route.
items:
properties:
name:
description: Name of the port.
maxLength: 15
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
port:
description: The port that will be exposed by this service.
format: int32
maximum: 65535
minimum: 1
type: integer
required:
- name
- port
type: object
minItems: 1
type: array
target:
description: Target for egress traffic.
properties:
fqdn:
description: FQDN targets an exact domain name (no wildcards).
properties:
hostname:
description: Hostname is a fully qualified domain name to
match exactly.
pattern: ^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$
type: string
required:
- hostname
type: object
ip:
description: IP targets a single specific IP address (not a CIDR
range).
properties:
address:
description: Address is a single IP address.
type: string
x-kubernetes-validations:
- message: address must be a valid IPv4 or IPv6 address
rule: isIP(self)
required:
- address
type: object
type: object
x-kubernetes-validations:
- message: exactly one of ip or fqdn must be set
rule: '(has(self.ip) ? 1 : 0) + (has(self.fqdn) ? 1 : 0) == 1'
required:
- networkRouterRef
- ports
- target
type: object
status:
default:
observedGeneration: -1
description: NetworkEgressStatus defines the observed state of NetworkEgress.
properties:
conditions:
description: Conditions holds the conditions for the NetworkEgress.
items:
description: Condition contains details for one aspect of the current
state of this API Resource.
properties:
lastTransitionTime:
description: |-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: |-
message is a human readable message indicating details about the transition.
This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: |-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: |-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
observedGeneration:
description: ObservedGeneration is the last reconciled generation.
format: int64
type: integer
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}
+1
View File
@@ -12,4 +12,5 @@ resources:
- bases/netbird.io_setupkeys.yaml
- bases/netbird.io_sidecarprofiles.yaml
- bases/netbird.io_clusterproxies.yaml
- bases/netbird.io_networkegresses.yaml
# +kubebuilder:scaffold:crdkustomizeresource