Skip to content

Commit

Permalink
fast node slice initial implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ivelichkovich committed May 9, 2024
1 parent 775603d commit ea19d43
Show file tree
Hide file tree
Showing 26 changed files with 2,681 additions and 14 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

# Output of the go coverage tool, specifically when used with LiteIDE
*.out
.idea
kind/

bin/
/github.com/
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ FROM alpine:latest
LABEL org.opencontainers.image.source https://github.com/k8snetworkplumbingwg/whereabouts
COPY --from=0 /go/src/github.com/k8snetworkplumbingwg/whereabouts/bin/whereabouts .
COPY --from=0 /go/src/github.com/k8snetworkplumbingwg/whereabouts/bin/ip-control-loop .
COPY --from=0 /go/src/github.com/k8snetworkplumbingwg/whereabouts/bin/node-slice-controller .
COPY script/install-cni.sh .
CMD ["/install-cni.sh"]
91 changes: 91 additions & 0 deletions cmd/nodeslicecontroller/node_slice_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package main

import (
"flag"
nadclient "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/client/clientset/versioned"
nadinformers "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/client/informers/externalversions"
clientset "github.com/k8snetworkplumbingwg/whereabouts/pkg/client/clientset/versioned"
informers "github.com/k8snetworkplumbingwg/whereabouts/pkg/client/informers/externalversions"
node_controller "github.com/k8snetworkplumbingwg/whereabouts/pkg/node-controller"

"time"

kubeinformers "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/klog/v2"

"github.com/k8snetworkplumbingwg/whereabouts/pkg/node-controller/signals"
)

var (
masterURL string
kubeconfig string
)

// TODO: leader election
func main() {
klog.InitFlags(nil)
flag.Parse()

// set up signals so we handle the shutdown signal gracefully
ctx := signals.SetupSignalHandler()
logger := klog.FromContext(ctx)

cfg, err := clientcmd.BuildConfigFromFlags(masterURL, kubeconfig)
if err != nil {
logger.Error(err, "Error building kubeconfig")
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
}

kubeClient, err := kubernetes.NewForConfig(cfg)
if err != nil {
logger.Error(err, "Error building kubernetes clientset")
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
}

whereaboutsClient, err := clientset.NewForConfig(cfg)
if err != nil {
logger.Error(err, "Error building kubernetes clientset")
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
}

nadClient, err := nadclient.NewForConfig(cfg)
if err != nil {
logger.Error(err, "Error building kubernetes clientset")
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
}

kubeInformerFactory := kubeinformers.NewSharedInformerFactory(kubeClient, time.Second*30)
whereaboutsInformerFactory := informers.NewSharedInformerFactory(whereaboutsClient, time.Second*30)
nadInformerFactory := nadinformers.NewSharedInformerFactory(nadClient, time.Second*30)

controller := node_controller.NewController(
ctx,
kubeClient,
whereaboutsClient,
nadClient,
kubeInformerFactory.Core().V1().Nodes(),
whereaboutsInformerFactory.Whereabouts().V1alpha1().NodeSlicePools(),
whereaboutsInformerFactory.Whereabouts().V1alpha1().IPPools(),
nadInformerFactory.K8sCniCncfIo().V1().NetworkAttachmentDefinitions(),
false,
)

// notice that there is no need to run Start methods in a separate goroutine. (i.e. go kubeInformerFactory.Start(ctx.done())
// Start method is non-blocking and runs all registered informers in a dedicated goroutine.
kubeInformerFactory.Start(ctx.Done())
whereaboutsInformerFactory.Start(ctx.Done())
nadInformerFactory.Start(ctx.Done())

//TODO: make workers configurable via flag, what is a sane value here? How will concurrency work?
if err = controller.Run(ctx, 1); err != nil {
logger.Error(err, "Error running controller")
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
}
}

func init() {
flag.StringVar(&kubeconfig, "kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.")
flag.StringVar(&masterURL, "master", "", "The address of the Kubernetes API server. Overrides any value in kubeconfig. Only required if out-of-cluster.")
}
76 changes: 76 additions & 0 deletions doc/crds/whereabouts.cni.cncf.io_nodeslicepools.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@

---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.4.1
creationTimestamp: null
name: nodeslicepools.whereabouts.cni.cncf.io
spec:
group: whereabouts.cni.cncf.io
names:
kind: NodeSlicePool
listKind: NodeSlicePoolList
plural: nodeslicepools
singular: nodeslicepool
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: NodeSlicePool is the Schema for the nodesliceippools 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: NodeSlicePoolSpec defines the desired state of NodeSlicePool
properties:
range:
description: Range is a RFC 4632/4291-style string that represents
an IP address and prefix length in CIDR notation this refers to
the entire range where the node is allocated a subset
type: string
sliceSize:
type: string
required:
- range
- sliceSize
type: object
status:
description: NodeSlicePoolStatus defines the desired state of NodeSlicePool
properties:
allocations:
items:
properties:
nodeName:
type: string
sliceRange:
type: string
required:
- nodeName
- sliceRange
type: object
type: array
required:
- allocations
type: object
type: object
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
2 changes: 2 additions & 0 deletions hack/build-go.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,5 @@ GLDFLAGS="${GLDFLAGS} ${VERSION_LDFLAGS}"

CGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} ${GO} build ${GOFLAGS} -ldflags "${GLDFLAGS}" -o bin/${cmd} cmd/${cmd}.go
CGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} ${GO} build ${GOFLAGS} -ldflags "${GLDFLAGS}" -o bin/ip-control-loop cmd/controlloop/*.go
CGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} ${GO} build ${GOFLAGS} -ldflags "${GLDFLAGS}" -o bin/node-slice-controller cmd/nodeslicecontroller/*.go

52 changes: 52 additions & 0 deletions pkg/api/whereabouts.cni.cncf.io/v1alpha1/nodeslicepool_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package v1alpha1

import (
"net"

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

// NodeSlicePoolSpec defines the desired state of NodeSlicePool
type NodeSlicePoolSpec struct {
// Range is a RFC 4632/4291-style string that represents an IP address and prefix length in CIDR notation
// this refers to the entire range where the node is allocated a subset
Range string `json:"range"`

SliceSize string `json:"sliceSize"`
}

// NodeSlicePoolStatus defines the desired state of NodeSlicePool
type NodeSlicePoolStatus struct {
Allocations []NodeSliceAllocation `json:"allocations"`
}

type NodeSliceAllocation struct {
NodeName string `json:"nodeName"`
SliceRange string `json:"sliceRange"`
}

// ParseCIDR formats the Range of the IPPool
func (i NodeSlicePool) ParseCIDR() (net.IP, *net.IPNet, error) {
return net.ParseCIDR(i.Spec.Range)
}

// +genclient
// +kubebuilder:object:root=true

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

Spec NodeSlicePoolSpec `json:"spec,omitempty"`
Status NodeSlicePoolStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

// NodeSlicePoolList contains a list of NodeSlicePool
type NodeSlicePoolList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []NodeSlicePool `json:"items"`
}
2 changes: 2 additions & 0 deletions pkg/api/whereabouts.cni.cncf.io/v1alpha1/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&IPPoolList{},
&OverlappingRangeIPReservation{},
&OverlappingRangeIPReservationList{},
&NodeSlicePool{},
&NodeSlicePoolList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
Expand Down
109 changes: 109 additions & 0 deletions pkg/api/whereabouts.cni.cncf.io/v1alpha1/zz_generated.deepcopy.go

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

Loading

0 comments on commit ea19d43

Please sign in to comment.