mirror of
https://github.com/intel/intel-device-plugins-for-kubernetes.git
synced 2025-06-03 03:59:37 +00:00
Merge pull request #753 from hj-johannes-lee/dlb-operator
operator: Add DLB support
This commit is contained in:
commit
471549c11d
@ -30,6 +30,7 @@ import (
|
|||||||
|
|
||||||
devicepluginv1 "github.com/intel/intel-device-plugins-for-kubernetes/pkg/apis/deviceplugin/v1"
|
devicepluginv1 "github.com/intel/intel-device-plugins-for-kubernetes/pkg/apis/deviceplugin/v1"
|
||||||
fpgav2 "github.com/intel/intel-device-plugins-for-kubernetes/pkg/apis/fpga/v2"
|
fpgav2 "github.com/intel/intel-device-plugins-for-kubernetes/pkg/apis/fpga/v2"
|
||||||
|
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers/dlb"
|
||||||
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers/dsa"
|
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers/dsa"
|
||||||
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers/fpga"
|
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers/fpga"
|
||||||
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers/gpu"
|
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers/gpu"
|
||||||
@ -58,7 +59,7 @@ type devicePluginControllerAndWebhook map[string](func(ctrl.Manager, string, boo
|
|||||||
|
|
||||||
type flagList []string
|
type flagList []string
|
||||||
|
|
||||||
var supportedDevices = flagList{"dsa", "fpga", "gpu", "qat", "sgx"}
|
var supportedDevices = flagList{"dsa", "dlb", "fpga", "gpu", "qat", "sgx"}
|
||||||
var devices flagList
|
var devices flagList
|
||||||
|
|
||||||
func (flag *flagList) String() string {
|
func (flag *flagList) String() string {
|
||||||
@ -110,6 +111,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupControllerAndWebhook := devicePluginControllerAndWebhook{
|
setupControllerAndWebhook := devicePluginControllerAndWebhook{
|
||||||
|
"dlb": dlb.SetupReconciler,
|
||||||
"dsa": dsa.SetupReconciler,
|
"dsa": dsa.SetupReconciler,
|
||||||
"gpu": gpu.SetupReconciler,
|
"gpu": gpu.SetupReconciler,
|
||||||
"fpga": fpga.SetupReconciler,
|
"fpga": fpga.SetupReconciler,
|
||||||
|
@ -24,6 +24,7 @@ spec:
|
|||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
securityContext:
|
securityContext:
|
||||||
readOnlyRootFilesystem: true
|
readOnlyRootFilesystem: true
|
||||||
|
terminationMessagePath: /tmp/termination-log
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: devfs
|
- name: devfs
|
||||||
mountPath: /dev
|
mountPath: /dev
|
||||||
|
@ -0,0 +1,140 @@
|
|||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.7.0
|
||||||
|
creationTimestamp: null
|
||||||
|
name: dlbdeviceplugins.deviceplugin.intel.com
|
||||||
|
spec:
|
||||||
|
group: deviceplugin.intel.com
|
||||||
|
names:
|
||||||
|
kind: DlbDevicePlugin
|
||||||
|
listKind: DlbDevicePluginList
|
||||||
|
plural: dlbdeviceplugins
|
||||||
|
singular: dlbdeviceplugin
|
||||||
|
scope: Cluster
|
||||||
|
versions:
|
||||||
|
- additionalPrinterColumns:
|
||||||
|
- jsonPath: .status.desiredNumberScheduled
|
||||||
|
name: Desired
|
||||||
|
type: integer
|
||||||
|
- jsonPath: .status.numberReady
|
||||||
|
name: Ready
|
||||||
|
type: integer
|
||||||
|
- jsonPath: .spec.nodeSelector
|
||||||
|
name: Node Selector
|
||||||
|
type: string
|
||||||
|
- jsonPath: .metadata.creationTimestamp
|
||||||
|
name: Age
|
||||||
|
type: date
|
||||||
|
name: v1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: DlbDevicePlugin is the Schema for the dlbdeviceplugins API. It
|
||||||
|
represents the DLB device plugin responsible for advertising Intel DLB hardware
|
||||||
|
resources to the kubelet.
|
||||||
|
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: DlbDevicePluginSpec defines the desired state of DlbDevicePlugin.
|
||||||
|
properties:
|
||||||
|
image:
|
||||||
|
description: Image is a container image with DLB device plugin executable.
|
||||||
|
type: string
|
||||||
|
logLevel:
|
||||||
|
description: LogLevel sets the plugin's log level.
|
||||||
|
minimum: 0
|
||||||
|
type: integer
|
||||||
|
nodeSelector:
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
description: NodeSelector provides a simple way to constrain device
|
||||||
|
plugin pods to nodes with particular labels.
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: DlbDevicePluginStatus defines the observed state of DlbDevicePlugin.
|
||||||
|
properties:
|
||||||
|
controlledDaemonSet:
|
||||||
|
description: ControlledDaemoSet references the DaemonSet controlled
|
||||||
|
by the operator.
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: API version of the referent.
|
||||||
|
type: string
|
||||||
|
fieldPath:
|
||||||
|
description: 'If referring to a piece of an object instead of
|
||||||
|
an entire object, this string should contain a valid JSON/Go
|
||||||
|
field access statement, such as desiredState.manifest.containers[2].
|
||||||
|
For example, if the object reference is to a container within
|
||||||
|
a pod, this would take on a value like: "spec.containers{name}"
|
||||||
|
(where "name" refers to the name of the container that triggered
|
||||||
|
the event) or if no container name is specified "spec.containers[2]"
|
||||||
|
(container with index 2 in this pod). This syntax is chosen
|
||||||
|
only to have some well-defined way of referencing a part of
|
||||||
|
an object. TODO: this design is not final and this field is
|
||||||
|
subject to change in the future.'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
|
||||||
|
type: string
|
||||||
|
namespace:
|
||||||
|
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
|
||||||
|
type: string
|
||||||
|
resourceVersion:
|
||||||
|
description: 'Specific resourceVersion to which this reference
|
||||||
|
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
|
||||||
|
type: string
|
||||||
|
uid:
|
||||||
|
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
desiredNumberScheduled:
|
||||||
|
description: The total number of nodes that should be running the
|
||||||
|
device plugin pod (including nodes correctly running the device
|
||||||
|
plugin pod).
|
||||||
|
format: int32
|
||||||
|
type: integer
|
||||||
|
nodeNames:
|
||||||
|
description: The list of Node names where the device plugin pods are
|
||||||
|
running.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
numberReady:
|
||||||
|
description: The number of nodes that should be running the device
|
||||||
|
plugin pod and have one or more of the device plugin pod running
|
||||||
|
and ready.
|
||||||
|
format: int32
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- desiredNumberScheduled
|
||||||
|
- numberReady
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
@ -7,6 +7,7 @@ resources:
|
|||||||
- bases/deviceplugin.intel.com_fpgadeviceplugins.yaml
|
- bases/deviceplugin.intel.com_fpgadeviceplugins.yaml
|
||||||
- bases/deviceplugin.intel.com_sgxdeviceplugins.yaml
|
- bases/deviceplugin.intel.com_sgxdeviceplugins.yaml
|
||||||
- bases/deviceplugin.intel.com_dsadeviceplugins.yaml
|
- bases/deviceplugin.intel.com_dsadeviceplugins.yaml
|
||||||
|
- bases/deviceplugin.intel.com_dlbdeviceplugins.yaml
|
||||||
- bases/fpga.intel.com_acceleratorfunctions.yaml
|
- bases/fpga.intel.com_acceleratorfunctions.yaml
|
||||||
- bases/fpga.intel.com_fpgaregions.yaml
|
- bases/fpga.intel.com_fpgaregions.yaml
|
||||||
# +kubebuilder:scaffold:crdkustomizeresource
|
# +kubebuilder:scaffold:crdkustomizeresource
|
||||||
|
14
deployments/operator/device/dlb/dlb.yaml
Normal file
14
deployments/operator/device/dlb/dlb.yaml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: inteldeviceplugins-controller-manager
|
||||||
|
namespace: inteldeviceplugins-system
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- args:
|
||||||
|
- --metrics-addr=127.0.0.1:8080
|
||||||
|
- --enable-leader-election
|
||||||
|
- --devices=dlb
|
||||||
|
name: manager
|
5
deployments/operator/device/dlb/kustomization.yaml
Normal file
5
deployments/operator/device/dlb/kustomization.yaml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
bases:
|
||||||
|
- ../../default
|
||||||
|
|
||||||
|
patchesStrategicMerge:
|
||||||
|
- dlb.yaml
|
File diff suppressed because one or more lines are too long
@ -51,6 +51,26 @@ rules:
|
|||||||
verbs:
|
verbs:
|
||||||
- get
|
- get
|
||||||
- update
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- deviceplugin.intel.com
|
||||||
|
resources:
|
||||||
|
- dlbdeviceplugins
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- deviceplugin.intel.com
|
||||||
|
resources:
|
||||||
|
- dlbdeviceplugins/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- deviceplugin.intel.com
|
- deviceplugin.intel.com
|
||||||
resources:
|
resources:
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: deviceplugin.intel.com/v1
|
||||||
|
kind: DlbDevicePlugin
|
||||||
|
metadata:
|
||||||
|
name: dlbdeviceplugin-sample
|
||||||
|
# example apparmor annotation
|
||||||
|
# see more details here:
|
||||||
|
# - https://kubernetes.io/docs/tutorials/clusters/apparmor/#securing-a-pod
|
||||||
|
# - https://github.com/intel/intel-device-plugins-for-kubernetes/issues/381
|
||||||
|
# annotations:
|
||||||
|
# container.apparmor.security.beta.kubernetes.io/intel-dlb-plugin: unconfined
|
||||||
|
spec:
|
||||||
|
image: intel/intel-dlb-plugin:0.22.0
|
||||||
|
logLevel: 4
|
||||||
|
nodeSelector:
|
||||||
|
feature.node.kubernetes.io/dlb: 'true'
|
@ -4,4 +4,5 @@ resources:
|
|||||||
- deviceplugin_v1_gpudeviceplugin.yaml
|
- deviceplugin_v1_gpudeviceplugin.yaml
|
||||||
- deviceplugin_v1_qatdeviceplugin.yaml
|
- deviceplugin_v1_qatdeviceplugin.yaml
|
||||||
- deviceplugin_v1_sgxdeviceplugin.yaml
|
- deviceplugin_v1_sgxdeviceplugin.yaml
|
||||||
|
- deviceplugin_v1_dlbdeviceplugin.yaml
|
||||||
- mappings-collection.yaml
|
- mappings-collection.yaml
|
||||||
|
@ -6,6 +6,26 @@ metadata:
|
|||||||
creationTimestamp: null
|
creationTimestamp: null
|
||||||
name: mutating-webhook-configuration
|
name: mutating-webhook-configuration
|
||||||
webhooks:
|
webhooks:
|
||||||
|
- admissionReviewVersions:
|
||||||
|
- v1
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
name: webhook-service
|
||||||
|
namespace: system
|
||||||
|
path: /mutate-deviceplugin-intel-com-v1-dlbdeviceplugin
|
||||||
|
failurePolicy: Fail
|
||||||
|
name: mdlbdeviceplugin.kb.io
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- deviceplugin.intel.com
|
||||||
|
apiVersions:
|
||||||
|
- v1
|
||||||
|
operations:
|
||||||
|
- CREATE
|
||||||
|
- UPDATE
|
||||||
|
resources:
|
||||||
|
- dlbdeviceplugins
|
||||||
|
sideEffects: None
|
||||||
- admissionReviewVersions:
|
- admissionReviewVersions:
|
||||||
- v1
|
- v1
|
||||||
clientConfig:
|
clientConfig:
|
||||||
@ -155,6 +175,26 @@ metadata:
|
|||||||
creationTimestamp: null
|
creationTimestamp: null
|
||||||
name: validating-webhook-configuration
|
name: validating-webhook-configuration
|
||||||
webhooks:
|
webhooks:
|
||||||
|
- admissionReviewVersions:
|
||||||
|
- v1
|
||||||
|
clientConfig:
|
||||||
|
service:
|
||||||
|
name: webhook-service
|
||||||
|
namespace: system
|
||||||
|
path: /validate-deviceplugin-intel-com-v1-dlbdeviceplugin
|
||||||
|
failurePolicy: Fail
|
||||||
|
name: vdlbdeviceplugin.kb.io
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- deviceplugin.intel.com
|
||||||
|
apiVersions:
|
||||||
|
- v1
|
||||||
|
operations:
|
||||||
|
- CREATE
|
||||||
|
- UPDATE
|
||||||
|
resources:
|
||||||
|
- dlbdeviceplugins
|
||||||
|
sideEffects: None
|
||||||
- admissionReviewVersions:
|
- admissionReviewVersions:
|
||||||
- v1
|
- v1
|
||||||
clientConfig:
|
clientConfig:
|
||||||
|
92
pkg/apis/deviceplugin/v1/dlbdeviceplugin_types.go
Normal file
92
pkg/apis/deviceplugin/v1/dlbdeviceplugin_types.go
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
// Copyright 2020-2021 Intel Corporation. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||||
|
|
||||||
|
// DlbDevicePluginSpec defines the desired state of DlbDevicePlugin.
|
||||||
|
type DlbDevicePluginSpec struct {
|
||||||
|
// Important: Run "make generate" to regenerate code after modifying this file
|
||||||
|
|
||||||
|
// NodeSelector provides a simple way to constrain device plugin pods to nodes with particular labels.
|
||||||
|
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
|
||||||
|
|
||||||
|
// Image is a container image with DLB device plugin executable.
|
||||||
|
Image string `json:"image,omitempty"`
|
||||||
|
|
||||||
|
// LogLevel sets the plugin's log level.
|
||||||
|
// +kubebuilder:validation:Minimum=0
|
||||||
|
LogLevel int `json:"logLevel,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DlbDevicePluginStatus defines the observed state of DlbDevicePlugin.
|
||||||
|
type DlbDevicePluginStatus struct {
|
||||||
|
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
||||||
|
// Important: Run "make generate" to regenerate code after modifying this file
|
||||||
|
|
||||||
|
// ControlledDaemoSet references the DaemonSet controlled by the operator.
|
||||||
|
// +optional
|
||||||
|
ControlledDaemonSet v1.ObjectReference `json:"controlledDaemonSet,omitempty"`
|
||||||
|
|
||||||
|
// The list of Node names where the device plugin pods are running.
|
||||||
|
// +optional
|
||||||
|
NodeNames []string `json:"nodeNames,omitempty"`
|
||||||
|
|
||||||
|
// The total number of nodes that should be running the device plugin
|
||||||
|
// pod (including nodes correctly running the device plugin pod).
|
||||||
|
DesiredNumberScheduled int32 `json:"desiredNumberScheduled"`
|
||||||
|
|
||||||
|
// The number of nodes that should be running the device plugin pod and have one
|
||||||
|
// or more of the device plugin pod running and ready.
|
||||||
|
NumberReady int32 `json:"numberReady"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:object:root=true
|
||||||
|
// +kubebuilder:resource:path=dlbdeviceplugins,scope=Cluster
|
||||||
|
// +kubebuilder:subresource:status
|
||||||
|
// +kubebuilder:printcolumn:name="Desired",type=integer,JSONPath=`.status.desiredNumberScheduled`
|
||||||
|
// +kubebuilder:printcolumn:name="Ready",type=integer,JSONPath=`.status.numberReady`
|
||||||
|
// +kubebuilder:printcolumn:name="Node Selector",type=string,JSONPath=`.spec.nodeSelector`
|
||||||
|
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
|
||||||
|
// +operator-sdk:csv:customresourcedefinitions:displayName="Intel DLB Device Plugin"
|
||||||
|
|
||||||
|
// DlbDevicePlugin is the Schema for the dlbdeviceplugins API. It represents
|
||||||
|
// the DLB device plugin responsible for advertising Intel DLB hardware resources to
|
||||||
|
// the kubelet.
|
||||||
|
type DlbDevicePlugin struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
|
Spec DlbDevicePluginSpec `json:"spec,omitempty"`
|
||||||
|
Status DlbDevicePluginStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:object:root=true
|
||||||
|
|
||||||
|
// DlbDevicePluginList contains a list of DlbDevicePlugin.
|
||||||
|
type DlbDevicePluginList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ListMeta `json:"metadata,omitempty"`
|
||||||
|
Items []DlbDevicePlugin `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SchemeBuilder.Register(&DlbDevicePlugin{}, &DlbDevicePluginList{})
|
||||||
|
}
|
90
pkg/apis/deviceplugin/v1/dlbdeviceplugin_webhook.go
Normal file
90
pkg/apis/deviceplugin/v1/dlbdeviceplugin_webhook.go
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// Copyright 2020 Intel Corporation. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
|
ctrl "sigs.k8s.io/controller-runtime"
|
||||||
|
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/webhook"
|
||||||
|
|
||||||
|
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
dlbPluginKind = "DlbDevicePlugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// dlbdevicepluginlog is for logging in this package.
|
||||||
|
dlbdevicepluginlog = logf.Log.WithName("dlbdeviceplugin-resource")
|
||||||
|
|
||||||
|
dlbMinVersion = version.MustParseSemantic(imageMinVersion)
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetupWebhookWithManager sets up a webhook for DlbDevicePlugin custom resources.
|
||||||
|
func (r *DlbDevicePlugin) SetupWebhookWithManager(mgr ctrl.Manager) error {
|
||||||
|
return ctrl.NewWebhookManagedBy(mgr).
|
||||||
|
For(r).
|
||||||
|
Complete()
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:webhook:path=/mutate-deviceplugin-intel-com-v1-dlbdeviceplugin,mutating=true,failurePolicy=fail,groups=deviceplugin.intel.com,resources=dlbdeviceplugins,verbs=create;update,versions=v1,name=mdlbdeviceplugin.kb.io,sideEffects=None,admissionReviewVersions=v1
|
||||||
|
|
||||||
|
var _ webhook.Defaulter = &DlbDevicePlugin{}
|
||||||
|
|
||||||
|
// Default implements webhook.Defaulter so a webhook will be registered for the type.
|
||||||
|
func (r *DlbDevicePlugin) Default() {
|
||||||
|
dlbdevicepluginlog.Info("default", "name", r.Name)
|
||||||
|
|
||||||
|
if len(r.Spec.Image) == 0 {
|
||||||
|
r.Spec.Image = "intel/intel-dlb-plugin:" + dlbMinVersion.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:webhook:verbs=create;update,path=/validate-deviceplugin-intel-com-v1-dlbdeviceplugin,mutating=false,failurePolicy=fail,groups=deviceplugin.intel.com,resources=dlbdeviceplugins,versions=v1,name=vdlbdeviceplugin.kb.io,sideEffects=None,admissionReviewVersions=v1
|
||||||
|
|
||||||
|
var _ webhook.Validator = &DlbDevicePlugin{}
|
||||||
|
|
||||||
|
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
|
||||||
|
func (r *DlbDevicePlugin) ValidateCreate() error {
|
||||||
|
dlbdevicepluginlog.Info("validate create", "name", r.Name)
|
||||||
|
|
||||||
|
if controllers.GetDevicePluginCount(dlbPluginKind) > 0 {
|
||||||
|
return errors.Errorf("an instance of %q already exists in the cluster", dlbPluginKind)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.validatePlugin()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
|
||||||
|
func (r *DlbDevicePlugin) ValidateUpdate(old runtime.Object) error {
|
||||||
|
dlbdevicepluginlog.Info("validate update", "name", r.Name)
|
||||||
|
|
||||||
|
return r.validatePlugin()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
|
||||||
|
func (r *DlbDevicePlugin) ValidateDelete() error {
|
||||||
|
dlbdevicepluginlog.Info("validate delete", "name", r.Name)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *DlbDevicePlugin) validatePlugin() error {
|
||||||
|
return validatePluginImage(r.Spec.Image, "intel-dlb-plugin", dlbMinVersion)
|
||||||
|
}
|
@ -23,6 +23,108 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/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 *DlbDevicePlugin) DeepCopyInto(out *DlbDevicePlugin) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
|
in.Spec.DeepCopyInto(&out.Spec)
|
||||||
|
in.Status.DeepCopyInto(&out.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DlbDevicePlugin.
|
||||||
|
func (in *DlbDevicePlugin) DeepCopy() *DlbDevicePlugin {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(DlbDevicePlugin)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *DlbDevicePlugin) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *DlbDevicePluginList) DeepCopyInto(out *DlbDevicePluginList) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
|
if in.Items != nil {
|
||||||
|
in, out := &in.Items, &out.Items
|
||||||
|
*out = make([]DlbDevicePlugin, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DlbDevicePluginList.
|
||||||
|
func (in *DlbDevicePluginList) DeepCopy() *DlbDevicePluginList {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(DlbDevicePluginList)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *DlbDevicePluginList) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *DlbDevicePluginSpec) DeepCopyInto(out *DlbDevicePluginSpec) {
|
||||||
|
*out = *in
|
||||||
|
if in.NodeSelector != nil {
|
||||||
|
in, out := &in.NodeSelector, &out.NodeSelector
|
||||||
|
*out = make(map[string]string, len(*in))
|
||||||
|
for key, val := range *in {
|
||||||
|
(*out)[key] = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DlbDevicePluginSpec.
|
||||||
|
func (in *DlbDevicePluginSpec) DeepCopy() *DlbDevicePluginSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(DlbDevicePluginSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *DlbDevicePluginStatus) DeepCopyInto(out *DlbDevicePluginStatus) {
|
||||||
|
*out = *in
|
||||||
|
out.ControlledDaemonSet = in.ControlledDaemonSet
|
||||||
|
if in.NodeNames != nil {
|
||||||
|
in, out := &in.NodeNames, &out.NodeNames
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DlbDevicePluginStatus.
|
||||||
|
func (in *DlbDevicePluginStatus) DeepCopy() *DlbDevicePluginStatus {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(DlbDevicePluginStatus)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *DsaDevicePlugin) DeepCopyInto(out *DsaDevicePlugin) {
|
func (in *DsaDevicePlugin) DeepCopyInto(out *DsaDevicePlugin) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
235
pkg/controllers/dlb/controller.go
Normal file
235
pkg/controllers/dlb/controller.go
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
// Copyright 2020 Intel Corporation. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Package dlb contains DLB specific reconciliation logic.
|
||||||
|
package dlb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
apps "k8s.io/api/apps/v1"
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/client-go/tools/reference"
|
||||||
|
ctrl "sigs.k8s.io/controller-runtime"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
|
||||||
|
devicepluginv1 "github.com/intel/intel-device-plugins-for-kubernetes/pkg/apis/deviceplugin/v1"
|
||||||
|
"github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ownerKey = ".metadata.controller.dlb"
|
||||||
|
appLabel = "intel-dlb-plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// +kubebuilder:rbac:groups=deviceplugin.intel.com,resources=dlbdeviceplugins,verbs=get;list;watch;create;update;patch;delete
|
||||||
|
// +kubebuilder:rbac:groups=deviceplugin.intel.com,resources=dlbdeviceplugins/status,verbs=get;update;patch
|
||||||
|
|
||||||
|
// SetupReconciler creates a new reconciler for DlbDevicePlugin objects.
|
||||||
|
func SetupReconciler(mgr ctrl.Manager, namespace string, withWebhook bool) error {
|
||||||
|
c := &controller{scheme: mgr.GetScheme(), ns: namespace}
|
||||||
|
if err := controllers.SetupWithManager(mgr, c, devicepluginv1.GroupVersion.String(), "DlbDevicePlugin", ownerKey); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if withWebhook {
|
||||||
|
return (&devicepluginv1.DlbDevicePlugin{}).SetupWebhookWithManager(mgr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type controller struct {
|
||||||
|
controllers.DefaultServiceAccountFactory
|
||||||
|
scheme *runtime.Scheme
|
||||||
|
ns string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) CreateEmptyObject() client.Object {
|
||||||
|
return &devicepluginv1.DlbDevicePlugin{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) GetTotalObjectCount(ctx context.Context, clnt client.Client) (int, error) {
|
||||||
|
var list devicepluginv1.DlbDevicePluginList
|
||||||
|
if err := clnt.List(ctx, &list); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(list.Items), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) NewDaemonSet(rawObj client.Object) *apps.DaemonSet {
|
||||||
|
devicePlugin := rawObj.(*devicepluginv1.DlbDevicePlugin)
|
||||||
|
yes := true
|
||||||
|
|
||||||
|
var nodeSelector map[string]string
|
||||||
|
|
||||||
|
daemonSet := apps.DaemonSet{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: c.ns,
|
||||||
|
GenerateName: devicePlugin.Name + "-",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": appLabel,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: apps.DaemonSetSpec{
|
||||||
|
Selector: &metav1.LabelSelector{
|
||||||
|
MatchLabels: map[string]string{
|
||||||
|
"app": appLabel,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Template: v1.PodTemplateSpec{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": appLabel,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{
|
||||||
|
{
|
||||||
|
Name: appLabel,
|
||||||
|
Env: []v1.EnvVar{
|
||||||
|
{
|
||||||
|
Name: "NODE_NAME",
|
||||||
|
ValueFrom: &v1.EnvVarSource{
|
||||||
|
FieldRef: &v1.ObjectFieldSelector{
|
||||||
|
FieldPath: "spec.nodeName",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TerminationMessagePath: "/tmp/termination-log",
|
||||||
|
Args: getPodArgs(devicePlugin),
|
||||||
|
Image: devicePlugin.Spec.Image,
|
||||||
|
ImagePullPolicy: "IfNotPresent",
|
||||||
|
SecurityContext: &v1.SecurityContext{
|
||||||
|
ReadOnlyRootFilesystem: &yes,
|
||||||
|
},
|
||||||
|
VolumeMounts: []v1.VolumeMount{
|
||||||
|
{
|
||||||
|
Name: "devfs",
|
||||||
|
MountPath: "/dev",
|
||||||
|
ReadOnly: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "sysfs",
|
||||||
|
MountPath: "/sys/class/dlb2",
|
||||||
|
ReadOnly: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "kubeletsockets",
|
||||||
|
MountPath: "/var/lib/kubelet/device-plugins",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
NodeSelector: nodeSelector,
|
||||||
|
Volumes: []v1.Volume{
|
||||||
|
{
|
||||||
|
Name: "devfs",
|
||||||
|
VolumeSource: v1.VolumeSource{
|
||||||
|
HostPath: &v1.HostPathVolumeSource{
|
||||||
|
Path: "/dev",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "sysfs",
|
||||||
|
VolumeSource: v1.VolumeSource{
|
||||||
|
HostPath: &v1.HostPathVolumeSource{
|
||||||
|
Path: "/sys/class/dlb2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "kubeletsockets",
|
||||||
|
VolumeSource: v1.VolumeSource{
|
||||||
|
HostPath: &v1.HostPathVolumeSource{
|
||||||
|
Path: "/var/lib/kubelet/device-plugins",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return &daemonSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) UpdateDaemonSet(rawObj client.Object, ds *apps.DaemonSet) (updated bool) {
|
||||||
|
dp := rawObj.(*devicepluginv1.DlbDevicePlugin)
|
||||||
|
|
||||||
|
if ds.Spec.Template.Spec.Containers[0].Image != dp.Spec.Image {
|
||||||
|
ds.Spec.Template.Spec.Containers[0].Image = dp.Spec.Image
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(ds.Spec.Template.Spec.NodeSelector, dp.Spec.NodeSelector) {
|
||||||
|
ds.Spec.Template.Spec.NodeSelector = dp.Spec.NodeSelector
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
|
||||||
|
newargs := getPodArgs(dp)
|
||||||
|
if strings.Join(ds.Spec.Template.Spec.Containers[0].Args, " ") != strings.Join(newargs, " ") {
|
||||||
|
ds.Spec.Template.Spec.Containers[0].Args = newargs
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return updated
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) UpdateStatus(rawObj client.Object, ds *apps.DaemonSet, nodeNames []string) (updated bool, err error) {
|
||||||
|
dp := rawObj.(*devicepluginv1.DlbDevicePlugin)
|
||||||
|
|
||||||
|
dsRef, err := reference.GetReference(c.scheme, ds)
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.Wrap(err, "unable to make reference to controlled daemon set")
|
||||||
|
}
|
||||||
|
|
||||||
|
if dp.Status.ControlledDaemonSet.UID != dsRef.UID {
|
||||||
|
dp.Status.ControlledDaemonSet = *dsRef
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if dp.Status.DesiredNumberScheduled != ds.Status.DesiredNumberScheduled {
|
||||||
|
dp.Status.DesiredNumberScheduled = ds.Status.DesiredNumberScheduled
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if dp.Status.NumberReady != ds.Status.NumberReady {
|
||||||
|
dp.Status.NumberReady = ds.Status.NumberReady
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Join(dp.Status.NodeNames, ",") != strings.Join(nodeNames, ",") {
|
||||||
|
dp.Status.NodeNames = nodeNames
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return updated, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPodArgs(gdp *devicepluginv1.DlbDevicePlugin) []string {
|
||||||
|
args := make([]string, 0, 4)
|
||||||
|
args = append(args, "-v", strconv.Itoa(gdp.Spec.LogLevel))
|
||||||
|
|
||||||
|
return args
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user