Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
46 changes: 46 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,50 @@ resources:
webhooks:
defaulting: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: netbird.io
kind: NBRoutingPeer
path: github.com/netbirdio/kubernetes-operator/api/v1
version: v1
webhooks:
validation: true
webhookVersion: v1
- controller: true
external: true
kind: Service
path: k8s.io/api/core/v1
version: v1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: netbird.io
kind: NBResource
path: github.com/netbirdio/kubernetes-operator/api/v1
version: v1
webhooks:
validation: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: netbird.io
kind: NBGroup
path: github.com/netbirdio/kubernetes-operator/api/v1
version: v1
webhooks:
validation: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: netbird.io
kind: NBPolicy
path: github.com/netbirdio/kubernetes-operator/api/v1
version: v1
version: "3"
97 changes: 23 additions & 74 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,107 +1,56 @@
# NetBird Kubernetes Operator
For easily provisioning access to Kubernetes resources using NetBird.

https://github.com/user-attachments/assets/5472a499-e63d-4301-a513-ad84cfe5ca7b

## Description

This operator enables easily provisioning NetBird access on kubernetes clusters, allowing users to access internal resources directly.
This operator easily provides NetBird access on Kubernetes clusters, allowing users to access internal resources directly.

## Getting Started

### Prerequisites
- helm version 3+
- (Recommended) helm version 3+
- kubectl version v1.11.3+.
- Access to a Kubernetes v1.11.3+ cluster.
- (Optional for Helm chart installation) Cert Manager.

### To Deploy on the cluster
- (Recommended) Cert Manager.

**Using the install.yaml**

```sh
kubectl create namespace netbird
kubectl apply -n netbird -f https://github.com/netbirdio/kubernetes-operator/releases/latest/manifests/install.yaml
```
### Deployment
> [!NOTE]
> Helm Installation method is recommended due to the automation of multiple settings within the deployment.

**Using the Helm Chart**
#### Using Helm

1. Add helm repository.
```sh
helm repo add netbirdio https://netbirdio.github.io/kubernetes-operator
helm install -n netbird kubernetes-operator netbirdio/kubernetes-operator
```
2. (Recommended) Install [cert-manager](https://cert-manager.io/docs/installation/#default-static-install).
3. (Recommended) Create a values.yaml file, check `helm show values netbirdio/kubernetes-operator` for more info.
4. Install using `helm install --create-namespace -f values.yaml -n netbird netbird-operator netbirdio/kubernetes-operator`.

For more options, check the default values by running
```sh
helm show values netbirdio/kubernetes-operator
```
> Learn more about the values.yaml options [here](helm/kubernetes-operator/values.yaml) and [Granting controller access to NetBird Management](docs/usage.md#granting-controller-access-to-netbird-management).
#### Using install.yaml

### To Uninstall
**Using install.yaml**
> [!IMPORTANT]
> install.yaml only includes a very basic template for deploying a stripped-down version of Kubernetes-operator.
> This excludes any and all configurations for ingress capabilities and requires the cert-manager to be installed.

```sh
kubectl delete -n netbird -f https://github.com/netbirdio/kubernetes-operator/releases/latest/manifests/install.yaml
kubectl delete namespace netbird
```

**Using helm**

```sh
helm uninstall -n netbird kubernetes-operator
kubectl create namespace netbird
kubectl apply -n netbird -f https://raw.githubusercontent.com/netbirdio/kubernetes-operator/refs/heads/main/manifests/install.yaml
```

### Provision pods with NetBird access

1. Create a Setup Key in your [NetBird console](https://docs.netbird.io/how-to/register-machines-using-setup-keys#using-setup-keys).
1. Create a Secret object in the namespace where you need to provision NetBird access (secret name and field can be anything).
```yaml
apiVersion: v1
stringData:
setupkey: EEEEEEEE-EEEE-EEEE-EEEE-EEEEEEEEEEEE
kind: Secret
metadata:
name: test
```
1. Create an NBSetupKey object referring to your secret.
```yaml
apiVersion: netbird.io/v1
kind: NBSetupKey
metadata:
name: test
spec:
# Optional, overrides management URL for this setupkey only
# defaults to https://api.netbird.io
managementURL: https://netbird.example.com
secretKeyRef:
name: test # Required
key: setupkey # Required
```
1. Annotate the pods you need to inject NetBird into with `netbird.io/setup-key`.
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment
spec:
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
annotations:
netbird.io/setup-key: test # Must match the name of an NBSetupKey object in the same namespace
spec:
containers:
- image: yourimage
name: container
### Usage

```
Check the usage of [usage.md](docs/usage.md) and examples.

## Contributing

### Prerequisites

To be able to develop on this project, you need to have the following tools installed:
To be able to develop this project, you need to have the following tools installed:

- [Git](https://git-scm.com/).
- [Make](https://www.gnu.org/software/make/).
Expand Down
52 changes: 52 additions & 0 deletions api/v1/nbgroup_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package v1

import (
"slices"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// NBGroupSpec defines the desired state of NBGroup.
type NBGroupSpec struct {
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
// +kubebuilder:validation:MinLength=1
Name string `json:"name"`
}

// NBGroupStatus defines the observed state of NBGroup.
type NBGroupStatus struct {
// +optional
GroupID *string `json:"groupID"`
// +optional
Conditions []NBCondition `json:"conditions,omitempty"`
}

// Equal returns if NBGroupStatus is equal to this one
func (a NBGroupStatus) Equal(b NBGroupStatus) bool {
return a.GroupID == b.GroupID && slices.Equal(a.Conditions, b.Conditions)
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status

// NBGroup is the Schema for the nbgroups API.
type NBGroup struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec NBGroupSpec `json:"spec,omitempty"`
Status NBGroupStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

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

func init() {
SchemeBuilder.Register(&NBGroup{}, &NBGroupList{})
}
81 changes: 81 additions & 0 deletions api/v1/nbpolicy_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package v1

import (
"slices"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// NBPolicySpec defines the desired state of NBPolicy.
type NBPolicySpec struct {
// Name Policy name
// +kubebuilder:validation:MinLength=1
Name string `json:"name"`
// +optional
Description string `json:"description,omitempty"`
// +optional
// +kubebuilder:validation:items:MinLength=1
SourceGroups []string `json:"sourceGroups,omitempty"`
// +optional
// +kubebuilder:validation:items:MinLength=1
DestinationGroups []string `json:"destinationGroups,omitempty"`
// +optional
// +kubebuilder:validation:items:Enum=tcp;udp
Protocols []string `json:"protocols,omitempty"`
// +optional
// +kubebuilder:validation:items:Minimum=0
// +kubebuilder:validation:items:Maximum=65535
Ports []int32 `json:"ports,omitempty"`
// +optional
// +default:value=true
Bidirectional bool `json:"bidirectional"`
}

// NBPolicyStatus defines the observed state of NBPolicy.
type NBPolicyStatus struct {
// +optional
TCPPolicyID *string `json:"tcpPolicyID"`
// +optional
UDPPolicyID *string `json:"udpPolicyID"`
// +optional
LastUpdatedAt *metav1.Time `json:"lastUpdatedAt"`
// +optional
ManagedServiceList []string `json:"managedServiceList"`
// +optional
Conditions []NBCondition `json:"conditions,omitempty"`
}

// Equal returns if NBPolicyStatus is equal to this one
func (a NBPolicyStatus) Equal(b NBPolicyStatus) bool {
return a.TCPPolicyID == b.TCPPolicyID &&
a.UDPPolicyID == b.UDPPolicyID &&
a.LastUpdatedAt == b.LastUpdatedAt &&
slices.Equal(a.ManagedServiceList, b.ManagedServiceList) &&
slices.Equal(a.Conditions, b.Conditions)
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:scope=Cluster

// NBPolicy is the Schema for the nbpolicies API.
type NBPolicy struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec NBPolicySpec `json:"spec,omitempty"`
Status NBPolicyStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

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

func init() {
SchemeBuilder.Register(&NBPolicy{}, &NBPolicyList{})
}
76 changes: 76 additions & 0 deletions api/v1/nbresource_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package v1

import (
"slices"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// NBResourceSpec defines the desired state of NBResource.
type NBResourceSpec struct {
// +kubebuilder:validation:MinLength=1
Name string `json:"name"`
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
NetworkID string `json:"networkID"`
// +kubebuilder:validation:MinLength=1
Address string `json:"address"`
// +kubebuilder:validation:items:MinLength=1
Groups []string `json:"groups"`
// +optional
PolicyName string `json:"policyName,omitempty"`
// +optional
TCPPorts []int32 `json:"tcpPorts,omitempty"`
// +optional
UDPPorts []int32 `json:"udpPorts,omitempty"`
}

// NBResourceStatus defines the observed state of NBResource.
type NBResourceStatus struct {
// +optional
NetworkResourceID *string `json:"networkResourceID,omitempty"`
// +optional
PolicyName *string `json:"policyName,omitempty"`
// +optional
TCPPorts []int32 `json:"tcpPorts,omitempty"`
// +optional
UDPPorts []int32 `json:"udpPorts,omitempty"`
// +optional
Groups []string `json:"groups,omitempty"`
// +optional
Conditions []NBCondition `json:"conditions,omitempty"`
}

// Equal returns if NBResourceStatus is equal to this one
func (a NBResourceStatus) Equal(b NBResourceStatus) bool {
return a.NetworkResourceID == b.NetworkResourceID &&
a.PolicyName == b.PolicyName &&
slices.Equal(a.TCPPorts, b.TCPPorts) &&
slices.Equal(a.UDPPorts, b.UDPPorts) &&
slices.Equal(a.Groups, b.Groups) &&
slices.Equal(a.Conditions, b.Conditions)
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status

// NBResource is the Schema for the nbresources API.
type NBResource struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec NBResourceSpec `json:"spec,omitempty"`
Status NBResourceStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

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

func init() {
SchemeBuilder.Register(&NBResource{}, &NBResourceList{})
}
Loading
Loading