From 4ab020681f593265652930deeba17ea9c4674280 Mon Sep 17 00:00:00 2001 From: Feruzjon Muyassarov Date: Fri, 15 Dec 2023 14:51:22 +0200 Subject: [PATCH] operator: introduce nri-plugins operator Introduce an operator for life-cycle-management of NRI plugins. Users are expected to interact with the operator through NriPluginDeployment namespaced Custom Resource. Signed-off-by: Feruzjon Muyassarov Co-authored-by: Krisztian Litkey --- .gitignore | 1 + Makefile | 15 +- .../config.nri_nriplugindeployments.yaml | 999 ++++++++++++++++++ ...gy.node.k8s.io_noderesourcetopologies.yaml | 270 +++++ deployment/operator/Dockerfile | 15 + deployment/operator/Makefile | 237 +++++ deployment/operator/PROJECT | 19 + deployment/operator/README.md | 69 ++ deployment/operator/ansible.cfg | 5 + deployment/operator/bundle.Dockerfile | 20 + deployment/operator/categories.json | 7 + .../operator/config/crd/kustomization.yaml | 12 + .../config/default/kustomization.yaml | 30 + .../default/manager_auth_proxy_patch.yaml | 56 + .../config/default/manager_config_patch.yaml | 10 + .../config/manager/kustomization.yaml | 8 + .../operator/config/manager/manager.yaml | 104 ++ ...lugins-operator.clusterserviceversion.yaml | 105 ++ .../config/manifests/kustomization.yaml | 7 + .../rbac/auth_proxy_client_clusterrole.yaml | 16 + .../operator/config/rbac/auth_proxy_role.yaml | 24 + .../config/rbac/auth_proxy_role_binding.yaml | 19 + .../config/rbac/auth_proxy_service.yaml | 21 + ...g.nri_nriplugindeployment_editor_role.yaml | 31 + ...g.nri_nriplugindeployment_viewer_role.yaml | 27 + .../operator/config/rbac/kustomization.yaml | 18 + .../config/rbac/leader_election_role.yaml | 44 + .../rbac/leader_election_role_binding.yaml | 19 + deployment/operator/config/rbac/role.yaml | 54 + .../operator/config/rbac/role_binding.yaml | 19 + .../operator/config/rbac/service_account.yaml | 12 + ...nfig.nri_v1alpha1_nriplugindeployment.yaml | 19 + .../config/samples/kustomization.yaml | 9 + .../config/scorecard/bases/config.yaml | 7 + .../config/scorecard/kustomization.yaml | 16 + .../scorecard/patches/basic.config.yaml | 10 + .../config/scorecard/patches/olm.config.yaml | 50 + .../operator/playbooks/plugin-deployment.yml | 9 + deployment/operator/requirements.yml | 10 + .../roles/plugin-deployment/tasks/main.yml | 32 + deployment/operator/watches.yaml | 12 + docs/deployment/balloons.md | 2 - docs/deployment/helm/balloons.md | 2 + docs/deployment/helm/index.md | 14 + docs/deployment/helm/memory-qos.md | 2 + docs/deployment/helm/memtierd.md | 2 + docs/deployment/helm/sgx-epc.md | 2 + docs/deployment/helm/template.md | 2 + docs/deployment/helm/topology-aware.md | 2 + docs/deployment/index.md | 8 +- docs/deployment/memory-qos.md | 2 - docs/deployment/memtierd.md | 2 - docs/deployment/operator/index.md | 9 + docs/deployment/operator/operator.md | 2 + docs/deployment/sgx-epc.md | 2 - docs/deployment/template.md | 2 - docs/deployment/topology-aware.md | 2 - sample-configs/noderesourcetopology.yaml | 103 ++ 58 files changed, 2608 insertions(+), 19 deletions(-) create mode 100644 config/crd/bases/config.nri_nriplugindeployments.yaml create mode 100644 config/crd/bases/topology.node.k8s.io_noderesourcetopologies.yaml create mode 100644 deployment/operator/Dockerfile create mode 100644 deployment/operator/Makefile create mode 100644 deployment/operator/PROJECT create mode 100644 deployment/operator/README.md create mode 100644 deployment/operator/ansible.cfg create mode 100644 deployment/operator/bundle.Dockerfile create mode 100644 deployment/operator/categories.json create mode 100644 deployment/operator/config/crd/kustomization.yaml create mode 100644 deployment/operator/config/default/kustomization.yaml create mode 100644 deployment/operator/config/default/manager_auth_proxy_patch.yaml create mode 100644 deployment/operator/config/default/manager_config_patch.yaml create mode 100644 deployment/operator/config/manager/kustomization.yaml create mode 100644 deployment/operator/config/manager/manager.yaml create mode 100644 deployment/operator/config/manifests/bases/nri-plugins-operator.clusterserviceversion.yaml create mode 100644 deployment/operator/config/manifests/kustomization.yaml create mode 100644 deployment/operator/config/rbac/auth_proxy_client_clusterrole.yaml create mode 100644 deployment/operator/config/rbac/auth_proxy_role.yaml create mode 100644 deployment/operator/config/rbac/auth_proxy_role_binding.yaml create mode 100644 deployment/operator/config/rbac/auth_proxy_service.yaml create mode 100644 deployment/operator/config/rbac/config.nri_nriplugindeployment_editor_role.yaml create mode 100644 deployment/operator/config/rbac/config.nri_nriplugindeployment_viewer_role.yaml create mode 100644 deployment/operator/config/rbac/kustomization.yaml create mode 100644 deployment/operator/config/rbac/leader_election_role.yaml create mode 100644 deployment/operator/config/rbac/leader_election_role_binding.yaml create mode 100644 deployment/operator/config/rbac/role.yaml create mode 100644 deployment/operator/config/rbac/role_binding.yaml create mode 100644 deployment/operator/config/rbac/service_account.yaml create mode 100644 deployment/operator/config/samples/config.nri_v1alpha1_nriplugindeployment.yaml create mode 100644 deployment/operator/config/samples/kustomization.yaml create mode 100644 deployment/operator/config/scorecard/bases/config.yaml create mode 100644 deployment/operator/config/scorecard/kustomization.yaml create mode 100644 deployment/operator/config/scorecard/patches/basic.config.yaml create mode 100644 deployment/operator/config/scorecard/patches/olm.config.yaml create mode 100644 deployment/operator/playbooks/plugin-deployment.yml create mode 100644 deployment/operator/requirements.yml create mode 100644 deployment/operator/roles/plugin-deployment/tasks/main.yml create mode 100644 deployment/operator/watches.yaml delete mode 100644 docs/deployment/balloons.md create mode 100644 docs/deployment/helm/balloons.md create mode 100644 docs/deployment/helm/index.md create mode 100644 docs/deployment/helm/memory-qos.md create mode 100644 docs/deployment/helm/memtierd.md create mode 100644 docs/deployment/helm/sgx-epc.md create mode 100644 docs/deployment/helm/template.md create mode 100644 docs/deployment/helm/topology-aware.md delete mode 100644 docs/deployment/memory-qos.md delete mode 100644 docs/deployment/memtierd.md create mode 100644 docs/deployment/operator/index.md create mode 100644 docs/deployment/operator/operator.md delete mode 100644 docs/deployment/sgx-epc.md delete mode 100644 docs/deployment/template.md delete mode 100644 docs/deployment/topology-aware.md create mode 100644 sample-configs/noderesourcetopology.yaml diff --git a/.gitignore b/.gitignore index dfd1f8d06..0660de8f7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *_gendata.go /build +/deployment/operator/bundle/ /build-aux /generate coverage.html diff --git a/Makefile b/Makefile index 32ff13818..d09132552 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,9 @@ ifdef IMAGE_REPO override IMAGE_REPO := $(IMAGE_REPO)/ endif +export IMAGE_VERSION +export IMAGE_PATH + # Determine binary version and buildid. BUILD_VERSION := $(shell scripts/build/get-buildid --version --shell=no) BUILD_BUILDID := $(shell scripts/build/get-buildid --buildid --shell=no) @@ -207,7 +210,9 @@ $(BIN_PATH)/%: .static.%.$(STATIC) # images: $(foreach p,$(PLUGINS),image.$(p)) \ - $(foreach p,$(BINARIES),image.$(p)) + $(foreach p,$(BINARIES),image.$(p)) \ + nri-plugins-operator-image \ + nri-plugins-operator-bundle-image image.nri-resource-policy-% \ image.nri-% \ @@ -235,6 +240,14 @@ image.%: NRI_IMAGE_TAR=`realpath "$(IMAGE_PATH)/$${tag}-image-$${NRI_IMAGE_ID}.tar"`; \ $(DOCKER) image save "$${NRI_IMAGE_REPOTAG}" > "$${NRI_IMAGE_TAR}"; +nri-plugins-operator-image: + $(Q)mkdir -p $(IMAGE_PATH); \ + $(MAKE) -C deployment/operator image-save + +nri-plugins-operator-bundle-image: + $(Q)mkdir -p $(IMAGE_PATH); \ + $(MAKE) -C deployment/operator bundle-save + # # plugin build dependencies # diff --git a/config/crd/bases/config.nri_nriplugindeployments.yaml b/config/crd/bases/config.nri_nriplugindeployments.yaml new file mode 100644 index 000000000..ce9030c55 --- /dev/null +++ b/config/crd/bases/config.nri_nriplugindeployments.yaml @@ -0,0 +1,999 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: nriplugindeployments.config.nri +spec: + group: config.nri + names: + kind: NriPluginDeployment + listKind: NriPluginDeploymentList + plural: nriplugindeployments + singular: nriplugindeployment + shortNames: + - npd + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: NriPluginDeployment is the Schema for the nriplugindeployments 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: Spec defines the intended state of NriPluginDeployment + properties: + pluginName: + type: string + x-kubernetes-validations: + - message: pluginName is immutable + rule: self == oldSelf + enum: + - topology-aware + - balloons + - memtierd + - memory-qos + - sgx-epc + pluginVersion: + type: string + state: + type: string + enum: + - absent + - present + values: + description: values defines fields to manipulate plugin Helm chart default values + type: object + x-kubernetes-validations: + - message: values is immutable + rule: self == oldSelf + properties: + nodeSelector: + additionalProperties: + type: string + description: Define which Nodes the Pods are scheduled on. + type: object + hostPort: + type: integer + nri: + type: object + properties: + patchRuntimeConfig: + type: boolean + image: + type: object + description: image defines Plugin DeamonSet image name and tag + properties: + name: + type: string + pullPolicy: + type: string + enum: + - Always + - Never + - IfNotPresent + initContainerImage: + type: object + description: initContainerImage defines InitContainer image name and tag + properties: + name: + type: string + pullPolicy: + type: string + enum: + - Always + - Never + - IfNotPresent + affinity: + description: If specified, the pod's scheduling constraints. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the + pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the + highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to an update), the system may or may not try to + eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate + this pod in the same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may or may + not try to eventually evict the pod from its node. When + there are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all terms + must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. + avoid putting this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the anti-affinity expressions specified + by this field, but it may choose a node that violates one + or more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the anti-affinity requirements + specified by this field cease to be met at some point during + pod execution (e.g. due to a pod label update), the system + may or may not try to eventually evict the pod from its + node. When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, i.e. + all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + tolerations: + description: If specified, the pod's tolerations. + items: + description: Toleration represents the toleration object that can + be attached to a pod. The pod this Toleration is attached to tolerates + any taint that matches the triple using the + matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. + NoSchedule - do not allow new pods to schedule onto the node + unless they tolerate the taint, but allow all pods submitted + to Kubelet without going through the scheduler to start, and + allow all already-running pods to continue running.Enforced by + the scheduler. + PreferNoSchedule - like TaintEffectNoSchedule, but the scheduler + tries not to schedule new pods onto the node, rather than + prohibiting new pods from scheduling onto the node entirely. + Enforced by the scheduler. + NoExecute - evict any already-running pods that do not tolerate + the taint. Currently enforced by NodeController. + enum: + - NoSchedule + - PreferNoSchedule + - NoExecute + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match all + values and all keys. + type: string + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod + can tolerate all taints of a particular category. + enum: + - Exists + - Equal + type: string + "tolerationS\teconds": + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. By default, it + is not set, which means tolerate the taint forever (do not + evict). Zero and negative values will be treated as 0 (evict + immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + required: + - pluginName + - pluginVersion + - state + type: object + x-kubernetes-preserve-unknown-fields: true + status: + description: Status defines the observed state of NriPluginDeployment + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/topology.node.k8s.io_noderesourcetopologies.yaml b/config/crd/bases/topology.node.k8s.io_noderesourcetopologies.yaml new file mode 100644 index 000000000..3719f2c2d --- /dev/null +++ b/config/crd/bases/topology.node.k8s.io_noderesourcetopologies.yaml @@ -0,0 +1,270 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes/enhancements/pull/1870 + controller-gen.kubebuilder.io/version: v0.11.2 + creationTimestamp: null + name: noderesourcetopologies.topology.node.k8s.io +spec: + group: topology.node.k8s.io + names: + kind: NodeResourceTopology + listKind: NodeResourceTopologyList + plural: noderesourcetopologies + shortNames: + - node-res-topo + singular: noderesourcetopology + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: NodeResourceTopology describes node resources and their topology. + 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 + topologyPolicies: + items: + type: string + type: array + zones: + description: ZoneList contains an array of Zone objects. + items: + description: Zone represents a resource topology zone, e.g. socket, + node, die or core. + properties: + attributes: + description: AttributeList contains an array of AttributeInfo objects. + items: + description: AttributeInfo contains one attribute of a Zone. + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + costs: + description: CostList contains an array of CostInfo objects. + items: + description: CostInfo describes the cost (or distance) between + two Zones. + properties: + name: + type: string + value: + format: int64 + type: integer + required: + - name + - value + type: object + type: array + name: + type: string + parent: + type: string + resources: + description: ResourceInfoList contains an array of ResourceInfo + objects. + items: + description: ResourceInfo contains information about one resource + type. + properties: + allocatable: + anyOf: + - type: integer + - type: string + description: Allocatable quantity of the resource, corresponding + to allocatable in node status, i.e. total amount of this + resource available to be used by pods. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + available: + anyOf: + - type: integer + - type: string + description: Available is the amount of this resource currently + available for new (to be scheduled) pods, i.e. Allocatable + minus the resources reserved by currently running pods. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + capacity: + anyOf: + - type: integer + - type: string + description: Capacity of the resource, corresponding to capacity + in node status, i.e. total amount of this resource that + the node has. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + name: + description: Name of the resource. + type: string + required: + - allocatable + - available + - capacity + - name + type: object + type: array + type: + type: string + required: + - name + - type + type: object + type: array + required: + - topologyPolicies + - zones + type: object + served: true + storage: false + - name: v1alpha2 + schema: + openAPIV3Schema: + description: NodeResourceTopology describes node resources and their topology. + 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 + attributes: + description: AttributeList contains an array of AttributeInfo objects. + items: + description: AttributeInfo contains one attribute of a Zone. + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + 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 + topologyPolicies: + description: 'DEPRECATED (to be removed in v1beta1): use top level attributes + if needed' + items: + type: string + type: array + zones: + description: ZoneList contains an array of Zone objects. + items: + description: Zone represents a resource topology zone, e.g. socket, + node, die or core. + properties: + attributes: + description: AttributeList contains an array of AttributeInfo objects. + items: + description: AttributeInfo contains one attribute of a Zone. + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + costs: + description: CostList contains an array of CostInfo objects. + items: + description: CostInfo describes the cost (or distance) between + two Zones. + properties: + name: + type: string + value: + format: int64 + type: integer + required: + - name + - value + type: object + type: array + name: + type: string + parent: + type: string + resources: + description: ResourceInfoList contains an array of ResourceInfo + objects. + items: + description: ResourceInfo contains information about one resource + type. + properties: + allocatable: + anyOf: + - type: integer + - type: string + description: Allocatable quantity of the resource, corresponding + to allocatable in node status, i.e. total amount of this + resource available to be used by pods. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + available: + anyOf: + - type: integer + - type: string + description: Available is the amount of this resource currently + available for new (to be scheduled) pods, i.e. Allocatable + minus the resources reserved by currently running pods. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + capacity: + anyOf: + - type: integer + - type: string + description: Capacity of the resource, corresponding to capacity + in node status, i.e. total amount of this resource that + the node has. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + name: + description: Name of the resource. + type: string + required: + - allocatable + - available + - capacity + - name + type: object + type: array + type: + type: string + required: + - name + - type + type: object + type: array + required: + - zones + type: object + served: true + storage: true diff --git a/deployment/operator/Dockerfile b/deployment/operator/Dockerfile new file mode 100644 index 000000000..7fe071731 --- /dev/null +++ b/deployment/operator/Dockerfile @@ -0,0 +1,15 @@ +FROM fedora:latest as build +ENV VERIFY_CHECKSUM=false +RUN curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 \ + && chmod 700 get_helm.sh && ./get_helm.sh + +FROM quay.io/operator-framework/ansible-operator:v1.32.0 +COPY --from=build /usr/local/bin/helm /usr/local/bin/helm +COPY requirements.yml ${HOME}/requirements.yml +RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \ + && chmod -R ug+rwx ${HOME}/.ansible + +COPY watches.yaml ${HOME}/watches.yaml +COPY ansible.cfg /etc/ansible/ansible.cfg +COPY roles/ ${HOME}/roles/ +COPY playbooks/ ${HOME}/playbooks/ diff --git a/deployment/operator/Makefile b/deployment/operator/Makefile new file mode 100644 index 000000000..91f82bebc --- /dev/null +++ b/deployment/operator/Makefile @@ -0,0 +1,237 @@ +SHELL := /bin/bash + +# Default image version (tag) and image save path. +IMAGE_VERSION ?= $(shell git describe --dirty 2> /dev/null) +IMAGE_PATH ?= . + +# VERSION defines the project version for the bundle. +# Update this value when you upgrade the version of your project. +# To re-generate a bundle for another specific version without changing the standard setup, you can: +# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) +# - use environment variables to overwrite this value (e.g export VERSION=0.0.2) +VERSION ?= $(shell echo $(IMAGE_VERSION) | sed 's/^v//') + +# CHANNELS define the bundle channels used in the bundle. +# Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable") +# To re-generate a bundle for other specific channels without changing the standard setup, you can: +# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=candidate,fast,stable) +# - use environment variables to overwrite this value (e.g export CHANNELS="candidate,fast,stable") +ifneq ($(origin CHANNELS), undefined) +BUNDLE_CHANNELS := --channels=$(CHANNELS) +endif + +# DEFAULT_CHANNEL defines the default channel used in the bundle. +# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable") +# To re-generate a bundle for any other default channel without changing the default setup, you can: +# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable) +# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL="stable") +ifneq ($(origin DEFAULT_CHANNEL), undefined) +BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) +endif +BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) + +# IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images. +# This variable is used to construct full image tags for bundle and catalog images. +# +# For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both +# ghcr.io/containers/nri-plugins-operator-bundle:$VERSION and ghcr.io/containers/nri-plugins-operator-catalog:$VERSION. +IMAGE_TAG_BASE ?= ghcr.io/containers/nri-plugins-operator + +# BUNDLE_IMG defines the image:tag used for the bundle. +# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=/:) +BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION) + +# BUNDLE_GEN_FLAGS are the flags passed to the operator-sdk generate bundle command +BUNDLE_GEN_FLAGS ?= -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) + +# USE_IMAGE_DIGESTS defines if images are resolved via tags or digests +# You can enable this value if you would like to use SHA Based Digests +# To enable set flag to true +USE_IMAGE_DIGESTS ?= false +ifeq ($(USE_IMAGE_DIGESTS), true) + BUNDLE_GEN_FLAGS += --use-image-digests +endif + +# Set the Operator SDK version to use. By default, what is installed on the system is used. +# This is useful for CI or a project to utilize a specific version of the operator-sdk toolkit. +OPERATOR_SDK_VERSION ?= v1.32.0 + +# Image URL to use all building/pushing image targets +IMG ?= $(IMAGE_TAG_BASE):$(IMAGE_VERSION) + +# (Default) operator image dockerfile and bundle image dockerfile. +DOCKERFILE ?= Dockerfile +BUNDLE_DOCKERFILE = bundle.Dockerfile + +CRD_SOURCE_DIR := ../../config/crd/bases +CRD_DEST_DIR := config/crd/bases +SAMPLE_SOURCE_DIR := ../../sample-configs +SAMPLE_DEST_DIR := config/samples + +.PHONY: all +all: docker-build + +##@ General + +.PHONY: help +help: ## Display this help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +.PHONY: ansible-operator +ANSIBLE_OPERATOR = $(shell pwd)/bin/ansible-operator +ansible-operator: ##Download ansible-operator locally if necessary, preferring the $(pwd)/bin path over global if both exist. +ifeq (,$(wildcard $(ANSIBLE_OPERATOR))) +ifeq (,$(shell which ansible-operator 2>/dev/null)) + @{ \ + set -e ;\ + mkdir -p $(dir $(ANSIBLE_OPERATOR)) ;\ + curl -sSLo $(ANSIBLE_OPERATOR) https://github.com/operator-framework/ansible-operator-plugins/releases/download/v1.32.0/ansible-operator_$(OS)_$(ARCH) ;\ + chmod +x $(ANSIBLE_OPERATOR) ;\ + } +else +ANSIBLE_OPERATOR = $(shell which ansible-operator) +endif +endif + +.PHONY: bundle +bundle: copy-crds kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files. + $(OPERATOR_SDK) generate kustomize manifests -q + cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) + $(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS) + OPERATOR_BUNDLE_CATEGORIES=categories.json $(OPERATOR_SDK) bundle validate ./bundle \ + --select-optional name=operatorhub \ + --select-optional suite=operatorframework \ + --select-optional name=good-practices \ + --select-optional suite=operatorframework; \ + $(MAKE) cleanup-crds; + +.PHONY: +docker-build: + docker build -f $(DOCKERFILE) -t ${IMG} . + +.PHONY: docker-push +docker-push: + docker push ${IMG} + +.PHONY: docker-save +docker-save: docker-build + @img_name="${IMG}"; \ + img_name="$${img_name##*/}"; \ + img_name="$${img_name%:*}"; \ + img_info=`docker images --filter=reference=${IMG} --format '{{.ID}} {{.Repository}}:{{.Tag}} (created {{.CreatedSince}}, {{.CreatedAt}})' | head -n 1`; \ + img_id=`awk '{print $$1}' <<< "$${img_info}"`; \ + img_tag=`awk '{print $$2}' <<< "$${img_info}"`; \ + img_tar=`realpath "$(IMAGE_PATH)/$${img_name}-image-$${img_id}.tar"`; \ + docker image save "$${img_tag}" > "$${img_tar}"; + +.PHONY: bundle-build +bundle-build: bundle ## Build the bundle image. + $(MAKE) DOCKERFILE=$(BUNDLE_DOCKERFILE) IMG=$(BUNDLE_IMG) docker-build + +.PHONY: bundle-push +bundle-push: ## Push the bundle image. + $(MAKE) docker-push IMG=$(BUNDLE_IMG) + +.PHONY: bundle-save ## Export the bundle image as a tarball. +bundle-save: bundle-build + $(MAKE) DOCKERFILE=$(BUNDLE_DOCKERFILE) IMG=$(BUNDLE_IMG) docker-save + +.PHONY: image-build +image-build: ## Build the operator image. + $(MAKE) docker-build + +.PHONY: image-push +image-push: ## Push the operator image. + $(MAKE) docker-push + +.PHONY: image-save +image-save: image-build ## Export the operator image as a tarball. + $(MAKE) docker-save + +# PLATFORMS defines the target platforms for the manager image be build to provide support to multiple +# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to: +# - able to use docker buildx . More info: https://docs.docker.com/build/buildx/ +# - have enable BuildKit, More info: https://docs.docker.com/develop/develop-images/build_enhancements/ +# - be able to push the image for your registry (i.e. if you do not inform a valid value via IMG=> than the export will fail) +# To properly provided solutions that supports more than one platform you should use this option. +PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le +.PHONY: docker-buildx +docker-buildx: ## Build and push docker image for the manager for cross-platform support + # copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile + sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross + - docker buildx create --name project-v3-builder + docker buildx use project-v3-builder + - docker buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross . + - docker buildx rm project-v3-builder + rm Dockerfile.cross + +.PHONY: install +install: copy-crds kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. + $(KUSTOMIZE) build config/crd | kubectl apply -f - + $(MAKE) cleanup-crds + +.PHONY: uninstall +uninstall: copy-crds kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. + $(KUSTOMIZE) build config/crd | kubectl delete -f - + $(MAKE) cleanup-crds + +.PHONY: deploy +deploy: kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config. + cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} + $(KUSTOMIZE) build config/default | kubectl apply -f - + +.PHONY: undeploy +undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. + $(KUSTOMIZE) build config/default | kubectl delete -f - + +OS := $(shell uname -s | tr '[:upper:]' '[:lower:]') +ARCH := $(shell uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/') + +.PHONY: kustomize +KUSTOMIZE = $(shell pwd)/bin/kustomize +kustomize: ## Download kustomize locally if necessary. +ifeq (,$(wildcard $(KUSTOMIZE))) +ifeq (,$(shell which kustomize 2>/dev/null)) + @{ \ + set -e ;\ + mkdir -p $(dir $(KUSTOMIZE)) ;\ + curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v4.5.7/kustomize_v4.5.7_$(OS)_$(ARCH).tar.gz | \ + tar xzf - -C bin/ ;\ + } +else +KUSTOMIZE = $(shell which kustomize) +endif +endif + +.PHONY: operator-sdk +OPERATOR_SDK ?= ./bin/operator-sdk +operator-sdk: ## Download operator-sdk locally if necessary. +ifeq (,$(wildcard $(OPERATOR_SDK))) +ifeq (, $(shell which operator-sdk 2>/dev/null)) + @{ \ + set -e ;\ + mkdir -p $(dir $(OPERATOR_SDK)) ;\ + curl -sSLo $(OPERATOR_SDK) https://github.com/operator-framework/operator-sdk/releases/download/$(OPERATOR_SDK_VERSION)/operator-sdk_$(OS)_$(ARCH) ;\ + chmod +x $(OPERATOR_SDK) ;\ + } +else +OPERATOR_SDK = $(shell which operator-sdk) +endif +endif + +.PHONY: copy-crds +copy-crds: ## Copy CRDs and CRs from root directory to operator directory for bundle packaging. + mkdir -p $(CRD_DEST_DIR) + cp $(CRD_SOURCE_DIR)/* $(CRD_DEST_DIR) + cp $(SAMPLE_SOURCE_DIR)/balloons-config.yaml $(SAMPLE_DEST_DIR) + cp $(SAMPLE_SOURCE_DIR)/template-config.yaml $(SAMPLE_DEST_DIR) + cp $(SAMPLE_SOURCE_DIR)/topologyaware-config.yaml $(SAMPLE_DEST_DIR) + cp $(SAMPLE_SOURCE_DIR)/noderesourcetopology.yaml $(SAMPLE_DEST_DIR) + +.PHONY: cleanup-crds +cleanup-crds: ## Clean up temporarily copied CRDs and CRs. + rm -f $(CRD_DEST_DIR)/* + rm -f $(SAMPLE_DEST_DIR)/balloons-config.yaml + rm -f $(SAMPLE_DEST_DIR)/template-config.yaml + rm -f $(SAMPLE_DEST_DIR)/topologyaware-config.yaml + rm -f $(SAMPLE_DEST_DIR)/noderesourcetopology.yaml diff --git a/deployment/operator/PROJECT b/deployment/operator/PROJECT new file mode 100644 index 000000000..d68bac2e5 --- /dev/null +++ b/deployment/operator/PROJECT @@ -0,0 +1,19 @@ +# Code generated by tool. DO NOT EDIT. +# This file is used to track the info used to scaffold your project +# and allow the plugins properly work. +# More info: https://book.kubebuilder.io/reference/project-config.html +layout: +- ansible.sdk.operatorframework.io/v1 +multigroup: true +plugins: + manifests.sdk.operatorframework.io/v2: {} + scorecard.sdk.operatorframework.io/v2: {} +projectName: nri-plugins-operator +resources: +- api: + crdVersion: v1 + namespaced: true + group: config.nri + kind: NriPluginDeployment + version: v1alpha1 +version: "3" diff --git a/deployment/operator/README.md b/deployment/operator/README.md new file mode 100644 index 000000000..bd6cd3c9f --- /dev/null +++ b/deployment/operator/README.md @@ -0,0 +1,69 @@ +# NRI-Plugins-Operator + +## Introduction + +The nri-plugins-operator is an Ansible-based operator created with operator-sdk to manage the life cycle of the +nri-plugins. The operator deploys community maintained [nri-plugins](https://github.com/containers/nri-plugins) in +Kubernetes cluster. When operator is installed, it doesn't do anything apart from watching for custom resources called +NriPluginDeployment. When NriPluginDeployment object is created, reconciliation loops kicks off and installs the +nri-plugin specified in the NriPluginDeployment. + +## Installation + +Build the operator image and push it to some registry +```shell +make -C deployment/operator docker-build docker-push IMG="my-registry.com/nri-plugins-operator:unstable" +``` + +Deploy the operator in your cluster +```shell +make -C deployment/operator deploy +``` + +Uninstall the operator +```shell +make -C deployment/operator undeploy +``` + +## Operator CRD + +```YAML +apiVersion: config.nri/v1alpha1 +kind: NriPluginDeployment +metadata: + name: nriplugindeployment-sample + namespace: kube-system +spec: + pluginName: topology-aware + pluginVersion: "v0.2.3" + state: present + values: + nri: + patchRuntimeConfig: true + tolerations: + - key: "node-role.kubernetes.io/control-plane" + operator: "Exists" + effect: "NoSchedule" + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: topology.kubernetes.io/disk + operator: In + values: + - ssd +``` + +- `metadata.namespace`: the same namespace is used to install the nri-plugin Helm chart. +- `spec.pluginName`: This field specifies the desired plugin to be installed, with currently accepted values including + topology-aware, balloons, memtierd, memory-qos, or sgx-epc. The list of allowed nri-plugins is expected to grow as + new plugins are introduced. The field is immutable and to deploy a different plugin you need to re-create the object + or create a new one with different name and namespace. +- `spec.pluginVersion`: specifies the version of the plugin. If not indicated, it defaults to the latest version. The + plugin version is mutable, and updating it will uninstall the current version before installing the updated one. +- `spec.state`: Determines whether to install (`present`) or uninstall (`absent`) the plugin. +- `spec.values`: Allows users to provide custom values for manipulating Helm chart values. This field is immutable, + requiring users to recreate the object to pass new values. +- `spec.status`: Tracks the basic state of the resource and includes basic messages in case the operator encounters + issues while reconciling the object. diff --git a/deployment/operator/ansible.cfg b/deployment/operator/ansible.cfg new file mode 100644 index 000000000..b770e0059 --- /dev/null +++ b/deployment/operator/ansible.cfg @@ -0,0 +1,5 @@ +[defaults] +roles_path = /opt/ansible/roles +library = /usr/share/ansible/openshift +display_skipped_hosts = False +force_color = 1 diff --git a/deployment/operator/bundle.Dockerfile b/deployment/operator/bundle.Dockerfile new file mode 100644 index 000000000..9dc53765c --- /dev/null +++ b/deployment/operator/bundle.Dockerfile @@ -0,0 +1,20 @@ +FROM scratch + +# Core bundle labels. +LABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1 +LABEL operators.operatorframework.io.bundle.manifests.v1=manifests/ +LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/ +LABEL operators.operatorframework.io.bundle.package.v1=nri-plugins-operator +LABEL operators.operatorframework.io.bundle.channels.v1=alpha +LABEL operators.operatorframework.io.metrics.builder=operator-sdk-v1.32.0 +LABEL operators.operatorframework.io.metrics.mediatype.v1=metrics+v1 +LABEL operators.operatorframework.io.metrics.project_layout=ansible.sdk.operatorframework.io/v1 + +# Labels for testing. +LABEL operators.operatorframework.io.test.mediatype.v1=scorecard+v1 +LABEL operators.operatorframework.io.test.config.v1=tests/scorecard/ + +# Copy files to locations specified by labels. +COPY bundle/manifests /manifests/ +COPY bundle/metadata /metadata/ +COPY bundle/tests/scorecard /tests/scorecard/ diff --git a/deployment/operator/categories.json b/deployment/operator/categories.json new file mode 100644 index 000000000..a0c234c66 --- /dev/null +++ b/deployment/operator/categories.json @@ -0,0 +1,7 @@ +{ + "categories":[ + "Performance", + "System components" + ] + } + \ No newline at end of file diff --git a/deployment/operator/config/crd/kustomization.yaml b/deployment/operator/config/crd/kustomization.yaml new file mode 100644 index 000000000..abd1d14ae --- /dev/null +++ b/deployment/operator/config/crd/kustomization.yaml @@ -0,0 +1,12 @@ +# This kustomization.yaml is not intended to be run by itself, +# since it depends on service name and namespace that are out of this kustomize package. +# It should be run by config/default +resources: +# NOTE(fmuyassarov): We will copy the below CRD files (from the top level config/crd/bases) +# during the bundle build process. We don't store the same copies here too to avoid duplication. +- bases/config.nri_nriplugindeployments.yaml +- bases/topology.node.k8s.io_noderesourcetopologies.yaml +- bases/config.nri_balloonspolicies.yaml +- bases/config.nri_templatepolicies.yaml +- bases/config.nri_topologyawarepolicies.yaml +#+kubebuilder:scaffold:crdkustomizeresource diff --git a/deployment/operator/config/default/kustomization.yaml b/deployment/operator/config/default/kustomization.yaml new file mode 100644 index 000000000..caaf995dd --- /dev/null +++ b/deployment/operator/config/default/kustomization.yaml @@ -0,0 +1,30 @@ +# Adds namespace to all resources. +namespace: nri-plugins-operator-system + +# Value of this field is prepended to the +# names of all resources, e.g. a deployment named +# "wordpress" becomes "alices-wordpress". +# Note that it should also match with the prefix (text before '-') of the namespace +# field above. +namePrefix: nri-plugins-operator- + +# Labels to add to all resources and selectors. +#labels: +#- includeSelectors: true +# pairs: +# someName: someValue + +resources: +- ../crd +- ../rbac +- ../manager +# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. +#- ../prometheus + +patchesStrategicMerge: +# Protect the /metrics endpoint by putting it behind auth. +# If you want your controller-manager to expose the /metrics +# endpoint w/o any authn/z, please comment the following line. +- manager_auth_proxy_patch.yaml + + diff --git a/deployment/operator/config/default/manager_auth_proxy_patch.yaml b/deployment/operator/config/default/manager_auth_proxy_patch.yaml new file mode 100644 index 000000000..cc9bc8869 --- /dev/null +++ b/deployment/operator/config/default/manager_auth_proxy_patch.yaml @@ -0,0 +1,56 @@ +# This patch inject a sidecar container which is a HTTP proxy for the +# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/arch + operator: In + values: + - amd64 + - arm64 + - ppc64le + - s390x + - key: kubernetes.io/os + operator: In + values: + - linux + containers: + - name: kube-rbac-proxy + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - "ALL" + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.1 + args: + - "--secure-listen-address=0.0.0.0:8443" + - "--upstream=http://127.0.0.1:8080/" + - "--logtostderr=true" + - "--v=0" + ports: + - containerPort: 8443 + protocol: TCP + name: https + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 5m + memory: 64Mi + - name: manager + args: + - "--health-probe-bind-address=:6789" + - "--metrics-bind-address=127.0.0.1:8080" + - "--leader-elect" + - "--leader-election-id=nri-plugins-operator" diff --git a/deployment/operator/config/default/manager_config_patch.yaml b/deployment/operator/config/default/manager_config_patch.yaml new file mode 100644 index 000000000..f6f589169 --- /dev/null +++ b/deployment/operator/config/default/manager_config_patch.yaml @@ -0,0 +1,10 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager diff --git a/deployment/operator/config/manager/kustomization.yaml b/deployment/operator/config/manager/kustomization.yaml new file mode 100644 index 000000000..9c1caf3b5 --- /dev/null +++ b/deployment/operator/config/manager/kustomization.yaml @@ -0,0 +1,8 @@ +resources: +- manager.yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +images: +- name: controller + newName: ghcr.io/containers/nri-plugins-operator + newTag: unstable diff --git a/deployment/operator/config/manager/manager.yaml b/deployment/operator/config/manager/manager.yaml new file mode 100644 index 000000000..734f9bbd7 --- /dev/null +++ b/deployment/operator/config/manager/manager.yaml @@ -0,0 +1,104 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + control-plane: controller-manager + app.kubernetes.io/name: namespace + app.kubernetes.io/instance: system + app.kubernetes.io/component: manager + app.kubernetes.io/created-by: nri-plugins-operator + app.kubernetes.io/part-of: nri-plugins-operator + app.kubernetes.io/managed-by: kustomize + name: system +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system + labels: + control-plane: controller-manager + app.kubernetes.io/name: deployment + app.kubernetes.io/instance: controller-manager + app.kubernetes.io/component: manager + app.kubernetes.io/created-by: nri-plugins-operator + app.kubernetes.io/part-of: nri-plugins-operator + app.kubernetes.io/managed-by: kustomize +spec: + selector: + matchLabels: + control-plane: controller-manager + replicas: 1 + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: manager + labels: + control-plane: controller-manager + spec: + # TODO(user): Uncomment the following code to configure the nodeAffinity expression + # according to the platforms which are supported by your solution. + # It is considered best practice to support multiple architectures. You can + # build your manager image using the makefile target docker-buildx. + # affinity: + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: kubernetes.io/arch + # operator: In + # values: + # - amd64 + # - arm64 + # - ppc64le + # - s390x + # - key: kubernetes.io/os + # operator: In + # values: + # - linux + securityContext: + runAsNonRoot: true + # TODO(user): For common cases that do not require escalating privileges + # it is recommended to ensure that all your Pods/Containers are restrictive. + # More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted + # Please uncomment the following code if your project does NOT have to work on old Kubernetes + # versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ). + # seccompProfile: + # type: RuntimeDefault + containers: + - args: + - --leader-elect + - --leader-election-id=nri-plugins-operator + image: controller:latest + name: manager + env: + - name: ANSIBLE_GATHERING + value: explicit + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - "ALL" + livenessProbe: + httpGet: + path: /healthz + port: 6789 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 6789 + initialDelaySeconds: 5 + periodSeconds: 10 + # TODO(user): Configure the resources accordingly based on the project requirements. + # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + resources: + limits: + cpu: 500m + memory: 768Mi + requests: + cpu: 10m + memory: 256Mi + serviceAccountName: controller-manager + terminationGracePeriodSeconds: 10 diff --git a/deployment/operator/config/manifests/bases/nri-plugins-operator.clusterserviceversion.yaml b/deployment/operator/config/manifests/bases/nri-plugins-operator.clusterserviceversion.yaml new file mode 100644 index 000000000..6c7ebcc0a --- /dev/null +++ b/deployment/operator/config/manifests/bases/nri-plugins-operator.clusterserviceversion.yaml @@ -0,0 +1,105 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: '[]' + capabilities: Basic Install + categories: Performance + certified: "false" + containerImage: ghcr.io/containers/nri-plugins/nri-plugins-operator:unstable + description: An operator that installs Node Resource Interface reference plugins. + repository: https://github.com/containers/nri-plugins-operator + support: "false" + name: nri-plugins-operator.v0.0.1 + namespace: placeholder +spec: + apiservicedefinitions: {} + customresourcedefinitions: + owned: + - description: Represents the deployment of NRI plugin + displayName: NRI Plugin Deployment + kind: NriPluginDeployment + name: nriplugindeployments.config.nri + version: v1alpha1 + - description: Describes node resources and their topology + displayName: Node Resource Topology (v1alpha1) + kind: NodeResourceTopology + name: noderesourcetopologies.topology.node.k8s.io + version: v1alpha1 + - description: Describes node resources and their topology + displayName: Node Resource Topology (v1alpha2) + kind: NodeResourceTopology + name: noderesourcetopologies.topology.node.k8s.io + version: v1alpha2 + - description: BalloonsPolicy represents the configuration for the balloons policy + displayName: Balloons Policy + kind: BalloonsPolicy + name: balloonspolicies.config.nri + version: v1alpha1 + - description: TemplatePolicy represents the configuration for the template policy. + displayName: Template Policy + kind: TemplatePolicy + name: templatepolicies.config.nri + version: v1alpha1 + - description: TopologyAwarePolicy represents the configuration for the topology-aware + policy. + displayName: Topology Aware Policy + kind: TopologyAwarePolicy + name: topologyawarepolicies.config.nri + version: v1alpha1 + description: |- + The **nri-plugins-operator** deploys community maintained [nri-plugins](https://github.com/containers/nri-plugins) into a Kubernetes cluster. + + # Node Resource Interface + NRI allows plugging domain- or vendor-specific custom logic into OCI- compatible runtimes. This logic can make controlled changes to containers or perform extra actions outside the scope of OCI at certain points in a containers lifecycle. This can be used, for instance, for improved allocation and management of devices and other container resources. + + For more info, visit [https://github.com/containerd/nri](https://github.com/containerd/nri) + + # Node Resource Interface reference plugins + + The NRI plugins is a collection of Node Resource Interface based plugins to manage various aspects of pod and container life cycle. For example the resource policy plugins can be used to modify the container resource allocation depending on available system resources. + + For more info, visit [https://github.com/containers/nri-plugins](https://github.com/containers/nri-plugins) + + # License + + nri-plugins-operator is distributed under the + [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt). + displayName: NRI-Plugins-Operator + icon: + - base64data: PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTguNTEgMjU4LjUxIj48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6I2QxZDFkMTt9LmNscy0ye2ZpbGw6IzhkOGQ4Zjt9PC9zdHlsZT48L2RlZnM+PHRpdGxlPkFzc2V0IDQ8L3RpdGxlPjxnIGlkPSJMYXllcl8yIiBkYXRhLW5hbWU9IkxheWVyIDIiPjxnIGlkPSJMYXllcl8xLTIiIGRhdGEtbmFtZT0iTGF5ZXIgMSI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTI5LjI1LDIwQTEwOS4xLDEwOS4xLDAsMCwxLDIwNi40LDIwNi40LDEwOS4xLDEwOS4xLDAsMSwxLDUyLjExLDUyLjExLDEwOC40NSwxMDguNDUsMCwwLDEsMTI5LjI1LDIwbTAtMjBoMEM1OC4xNiwwLDAsNTguMTYsMCwxMjkuMjVIMGMwLDcxLjA5LDU4LjE2LDEyOS4yNiwxMjkuMjUsMTI5LjI2aDBjNzEuMDksMCwxMjkuMjYtNTguMTcsMTI5LjI2LTEyOS4yNmgwQzI1OC41MSw1OC4xNiwyMDAuMzQsMCwxMjkuMjUsMFoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xNzcuNTQsMTAzLjQxSDE0MS42NkwxNTQuOSw2NS43NmMxLjI1LTQuNC0yLjMzLTguNzYtNy4yMS04Ljc2SDEwMi45M2E3LjMyLDcuMzIsMCwwLDAtNy40LDZsLTEwLDY5LjYxYy0uNTksNC4xNywyLjg5LDcuODksNy40LDcuODloMzYuOUwxMTUuNTUsMTk3Yy0xLjEyLDQuNDEsMi40OCw4LjU1LDcuMjQsOC41NWE3LjU4LDcuNTgsMCwwLDAsNi40Ny0zLjQ4TDE4NCwxMTMuODVDMTg2Ljg2LDEwOS4yNCwxODMuMjksMTAzLjQxLDE3Ny41NCwxMDMuNDFaIi8+PC9nPjwvZz48L3N2Zz4= + mediatype: image/svg+xml + install: + spec: + deployments: null + strategy: deployment + installModes: + - supported: false + type: OwnNamespace + - supported: false + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: true + type: AllNamespaces + keywords: + - nri-plugins + - nri + - cri-o + - containerd + - kubernetes + - performance + links: + - name: NRI-Plugins + url: https://github.com/containers/nri-plugins + - name: NRI + url: https://github.com/containers/nri + maintainers: + - email: feruzjon.muyassarov@intel.com + name: nri-plugins project maintainers + maturity: alpha + minKubeVersion: 1.27.0 + provider: + name: nri-plugins project owners + url: https://github.com/containers/nri-plugins + version: 0.0.1 diff --git a/deployment/operator/config/manifests/kustomization.yaml b/deployment/operator/config/manifests/kustomization.yaml new file mode 100644 index 000000000..70b1330b6 --- /dev/null +++ b/deployment/operator/config/manifests/kustomization.yaml @@ -0,0 +1,7 @@ +# These resources constitute the fully configured set of manifests +# used to generate the 'manifests/' directory in a bundle. +resources: +- bases/nri-plugins-operator.clusterserviceversion.yaml +- ../default +- ../samples +- ../scorecard diff --git a/deployment/operator/config/rbac/auth_proxy_client_clusterrole.yaml b/deployment/operator/config/rbac/auth_proxy_client_clusterrole.yaml new file mode 100644 index 000000000..5e4cc181c --- /dev/null +++ b/deployment/operator/config/rbac/auth_proxy_client_clusterrole.yaml @@ -0,0 +1,16 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: metrics-reader + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: nri-plugins-operator + app.kubernetes.io/part-of: nri-plugins-operator + app.kubernetes.io/managed-by: kustomize + name: metrics-reader +rules: +- nonResourceURLs: + - "/metrics" + verbs: + - get diff --git a/deployment/operator/config/rbac/auth_proxy_role.yaml b/deployment/operator/config/rbac/auth_proxy_role.yaml new file mode 100644 index 000000000..3fcbf826c --- /dev/null +++ b/deployment/operator/config/rbac/auth_proxy_role.yaml @@ -0,0 +1,24 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: proxy-role + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: nri-plugins-operator + app.kubernetes.io/part-of: nri-plugins-operator + app.kubernetes.io/managed-by: kustomize + name: proxy-role +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create diff --git a/deployment/operator/config/rbac/auth_proxy_role_binding.yaml b/deployment/operator/config/rbac/auth_proxy_role_binding.yaml new file mode 100644 index 000000000..ee4513ea7 --- /dev/null +++ b/deployment/operator/config/rbac/auth_proxy_role_binding.yaml @@ -0,0 +1,19 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: clusterrolebinding + app.kubernetes.io/instance: proxy-rolebinding + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: nri-plugins-operator + app.kubernetes.io/part-of: nri-plugins-operator + app.kubernetes.io/managed-by: kustomize + name: proxy-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: proxy-role +subjects: +- kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/deployment/operator/config/rbac/auth_proxy_service.yaml b/deployment/operator/config/rbac/auth_proxy_service.yaml new file mode 100644 index 000000000..75527f7e2 --- /dev/null +++ b/deployment/operator/config/rbac/auth_proxy_service.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + control-plane: controller-manager + app.kubernetes.io/name: service + app.kubernetes.io/instance: controller-manager-metrics-service + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: nri-plugins-operator + app.kubernetes.io/part-of: nri-plugins-operator + app.kubernetes.io/managed-by: kustomize + name: controller-manager-metrics-service + namespace: system +spec: + ports: + - name: https + port: 8443 + protocol: TCP + targetPort: https + selector: + control-plane: controller-manager diff --git a/deployment/operator/config/rbac/config.nri_nriplugindeployment_editor_role.yaml b/deployment/operator/config/rbac/config.nri_nriplugindeployment_editor_role.yaml new file mode 100644 index 000000000..c820935f9 --- /dev/null +++ b/deployment/operator/config/rbac/config.nri_nriplugindeployment_editor_role.yaml @@ -0,0 +1,31 @@ +# permissions for end users to edit nriplugindeployments. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: nriplugindeployment-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: nri-plugins-operator + app.kubernetes.io/part-of: nri-plugins-operator + app.kubernetes.io/managed-by: kustomize + name: nriplugindeployment-editor-role +rules: +- apiGroups: + - config.nri + resources: + - nriplugindeployments + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - config.nri + resources: + - nriplugindeployments/status + verbs: + - get diff --git a/deployment/operator/config/rbac/config.nri_nriplugindeployment_viewer_role.yaml b/deployment/operator/config/rbac/config.nri_nriplugindeployment_viewer_role.yaml new file mode 100644 index 000000000..576f1141f --- /dev/null +++ b/deployment/operator/config/rbac/config.nri_nriplugindeployment_viewer_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to view nriplugindeployments. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: nriplugindeployment-viewer-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: nri-plugins-operator + app.kubernetes.io/part-of: nri-plugins-operator + app.kubernetes.io/managed-by: kustomize + name: nriplugindeployment-viewer-role +rules: +- apiGroups: + - config.nri + resources: + - nriplugindeployments + verbs: + - get + - list + - watch +- apiGroups: + - config.nri + resources: + - nriplugindeployments/status + verbs: + - get diff --git a/deployment/operator/config/rbac/kustomization.yaml b/deployment/operator/config/rbac/kustomization.yaml new file mode 100644 index 000000000..731832a6a --- /dev/null +++ b/deployment/operator/config/rbac/kustomization.yaml @@ -0,0 +1,18 @@ +resources: +# All RBAC will be applied under this service account in +# the deployment namespace. You may comment out this resource +# if your manager will use a service account that exists at +# runtime. Be sure to update RoleBinding and ClusterRoleBinding +# subjects if changing service account names. +- service_account.yaml +- role.yaml +- role_binding.yaml +- leader_election_role.yaml +- leader_election_role_binding.yaml +# Comment the following 4 lines if you want to disable +# the auth proxy (https://github.com/brancz/kube-rbac-proxy) +# which protects your /metrics endpoint. +- auth_proxy_service.yaml +- auth_proxy_role.yaml +- auth_proxy_role_binding.yaml +- auth_proxy_client_clusterrole.yaml diff --git a/deployment/operator/config/rbac/leader_election_role.yaml b/deployment/operator/config/rbac/leader_election_role.yaml new file mode 100644 index 000000000..945d9313e --- /dev/null +++ b/deployment/operator/config/rbac/leader_election_role.yaml @@ -0,0 +1,44 @@ +# permissions to do leader election. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/name: role + app.kubernetes.io/instance: leader-election-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: nri-plugins-operator + app.kubernetes.io/part-of: nri-plugins-operator + app.kubernetes.io/managed-by: kustomize + name: leader-election-role +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch diff --git a/deployment/operator/config/rbac/leader_election_role_binding.yaml b/deployment/operator/config/rbac/leader_election_role_binding.yaml new file mode 100644 index 000000000..f7756166d --- /dev/null +++ b/deployment/operator/config/rbac/leader_election_role_binding.yaml @@ -0,0 +1,19 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/name: rolebinding + app.kubernetes.io/instance: leader-election-rolebinding + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: nri-plugins-operator + app.kubernetes.io/part-of: nri-plugins-operator + app.kubernetes.io/managed-by: kustomize + name: leader-election-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: leader-election-role +subjects: +- kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/deployment/operator/config/rbac/role.yaml b/deployment/operator/config/rbac/role.yaml new file mode 100644 index 000000000..1de3081ac --- /dev/null +++ b/deployment/operator/config/rbac/role.yaml @@ -0,0 +1,54 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: manager-role +rules: + ## + ## Rules for the operator + ## + - apiGroups: + - config.nri + resources: + - nriplugindeployments + verbs: + - get + - list + - watch + - update + - apiGroups: + - config.nri + resources: + - nriplugindeployments/status + verbs: + - get + - update + - patch + - apiGroups: + - topology.node.k8s.io + resources: + - noderesourcetopologies + verbs: + - create + - get + - update + ## + ## Rules for config.nri/v1alpha1, Kind: NriPluginDeployment + ## + - verbs: + - "*" + apiGroups: + - "rbac.authorization.k8s.io" + - "apps" + - "" + resources: + - "clusterrolebindings" + - "clusterroles" + - "rolebindings" + - "roles" + - "daemonsets" + - "configmaps" + - "serviceaccounts" + - "namespaces" + - "secrets" + #+kubebuilder:scaffold:rules diff --git a/deployment/operator/config/rbac/role_binding.yaml b/deployment/operator/config/rbac/role_binding.yaml new file mode 100644 index 000000000..441459430 --- /dev/null +++ b/deployment/operator/config/rbac/role_binding.yaml @@ -0,0 +1,19 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: clusterrolebinding + app.kubernetes.io/instance: manager-rolebinding + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: nri-plugins-operator + app.kubernetes.io/part-of: nri-plugins-operator + app.kubernetes.io/managed-by: kustomize + name: manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: manager-role +subjects: +- kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/deployment/operator/config/rbac/service_account.yaml b/deployment/operator/config/rbac/service_account.yaml new file mode 100644 index 000000000..03c3e2f36 --- /dev/null +++ b/deployment/operator/config/rbac/service_account.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/name: serviceaccount + app.kubernetes.io/instance: controller-manager-sa + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: nri-plugins-operator + app.kubernetes.io/part-of: nri-plugins-operator + app.kubernetes.io/managed-by: kustomize + name: controller-manager + namespace: system diff --git a/deployment/operator/config/samples/config.nri_v1alpha1_nriplugindeployment.yaml b/deployment/operator/config/samples/config.nri_v1alpha1_nriplugindeployment.yaml new file mode 100644 index 000000000..fc60a1c6a --- /dev/null +++ b/deployment/operator/config/samples/config.nri_v1alpha1_nriplugindeployment.yaml @@ -0,0 +1,19 @@ +apiVersion: config.nri/v1alpha1 +kind: NriPluginDeployment +metadata: + labels: + app.kubernetes.io/name: nriplugindeployment + app.kubernetes.io/instance: nriplugindeployment-sample + app.kubernetes.io/part-of: nri-plugins-operator + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: nri-plugins-operator + name: nriplugindeployment-sample + namespace: kube-system +spec: + pluginName: topology-aware + pluginVersion: "v0.2.3" + state: present + values: + nri: + patchRuntimeConfig: true + diff --git a/deployment/operator/config/samples/kustomization.yaml b/deployment/operator/config/samples/kustomization.yaml new file mode 100644 index 000000000..410458176 --- /dev/null +++ b/deployment/operator/config/samples/kustomization.yaml @@ -0,0 +1,9 @@ +# NOTE(fmuyassarov): We will copy the below CR files (from the top level sample-configs/) +# during the bundle build process. We don't store the same copies here too to avoid duplication. +resources: +- config.nri_v1alpha1_nriplugindeployment.yaml +- balloons-config.yaml +- template-config.yaml +- topologyaware-config.yaml +- noderesourcetopology.yaml +#+kubebuilder:scaffold:manifestskustomizesamples diff --git a/deployment/operator/config/scorecard/bases/config.yaml b/deployment/operator/config/scorecard/bases/config.yaml new file mode 100644 index 000000000..c77047841 --- /dev/null +++ b/deployment/operator/config/scorecard/bases/config.yaml @@ -0,0 +1,7 @@ +apiVersion: scorecard.operatorframework.io/v1alpha3 +kind: Configuration +metadata: + name: config +stages: +- parallel: true + tests: [] diff --git a/deployment/operator/config/scorecard/kustomization.yaml b/deployment/operator/config/scorecard/kustomization.yaml new file mode 100644 index 000000000..50cd2d084 --- /dev/null +++ b/deployment/operator/config/scorecard/kustomization.yaml @@ -0,0 +1,16 @@ +resources: +- bases/config.yaml +patchesJson6902: +- path: patches/basic.config.yaml + target: + group: scorecard.operatorframework.io + version: v1alpha3 + kind: Configuration + name: config +- path: patches/olm.config.yaml + target: + group: scorecard.operatorframework.io + version: v1alpha3 + kind: Configuration + name: config +#+kubebuilder:scaffold:patchesJson6902 diff --git a/deployment/operator/config/scorecard/patches/basic.config.yaml b/deployment/operator/config/scorecard/patches/basic.config.yaml new file mode 100644 index 000000000..472a98823 --- /dev/null +++ b/deployment/operator/config/scorecard/patches/basic.config.yaml @@ -0,0 +1,10 @@ +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - basic-check-spec + image: quay.io/operator-framework/scorecard-test:v1.32.0 + labels: + suite: basic + test: basic-check-spec-test diff --git a/deployment/operator/config/scorecard/patches/olm.config.yaml b/deployment/operator/config/scorecard/patches/olm.config.yaml new file mode 100644 index 000000000..343c6d8d8 --- /dev/null +++ b/deployment/operator/config/scorecard/patches/olm.config.yaml @@ -0,0 +1,50 @@ +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-bundle-validation + image: quay.io/operator-framework/scorecard-test:v1.32.0 + labels: + suite: olm + test: olm-bundle-validation-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-crds-have-validation + image: quay.io/operator-framework/scorecard-test:v1.32.0 + labels: + suite: olm + test: olm-crds-have-validation-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-crds-have-resources + image: quay.io/operator-framework/scorecard-test:v1.32.0 + labels: + suite: olm + test: olm-crds-have-resources-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-spec-descriptors + image: quay.io/operator-framework/scorecard-test:v1.32.0 + labels: + suite: olm + test: olm-spec-descriptors-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-status-descriptors + image: quay.io/operator-framework/scorecard-test:v1.32.0 + labels: + suite: olm + test: olm-status-descriptors-test diff --git a/deployment/operator/playbooks/plugin-deployment.yml b/deployment/operator/playbooks/plugin-deployment.yml new file mode 100644 index 000000000..ea7599cbd --- /dev/null +++ b/deployment/operator/playbooks/plugin-deployment.yml @@ -0,0 +1,9 @@ +--- +- hosts: localhost + gather_facts: no + collections: + - kubernetes.core + - operator_sdk.util + tasks: + - import_role: + name: "plugin-deployment" diff --git a/deployment/operator/requirements.yml b/deployment/operator/requirements.yml new file mode 100644 index 000000000..8baf91913 --- /dev/null +++ b/deployment/operator/requirements.yml @@ -0,0 +1,10 @@ +--- +collections: + - name: operator_sdk.util + version: "0.5.0" + - name: kubernetes.core + version: "2.4.0" + - name: cloud.common + version: "2.1.1" + - name: community.docker + version: "3.4.0" diff --git a/deployment/operator/roles/plugin-deployment/tasks/main.yml b/deployment/operator/roles/plugin-deployment/tasks/main.yml new file mode 100644 index 000000000..9bef44b0b --- /dev/null +++ b/deployment/operator/roles/plugin-deployment/tasks/main.yml @@ -0,0 +1,32 @@ +--- +- name: Add nri-plugins helm chart repo + kubernetes.core.helm_repository: + name: nri-plugins + repo_url: "https://containers.github.io/nri-plugins" + +- name: Plugin installation + block: + - name: Set plugin chart reference + set_fact: + chart_ref: "nri-plugins/nri-{{ 'resource-policy-' if pluginName in ['topology-aware', 'balloons'] else '' }}{{ pluginName }}" + + - name: Deploy {{ pluginName }} plugin + kubernetes.core.helm: + name: "{{ pluginName }}" + chart_ref: "{{ chart_ref }}" + release_namespace: "{{ ansible_operator_meta.namespace }}" + chart_version: "{{ pluginVersion }}" + wait: True + create_namespace: True + values: "{{ values | default({}) }}" + skip_crds: True + when: + - state == "present" + - pluginName in ["topology-aware", "balloons", "memory-qos", "memtierd", "sgx-epc"] + +- name: Uninstall {{ pluginName }} plugin + kubernetes.core.helm: + name: "{{ pluginName }}" + namespace: "{{ ansible_operator_meta.namespace }}" + state: absent + when: state == "absent" or state == "revoked" diff --git a/deployment/operator/watches.yaml b/deployment/operator/watches.yaml new file mode 100644 index 000000000..b75fac2c8 --- /dev/null +++ b/deployment/operator/watches.yaml @@ -0,0 +1,12 @@ +--- +- version: v1alpha1 + group: config.nri + kind: NriPluginDeployment + playbook: playbooks/plugin-deployment.yml + snakeCaseParameters: False + manageStatus: True + finalizer: + name: nriplugindeployment.config.nri/finalizer + vars: + state: revoked +#+kubebuilder:scaffold:watch diff --git a/docs/deployment/balloons.md b/docs/deployment/balloons.md deleted file mode 100644 index f180666e5..000000000 --- a/docs/deployment/balloons.md +++ /dev/null @@ -1,2 +0,0 @@ -```{include} ../../deployment/helm/balloons/README.md -``` diff --git a/docs/deployment/helm/balloons.md b/docs/deployment/helm/balloons.md new file mode 100644 index 000000000..126512d48 --- /dev/null +++ b/docs/deployment/helm/balloons.md @@ -0,0 +1,2 @@ +```{include} ../../../deployment/helm/balloons/README.md +``` diff --git a/docs/deployment/helm/index.md b/docs/deployment/helm/index.md new file mode 100644 index 000000000..b635e2198 --- /dev/null +++ b/docs/deployment/helm/index.md @@ -0,0 +1,14 @@ +# Helm + +```{toctree} +--- +maxdepth: 2 +caption: Contents +--- +balloons.md +topology-aware.md +template.md +memory-qos.md +memtierd.md +sgx-epc.md +``` diff --git a/docs/deployment/helm/memory-qos.md b/docs/deployment/helm/memory-qos.md new file mode 100644 index 000000000..195a51856 --- /dev/null +++ b/docs/deployment/helm/memory-qos.md @@ -0,0 +1,2 @@ +```{include} ../../../deployment/helm/memory-qos/README.md +``` diff --git a/docs/deployment/helm/memtierd.md b/docs/deployment/helm/memtierd.md new file mode 100644 index 000000000..834725360 --- /dev/null +++ b/docs/deployment/helm/memtierd.md @@ -0,0 +1,2 @@ +```{include} ../../../deployment/helm/memtierd/README.md +``` diff --git a/docs/deployment/helm/sgx-epc.md b/docs/deployment/helm/sgx-epc.md new file mode 100644 index 000000000..a22a3cc7e --- /dev/null +++ b/docs/deployment/helm/sgx-epc.md @@ -0,0 +1,2 @@ +```{include} ../../../deployment/helm/sgx-epc/README.md +``` diff --git a/docs/deployment/helm/template.md b/docs/deployment/helm/template.md new file mode 100644 index 000000000..f724e0699 --- /dev/null +++ b/docs/deployment/helm/template.md @@ -0,0 +1,2 @@ +```{include} ../../../deployment/helm/template/README.md +``` diff --git a/docs/deployment/helm/topology-aware.md b/docs/deployment/helm/topology-aware.md new file mode 100644 index 000000000..4e6ad805e --- /dev/null +++ b/docs/deployment/helm/topology-aware.md @@ -0,0 +1,2 @@ +```{include} ../../../deployment/helm/topology-aware/README.md +``` diff --git a/docs/deployment/index.md b/docs/deployment/index.md index 129e252ac..92c4a2e22 100644 --- a/docs/deployment/index.md +++ b/docs/deployment/index.md @@ -8,10 +8,6 @@ through Helm. maxdepth: 2 caption: Contents --- -balloons.md -topology-aware.md -template.md -memory-qos.md -memtierd.md -sgx-epc.md +helm/index.md +operator/index.md ``` diff --git a/docs/deployment/memory-qos.md b/docs/deployment/memory-qos.md deleted file mode 100644 index 4ed196196..000000000 --- a/docs/deployment/memory-qos.md +++ /dev/null @@ -1,2 +0,0 @@ -```{include} ../../deployment/helm/memory-qos/README.md -``` diff --git a/docs/deployment/memtierd.md b/docs/deployment/memtierd.md deleted file mode 100644 index 40612361c..000000000 --- a/docs/deployment/memtierd.md +++ /dev/null @@ -1,2 +0,0 @@ -```{include} ../../deployment/helm/memtierd/README.md -``` diff --git a/docs/deployment/operator/index.md b/docs/deployment/operator/index.md new file mode 100644 index 000000000..865748f8e --- /dev/null +++ b/docs/deployment/operator/index.md @@ -0,0 +1,9 @@ +# Operator + +```{toctree} +--- +maxdepth: 2 +caption: Contents +--- +operator.md +``` diff --git a/docs/deployment/operator/operator.md b/docs/deployment/operator/operator.md new file mode 100644 index 000000000..6f2c3ae10 --- /dev/null +++ b/docs/deployment/operator/operator.md @@ -0,0 +1,2 @@ +```{include} ../../../deployment/operator/README.md +``` \ No newline at end of file diff --git a/docs/deployment/sgx-epc.md b/docs/deployment/sgx-epc.md deleted file mode 100644 index d000fbe22..000000000 --- a/docs/deployment/sgx-epc.md +++ /dev/null @@ -1,2 +0,0 @@ -```{include} ../../deployment/helm/sgx-epc/README.md -``` diff --git a/docs/deployment/template.md b/docs/deployment/template.md deleted file mode 100644 index 366ed285a..000000000 --- a/docs/deployment/template.md +++ /dev/null @@ -1,2 +0,0 @@ -```{include} ../../deployment/helm/template/README.md -``` diff --git a/docs/deployment/topology-aware.md b/docs/deployment/topology-aware.md deleted file mode 100644 index 3ad6dc67d..000000000 --- a/docs/deployment/topology-aware.md +++ /dev/null @@ -1,2 +0,0 @@ -```{include} ../../deployment/helm/topology-aware/README.md -``` diff --git a/sample-configs/noderesourcetopology.yaml b/sample-configs/noderesourcetopology.yaml new file mode 100644 index 000000000..d655678d1 --- /dev/null +++ b/sample-configs/noderesourcetopology.yaml @@ -0,0 +1,103 @@ +--- +apiVersion: topology.node.k8s.io/v1alpha1 +kind: NodeResourceTopology +metadata: + name: node1 +topologyPolicies: ["SingleNUMANode"] +zones: + - name: node-0 + type: Node + resources: + - name: cpu + capacity: 20 + allocatable: 15 + available: 10 + - name: vendor/nic1 + capacity: 3 + allocatable: 3 + available: 3 + - name: node-1 + type: Node + resources: + - name: cpu + capacity: 30 + allocatable: 25 + available: 15 + - name: vendor/nic2 + capacity: 6 + allocatable: 6 + available: 6 + - name: node-2 + type: Node + resources: + - name: cpu + capacity: 30 + allocatable: 25 + available: 15 + - name: vendor/nic1 + capacity: 3 + allocatable: 3 + available: 3 + - name: node-3 + type: Node + resources: + - name: cpu + capacity: 30 + allocatable: 25 + available: 15 + - name: vendor/nic1 + capacity: 3 + allocatable: 3 + available: 3 +--- +--- +apiVersion: topology.node.k8s.io/v1alpha2 +kind: NodeResourceTopology +metadata: + name: node1 +topologyPolicies: ["SingleNUMANode"] +zones: + - name: node-0 + type: Node + resources: + - name: cpu + capacity: 20 + allocatable: 15 + available: 10 + - name: vendor/nic1 + capacity: 3 + allocatable: 3 + available: 3 + - name: node-1 + type: Node + resources: + - name: cpu + capacity: 30 + allocatable: 25 + available: 15 + - name: vendor/nic2 + capacity: 6 + allocatable: 6 + available: 6 + - name: node-2 + type: Node + resources: + - name: cpu + capacity: 30 + allocatable: 25 + available: 15 + - name: vendor/nic1 + capacity: 3 + allocatable: 3 + available: 3 + - name: node-3 + type: Node + resources: + - name: cpu + capacity: 30 + allocatable: 25 + available: 15 + - name: vendor/nic1 + capacity: 3 + allocatable: 3 + available: 3