Skip to content

Commit

Permalink
wip: enable gke autopilot support
Browse files Browse the repository at this point in the history
  • Loading branch information
redhatrises committed Oct 24, 2023
1 parent c9f180d commit 1def93a
Show file tree
Hide file tree
Showing 16 changed files with 679 additions and 83 deletions.
53 changes: 52 additions & 1 deletion api/falcon/v1alpha1/falconnodesensor_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,67 @@ type FalconNodeSensorConfig struct {
// +kubebuilder:default=false
// +operator-sdk:csv:customresourcedefinitions:type=spec,order=8
NodeCleanup *bool `json:"disableCleanup,omitempty"`

// Configure resource requests and limits for the DaemonSet Sensor. Only applies when using the eBPF backend.
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Falcon eBPF Sensor Resources",order=9
SensorResources Resources `json:"resources,omitempty"`

// Sets the backend to be used by the DaemonSet Sensor.
// +kubebuilder:default=kernel
// +kubebuilder:validation:Enum=kernel;bpf
// +operator-sdk-csv:customresourcedefinitions:type=spec,order=9
// +operator-sdk-csv:customresourcedefinitions:type=spec,order=10
Backend string `json:"backend,omitempty"`

// Enables the use of GKE Autopilot.
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="GKE Autopilot Settings",order=11
GKE AutoPilot `json:"gke,omitempty"`

// Enable priority class for the DaemonSet. This is useful for GKE Autopilot clusters, but can be set for any cluster.
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Priority Class",order=12
PriorityClass PriorityClassConfig `json:"priorityClass,omitempty"`

// Version of the sensor to be installed. The latest version will be selected when this version specifier is missing.
Version *string `json:"version,omitempty"`
}

type PriorityClassConfig struct {
// Enables the operator to deploy a PriorityClass instead of rolling your own.
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Deploy Priority Class to cluster",order=2
Deploy *bool `json:"deploy,omitempty"`

// Name of the priority class to use for the DaemonSet.
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Name of the Priority Class to use",order=2
Name string `json:"name,omitempty"`

// Value of the priority class to use for the DaemonSet. Requires the Deploy field to be set to true.
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Priority Class Value",order=3
Value *int32 `json:"value,omitempty"`
}

type Resources struct {
// Sets the resource limits for the DaemonSet Sensor. Only applies when using the eBPF backend.
// +operator-sdk:csv:customresourcedefinitions:type=spec
Limits ResourceList `json:"limits,omitempty"`
// Sets the resource requests for the DaemonSet Sensor. Only applies when using the eBPF backend.
// +operator-sdk:csv:customresourcedefinitions:type=spec
Requests ResourceList `json:"requests,omitempty"`
}

type ResourceList struct {
// +operator-sdk:csv:customresourcedefinitions:type=spec
// +kubebuilder:validation:Pattern="^(([0-9]{4,}|[2-9][5-9][0-9])m$)|[0-9]+$"
CPU string `json:"cpu,omitempty"`
// +operator-sdk:csv:customresourcedefinitions:type=spec
// +kubebuilder:validation:Pattern="^(([5-9][0-9]{2}[Mi]+)|([0-9.]+[iEGTP]+))|(([5-9][0-9]{8})|([0-9]{10,}))$"
Memory string `json:"memory,omitempty"`
}

type AutoPilot struct {
// Enables the use of GKE Autopilot.
// +operator-sdk:csv:customresourcedefinitions:type=spec
Enabled *bool `json:"autopilot,omitempty"`
}

type FalconNodeUpdateStrategy struct {
// +kubebuilder:default=RollingUpdate
// +kubebuilder:validation:Enum=RollingUpdate;OnDelete
Expand Down
80 changes: 80 additions & 0 deletions api/falcon/v1alpha1/zz_generated.deepcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,26 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime"
)

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AutoPilot) DeepCopyInto(out *AutoPilot) {
*out = *in
if in.Enabled != nil {
in, out := &in.Enabled, &out.Enabled
*out = new(bool)
**out = **in
}
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoPilot.
func (in *AutoPilot) DeepCopy() *AutoPilot {
if in == nil {
return nil
}
out := new(AutoPilot)
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FalconAPI) DeepCopyInto(out *FalconAPI) {
*out = *in
Expand Down Expand Up @@ -784,6 +804,9 @@ func (in *FalconNodeSensorConfig) DeepCopyInto(out *FalconNodeSensorConfig) {
*out = new(bool)
**out = **in
}
out.SensorResources = in.SensorResources
in.GKE.DeepCopyInto(&out.GKE)
in.PriorityClass.DeepCopyInto(&out.PriorityClass)
if in.Version != nil {
in, out := &in.Version, &out.Version
*out = new(string)
Expand Down Expand Up @@ -955,6 +978,31 @@ func (in *FalconSensor) DeepCopy() *FalconSensor {
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PriorityClassConfig) DeepCopyInto(out *PriorityClassConfig) {
*out = *in
if in.Deploy != nil {
in, out := &in.Deploy, &out.Deploy
*out = new(bool)
**out = **in
}
if in.Value != nil {
in, out := &in.Value, &out.Value
*out = new(int32)
**out = **in
}
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PriorityClassConfig.
func (in *PriorityClassConfig) DeepCopy() *PriorityClassConfig {
if in == nil {
return nil
}
out := new(PriorityClassConfig)
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RegistrySpec) DeepCopyInto(out *RegistrySpec) {
*out = *in
Expand Down Expand Up @@ -990,3 +1038,35 @@ func (in *RegistryTLSSpec) DeepCopy() *RegistryTLSSpec {
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ResourceList) DeepCopyInto(out *ResourceList) {
*out = *in
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceList.
func (in *ResourceList) DeepCopy() *ResourceList {
if in == nil {
return nil
}
out := new(ResourceList)
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Resources) DeepCopyInto(out *Resources) {
*out = *in
out.Limits = in.Limits
out.Requests = in.Requests
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources.
func (in *Resources) DeepCopy() *Resources {
if in == nil {
return nil
}
out := new(Resources)
in.DeepCopyInto(out)
return out
}
51 changes: 51 additions & 0 deletions config/crd/bases/falcon.crowdstrike.com_falconnodesensors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ spec:
on the nodes. Disabling might have unintended consequences for
certain operations such as sensor downgrading.
type: boolean
gke:
description: Enables the use of GKE Autopilot.
properties:
autopilot:
description: Enables the use of GKE Autopilot.
type: boolean
type: object
image:
description: Location of the Falcon Sensor image. Use only in
cases when you mirror the original image to your repository/name:tag
Expand Down Expand Up @@ -379,6 +386,50 @@ spec:
type: object
x-kubernetes-map-type: atomic
type: object
priorityClass:
description: Enable priority class for the DaemonSet. This is
useful for GKE Autopilot clusters, but can be set for any cluster.
properties:
deploy:
description: Enables the operator to deploy a PriorityClass
instead of rolling your own.
type: boolean
name:
description: Name of the priority class to use for the DaemonSet.
type: string
value:
description: Value of the priority class to use for the DaemonSet.
Requires the Deploy field to be set to true.
format: int32
type: integer
type: object
resources:
description: Configure resource requests and limits for the DaemonSet
Sensor. Only applies when using the eBPF backend.
properties:
limits:
description: Sets the resource limits for the DaemonSet Sensor.
Only applies when using the eBPF backend.
properties:
cpu:
pattern: ^(([0-9]{4,}|[2-9][5-9][0-9])m$)|[0-9]+$
type: string
memory:
pattern: ^(([5-9][0-9]{2}[Mi]+)|([0-9.]+[iEGTP]+))|(([5-9][0-9]{8})|([0-9]{10,}))$
type: string
type: object
requests:
description: Sets the resource requests for the DaemonSet
Sensor. Only applies when using the eBPF backend.
properties:
cpu:
pattern: ^(([0-9]{4,}|[2-9][5-9][0-9])m$)|[0-9]+$
type: string
memory:
pattern: ^(([5-9][0-9]{2}[Mi]+)|([0-9.]+[iEGTP]+))|(([5-9][0-9]{8})|([0-9]{10,}))$
type: string
type: object
type: object
serviceAccount:
description: Add metadata to the DaemonSet Service Account for
IAM roles.
Expand Down
1 change: 1 addition & 0 deletions config/default/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ bases:
- ../crd
- ../rbac
- ../manager
#- ../resources
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
# crd/kustomization.yaml
#- ../webhook
Expand Down
2 changes: 1 addition & 1 deletion config/manager/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ kind: Kustomization
images:
- name: controller
newName: quay.io/crowdstrike/falcon-operator
newTag: latest
newTag: test
1 change: 1 addition & 0 deletions config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ spec:
args:
- --leader-elect
image: controller:latest
imagePullPolicy: Always
name: manager
env:
- name: WATCH_NAMESPACE
Expand Down
10 changes: 10 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,16 @@ rules:
- list
- update
- watch
- apiGroups:
- scheduling.k8s.io
resources:
- priorityclass
verbs:
- create
- delete
- get
- update
- watch
- apiGroups:
- security.openshift.io
resourceNames:
Expand Down
55 changes: 55 additions & 0 deletions controllers/falcon_node/falconnodesensor_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
schedulingv1 "k8s.io/api/scheduling/v1"
"k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
Expand Down Expand Up @@ -58,6 +59,7 @@ func (r *FalconNodeSensorReconciler) SetupWithManager(mgr ctrl.Manager) error {
//+kubebuilder:rbac:groups="",resources=namespaces,verbs=get;list;watch
//+kubebuilder:rbac:groups="rbac.authorization.k8s.io",resources=clusterrolebindings,verbs=get;list;watch;create
//+kubebuilder:rbac:groups="security.openshift.io",resources=securitycontextconstraints,resourceNames=privileged,verbs=use
//+kubebuilder:rbac:groups="scheduling.k8s.io",resources=priorityclass,verbs=get;watch;create;delete;update

// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
Expand Down Expand Up @@ -115,6 +117,13 @@ func (r *FalconNodeSensorReconciler) Reconcile(ctx context.Context, req ctrl.Req
return ctrl.Result{Requeue: true}, nil
}

if nodesensor.Spec.Node.PriorityClass.Deploy != nil {
err := r.handlePriorityClass(ctx, nodesensor, logger)
if err != nil {
return ctrl.Result{}, err
}
}

serviceAccount := common.NodeServiceAccountName

created, err = r.handlePermissions(ctx, nodesensor, logger)
Expand Down Expand Up @@ -245,6 +254,11 @@ func (r *FalconNodeSensorReconciler) Reconcile(ctx context.Context, req ctrl.Req
volumeUpdates := updateDaemonSetVolumes(dsUpdate, dsTarget, logger)
updated = updateDaemonSetContainerProxy(dsUpdate, nodesensor, logger)

if dsUpdate.Spec.Template.Spec.PriorityClassName != dsTarget.Spec.Template.Spec.PriorityClassName {
dsUpdate.Spec.Template.Spec.PriorityClassName = dsTarget.Spec.Template.Spec.PriorityClassName
updated = true
}

// Update the daemonset and re-spin pods with changes
if imgUpdate || tolsUpdate || affUpdate || containerVolUpdate || volumeUpdates || updated {
err = r.Update(ctx, dsUpdate)
Expand Down Expand Up @@ -369,6 +383,47 @@ func (r *FalconNodeSensorReconciler) handleNamespace(ctx context.Context, nodese
return true, nil
}

// handlePriorityClass creates and updates the priority class
func (r *FalconNodeSensorReconciler) handlePriorityClass(ctx context.Context, nodesensor *falconv1alpha1.FalconNodeSensor, logger logr.Logger) error {
existingPC := &schedulingv1.PriorityClass{}
pcName := nodesensor.Name + "-priorityclass"
update := false

if nodesensor.Spec.Node.PriorityClass.Name == "" {
nodesensor.Spec.Node.PriorityClass.Name = pcName
}
pc := assets.PriorityClass(nodesensor.Spec.Node.PriorityClass.Name, nodesensor.Spec.Node.PriorityClass.Value)

err := r.Get(ctx, types.NamespacedName{Name: nodesensor.Name, Namespace: nodesensor.TargetNs()}, pc)
if err != nil && errors.IsNotFound(err) {
err = r.Create(ctx, pc)
if err != nil {
logger.Error(err, "Failed to create PriorityClass", "PriorityClass.Name", nodesensor.Spec.Node.PriorityClass.Name)
return err
}
} else if err != nil {
logger.Error(err, "Failed to get FalconNodeSensor ResourceQuota")
return err
}

if nodesensor.Spec.Node.PriorityClass.Value != nil && existingPC.Value != *nodesensor.Spec.Node.PriorityClass.Value {
update = true
}

if nodesensor.Spec.Node.PriorityClass.Name != "" && existingPC.Name != nodesensor.Spec.Node.PriorityClass.Name {
update = true
}

if update {
err = r.Update(ctx, existingPC)
if err != nil {
return err
}
}

return nil
}

// handleConfigMaps creates and updates the node sensor configmap
func (r *FalconNodeSensorReconciler) handleConfigMaps(ctx context.Context, config *node.ConfigCache, nodesensor *falconv1alpha1.FalconNodeSensor, logger logr.Logger) (*corev1.ConfigMap, bool, error) {
var updated bool
Expand Down
Loading

0 comments on commit 1def93a

Please sign in to comment.