summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@spreadspace.org>2022-08-29 00:14:02 +0200
committerChristian Pointner <equinox@spreadspace.org>2022-08-29 00:14:02 +0200
commit9005cfec6f6c13398d8af396c94e7455edee0420 (patch)
tree48c1f781bd4dd9f5a4bf4859ad2464a580a4c88b
parentkubernetes/addons: run role on all cluster nodes (diff)
add kubernetes cluster addon: node-feature-discovery
-rw-r--r--dan/k8s-emc.yml1
-rw-r--r--inventory/group_vars/k8s-emc/vars.yml2
-rw-r--r--roles/kubernetes/addons/node-feature-discovery/defaults/main.yml2
-rw-r--r--roles/kubernetes/addons/node-feature-discovery/tasks/main.yml45
-rw-r--r--roles/kubernetes/addons/node-feature-discovery/tasks/tls-ca-master.yml101
-rw-r--r--roles/kubernetes/addons/node-feature-discovery/tasks/tls-worker.yml79
-rw-r--r--roles/kubernetes/addons/node-feature-discovery/templates/config.0.11.2.yml.j2710
-rw-r--r--roles/kubernetes/addons/node-feature-discovery/templates/kustomization.yml.j214
8 files changed, 954 insertions, 0 deletions
diff --git a/dan/k8s-emc.yml b/dan/k8s-emc.yml
index 549b7a63..340986e5 100644
--- a/dan/k8s-emc.yml
+++ b/dan/k8s-emc.yml
@@ -38,3 +38,4 @@
- role: kubernetes/addons/metrics-server
- role: kubernetes/addons/openebs-zfs
- role: kubernetes/addons/cert-manager
+ - role: kubernetes/addons/node-feature-discovery
diff --git a/inventory/group_vars/k8s-emc/vars.yml b/inventory/group_vars/k8s-emc/vars.yml
index b1f29671..86ac5116 100644
--- a/inventory/group_vars/k8s-emc/vars.yml
+++ b/inventory/group_vars/k8s-emc/vars.yml
@@ -69,3 +69,5 @@ kubernetes_openebs_zfs_storage_classes:
poolname: "storage"
kubernetes_cert_manager_version: 1.9.1
+
+kubernetes_node_feature_discovery_version: 0.11.2
diff --git a/roles/kubernetes/addons/node-feature-discovery/defaults/main.yml b/roles/kubernetes/addons/node-feature-discovery/defaults/main.yml
new file mode 100644
index 00000000..36f8b848
--- /dev/null
+++ b/roles/kubernetes/addons/node-feature-discovery/defaults/main.yml
@@ -0,0 +1,2 @@
+---
+# kubernetes_node_feature_discovery_version: 0.11.2
diff --git a/roles/kubernetes/addons/node-feature-discovery/tasks/main.yml b/roles/kubernetes/addons/node-feature-discovery/tasks/main.yml
new file mode 100644
index 00000000..80acb7b9
--- /dev/null
+++ b/roles/kubernetes/addons/node-feature-discovery/tasks/main.yml
@@ -0,0 +1,45 @@
+---
+- name: create base directory for node-feature-discovery addon
+ run_once: true
+ delegate_to: "{{ groups['_kubernetes_primary_controlplane_node_'] | first }}"
+ file:
+ path: /etc/kubernetes/addons/node-feature-discovery
+ state: directory
+
+- name: install python-cryptoraphy
+ apt:
+ name: "{{ python_basename }}-cryptography"
+ state: present
+
+- name: generate certificate authority and master certificate
+ run_once: true
+ delegate_to: "{{ groups['_kubernetes_primary_controlplane_node_'] | first }}"
+ import_tasks: tls-ca-master.yml
+
+- name: generate certificate
+ import_tasks: tls-worker.yml
+
+- name: deploy node-feature-discovery addon
+ run_once: true
+ delegate_to: "{{ groups['_kubernetes_primary_controlplane_node_'] | first }}"
+ block:
+ - name: copy config for node-feature-discovery
+ template:
+ src: "config.{{ kubernetes_node_feature_discovery_version }}.yml.j2"
+ dest: /etc/kubernetes/addons/node-feature-discovery/config.yml
+
+ - name: generate kustomization file
+ template:
+ src: "kustomization.yml.j2"
+ dest: /etc/kubernetes/addons/node-feature-discovery/kustomization.yml
+
+ - name: check if node-feature-discovery is already installed
+ check_mode: no
+ command: kubectl --kubeconfig /etc/kubernetes/admin.conf diff -k /etc/kubernetes/addons/node-feature-discovery/
+ failed_when: false
+ changed_when: false
+ register: kube_node_feature_discovery_diff_result
+
+ - name: install node-feature-discovery onto the cluster
+ when: kube_node_feature_discovery_diff_result.rc != 0
+ command: kubectl --kubeconfig /etc/kubernetes/admin.conf apply -k /etc/kubernetes/addons/node-feature-discovery/
diff --git a/roles/kubernetes/addons/node-feature-discovery/tasks/tls-ca-master.yml b/roles/kubernetes/addons/node-feature-discovery/tasks/tls-ca-master.yml
new file mode 100644
index 00000000..a433ab32
--- /dev/null
+++ b/roles/kubernetes/addons/node-feature-discovery/tasks/tls-ca-master.yml
@@ -0,0 +1,101 @@
+---
+- name: create CA directory
+ file:
+ path: /etc/kubernetes/addons/node-feature-discovery/ca
+ state: directory
+ owner: root
+ group: root
+ mode: 0700
+
+- name: create CA private key
+ openssl_privatekey:
+ path: /etc/kubernetes/addons/node-feature-discovery/ca/key.pem
+ type: RSA
+ size: 4096
+ owner: root
+ group: root
+ mode: 0600
+
+- name: create signing request for CA certificate
+ openssl_csr:
+ path: /etc/kubernetes/addons/node-feature-discovery/ca/csr.pem
+ privatekey_path: /etc/kubernetes/addons/node-feature-discovery/ca/key.pem
+ CN: "CA for kubernetes cluster addon node-feature discovery"
+ useCommonNameForSAN: no
+ key_usage:
+ - cRLSign
+ - keyCertSign
+ key_usage_critical: yes
+ basic_constraints:
+ - 'CA:TRUE'
+ - 'pathlen:0'
+ basic_constraints_critical: yes
+
+- name: create self-signed CA certificate
+ openssl_certificate:
+ path: /etc/kubernetes/addons/node-feature-discovery/ca/crt.pem
+ csr_path: /etc/kubernetes/addons/node-feature-discovery/ca/csr.pem
+ privatekey_path: /etc/kubernetes/addons/node-feature-discovery/ca/key.pem
+ provider: selfsigned
+ selfsigned_digest: sha256
+ selfsigned_not_after: "+18250d" ## 50 years
+ selfsigned_create_subject_key_identifier: always_create
+
+- name: slurp CA certificate for worker to use
+ slurp:
+ src: /etc/kubernetes/addons/node-feature-discovery/ca/crt.pem
+ register: node_feature_discovery_ca_certificate
+
+
+- name: create private key for master certificate
+ openssl_privatekey:
+ path: /etc/kubernetes/addons/node-feature-discovery/ca/master.key
+ type: RSA
+ size: 4096
+ owner: root
+ group: root
+ mode: 0600
+
+- name: create signing request for master certificate
+ openssl_csr:
+ path: /etc/kubernetes/addons/node-feature-discovery/ca/master.csr
+ privatekey_path: /etc/kubernetes/addons/node-feature-discovery/ca/master.key
+ CN: nfd-master
+ subject_alt_name:
+ - "DNS:nfd-master"
+ - "DNS:nfd-master.node-feature-discovery.svc.{{ kubernetes.dns_domain | default('cluster.local') }}"
+ - "DNS:localhost"
+ key_usage:
+ - digitalSignature
+ key_usage_critical: yes
+ extended_key_usage:
+ - serverAuth
+ - clientAuth ## this cert is also used for health checks
+ extended_key_usage_critical: yes
+ basic_constraints:
+ - 'CA:FALSE'
+ basic_constraints_critical: yes
+
+- name: check if master certificate exists
+ stat:
+ path: /etc/kubernetes/addons/node-feature-discovery/ca/master.crt
+ register: node_feature_discovery_master_certificate_stat
+
+- name: check master certificate validity
+ when: node_feature_discovery_master_certificate_stat.stat.exists
+ openssl_certificate_info:
+ path: /etc/kubernetes/addons/node-feature-discovery/ca/master.crt
+ valid_at:
+ ten_years: '+3650d'
+ register: node_feature_discovery_master_certificate_info
+
+- name: create master certificate
+ openssl_certificate:
+ path: /etc/kubernetes/addons/node-feature-discovery/ca/master.crt
+ csr_path: /etc/kubernetes/addons/node-feature-discovery/ca/master.csr
+ provider: ownca
+ ownca_path: /etc/kubernetes/addons/node-feature-discovery/ca/crt.pem
+ ownca_privatekey_path: /etc/kubernetes/addons/node-feature-discovery/ca/key.pem
+ ownca_digest: sha256
+ ownca_not_after: "+18250d" ## 50 years
+ force: "{{ node_feature_discovery_master_certificate_stat.stat.exists and (not node_feature_discovery_master_certificate_info.valid_at.ten_years) }}"
diff --git a/roles/kubernetes/addons/node-feature-discovery/tasks/tls-worker.yml b/roles/kubernetes/addons/node-feature-discovery/tasks/tls-worker.yml
new file mode 100644
index 00000000..888c0872
--- /dev/null
+++ b/roles/kubernetes/addons/node-feature-discovery/tasks/tls-worker.yml
@@ -0,0 +1,79 @@
+---
+- name: create certs directory for nfd-worker
+ file:
+ path: /etc/kubernetes/node-feature-discovery/certs
+ state: directory
+ owner: nobody
+ group: root
+ mode: 0500
+
+- name: install CA certificate
+ copy:
+ content: "{{ node_feature_discovery_ca_certificate.content | b64decode }}"
+ dest: /etc/kubernetes/node-feature-discovery/certs/ca.crt
+
+- name: create private key for worker certificate
+ openssl_privatekey:
+ path: /etc/kubernetes/node-feature-discovery/certs/tls.key
+ type: RSA
+ size: 4096
+ owner: nobody
+ group: root
+ mode: 0400
+
+- name: create signing request for worker certificate
+ openssl_csr:
+ path: /etc/kubernetes/node-feature-discovery/certs/tls.csr
+ privatekey_path: /etc/kubernetes/node-feature-discovery/certs/tls.key
+ CN: "{{ kubernetes_node_name }}"
+ key_usage:
+ - digitalSignature
+ key_usage_critical: yes
+ extended_key_usage:
+ - clientAuth
+ extended_key_usage_critical: yes
+ basic_constraints:
+ - 'CA:FALSE'
+ basic_constraints_critical: yes
+
+- name: slurp CSR for worker certificate
+ slurp:
+ src: /etc/kubernetes/node-feature-discovery/certs/tls.csr
+ register: node_feature_discovery_worker_csr
+
+- name: check if worker certificate already exists
+ stat:
+ path: /etc/kubernetes/node-feature-discovery/certs/tls.crt
+ register: node_feature_discovery_worker_certificate_stat
+
+- name: read worker certificate validity
+ when: node_feature_discovery_worker_certificate_stat.stat.exists
+ openssl_certificate_info:
+ path: /etc/kubernetes/node-feature-discovery/certs/tls.crt
+ valid_at:
+ ten_years: '+3650d'
+ register: node_feature_discovery_worker_certificate_info
+
+- name: slurp existing worker certificate
+ when: node_feature_discovery_worker_certificate_stat.stat.exists
+ slurp:
+ src: /etc/kubernetes/node-feature-discovery/certs/tls.crt
+ register: node_feature_discovery_worker_certificate_current
+
+- name: generate worker certificate
+ delegate_to: "{{ groups['_kubernetes_primary_controlplane_node_'] | first }}"
+ community.crypto.x509_certificate_pipe:
+ content: "{{ node_feature_discovery_worker_certificate_current.content | default('') | b64decode }}"
+ csr_content: "{{ node_feature_discovery_worker_csr.content | b64decode }}"
+ provider: ownca
+ ownca_path: /etc/kubernetes/addons/node-feature-discovery/ca/crt.pem
+ ownca_privatekey_path: /etc/kubernetes/addons/node-feature-discovery/ca/key.pem
+ ownca_digest: sha256
+ ownca_not_after: "+18250d" ## 50 years
+ force: "{{ node_feature_discovery_worker_certificate_stat.stat.exists and (not node_feature_discovery_worker_certificate_info.valid_at.ten_years) }}"
+ register: node_feature_discovery_worker_cert
+
+- name: store worker certificate
+ copy:
+ content: "{{ node_feature_discovery_worker_cert.certificate }}"
+ dest: /etc/kubernetes/node-feature-discovery/certs/tls.crt
diff --git a/roles/kubernetes/addons/node-feature-discovery/templates/config.0.11.2.yml.j2 b/roles/kubernetes/addons/node-feature-discovery/templates/config.0.11.2.yml.j2
new file mode 100644
index 00000000..7081c290
--- /dev/null
+++ b/roles/kubernetes/addons/node-feature-discovery/templates/config.0.11.2.yml.j2
@@ -0,0 +1,710 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: node-feature-discovery
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.7.0
+ creationTimestamp: null
+ name: nodefeaturerules.nfd.k8s-sigs.io
+spec:
+ group: nfd.k8s-sigs.io
+ names:
+ kind: NodeFeatureRule
+ listKind: NodeFeatureRuleList
+ plural: nodefeaturerules
+ singular: nodefeaturerule
+ scope: Cluster
+ versions:
+ - name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: NodeFeatureRule resource specifies a configuration for feature-based
+ customization of node objects, such as node labeling.
+ 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: NodeFeatureRuleSpec describes a NodeFeatureRule.
+ properties:
+ rules:
+ description: Rules is a list of node customization rules.
+ items:
+ description: Rule defines a rule for node customization such as
+ labeling.
+ properties:
+ labels:
+ additionalProperties:
+ type: string
+ description: Labels to create if the rule matches.
+ type: object
+ labelsTemplate:
+ description: LabelsTemplate specifies a template to expand for
+ dynamically generating multiple labels. Data (after template
+ expansion) must be keys with an optional value (<key>[=<value>])
+ separated by newlines.
+ type: string
+ matchAny:
+ description: MatchAny specifies a list of matchers one of which
+ must match.
+ items:
+ description: MatchAnyElem specifies one sub-matcher of MatchAny.
+ properties:
+ matchFeatures:
+ description: MatchFeatures specifies a set of matcher
+ terms all of which must match.
+ items:
+ description: FeatureMatcherTerm defines requirements
+ against one feature set. All requirements (specified
+ as MatchExpressions) are evaluated against each element
+ in the feature set.
+ properties:
+ feature:
+ type: string
+ matchExpressions:
+ additionalProperties:
+ description: "MatchExpression specifies an expression
+ to evaluate against a set of input values. It
+ contains an operator that is applied when matching
+ the input and an array of values that the operator
+ evaluates the input against. \n NB: CreateMatchExpression
+ or MustCreateMatchExpression() should be used
+ for creating new instances. NB: Validate()
+ must be called if Op or Value fields are modified
+ or if a new instance is created from scratch
+ without using the helper functions."
+ properties:
+ op:
+ description: Op is the operator to be applied.
+ enum:
+ - In
+ - NotIn
+ - InRegexp
+ - Exists
+ - DoesNotExist
+ - Gt
+ - Lt
+ - GtLt
+ - IsTrue
+ - IsFalse
+ type: string
+ value:
+ description: Value is the list of values that
+ the operand evaluates the input against.
+ Value should be empty if the operator is
+ Exists, DoesNotExist, IsTrue or IsFalse.
+ Value should contain exactly one element
+ if the operator is Gt or Lt and exactly
+ two elements if the operator is GtLt. In
+ other cases Value should contain at least
+ one element.
+ items:
+ type: string
+ type: array
+ required:
+ - op
+ type: object
+ description: MatchExpressionSet contains a set of
+ MatchExpressions, each of which is evaluated against
+ a set of input values.
+ type: object
+ required:
+ - feature
+ - matchExpressions
+ type: object
+ type: array
+ required:
+ - matchFeatures
+ type: object
+ type: array
+ matchFeatures:
+ description: MatchFeatures specifies a set of matcher terms
+ all of which must match.
+ items:
+ description: FeatureMatcherTerm defines requirements against
+ one feature set. All requirements (specified as MatchExpressions)
+ are evaluated against each element in the feature set.
+ properties:
+ feature:
+ type: string
+ matchExpressions:
+ additionalProperties:
+ description: "MatchExpression specifies an expression
+ to evaluate against a set of input values. It contains
+ an operator that is applied when matching the input
+ and an array of values that the operator evaluates
+ the input against. \n NB: CreateMatchExpression or
+ MustCreateMatchExpression() should be used for creating
+ new instances. NB: Validate() must be called if Op
+ or Value fields are modified or if a new instance
+ is created from scratch without using the helper functions."
+ properties:
+ op:
+ description: Op is the operator to be applied.
+ enum:
+ - In
+ - NotIn
+ - InRegexp
+ - Exists
+ - DoesNotExist
+ - Gt
+ - Lt
+ - GtLt
+ - IsTrue
+ - IsFalse
+ type: string
+ value:
+ description: Value is the list of values that the
+ operand evaluates the input against. Value should
+ be empty if the operator is Exists, DoesNotExist,
+ IsTrue or IsFalse. Value should contain exactly
+ one element if the operator is Gt or Lt and exactly
+ two elements if the operator is GtLt. In other
+ cases Value should contain at least one element.
+ items:
+ type: string
+ type: array
+ required:
+ - op
+ type: object
+ description: MatchExpressionSet contains a set of MatchExpressions,
+ each of which is evaluated against a set of input values.
+ type: object
+ required:
+ - feature
+ - matchExpressions
+ type: object
+ type: array
+ name:
+ description: Name of the rule.
+ type: string
+ vars:
+ additionalProperties:
+ type: string
+ description: Vars is the variables to store if the rule matches.
+ Variables do not directly inflict any changes in the node
+ object. However, they can be referenced from other rules enabling
+ more complex rule hierarchies, without exposing intermediary
+ output values as labels.
+ type: object
+ varsTemplate:
+ description: VarsTemplate specifies a template to expand for
+ dynamically generating multiple variables. Data (after template
+ expansion) must be keys with an optional value (<key>[=<value>])
+ separated by newlines.
+ type: string
+ required:
+ - name
+ type: object
+ type: array
+ required:
+ - rules
+ type: object
+ required:
+ - spec
+ type: object
+ served: true
+ storage: true
+status:
+ acceptedNames:
+ kind: ""
+ plural: ""
+ conditions: []
+ storedVersions: []
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: nfd-master
+ namespace: node-feature-discovery
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: nfd-master
+rules:
+- apiGroups:
+ - ""
+ resources:
+ - nodes
+ verbs:
+ - get
+ - patch
+ - update
+ - list
+- apiGroups:
+ - topology.node.k8s.io
+ resources:
+ - noderesourcetopologies
+ verbs:
+ - create
+ - get
+ - update
+- apiGroups:
+ - nfd.k8s-sigs.io
+ resources:
+ - nodefeaturerules
+ verbs:
+ - get
+ - list
+ - watch
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: nfd-master
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: nfd-master
+subjects:
+- kind: ServiceAccount
+ name: nfd-master
+ namespace: node-feature-discovery
+---
+apiVersion: v1
+data:
+ nfd-worker.conf: |
+ #core:
+ # labelWhiteList:
+ # noPublish: false
+ # sleepInterval: 60s
+ # featureSources: [all]
+ # labelSources: [all]
+ # klog:
+ # addDirHeader: false
+ # alsologtostderr: false
+ # logBacktraceAt:
+ # logtostderr: true
+ # skipHeaders: false
+ # stderrthreshold: 2
+ # v: 0
+ # vmodule:
+ ## NOTE: the following options are not dynamically run-time configurable
+ ## and require a nfd-worker restart to take effect after being changed
+ # logDir:
+ # logFile:
+ # logFileMaxSize: 1800
+ # skipLogHeaders: false
+ #sources:
+ # cpu:
+ # cpuid:
+ ## NOTE: whitelist has priority over blacklist
+ # attributeBlacklist:
+ # - "BMI1"
+ # - "BMI2"
+ # - "CLMUL"
+ # - "CMOV"
+ # - "CX16"
+ # - "ERMS"
+ # - "F16C"
+ # - "HTT"
+ # - "LZCNT"
+ # - "MMX"
+ # - "MMXEXT"
+ # - "NX"
+ # - "POPCNT"
+ # - "RDRAND"
+ # - "RDSEED"
+ # - "RDTSCP"
+ # - "SGX"
+ # - "SSE"
+ # - "SSE2"
+ # - "SSE3"
+ # - "SSE4"
+ # - "SSE42"
+ # - "SSSE3"
+ # attributeWhitelist:
+ # kernel:
+ # kconfigFile: "/path/to/kconfig"
+ # configOpts:
+ # - "NO_HZ"
+ # - "X86"
+ # - "DMI"
+ # pci:
+ # deviceClassWhitelist:
+ # - "0200"
+ # - "03"
+ # - "12"
+ # deviceLabelFields:
+ # - "class"
+ # - "vendor"
+ # - "device"
+ # - "subsystem_vendor"
+ # - "subsystem_device"
+ # usb:
+ # deviceClassWhitelist:
+ # - "0e"
+ # - "ef"
+ # - "fe"
+ # - "ff"
+ # deviceLabelFields:
+ # - "class"
+ # - "vendor"
+ # - "device"
+ # custom:
+ # # The following feature demonstrates the capabilities of the matchFeatures
+ # - name: "my custom rule"
+ # labels:
+ # my-ng-feature: "true"
+ # # matchFeatures implements a logical AND over all matcher terms in the
+ # # list (i.e. all of the terms, or per-feature matchers, must match)
+ # matchFeatures:
+ # - feature: cpu.cpuid
+ # matchExpressions:
+ # AVX512F: {op: Exists}
+ # - feature: cpu.cstate
+ # matchExpressions:
+ # enabled: {op: IsTrue}
+ # - feature: cpu.pstate
+ # matchExpressions:
+ # no_turbo: {op: IsFalse}
+ # scaling_governor: {op: In, value: ["performance"]}
+ # - feature: cpu.rdt
+ # matchExpressions:
+ # RDTL3CA: {op: Exists}
+ # - feature: cpu.sst
+ # matchExpressions:
+ # bf.enabled: {op: IsTrue}
+ # - feature: cpu.topology
+ # matchExpressions:
+ # hardware_multithreading: {op: IsFalse}
+ #
+ # - feature: kernel.config
+ # matchExpressions:
+ # X86: {op: Exists}
+ # LSM: {op: InRegexp, value: ["apparmor"]}
+ # - feature: kernel.loadedmodule
+ # matchExpressions:
+ # e1000e: {op: Exists}
+ # - feature: kernel.selinux
+ # matchExpressions:
+ # enabled: {op: IsFalse}
+ # - feature: kernel.version
+ # matchExpressions:
+ # major: {op: In, value: ["5"]}
+ # minor: {op: Gt, value: ["10"]}
+ #
+ # - feature: storage.block
+ # matchExpressions:
+ # rotational: {op: In, value: ["0"]}
+ # dax: {op: In, value: ["0"]}
+ #
+ # - feature: network.device
+ # matchExpressions:
+ # operstate: {op: In, value: ["up"]}
+ # speed: {op: Gt, value: ["100"]}
+ #
+ # - feature: memory.numa
+ # matchExpressions:
+ # node_count: {op: Gt, value: ["2"]}
+ # - feature: memory.nv
+ # matchExpressions:
+ # devtype: {op: In, value: ["nd_dax"]}
+ # mode: {op: In, value: ["memory"]}
+ #
+ # - feature: system.osrelease
+ # matchExpressions:
+ # ID: {op: In, value: ["fedora", "centos"]}
+ # - feature: system.name
+ # matchExpressions:
+ # nodename: {op: InRegexp, value: ["^worker-X"]}
+ #
+ # - feature: local.label
+ # matchExpressions:
+ # custom-feature-knob: {op: Gt, value: ["100"]}
+ #
+ # # The following feature demonstrates the capabilities of the matchAny
+ # - name: "my matchAny rule"
+ # labels:
+ # my-ng-feature-2: "my-value"
+ # # matchAny implements a logical IF over all elements (sub-matchers) in
+ # # the list (i.e. at least one feature matcher must match)
+ # matchAny:
+ # - matchFeatures:
+ # - feature: kernel.loadedmodule
+ # matchExpressions:
+ # driver-module-X: {op: Exists}
+ # - feature: pci.device
+ # matchExpressions:
+ # vendor: {op: In, value: ["8086"]}
+ # class: {op: In, value: ["0200"]}
+ # - matchFeatures:
+ # - feature: kernel.loadedmodule
+ # matchExpressions:
+ # driver-module-Y: {op: Exists}
+ # - feature: usb.device
+ # matchExpressions:
+ # vendor: {op: In, value: ["8086"]}
+ # class: {op: In, value: ["02"]}
+ #
+ # # The following features demonstreate label templating capabilities
+ # - name: "my template rule"
+ # labelsTemplate: |
+ # {{ '{{' }} range .system.osrelease {{ '}}' }}my-system-feature.{{ '{{' }} .Name {{ '}}' }}={{ '{{' }} .Value {{ '}}' }}
+ # {{ '{{' }} end {{ '}}' }}
+ # matchFeatures:
+ # - feature: system.osrelease
+ # matchExpressions:
+ # ID: {op: InRegexp, value: ["^open.*"]}
+ # VERSION_ID.major: {op: In, value: ["13", "15"]}
+ #
+ # - name: "my template rule 2"
+ # labelsTemplate: |
+ # {{ '{{' }} range .pci.device {{ '}}' }}my-pci-device.{{ '{{' }} .class {{ '}}' }}-{{ '{{' }} .device {{ '}}' }}=with-cpuid
+ # {{ '{{' }} end {{ '}}' }}
+ # matchFeatures:
+ # - feature: pci.device
+ # matchExpressions:
+ # class: {op: InRegexp, value: ["^06"]}
+ # vendor: ["8086"]
+ # - feature: cpu.cpuid
+ # matchExpressions:
+ # AVX: {op: Exists}
+ #
+ # # The following examples demonstrate vars field and back-referencing
+ # # previous labels and vars
+ # - name: "my dummy kernel rule"
+ # labels:
+ # "my.kernel.feature": "true"
+ # matchFeatures:
+ # - feature: kernel.version
+ # matchExpressions:
+ # major: {op: Gt, value: ["2"]}
+ #
+ # - name: "my dummy rule with no labels"
+ # vars:
+ # "my.dummy.var": "1"
+ # matchFeatures:
+ # - feature: cpu.cpuid
+ # matchExpressions: {}
+ #
+ # - name: "my rule using backrefs"
+ # labels:
+ # "my.backref.feature": "true"
+ # matchFeatures:
+ # - feature: rule.matched
+ # matchExpressions:
+ # my.kernel.feature: {op: IsTrue}
+ # my.dummy.var: {op: Gt, value: ["0"]}
+ #
+kind: ConfigMap
+metadata:
+ name: nfd-worker-conf
+ namespace: node-feature-discovery
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: nfd-master
+ namespace: node-feature-discovery
+spec:
+ ports:
+ - port: 8080
+ protocol: TCP
+ selector:
+ app: nfd-master
+ type: ClusterIP
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ labels:
+ app: nfd
+ name: nfd-master
+ namespace: node-feature-discovery
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: nfd-master
+ template:
+ metadata:
+ labels:
+ app: nfd-master
+ spec:
+ affinity:
+ nodeAffinity:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ - preference:
+ matchExpressions:
+ - key: node-role.kubernetes.io/master
+ operator: In
+ values:
+ - ""
+ weight: 1
+ - preference:
+ matchExpressions:
+ - key: node-role.kubernetes.io/control-plane
+ operator: In
+ values:
+ - ""
+ weight: 1
+ containers:
+ - args:
+ - "-ca-file=/etc/kubernetes/node-feature-discovery/certs/ca.crt"
+ - "-key-file=/etc/kubernetes/node-feature-discovery/certs/tls.key"
+ - "-cert-file=/etc/kubernetes/node-feature-discovery/certs/tls.crt"
+ - -verify-node-name
+ command:
+ - nfd-master
+ env:
+ - name: NODE_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: spec.nodeName
+ image: k8s.gcr.io/nfd/node-feature-discovery:v0.11.2
+ imagePullPolicy: IfNotPresent
+ livenessProbe:
+ exec:
+ command:
+ - /usr/bin/grpc_health_probe
+ - -addr=:8080
+ - -tls
+ - "-tls-ca-cert=/etc/kubernetes/node-feature-discovery/certs/ca.crt"
+ - "-tls-client-key=/etc/kubernetes/node-feature-discovery/certs/tls.key"
+ - "-tls-client-cert=/etc/kubernetes/node-feature-discovery/certs/tls.crt"
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ name: nfd-master
+ readinessProbe:
+ exec:
+ command:
+ - /usr/bin/grpc_health_probe
+ - -addr=:8080
+ - -tls
+ - "-tls-ca-cert=/etc/kubernetes/node-feature-discovery/certs/ca.crt"
+ - "-tls-client-key=/etc/kubernetes/node-feature-discovery/certs/tls.key"
+ - "-tls-client-cert=/etc/kubernetes/node-feature-discovery/certs/tls.crt"
+ failureThreshold: 10
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop:
+ - ALL
+ readOnlyRootFilesystem: true
+ runAsNonRoot: true
+ volumeMounts:
+ - mountPath: /etc/kubernetes/node-feature-discovery/certs/
+ name: tls-certs
+ readOnly: true
+ serviceAccount: nfd-master
+ tolerations:
+ - effect: NoSchedule
+ key: node-role.kubernetes.io/master
+ operator: Equal
+ value: ""
+ - effect: NoSchedule
+ key: node-role.kubernetes.io/control-plane
+ operator: Equal
+ value: ""
+ volumes:
+ - name: tls-certs
+ secret:
+ secretName: nfd-master-cert
+---
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+ labels:
+ app: nfd
+ name: nfd-worker
+ namespace: node-feature-discovery
+spec:
+ selector:
+ matchLabels:
+ app: nfd-worker
+ template:
+ metadata:
+ labels:
+ app: nfd-worker
+ spec:
+ containers:
+ - args:
+ - -server=nfd-master:8080
+ - "-ca-file=/etc/kubernetes/node-feature-discovery/certs/ca.crt"
+ - "-key-file=/etc/kubernetes/node-feature-discovery/certs/tls.key"
+ - "-cert-file=/etc/kubernetes/node-feature-discovery/certs/tls.crt"
+ command:
+ - nfd-worker
+ env:
+ - name: NODE_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: spec.nodeName
+ image: k8s.gcr.io/nfd/node-feature-discovery:v0.11.2
+ imagePullPolicy: IfNotPresent
+ name: nfd-worker
+ securityContext:
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop:
+ - ALL
+ readOnlyRootFilesystem: true
+ runAsNonRoot: true
+ volumeMounts:
+ - mountPath: /host-boot
+ name: host-boot
+ readOnly: true
+ - mountPath: /host-etc/os-release
+ name: host-os-release
+ readOnly: true
+ - mountPath: /host-sys
+ name: host-sys
+ readOnly: true
+ - mountPath: /host-usr/lib
+ name: host-usr-lib
+ readOnly: true
+ - mountPath: /etc/kubernetes/node-feature-discovery/source.d/
+ name: source-d
+ readOnly: true
+ - mountPath: /etc/kubernetes/node-feature-discovery/features.d/
+ name: features-d
+ readOnly: true
+ - mountPath: /etc/kubernetes/node-feature-discovery
+ name: nfd-worker-conf
+ readOnly: true
+ - mountPath: /etc/kubernetes/node-feature-discovery/certs/
+ name: tls-certs
+ readOnly: true
+ dnsPolicy: ClusterFirstWithHostNet
+ volumes:
+ - hostPath:
+ path: /boot
+ name: host-boot
+ - hostPath:
+ path: /etc/os-release
+ name: host-os-release
+ - hostPath:
+ path: /sys
+ name: host-sys
+ - hostPath:
+ path: /usr/lib
+ name: host-usr-lib
+ - hostPath:
+ path: /etc/kubernetes/node-feature-discovery/source.d/
+ name: source-d
+ - hostPath:
+ path: /etc/kubernetes/node-feature-discovery/features.d/
+ name: features-d
+ - configMap:
+ name: nfd-worker-conf
+ name: nfd-worker-conf
+ - name: tls-certs
+ hostPath:
+ path: /etc/kubernetes/node-feature-discovery/certs
diff --git a/roles/kubernetes/addons/node-feature-discovery/templates/kustomization.yml.j2 b/roles/kubernetes/addons/node-feature-discovery/templates/kustomization.yml.j2
new file mode 100644
index 00000000..b8b81411
--- /dev/null
+++ b/roles/kubernetes/addons/node-feature-discovery/templates/kustomization.yml.j2
@@ -0,0 +1,14 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+
+resources:
+ - config.yml
+
+secretGenerator:
+ - name: nfd-master-cert
+ namespace: node-feature-discovery
+ type: "kubernetes.io/tls"
+ files:
+ - ca.crt=ca/crt.pem
+ - tls.crt=ca/master.crt
+ - tls.key=ca/master.key