diff --git a/cdi-chart/crds.obscpio b/cdi-chart/crds/cdi.yaml similarity index 99% rename from cdi-chart/crds.obscpio rename to cdi-chart/crds/cdi.yaml index 934dbbb..8621e0f 100644 Binary files a/cdi-chart/crds.obscpio and b/cdi-chart/crds/cdi.yaml differ diff --git a/cdi-chart/templates.obscpio b/cdi-chart/templates.obscpio deleted file mode 100644 index f1fb05f..0000000 Binary files a/cdi-chart/templates.obscpio and /dev/null differ diff --git a/cdi-chart/templates/NOTES.txt b/cdi-chart/templates/NOTES.txt new file mode 100644 index 0000000..f6a43a4 --- /dev/null +++ b/cdi-chart/templates/NOTES.txt @@ -0,0 +1,2 @@ +Verify that all CDI components are installed correctly: + kubectl get all -n {{ .Release.Namespace }} diff --git a/cdi-chart/templates/_helpers.tpl b/cdi-chart/templates/_helpers.tpl new file mode 100644 index 0000000..5f2e091 --- /dev/null +++ b/cdi-chart/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "cdi.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "cdi.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "cdi.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "cdi.labels" -}} +helm.sh/chart: {{ include "cdi.chart" . }} +{{ include "cdi.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "cdi.selectorLabels" -}} +app.kubernetes.io/name: {{ include "cdi.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "cdi.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "cdi.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/cdi-chart/templates/_hooks.tpl b/cdi-chart/templates/_hooks.tpl new file mode 100644 index 0000000..d857801 --- /dev/null +++ b/cdi-chart/templates/_hooks.tpl @@ -0,0 +1,47 @@ +{{/* Hook annotations */}} +{{- define "cdi.hook.annotations" -}} + annotations: + "helm.sh/hook": {{ .hookType }} + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + "helm.sh/hook-weight": {{ .hookWeight | quote }} +{{- end -}} + +{{/* Namespace modifying hook annotations */}} +{{- define "cdi.namespaceHook.annotations" -}} +{{ template "cdi.hook.annotations" merge (dict "hookType" "pre-install") . }} +{{- end -}} + +{{/* CRD upgrading hook annotations */}} +{{- define "cdi.crdUpgradeHook.annotations" -}} +{{ template "cdi.hook.annotations" merge (dict "hookType" "pre-upgrade") . }} +{{- end -}} + +{{/* Custom resource uninstalling hook annotations */}} +{{- define "cdi.crUninstallHook.annotations" -}} +{{ template "cdi.hook.annotations" merge (dict "hookType" "pre-delete") . }} +{{- end -}} + +{{/* CRD uninstalling hook annotations */}} +{{- define "cdi.crdUninstallHook.annotations" -}} +{{ template "cdi.hook.annotations" merge (dict "hookType" "post-delete") . }} +{{- end -}} + +{{/* Namespace modifying hook name */}} +{{- define "cdi.namespaceHook.name" -}} +{{ include "cdi.fullname" . }}-namespace-modify +{{- end }} + +{{/* CRD upgrading hook name */}} +{{- define "cdi.crdUpgradeHook.name" -}} +{{ include "cdi.fullname" . }}-crd-upgrade +{{- end }} + +{{/* Custom resource uninstalling hook name */}} +{{- define "cdi.crUninstallHook.name" -}} +{{ include "cdi.fullname" . }}-uninstall +{{- end }} + +{{/* CRD uninstalling hook name */}} +{{- define "cdi.crdUninstallHook.name" -}} +{{ include "cdi.fullname" . }}-crd-uninstall +{{- end }} diff --git a/cdi-chart/templates/cdi-operator.yaml b/cdi-chart/templates/cdi-operator.yaml new file mode 100644 index 0000000..f6ab6fe --- /dev/null +++ b/cdi-chart/templates/cdi-operator.yaml @@ -0,0 +1,671 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + operator.cdi.kubevirt.io: "" + name: cdi-operator-cluster +rules: + - apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterrolebindings + - clusterroles + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + verbs: + - get + - list + - watch + - update + - create + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + - customresourcedefinitions/status + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - cdi.kubevirt.io + - upload.cdi.kubevirt.io + resources: + - '*' + verbs: + - '*' + - apiGroups: + - admissionregistration.k8s.io + resources: + - validatingwebhookconfigurations + - mutatingwebhookconfigurations + verbs: + - create + - list + - watch + - apiGroups: + - admissionregistration.k8s.io + resourceNames: + - cdi-api-dataimportcron-validate + - cdi-api-populator-validate + - cdi-api-datavolume-validate + - cdi-api-validate + - objecttransfer-api-validate + resources: + - validatingwebhookconfigurations + verbs: + - get + - update + - delete + - apiGroups: + - admissionregistration.k8s.io + resourceNames: + - cdi-api-datavolume-mutate + - cdi-api-pvc-mutate + resources: + - mutatingwebhookconfigurations + verbs: + - get + - update + - delete + - apiGroups: + - apiregistration.k8s.io + resources: + - apiservices + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - watch + - apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshots + verbs: + - get + - list + - watch + - apiGroups: + - cdi.kubevirt.io + resources: + - datavolumes + verbs: + - list + - get + - apiGroups: + - cdi.kubevirt.io + resources: + - datasources + verbs: + - get + - apiGroups: + - cdi.kubevirt.io + resources: + - volumeclonesources + verbs: + - get + - list + - watch + - apiGroups: + - cdi.kubevirt.io + resources: + - storageprofiles + verbs: + - get + - list + - watch + - apiGroups: + - cdi.kubevirt.io + resources: + - cdis + verbs: + - get + - list + - watch + - apiGroups: + - cdi.kubevirt.io + resources: + - cdiconfigs + verbs: + - get + - list + - watch + - apiGroups: + - cdi.kubevirt.io + resources: + - cdis/finalizers + verbs: + - update + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - get + - list + - watch + - create + - update + - delete + - deletecollection + - patch + - apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - watch + - update + - apiGroups: + - "" + resources: + - persistentvolumeclaims/finalizers + - pods/finalizers + verbs: + - update + - apiGroups: + - "" + resources: + - pods + - services + verbs: + - get + - list + - watch + - create + - delete + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - create + - apiGroups: + - storage.k8s.io + resources: + - storageclasses + - csidrivers + verbs: + - get + - list + - watch + - apiGroups: + - config.openshift.io + resources: + - proxies + - infrastructures + verbs: + - get + - list + - watch + - apiGroups: + - config.openshift.io + resources: + - clusterversions + verbs: + - get + - apiGroups: + - cdi.kubevirt.io + resources: + - '*' + verbs: + - '*' + - apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshots + - volumesnapshotclasses + - volumesnapshotcontents + verbs: + - get + - list + - watch + - create + - delete + - apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshots + verbs: + - update + - deletecollection + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - list + - watch + - apiGroups: + - scheduling.k8s.io + resources: + - priorityclasses + verbs: + - get + - list + - watch + - apiGroups: + - image.openshift.io + resources: + - imagestreams + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - secrets + verbs: + - create + - apiGroups: + - kubevirt.io + resources: + - virtualmachines/finalizers + verbs: + - update + - apiGroups: + - forklift.cdi.kubevirt.io + resources: + - ovirtvolumepopulators + - openstackvolumepopulators + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - get + - apiGroups: + - cdi.kubevirt.io + resources: + - dataimportcrons + verbs: + - get + - list + - update +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + operator.cdi.kubevirt.io: "" + name: cdi-operator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cdi-operator-cluster +subjects: + - kind: ServiceAccount + name: cdi-operator + namespace: {{ .Release.Namespace }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + operator.cdi.kubevirt.io: "" + name: cdi-operator + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app: containerized-data-importer + app.kubernetes.io/component: storage + app.kubernetes.io/managed-by: cdi-operator + cdi.kubevirt.io: "" + name: cdi-operator + namespace: {{ .Release.Namespace }} +rules: + - apiGroups: + - rbac.authorization.k8s.io + resources: + - rolebindings + - roles + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - "" + resources: + - serviceaccounts + - configmaps + - events + - secrets + - services + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - apps + resources: + - deployments + - deployments/finalizers + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - route.openshift.io + resources: + - routes + - routes/custom-host + verbs: + - get + - list + - watch + - create + - update + - apiGroups: + - config.openshift.io + resources: + - proxies + verbs: + - get + - list + - watch + - apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + - prometheusrules + verbs: + - get + - list + - watch + - create + - delete + - update + - patch + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - create + - update + - apiGroups: + - "" + resources: + - secrets + - configmaps + verbs: + - get + - list + - watch + - create + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - watch + - apiGroups: + - batch + resources: + - cronjobs + verbs: + - get + - list + - watch + - create + - update + - deletecollection + - apiGroups: + - batch + resources: + - jobs + verbs: + - create + - deletecollection + - list + - watch + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - create + - update + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - list + - watch + - apiGroups: + - route.openshift.io + resources: + - routes + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - apiGroups: + - "" + resources: + - services + - endpoints + - pods + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app: containerized-data-importer + app.kubernetes.io/component: storage + app.kubernetes.io/managed-by: cdi-operator + cdi.kubevirt.io: "" + name: cdi-operator + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: cdi-operator +subjects: + - kind: ServiceAccount + name: cdi-operator + namespace: {{ .Release.Namespace }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + cdi.kubevirt.io: cdi-operator + name: cdi-operator + operator.cdi.kubevirt.io: "" + prometheus.cdi.kubevirt.io: "true" + name: cdi-operator + namespace: {{ .Release.Namespace }} +spec: + replicas: 1 + selector: + matchLabels: + name: cdi-operator + operator.cdi.kubevirt.io: "" + strategy: {} + template: + metadata: + labels: + cdi.kubevirt.io: cdi-operator + name: cdi-operator + operator.cdi.kubevirt.io: "" + prometheus.cdi.kubevirt.io: "true" + spec: + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchExpressions: + - key: cdi.kubevirt.io + operator: In + values: + - cdi-operator + topologyKey: kubernetes.io/hostname + weight: 1 + containers: + - env: + - name: DEPLOY_CLUSTER_RESOURCES + value: "true" + - name: OPERATOR_VERSION + value: {{ .Values.deployment.version }} + - name: CONTROLLER_IMAGE + value: {{ .Values.deployment.controllerImage }}:{{ .Values.deployment.version }} + - name: IMPORTER_IMAGE + value: {{ .Values.deployment.importerImage }}:{{ .Values.deployment.version }} + - name: CLONER_IMAGE + value: {{ .Values.deployment.clonerImage }}:{{ .Values.deployment.version }} + - name: OVIRT_POPULATOR_IMAGE + value: {{ .Values.deployment.importerImage }}:{{ .Values.deployment.version }} + - name: APISERVER_IMAGE + value: {{ .Values.deployment.apiserverImage }}:{{ .Values.deployment.version }} + - name: UPLOAD_SERVER_IMAGE + value: {{ .Values.deployment.uploadserverImage }}:{{ .Values.deployment.version }} + - name: UPLOAD_PROXY_IMAGE + value: {{ .Values.deployment.uploadproxyImage }}:{{ .Values.deployment.version }} + - name: VERBOSITY + value: "1" + - name: PULL_POLICY + value: {{ .Values.deployment.pullPolicy }} + - name: MONITORING_NAMESPACE + image: {{ .Values.deployment.operatorImage }}:{{ .Values.deployment.version }} + imagePullPolicy: {{ .Values.deployment.pullPolicy }} + name: cdi-operator + ports: + - containerPort: 8080 + name: metrics + protocol: TCP + resources: + requests: + cpu: 100m + memory: 150Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + nodeSelector: + kubernetes.io/os: linux + securityContext: + runAsNonRoot: true + serviceAccountName: cdi-operator + tolerations: + - key: CriticalAddonsOnly + operator: Exists diff --git a/cdi-chart/templates/cdi-uninstall-hooks.yaml b/cdi-chart/templates/cdi-uninstall-hooks.yaml new file mode 100644 index 0000000..d737539 --- /dev/null +++ b/cdi-chart/templates/cdi-uninstall-hooks.yaml @@ -0,0 +1,69 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crUninstallHook.name" . }} + {{ template "cdi.crUninstallHook.annotations" (dict "hookWeight" 1) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cdi.crUninstallHook.name" . }} + {{ template "cdi.crUninstallHook.annotations" (dict "hookWeight" 1) }} +rules: + - apiGroups: [ "cdi.kubevirt.io" ] + resources: [ "cdis" ] + resourceNames: + - "cdi" + verbs: [ "delete" ] + - apiGroups: [ "apps" ] + resources: [ "deployments" ] + verbs: [ "get", "list" ] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cdi.crUninstallHook.name" . }} + {{ template "cdi.crUninstallHook.annotations" (dict "hookWeight" 2) }} +subjects: + - kind: ServiceAccount + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crUninstallHook.name" . }} +roleRef: + kind: ClusterRole + name: {{ template "cdi.crUninstallHook.name" . }} + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: batch/v1 +kind: Job +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crUninstallHook.name" . }} + {{ template "cdi.crUninstallHook.annotations" (dict "hookWeight" 3) }} +spec: + template: + metadata: + name: {{ template "cdi.crUninstallHook.name" . }} + spec: + serviceAccountName: {{ template "cdi.crUninstallHook.name" . }} + restartPolicy: {{ .Values.hookRestartPolicy }} + containers: + - name: {{ template "cdi.crUninstallHook.name" . }} + image: {{ .Values.hookImage }} + securityContext: + {{- toYaml .Values.hookSecurityContext | nindent 12 }} + args: + - delete + - cdi + - cdi + - name: {{ template "cdi.crUninstallHook.name" . }}-cleanup + image: {{ .Values.hookImage }} + securityContext: + {{- toYaml .Values.hookSecurityContext | nindent 12 }} + args: + - wait + - --for=delete + - deployments/cdi-apiserver + - deployments/cdi-deployment + - deployments/cdi-uploadproxy + - --timeout=60s diff --git a/cdi-chart/templates/cdi.yaml b/cdi-chart/templates/cdi.yaml new file mode 100644 index 0000000..b3e476d --- /dev/null +++ b/cdi-chart/templates/cdi.yaml @@ -0,0 +1,21 @@ +apiVersion: cdi.kubevirt.io/v1beta1 +kind: CDI +metadata: + name: cdi +spec: + {{- with .Values.cdi.config }} + config: + {{- toYaml . | nindent 4 }} + {{- end }} + imagePullPolicy: {{ .Values.cdi.imagePullPolicy }} + {{- with .Values.cdi.infra }} + infra: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.cdi.uninstallStrategy }} + uninstallStrategy: {{ .Values.cdi.uninstallStrategy }} + {{- end }} + {{- with .Values.cdi.workload }} + workload: + {{- toYaml . | nindent 4 }} + {{- end }} diff --git a/cdi-chart/templates/crd-uninstall-hooks.yaml b/cdi-chart/templates/crd-uninstall-hooks.yaml new file mode 100644 index 0000000..19bdaf2 --- /dev/null +++ b/cdi-chart/templates/crd-uninstall-hooks.yaml @@ -0,0 +1,55 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crdUninstallHook.name" . }} + {{ template "cdi.crdUninstallHook.annotations" (dict "hookWeight" 1) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cdi.crdUninstallHook.name" . }} + {{ template "cdi.crdUninstallHook.annotations" (dict "hookWeight" 1) }} +rules: + - apiGroups: [ "apiextensions.k8s.io" ] + resources: [ "customresourcedefinitions" ] + resourceNames: + - "cdis.cdi.kubevirt.io" + verbs: [ "delete" ] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cdi.crdUninstallHook.name" . }} + {{ template "cdi.crdUninstallHook.annotations" (dict "hookWeight" 2) }} +subjects: + - kind: ServiceAccount + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crdUninstallHook.name" . }} +roleRef: + kind: ClusterRole + name: {{ template "cdi.crdUninstallHook.name" . }} + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: batch/v1 +kind: Job +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crdUninstallHook.name" . }} + {{ template "cdi.crdUninstallHook.annotations" (dict "hookWeight" 3) }} +spec: + template: + metadata: + name: {{ template "cdi.crdUninstallHook.name" . }} + spec: + serviceAccountName: {{ template "cdi.crdUninstallHook.name" . }} + restartPolicy: {{ .Values.hookRestartPolicy }} + containers: + - name: {{ template "cdi.crdUninstallHook.name" . }} + image: {{ .Values.hookImage }} + args: + - delete + - customresourcedefinitions + - cdis.cdi.kubevirt.io + securityContext: + {{- toYaml .Values.hookSecurityContext | nindent 12 }} diff --git a/cdi-chart/templates/crd-upgrade-hooks.yaml b/cdi-chart/templates/crd-upgrade-hooks.yaml new file mode 100644 index 0000000..f650adc --- /dev/null +++ b/cdi-chart/templates/crd-upgrade-hooks.yaml @@ -0,0 +1,80 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Release.Namespace }} + name: cdi-crd-manifest + {{ template "cdi.crdUpgradeHook.annotations" (dict "hookWeight" 1) }} +data: + crd: |- + {{ $.Files.Get "crds/cdi.yaml" | nindent 4 }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crdUpgradeHook.name" . }} + {{ template "cdi.crdUpgradeHook.annotations" (dict "hookWeight" 2) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cdi.crdUpgradeHook.name" . }} + {{ template "cdi.crdUpgradeHook.annotations" (dict "hookWeight" 2) }} +rules: + - apiGroups: [ "" ] + resources: [ "configmaps" ] + resourceNames: + - "cdi-crd-manifest" + verbs: [ "get" ] + - apiGroups: [ "apiextensions.k8s.io" ] + resources: [ "customresourcedefinitions" ] + resourceNames: + - "cdis.cdi.kubevirt.io" + verbs: [ "get", "patch" ] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cdi.crdUpgradeHook.name" . }} + {{ template "cdi.crdUpgradeHook.annotations" (dict "hookWeight" 3) }} +subjects: + - kind: ServiceAccount + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crdUpgradeHook.name" . }} +roleRef: + kind: ClusterRole + name: {{ template "cdi.crdUpgradeHook.name" . }} + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: batch/v1 +kind: Job +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.crdUpgradeHook.name" . }} + {{ template "cdi.crdUpgradeHook.annotations" (dict "hookWeight" 4) }} +spec: + template: + metadata: + name: {{ template "cdi.crdUpgradeHook.name" . }} + spec: + serviceAccountName: {{ template "cdi.crdUpgradeHook.name" . }} + restartPolicy: {{ .Values.hookRestartPolicy }} + containers: + - name: {{ template "cdi.crdUpgradeHook.name" . }} + image: {{ .Values.hookImage }} + args: + - apply + - -f + - /etc/manifests/crd.yaml + securityContext: + {{- toYaml .Values.hookSecurityContext | nindent 12 }} + volumeMounts: + - name: crd-volume + mountPath: /etc/manifests + volumes: + - name: crd-volume + configMap: + name: cdi-crd-manifest + items: + - key: crd + path: crd.yaml diff --git a/cdi-chart/templates/namespace-hooks.yaml b/cdi-chart/templates/namespace-hooks.yaml new file mode 100644 index 0000000..30d16a4 --- /dev/null +++ b/cdi-chart/templates/namespace-hooks.yaml @@ -0,0 +1,56 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.namespaceHook.name" . }} + {{ template "cdi.namespaceHook.annotations" (dict "hookWeight" 1) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "cdi.namespaceHook.name" . }} + {{ template "cdi.namespaceHook.annotations" (dict "hookWeight" 1) }} +rules: + - apiGroups: [ "" ] + resources: [ "namespaces" ] + resourceNames: + - {{ .Release.Namespace | quote }} + verbs: [ "get", "patch" ] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "cdi.namespaceHook.name" . }} + {{ template "cdi.namespaceHook.annotations" (dict "hookWeight" 2) }} +subjects: + - kind: ServiceAccount + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.namespaceHook.name" . }} +roleRef: + kind: ClusterRole + name: {{ template "cdi.namespaceHook.name" . }} + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: batch/v1 +kind: Job +metadata: + namespace: {{ .Release.Namespace }} + name: {{ template "cdi.namespaceHook.name" . }} + {{ template "cdi.namespaceHook.annotations" (dict "hookWeight" 3) }} +spec: + template: + metadata: + name: {{ template "cdi.namespaceHook.name" . }} + spec: + serviceAccountName: {{ template "cdi.namespaceHook.name" . }} + restartPolicy: {{ .Values.hookRestartPolicy }} + containers: + - name: {{ template "cdi.namespaceHook.name" . }} + securityContext: + {{- toYaml .Values.hookSecurityContext | nindent 12 }} + image: {{ .Values.hookImage }} + args: + - label + - namespace + - {{ .Release.Namespace }} + - cdi.kubevirt.io= diff --git a/metal3-chart/charts.obscpio b/metal3-chart/charts.obscpio deleted file mode 100644 index c3b1f6c..0000000 Binary files a/metal3-chart/charts.obscpio and /dev/null differ diff --git a/metal3-chart/charts/baremetal-operator/.helmignore b/metal3-chart/charts/baremetal-operator/.helmignore new file mode 100644 index 0000000..1b9a9cc --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/metal3-chart/charts/baremetal-operator/Chart.yaml b/metal3-chart/charts/baremetal-operator/Chart.yaml new file mode 100644 index 0000000..1900441 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: 0.6.1 +description: A Helm chart for baremetal-operator, used by Metal3 +name: baremetal-operator +type: application +version: 0.5.0 diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-baremetalhosts.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-baremetalhosts.yaml new file mode 100644 index 0000000..6406700 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/crds/customresource-baremetalhosts.yaml @@ -0,0 +1,1148 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: baremetal-operator-system/baremetal-operator-serving-cert + controller-gen.kubebuilder.io/version: v0.12.1 + labels: + clusterctl.cluster.x-k8s.io: "" + name: baremetalhosts.metal3.io +spec: + group: metal3.io + names: + kind: BareMetalHost + listKind: BareMetalHostList + plural: baremetalhosts + shortNames: + - bmh + - bmhost + singular: baremetalhost + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Operational status + jsonPath: .status.operationalStatus + name: Status + priority: 1 + type: string + - description: Provisioning status + jsonPath: .status.provisioning.state + name: State + type: string + - description: Consumer using this host + jsonPath: .spec.consumerRef.name + name: Consumer + type: string + - description: Address of management controller + jsonPath: .spec.bmc.address + name: BMC + priority: 1 + type: string + - description: The type of hardware detected + jsonPath: .status.hardwareProfile + name: Hardware_Profile + priority: 1 + type: string + - description: Whether the host is online or not + jsonPath: .spec.online + name: Online + type: string + - description: Type of the most recent error + jsonPath: .status.errorType + name: Error + type: string + - description: Time duration since creation of BaremetalHost + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: BareMetalHost is the Schema for the baremetalhosts 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: BareMetalHostSpec defines the desired state of BareMetalHost. + properties: + architecture: + description: CPU architecture of the host, e.g. "x86_64" or "aarch64". + If unset, eventually populated by inspection. + type: string + automatedCleaningMode: + default: metadata + description: When set to disabled, automated cleaning will be avoided + during provisioning and deprovisioning. + enum: + - metadata + - disabled + type: string + bmc: + description: How do we connect to the BMC? + properties: + address: + description: Address holds the URL for accessing the controller + on the network. + type: string + credentialsName: + description: The name of the secret containing the BMC credentials + (requires keys "username" and "password"). + type: string + disableCertificateVerification: + description: DisableCertificateVerification disables verification + of server certificates when using HTTPS to connect to the BMC. + This is required when the server certificate is self-signed, + but is insecure because it allows a man-in-the-middle to intercept + the connection. + type: boolean + required: + - address + - credentialsName + type: object + bootMACAddress: + description: Which MAC address will PXE boot? This is optional for + some types, but required for libvirt VMs driven by vbmc. + pattern: '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}' + type: string + bootMode: + description: Select the method of initializing the hardware during + boot. Defaults to UEFI. + enum: + - UEFI + - UEFISecureBoot + - legacy + type: string + consumerRef: + description: ConsumerRef can be used to store information about something + that is using a host. When it is not empty, the host is considered + "in use". + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of + an entire object, this string should contain a valid JSON/Go + field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen + only to have some well-defined way of referencing a part of + an object. TODO: this design is not final and this field is + subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference + is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + type: object + x-kubernetes-map-type: atomic + customDeploy: + description: A custom deploy procedure. + properties: + method: + description: Custom deploy method name. This name is specific + to the deploy ramdisk used. If you don't have a custom deploy + ramdisk, you shouldn't use CustomDeploy. + type: string + required: + - method + type: object + description: + description: Description is a human-entered text used to help identify + the host + type: string + externallyProvisioned: + description: ExternallyProvisioned means something else is managing + the image running on the host and the operator should only manage + the power status and hardware inventory inspection. If the Image + field is filled in, this field is ignored. + type: boolean + firmware: + description: BIOS configuration for bare metal server + properties: + simultaneousMultithreadingEnabled: + description: 'Allows a single physical processor core to appear + as several logical processors. This supports following options: + true, false.' + enum: + - true + - false + type: boolean + sriovEnabled: + description: 'SR-IOV support enables a hypervisor to create virtual + instances of a PCI-express device, potentially increasing performance. + This supports following options: true, false.' + enum: + - true + - false + type: boolean + virtualizationEnabled: + description: 'Supports the virtualization of platform hardware. + This supports following options: true, false.' + enum: + - true + - false + type: boolean + type: object + hardwareProfile: + description: What is the name of the hardware profile for this host? + Hardware profiles are deprecated and should not be used. Use the + separate fields Architecture and RootDeviceHints instead. Set to + "empty" to prepare for the future version of the API without hardware + profiles. + type: string + image: + description: Image holds the details of the image to be provisioned. + properties: + checksum: + description: Checksum is the checksum for the image. + type: string + checksumType: + description: ChecksumType is the checksum algorithm for the image, + e.g md5, sha256 or sha512. The special value "auto" can be used + to detect the algorithm from the checksum. If missing, MD5 is + used. If in doubt, use "auto". + enum: + - md5 + - sha256 + - sha512 + - auto + type: string + format: + description: DiskFormat contains the format of the image (raw, + qcow2, ...). Needs to be set to raw for raw images streaming. + Note live-iso means an iso referenced by the url will be live-booted + and not deployed to disk, and in this case the checksum options + are not required and if specified will be ignored. + enum: + - raw + - qcow2 + - vdi + - vmdk + - live-iso + type: string + url: + description: URL is a location of an image to deploy. + type: string + required: + - url + type: object + metaData: + description: MetaData holds the reference to the Secret containing + host metadata (e.g. meta_data.json) which is passed to the Config + Drive. + properties: + name: + description: name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: namespace defines the space within which the secret + name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + networkData: + description: NetworkData holds the reference to the Secret containing + network configuration (e.g content of network_data.json) which is + passed to the Config Drive. + properties: + name: + description: name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: namespace defines the space within which the secret + name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + online: + description: Should the server be online? + type: boolean + preprovisioningNetworkDataName: + description: PreprovisioningNetworkDataName is the name of the Secret + in the local namespace containing network configuration (e.g content + of network_data.json) which is passed to the preprovisioning image, + and to the Config Drive if not overridden by specifying NetworkData. + type: string + raid: + description: RAID configuration for bare metal server + properties: + hardwareRAIDVolumes: + description: The list of logical disks for hardware RAID, if rootDeviceHints + isn't used, first volume is root volume. You can set the value + of this field to `[]` to clear all the hardware RAID configurations. + items: + description: HardwareRAIDVolume defines the desired configuration + of volume in hardware RAID. + properties: + controller: + description: The name of the RAID controller to use + type: string + level: + description: 'RAID level for the logical disk. The following + levels are supported: 0;1;2;5;6;1+0;5+0;6+0.' + enum: + - "0" + - "1" + - "2" + - "5" + - "6" + - 1+0 + - 5+0 + - 6+0 + type: string + name: + description: Name of the volume. Should be unique within + the Node. If not specified, volume name will be auto-generated. + maxLength: 64 + type: string + numberOfPhysicalDisks: + description: Integer, number of physical disks to use for + the logical disk. Defaults to minimum number of disks + required for the particular RAID level. + minimum: 1 + type: integer + physicalDisks: + description: Optional list of physical disk names to be + used for the Hardware RAID volumes. The disk names are + interpreted by the Hardware RAID controller, and the format + is hardware specific. + items: + type: string + type: array + rotational: + description: Select disks with only rotational or solid-state + storage + type: boolean + sizeGibibytes: + description: Size (Integer) of the logical disk to be created + in GiB. If unspecified or set be 0, the maximum capacity + of disk will be used for logical disk. + minimum: 0 + type: integer + required: + - level + type: object + nullable: true + type: array + softwareRAIDVolumes: + description: The list of logical disks for software RAID, if rootDeviceHints + isn't used, first volume is root volume. If HardwareRAIDVolumes + is set this item will be invalid. The number of created Software + RAID devices must be 1 or 2. If there is only one Software RAID + device, it has to be a RAID-1. If there are two, the first one + has to be a RAID-1, while the RAID level for the second one + can be 0, 1, or 1+0. As the first RAID device will be the deployment + device, enforcing a RAID-1 reduces the risk of ending up with + a non-booting node in case of a disk failure. Software RAID + will always be deleted. + items: + description: SoftwareRAIDVolume defines the desired configuration + of volume in software RAID. + properties: + level: + description: 'RAID level for the logical disk. The following + levels are supported: 0;1;1+0.' + enum: + - "0" + - "1" + - 1+0 + type: string + physicalDisks: + description: A list of device hints, the number of items + should be greater than or equal to 2. + items: + description: RootDeviceHints holds the hints for specifying + the storage location for the root filesystem for the + image. + properties: + deviceName: + description: A Linux device name like "/dev/vda", + or a by-path link to it like "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0". + The hint must match the actual value exactly. + type: string + hctl: + description: A SCSI bus address like 0:0:0:0. The + hint must match the actual value exactly. + type: string + minSizeGigabytes: + description: The minimum size of the device in Gigabytes. + minimum: 0 + type: integer + model: + description: A vendor-specific device identifier. + The hint can be a substring of the actual value. + type: string + rotational: + description: True if the device should use spinning + media, false otherwise. + type: boolean + serialNumber: + description: Device serial number. The hint must match + the actual value exactly. + type: string + vendor: + description: The name of the vendor or manufacturer + of the device. The hint can be a substring of the + actual value. + type: string + wwn: + description: Unique storage identifier. The hint must + match the actual value exactly. + type: string + wwnVendorExtension: + description: Unique vendor storage identifier. The + hint must match the actual value exactly. + type: string + wwnWithExtension: + description: Unique storage identifier with the vendor + extension appended. The hint must match the actual + value exactly. + type: string + type: object + minItems: 2 + type: array + sizeGibibytes: + description: Size (Integer) of the logical disk to be created + in GiB. If unspecified or set be 0, the maximum capacity + of disk will be used for logical disk. + minimum: 0 + type: integer + required: + - level + type: object + maxItems: 2 + nullable: true + type: array + type: object + rootDeviceHints: + description: Provide guidance about how to choose the device for the + image being provisioned. + properties: + deviceName: + description: A Linux device name like "/dev/vda", or a by-path + link to it like "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0". + The hint must match the actual value exactly. + type: string + hctl: + description: A SCSI bus address like 0:0:0:0. The hint must match + the actual value exactly. + type: string + minSizeGigabytes: + description: The minimum size of the device in Gigabytes. + minimum: 0 + type: integer + model: + description: A vendor-specific device identifier. The hint can + be a substring of the actual value. + type: string + rotational: + description: True if the device should use spinning media, false + otherwise. + type: boolean + serialNumber: + description: Device serial number. The hint must match the actual + value exactly. + type: string + vendor: + description: The name of the vendor or manufacturer of the device. + The hint can be a substring of the actual value. + type: string + wwn: + description: Unique storage identifier. The hint must match the + actual value exactly. + type: string + wwnVendorExtension: + description: Unique vendor storage identifier. The hint must match + the actual value exactly. + type: string + wwnWithExtension: + description: Unique storage identifier with the vendor extension + appended. The hint must match the actual value exactly. + type: string + type: object + taints: + description: Taints is the full, authoritative list of taints to apply + to the corresponding Machine. This list will overwrite any modifications + made to the Machine on an ongoing basis. + items: + description: The node this Taint is attached to has the "effect" + on any pod that does not tolerate the Taint. + properties: + effect: + description: Required. The effect of the taint on pods that + do not tolerate the taint. Valid effects are NoSchedule, PreferNoSchedule + and NoExecute. + type: string + key: + description: Required. The taint key to be applied to a node. + type: string + timeAdded: + description: TimeAdded represents the time at which the taint + was added. It is only written for NoExecute taints. + format: date-time + type: string + value: + description: The taint value corresponding to the taint key. + type: string + required: + - effect + - key + type: object + type: array + userData: + description: UserData holds the reference to the Secret containing + the user data to be passed to the host before it boots. + properties: + name: + description: name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: namespace defines the space within which the secret + name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + required: + - online + type: object + status: + description: BareMetalHostStatus defines the observed state of BareMetalHost. + properties: + errorCount: + default: 0 + description: ErrorCount records how many times the host has encoutered + an error since the last successful operation + type: integer + errorMessage: + description: the last error message reported by the provisioning subsystem + type: string + errorType: + description: ErrorType indicates the type of failure encountered when + the OperationalStatus is OperationalStatusError + enum: + - provisioned registration error + - registration error + - inspection error + - preparation error + - provisioning error + - power management error + type: string + goodCredentials: + description: the last credentials we were able to validate as working + properties: + credentials: + description: SecretReference represents a Secret Reference. It + has enough information to retrieve secret in any namespace + properties: + name: + description: name is unique within a namespace to reference + a secret resource. + type: string + namespace: + description: namespace defines the space within which the + secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + credentialsVersion: + type: string + type: object + hardware: + description: The hardware discovered to exist on the host. + properties: + cpu: + description: CPU describes one processor on the host. + properties: + arch: + type: string + clockMegahertz: + description: ClockSpeed is a clock speed in MHz + format: double + type: number + count: + type: integer + flags: + items: + type: string + type: array + model: + type: string + type: object + firmware: + description: Firmware describes the firmware on the host. + properties: + bios: + description: The BIOS for this firmware + properties: + date: + description: The release/build date for this BIOS + type: string + vendor: + description: The vendor name for this BIOS + type: string + version: + description: The version of the BIOS + type: string + type: object + type: object + hostname: + type: string + nics: + items: + description: NIC describes one network interface on the host. + properties: + ip: + description: The IP address of the interface. This will + be an IPv4 or IPv6 address if one is present. If both + IPv4 and IPv6 addresses are present in a dual-stack environment, + two nics will be output, one with each IP. + type: string + mac: + description: The device MAC address + pattern: '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}' + type: string + model: + description: The vendor and product IDs of the NIC, e.g. + "0x8086 0x1572" + type: string + name: + description: The name of the network interface, e.g. "en0" + type: string + pxe: + description: Whether the NIC is PXE Bootable + type: boolean + speedGbps: + description: The speed of the device in Gigabits per second + type: integer + vlanId: + description: The untagged VLAN ID + format: int32 + maximum: 4094 + minimum: 0 + type: integer + vlans: + description: The VLANs available + items: + description: VLAN represents the name and ID of a VLAN. + properties: + id: + description: VLANID is a 12-bit 802.1Q VLAN identifier + format: int32 + maximum: 4094 + minimum: 0 + type: integer + name: + type: string + type: object + type: array + type: object + type: array + ramMebibytes: + type: integer + storage: + items: + description: Storage describes one storage device (disk, SSD, + etc.) on the host. + properties: + alternateNames: + description: A list of alternate Linux device names of the + disk, e.g. "/dev/sda". Note that this list is not exhaustive, + and names may not be stable across reboots. + items: + type: string + type: array + hctl: + description: The SCSI location of the device + type: string + model: + description: Hardware model + type: string + name: + description: A Linux device name of the disk, e.g. "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0". + This will be a name that is stable across reboots if one + is available. + type: string + rotational: + description: Whether this disk represents rotational storage. + This field is not recommended for usage, please prefer + using 'Type' field instead, this field will be deprecated + eventually. + type: boolean + serialNumber: + description: The serial number of the device + type: string + sizeBytes: + description: The size of the disk in Bytes + format: int64 + type: integer + type: + description: 'Device type, one of: HDD, SSD, NVME.' + enum: + - HDD + - SSD + - NVME + type: string + vendor: + description: The name of the vendor of the device + type: string + wwn: + description: The WWN of the device + type: string + wwnVendorExtension: + description: The WWN Vendor extension of the device + type: string + wwnWithExtension: + description: The WWN with the extension + type: string + type: object + type: array + systemVendor: + description: HardwareSystemVendor stores details about the whole + hardware system. + properties: + manufacturer: + type: string + productName: + type: string + serialNumber: + type: string + type: object + type: object + hardwareProfile: + description: The name of the profile matching the hardware details. + type: string + lastUpdated: + description: LastUpdated identifies when this status was last observed. + format: date-time + type: string + operationHistory: + description: OperationHistory holds information about operations performed + on this host. + properties: + deprovision: + description: OperationMetric contains metadata about an operation + (inspection, provisioning, etc.) used for tracking metrics. + properties: + end: + format: date-time + nullable: true + type: string + start: + format: date-time + nullable: true + type: string + type: object + inspect: + description: OperationMetric contains metadata about an operation + (inspection, provisioning, etc.) used for tracking metrics. + properties: + end: + format: date-time + nullable: true + type: string + start: + format: date-time + nullable: true + type: string + type: object + provision: + description: OperationMetric contains metadata about an operation + (inspection, provisioning, etc.) used for tracking metrics. + properties: + end: + format: date-time + nullable: true + type: string + start: + format: date-time + nullable: true + type: string + type: object + register: + description: OperationMetric contains metadata about an operation + (inspection, provisioning, etc.) used for tracking metrics. + properties: + end: + format: date-time + nullable: true + type: string + start: + format: date-time + nullable: true + type: string + type: object + type: object + operationalStatus: + description: OperationalStatus holds the status of the host + enum: + - "" + - OK + - discovered + - error + - delayed + - detached + type: string + poweredOn: + description: indicator for whether or not the host is powered on + type: boolean + provisioning: + description: Information tracked by the provisioner. + properties: + ID: + description: The machine's UUID from the underlying provisioning + tool + type: string + bootMode: + description: BootMode indicates the boot mode used to provision + the node + enum: + - UEFI + - UEFISecureBoot + - legacy + type: string + customDeploy: + description: Custom deploy procedure applied to the host. + properties: + method: + description: Custom deploy method name. This name is specific + to the deploy ramdisk used. If you don't have a custom deploy + ramdisk, you shouldn't use CustomDeploy. + type: string + required: + - method + type: object + firmware: + description: The Bios set by the user + properties: + simultaneousMultithreadingEnabled: + description: 'Allows a single physical processor core to appear + as several logical processors. This supports following options: + true, false.' + enum: + - true + - false + type: boolean + sriovEnabled: + description: 'SR-IOV support enables a hypervisor to create + virtual instances of a PCI-express device, potentially increasing + performance. This supports following options: true, false.' + enum: + - true + - false + type: boolean + virtualizationEnabled: + description: 'Supports the virtualization of platform hardware. + This supports following options: true, false.' + enum: + - true + - false + type: boolean + type: object + image: + description: Image holds the details of the last image successfully + provisioned to the host. + properties: + checksum: + description: Checksum is the checksum for the image. + type: string + checksumType: + description: ChecksumType is the checksum algorithm for the + image, e.g md5, sha256 or sha512. The special value "auto" + can be used to detect the algorithm from the checksum. If + missing, MD5 is used. If in doubt, use "auto". + enum: + - md5 + - sha256 + - sha512 + - auto + type: string + format: + description: DiskFormat contains the format of the image (raw, + qcow2, ...). Needs to be set to raw for raw images streaming. + Note live-iso means an iso referenced by the url will be + live-booted and not deployed to disk, and in this case the + checksum options are not required and if specified will + be ignored. + enum: + - raw + - qcow2 + - vdi + - vmdk + - live-iso + type: string + url: + description: URL is a location of an image to deploy. + type: string + required: + - url + type: object + raid: + description: The Raid set by the user + properties: + hardwareRAIDVolumes: + description: The list of logical disks for hardware RAID, + if rootDeviceHints isn't used, first volume is root volume. + You can set the value of this field to `[]` to clear all + the hardware RAID configurations. + items: + description: HardwareRAIDVolume defines the desired configuration + of volume in hardware RAID. + properties: + controller: + description: The name of the RAID controller to use + type: string + level: + description: 'RAID level for the logical disk. The following + levels are supported: 0;1;2;5;6;1+0;5+0;6+0.' + enum: + - "0" + - "1" + - "2" + - "5" + - "6" + - 1+0 + - 5+0 + - 6+0 + type: string + name: + description: Name of the volume. Should be unique within + the Node. If not specified, volume name will be auto-generated. + maxLength: 64 + type: string + numberOfPhysicalDisks: + description: Integer, number of physical disks to use + for the logical disk. Defaults to minimum number of + disks required for the particular RAID level. + minimum: 1 + type: integer + physicalDisks: + description: Optional list of physical disk names to + be used for the Hardware RAID volumes. The disk names + are interpreted by the Hardware RAID controller, and + the format is hardware specific. + items: + type: string + type: array + rotational: + description: Select disks with only rotational or solid-state + storage + type: boolean + sizeGibibytes: + description: Size (Integer) of the logical disk to be + created in GiB. If unspecified or set be 0, the maximum + capacity of disk will be used for logical disk. + minimum: 0 + type: integer + required: + - level + type: object + nullable: true + type: array + softwareRAIDVolumes: + description: The list of logical disks for software RAID, + if rootDeviceHints isn't used, first volume is root volume. + If HardwareRAIDVolumes is set this item will be invalid. + The number of created Software RAID devices must be 1 or + 2. If there is only one Software RAID device, it has to + be a RAID-1. If there are two, the first one has to be a + RAID-1, while the RAID level for the second one can be 0, + 1, or 1+0. As the first RAID device will be the deployment + device, enforcing a RAID-1 reduces the risk of ending up + with a non-booting node in case of a disk failure. Software + RAID will always be deleted. + items: + description: SoftwareRAIDVolume defines the desired configuration + of volume in software RAID. + properties: + level: + description: 'RAID level for the logical disk. The following + levels are supported: 0;1;1+0.' + enum: + - "0" + - "1" + - 1+0 + type: string + physicalDisks: + description: A list of device hints, the number of items + should be greater than or equal to 2. + items: + description: RootDeviceHints holds the hints for specifying + the storage location for the root filesystem for + the image. + properties: + deviceName: + description: A Linux device name like "/dev/vda", + or a by-path link to it like "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0". + The hint must match the actual value exactly. + type: string + hctl: + description: A SCSI bus address like 0:0:0:0. + The hint must match the actual value exactly. + type: string + minSizeGigabytes: + description: The minimum size of the device in + Gigabytes. + minimum: 0 + type: integer + model: + description: A vendor-specific device identifier. + The hint can be a substring of the actual value. + type: string + rotational: + description: True if the device should use spinning + media, false otherwise. + type: boolean + serialNumber: + description: Device serial number. The hint must + match the actual value exactly. + type: string + vendor: + description: The name of the vendor or manufacturer + of the device. The hint can be a substring of + the actual value. + type: string + wwn: + description: Unique storage identifier. The hint + must match the actual value exactly. + type: string + wwnVendorExtension: + description: Unique vendor storage identifier. + The hint must match the actual value exactly. + type: string + wwnWithExtension: + description: Unique storage identifier with the + vendor extension appended. The hint must match + the actual value exactly. + type: string + type: object + minItems: 2 + type: array + sizeGibibytes: + description: Size (Integer) of the logical disk to be + created in GiB. If unspecified or set be 0, the maximum + capacity of disk will be used for logical disk. + minimum: 0 + type: integer + required: + - level + type: object + maxItems: 2 + nullable: true + type: array + type: object + rootDeviceHints: + description: The RootDevicehints set by the user + properties: + deviceName: + description: A Linux device name like "/dev/vda", or a by-path + link to it like "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0". + The hint must match the actual value exactly. + type: string + hctl: + description: A SCSI bus address like 0:0:0:0. The hint must + match the actual value exactly. + type: string + minSizeGigabytes: + description: The minimum size of the device in Gigabytes. + minimum: 0 + type: integer + model: + description: A vendor-specific device identifier. The hint + can be a substring of the actual value. + type: string + rotational: + description: True if the device should use spinning media, + false otherwise. + type: boolean + serialNumber: + description: Device serial number. The hint must match the + actual value exactly. + type: string + vendor: + description: The name of the vendor or manufacturer of the + device. The hint can be a substring of the actual value. + type: string + wwn: + description: Unique storage identifier. The hint must match + the actual value exactly. + type: string + wwnVendorExtension: + description: Unique vendor storage identifier. The hint must + match the actual value exactly. + type: string + wwnWithExtension: + description: Unique storage identifier with the vendor extension + appended. The hint must match the actual value exactly. + type: string + type: object + state: + description: An indiciator for what the provisioner is doing with + the host. + type: string + required: + - ID + - state + type: object + triedCredentials: + description: the last credentials we sent to the provisioning backend + properties: + credentials: + description: SecretReference represents a Secret Reference. It + has enough information to retrieve secret in any namespace + properties: + name: + description: name is unique within a namespace to reference + a secret resource. + type: string + namespace: + description: namespace defines the space within which the + secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + credentialsVersion: + type: string + type: object + required: + - errorCount + - errorMessage + - hardwareProfile + - operationalStatus + - poweredOn + - provisioning + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-bmceventsubscriptions.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-bmceventsubscriptions.yaml new file mode 100644 index 0000000..c0dc2bf --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/crds/customresource-bmceventsubscriptions.yaml @@ -0,0 +1,85 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + labels: + clusterctl.cluster.x-k8s.io: "" + name: bmceventsubscriptions.metal3.io +spec: + group: metal3.io + names: + kind: BMCEventSubscription + listKind: BMCEventSubscriptionList + plural: bmceventsubscriptions + shortNames: + - bes + - bmcevent + singular: bmceventsubscription + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: The most recent error message + jsonPath: .status.error + name: Error + type: string + - description: Time duration since creation of BMCEventSubscription + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: BMCEventSubscription is the Schema for the fast eventing 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: + properties: + context: + description: Arbitrary user-provided context for the event + type: string + destination: + description: A webhook URL to send events to + type: string + hostName: + description: A reference to a BareMetalHost + type: string + httpHeadersRef: + description: A secret containing HTTP headers which should be passed + along to the Destination when making a request + properties: + name: + description: name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: namespace defines the space within which the secret + name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + type: object + status: + properties: + error: + type: string + subscriptionID: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-dataimages.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-dataimages.yaml new file mode 100644 index 0000000..c1bb7b0 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/crds/customresource-dataimages.yaml @@ -0,0 +1,75 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + name: dataimages.metal3.io +spec: + group: metal3.io + names: + kind: DataImage + listKind: DataImageList + plural: dataimages + singular: dataimage + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: DataImage is the Schema for the dataimages 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: DataImageSpec defines the desired state of DataImage. + properties: + url: + description: Url is the address of the dataImage that we want to attach + to a BareMetalHost + type: string + required: + - url + type: object + status: + description: DataImageStatus defines the observed state of DataImage. + properties: + attachedImage: + description: Currently attached DataImage + properties: + url: + type: string + required: + - url + type: object + error: + description: Error count and message when attaching/detaching + properties: + count: + type: integer + message: + type: string + required: + - count + - message + type: object + lastReconciled: + description: Time of last reconciliation + format: date-time + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-firmwareschemas.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-firmwareschemas.yaml new file mode 100644 index 0000000..3b3c4fe --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/crds/customresource-firmwareschemas.yaml @@ -0,0 +1,90 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + labels: + clusterctl.cluster.x-k8s.io: "" + name: firmwareschemas.metal3.io +spec: + group: metal3.io + names: + kind: FirmwareSchema + listKind: FirmwareSchemaList + plural: firmwareschemas + singular: firmwareschema + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: FirmwareSchema is the Schema for the firmwareschemas 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: FirmwareSchemaSpec defines the desired state of FirmwareSchema. + properties: + hardwareModel: + description: The hardware model associated with this schema + type: string + hardwareVendor: + description: The hardware vendor associated with this schema + type: string + schema: + additionalProperties: + description: Additional data describing the firmware setting. + properties: + allowable_values: + description: The allowable value for an Enumeration type setting. + items: + type: string + type: array + attribute_type: + description: The type of setting. + enum: + - Enumeration + - String + - Integer + - Boolean + - Password + type: string + lower_bound: + description: The lowest value for an Integer type setting. + type: integer + max_length: + description: Maximum length for a String type setting. + type: integer + min_length: + description: Minimum length for a String type setting. + type: integer + read_only: + description: Whether or not this setting is read only. + type: boolean + unique: + description: Whether or not this setting's value is unique to + this node, e.g. a serial number. + type: boolean + upper_bound: + description: The highest value for an Integer type setting. + type: integer + type: object + description: Map of firmware name to schema + type: object + required: + - schema + type: object + type: object + served: true + storage: true diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-hardwaredata.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-hardwaredata.yaml new file mode 100644 index 0000000..7a39068 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/crds/customresource-hardwaredata.yaml @@ -0,0 +1,211 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + labels: + clusterctl.cluster.x-k8s.io: "" + name: hardwaredata.metal3.io +spec: + group: metal3.io + names: + kind: HardwareData + listKind: HardwareDataList + plural: hardwaredata + shortNames: + - hd + singular: hardwaredata + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Time duration since creation of HardwareData + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: HardwareData is the Schema for the hardwaredata 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: HardwareDataSpec defines the desired state of HardwareData. + properties: + hardware: + description: The hardware discovered on the host during its inspection. + properties: + cpu: + description: CPU describes one processor on the host. + properties: + arch: + type: string + clockMegahertz: + description: ClockSpeed is a clock speed in MHz + format: double + type: number + count: + type: integer + flags: + items: + type: string + type: array + model: + type: string + type: object + firmware: + description: Firmware describes the firmware on the host. + properties: + bios: + description: The BIOS for this firmware + properties: + date: + description: The release/build date for this BIOS + type: string + vendor: + description: The vendor name for this BIOS + type: string + version: + description: The version of the BIOS + type: string + type: object + type: object + hostname: + type: string + nics: + items: + description: NIC describes one network interface on the host. + properties: + ip: + description: The IP address of the interface. This will + be an IPv4 or IPv6 address if one is present. If both + IPv4 and IPv6 addresses are present in a dual-stack environment, + two nics will be output, one with each IP. + type: string + mac: + description: The device MAC address + pattern: '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}' + type: string + model: + description: The vendor and product IDs of the NIC, e.g. + "0x8086 0x1572" + type: string + name: + description: The name of the network interface, e.g. "en0" + type: string + pxe: + description: Whether the NIC is PXE Bootable + type: boolean + speedGbps: + description: The speed of the device in Gigabits per second + type: integer + vlanId: + description: The untagged VLAN ID + format: int32 + maximum: 4094 + minimum: 0 + type: integer + vlans: + description: The VLANs available + items: + description: VLAN represents the name and ID of a VLAN. + properties: + id: + description: VLANID is a 12-bit 802.1Q VLAN identifier + format: int32 + maximum: 4094 + minimum: 0 + type: integer + name: + type: string + type: object + type: array + type: object + type: array + ramMebibytes: + type: integer + storage: + items: + description: Storage describes one storage device (disk, SSD, + etc.) on the host. + properties: + alternateNames: + description: A list of alternate Linux device names of the + disk, e.g. "/dev/sda". Note that this list is not exhaustive, + and names may not be stable across reboots. + items: + type: string + type: array + hctl: + description: The SCSI location of the device + type: string + model: + description: Hardware model + type: string + name: + description: A Linux device name of the disk, e.g. "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:2:0:0". + This will be a name that is stable across reboots if one + is available. + type: string + rotational: + description: Whether this disk represents rotational storage. + This field is not recommended for usage, please prefer + using 'Type' field instead, this field will be deprecated + eventually. + type: boolean + serialNumber: + description: The serial number of the device + type: string + sizeBytes: + description: The size of the disk in Bytes + format: int64 + type: integer + type: + description: 'Device type, one of: HDD, SSD, NVME.' + enum: + - HDD + - SSD + - NVME + type: string + vendor: + description: The name of the vendor of the device + type: string + wwn: + description: The WWN of the device + type: string + wwnVendorExtension: + description: The WWN Vendor extension of the device + type: string + wwnWithExtension: + description: The WWN with the extension + type: string + type: object + type: array + systemVendor: + description: HardwareSystemVendor stores details about the whole + hardware system. + properties: + manufacturer: + type: string + productName: + type: string + serialNumber: + type: string + type: object + type: object + type: object + type: object + served: true + storage: true + subresources: {} diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwarecomponents.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwarecomponents.yaml new file mode 100644 index 0000000..2962d52 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwarecomponents.yaml @@ -0,0 +1,178 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + name: hostfirmwarecomponents.metal3.io +spec: + group: metal3.io + names: + kind: HostFirmwareComponents + listKind: HostFirmwareComponentsList + plural: hostfirmwarecomponents + singular: hostfirmwarecomponents + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: HostFirmwareComponents is the Schema for the hostfirmwarecomponents + 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: HostFirmwareComponentsSpec defines the desired state of HostFirmwareComponents. + properties: + updates: + items: + description: FirmwareUpdate defines a firmware update specification. + properties: + component: + type: string + url: + type: string + required: + - component + - url + type: object + type: array + required: + - updates + type: object + status: + description: HostFirmwareComponentsStatus defines the observed state of + HostFirmwareComponents. + properties: + components: + description: Components is the list of all available firmware components + and their information. + items: + description: FirmwareComponentStatus defines the status of a firmware + component. + properties: + component: + type: string + currentVersion: + type: string + initialVersion: + type: string + lastVersionFlashed: + type: string + updatedAt: + format: date-time + type: string + required: + - component + - initialVersion + type: object + type: array + conditions: + description: Track whether updates stored in the spec are valid based + on the schema + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + lastUpdated: + description: Time that the status was last updated + format: date-time + type: string + updates: + description: Updates is the list of all firmware components that should + be updated they are specified via name and url fields. + items: + description: FirmwareUpdate defines a firmware update specification. + properties: + component: + type: string + url: + type: string + required: + - component + - url + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwaresettings.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwaresettings.yaml new file mode 100644 index 0000000..62679cf --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/crds/customresource-hostfirmwaresettings.yaml @@ -0,0 +1,164 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + labels: + clusterctl.cluster.x-k8s.io: "" + name: hostfirmwaresettings.metal3.io +spec: + group: metal3.io + names: + kind: HostFirmwareSettings + listKind: HostFirmwareSettingsList + plural: hostfirmwaresettings + shortNames: + - hfs + singular: hostfirmwaresettings + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: HostFirmwareSettings is the Schema for the hostfirmwaresettings + 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: HostFirmwareSettingsSpec defines the desired state of HostFirmwareSettings. + properties: + settings: + additionalProperties: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + description: Settings are the desired firmware settings stored as + name/value pairs. + type: object + required: + - settings + type: object + status: + description: HostFirmwareSettingsStatus defines the observed state of + HostFirmwareSettings. + properties: + conditions: + description: Track whether settings stored in the spec are valid based + on the schema + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + lastUpdated: + description: Time that the status was last updated + format: date-time + type: string + schema: + description: FirmwareSchema is a reference to the Schema used to describe + each FirmwareSetting. By default, this will be a Schema in the same + Namespace as the settings but it can be overwritten in the Spec + properties: + name: + description: '`name` is the reference to the schema.' + type: string + namespace: + description: '`namespace` is the namespace of the where the schema + is stored.' + type: string + required: + - name + - namespace + type: object + settings: + additionalProperties: + type: string + description: Settings are the firmware settings stored as name/value + pairs + type: object + required: + - settings + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metal3-chart/charts/baremetal-operator/crds/customresource-preprovisioningimages.yaml b/metal3-chart/charts/baremetal-operator/crds/customresource-preprovisioningimages.yaml new file mode 100644 index 0000000..f743a89 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/crds/customresource-preprovisioningimages.yaml @@ -0,0 +1,183 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + labels: + clusterctl.cluster.x-k8s.io: "" + name: preprovisioningimages.metal3.io +spec: + group: metal3.io + names: + kind: PreprovisioningImage + listKind: PreprovisioningImageList + plural: preprovisioningimages + shortNames: + - ppimg + singular: preprovisioningimage + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Whether the image is ready + jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + - description: The reason for the image readiness status + jsonPath: .status.conditions[?(@.type=='Ready')].reason + name: Reason + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: PreprovisioningImage is the Schema for the preprovisioningimages + 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: PreprovisioningImageSpec defines the desired state of PreprovisioningImage. + properties: + acceptFormats: + description: acceptFormats is a list of acceptable image formats. + items: + description: ImageFormat enumerates the allowed image formats + enum: + - iso + - initrd + type: string + type: array + architecture: + description: architecture is the processor architecture for which + to build the image. + type: string + networkDataName: + description: networkDataName is the name of a Secret in the local + namespace that contains network data to build in to the image. + type: string + type: object + status: + description: PreprovisioningImageStatus defines the observed state of + PreprovisioningImage. + properties: + architecture: + description: architecture is the processor architecture for which + the image is built + type: string + conditions: + description: conditions describe the state of the built image + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + extraKernelParams: + description: extraKernelParams is a string with extra parameters to + pass to the kernel when booting the image over network. Only makes + sense for initrd images. + type: string + format: + description: 'format is the type of image that is available at the + download url: either iso or initrd.' + enum: + - iso + - initrd + type: string + imageUrl: + description: imageUrl is the URL from which the built image can be + downloaded. + type: string + kernelUrl: + description: kernelUrl is the URL from which the kernel of the image + can be downloaded. Only makes sense for initrd images. + type: string + networkData: + description: networkData is a reference to the version of the Secret + containing the network data used to build the image. + properties: + name: + type: string + version: + type: string + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metal3-chart/charts/baremetal-operator/templates/NOTES.txt b/metal3-chart/charts/baremetal-operator/templates/NOTES.txt new file mode 100644 index 0000000..a46dc2b --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/NOTES.txt @@ -0,0 +1,16 @@ +1. Get the application URL by running these commands: +{{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "baremetal-operator.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "baremetal-operator.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "baremetal-operator.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "baremetal-operator.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/metal3-chart/charts/baremetal-operator/templates/_helpers.tpl b/metal3-chart/charts/baremetal-operator/templates/_helpers.tpl new file mode 100644 index 0000000..08dc581 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "baremetal-operator.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "baremetal-operator.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "baremetal-operator.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "baremetal-operator.labels" -}} +helm.sh/chart: {{ include "baremetal-operator.chart" . }} +{{ include "baremetal-operator.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "baremetal-operator.selectorLabels" -}} +app.kubernetes.io/component: baremetal-operator +app.kubernetes.io/name: {{ include "baremetal-operator.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "baremetal-operator.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "baremetal-operator.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/metal3-chart/charts/baremetal-operator/templates/certificate.yaml b/metal3-chart/charts/baremetal-operator/templates/certificate.yaml new file mode 100644 index 0000000..ad0fd88 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/certificate.yaml @@ -0,0 +1,14 @@ +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ include "baremetal-operator.fullname" . }}-serving-cert + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} +spec: + dnsNames: + - baremetal-operator-webhook-service.{{ .Release.Namespace }}.svc + - baremetal-operator-webhook-service.{{ .Release.Namespace }}.svc.cluster.local + issuerRef: + kind: Issuer + name: {{ include "baremetal-operator.fullname" . }}-selfsigned-issuer + secretName: bmo-webhook-server-cert diff --git a/metal3-chart/charts/baremetal-operator/templates/clusterrole-manager.yaml b/metal3-chart/charts/baremetal-operator/templates/clusterrole-manager.yaml new file mode 100644 index 0000000..e55cb06 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/clusterrole-manager.yaml @@ -0,0 +1,186 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: {{ include "baremetal-operator.fullname" . }}-manager-role + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - events + verbs: + - create + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - update + - watch +- apiGroups: + - metal3.io + resources: + - baremetalhosts + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - metal3.io + resources: + - baremetalhosts/status + verbs: + - get + - patch + - update +- apiGroups: + - metal3.io + resources: + - bmceventsubscriptions + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - metal3.io + resources: + - bmceventsubscriptions/status + verbs: + - get + - patch + - update +- apiGroups: + - metal3.io + resources: + - firmwareschemas + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - metal3.io + resources: + - firmwareschemas/status + verbs: + - get + - patch + - update +- apiGroups: + - metal3.io + resources: + - hardware/finalizers + verbs: + - update +- apiGroups: + - metal3.io + resources: + - hardwaredata + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - metal3.io + resources: + - hostfirmwaresettings + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - metal3.io + resources: + - hostfirmwaresettings/status + verbs: + - get + - patch + - update +- apiGroups: + - metal3.io + resources: + - preprovisioningimages + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - metal3.io + resources: + - preprovisioningimages/status + verbs: + - get + - patch + - update +- apiGroups: + - metal3.io + resources: + - dataimages + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - metal3.io + resources: + - dataimages/status + verbs: + - get + - patch + - update +- apiGroups: + - metal3.io + resources: + - hostfirmwarecomponents + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - metal3.io + resources: + - hostfirmwarecomponents/status + verbs: + - get + - patch + - update diff --git a/metal3-chart/charts/baremetal-operator/templates/clusterrole-metrics-reader.yaml b/metal3-chart/charts/baremetal-operator/templates/clusterrole-metrics-reader.yaml new file mode 100644 index 0000000..cad7903 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/clusterrole-metrics-reader.yaml @@ -0,0 +1,11 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "baremetal-operator.fullname" . }}-metrics-reader + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} +rules: +- nonResourceURLs: + - /metrics + verbs: + - get diff --git a/metal3-chart/charts/baremetal-operator/templates/clusterrole-proxy.yaml b/metal3-chart/charts/baremetal-operator/templates/clusterrole-proxy.yaml new file mode 100644 index 0000000..db6d71d --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/clusterrole-proxy.yaml @@ -0,0 +1,19 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "baremetal-operator.fullname" . }}-proxy-role + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create diff --git a/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-manager.yaml b/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-manager.yaml new file mode 100644 index 0000000..bfce20a --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-manager.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "baremetal-operator.fullname" . }}-manager-rolebinding + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "baremetal-operator.fullname" . }}-manager-role +subjects: +- kind: ServiceAccount + name: {{ include "baremetal-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-proxy.yaml b/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-proxy.yaml new file mode 100644 index 0000000..5207b62 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/clusterrolebinding-proxy.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "baremetal-operator.fullname" . }}-proxy-rolebinding + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "baremetal-operator.fullname" . }}-proxy-role +subjects: +- kind: ServiceAccount + name: {{ include "baremetal-operator.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/metal3-chart/charts/baremetal-operator/templates/configmap-ironic.yaml b/metal3-chart/charts/baremetal-operator/templates/configmap-ironic.yaml new file mode 100644 index 0000000..20d3b8c --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/configmap-ironic.yaml @@ -0,0 +1,30 @@ + {{- $enableTLS := .Values.global.enable_tls }} + {{- $enableVMediaTLS := .Values.global.enable_vmedia_tls }} + {{- $protocol := ternary "https" "http" $enableTLS }} + {{- $ironicIP := .Values.global.ironicIP | default "" }} + {{- $ironicApiHost := print $ironicIP ":6385" }} + {{- $ironicInspectorHost := print $ironicIP ":5050" }} + {{- $ironicBootHost := print $ironicIP ":6180" }} + {{- $ironicCacheHost := print $ironicIP ":6180" }} + +apiVersion: v1 +data: + IRONIC_ENDPOINT: "{{ $protocol }}://{{ $ironicApiHost }}/v1/" + IRONIC_INSPECTOR_ENDPOINT: "{{ $protocol }}://{{ $ironicInspectorHost }}/v1/" + RESTART_CONTAINER_CERTIFICATE_UPDATED: "false" + # Switch VMedia to HTTP if enable_vmedia_tls is false + {{- if and $enableTLS $enableVMediaTLS }} + {{- $ironicBootHost = print $ironicIP ":" .Values.global.vmediaTLSPort }} + {{- $ironicCacheHost = print $ironicIP ":" .Values.global.vmediaTLSPort }} + {{- $protocol = "https" }} + {{- else }} + {{- $protocol = "http" }} + {{- end }} + CACHEURL: "{{ $protocol }}://{{ $ironicCacheHost }}/images" + DEPLOY_KERNEL_URL: "{{ $protocol }}://{{ $ironicBootHost }}/images/ironic-python-agent.kernel" + DEPLOY_RAMDISK_URL: "{{ $protocol }}://{{ $ironicBootHost }}/images/ironic-python-agent.initramfs" +kind: ConfigMap +metadata: + name: baremetal-operator-ironic + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} diff --git a/metal3-chart/charts/baremetal-operator/templates/configmap.yaml b/metal3-chart/charts/baremetal-operator/templates/configmap.yaml new file mode 100644 index 0000000..b22579a --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/configmap.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +data: + controller_manager_config.yaml: | + apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 + kind: ControllerManagerConfig + health: + healthProbeBindAddress: :9440 + metrics: + bindAddress: 127.0.0.1:8085 + webhook: + port: 9443 + leaderElection: + leaderElect: true + resourceName: a9498140.metal3.io +kind: ConfigMap +metadata: + name: baremetal-operator-manager-config + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} diff --git a/metal3-chart/charts/baremetal-operator/templates/deployment.yaml b/metal3-chart/charts/baremetal-operator/templates/deployment.yaml new file mode 100644 index 0000000..877c714 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/deployment.yaml @@ -0,0 +1,131 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} + control-plane: controller-manager + webhook: metal3-io-v1alpha1-baremetalhost + name: {{ include "baremetal-operator.fullname" . }}-controller-manager +spec: + minReadySeconds: 10 + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "baremetal-operator.selectorLabels" . | nindent 6 }} + control-plane: controller-manager + template: + metadata: + labels: + {{- include "baremetal-operator.selectorLabels" . | nindent 8 }} + control-plane: controller-manager + webhook: metal3-io-v1alpha1-baremetalhost + spec: + containers: + - args: + - --metrics-addr=127.0.0.1:8085 + - --enable-leader-election + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + envFrom: + - configMapRef: + name: {{ include "baremetal-operator.fullname" . }}-ironic + image: "{{ .Values.images.baremetalOperator.repository }}:{{ .Values.images.baremetalOperator.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.images.baremetalOperator.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + livenessProbe: + failureThreshold: 10 + httpGet: + path: /healthz + port: 9440 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 2 + name: manager + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP + readinessProbe: + failureThreshold: 10 + httpGet: + path: /readyz + port: 9440 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 2 + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + {{- if .Values.global.enable_basicAuth }} + - name: ironic-basic-auth + mountPath: "/opt/metal3/auth/ironic/username" + subPath: username + readOnly: true + - name: ironic-basic-auth + mountPath: "/opt/metal3/auth/ironic/password" + subPath: password + readOnly: true + - name: ironic-inspector-basic-auth + mountPath: "/opt/metal3/auth/ironic-inspector/username" + subPath: username + readOnly: true + - name: ironic-inspector-basic-auth + mountPath: "/opt/metal3/auth/ironic-inspector/password" + subPath: password + readOnly: true + {{- end }} + {{- if .Values.global.enable_tls }} + - name: cacert + mountPath: "/opt/metal3/certs/ca" + readOnly: true + {{- end }} + - args: + - --secure-listen-address=0.0.0.0:8443 + - --upstream=http://127.0.0.1:8085/ + - --logtostderr=true + - --v=10 + image: "{{ .Values.images.rbacProxy.repository }}:{{ .Values.images.rbacProxy.tag }}" + imagePullPolicy: {{ .Values.images.rbacProxy.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + name: kube-rbac-proxy + ports: + - containerPort: 8443 + name: https + serviceAccountName: {{ include "baremetal-operator.serviceAccountName" . }} + terminationGracePeriodSeconds: 10 + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: bmo-webhook-server-cert + {{- if .Values.global.enable_basicAuth }} + - name: ironic-basic-auth + secret: + secretName: ironic-basic-auth + - name: ironic-inspector-basic-auth + secret: + secretName: ironic-inspector-basic-auth + {{- end }} + {{- if .Values.global.enable_tls }} + - name: cacert + secret: + secretName: ironic-cacert + {{- end }} + {{- with .Values.global.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/metal3-chart/charts/baremetal-operator/templates/issuer.yaml b/metal3-chart/charts/baremetal-operator/templates/issuer.yaml new file mode 100644 index 0000000..c9d1522 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/issuer.yaml @@ -0,0 +1,8 @@ +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} + name: {{ include "baremetal-operator.fullname" . }}-selfsigned-issuer +spec: + selfSigned: {} diff --git a/metal3-chart/charts/baremetal-operator/templates/role.yaml b/metal3-chart/charts/baremetal-operator/templates/role.yaml new file mode 100644 index 0000000..d56496f --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/role.yaml @@ -0,0 +1,45 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "baremetal-operator.fullname" . }}-leader-election-role + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch +- apiGroups: + - "" + resources: + - events + verbs: + - create +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete diff --git a/metal3-chart/charts/baremetal-operator/templates/rolebinding.yaml b/metal3-chart/charts/baremetal-operator/templates/rolebinding.yaml new file mode 100644 index 0000000..5704c6a --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/rolebinding.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "baremetal-operator.fullname" . }}-leader-election-rolebinding + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "baremetal-operator.fullname" . }}-leader-election-role +subjects: +- kind: ServiceAccount + name: {{ include "baremetal-operator.serviceAccountName" . }} diff --git a/metal3-chart/charts/baremetal-operator/templates/service-controller-manager.yaml b/metal3-chart/charts/baremetal-operator/templates/service-controller-manager.yaml new file mode 100644 index 0000000..64f39a6 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/service-controller-manager.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} + control-plane: controller-manager + name: {{ include "baremetal-operator.fullname" . }}-controller-manager-metrics-service +spec: + ports: + - name: https + port: 8443 + targetPort: https + selector: + control-plane: controller-manager diff --git a/metal3-chart/charts/baremetal-operator/templates/service-webhook.yaml b/metal3-chart/charts/baremetal-operator/templates/service-webhook.yaml new file mode 100644 index 0000000..67fea7f --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/service-webhook.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} + name: {{ include "baremetal-operator.fullname" . }}-webhook-service +spec: + ports: + - port: 443 + targetPort: 9443 + selector: + control-plane: controller-manager + webhook: metal3-io-v1alpha1-baremetalhost diff --git a/metal3-chart/charts/baremetal-operator/templates/serviceaccount.yaml b/metal3-chart/charts/baremetal-operator/templates/serviceaccount.yaml new file mode 100644 index 0000000..14376e8 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "baremetal-operator.serviceAccountName" . }} + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/metal3-chart/charts/baremetal-operator/templates/tests/test-connection.yaml b/metal3-chart/charts/baremetal-operator/templates/tests/test-connection.yaml new file mode 100644 index 0000000..28715fe --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "baremetal-operator.fullname" . }}-test-connection" + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "baremetal-operator.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/metal3-chart/charts/baremetal-operator/templates/validatingwebhookconfiguration.yaml b/metal3-chart/charts/baremetal-operator/templates/validatingwebhookconfiguration.yaml new file mode 100644 index 0000000..1cefe78 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/templates/validatingwebhookconfiguration.yaml @@ -0,0 +1,51 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + labels: + {{- include "baremetal-operator.labels" . | nindent 4 }} + annotations: + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "baremetal-operator.fullname" . }}-serving-cert + name: {{ include "baremetal-operator.fullname" . }}-validating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + - v1beta + clientConfig: + service: + name: {{ include "baremetal-operator.fullname" . }}-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metal3-io-v1alpha1-baremetalhost + failurePolicy: Fail + name: baremetalhost.metal3.io + rules: + - apiGroups: + - metal3.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - baremetalhosts + sideEffects: None +- admissionReviewVersions: + - v1 + - v1beta + clientConfig: + service: + name: {{ include "baremetal-operator.fullname" . }}-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metal3-io-v1alpha1-bmceventsubscription + failurePolicy: Fail + name: bmceventsubscription.metal3.io + rules: + - apiGroups: + - metal3.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - bmceventsubscriptions + sideEffects: None diff --git a/metal3-chart/charts/baremetal-operator/values.yaml b/metal3-chart/charts/baremetal-operator/values.yaml new file mode 100644 index 0000000..cf7fad4 --- /dev/null +++ b/metal3-chart/charts/baremetal-operator/values.yaml @@ -0,0 +1,90 @@ +# Default values for baremetal-operator. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +global: + # specify comma serparate beginning and end of the range of IP + # addresses the DHCP server will manage. + dhcpRange: 192.168.20.20,192.168.20.80 + + # Network interface on which provisioning network can be accessed + provisioningInterface: ens4 + + # IP Address assigned to network interface on provisioning network + provisioningIP: 192.168.20.5 + + # If running in a multi-node kubernetes cluster, "pin" the baremtal container + # to the same host where the ironic and media containers + # arerunning. Uncomment the nodeSelector and update the hostname accordingly. + #nodeSelector: + #kubernetes.io/hostname: "my-hostname" + + # Comment this out when pinning the baremetal-operator container to a specfic host. + nodeSelector: {} + +replicaCount: 1 + +images: + baremetalOperator: + repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/baremetal-operator + pullPolicy: IfNotPresent + tag: "0.6.1" + rbacProxy: + repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/kube-rbac-proxy + pullPolicy: IfNotPresent + tag: "v0.14.2" + +imagePullSecrets: [] +nameOverride: "manger" +fullnameOverride: "baremetal-operator" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "baremetal-operator-controller-manager" + +podAnnotations: {} + +securityContext: + runAsUser: 11000 + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + runAsNonRoot: true + +service: + type: ClusterIP + port: 80 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +tolerations: [] + +affinity: {} + +baremetaloperator: + httpPort: "6180" diff --git a/metal3-chart/charts/ironic/.helmignore b/metal3-chart/charts/ironic/.helmignore new file mode 100644 index 0000000..1b9a9cc --- /dev/null +++ b/metal3-chart/charts/ironic/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/metal3-chart/charts/ironic/Chart.yaml b/metal3-chart/charts/ironic/Chart.yaml new file mode 100644 index 0000000..a9d39ec --- /dev/null +++ b/metal3-chart/charts/ironic/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: 24.1.2 +description: A Helm chart for Ironic, used by Metal3 +name: ironic +type: application +version: 0.7.0 diff --git a/metal3-chart/charts/ironic/README.md b/metal3-chart/charts/ironic/README.md new file mode 100644 index 0000000..d88fccc --- /dev/null +++ b/metal3-chart/charts/ironic/README.md @@ -0,0 +1,24 @@ +## How to Enable Provisioning Network + +By default PXE boot functionality is disabled, so deployments via e.g redfish-virtualmedia may +be performed without any dedicated provisioning network. + +For PXE boot a dedicated network is required, in this case we run a dnsmasq instance to provide +DHCP and require a dedicated NIC for connectivity to the provisioning network on each host. + +To enable this mode you must provide the following additional configuration (note the values are +examples and will depend on your environment): + +``` +global: + enable_dnsmasq: true + enable_pxe_boot: true + dnsmasqDefaultRouter: 192.168.21.254 + dnsmasqDNSServer: 192.168.20.5 + dhcpRange: 192.168.20.20,192.168.20.80 + provisioningInterface: ens4 + provisioningIP: 192.168.20.5 +``` + +Note that these values *must not* conflict with your controlplane or other networks otherwise unexpected +behavior is likely - a dedicated physical network is required in this configuration. diff --git a/metal3-chart/charts/ironic/templates/NOTES.txt b/metal3-chart/charts/ironic/templates/NOTES.txt new file mode 100644 index 0000000..acc38ed --- /dev/null +++ b/metal3-chart/charts/ironic/templates/NOTES.txt @@ -0,0 +1,16 @@ +1. Get the application URL by running these commands: +{{- if eq .Values.service.type "NodePort" }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "ironic.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if eq .Values.service.type "LoadBalancer" }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "ironic.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "ironic.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:6385 +{{- else if eq .Values.service.type "ClusterIP" }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "ironic.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/metal3-chart/charts/ironic/templates/_helpers.tpl b/metal3-chart/charts/ironic/templates/_helpers.tpl new file mode 100644 index 0000000..eb97966 --- /dev/null +++ b/metal3-chart/charts/ironic/templates/_helpers.tpl @@ -0,0 +1,88 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "ironic.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "ironic.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ironic.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "ironic.labels" -}} +helm.sh/chart: {{ include "ironic.chart" . }} +{{ include "ironic.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "ironic.selectorLabels" -}} +app.kubernetes.io/component: ironic +app.kubernetes.io/name: {{ include "ironic.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "ironic.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "ironic.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Shared directory volumeMount +*/}} +{{- define "ironic.sharedVolumeMount" -}} +- mountPath: /shared + name: ironic-data-volume +{{- end }} + +{{/* +Get ironic CA volumeMounts +*/}} +{{- define "ironic.CAVolumeMounts" -}} +- name: cert-ironic-ca + mountPath: "/certs/ca/ironic" + readOnly: true +- name: cert-ironic-inspector-ca + mountPath: "/certs/ca/ironic-inspector" + readOnly: true +{{- if .Values.global.enable_vmedia_tls }} +- name: cert-ironic-vmedia-ca + mountPath: "/certs/ca/vmedia" + readOnly: true +{{- end }} +{{- end }} diff --git a/metal3-chart/charts/ironic/templates/certificates.yaml b/metal3-chart/charts/ironic/templates/certificates.yaml new file mode 100644 index 0000000..f745c34 --- /dev/null +++ b/metal3-chart/charts/ironic/templates/certificates.yaml @@ -0,0 +1,56 @@ +{{- if .Values.global.enable_tls -}} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: ironic-cacert +spec: + commonName: ironic-ca + isCA: true + ipAddresses: + - {{ .Values.global.ironicIP }} + issuerRef: + kind: Issuer + name: selfsigned-issuer + secretName: ironic-cacert +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: ironic-cert +spec: + commonName: ironic-cert + ipAddresses: + - {{ .Values.global.ironicIP }} + issuerRef: + kind: Issuer + name: ca-issuer + secretName: ironic-cert +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: ironic-inspector-cert +spec: + commonName: ironic-inspector-cert + ipAddresses: + - {{ .Values.global.ironicIP }} + issuerRef: + kind: Issuer + name: ca-issuer + secretName: ironic-inspector-cert +{{- if .Values.global.enable_vmedia_tls }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: ironic-vmedia-cert +spec: + commonName: ironic-vmedia-cert + ipAddresses: + - {{ .Values.global.ironicIP }} + issuerRef: + kind: Issuer + name: ca-issuer + secretName: ironic-vmedia-cert +{{- end }} +{{- end }} diff --git a/metal3-chart/charts/ironic/templates/configmap-ipa-downloader.yaml b/metal3-chart/charts/ironic/templates/configmap-ipa-downloader.yaml new file mode 100644 index 0000000..3636717 --- /dev/null +++ b/metal3-chart/charts/ironic/templates/configmap-ipa-downloader.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: ironic-ipa-downloader + labels: + {{- include "ironic.labels" . | nindent 4 }} +data: + {{- with .Values.baremetaloperator }} + {{ if .ipaBaseUri }} + IPA_BASEURI: {{ .ipaBaseUri }} + {{ end }} + {{ end }} diff --git a/metal3-chart/charts/ironic/templates/configmap.yaml b/metal3-chart/charts/ironic/templates/configmap.yaml new file mode 100644 index 0000000..3a66c9d --- /dev/null +++ b/metal3-chart/charts/ironic/templates/configmap.yaml @@ -0,0 +1,86 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: ironic-bmo + labels: + {{- include "ironic.labels" . | nindent 4 }} +data: + {{- $enableTLS := .Values.global.enable_tls }} + {{- $enableVMediaTLS := .Values.global.enable_vmedia_tls }} + {{- $protocol := ternary "https" "http" $enableTLS }} + {{- $ironicIP := .Values.global.ironicIP | default "" }} + {{- $ironicApiHost := print $ironicIP ":6385" }} + {{- $ironicInspectorHost := print $ironicIP ":5050" }} + {{- $ironicBootHost := print $ironicIP ":6180" }} + {{- $ironicCacheHost := print $ironicIP ":6180" }} + + {{- if ( .Values.global.enable_dnsmasq ) }} + DNSMASQ_BOOT_SERVER_ADDRESS: {{ $ironicBootHost }} + DNSMASQ_DNS_SERVER_ADDRESS: {{ .Values.global.dnsmasqDNSServer }} + DNSMASQ_DEFAULT_ROUTER: {{ .Values.global.dnsmasqDefaultRouter }} + DHCP_RANGE: {{ .Values.global.dhcpRange }} + {{- end }} + {{- if .Values.debug.ironicRamdiskSshKey }} + IRONIC_RAMDISK_SSH_KEY: {{ .Values.debug.ironicRamdiskSshKey }} + {{- end }} + HTTP_PORT: "6180" + PREDICTABLE_NIC_NAMES: "{{ .Values.global.predictableNicNames }}" + USE_IRONIC_INSPECTOR: "true" + IRONIC_API_BASE_URL: {{ $protocol }}://{{ $ironicApiHost }} + IRONIC_API_HOST: {{ $ironicApiHost }} + IRONIC_API_HTTPD_SERVER_NAME: {{ $ironicApiHost }} + IRONIC_ENDPOINT: {{ $protocol }}://{{ $ironicApiHost }}/v1/ + IRONIC_INSPECTOR_BASE_URL: {{ $protocol }}://{{ $ironicInspectorHost }} + IRONIC_INSPECTOR_ENDPOINT: {{ $protocol }}://{{ $ironicInspectorHost }}/v1/ + IRONIC_INSPECTOR_HOST: {{ $ironicInspectorHost }} + IRONIC_INSPECTOR_HTTPD_SERVER_NAME: {{ $ironicInspectorHost }} + # Switch VMedia to HTTP if enable_vmedia_tls is false + {{- if and $enableTLS $enableVMediaTLS }} + {{- $ironicBootHost = print $ironicIP ":" .Values.global.vmediaTLSPort }} + {{- $ironicCacheHost = print $ironicIP ":" .Values.global.vmediaTLSPort }} + {{- $protocol = "https" }} + {{- else }} + {{- $protocol = "http" }} + {{- end }} + IRONIC_EXTERNAL_HTTP_URL: {{ $protocol }}://{{ $ironicCacheHost }} + CACHEURL: {{ $protocol }}://{{ $ironicCacheHost }}/images + DEPLOY_KERNEL_URL: {{ $protocol }}://{{ $ironicBootHost }}/images/ironic-python-agent.kernel + DEPLOY_RAMDISK_URL: {{ $protocol }}://{{ $ironicBootHost }}/images/ironic-python-agent.initramfs + IRONIC_BOOT_BASE_URL: {{ $protocol }}://{{ $ironicBootHost }} + IRONIC_VMEDIA_HTTPD_SERVER_NAME: {{ $ironicBootHost }} + ENABLE_PXE_BOOT: "{{ .Values.global.enable_pxe_boot }}" + {{- if .Values.global.provisioningInterface }} + PROVISIONING_INTERFACE: {{ .Values.global.provisioningInterface }} + {{- end }} + {{- if .Values.global.provisioningIP }} + PROVISIONING_IP: {{ .Values.global.provisioningIP }} + {{- end }} + IRONIC_INSPECTOR_VLAN_INTERFACES: all + IRONIC_ILO_USE_SWIFT: "false" + IRONIC_ILO_USE_WEB_SERVER_FOR_IMAGES: "true" + IRONIC_FAST_TRACK: "true" + IRONIC_USE_MARIADB: "true" + LISTEN_ALL_INTERFACES: "true" + {{- if .Values.global.ironicIP }} + IRONIC_IP: {{ .Values.global.ironicIP }} + {{- end }} + {{- if ( .Values.global.enable_tls ) }} + RESTART_CONTAINER_CERTIFICATE_UPDATED: "true" + IRONIC_KERNEL_PARAMS: {{ .Values.global.ironicKernelParams }} tls.enabled=true + IPA_INSECURE: "0" + IRONIC_REVERSE_PROXY_SETUP: "true" + INSPECTOR_REVERSE_PROXY_SETUP: "true" + {{- if ( .Values.global.enable_vmedia_tls ) }} + VMEDIA_TLS_PORT: "{{ .Values.global.vmediaTLSPort }}" + {{- end }} + {{- else }} + RESTART_CONTAINER_CERTIFICATE_UPDATED: "false" + IRONIC_KERNEL_PARAMS: {{ .Values.global.ironicKernelParams }} + IPA_INSECURE: "1" + IRONIC_REVERSE_PROXY_SETUP: "false" + {{- end }} + {{- if ( .Values.global.enable_basicAuth ) }} + AUTH_STRATEGY: "http_basic" + INSPECTOR_AUTH_STRATEGY: "http_basic" + {{- end }} + MARIADB_HOST: {{ .Values.global.databaseServiceName }}.{{ .Release.Namespace }}.svc.cluster.local diff --git a/metal3-chart/charts/ironic/templates/deployment.yaml b/metal3-chart/charts/ironic/templates/deployment.yaml new file mode 100644 index 0000000..7f5e39d --- /dev/null +++ b/metal3-chart/charts/ironic/templates/deployment.yaml @@ -0,0 +1,367 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ironic.fullname" . }} + labels: + {{- include "ironic.labels" . | nindent 4 }} +spec: + minReadySeconds: 10 + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "ironic.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "ironic.selectorLabels" . | nindent 8 }} + spec: + {{- if .Values.podSecurityContext }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- end }} + {{- if .Values.baremetaloperator.ironichostNetwork }} + hostNetwork: {{ .Values.baremetaloperator.ironichostNetwork }} + {{- end }} + containers: + - name: ironic-httpd + image: {{ .Values.images.ironic.repository }}:{{ .Values.images.ironic.tag }} + imagePullPolicy: {{ .Values.images.ironic.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + command: + - /bin/runhttpd + envFrom: + - configMapRef: + name: ironic-bmo + livenessProbe: + exec: + command: + - /bin/sh + - -c + - curl {{ if and .Values.global.enable_tls .Values.global.enable_vmedia_tls }}-sSfk https://127.0.0.1:{{ .Values.global.vmediaTLSPort }}/boot.ipxe {{ else }}-sSf http://127.0.0.1:6180/boot.ipxe{{ end }} + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + ports: + {{- if and .Values.global.enable_tls .Values.global.enable_vmedia_tls }} + - containerPort: {{ .Values.global.vmediaTLSPort }} + name: httpd-tls + protocol: TCP + {{- else }} + - containerPort: 6180 + name: httpd + protocol: TCP + {{- end }} + readinessProbe: + exec: + command: + - /bin/sh + - -c + - curl {{ if and .Values.global.enable_tls .Values.global.enable_vmedia_tls }}-sSfk https://127.0.0.1:{{ .Values.global.vmediaTLSPort }}/boot.ipxe {{ else }}-sSf http://127.0.0.1:6180/boot.ipxe{{ end }} + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + volumeMounts: + {{- include "ironic.sharedVolumeMount" . | nindent 10 }} + {{- if .Values.global.enable_tls }} + {{- include "ironic.CAVolumeMounts" . | nindent 10 }} + - name: cert-ironic + mountPath: "/certs/ironic" + readOnly: true + - name: cert-ironic-inspector + mountPath: "/certs/ironic-inspector" + readOnly: true + {{- if .Values.global.enable_vmedia_tls }} + - name: cert-ironic-vmedia + mountPath: "/certs/vmedia" + readOnly: true + {{- end }} + - mountPath: /shared/html/tstcerts + name: cert-ironic-ca + readOnly: true + {{- end }} + - name: ironic-inspector + image: {{ .Values.images.ironic.repository }}:{{ .Values.images.ironic.tag }} + imagePullPolicy: {{ .Values.images.ironic.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + command: + - /bin/runironic-inspector + envFrom: + - configMapRef: + name: ironic-bmo + env: + {{- if .Values.global.enable_basicAuth }} + - name: INSPECTOR_HTPASSWD + valueFrom: + secretKeyRef: + name: ironic-inspector-basic-auth + key: htpasswd + {{- end }} + - name: MARIADB_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: ironic-mariadb + livenessProbe: + exec: + command: + - /bin/sh + - -c + - curl -sSf http://127.0.0.1:{{ if .Values.global.enable_tls }}5049{{ else }}5050{{ end }} + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + ports: + - containerPort: 5050 + name: inspector + protocol: TCP + readinessProbe: + exec: + command: + - /bin/sh + - -c + - curl -sSf http://127.0.0.1:{{ if .Values.global.enable_tls }}5049{{ else }}5050{{ end }} + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + volumeMounts: + {{- include "ironic.sharedVolumeMount" . | nindent 10 }} + {{- if .Values.global.enable_basicAuth }} + - mountPath: "/auth/ironic/auth-config" + name: ironic-basic-auth + subPath: auth-config + readOnly: true + - mountPath: "/auth/ironic-inspector/auth-config" + name: ironic-inspector-basic-auth + subPath: auth-config + readOnly: true + {{- end }} + {{- if .Values.global.enable_tls }} + {{- include "ironic.CAVolumeMounts" . | nindent 10 }} + - name: cert-ironic-inspector + mountPath: "/certs/ironic-inspector" + readOnly: true + {{- end }} + - name: ironic-log-watch + image: {{ .Values.images.ironic.repository }}:{{ .Values.images.ironic.tag }} + imagePullPolicy: {{ .Values.images.ironic.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + command: + - /bin/runlogwatch.sh + volumeMounts: + {{- include "ironic.sharedVolumeMount" . | nindent 10 }} + - name: ironic + image: {{ .Values.images.ironic.repository }}:{{ .Values.images.ironic.tag }} + imagePullPolicy: {{ .Values.images.ironic.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + command: + - /bin/runironic + envFrom: + - configMapRef: + name: ironic-bmo + env: + {{- if .Values.global.enable_basicAuth }} + - name: IRONIC_HTPASSWD + valueFrom: + secretKeyRef: + name: ironic-basic-auth + key: htpasswd + {{- end }} + - name: MARIADB_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: ironic-mariadb + livenessProbe: + exec: + command: + - /bin/sh + - -c + - curl -sSf http://127.0.0.1:{{ if .Values.global.enable_tls }}6388{{ else }}6385{{ end }} + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + ports: + - containerPort: 6385 + name: api + protocol: TCP + readinessProbe: + exec: + command: + - /bin/sh + - -c + - curl -sSf http://127.0.0.1:{{ if .Values.global.enable_tls }}6388{{ else }}6385{{ end }} + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + volumeMounts: + {{- include "ironic.sharedVolumeMount" . | nindent 10 }} + {{- if .Values.global.enable_basicAuth }} + - mountPath: "/auth/ironic/auth-config" + name: ironic-basic-auth + subPath: auth-config + readOnly: true + - mountPath: "/auth/ironic-inspector/auth-config" + name: ironic-inspector-basic-auth + subPath: auth-config + readOnly: true + {{- end }} + {{- if .Values.global.enable_tls }} + {{- include "ironic.CAVolumeMounts" . | nindent 10 }} + - name: cert-ironic + mountPath: "/certs/ironic" + readOnly: true + - mountPath: /etc/pki/trust/anchors + name: trusted-certs + readOnly: true + lifecycle: + postStart: + exec: + command: + - update-ca-certificates + {{- end }} + {{- if .Values.global.enable_dnsmasq }} + - name: ironic-dnsmasq + image: {{ .Values.images.ironic.repository }}:{{ .Values.images.ironic.tag }} + imagePullPolicy: {{ .Values.images.ironic.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + securityContext: + capabilities: + add: + - NET_ADMIN + - NET_RAW + command: + - /bin/rundnsmasq + envFrom: + - configMapRef: + name: ironic-bmo + livenessProbe: + exec: + command: + - sh + - -c + - ss -lun | grep :67 && ss -lun | grep :69 + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + ports: + - containerPort: 67 + name: dhcp + protocol: UDP + - containerPort: 69 + name: tftp + protocol: UDP + readinessProbe: + exec: + command: + - sh + - -c + - ss -lun | grep :67 && ss -lun | grep :69 + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + volumeMounts: + {{- include "ironic.sharedVolumeMount" . | nindent 10 }} + {{- end }} + initContainers: + - name: ironic-ipa-downloader + image: {{ .Values.images.ironicIPADownloader.repository }}:{{ .Values.images.ironicIPADownloader.tag }} + imagePullPolicy: {{ .Values.images.ironicIPADownloader.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} + command: + - /usr/local/bin/get-resource.sh + envFrom: + - configMapRef: + name: ironic-ipa-downloader + volumeMounts: + {{- include "ironic.sharedVolumeMount" . | nindent 10 }} + {{- if .Values.global.enable_tls }} + - mountPath: /tmp/ironic-certificates + name: trusted-certs + {{- end }} + volumes: + - name: ironic-data-volume + persistentVolumeClaim: + claimName: ironic-shared-volume + {{- if .Values.global.enable_basicAuth }} + - name: ironic-basic-auth + secret: + secretName: ironic-basic-auth + - name: ironic-inspector-basic-auth + secret: + secretName: ironic-inspector-basic-auth + {{- if .Values.global.enable_tls }} + - name: trusted-certs + projected: + sources: + - secret: + name: ironic-cacert + {{- if .Values.global.additionalTrustedCAs }} + - secret: + name: tls-ca-additional + {{- end }} + - name: cert-ironic-ca + secret: + secretName: ironic-cacert + - name: cert-ironic + secret: + secretName: ironic-cert + - name: cert-ironic-inspector-ca + secret: + secretName: ironic-cacert + - name: cert-ironic-inspector + secret: + secretName: ironic-inspector-cert + {{- if .Values.global.enable_vmedia_tls }} + - name: cert-ironic-vmedia-ca + secret: + secretName: ironic-cacert + - name: cert-ironic-vmedia + secret: + secretName: ironic-vmedia-cert + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.global.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.global.dnsPolicy }} + dnsPolicy: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/metal3-chart/charts/ironic/templates/issuers.yaml b/metal3-chart/charts/ironic/templates/issuers.yaml new file mode 100644 index 0000000..b03cbcc --- /dev/null +++ b/metal3-chart/charts/ironic/templates/issuers.yaml @@ -0,0 +1,16 @@ +{{- if .Values.global.enable_tls -}} +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: selfsigned-issuer +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: ca-issuer +spec: + ca: + secretName: ironic-cacert +{{- end }} diff --git a/metal3-chart/charts/ironic/templates/pvc.yaml b/metal3-chart/charts/ironic/templates/pvc.yaml new file mode 100644 index 0000000..e50c856 --- /dev/null +++ b/metal3-chart/charts/ironic/templates/pvc.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: ironic-shared-volume + {{- if .Values.persistence.ironic.keep }} + annotations: + "helm.sh/resource-policy": keep + {{- end }} +spec: + accessModes: + {{- if .Values.persistence.ironic.accessMode }} + - {{ .Values.persistence.ironic.accessMode }} + {{- else if eq (int .Values.replicaCount) 1 }} + - ReadWriteOnce + {{- else }} + - ReadWriteMany + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.ironic.size }} + {{- if .Values.persistence.ironic.storageClass }} + storageClassName: {{ .Values.persistence.ironic.storageClass }} + {{- end }} + volumeMode: Filesystem diff --git a/metal3-chart/charts/ironic/templates/secret-tls.yaml b/metal3-chart/charts/ironic/templates/secret-tls.yaml new file mode 100644 index 0000000..173d2fb --- /dev/null +++ b/metal3-chart/charts/ironic/templates/secret-tls.yaml @@ -0,0 +1,16 @@ +{{- if and (.Values.global.enable_tls) + (ne .Values.tlscerts.crt "") + (ne .Values.tlscerts.key "") + (ne .Values.tlscerts.cacert "") -}} +apiVersion: v1 +kind: Secret +metadata: + name: ironic-cacert + labels: + {{- include "ironic.labels" . | nindent 4 }} +type: Opaque +data: + tls.crt: {{ .Values.tlscerts.crt | toString | b64enc }} + tls.key: {{ .Values.tlscerts.key | toString | b64enc }} + ca.crt: {{ .Values.tlscerts.cacert | toString | b64enc }} +{{- end }} diff --git a/metal3-chart/charts/ironic/templates/secrets-basic-auth.yaml b/metal3-chart/charts/ironic/templates/secrets-basic-auth.yaml new file mode 100644 index 0000000..aa5736d --- /dev/null +++ b/metal3-chart/charts/ironic/templates/secrets-basic-auth.yaml @@ -0,0 +1,62 @@ +{{- if .Values.global.enable_basicAuth }} + +{{- $ironicUsername := "" -}} +{{- $ironicPassword := "" -}} +{{- $ironicSecretName := "ironic-basic-auth" -}} + +# Check if the secret is deployed and has a password +{{- $oldIronicSecret := lookup "v1" "Secret" .Release.Namespace $ironicSecretName }} +{{- if and $oldIronicSecret (index $oldIronicSecret.data "username") (index $oldIronicSecret.data "password") }} +{{- $ironicUsername = b64dec (index $oldIronicSecret.data "username" | toString) -}} +{{- $ironicPassword = b64dec (index $oldIronicSecret.data "password" | toString) -}} +# If not, check if a username and password are provided in values.yaml +{{- else if and (.Values.global.auth.ironicUsername) (.Values.global.auth.ironicPassword) }} +{{- $ironicUsername = .Values.global.auth.ironicUsername -}} +{{- $ironicPassword = .Values.global.auth.ironicPassword -}} +{{- else }} +# If no username and password are provided in values.yaml, generate new ones +{{- $ironicUsername = "ironic" -}} +{{- $ironicPassword = (randAlphaNum 20) -}} +{{- end }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $ironicSecretName }} +type: Opaque +data: + username: {{ $ironicUsername | b64enc }} + password: {{ $ironicPassword | b64enc }} + htpasswd: {{ b64enc (htpasswd $ironicUsername $ironicPassword) }} + auth-config: | + {{- printf "[ironic]\nauth_type=http_basic\nusername: %s\npassword: %s" $ironicUsername $ironicPassword | b64enc | nindent 4 }} +--- +{{- $ironicInspectorUsername := "" -}} +{{- $ironicInspectorPassword := "" -}} +{{- $inspectorSecretName := "ironic-inspector-basic-auth" -}} + +# Check if the secret is deployed and has a password +{{- $oldInspectorSecret := lookup "v1" "Secret" .Release.Namespace $inspectorSecretName }} +{{- if and $oldInspectorSecret (index $oldInspectorSecret.data "username") (index $oldInspectorSecret.data "password") }} +{{- $ironicInspectorUsername = b64dec (index $oldInspectorSecret.data "username" | toString) -}} +{{- $ironicInspectorPassword = b64dec (index $oldInspectorSecret.data "password" | toString) -}} +# If not, check if a username and password are provided in values.yaml +{{- else if and (.Values.global.auth.ironicInspectorUsername) (.Values.global.auth.ironicInspectorPassword) }} +{{- $ironicInspectorUsername = .Values.global.auth.ironicInspectorUsername -}} +{{- $ironicInspectorPassword = .Values.global.auth.ironicInspectorPassword -}} +{{- else }} +# If no username and password are provided in values.yaml, generate new ones +{{- $ironicInspectorUsername = "ironic" -}} +{{- $ironicInspectorPassword = (randAlphaNum 20) -}} +{{- end }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $inspectorSecretName }} +type: Opaque +data: + username: {{ $ironicInspectorUsername | b64enc }} + password: {{ $ironicInspectorPassword | b64enc }} + htpasswd: {{ b64enc (htpasswd $ironicInspectorUsername $ironicInspectorPassword) }} + auth-config: | + {{- printf "[inspector]\nauth_type=http_basic\nusername: %s\npassword: %s" $ironicInspectorUsername $ironicInspectorPassword | b64enc | nindent 4 }} +{{- end }} diff --git a/metal3-chart/charts/ironic/templates/service.yaml b/metal3-chart/charts/ironic/templates/service.yaml new file mode 100644 index 0000000..f3f0b51 --- /dev/null +++ b/metal3-chart/charts/ironic/templates/service.yaml @@ -0,0 +1,39 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "ironic.fullname" . }} + labels: + {{- include "ironic.labels" . | nindent 4 }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + ports: + {{- $enableTLS := .Values.global.enable_tls }} + {{- $enableVMediaTLS := .Values.global.enable_vmedia_tls }} + {{- range .Values.service.ports }} + {{- if and (eq .name "httpd") (or (not $enableTLS) (not $enableVMediaTLS)) }} + - name: {{ .name }} + port: {{ .port }} + protocol: {{ .protocol }} + targetPort: {{ .targetPort }} + {{- else if and (eq .name "httpd-tls") ($enableTLS) ($enableVMediaTLS) }} + - name: {{ .name }} + port: {{ .port }} + protocol: {{ .protocol }} + targetPort: {{ .targetPort }} + {{- else if and (ne .name "httpd") (ne .name "httpd-tls") }} + - name: {{ .name }} + port: {{ .port }} + protocol: {{ .protocol }} + targetPort: {{ .targetPort }} + {{- end }} + {{- end }} + selector: + {{- include "ironic.selectorLabels" . | nindent 4 }} + {{- if or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") }} + externalIPs: + {{- toYaml .Values.service.externalIPs | nindent 4 }} + {{- end }} diff --git a/metal3-chart/charts/ironic/templates/serviceaccount.yaml b/metal3-chart/charts/ironic/templates/serviceaccount.yaml new file mode 100644 index 0000000..c94a90f --- /dev/null +++ b/metal3-chart/charts/ironic/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ironic.serviceAccountName" . }} + labels: + {{- include "ironic.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/metal3-chart/charts/ironic/values.yaml b/metal3-chart/charts/ironic/values.yaml new file mode 100644 index 0000000..2ffb69a --- /dev/null +++ b/metal3-chart/charts/ironic/values.yaml @@ -0,0 +1,153 @@ +# Default values for ironic. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +global: + # whether to enable dnsmasq on the provisioning network (for PXE boot) + enable_dnsmasq: false + + # whether to enable PXE boot capability + # NOTE: enable_dnsmasq must set to 'true' in order for this option to be effective. + enable_pxe_boot: false + + # DNS Policy of the Ironic pod + dnsPolicy: "ClusterFirstWithHostNet" + + # IP address of the router associated with the specified DHCP + # address range + dnsmasqDefaultRouter: "" + + # IP address of the dns server to be provided with DHCP + # response + dnsmasqDNSServer: "" + + # specify comma-delimited xrange of IP addresses the DHCP server will manage. + # e.g 192.168.20.20,192.168.20.80 + dhcpRange: "" + + # Network interface on which provisioning network can be accessed + # Note this must be a dedicated NIC separate from the controlplane network + provisioningInterface: "" + + # IP Address assigned to network interface on provisioning network + provisioningIP: "" + + # Whether the NIC names should be predictable or not + predictableNicNames: "true" + + # The kernel params for Ironic + ironicKernelParams: "console=ttyS0" + + databaseServiceName: "metal3-mariadb" + + # In a multi-node kubernetes cluster, we need to "pin" the + # ironic containers to the given host where the + # provisioningIP exists. Uncomment the nodeSelector + # here and update the hostname accordingly. + #nodeSelector: + #kubernetes.io/hostname: "csrancher-n1" + + # Comment this out when pinning the pdns containers to a specfic host. + nodeSelector: {} + +replicaCount: 1 + +images: + ironic: + repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/ironic + pullPolicy: IfNotPresent + tag: 24.1.2.0 + ironicIPADownloader: + repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/ironic-ipa-downloader + pullPolicy: IfNotPresent + tag: 2.0.0 + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: + runAsUser: 10475 + fsGroup: 10475 + +securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + runAsNonRoot: true + +service: + type: LoadBalancer + annotations: {} + externalIPs: [] + ports: + - name: httpd + port: 6180 + protocol: TCP + targetPort: 6180 + - name: httpd-tls + port: 6185 + protocol: TCP + targetPort: 6185 + - name: inspector + port: 5050 + protocol: TCP + targetPort: 5050 + - name: api + port: 6385 + protocol: TCP + targetPort: 6385 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +tolerations: [] + +affinity: {} + +baremetaloperator: + cloudflareApiToken: "foo" + ironichostNetwork: true + +debug: + ironicRamdiskSshKey: "" + +tlscerts: + cacert: "" + key: "" + crt: "" + +persistence: + ironic: + # storageClass for the ironic shared volume + # Ensure the storageClass is defined + storageClass: "" + # size of the ironic shared volume + size: "1Gi" + # accessMode of the ironic shared volume PVC + # If empty defaults to ReadWriteOnce when replicaCount=1 otherwise ReadWriteMany + accessMode: "" + # flag to indicate to keep pvc upon helm uninstall + keep: false diff --git a/metal3-chart/charts/mariadb/.helmignore b/metal3-chart/charts/mariadb/.helmignore new file mode 100644 index 0000000..f0907ec --- /dev/null +++ b/metal3-chart/charts/mariadb/.helmignore @@ -0,0 +1,24 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ + diff --git a/metal3-chart/charts/mariadb/Chart.yaml b/metal3-chart/charts/mariadb/Chart.yaml new file mode 100644 index 0000000..df93690 --- /dev/null +++ b/metal3-chart/charts/mariadb/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: 10.6.7 +description: A Helm chart for MariaDB, used by Metal3 +name: mariadb +type: application +version: 0.5.4 diff --git a/metal3-chart/charts/mariadb/templates/_helpers.tpl b/metal3-chart/charts/mariadb/templates/_helpers.tpl new file mode 100644 index 0000000..d3d47e4 --- /dev/null +++ b/metal3-chart/charts/mariadb/templates/_helpers.tpl @@ -0,0 +1,64 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "mariadb.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "mariadb.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "mariadb.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "mariadb.labels" -}} +helm.sh/chart: {{ include "mariadb.chart" . }} +{{ include "mariadb.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "mariadb.selectorLabels" -}} +app.kubernetes.io/component: mariadb +app.kubernetes.io/name: {{ include "mariadb.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "mariadb.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "mariadb.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + diff --git a/metal3-chart/charts/mariadb/templates/configmap.yaml b/metal3-chart/charts/mariadb/templates/configmap.yaml new file mode 100644 index 0000000..59a2cc1 --- /dev/null +++ b/metal3-chart/charts/mariadb/templates/configmap.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: mariadb-cm + labels: + {{- include "mariadb.labels" . | nindent 4 }} +data: + RESTART_CONTAINER_CERTIFICATE_UPDATED: "false" diff --git a/metal3-chart/charts/mariadb/templates/deployment.yaml b/metal3-chart/charts/mariadb/templates/deployment.yaml new file mode 100644 index 0000000..070c2fb --- /dev/null +++ b/metal3-chart/charts/mariadb/templates/deployment.yaml @@ -0,0 +1,85 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "mariadb.fullname" . }} + labels: + {{- include "mariadb.labels" . | nindent 4 }} +spec: + replicas: {{.Values.replicaCount}} + selector: + matchLabels: + {{- include "mariadb.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "mariadb.selectorLabels" . | nindent 8 }} + spec: + {{- $volmounts := toYaml .Values.volumeMounts | trim | nindent 12 }} + {{- $volumes := toYaml .Values.volumes | trim | nindent 8 }} + serviceAccountName: {{ include "mariadb.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: mariadb + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + env: + - name: MARIADB_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: ironic-mariadb + - name: RESTART_CONTAINER_CERTIFICATE_UPDATED + valueFrom: + configMapKeyRef: + name: mariadb-cm + key: RESTART_CONTAINER_CERTIFICATE_UPDATED + lifecycle: + preStop: + exec: + command: + - sh + - -c + - mysqladmin shutdown -uironic -p$(printenv MARIADB_PASSWORD) + livenessProbe: + exec: + command: + - sh + - -c + - mysqladmin status -uironic -p$(printenv MARIADB_PASSWORD) + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + ports: + - containerPort: 3306 + name: mariadb + protocol: TCP + readinessProbe: + exec: + command: + - sh + - -c + - mysqladmin status -uironic -p$(printenv MARIADB_PASSWORD) + failureThreshold: 10 + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + volumeMounts: + {{- $volmounts }} + {{- with .Values.global.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + {{- $volumes }} diff --git a/metal3-chart/charts/mariadb/templates/pvc.yaml b/metal3-chart/charts/mariadb/templates/pvc.yaml new file mode 100644 index 0000000..fa0a176 --- /dev/null +++ b/metal3-chart/charts/mariadb/templates/pvc.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: mariadb-volume-claim + {{- if .Values.persistence.keep }} + annotations: + "helm.sh/resource-policy": keep + {{- end }} +spec: + accessModes: + {{- if .Values.persistence.accessMode }} + - {{ .Values.persistence.accessMode }} + {{- else if eq (int .Values.replicaCount) 1 }} + - ReadWriteOnce + {{- else }} + - ReadWriteMany + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size }} + {{- if .Values.persistence.storageClass }} + storageClassName: {{ .Values.persistence.storageClass }} + {{- end }} + volumeMode: Filesystem diff --git a/metal3-chart/charts/mariadb/templates/secret.yaml b/metal3-chart/charts/mariadb/templates/secret.yaml new file mode 100644 index 0000000..d4b2318 --- /dev/null +++ b/metal3-chart/charts/mariadb/templates/secret.yaml @@ -0,0 +1,21 @@ +{{- $secret_name := "ironic-mariadb" -}} + +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secret_name }} + labels: + {{- include "mariadb.labels" . | nindent 4 }} +type: Opaque +data: + # Check if the secret is deployed and has a password + {{- $old_sec := lookup "v1" "Secret" .Release.Namespace $secret_name }} + {{- if and $old_sec (index $old_sec.data "password") }} + password: {{ index $old_sec.data "password" }} + {{- else if .Values.password }} + # If not, check if a password is provided in values.yaml + password: {{ .Values.password | toString | b64enc }} + {{- else }} + # If no secret and no password in values.yaml, generate a new password + password: {{ randAlphaNum 20 | b64enc }} + {{- end }} \ No newline at end of file diff --git a/metal3-chart/charts/mariadb/templates/service-account.yaml b/metal3-chart/charts/mariadb/templates/service-account.yaml new file mode 100644 index 0000000..5101f01 --- /dev/null +++ b/metal3-chart/charts/mariadb/templates/service-account.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "mariadb.serviceAccountName" . }} + labels: + {{- include "mariadb.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + diff --git a/metal3-chart/charts/mariadb/templates/service.yaml b/metal3-chart/charts/mariadb/templates/service.yaml new file mode 100644 index 0000000..5d0d75d --- /dev/null +++ b/metal3-chart/charts/mariadb/templates/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.global.databaseServiceName }} + labels: + {{- include "mariadb.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + selector: + {{- include "mariadb.selectorLabels" . | nindent 4 }} + ports: + {{- with .Values.service.ports }} + {{- toYaml . | nindent 2 }} + {{- end }} \ No newline at end of file diff --git a/metal3-chart/charts/mariadb/values.yaml b/metal3-chart/charts/mariadb/values.yaml new file mode 100644 index 0000000..7d2fbce --- /dev/null +++ b/metal3-chart/charts/mariadb/values.yaml @@ -0,0 +1,67 @@ +global: + databaseServiceName: "metal3-mariadb" + nodeSelector: {} + +replicaCount: 1 + +service: + type: ClusterIP + ports: + - protocol: TCP + port: 3306 + targetPort: 3306 + +image: + repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/suse/mariadb + pullPolicy: IfNotPresent + tag: 10.6.15.1 + +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: + runAsUser: 10060 + fsGroup: 10060 + +securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + runAsNonRoot: true + +# Password for the mariadb ironic user +password: "" + +persistence: + # storageClass for the mariadb data volume + storageClass: "" + # size of the mariadb data volume + size: "1Gi" + # accessMode of the mariadb data volume PVC + # If empty defaults to ReadWriteOnce when replicaCount=1 otherwise ReadWriteMany + accessMode: "" + # flag to indicate to keep pvc upon helm uninstall + keep: false + +volumeMounts: + - name: mariadb-data-volume + mountPath: /var/lib/mysql + +volumes: + - name: mariadb-data-volume + persistentVolumeClaim: + claimName: mariadb-volume-claim diff --git a/metal3-chart/charts/media/.helmignore b/metal3-chart/charts/media/.helmignore new file mode 100644 index 0000000..1b9a9cc --- /dev/null +++ b/metal3-chart/charts/media/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/metal3-chart/charts/media/Chart.yaml b/metal3-chart/charts/media/Chart.yaml new file mode 100644 index 0000000..544c704 --- /dev/null +++ b/metal3-chart/charts/media/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: 1.16.0 +description: A Helm chart for Media, used by Metal3 +name: media +type: application +version: 0.5.0 diff --git a/metal3-chart/charts/media/templates/NOTES.txt b/metal3-chart/charts/media/templates/NOTES.txt new file mode 100644 index 0000000..c6350f5 --- /dev/null +++ b/metal3-chart/charts/media/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "media.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "media.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "media.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "media.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/metal3-chart/charts/media/templates/_helpers.tpl b/metal3-chart/charts/media/templates/_helpers.tpl new file mode 100644 index 0000000..37c5e87 --- /dev/null +++ b/metal3-chart/charts/media/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "media.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "media.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "media.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "media.labels" -}} +helm.sh/chart: {{ include "media.chart" . }} +{{ include "media.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "media.selectorLabels" -}} +app.kubernetes.io/component: media +app.kubernetes.io/name: {{ include "media.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "media.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "media.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/metal3-chart/charts/media/templates/deployment.yaml b/metal3-chart/charts/media/templates/deployment.yaml new file mode 100644 index 0000000..9dccd57 --- /dev/null +++ b/metal3-chart/charts/media/templates/deployment.yaml @@ -0,0 +1,66 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "media.fullname" . }} + labels: + {{- include "media.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "media.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + rollme: {{ randAlphaNum 5 | quote }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "media.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "media.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + command: + - /usr/sbin/httpd + args: + - -DFOREGROUND + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 80 + protocol: TCP + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.global.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/metal3-chart/charts/media/templates/hpa.yaml b/metal3-chart/charts/media/templates/hpa.yaml new file mode 100644 index 0000000..0bd8a10 --- /dev/null +++ b/metal3-chart/charts/media/templates/hpa.yaml @@ -0,0 +1,28 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "media.fullname" . }} + labels: + {{- include "media.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "media.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/metal3-chart/charts/media/templates/ingress.yaml b/metal3-chart/charts/media/templates/ingress.yaml new file mode 100644 index 0000000..576ecb9 --- /dev/null +++ b/metal3-chart/charts/media/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "media.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "media.labels" . | nindent 4 }} + {{- with $_ := merge .Values.ingress.annotations $.Values.global.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ tpl .host $ }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/metal3-chart/charts/media/templates/persistentvolume.yaml b/metal3-chart/charts/media/templates/persistentvolume.yaml new file mode 100644 index 0000000..8ebf28c --- /dev/null +++ b/metal3-chart/charts/media/templates/persistentvolume.yaml @@ -0,0 +1,18 @@ +{{- if eq .Values.mediaVolume.storageClassName "local" }} +--- +kind: PersistentVolume +apiVersion: v1 +metadata: + name: media + labels: + {{- include "media.labels" . | nindent 4 }} +spec: + storageClassName: {{ .Values.mediaVolume.storageClassName }} + accessModes: + {{ toYaml .Values.mediaVolume.accessModes }} + capacity: + storage: {{ .Values.mediaVolume.storage }} + hostPath: + path: {{ .Values.mediaVolume.hostPath }} + type: DirectoryOrCreate +{{- end }} diff --git a/metal3-chart/charts/media/templates/persistentvolumeclaim.yaml b/metal3-chart/charts/media/templates/persistentvolumeclaim.yaml new file mode 100644 index 0000000..7cb52f8 --- /dev/null +++ b/metal3-chart/charts/media/templates/persistentvolumeclaim.yaml @@ -0,0 +1,14 @@ +--- +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: media + labels: + {{- include "media.labels" . | nindent 4 }} +spec: + storageClassName: {{ .Values.mediaVolume.storageClassName }} + accessModes: + {{ toYaml .Values.mediaVolume.accessModes }} + resources: + requests: + storage: {{ .Values.mediaVolume.storage }} diff --git a/metal3-chart/charts/media/templates/service.yaml b/metal3-chart/charts/media/templates/service.yaml new file mode 100644 index 0000000..93598e5 --- /dev/null +++ b/metal3-chart/charts/media/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "media.fullname" . }} + labels: + {{- include "media.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "media.selectorLabels" . | nindent 4 }} diff --git a/metal3-chart/charts/media/templates/serviceaccount.yaml b/metal3-chart/charts/media/templates/serviceaccount.yaml new file mode 100644 index 0000000..3badde4 --- /dev/null +++ b/metal3-chart/charts/media/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "media.serviceAccountName" . }} + labels: + {{- include "media.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/metal3-chart/charts/media/templates/storageclass.yaml b/metal3-chart/charts/media/templates/storageclass.yaml new file mode 100644 index 0000000..6c491aa --- /dev/null +++ b/metal3-chart/charts/media/templates/storageclass.yaml @@ -0,0 +1,9 @@ +--- +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: {{ include "media.fullname" . }} + labels: + {{- include "media.labels" . | nindent 4 }} +provisioner: kubernetes.io/no-provisioner +volumeBindingMode: WaitForFirstConsumer diff --git a/metal3-chart/charts/media/templates/tests/test-connection.yaml b/metal3-chart/charts/media/templates/tests/test-connection.yaml new file mode 100644 index 0000000..f96c62c --- /dev/null +++ b/metal3-chart/charts/media/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "media.fullname" . }}-test-connection" + labels: + {{- include "media.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "media.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/metal3-chart/charts/media/values.yaml b/metal3-chart/charts/media/values.yaml new file mode 100644 index 0000000..9f46ebe --- /dev/null +++ b/metal3-chart/charts/media/values.yaml @@ -0,0 +1,117 @@ +# Default values for media. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +global: + # Global ingress annotations that is shared by all the ingress services. + # For example, use it to override extern-dns records. + ingress: + annotations: {} + # The IP to register with external-dns for this service + #external-dns.alpha.kubernetes.io/target: 192.168.20.5 + + # If running in a multi-node kubernetes cluster, "pin" the media container + # to the given host where the /opt/media volume exists. Uncomment the + # nodeSelector and update the hostname accordingly. + #nodeSelector: + #kubernetes.io/hostname: "my-hostname" + + # Comment this out when pinning the media container to a specfic host. + nodeSelector: {} + +replicaCount: 1 + +image: + repository: registry.opensuse.org/isv/suse/edge/metal3/containers/images/ironic + pullPolicy: IfNotPresent + tag: 24.1.2.0 + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: + runAsUser: 10475 + fsGroup: 10475 + +securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + runAsNonRoot: true + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: true + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: media.suse.baremetal + paths: + - path: / + pathType: Prefix + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +tolerations: [] + +affinity: {} + +# volumes +volumes: + - name: assets + persistentVolumeClaim: + claimName: media + +# volume mounts +volumeMounts: + - mountPath: /srv/www/htdocs + name: assets + +# media volume settings +mediaVolume: + storageClassName: local + accessModes: + - ReadOnlyMany + hostPath: /opt/media + storage: 5Gi diff --git a/metal3-chart/templates/NOTES.txt b/metal3-chart/templates/NOTES.txt new file mode 100644 index 0000000..acbebf0 --- /dev/null +++ b/metal3-chart/templates/NOTES.txt @@ -0,0 +1,3 @@ +TBD: Document the deployed application/service endpoints + +You should now be ready to install and configure ClusterAPI. diff --git a/metal3-chart/templates.obscpio b/metal3-chart/templates/_helpers.tpl similarity index 69% rename from metal3-chart/templates.obscpio rename to metal3-chart/templates/_helpers.tpl index a34873e..67024dd 100644 Binary files a/metal3-chart/templates.obscpio and b/metal3-chart/templates/_helpers.tpl differ diff --git a/metallb-chart/charts.obscpio b/metallb-chart/charts.obscpio deleted file mode 100644 index abb1383..0000000 Binary files a/metallb-chart/charts.obscpio and /dev/null differ diff --git a/metallb-chart/charts/frr-k8s/Chart.yaml b/metallb-chart/charts/frr-k8s/Chart.yaml new file mode 100644 index 0000000..2fa4501 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/Chart.yaml @@ -0,0 +1,11 @@ +apiVersion: v2 +appVersion: v0.0.14 +description: A cloud native wrapper of FRR +home: https://metallb.universe.tf +icon: https://metallb.universe.tf/images/logo/metallb-white.png +kubeVersion: '>= 1.19.0-0' +name: frr-k8s +sources: +- https://github.com/metallb/frr-k8s +type: application +version: 0.0.15 diff --git a/metallb-chart/charts/frr-k8s/README.md b/metallb-chart/charts/frr-k8s/README.md new file mode 100644 index 0000000..0418d64 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/README.md @@ -0,0 +1,96 @@ +# frr-k8s + +![Version: 0.0.14](https://img.shields.io/badge/Version-0.0.14-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.0.14](https://img.shields.io/badge/AppVersion-v0.0.14-informational?style=flat-square) + +A cloud native wrapper of FRR + +**Homepage:** + +## Source Code + +* + +## Requirements + +Kubernetes: `>= 1.19.0-0` + +| Repository | Name | Version | +|------------|------|---------| +| | crds | 0.0.14 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| crds.enabled | bool | `true` | | +| crds.validationFailurePolicy | string | `"Fail"` | | +| frrk8s.affinity | object | `{}` | | +| frrk8s.alwaysBlock | string | `""` | | +| frrk8s.disableCertRotation | bool | `false` | | +| frrk8s.frr.image.pullPolicy | string | `nil` | | +| frrk8s.frr.image.repository | string | `"quay.io/frrouting/frr"` | | +| frrk8s.frr.image.tag | string | `"9.1.0"` | | +| frrk8s.frr.metricsBindAddress | string | `"127.0.0.1"` | | +| frrk8s.frr.metricsPort | int | `7573` | | +| frrk8s.frr.resources | object | `{}` | | +| frrk8s.frr.secureMetricsPort | int | `9141` | | +| frrk8s.frrMetrics.resources | object | `{}` | | +| frrk8s.healthPort | int | `8081` | | +| frrk8s.image.pullPolicy | string | `nil` | | +| frrk8s.image.repository | string | `"quay.io/metallb/frr-k8s"` | | +| frrk8s.image.tag | string | `nil` | | +| frrk8s.labels.app | string | `"frr-k8s"` | | +| frrk8s.livenessProbe.enabled | bool | `true` | | +| frrk8s.livenessProbe.failureThreshold | int | `3` | | +| frrk8s.livenessProbe.initialDelaySeconds | int | `10` | | +| frrk8s.livenessProbe.periodSeconds | int | `10` | | +| frrk8s.livenessProbe.successThreshold | int | `1` | | +| frrk8s.livenessProbe.timeoutSeconds | int | `1` | | +| frrk8s.logLevel | string | `"info"` | Controller log level. Must be one of: `all`, `debug`, `info`, `warn`, `error` or `none` | +| frrk8s.nodeSelector | object | `{}` | | +| frrk8s.podAnnotations | object | `{}` | | +| frrk8s.priorityClassName | string | `""` | | +| frrk8s.readinessProbe.enabled | bool | `true` | | +| frrk8s.readinessProbe.failureThreshold | int | `3` | | +| frrk8s.readinessProbe.initialDelaySeconds | int | `10` | | +| frrk8s.readinessProbe.periodSeconds | int | `10` | | +| frrk8s.readinessProbe.successThreshold | int | `1` | | +| frrk8s.readinessProbe.timeoutSeconds | int | `1` | | +| frrk8s.reloader.resources | object | `{}` | | +| frrk8s.resources | object | `{}` | | +| frrk8s.restartOnRotatorSecretRefresh | bool | `false` | | +| frrk8s.runtimeClassName | string | `""` | | +| frrk8s.serviceAccount.annotations | object | `{}` | | +| frrk8s.serviceAccount.create | bool | `true` | | +| frrk8s.serviceAccount.name | string | `""` | | +| frrk8s.startupProbe.enabled | bool | `true` | | +| frrk8s.startupProbe.failureThreshold | int | `30` | | +| frrk8s.startupProbe.periodSeconds | int | `5` | | +| frrk8s.tolerateMaster | bool | `true` | | +| frrk8s.tolerations | list | `[]` | | +| frrk8s.updateStrategy.type | string | `"RollingUpdate"` | | +| fullnameOverride | string | `""` | | +| nameOverride | string | `""` | | +| prometheus.metricsBindAddress | string | `"127.0.0.1"` | | +| prometheus.metricsPort | int | `7572` | | +| prometheus.metricsTLSSecret | string | `""` | | +| prometheus.namespace | string | `""` | | +| prometheus.rbacPrometheus | bool | `false` | | +| prometheus.rbacProxy.pullPolicy | string | `nil` | | +| prometheus.rbacProxy.repository | string | `"gcr.io/kubebuilder/kube-rbac-proxy"` | | +| prometheus.rbacProxy.tag | string | `"v0.12.0"` | | +| prometheus.scrapeAnnotations | bool | `false` | | +| prometheus.secureMetricsPort | int | `9140` | | +| prometheus.serviceAccount | string | `""` | | +| prometheus.serviceMonitor.additionalLabels | object | `{}` | | +| prometheus.serviceMonitor.annotations | object | `{}` | | +| prometheus.serviceMonitor.enabled | bool | `false` | | +| prometheus.serviceMonitor.interval | string | `nil` | | +| prometheus.serviceMonitor.jobLabel | string | `"app.kubernetes.io/name"` | | +| prometheus.serviceMonitor.metricRelabelings | list | `[]` | | +| prometheus.serviceMonitor.relabelings | list | `[]` | | +| prometheus.serviceMonitor.tlsConfig.insecureSkipVerify | bool | `true` | | +| rbac.create | bool | `true` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.10.0](https://github.com/norwoodj/helm-docs/releases/v1.10.0) diff --git a/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrconfigurations.yaml b/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrconfigurations.yaml new file mode 100644 index 0000000..2813767 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrconfigurations.yaml @@ -0,0 +1,462 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: frrconfigurations.frrk8s.metallb.io +spec: + group: frrk8s.metallb.io + names: + kind: FRRConfiguration + listKind: FRRConfigurationList + plural: frrconfigurations + singular: frrconfiguration + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: FRRConfiguration is a piece of FRR configuration. + 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: FRRConfigurationSpec defines the desired state of FRRConfiguration. + properties: + bgp: + description: BGP is the configuration related to the BGP protocol. + properties: + bfdProfiles: + description: BFDProfiles is the list of bfd profiles to be used + when configuring the neighbors. + items: + description: |- + BFDProfile is the configuration related to the BFD protocol associated + to a BGP session. + properties: + detectMultiplier: + description: |- + Configures the detection multiplier to determine + packet loss. The remote transmission interval will be multiplied + by this value to determine the connection loss detection timer. + format: int32 + maximum: 255 + minimum: 2 + type: integer + echoInterval: + description: |- + Configures the minimal echo receive transmission + interval that this system is capable of handling in milliseconds. + Defaults to 50ms + format: int32 + maximum: 60000 + minimum: 10 + type: integer + echoMode: + description: |- + Enables or disables the echo transmission mode. + This mode is disabled by default, and not supported on multi + hops setups. + type: boolean + minimumTtl: + description: |- + For multi hop sessions only: configure the minimum + expected TTL for an incoming BFD control packet. + format: int32 + maximum: 254 + minimum: 1 + type: integer + name: + description: |- + The name of the BFD Profile to be referenced in other parts + of the configuration. + type: string + passiveMode: + description: |- + Mark session as passive: a passive session will not + attempt to start the connection and will wait for control packets + from peer before it begins replying. + type: boolean + receiveInterval: + description: |- + The minimum interval that this system is capable of + receiving control packets in milliseconds. + Defaults to 300ms. + format: int32 + maximum: 60000 + minimum: 10 + type: integer + transmitInterval: + description: |- + The minimum transmission interval (less jitter) + that this system wants to use to send BFD control packets in + milliseconds. Defaults to 300ms + format: int32 + maximum: 60000 + minimum: 10 + type: integer + required: + - name + type: object + type: array + routers: + description: Routers is the list of routers we want FRR to configure + (one per VRF). + items: + description: Router represent a neighbor router we want FRR + to connect to. + properties: + asn: + description: ASN is the AS number to use for the local end + of the session. + format: int32 + maximum: 4294967295 + minimum: 0 + type: integer + id: + description: ID is the BGP router ID + type: string + imports: + description: Imports is the list of imported VRFs we want + for this router / vrf. + items: + description: Import represents the possible imported VRFs + to a given router. + properties: + vrf: + description: Vrf is the vrf we want to import from + type: string + type: object + type: array + neighbors: + description: Neighbors is the list of neighbors we want + to establish BGP sessions with. + items: + description: Neighbor represents a BGP Neighbor we want + FRR to connect to. + properties: + address: + description: Address is the IP address to establish + the session with. + type: string + asn: + description: ASN is the AS number to use for the local + end of the session. + format: int32 + maximum: 4294967295 + minimum: 0 + type: integer + bfdProfile: + description: |- + BFDProfile is the name of the BFD Profile to be used for the BFD session associated + to the BGP session. If not set, the BFD session won't be set up. + type: string + connectTime: + description: Requested BGP connect time, controls + how long BGP waits between connection attempts to + a neighbor. + type: string + x-kubernetes-validations: + - message: connect time should be between 1 seconds + to 65535 + rule: duration(self).getSeconds() >= 1 && duration(self).getSeconds() + <= 65535 + - message: connect time should contain a whole number + of seconds + rule: duration(self).getMilliseconds() % 1000 == + 0 + disableMP: + default: false + description: To set if we want to disable MP BGP that + will separate IPv4 and IPv6 route exchanges into + distinct BGP sessions. + type: boolean + ebgpMultiHop: + description: EBGPMultiHop indicates if the BGPPeer + is multi-hops away. + type: boolean + enableGracefulRestart: + description: |- + EnableGracefulRestart allows BGP peer to continue to forward data packets along + known routes while the routing protocol information is being restored. If + the session is already established, the configuration will have effect + after reconnecting to the peer + type: boolean + holdTime: + description: |- + HoldTime is the requested BGP hold time, per RFC4271. + Defaults to 180s. + type: string + keepaliveTime: + description: |- + KeepaliveTime is the requested BGP keepalive time, per RFC4271. + Defaults to 60s. + type: string + password: + description: |- + Password to be used for establishing the BGP session. + Password and PasswordSecret are mutually exclusive. + type: string + passwordSecret: + description: |- + PasswordSecret is name of the authentication secret for the neighbor. + the secret must be of type "kubernetes.io/basic-auth", and created in the + same namespace as the frr-k8s daemon. The password is stored in the + secret as the key "password". + Password and PasswordSecret are mutually exclusive. + properties: + name: + description: name is unique within a namespace + to reference a secret resource. + type: string + namespace: + description: namespace defines the space within + which the secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + port: + description: |- + Port is the port to dial when establishing the session. + Defaults to 179. + maximum: 16384 + minimum: 0 + type: integer + sourceaddress: + description: |- + SourceAddress is the IPv4 or IPv6 source address to use for the BGP + session to this neighbour, may be specified as either an IP address + directly or as an interface name + type: string + toAdvertise: + description: |- + ToAdvertise represents the list of prefixes to advertise to the given neighbor + and the associated properties. + properties: + allowed: + description: |- + Allowed is is the list of prefixes allowed to be propagated to + this neighbor. They must match the prefixes defined in the router. + properties: + mode: + default: filtered + description: |- + Mode is the mode to use when handling the prefixes. + When set to "filtered", only the prefixes in the given list will be allowed. + When set to "all", all the prefixes configured on the router will be allowed. + enum: + - all + - filtered + type: string + prefixes: + items: + type: string + type: array + type: object + withCommunity: + description: |- + PrefixesWithCommunity is a list of prefixes that are associated to a + bgp community when being advertised. The prefixes associated to a given local pref + must be in the prefixes allowed to be advertised. + items: + description: CommunityPrefixes is a list of + prefixes associated to a community. + properties: + community: + description: Community is the community + associated to the prefixes. + type: string + prefixes: + description: Prefixes is the list of prefixes + associated to the community. + format: cidr + items: + type: string + minItems: 1 + type: array + type: object + type: array + withLocalPref: + description: |- + PrefixesWithLocalPref is a list of prefixes that are associated to a local + preference when being advertised. The prefixes associated to a given local pref + must be in the prefixes allowed to be advertised. + items: + description: LocalPrefPrefixes is a list of + prefixes associated to a local preference. + properties: + localPref: + description: LocalPref is the local preference + associated to the prefixes. + format: int32 + type: integer + prefixes: + description: Prefixes is the list of prefixes + associated to the local preference. + format: cidr + items: + type: string + minItems: 1 + type: array + type: object + type: array + type: object + toReceive: + description: ToReceive represents the list of prefixes + to receive from the given neighbor. + properties: + allowed: + description: |- + Allowed is the list of prefixes allowed to be received from + this neighbor. + properties: + mode: + default: filtered + description: |- + Mode is the mode to use when handling the prefixes. + When set to "filtered", only the prefixes in the given list will be allowed. + When set to "all", all the prefixes configured on the router will be allowed. + enum: + - all + - filtered + type: string + prefixes: + items: + description: PrefixSelector is a filter + of prefixes to receive. + properties: + ge: + description: |- + The prefix length modifier. This selector accepts any matching prefix with length + greater or equal the given value. + format: int32 + maximum: 128 + minimum: 1 + type: integer + le: + description: |- + The prefix length modifier. This selector accepts any matching prefix with length + less or equal the given value. + format: int32 + maximum: 128 + minimum: 1 + type: integer + prefix: + format: cidr + type: string + type: object + type: array + type: object + type: object + required: + - address + - asn + type: object + type: array + prefixes: + description: Prefixes is the list of prefixes we want to + advertise from this router instance. + items: + type: string + type: array + vrf: + description: VRF is the host vrf used to establish sessions + from this router. + type: string + required: + - asn + type: object + type: array + type: object + nodeSelector: + description: |- + NodeSelector limits the nodes that will attempt to apply this config. + When specified, the configuration will be considered only on nodes + whose labels match the specified selectors. + When it is not specified all nodes will attempt to apply this config. + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + raw: + description: |- + Raw is a snippet of raw frr configuration that gets appended to the + one rendered translating the type safe API. + properties: + priority: + description: |- + Priority is the order with this configuration is appended to the + bottom of the rendered configuration. A higher value means the + raw config is appended later in the configuration file. + type: integer + rawConfig: + description: |- + Config is a raw FRR configuration to be appended to the configuration + rendered via the k8s api. + type: string + type: object + type: object + status: + description: FRRConfigurationStatus defines the observed state of FRRConfiguration. + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrnodestates.yaml b/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrnodestates.yaml new file mode 100644 index 0000000..66f4196 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/crds/frrk8s.metallb.io_frrnodestates.yaml @@ -0,0 +1,65 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: frrnodestates.frrk8s.metallb.io +spec: + group: frrk8s.metallb.io + names: + kind: FRRNodeState + listKind: FRRNodeStateList + plural: frrnodestates + singular: frrnodestate + scope: Cluster + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: FRRNodeState exposes the status of the FRR instance running on + each node. + 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: FRRNodeStateSpec defines the desired state of FRRNodeState. + type: object + status: + description: FRRNodeStateStatus defines the observed state of FRRNodeState. + properties: + lastConversionResult: + description: LastConversionResult is the status of the last translation + between the `FRRConfiguration`s resources and FRR's configuration, + contains "success" or an error. + type: string + lastReloadResult: + description: LastReloadResult represents the status of the last configuration + update operation by FRR, contains "success" or an error. + type: string + runningConfig: + description: RunningConfig represents the current FRR running config, + which is the configuration the FRR instance is currently running + with. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metallb-chart/charts/frr-k8s/templates/NOTES.txt b/metallb-chart/charts/frr-k8s/templates/NOTES.txt new file mode 100644 index 0000000..813ab8a --- /dev/null +++ b/metallb-chart/charts/frr-k8s/templates/NOTES.txt @@ -0,0 +1,4 @@ +FRR-k8s is now running in the cluster. + +Now you can configure it via its CRs. Please refer to the frr-k8s official docs +on how to use the CRs. diff --git a/metallb-chart/charts/frr-k8s/templates/_helpers.tpl b/metallb-chart/charts/frr-k8s/templates/_helpers.tpl new file mode 100644 index 0000000..8b728d2 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "frrk8s.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "frrk8s.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "frrk8s.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "frrk8s.labels" -}} +helm.sh/chart: {{ include "frrk8s.chart" . }} +{{ include "frrk8s.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "frrk8s.selectorLabels" -}} +app.kubernetes.io/name: {{ include "frrk8s.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the frrk8s service account to use +*/}} +{{- define "frrk8s.serviceAccountName" -}} +{{- if .Values.frrk8s.serviceAccount.create }} +{{- default (printf "%s-controller" (include "frrk8s.fullname" .)) .Values.frrk8s.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.frrk8s.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/metallb-chart/charts/frr-k8s/templates/controller.yaml b/metallb-chart/charts/frr-k8s/templates/controller.yaml new file mode 100644 index 0000000..50badde --- /dev/null +++ b/metallb-chart/charts/frr-k8s/templates/controller.yaml @@ -0,0 +1,431 @@ +# FRR expects to have these files owned by frr:frr on startup. +# Having them in a ConfigMap allows us to modify behaviors: for example enabling more daemons on startup. +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "frrk8s.fullname" . }}-frr-startup + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "frrk8s.labels" . | nindent 4 }} + app.kubernetes.io/component: frr-k8s +data: + daemons: | + # This file tells the frr package which daemons to start. + # + # Sample configurations for these daemons can be found in + # /usr/share/doc/frr/examples/. + # + # ATTENTION: + # + # When activating a daemon for the first time, a config file, even if it is + # empty, has to be present *and* be owned by the user and group "frr", else + # the daemon will not be started by /etc/init.d/frr. The permissions should + # be u=rw,g=r,o=. + # When using "vtysh" such a config file is also needed. It should be owned by + # group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too. + # + # The watchfrr and zebra daemons are always started. + # + bgpd=yes + ospfd=no + ospf6d=no + ripd=no + ripngd=no + isisd=no + pimd=no + ldpd=no + nhrpd=no + eigrpd=no + babeld=no + sharpd=no + pbrd=no + bfdd=yes + fabricd=no + vrrpd=no + + # + # If this option is set the /etc/init.d/frr script automatically loads + # the config via "vtysh -b" when the servers are started. + # Check /etc/pam.d/frr if you intend to use "vtysh"! + # + vtysh_enable=yes + zebra_options=" -A 127.0.0.1 -s 90000000" + bgpd_options=" -A 127.0.0.1" + ospfd_options=" -A 127.0.0.1" + ospf6d_options=" -A ::1" + ripd_options=" -A 127.0.0.1" + ripngd_options=" -A ::1" + isisd_options=" -A 127.0.0.1" + pimd_options=" -A 127.0.0.1" + ldpd_options=" -A 127.0.0.1" + nhrpd_options=" -A 127.0.0.1" + eigrpd_options=" -A 127.0.0.1" + babeld_options=" -A 127.0.0.1" + sharpd_options=" -A 127.0.0.1" + pbrd_options=" -A 127.0.0.1" + staticd_options="-A 127.0.0.1" + bfdd_options=" -A 127.0.0.1" + fabricd_options="-A 127.0.0.1" + vrrpd_options=" -A 127.0.0.1" + + # configuration profile + # + #frr_profile="traditional" + #frr_profile="datacenter" + + # + # This is the maximum number of FD's that will be available. + # Upon startup this is read by the control files and ulimit + # is called. Uncomment and use a reasonable value for your + # setup if you are expecting a large number of peers in + # say BGP. + #MAX_FDS=1024 + + # The list of daemons to watch is automatically generated by the init script. + #watchfrr_options="" + + # for debugging purposes, you can specify a "wrap" command to start instead + # of starting the daemon directly, e.g. to use valgrind on ospfd: + # ospfd_wrap="/usr/bin/valgrind" + # or you can use "all_wrap" for all daemons, e.g. to use perf record: + # all_wrap="/usr/bin/perf record --call-graph -" + # the normal daemon command is added to this at the end. + vtysh.conf: |+ + service integrated-vtysh-config + frr.conf: |+ + ! This file gets overriden the first time the speaker renders a config. + ! So anything configured here is only temporary. + frr version 8.0 + frr defaults traditional + hostname Router + line vty + log file /etc/frr/frr.log informational +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ template "frrk8s.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "frrk8s.labels" . | nindent 4 }} + app.kubernetes.io/component: frr-k8s + {{- range $key, $value := .Values.frrk8s.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} +spec: + {{- if .Values.frrk8s.updateStrategy }} + updateStrategy: {{- toYaml .Values.frrk8s.updateStrategy | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "frrk8s.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: frr-k8s + template: + metadata: + labels: + {{- include "frrk8s.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: frr-k8s + {{- range $key, $value := .Values.frrk8s.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + spec: + {{- if .Values.frrk8s.runtimeClassName }} + runtimeClassName: {{ .Values.frrk8s.runtimeClassName }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "frrk8s.serviceAccountName" . }} + terminationGracePeriodSeconds: 0 + hostNetwork: true + volumes: + - name: frr-sockets + emptyDir: {} + - name: frr-startup + configMap: + name: {{ template "frrk8s.fullname" . }}-frr-startup + - name: frr-conf + emptyDir: {} + - name: reloader + emptyDir: {} + - name: metrics + emptyDir: {} + {{- if .Values.prometheus.metricsTLSSecret }} + - name: metrics-certs + secret: + secretName: {{ .Values.prometheus.metricsTLSSecret }} + {{- end }} + initContainers: + # Copies the initial config files with the right permissions to the shared volume. + - name: cp-frr-files + image: {{ .Values.frrk8s.frr.image.repository }}:{{ .Values.frrk8s.frr.image.tag | default .Chart.AppVersion }} + securityContext: + runAsUser: 100 + runAsGroup: 101 + command: ["/bin/sh", "-c", "cp -rLf /tmp/frr/* /etc/frr/"] + volumeMounts: + - name: frr-startup + mountPath: /tmp/frr + - name: frr-conf + mountPath: /etc/frr + # Copies the reloader to the shared volume between the speaker and reloader. + - name: cp-reloader + image: {{ .Values.frrk8s.image.repository }}:{{ .Values.frrk8s.image.tag | default .Chart.AppVersion }} + command: ["/bin/sh", "-c", "cp -f /frr-reloader.sh /etc/frr_reloader/"] + volumeMounts: + - name: reloader + mountPath: /etc/frr_reloader + # Copies the metrics exporter + - name: cp-metrics + image: {{ .Values.frrk8s.image.repository }}:{{ .Values.frrk8s.image.tag | default .Chart.AppVersion }} + command: ["/bin/sh", "-c", "cp -f /frr-metrics /etc/frr_metrics/"] + volumeMounts: + - name: metrics + mountPath: /etc/frr_metrics + shareProcessNamespace: true + containers: + - name: controller + image: {{ .Values.frrk8s.image.repository }}:{{ .Values.frrk8s.image.tag | default .Chart.AppVersion }} + {{- if .Values.frrk8s.image.pullPolicy }} + imagePullPolicy: {{ .Values.frrk8s.image.pullPolicy }} + {{- end }} + command: + - /frr-k8s + args: + - "--node-name=$(NODE_NAME)" + - "--namespace=$(NAMESPACE)" + - "--metrics-bind-address={{.Values.prometheus.metricsBindAddress}}:{{ .Values.prometheus.metricsPort }}" + {{- with .Values.frrk8s.logLevel }} + - --log-level={{ . }} + {{- end }} + - --health-probe-bind-address={{.Values.prometheus.metricsBindAddress}}:{{ .Values.frrk8s.healthPort }} + {{- if .Values.frrk8s.alwaysBlock }} + - --always-block={{ .Values.frrk8s.alwaysBlock }} + {{- end }} + env: + - name: FRR_CONFIG_FILE + value: /etc/frr_reloader/frr.conf + - name: FRR_RELOADER_PID_FILE + value: /etc/frr_reloader/reloader.pid + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + ports: + - containerPort: {{ .Values.prometheus.metricsPort }} + name: monitoring + {{- if .Values.frrk8s.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /healthz + port: {{ .Values.frrk8s.healthPort }} + host: {{ .Values.prometheus.metricsBindAddress }} + initialDelaySeconds: {{ .Values.frrk8s.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.frrk8s.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.frrk8s.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.frrk8s.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.frrk8s.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.frrk8s.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: /healthz + port: {{ .Values.frrk8s.healthPort }} + host: {{ .Values.prometheus.metricsBindAddress }} + initialDelaySeconds: {{ .Values.frrk8s.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.frrk8s.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.frrk8s.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.frrk8s.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.frrk8s.readinessProbe.failureThreshold }} + {{- end }} + {{- with .Values.frrk8s.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + add: + - NET_RAW + volumeMounts: + - name: reloader + mountPath: /etc/frr_reloader + - name: frr + securityContext: + capabilities: + add: + - NET_ADMIN + - NET_RAW + - SYS_ADMIN + - NET_BIND_SERVICE + image: {{ .Values.frrk8s.frr.image.repository }}:{{ .Values.frrk8s.frr.image.tag | default .Chart.AppVersion }} + {{- if .Values.frrk8s.frr.image.pullPolicy }} + imagePullPolicy: {{ .Values.frrk8s.frr.image.pullPolicy }} + {{- end }} + env: + - name: TINI_SUBREAPER + value: "true" + volumeMounts: + - name: frr-sockets + mountPath: /var/run/frr + - name: frr-conf + mountPath: /etc/frr + # The command is FRR's default entrypoint & waiting for the log file to appear and tailing it. + # If the log file isn't created in 60 seconds the tail fails and the container is restarted. + # This workaround is needed to have the frr logs as part of kubectl logs -c frr < controller_pod_name >. + command: + - /bin/sh + - -c + - | + /sbin/tini -- /usr/lib/frr/docker-start & + attempts=0 + until [[ -f /etc/frr/frr.log || $attempts -eq 60 ]]; do + sleep 1 + attempts=$(( $attempts + 1 )) + done + tail -f /etc/frr/frr.log + {{- with .Values.frrk8s.frr.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.frrk8s.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /livez + port: {{ .Values.frrk8s.frr.metricsPort }} + host: {{ .Values.frrk8s.frr.metricsBindAddress }} + periodSeconds: {{ .Values.frrk8s.livenessProbe.periodSeconds }} + failureThreshold: {{ .Values.frrk8s.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.frrk8s.startupProbe.enabled }} + startupProbe: + httpGet: + path: /livez + port: {{ .Values.frrk8s.frr.metricsPort }} + host: {{ .Values.frrk8s.frr.metricsBindAddress }} + failureThreshold: {{ .Values.frrk8s.startupProbe.failureThreshold }} + periodSeconds: {{ .Values.frrk8s.startupProbe.periodSeconds }} + {{- end }} + - name: reloader + image: {{ .Values.frrk8s.frr.image.repository }}:{{ .Values.frrk8s.frr.image.tag | default .Chart.AppVersion }} + {{- if .Values.frrk8s.frr.image.pullPolicy }} + imagePullPolicy: {{ .Values.frrk8s.frr.image.pullPolicy }} + {{- end }} + command: ["/etc/frr_reloader/frr-reloader.sh"] + volumeMounts: + - name: frr-sockets + mountPath: /var/run/frr + - name: frr-conf + mountPath: /etc/frr + - name: reloader + mountPath: /etc/frr_reloader + {{- with .Values.frrk8s.reloader.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: frr-metrics + image: {{ .Values.frrk8s.frr.image.repository }}:{{ .Values.frrk8s.frr.image.tag | default .Chart.AppVersion }} + command: ["/etc/frr_metrics/frr-metrics"] + args: + - --metrics-port={{ .Values.frrk8s.frr.metricsPort }} + - --metrics-bind-address={{ .Values.frrk8s.frr.metricsBindAddress }} + ports: + - containerPort: {{ .Values.frrk8s.frr.metricsPort }} + name: monitoring + volumeMounts: + - name: frr-sockets + mountPath: /var/run/frr + - name: frr-conf + mountPath: /etc/frr + - name: metrics + mountPath: /etc/frr_metrics + {{- with .Values.frrk8s.frrMetrics.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: kube-rbac-proxy + image: {{ .Values.prometheus.rbacProxy.repository }}:{{ .Values.prometheus.rbacProxy.tag }} + imagePullPolicy: {{ .Values.prometheus.rbacProxy.pullPolicy }} + args: + - --logtostderr + - --secure-listen-address=:{{ .Values.prometheus.secureMetricsPort }} + - --upstream=http://{{.Values.prometheus.metricsBindAddress}}:{{ .Values.prometheus.metricsPort }}/ + - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + {{- if .Values.prometheus.metricsTLSSecret }} + - --tls-private-key-file=/etc/metrics/tls.key + - --tls-cert-file=/etc/metrics/tls.crt + {{- end }} + ports: + - containerPort: {{ .Values.prometheus.secureMetricsPort }} + name: metricshttps + resources: + requests: + cpu: 10m + memory: 20Mi + terminationMessagePolicy: FallbackToLogsOnError + {{- if .Values.prometheus.metricsTLSSecret }} + volumeMounts: + - name: metrics-certs + mountPath: /etc/metrics + readOnly: true + {{- end }} + - name: kube-rbac-proxy-frr + image: {{ .Values.prometheus.rbacProxy.repository }}:{{ .Values.prometheus.rbacProxy.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.prometheus.rbacProxy.pullPolicy }} + args: + - --logtostderr + - --secure-listen-address=:{{ .Values.frrk8s.frr.secureMetricsPort }} + - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + - --upstream=http://{{ .Values.frrk8s.frr.metricsBindAddress }}:{{ .Values.frrk8s.frr.metricsPort }}/ + {{- if .Values.prometheus.metricsTLSSecret }} + - --tls-private-key-file=/etc/metrics/tls.key + - --tls-cert-file=/etc/metrics/tls.crt + {{- end }} + ports: + - containerPort: {{ .Values.frrk8s.frr.secureMetricsPort }} + name: metricshttps + resources: + requests: + cpu: 10m + memory: 20Mi + terminationMessagePolicy: FallbackToLogsOnError + {{- if .Values.prometheus.metricsTLSSecret }} + volumeMounts: + - name: metrics-certs + mountPath: /etc/metrics + readOnly: true + {{- end }} + nodeSelector: + "kubernetes.io/os": linux + {{- with .Values.frrk8s.nodeSelector }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.frrk8s.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if or .Values.frrk8s.tolerateMaster .Values.frrk8s.tolerations }} + tolerations: + {{- if .Values.frrk8s.tolerateMaster }} + - key: node-role.kubernetes.io/master + effect: NoSchedule + operator: Exists + - key: node-role.kubernetes.io/control-plane + effect: NoSchedule + operator: Exists + {{- end }} + {{- with .Values.frrk8s.tolerations }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- end }} + {{- with .Values.frrk8s.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} diff --git a/metallb-chart/charts/frr-k8s/templates/rbac.yaml b/metallb-chart/charts/frr-k8s/templates/rbac.yaml new file mode 100644 index 0000000..5c0b9d6 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/templates/rbac.yaml @@ -0,0 +1,73 @@ +{{- if .Values.rbac.create -}} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "frrk8s.fullname" . }}-controller + labels: {{- include "frrk8s.labels" . | nindent 4 }} +rules: +- apiGroups: ["frrk8s.metallb.io"] + resources: ["frrconfigurations"] + verbs: ["get", "list", "watch"] +- apiGroups: ["frrk8s.metallb.io"] + resources: ["frrnodestates"] + verbs: ["get", "list", "watch", "create", "delete", "patch", "update"] +- apiGroups: ["frrk8s.metallb.io"] + resources: ["frrnodestates/status"] + verbs: ["get", "patch", "update"] +- apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch"] +- apiGroups: ["authentication.k8s.io"] + resources: ["tokenreviews"] + verbs: ["create"] +- apiGroups: ["authorization.k8s.io"] + resources: ["subjectaccessreviews"] + verbs: ["create"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations"] + verbs: ["get", "list", "watch"] +- apiGroups: ["admissionregistration.k8s.io"] + resourceNames: ["frr-k8s-validating-webhook-configuration"] + resources: ["validatingwebhookconfigurations"] + verbs: ["update"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "frrk8s.fullname" . }}-controller + labels: {{- include "frrk8s.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "frrk8s.fullname" . }}-controller +subjects: +- kind: ServiceAccount + name: {{ include "frrk8s.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "frrk8s.fullname" . }}-controller + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "frrk8s.labels" . | nindent 4 }} +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch","update"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "frrk8s.fullname" . }}-controller + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "frrk8s.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "frrk8s.fullname" . }}-controller +subjects: +- kind: ServiceAccount + name: {{ include "frrk8s.serviceAccountName" . }} +{{ end -}} diff --git a/metallb-chart/charts/frr-k8s/templates/service-accounts.yaml b/metallb-chart/charts/frr-k8s/templates/service-accounts.yaml new file mode 100644 index 0000000..c3d7423 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/templates/service-accounts.yaml @@ -0,0 +1,16 @@ +{{- if .Values.frrk8s.serviceAccount.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "frrk8s.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "frrk8s.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.frrk8s.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + diff --git a/metallb-chart/charts/frr-k8s/templates/service-monitor.yaml b/metallb-chart/charts/frr-k8s/templates/service-monitor.yaml new file mode 100644 index 0000000..323c442 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/templates/service-monitor.yaml @@ -0,0 +1,128 @@ +{{- if .Values.prometheus.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "frrk8s.fullname" . }}-frr-k8s-monitor + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "frrk8s.labels" . | nindent 4 }} + app.kubernetes.io/component: frr-k8s + {{- if .Values.prometheus.serviceMonitor.additionalLabels }} +{{ toYaml .Values.prometheus.serviceMonitor.additionalLabels | indent 4 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.annotations }} + annotations: +{{ toYaml .Values.prometheus.serviceMonitor.annotations | indent 4 }} + {{- end }} +spec: + endpoints: + - port: "metricshttps" + honorLabels: true + {{- if .Values.prometheus.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml .Values.prometheus.serviceMonitor.metricRelabelings | nindent 8 }} + {{- end -}} + {{- if .Values.prometheus.serviceMonitor.relabelings }} + relabelings: + {{- toYaml .Values.prometheus.serviceMonitor.relabelings | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.interval }} + interval: {{ .Values.prometheus.serviceMonitor.interval }} + {{- end -}} +{{ if .Values.prometheus.secureMetricsPort }} + bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token" + scheme: "https" +{{- if .Values.prometheus.serviceMonitor.tlsConfig }} + tlsConfig: +{{ toYaml .Values.prometheus.serviceMonitor.tlsConfig | indent 8 }} +{{- end }} +{{ end }} +{{ if .Values.frrk8s.frr.secureMetricsPort }} + - port: "frrmetricshttps" + honorLabels: true + {{- if .Values.prometheus.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml .Values.prometheus.serviceMonitor.metricRelabelings | nindent 8 }} + {{- end -}} + {{- if .Values.prometheus.serviceMonitor.relabelings }} + relabelings: + {{- toYaml .Values.prometheus.serviceMonitor.relabelings | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.interval }} + interval: {{ .Values.prometheus.serviceMonitor.interval }} + {{- end }} + bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token" + scheme: "https" +{{- if .Values.prometheus.serviceMonitor.tlsConfig }} + tlsConfig: +{{ toYaml .Values.prometheus.serviceMonitor.tlsConfig | indent 8 }} +{{- end }} +{{- end }} + jobLabel: {{ .Values.prometheus.serviceMonitor.jobLabel | quote }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + name: {{ template "frrk8s.fullname" . }}-frr-k8s-monitor-service +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/scrape: "true" + {{- if .Values.prometheus.serviceMonitor.annotations }} +{{ toYaml .Values.prometheus.serviceMonitor.annotations | indent 4 }} + {{- end }} + labels: + name: {{ template "frrk8s.fullname" . }}-frr-k8s-monitor-service + name: {{ template "frrk8s.fullname" . }}-frr-k8s-monitor-service + namespace: {{ .Release.Namespace | quote }} +spec: + selector: + {{- include "frrk8s.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: frr-k8s + clusterIP: None + ports: + - name: "metricshttps" + port: {{ .Values.prometheus.secureMetricsPort }} + targetPort: {{ .Values.prometheus.secureMetricsPort }} + - name: frrmetricshttps + port: {{ .Values.frrk8s.frr.secureMetricsPort }} + targetPort: {{ .Values.frrk8s.frr.secureMetricsPort }} + sessionAffinity: None + type: ClusterIP +--- +{{- if .Values.prometheus.rbacPrometheus }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "frrk8s.fullname" . }}-prometheus + namespace: {{ .Release.Namespace | quote }} +rules: + - apiGroups: + - "" + resources: + - pods + - services + - endpoints + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "frrk8s.fullname" . }}-prometheus + namespace: {{ .Release.Namespace | quote }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "frrk8s.fullname" . }}-prometheus +subjects: + - kind: ServiceAccount + name: {{ required ".Values.prometheus.serviceAccount must be defined when .Values.prometheus.serviceMonitor.enabled == true" .Values.prometheus.serviceAccount }} + namespace: {{ required ".Values.prometheus.namespace must be defined when .Values.prometheus.serviceMonitor.enabled == true" .Values.prometheus.namespace }} +{{- end }} +{{- end }} diff --git a/metallb-chart/charts/frr-k8s/templates/webhooks.yaml b/metallb-chart/charts/frr-k8s/templates/webhooks.yaml new file mode 100644 index 0000000..a84b3b6 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/templates/webhooks.yaml @@ -0,0 +1,163 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "frrk8s.fullname" . }}-webhook-server + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "frrk8s.labels" . | nindent 4 }} + app.kubernetes.io/component: frr-k8s-webhook-server + {{- range $key, $value := .Values.frrk8s.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} +spec: + selector: + matchLabels: + app.kubernetes.io/component: frr-k8s-webhook-server + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: frr-k8s-webhook-server + labels: + app.kubernetes.io/component: frr-k8s-webhook-server + spec: + {{- if .Values.frrk8s.runtimeClassName }} + runtimeClassName: {{ .Values.frrk8s.runtimeClassName }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.podSecurityContext }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- end }} + containers: + - command: + - /frr-k8s + args: + {{- with .Values.frrk8s.logLevel }} + - --log-level={{ . }} + {{- end }} + - "--webhook-mode=onlywebhook" + {{- if .Values.frrk8s.disableCertRotation }} + - "--disable-cert-rotation=true" + {{- end }} + {{- if .Values.frrk8s.restartOnRotatorSecretRefresh }} + - "--restart-on-rotator-secret-refresh=true" + {{- end }} + - "--namespace=$(NAMESPACE)" + - --health-probe-bind-address=:8081 + env: + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: {{ .Values.frrk8s.image.repository }}:{{ .Values.frrk8s.image.tag | default .Chart.AppVersion }} + {{- if .Values.frrk8s.image.pullPolicy }} + imagePullPolicy: {{ .Values.frrk8s.image.pullPolicy }} + {{- end }} + name: frr-k8s-webhook-server + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + {{- if .Values.frrk8s.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: {{ .Values.frrk8s.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.frrk8s.livenessProbe.periodSeconds }} + failureThreshold: {{ .Values.frrk8s.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.frrk8s.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: {{ .Values.frrk8s.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.frrk8s.readinessProbe.periodSeconds }} + failureThreshold: {{ .Values.frrk8s.readinessProbe.failureThreshold }} + {{- end }} + {{- with .Values.frrk8s.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + volumeMounts: + - name: cert + mountPath: /tmp/k8s-webhook-server/serving-certs + readOnly: true + {{- with .Values.frrk8s.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if or .Values.frrk8s.tolerateMaster .Values.frrk8s.tolerations }} + tolerations: + {{- if .Values.frrk8s.tolerateMaster }} + - key: node-role.kubernetes.io/master + effect: NoSchedule + operator: Exists + - key: node-role.kubernetes.io/control-plane + effect: NoSchedule + operator: Exists + {{- end }} + {{- with .Values.frrk8s.tolerations }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- end }} + {{- with .Values.frrk8s.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: frr-k8s-webhook-server-cert + serviceAccountName: {{ template "frrk8s.serviceAccountName" . }} + terminationGracePeriodSeconds: 10 +--- +apiVersion: v1 +kind: Secret +metadata: + name: frr-k8s-webhook-server-cert + namespace: {{ .Release.Namespace | quote }} +--- +apiVersion: v1 +kind: Service +metadata: + name: frr-k8s-webhook-service + namespace: {{ .Release.Namespace | quote }} +spec: + ports: + - port: 443 + targetPort: 9443 + selector: + app.kubernetes.io/component: frr-k8s-webhook-server +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: frr-k8s-validating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: frr-k8s-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-frrk8s-metallb-io-v1beta1-frrconfiguration + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: frrconfigurationsvalidationwebhook.metallb.io + rules: + - apiGroups: + - frrk8s.metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - frrconfigurations + sideEffects: None diff --git a/metallb-chart/charts/frr-k8s/values.schema.json b/metallb-chart/charts/frr-k8s/values.schema.json new file mode 100644 index 0000000..67ec727 --- /dev/null +++ b/metallb-chart/charts/frr-k8s/values.schema.json @@ -0,0 +1,387 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema#", + "title": "Values", + "type": "object", + "definitions": { + "prometheusAlert": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "required": [ + "enabled" + ] + }, + "probe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "failureThreshold": { + "type": "integer" + }, + "initialDelaySeconds": { + "type": "integer" + }, + "periodSeconds": { + "type": "integer" + }, + "successThreshold": { + "type": "integer" + }, + "timeoutSeconds": { + "type": "integer" + } + }, + "required": [ + "failureThreshold", + "initialDelaySeconds", + "periodSeconds", + "successThreshold", + "timeoutSeconds" + ] + }, + "component": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "logLevel": { + "type": "string", + "enum": [ + "all", + "debug", + "info", + "warn", + "error", + "none" + ] + }, + "image": { + "type": "object", + "properties": { + "repository": { + "type": "string" + }, + "tag": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "pullPolicy": { + "anyOf": [ + { + "type": "null" + }, + { + "type": "string", + "enum": [ + "Always", + "IfNotPresent", + "Never" + ] + } + ] + } + } + }, + "serviceAccount": { + "type": "object", + "properties": { + "create": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "annotations": { + "type": "object" + } + } + }, + "resources": { + "type": "object" + }, + "nodeSelector": { + "type": "object" + }, + "tolerations": { + "type": "array", + "items": { + "type": "object" + } + }, + "priorityClassName": { + "type": "string" + }, + "runtimeClassName": { + "type": "string" + }, + "affinity": { + "type": "object" + }, + "podAnnotations": { + "type": "object" + }, + "livenessProbe": { + "$ref": "#/definitions/probe" + }, + "readinessProbe": { + "$ref": "#/definitions/probe" + } + }, + "required": [ + "image", + "serviceAccount" + ] + } + }, + "properties": { + "imagePullSecrets": { + "description": "Secrets used for pulling images", + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": [ + "name" + ], + "additionalProperties": false + } + }, + "nameOverride": { + "description": "Override chart name", + "type": "string" + }, + "fullNameOverride": { + "description": "Override fully qualified app name", + "type": "string" + }, + "rbac": { + "description": "RBAC configuration", + "type": "object", + "properties": { + "create": { + "description": "Enable RBAC", + "type": "boolean" + } + } + }, + "prometheus": { + "description": "Prometheus monitoring config", + "type": "object", + "properties": { + "scrapeAnnotations": { + "type": "boolean" + }, + "metricsPort": { + "type": "integer" + }, + "secureMetricsPort": { + "type": "integer" + }, + "rbacPrometheus": { + "type": "boolean" + }, + "serviceAccount": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "rbacProxy": { + "description": "kube-rbac-proxy configuration", + "type": "object", + "properties": { + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "serviceMonitor": { + "description": "Prometheus Operator ServiceMonitors", + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "jobLabel": { + "type": "string" + }, + "interval": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "metricRelabelings": { + "type": "array", + "items": { + "type": "object" + } + }, + "relabelings": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + }, + "frrk8s": { + "allOf": [ + { + "$ref": "#/definitions/component" + }, + { + "description": "FRR-K8s controller", + "type": "object", + "properties": { + "tolerateMaster": { + "type": "boolean" + }, + "updateStrategy": { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "runtimeClassName": { + "type": "string" + }, + "secretName": { + "type": "string" + }, + "frr": { + "description": "The FRR properties in the controller", + "type": "object", + "properties": { + "image": { + "$ref": "#/definitions/component/properties/image" + }, + "metricsPort": { + "type": "integer" + }, + "secureMetricsPort": { + "type": "integer" + }, + "resources:": { + "type": "object" + } + }, + "required": [ + "enabled" + ] + }, + "command": { + "type": "string" + }, + "reloader": { + "type": "object", + "properties": { + "resources": { + "type": "object" + } + } + }, + "frrMetrics": { + "type": "object", + "properties": { + "resources": { + "type": "object" + } + } + } + }, + "required": [ + "tolerateMaster" + ] + } + ] + }, + "crds": { + "description": "CRD configuration", + "type": "object", + "properties": { + "enabled": { + "description": "Enable CRDs", + "type": "boolean" + }, + "validationFailurePolicy": { + "description": "Failure policy to use with validating webhooks", + "type": "string", + "enum": [ + "Ignore", + "Fail" + ] + } + } + } + }, + "frrk8s": { + "allOf": [ + { + "$ref": "#/definitions/component" + }, + { + "description": "FRRk8s Controller", + "type": "object", + "properties": { + "strategy": { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + }, + "command": { + "type": "string" + }, + "webhookMode": { + "type": "string" + } + } + } + ] + } + }, + "required": [ + "frrk8s" + ] +} \ No newline at end of file diff --git a/metallb-chart/charts/frr-k8s/values.yaml b/metallb-chart/charts/frr-k8s/values.yaml new file mode 100644 index 0000000..87731fe --- /dev/null +++ b/metallb-chart/charts/frr-k8s/values.yaml @@ -0,0 +1,176 @@ +# Default values for frr-k8s. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +nameOverride: "" +fullnameOverride: "" + +rbac: + # create specifies whether to install and use RBAC rules. + create: true + +podSecurityContext: + seccompProfile: + type: RuntimeDefault + +prometheus: + # scrape annotations specifies whether to add Prometheus metric + # auto-collection annotations to pods. See + # https://github.com/prometheus/prometheus/blob/release-2.1/documentation/examples/prometheus-kubernetes.yml + # for a corresponding Prometheus configuration. Alternatively, you + # may want to use the Prometheus Operator + # (https://github.com/coreos/prometheus-operator) for more powerful + # monitoring configuration. If you use the Prometheus operator, this + # can be left at false. + scrapeAnnotations: false + + # bind addr frr-k8s will use for metrics + metricsBindAddress: 127.0.0.1 + + # port frr-k8s will listen on for metrics + metricsPort: 7572 + + # if set, enables rbac proxy on frr-k8s to expose + # the metrics via tls. + secureMetricsPort: 9140 + + # the name of the secret to be mounted in the frr-k8s pod + # to expose the metrics securely. If not present, a self signed + # certificate to be used. + metricsTLSSecret: "" + + # prometheus doens't have the permission to scrape all namespaces so we give it permission to scrape metallb's one + rbacPrometheus: false + + # the service account used by prometheus + # required when " .Values.prometheus.rbacPrometheus == true " and " prometheus.serviceMonitor.enabled=true " + serviceAccount: "" + + # the namespace where prometheus is deployed + # required when " .Values.prometheus.rbacPrometheus == true " and " prometheus.serviceMonitor.enabled=true " + namespace: "" + + # the image to be used for the kuberbacproxy container + rbacProxy: + repository: "registry.opensuse.org/isv/suse/edge/metallb/images/kube-rbac-proxy" + tag: "v0.18.0" + pullPolicy: IfNotPresent + + # Prometheus Operator ServiceMonitors. + serviceMonitor: + # enable support for Prometheus Operator + enabled: false + + additionalLabels: {} + # optional additional annotations for the controller serviceMonitor + annotations: {} + # optional tls configuration for the controller serviceMonitor, in case + # secure metrics are enabled. + tlsConfig: + insecureSkipVerify: true + + # Job label for scrape target + jobLabel: "app.kubernetes.io/name" + + # Scrape interval. If not set, the Prometheus default scrape interval is used. + interval: + + # metric relabel configs to apply to samples before ingestion. + metricRelabelings: [] + # - action: keep + # regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+' + # sourceLabels: [__name__] + + # relabel configs to apply to samples before ingestion. + relabelings: [] + # - sourceLabels: [__meta_kubernetes_pod_node_name] + # separator: ; + # regex: ^(.*)$ + # target_label: nodename + # replacement: $1 + # action: replace + +# controller contains configuration specific to the FRRK8s controller +# daemonset. +frrk8s: + # -- Controller log level. Must be one of: `all`, `debug`, `info`, `warn`, `error` or `none` + logLevel: info + tolerateMaster: true + image: + repository: "registry.opensuse.org/isv/suse/edge/metallb/images/frr-k8s" + tag: "v0.0.14" + pullPolicy: IfNotPresent + ## @param controller.updateStrategy.type FRR-K8s controller daemonset strategy type + ## ref: https://kubernetes.io/docs/tasks/manage-daemon/update-daemon-set/ + ## + updateStrategy: + ## StrategyType + ## Can be set to RollingUpdate or OnDelete + ## + type: RollingUpdate + serviceAccount: + # Specifies whether a ServiceAccount should be created + create: true + # The name of the ServiceAccount to use. If not set and create is + # true, a name is generated using the fullname template + name: "" + annotations: {} + ## Defines a secret name for the controller to generate a memberlist encryption secret + ## By default secretName: {{ "metallb.fullname" }}-memberlist + ## + # secretName: + resources: {} + # limits: + # cpu: 100m + # memory: 100Mi + nodeSelector: {} + tolerations: [] + priorityClassName: "" + affinity: {} + ## Selects which runtime class will be used by the pod. + runtimeClassName: "" + podAnnotations: {} + labels: + app: frr-k8s + healthPort: 8081 + livenessProbe: + enabled: true + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + readinessProbe: + enabled: true + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + startupProbe: + enabled: true + failureThreshold: 30 + periodSeconds: 5 + ## A comma separated list of cidrs we want always to block for incoming routes + alwaysBlock: "" + ## Specifies whether the cert rotator works as part of the webhook. + disableCertRotation: false + ## Specifies whether the pod restarts when the rotator refreshes the cert secret. + ## Enabling this proved useful for the webhook's stability when it is redeployed multiple times in succession. + restartOnRotatorSecretRefresh: false + # frr contains configuration specific to the FRR container, + frr: + image: + repository: "registry.opensuse.org/isv/suse/edge/metallb/images/frr" + tag: "8.4" + pullPolicy: IfNotPresent + metricsBindAddress: 127.0.0.1 + metricsPort: 7573 + resources: {} + secureMetricsPort: 9141 + reloader: + resources: {} + frrMetrics: + resources: {} +crds: + validationFailurePolicy: Fail diff --git a/metallb-chart/charts/metallb-crds/.helmignore b/metallb-chart/charts/metallb-crds/.helmignore new file mode 100644 index 0000000..1b9a9cc --- /dev/null +++ b/metallb-chart/charts/metallb-crds/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/metallb-chart/charts/metallb-crds/Chart.yaml b/metallb-chart/charts/metallb-crds/Chart.yaml new file mode 100644 index 0000000..6d070fc --- /dev/null +++ b/metallb-chart/charts/metallb-crds/Chart.yaml @@ -0,0 +1,10 @@ +apiVersion: v2 +appVersion: v0.14.9 +description: MetalLB CRDs +home: https://metallb.universe.tf +icon: https://metallb.universe.tf/images/logo/metallb-white.png +name: metallb-crds +sources: +- https://github.com/metallb/metallb +type: application +version: 0.14.8 diff --git a/metallb-chart/charts/metallb-crds/README.md b/metallb-chart/charts/metallb-crds/README.md new file mode 100644 index 0000000..58cf71b --- /dev/null +++ b/metallb-chart/charts/metallb-crds/README.md @@ -0,0 +1,11 @@ +# crds + +![Version: 0.14.3](https://img.shields.io/badge/Version-0.14.3-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.14.3](https://img.shields.io/badge/AppVersion-v0.14.3-informational?style=flat-square) + +MetalLB CRDs + +**Homepage:** + +## Source Code + +* diff --git a/metallb-chart/charts/metallb-crds/templates/crds.yaml b/metallb-chart/charts/metallb-crds/templates/crds.yaml new file mode 100644 index 0000000..9341bb4 --- /dev/null +++ b/metallb-chart/charts/metallb-crds/templates/crds.yaml @@ -0,0 +1,1205 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: bfdprofiles.metallb.io +spec: + group: metallb.io + names: + kind: BFDProfile + listKind: BFDProfileList + plural: bfdprofiles + singular: bfdprofile + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.passiveMode + name: Passive Mode + type: boolean + - jsonPath: .spec.transmitInterval + name: Transmit Interval + type: integer + - jsonPath: .spec.receiveInterval + name: Receive Interval + type: integer + - jsonPath: .spec.detectMultiplier + name: Multiplier + type: integer + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + BFDProfile represents the settings of the bfd session that can be + optionally associated with a BGP session. + 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: BFDProfileSpec defines the desired state of BFDProfile. + properties: + detectMultiplier: + description: |- + Configures the detection multiplier to determine + packet loss. The remote transmission interval will be multiplied + by this value to determine the connection loss detection timer. + format: int32 + maximum: 255 + minimum: 2 + type: integer + echoInterval: + description: |- + Configures the minimal echo receive transmission + interval that this system is capable of handling in milliseconds. + Defaults to 50ms + format: int32 + maximum: 60000 + minimum: 10 + type: integer + echoMode: + description: |- + Enables or disables the echo transmission mode. + This mode is disabled by default, and not supported on multi + hops setups. + type: boolean + minimumTtl: + description: |- + For multi hop sessions only: configure the minimum + expected TTL for an incoming BFD control packet. + format: int32 + maximum: 254 + minimum: 1 + type: integer + passiveMode: + description: |- + Mark session as passive: a passive session will not + attempt to start the connection and will wait for control packets + from peer before it begins replying. + type: boolean + receiveInterval: + description: |- + The minimum interval that this system is capable of + receiving control packets in milliseconds. + Defaults to 300ms. + format: int32 + maximum: 60000 + minimum: 10 + type: integer + transmitInterval: + description: |- + The minimum transmission interval (less jitter) + that this system wants to use to send BFD control packets in + milliseconds. Defaults to 300ms + format: int32 + maximum: 60000 + minimum: 10 + type: integer + type: object + status: + description: BFDProfileStatus defines the observed state of BFDProfile. + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: bgpadvertisements.metallb.io +spec: + group: metallb.io + names: + kind: BGPAdvertisement + listKind: BGPAdvertisementList + plural: bgpadvertisements + singular: bgpadvertisement + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.ipAddressPools + name: IPAddressPools + type: string + - jsonPath: .spec.ipAddressPoolSelectors + name: IPAddressPool Selectors + type: string + - jsonPath: .spec.peers + name: Peers + type: string + - jsonPath: .spec.nodeSelectors + name: Node Selectors + priority: 10 + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + BGPAdvertisement allows to advertise the IPs coming + from the selected IPAddressPools via BGP, setting the parameters of the + BGP Advertisement. + 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: BGPAdvertisementSpec defines the desired state of BGPAdvertisement. + properties: + aggregationLength: + default: 32 + description: The aggregation-length advertisement option lets you “roll up” the /32s into a larger prefix. Defaults to 32. Works for IPv4 addresses. + format: int32 + minimum: 1 + type: integer + aggregationLengthV6: + default: 128 + description: The aggregation-length advertisement option lets you “roll up” the /128s into a larger prefix. Defaults to 128. Works for IPv6 addresses. + format: int32 + type: integer + communities: + description: |- + The BGP communities to be associated with the announcement. Each item can be a standard community of the + form 1234:1234, a large community of the form large:1234:1234:1234 or the name of an alias defined in the + Community CRD. + items: + type: string + type: array + ipAddressPoolSelectors: + description: |- + A selector for the IPAddressPools which would get advertised via this advertisement. + If no IPAddressPool is selected by this or by the list, the advertisement is applied to all the IPAddressPools. + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + type: array + ipAddressPools: + description: The list of IPAddressPools to advertise via this advertisement, selected by name. + items: + type: string + type: array + localPref: + description: |- + The BGP LOCAL_PREF attribute which is used by BGP best path algorithm, + Path with higher localpref is preferred over one with lower localpref. + format: int32 + type: integer + nodeSelectors: + description: NodeSelectors allows to limit the nodes to announce as next hops for the LoadBalancer IP. When empty, all the nodes having are announced as next hops. + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + type: array + peers: + description: |- + Peers limits the bgppeer to advertise the ips of the selected pools to. + When empty, the loadbalancer IP is announced to all the BGPPeers configured. + items: + type: string + type: array + type: object + status: + description: BGPAdvertisementStatus defines the observed state of BGPAdvertisement. + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: bgppeers.metallb.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGWlRDQ0EwMmdBd0lCQWdJVU5GRW1XcTM3MVpKdGkrMmlSQzk1WmpBV1MxZ3dEUVlKS29aSWh2Y05BUUVMDQpCUUF3UWpFTE1Ba0dBMVVFQmhNQ1dGZ3hGVEFUQmdOVkJBY01ERVJsWm1GMWJIUWdRMmwwZVRFY01Cb0dBMVVFDQpDZ3dUUkdWbVlYVnNkQ0JEYjIxd1lXNTVJRXgwWkRBZUZ3MHlNakEzTVRrd09UTXlNek5hRncweU1qQTRNVGd3DQpPVE15TXpOYU1FSXhDekFKQmdOVkJBWVRBbGhZTVJVd0V3WURWUVFIREF4RVpXWmhkV3gwSUVOcGRIa3hIREFhDQpCZ05WQkFvTUUwUmxabUYxYkhRZ1EyOXRjR0Z1ZVNCTWRHUXdnZ0lpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElDDQpEd0F3Z2dJS0FvSUNBUUNxVFpxMWZRcC9vYkdlenhES0o3OVB3Ny94azJwellualNzMlkzb1ZYSm5sRmM4YjVlDQpma2ZZQnY2bndscW1keW5PL2phWFBaQmRQSS82aFdOUDBkdVhadEtWU0NCUUpyZzEyOGNXb3F0MGNTN3pLb1VpDQpvcU1tQ0QvRXVBeFFNZjhRZDF2c1gvVllkZ0poVTZBRXJLZEpIaXpFOUJtUkNkTDBGMW1OVW55Rk82UnRtWFZUDQpidkxsTDVYeTc2R0FaQVBLOFB4aVlDa0NtbDdxN0VnTWNiOXlLWldCYmlxQ3VkTXE5TGJLNmdKNzF6YkZnSXV4DQo1L1pXK2JraTB2RlplWk9ZODUxb1psckFUNzJvMDI4NHNTWW9uN0pHZVZkY3NoUnh5R1VpSFpSTzdkaXZVTDVTDQpmM2JmSDFYbWY1ZDQzT0NWTWRuUUV2NWVaOG8zeWVLa3ZrbkZQUGVJMU9BbjdGbDlFRVNNR2dhOGFaSG1URSttDQpsLzlMSmdDYjBnQmtPT0M0WnV4bWh2aERKV1EzWnJCS3pMQlNUZXN0NWlLNVlwcXRWVVk2THRyRW9FelVTK1lsDQpwWndXY2VQWHlHeHM5ZURsR3lNVmQraW15Y3NTU1UvVno2Mmx6MnZCS21NTXBkYldDQWhud0RsRTVqU2dyMjRRDQp0eGNXLys2N3d5KzhuQlI3UXdqVTFITndVRjBzeERWdEwrZ1NHVERnSEVZSlhZelYvT05zMy94TkpoVFNPSkxNDQpoeXNVdyttaGdackdhbUdXcHVIVU1DUitvTWJzMTc1UkcrQjJnUFFHVytPTjJnUTRyOXN2b0ZBNHBBQm8xd1dLDQpRYjRhY3pmeVVscElBOVFoSmFsZEY3S3dPSHVlV3gwRUNrNXg0T2tvVDBvWVp0dzFiR0JjRGtaSmF3SURBUUFCDQpvMU13VVRBZEJnTlZIUTRFRmdRVW90UlNIUm9IWTEyRFZ4R0NCdEhpb1g2ZmVFQXdId1lEVlIwakJCZ3dGb0FVDQpvdFJTSFJvSFkxMkRWeEdDQnRIaW9YNmZlRUF3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFOQmdrcWhraUc5dzBCDQpBUXNGQUFPQ0FnRUFSbkpsWWRjMTFHd0VxWnh6RDF2R3BDR2pDN2VWTlQ3aVY1d3IybXlybHdPYi9aUWFEa0xYDQpvVStaOVVXT1VlSXJTdzUydDdmQUpvVVAwSm5iYkMveVIrU1lqUGhvUXNiVHduOTc2ZldBWTduM3FMOXhCd1Y0DQphek41OXNjeUp0dlhMeUtOL2N5ak1ReDRLajBIMFg0bWJ6bzVZNUtzWWtYVU0vOEFPdWZMcEd0S1NGVGgrSEFDDQpab1Q5YnZHS25adnNHd0tYZFF0Wnh0akhaUjVqK3U3ZGtQOTJBT051RFNabS8rWVV4b2tBK09JbzdSR3BwSHNXDQo1ZTdNY0FTVXRtb1FORXd6dVFoVkJaRWQ1OGtKYjUrV0VWbGNzanlXNnRTbzErZ25tTWNqR1BsMWgxR2hVbjV4DQpFY0lWRnBIWXM5YWo1NmpBSjk1MVQvZjhMaWxmTlVnanBLQ0c1bnl0SUt3emxhOHNtdGlPdm1UNEpYbXBwSkI2DQo4bmdHRVluVjUrUTYwWFJ2OEhSSGp1VG9CRHVhaERrVDA2R1JGODU1d09FR2V4bkZpMXZYWUxLVllWb1V2MXRKDQo4dVdUR1pwNllDSVJldlBqbzg5ZytWTlJSaVFYUThJd0dybXE5c0RoVTlqTjA0SjdVL1RvRDFpNHE3VnlsRUc5DQorV1VGNkNLaEdBeTJIaEhwVncyTGFoOS9lUzdZMUZ1YURrWmhPZG1laG1BOCtqdHNZamJadnR5Mm1SWlF0UUZzDQpUU1VUUjREbUR2bVVPRVRmeStpRHdzK2RkWXVNTnJGeVVYV2dkMnpBQU4ydVl1UHFGY2pRcFNPODFzVTJTU3R3DQoxVzAyeUtYOGJEYmZFdjBzbUh3UzliQnFlSGo5NEM1Mjg0YXpsdTBmaUdpTm1OUEM4ckJLRmhBPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ== + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /convert + conversionReviewVersions: + - v1beta1 + - v1beta2 + group: metallb.io + names: + kind: BGPPeer + listKind: BGPPeerList + plural: bgppeers + singular: bgppeer + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.peerAddress + name: Address + type: string + - jsonPath: .spec.peerASN + name: ASN + type: string + - jsonPath: .spec.bfdProfile + name: BFD Profile + type: string + - jsonPath: .spec.ebgpMultiHop + name: Multi Hops + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: BGPPeer is the Schema for the peers 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: BGPPeerSpec defines the desired state of Peer. + properties: + bfdProfile: + type: string + ebgpMultiHop: + description: EBGP peer is multi-hops away + type: boolean + holdTime: + description: Requested BGP hold time, per RFC4271. + type: string + keepaliveTime: + description: Requested BGP keepalive time, per RFC4271. + type: string + myASN: + description: AS number to use for the local end of the session. + format: int32 + maximum: 4294967295 + minimum: 0 + type: integer + nodeSelectors: + description: |- + Only connect to this peer on nodes that match one of these + selectors. + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + minItems: 1 + type: array + required: + - key + - operator + - values + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + type: array + password: + description: Authentication password for routers enforcing TCP MD5 authenticated sessions + type: string + peerASN: + description: AS number to expect from the remote end of the session. + format: int32 + maximum: 4294967295 + minimum: 0 + type: integer + peerAddress: + description: Address to dial when establishing the session. + type: string + peerPort: + description: Port to dial when establishing the session. + maximum: 16384 + minimum: 0 + type: integer + routerID: + description: BGP router ID to advertise to the peer + type: string + sourceAddress: + description: Source address to use when establishing the session. + type: string + required: + - myASN + - peerASN + - peerAddress + type: object + status: + description: BGPPeerStatus defines the observed state of Peer. + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.peerAddress + name: Address + type: string + - jsonPath: .spec.peerASN + name: ASN + type: string + - jsonPath: .spec.bfdProfile + name: BFD Profile + type: string + - jsonPath: .spec.ebgpMultiHop + name: Multi Hops + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: BGPPeer is the Schema for the peers 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: BGPPeerSpec defines the desired state of Peer. + properties: + bfdProfile: + description: The name of the BFD Profile to be used for the BFD session associated to the BGP session. If not set, the BFD session won't be set up. + type: string + connectTime: + description: Requested BGP connect time, controls how long BGP waits between connection attempts to a neighbor. + type: string + x-kubernetes-validations: + - message: connect time should be between 1 seconds to 65535 + rule: duration(self).getSeconds() >= 1 && duration(self).getSeconds() <= 65535 + - message: connect time should contain a whole number of seconds + rule: duration(self).getMilliseconds() % 1000 == 0 + disableMP: + default: false + description: To set if we want to disable MP BGP that will separate IPv4 and IPv6 route exchanges into distinct BGP sessions. + type: boolean + ebgpMultiHop: + description: To set if the BGPPeer is multi-hops away. Needed for FRR mode only. + type: boolean + enableGracefulRestart: + description: |- + EnableGracefulRestart allows BGP peer to continue to forward data packets along + known routes while the routing protocol information is being restored. + This field is immutable because it requires restart of the BGP session + Supported for FRR mode only. + type: boolean + x-kubernetes-validations: + - message: EnableGracefulRestart cannot be changed after creation + rule: self == oldSelf + holdTime: + description: Requested BGP hold time, per RFC4271. + type: string + keepaliveTime: + description: Requested BGP keepalive time, per RFC4271. + type: string + myASN: + description: AS number to use for the local end of the session. + format: int32 + maximum: 4294967295 + minimum: 0 + type: integer + nodeSelectors: + description: |- + Only connect to this peer on nodes that match one of these + selectors. + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + type: array + password: + description: Authentication password for routers enforcing TCP MD5 authenticated sessions + type: string + passwordSecret: + description: |- + passwordSecret is name of the authentication secret for BGP Peer. + the secret must be of type "kubernetes.io/basic-auth", and created in the + same namespace as the MetalLB deployment. The password is stored in the + secret as the key "password". + properties: + name: + description: name is unique within a namespace to reference a secret resource. + type: string + namespace: + description: namespace defines the space within which the secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + peerASN: + description: AS number to expect from the remote end of the session. + format: int32 + maximum: 4294967295 + minimum: 0 + type: integer + peerAddress: + description: Address to dial when establishing the session. + type: string + peerPort: + default: 179 + description: Port to dial when establishing the session. + maximum: 16384 + minimum: 0 + type: integer + routerID: + description: BGP router ID to advertise to the peer + type: string + sourceAddress: + description: Source address to use when establishing the session. + type: string + vrf: + description: |- + To set if we want to peer with the BGPPeer using an interface belonging to + a host vrf + type: string + required: + - myASN + - peerASN + - peerAddress + type: object + status: + description: BGPPeerStatus defines the observed state of Peer. + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: communities.metallb.io +spec: + group: metallb.io + names: + kind: Community + listKind: CommunityList + plural: communities + singular: community + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: |- + Community is a collection of aliases for communities. + Users can define named aliases to be used in the BGPPeer CRD. + 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: CommunitySpec defines the desired state of Community. + properties: + communities: + items: + properties: + name: + description: The name of the alias for the community. + type: string + value: + description: |- + The BGP community value corresponding to the given name. Can be a standard community of the form 1234:1234 + or a large community of the form large:1234:1234:1234. + type: string + type: object + type: array + type: object + status: + description: CommunityStatus defines the observed state of Community. + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: ipaddresspools.metallb.io +spec: + group: metallb.io + names: + kind: IPAddressPool + listKind: IPAddressPoolList + plural: ipaddresspools + singular: ipaddresspool + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.autoAssign + name: Auto Assign + type: boolean + - jsonPath: .spec.avoidBuggyIPs + name: Avoid Buggy IPs + type: boolean + - jsonPath: .spec.addresses + name: Addresses + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + IPAddressPool represents a pool of IP addresses that can be allocated + to LoadBalancer services. + 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: IPAddressPoolSpec defines the desired state of IPAddressPool. + properties: + addresses: + description: |- + A list of IP address ranges over which MetalLB has authority. + You can list multiple ranges in a single pool, they will all share the + same settings. Each range can be either a CIDR prefix, or an explicit + start-end range of IPs. + items: + type: string + type: array + autoAssign: + default: true + description: |- + AutoAssign flag used to prevent MetallB from automatic allocation + for a pool. + type: boolean + avoidBuggyIPs: + default: false + description: |- + AvoidBuggyIPs prevents addresses ending with .0 and .255 + to be used by a pool. + type: boolean + serviceAllocation: + description: |- + AllocateTo makes ip pool allocation to specific namespace and/or service. + The controller will use the pool with lowest value of priority in case of + multiple matches. A pool with no priority set will be used only if the + pools with priority can't be used. If multiple matching IPAddressPools are + available it will check for the availability of IPs sorting the matching + IPAddressPools by priority, starting from the highest to the lowest. If + multiple IPAddressPools have the same priority, choice will be random. + properties: + namespaceSelectors: + description: |- + NamespaceSelectors list of label selectors to select namespace(s) for ip pool, + an alternative to using namespace list. + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + type: array + namespaces: + description: Namespaces list of namespace(s) on which ip pool can be attached. + items: + type: string + type: array + priority: + description: Priority priority given for ip pool while ip allocation on a service. + type: integer + serviceSelectors: + description: |- + ServiceSelectors list of label selector to select service(s) for which ip pool + can be used for ip allocation. + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + type: array + type: object + required: + - addresses + type: object + status: + description: IPAddressPoolStatus defines the observed state of IPAddressPool. + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: l2advertisements.metallb.io +spec: + group: metallb.io + names: + kind: L2Advertisement + listKind: L2AdvertisementList + plural: l2advertisements + singular: l2advertisement + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.ipAddressPools + name: IPAddressPools + type: string + - jsonPath: .spec.ipAddressPoolSelectors + name: IPAddressPool Selectors + type: string + - jsonPath: .spec.interfaces + name: Interfaces + type: string + - jsonPath: .spec.nodeSelectors + name: Node Selectors + priority: 10 + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: |- + L2Advertisement allows to advertise the LoadBalancer IPs provided + by the selected pools via L2. + 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: L2AdvertisementSpec defines the desired state of L2Advertisement. + properties: + interfaces: + description: |- + A list of interfaces to announce from. The LB IP will be announced only from these interfaces. + If the field is not set, we advertise from all the interfaces on the host. + items: + type: string + type: array + ipAddressPoolSelectors: + description: |- + A selector for the IPAddressPools which would get advertised via this advertisement. + If no IPAddressPool is selected by this or by the list, the advertisement is applied to all the IPAddressPools. + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + type: array + ipAddressPools: + description: The list of IPAddressPools to advertise via this advertisement, selected by name. + items: + type: string + type: array + nodeSelectors: + description: NodeSelectors allows to limit the nodes to announce as next hops for the LoadBalancer IP. When empty, all the nodes having are announced as next hops. + items: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + type: array + type: object + status: + description: L2AdvertisementStatus defines the observed state of L2Advertisement. + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: servicel2statuses.metallb.io +spec: + group: metallb.io + names: + kind: ServiceL2Status + listKind: ServiceL2StatusList + plural: servicel2statuses + singular: servicel2status + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.node + name: Allocated Node + type: string + - jsonPath: .status.serviceName + name: Service Name + type: string + - jsonPath: .status.serviceNamespace + name: Service Namespace + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: ServiceL2Status reveals the actual traffic status of loadbalancer services in layer2 mode. + 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: ServiceL2StatusSpec defines the desired state of ServiceL2Status. + type: object + status: + description: MetalLBServiceL2Status defines the observed state of ServiceL2Status. + properties: + interfaces: + description: Interfaces indicates the interfaces that receive the directed traffic + items: + description: InterfaceInfo defines interface info of layer2 announcement. + properties: + name: + description: Name the name of network interface card + type: string + type: object + type: array + node: + description: Node indicates the node that receives the directed traffic + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf + serviceName: + description: ServiceName indicates the service this status represents + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf + serviceNamespace: + description: ServiceNamespace indicates the namespace of the service + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/metallb-chart/policy.obscpio b/metallb-chart/policy.obscpio deleted file mode 100644 index 09b648f..0000000 Binary files a/metallb-chart/policy.obscpio and /dev/null differ diff --git a/metallb-chart/policy/controller.rego b/metallb-chart/policy/controller.rego new file mode 100644 index 0000000..a91be16 --- /dev/null +++ b/metallb-chart/policy/controller.rego @@ -0,0 +1,16 @@ +package main + +# validate serviceAccountName +deny[msg] { + input.kind == "Deployment" + serviceAccountName := input.spec.template.spec.serviceAccountName + not serviceAccountName == "release-name-metallb-controller" + msg = sprintf("controller serviceAccountName '%s' does not match expected value", [serviceAccountName]) +} + +# validate node selector includes builtin when custom ones are provided +deny[msg] { + input.kind == "Deployment" + not input.spec.template.spec.nodeSelector["kubernetes.io/os"] == "linux" + msg = "controller nodeSelector does not include '\"kubernetes.io/os\": linux'" +} diff --git a/metallb-chart/policy/rbac.rego b/metallb-chart/policy/rbac.rego new file mode 100644 index 0000000..8e261af --- /dev/null +++ b/metallb-chart/policy/rbac.rego @@ -0,0 +1,27 @@ +package main + +# Validate PSP exists in ClusterRole :controller +deny[msg] { + input.kind == "ClusterRole" + input.metadata.name == "metallb:controller" + input.rules[3] == { + "apiGroups": ["policy"], + "resources": ["podsecuritypolicies"], + "resourceNames": ["metallb-controller"], + "verbs": ["use"] + } + msg = "ClusterRole metallb:controller does not include PSP rule" +} + +# Validate PSP exists in ClusterRole :speaker +deny[msg] { + input.kind == "ClusterRole" + input.metadata.name == "metallb:speaker" + input.rules[3] == { + "apiGroups": ["policy"], + "resources": ["podsecuritypolicies"], + "resourceNames": ["metallb-controller"], + "verbs": ["use"] + } + msg = "ClusterRole metallb:speaker does not include PSP rule" +} diff --git a/metallb-chart/policy/speaker.rego b/metallb-chart/policy/speaker.rego new file mode 100644 index 0000000..7e7775b --- /dev/null +++ b/metallb-chart/policy/speaker.rego @@ -0,0 +1,30 @@ +package main + +# validate serviceAccountName +deny[msg] { + input.kind == "DaemonSet" + serviceAccountName := input.spec.template.spec.serviceAccountName + not serviceAccountName == "release-name-metallb-speaker" + msg = sprintf("speaker serviceAccountName '%s' does not match expected value", [serviceAccountName]) +} + +# validate METALLB_ML_SECRET_KEY (memberlist) +deny[msg] { + input.kind == "DaemonSet" + not input.spec.template.spec.containers[0].env[5].name == "METALLB_ML_SECRET_KEY_PATH" + msg = "speaker env does not contain METALLB_ML_SECRET_KEY_PATH at env[5]" +} + +# validate node selector includes builtin when custom ones are provided +deny[msg] { + input.kind == "DaemonSet" + not input.spec.template.spec.nodeSelector["kubernetes.io/os"] == "linux" + msg = "controller nodeSelector does not include '\"kubernetes.io/os\": linux'" +} + +# validate tolerations include the builtins when custom ones are provided +deny[msg] { + input.kind == "DaemonSet" + not input.spec.template.spec.tolerations[0] == { "key": "node-role.kubernetes.io/master", "effect": "NoSchedule", "operator": "Exists" } + msg = "controller tolerations does not include node-role.kubernetes.io/master:NoSchedule" +} diff --git a/metallb-chart/templates.obscpio b/metallb-chart/templates.obscpio deleted file mode 100644 index 9d21bff..0000000 Binary files a/metallb-chart/templates.obscpio and /dev/null differ diff --git a/metallb-chart/templates/NOTES.txt b/metallb-chart/templates/NOTES.txt new file mode 100644 index 0000000..ec05bd7 --- /dev/null +++ b/metallb-chart/templates/NOTES.txt @@ -0,0 +1,4 @@ +MetalLB is now running in the cluster. + +Now you can configure it via its CRs. Please refer to the metallb official docs +on how to use the CRs. diff --git a/metallb-chart/templates/_helpers.tpl b/metallb-chart/templates/_helpers.tpl new file mode 100644 index 0000000..0dc55f3 --- /dev/null +++ b/metallb-chart/templates/_helpers.tpl @@ -0,0 +1,113 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "metallb.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "metallb.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "metallb.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "metallb.labels" -}} +helm.sh/chart: {{ include "metallb.chart" . }} +{{ include "metallb.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "metallb.selectorLabels" -}} +app.kubernetes.io/name: {{ include "metallb.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the controller service account to use +*/}} +{{- define "metallb.controller.serviceAccountName" -}} +{{- if .Values.controller.serviceAccount.create }} +{{- default (printf "%s-controller" (include "metallb.fullname" .)) .Values.controller.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.controller.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the speaker service account to use +*/}} +{{- define "metallb.speaker.serviceAccountName" -}} +{{- if .Values.speaker.serviceAccount.create }} +{{- default (printf "%s-speaker" (include "metallb.fullname" .)) .Values.speaker.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.speaker.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the settings Secret to use. +*/}} +{{- define "metallb.secretName" -}} + {{ default ( printf "%s-memberlist" (include "metallb.fullname" .)) .Values.speaker.secretName | trunc 63 | trimSuffix "-" }} +{{- end -}} + +{{- define "metrics.exposedportname" -}} +{{- if .Values.prometheus.secureMetricsPort -}} +"metricshttps" +{{- else -}} +"metrics" +{{- end -}} +{{- end -}} + +{{- define "metrics.exposedfrrportname" -}} +{{- if .Values.speaker.frr.secureMetricsPort -}} +"frrmetricshttps" +{{- else -}} +"frrmetrics" +{{- end }} +{{- end }} + +{{- define "metrics.exposedport" -}} +{{- if .Values.prometheus.secureMetricsPort -}} +{{ .Values.prometheus.secureMetricsPort }} +{{- else -}} +{{ .Values.prometheus.metricsPort }} +{{- end -}} +{{- end }} + +{{- define "metrics.exposedfrrport" -}} +{{- if .Values.speaker.frr.secureMetricsPort -}} +{{ .Values.speaker.frr.secureMetricsPort }} +{{- else -}} +{{ .Values.speaker.frr.metricsPort }} +{{- end }} +{{- end }} diff --git a/metallb-chart/templates/controller.yaml b/metallb-chart/templates/controller.yaml new file mode 100644 index 0000000..311a559 --- /dev/null +++ b/metallb-chart/templates/controller.yaml @@ -0,0 +1,194 @@ +{{- if .Values.controller.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "metallb.fullname" . }}-controller + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- range $key, $value := .Values.controller.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} +spec: + {{- if .Values.controller.strategy }} + strategy: {{- toYaml .Values.controller.strategy | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "metallb.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller + template: + metadata: + {{- if or .Values.prometheus.scrapeAnnotations .Values.controller.podAnnotations }} + annotations: + {{- if .Values.prometheus.scrapeAnnotations }} + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.prometheus.metricsPort }}" + {{- end }} + {{- with .Values.controller.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + labels: + {{- include "metallb.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: controller + {{- range $key, $value := .Values.controller.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + spec: + {{- with .Values.controller.runtimeClassName }} + runtimeClassName: {{ . | quote }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "metallb.controller.serviceAccountName" . }} + terminationGracePeriodSeconds: 0 +{{- if .Values.controller.securityContext }} + securityContext: +{{ toYaml .Values.controller.securityContext | indent 8 }} +{{- end }} + containers: + - name: controller + image: {{ .Values.controller.image.repository }}:{{ .Values.controller.image.tag | default .Chart.AppVersion }} + {{- if .Values.controller.image.pullPolicy }} + imagePullPolicy: {{ .Values.controller.image.pullPolicy }} + {{- end }} + {{- if .Values.controller.command }} + command: + - {{ .Values.controller.command }} + {{- end }} + args: + - --port={{ .Values.prometheus.metricsPort }} + {{- with .Values.controller.logLevel }} + - --log-level={{ . }} + {{- end }} + {{- if .Values.loadBalancerClass }} + - --lb-class={{ .Values.loadBalancerClass }} + {{- end }} + {{- if .Values.controller.webhookMode }} + - --webhook-mode={{ .Values.controller.webhookMode }} + {{- end }} + {{- if .Values.controller.tlsMinVersion }} + - --tls-min-version={{ .Values.controller.tlsMinVersion }} + {{- end }} + {{- if .Values.controller.tlsCipherSuites }} + - --tls-cipher-suites={{ .Values.controller.tlsCipherSuites }} + {{- end }} + env: + {{- if and .Values.speaker.enabled .Values.speaker.memberlist.enabled }} + - name: METALLB_ML_SECRET_NAME + value: {{ include "metallb.secretName" . }} + - name: METALLB_DEPLOYMENT + value: {{ template "metallb.fullname" . }}-controller + {{- end }} + {{- if .Values.speaker.frr.enabled }} + - name: METALLB_BGP_TYPE + value: frr + {{- end }} + {{- if or .Values.frrk8s.enabled .Values.frrk8s.external }} + - name: METALLB_BGP_TYPE + value: frr-k8s + {{- end }} + ports: + - name: monitoring + containerPort: {{ .Values.prometheus.metricsPort }} + - containerPort: 9443 + name: webhook-server + protocol: TCP + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + {{- if .Values.controller.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /metrics + port: monitoring + initialDelaySeconds: {{ .Values.controller.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.controller.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.controller.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.controller.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.controller.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.controller.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: /metrics + port: monitoring + initialDelaySeconds: {{ .Values.controller.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.controller.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.controller.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.controller.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.controller.readinessProbe.failureThreshold }} + {{- end }} + {{- with .Values.controller.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + {{- if .Values.prometheus.secureMetricsPort }} + - name: kube-rbac-proxy + image: {{ .Values.prometheus.rbacProxy.repository }}:{{ .Values.prometheus.rbacProxy.tag }} + imagePullPolicy: {{ .Values.prometheus.rbacProxy.pullPolicy }} + args: + - --logtostderr + - --secure-listen-address=:{{ .Values.prometheus.secureMetricsPort }} + - --upstream=http://127.0.0.1:{{ .Values.prometheus.metricsPort }}/ + - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + {{- if .Values.prometheus.controllerMetricsTLSSecret }} + - --tls-private-key-file=/etc/metrics/tls.key + - --tls-cert-file=/etc/metrics/tls.crt + {{- end }} + ports: + - containerPort: {{ .Values.prometheus.secureMetricsPort }} + name: metricshttps + resources: + requests: + cpu: 10m + memory: 20Mi + terminationMessagePolicy: FallbackToLogsOnError + {{- if .Values.prometheus.controllerMetricsTLSSecret }} + volumeMounts: + - name: metrics-certs + mountPath: /etc/metrics + readOnly: true + {{- end }} + {{ end }} + {{- if .Values.controller.extraContainers }} + {{- toYaml .Values.controller.extraContainers | nindent 6 }} + {{- end }} + nodeSelector: + "kubernetes.io/os": linux + {{- with .Values.controller.nodeSelector }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.tolerations }} + tolerations: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.controller.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: metallb-webhook-cert + {{- if .Values.prometheus.controllerMetricsTLSSecret }} + - name: metrics-certs + secret: + secretName: {{ .Values.prometheus.controllerMetricsTLSSecret }} + {{- end }} +{{- end }} diff --git a/metallb-chart/templates/deprecated_configInline.yaml b/metallb-chart/templates/deprecated_configInline.yaml new file mode 100644 index 0000000..077c7b6 --- /dev/null +++ b/metallb-chart/templates/deprecated_configInline.yaml @@ -0,0 +1,3 @@ +{{- if .Values.configInline }} +{{- fail "Starting from v0.13.0 configInline is no longer supported. Please see https://metallb.universe.tf/#backward-compatibility" }} +{{- end }} diff --git a/metallb-chart/templates/exclude-l2-config.yaml b/metallb-chart/templates/exclude-l2-config.yaml new file mode 100644 index 0000000..2c85c88 --- /dev/null +++ b/metallb-chart/templates/exclude-l2-config.yaml @@ -0,0 +1,25 @@ +{{- if and .Values.speaker.enabled .Values.speaker.excludeInterfaces.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: metallb-excludel2 + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} +data: + excludel2.yaml: | + announcedInterfacesToExclude: + - ^docker.* + - ^cbr.* + - ^dummy.* + - ^virbr.* + - ^lxcbr.* + - ^veth.* + - ^lo$ + - ^cali.* + - ^tunl.* + - ^flannel.* + - ^kube-ipvs.* + - ^cni.* + - ^nodelocaldns.* +{{- end }} \ No newline at end of file diff --git a/metallb-chart/templates/podmonitor.yaml b/metallb-chart/templates/podmonitor.yaml new file mode 100644 index 0000000..40155de --- /dev/null +++ b/metallb-chart/templates/podmonitor.yaml @@ -0,0 +1,106 @@ +{{- if .Values.prometheus.podMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: {{ template "metallb.fullname" . }}-controller + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- if .Values.prometheus.podMonitor.additionalLabels }} +{{ toYaml .Values.prometheus.podMonitor.additionalLabels | indent 4 }} + {{- end }} + {{- if .Values.prometheus.podMonitor.annotations }} + annotations: +{{ toYaml .Values.prometheus.podMonitor.annotations | indent 4 }} + {{- end }} +spec: + jobLabel: {{ .Values.prometheus.podMonitor.jobLabel | quote }} + selector: + matchLabels: + {{- include "metallb.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: controller + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + podMetricsEndpoints: + - port: monitoring + path: /metrics + {{- if .Values.prometheus.podMonitor.interval }} + interval: {{ .Values.prometheus.podMonitor.interval }} + {{- end }} +{{- if .Values.prometheus.podMonitor.metricRelabelings }} + metricRelabelings: +{{- toYaml .Values.prometheus.podMonitor.metricRelabelings | nindent 4 }} +{{- end }} +{{- if .Values.prometheus.podMonitor.relabelings }} + relabelings: +{{- toYaml .Values.prometheus.podMonitor.relabelings | nindent 4 }} +{{- end }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: {{ template "metallb.fullname" . }}-speaker + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: speaker + {{- if .Values.prometheus.podMonitor.additionalLabels }} +{{ toYaml .Values.prometheus.podMonitor.additionalLabels | indent 4 }} + {{- end }} + {{- if .Values.prometheus.podMonitor.annotations }} + annotations: +{{ toYaml .Values.prometheus.podMonitor.annotations | indent 4 }} + {{- end }} +spec: + jobLabel: {{ .Values.prometheus.podMonitor.jobLabel | quote }} + selector: + matchLabels: + {{- include "metallb.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: speaker + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + podMetricsEndpoints: + - port: monitoring + path: /metrics + {{- if .Values.prometheus.podMonitor.interval }} + interval: {{ .Values.prometheus.podMonitor.interval }} + {{- end }} +{{- if .Values.prometheus.podMonitor.metricRelabelings }} + metricRelabelings: +{{- toYaml .Values.prometheus.podMonitor.metricRelabelings | nindent 4 }} +{{- end }} +{{- if .Values.prometheus.podMonitor.relabelings }} + relabelings: +{{- toYaml .Values.prometheus.podMonitor.relabelings | nindent 4 }} +{{- end }} +--- +{{- if .Values.prometheus.rbacPrometheus }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "metallb.fullname" . }}-prometheus +rules: + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "metallb.fullname" . }}-prometheus +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "metallb.fullname" . }}-prometheus +subjects: + - kind: ServiceAccount + name: {{ required ".Values.prometheus.serviceAccount must be defined when .Values.prometheus.podMonitor.enabled == true" .Values.prometheus.serviceAccount }} + namespace: {{ required ".Values.prometheus.namespace must be defined when .Values.prometheus.podMonitor.enabled == true" .Values.prometheus.namespace }} +{{- end }} +{{- end }} diff --git a/metallb-chart/templates/prometheusrules.yaml b/metallb-chart/templates/prometheusrules.yaml new file mode 100644 index 0000000..50bd49a --- /dev/null +++ b/metallb-chart/templates/prometheusrules.yaml @@ -0,0 +1,84 @@ +{{- if .Values.prometheus.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ template "metallb.fullname" . }} + labels: + {{- include "metallb.labels" . | nindent 4 }} + {{- if .Values.prometheus.prometheusRule.additionalLabels }} +{{ toYaml .Values.prometheus.prometheusRule.additionalLabels | indent 4 }} + {{- end }} + {{- if .Values.prometheus.prometheusRule.annotations }} + annotations: +{{ toYaml .Values.prometheus.prometheusRule.annotations | indent 4 }} + {{- end }} +spec: + groups: + - name: {{ template "metallb.fullname" . }}.rules + rules: + {{- if .Values.prometheus.prometheusRule.staleConfig.enabled }} + - alert: MetalLBStaleConfig + annotations: + message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod + }} has a stale config for > 1 minute'`}} + expr: metallb_k8s_client_config_stale_bool{job=~"{{ template "metallb.fullname" . }}.*"} == 1 + for: 1m + {{- with .Values.prometheus.prometheusRule.staleConfig.labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.prometheus.prometheusRule.configNotLoaded.enabled }} + - alert: MetalLBConfigNotLoaded + annotations: + message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod + }} has not loaded for > 1 minute'`}} + expr: metallb_k8s_client_config_loaded_bool{job=~"{{ template "metallb.fullname" . }}.*"} == 0 + for: 1m + {{- with .Values.prometheus.prometheusRule.configNotLoaded.labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.prometheus.prometheusRule.addressPoolExhausted.enabled }} + - alert: MetalLBAddressPoolExhausted + annotations: + message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod + }} has exhausted address pool {{ $labels.pool }} for > 1 minute'`}} + expr: metallb_allocator_addresses_in_use_total >= on(pool) metallb_allocator_addresses_total + for: 1m + {{- with .Values.prometheus.prometheusRule.addressPoolExhausted.labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + + {{- if .Values.prometheus.prometheusRule.addressPoolUsage.enabled }} + {{- range .Values.prometheus.prometheusRule.addressPoolUsage.thresholds }} + - alert: MetalLBAddressPoolUsage{{ .percent }}Percent + annotations: + message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod + }} has address pool {{ $labels.pool }} past `}}{{ .percent }}{{`% usage for > 1 minute'`}} + expr: ( metallb_allocator_addresses_in_use_total / on(pool) metallb_allocator_addresses_total ) * 100 > {{ .percent }} + {{- with .labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.prometheus.prometheusRule.bgpSessionDown.enabled }} + - alert: MetalLBBGPSessionDown + annotations: + message: {{`'{{ $labels.job }} - MetalLB {{ $labels.container }} on {{ $labels.pod + }} has BGP session {{ $labels.peer }} down for > 1 minute'`}} + expr: metallb_bgp_session_up{job=~"{{ template "metallb.fullname" . }}.*"} == 0 + for: 1m + {{- with .Values.prometheus.prometheusRule.bgpSessionDown.labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- with .Values.prometheus.prometheusRule.extraAlerts }} + {{- toYaml . | nindent 4 }} + {{- end}} +{{- end }} diff --git a/metallb-chart/templates/rbac.yaml b/metallb-chart/templates/rbac.yaml new file mode 100644 index 0000000..8c66b80 --- /dev/null +++ b/metallb-chart/templates/rbac.yaml @@ -0,0 +1,212 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "metallb.fullname" . }}:controller + labels: + {{- include "metallb.labels" . | nindent 4 }} +rules: +- apiGroups: [""] + resources: ["services", "namespaces"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["nodes"] + verbs: ["list"] +- apiGroups: [""] + resources: ["services/status"] + verbs: ["update"] +- apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] + resourceNames: ["metallb-webhook-configuration"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations", "mutatingwebhookconfigurations"] + verbs: ["list", "watch"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + resourceNames: ["bfdprofiles.metallb.io","bgpadvertisements.metallb.io", + "bgppeers.metallb.io","ipaddresspools.metallb.io","l2advertisements.metallb.io","communities.metallb.io"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["list", "watch"] +{{- if .Values.prometheus.secureMetricsPort }} +- apiGroups: ["authentication.k8s.io"] + resources: ["tokenreviews"] + verbs: ["create"] +- apiGroups: ["authorization.k8s.io"] + resources: ["subjectaccessreviews"] + verbs: ["create"] +{{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "metallb.fullname" . }}:speaker + labels: + {{- include "metallb.labels" . | nindent 4 }} +rules: +- apiGroups: [""] + resources: ["services", "endpoints", "nodes", "namespaces"] + verbs: ["get", "list", "watch"] +- apiGroups: ["discovery.k8s.io"] + resources: ["endpointslices"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] +- apiGroups: ["metallb.io"] + resources: ["servicel2statuses","servicel2statuses/status"] + verbs: ["*"] +{{- if .Values.prometheus.secureMetricsPort }} +- apiGroups: ["authentication.k8s.io"] + resources: ["tokenreviews"] + verbs: ["create"] +- apiGroups: ["authorization.k8s.io"] + resources: ["subjectaccessreviews"] + verbs: ["create"] +{{- end }} +{{- if or .Values.frrk8s.enabled .Values.frrk8s.external }} +- apiGroups: ["frrk8s.metallb.io"] + resources: ["frrconfigurations"] + verbs: ["get", "list", "watch","create","update"] +{{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "metallb.fullname" . }}-pod-lister + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "metallb.labels" . | nindent 4 }} +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["list", "get"] +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["bfdprofiles"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["bgppeers"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["l2advertisements"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["bgpadvertisements"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["ipaddresspools"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["communities"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "metallb.fullname" . }}-controller + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "metallb.labels" . | nindent 4 }} +rules: +{{- if .Values.speaker.memberlist.enabled }} +- apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "list", "watch"] +- apiGroups: [""] + resources: ["secrets"] + resourceNames: [{{ include "metallb.secretName" . | quote }}] + verbs: ["list"] +- apiGroups: ["apps"] + resources: ["deployments"] + resourceNames: ["{{ template "metallb.fullname" . }}-controller"] + verbs: ["get"] +{{- end }} +- apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "delete", "get", "list", "patch", "update", "watch"] +- apiGroups: ["metallb.io"] + resources: ["ipaddresspools"] + verbs: ["get", "list", "watch"] +- apiGroups: ["metallb.io"] + resources: ["bgppeers"] + verbs: ["get", "list"] +- apiGroups: ["metallb.io"] + resources: ["bgpadvertisements"] + verbs: ["get", "list"] +- apiGroups: ["metallb.io"] + resources: ["l2advertisements"] + verbs: ["get", "list"] +- apiGroups: ["metallb.io"] + resources: ["communities"] + verbs: ["get", "list","watch"] +- apiGroups: ["metallb.io"] + resources: ["bfdprofiles"] + verbs: ["get", "list","watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "metallb.fullname" . }}:controller + labels: + {{- include "metallb.labels" . | nindent 4 }} +subjects: +- kind: ServiceAccount + name: {{ template "metallb.controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "metallb.fullname" . }}:controller +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "metallb.fullname" . }}:speaker + labels: + {{- include "metallb.labels" . | nindent 4 }} +subjects: +- kind: ServiceAccount + name: {{ template "metallb.speaker.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "metallb.fullname" . }}:speaker +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "metallb.fullname" . }}-pod-lister + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "metallb.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "metallb.fullname" . }}-pod-lister +subjects: +- kind: ServiceAccount + name: {{ include "metallb.speaker.serviceAccountName" . }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "metallb.fullname" . }}-controller + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "metallb.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "metallb.fullname" . }}-controller +subjects: +- kind: ServiceAccount + name: {{ include "metallb.controller.serviceAccountName" . }} +{{- end -}} diff --git a/metallb-chart/templates/service-accounts.yaml b/metallb-chart/templates/service-accounts.yaml new file mode 100644 index 0000000..c2157ff --- /dev/null +++ b/metallb-chart/templates/service-accounts.yaml @@ -0,0 +1,30 @@ +{{- if .Values.controller.serviceAccount.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "metallb.controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: controller + {{- with .Values.controller.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +{{- if .Values.speaker.serviceAccount.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "metallb.speaker.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: speaker + {{- with .Values.speaker.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/metallb-chart/templates/servicemonitor.yaml b/metallb-chart/templates/servicemonitor.yaml new file mode 100644 index 0000000..0aacf85 --- /dev/null +++ b/metallb-chart/templates/servicemonitor.yaml @@ -0,0 +1,194 @@ +{{- if .Values.prometheus.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "metallb.fullname" . }}-speaker-monitor + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: speaker + {{- if .Values.prometheus.serviceMonitor.speaker.additionalLabels }} +{{ toYaml .Values.prometheus.serviceMonitor.speaker.additionalLabels | indent 4 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.speaker.annotations }} + annotations: +{{ toYaml .Values.prometheus.serviceMonitor.speaker.annotations | indent 4 }} + {{- end }} +spec: + endpoints: + - port: {{ template "metrics.exposedportname" . }} + honorLabels: true + {{- if .Values.prometheus.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml .Values.prometheus.serviceMonitor.metricRelabelings | nindent 8 }} + {{- end -}} + {{- if .Values.prometheus.serviceMonitor.relabelings }} + relabelings: + {{- toYaml .Values.prometheus.serviceMonitor.relabelings | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.interval }} + interval: {{ .Values.prometheus.serviceMonitor.interval }} + {{- end -}} +{{ if .Values.prometheus.secureMetricsPort }} + bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token" + scheme: "https" +{{- if .Values.prometheus.serviceMonitor.speaker.tlsConfig }} + tlsConfig: +{{ toYaml .Values.prometheus.serviceMonitor.speaker.tlsConfig | indent 8 }} +{{- end }} +{{ end }} +{{- if .Values.speaker.frr.enabled }} + - port: {{ template "metrics.exposedfrrportname" . }} + honorLabels: true +{{ if .Values.speaker.frr.secureMetricsPort }} + {{- if .Values.prometheus.serviceMonitor.interval }} + interval: {{ .Values.prometheus.serviceMonitor.interval }} + {{- end }} + bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token" + scheme: "https" +{{- if .Values.prometheus.serviceMonitor.speaker.tlsConfig }} + tlsConfig: +{{ toYaml .Values.prometheus.serviceMonitor.speaker.tlsConfig | indent 8 }} +{{- end }} +{{- end }} +{{- end }} + jobLabel: {{ .Values.prometheus.serviceMonitor.jobLabel | quote }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + name: {{ template "metallb.fullname" . }}-speaker-monitor-service +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/scrape: "true" + {{- if .Values.prometheus.serviceMonitor.speaker.annotations }} +{{ toYaml .Values.prometheus.serviceMonitor.speaker.annotations | indent 4 }} + {{- end }} + labels: + name: {{ template "metallb.fullname" . }}-speaker-monitor-service + {{- include "metallb.labels" . | nindent 4 }} + name: {{ template "metallb.fullname" . }}-speaker-monitor-service + namespace: {{ .Release.Namespace | quote }} +spec: + selector: + {{- include "metallb.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: speaker + clusterIP: None + ports: + - name: {{ template "metrics.exposedportname" . }} + port: {{ template "metrics.exposedport" . }} + targetPort: {{ template "metrics.exposedport" . }} +{{- if .Values.speaker.frr.enabled }} + - name: {{ template "metrics.exposedfrrportname" . }} + port: {{ template "metrics.exposedfrrport" . }} + targetPort: {{ template "metrics.exposedfrrport" . }} +{{- end }} + sessionAffinity: None + type: ClusterIP +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "metallb.fullname" . }}-controller-monitor + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: speaker + {{- if .Values.prometheus.serviceMonitor.controller.additionalLabels }} +{{ toYaml .Values.prometheus.serviceMonitor.controller.additionalLabels | indent 4 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.controller.annotations }} + annotations: +{{ toYaml .Values.prometheus.serviceMonitor.controller.annotations | indent 4 }} + {{- end }} +spec: + endpoints: + - port: {{ template "metrics.exposedportname" . }} + {{- if .Values.prometheus.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml .Values.prometheus.serviceMonitor.metricRelabelings | nindent 8 }} + {{- end -}} + {{- if .Values.prometheus.serviceMonitor.relabelings }} + relabelings: + {{- toYaml .Values.prometheus.serviceMonitor.relabelings | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.serviceMonitor.interval }} + interval: {{ .Values.prometheus.serviceMonitor.interval }} + {{- end }} + honorLabels: true +{{- if .Values.prometheus.secureMetricsPort }} + bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token" + scheme: "https" +{{- if .Values.prometheus.serviceMonitor.controller.tlsConfig }} + tlsConfig: +{{ toYaml .Values.prometheus.serviceMonitor.controller.tlsConfig | indent 8 }} +{{- end }} +{{- end }} + jobLabel: {{ .Values.prometheus.serviceMonitor.jobLabel | quote }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + name: {{ template "metallb.fullname" . }}-controller-monitor-service +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/scrape: "true" + {{- if .Values.prometheus.serviceMonitor.controller.annotations }} +{{ toYaml .Values.prometheus.serviceMonitor.controller.annotations | indent 4 }} + {{- end }} + labels: + name: {{ template "metallb.fullname" . }}-controller-monitor-service + name: {{ template "metallb.fullname" . }}-controller-monitor-service +spec: + selector: + {{- include "metallb.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: controller + clusterIP: None + ports: + - name: {{ template "metrics.exposedportname" . }} + port: {{ template "metrics.exposedport" . }} + targetPort: {{ template "metrics.exposedport" . }} + sessionAffinity: None + type: ClusterIP +--- +{{- if .Values.prometheus.rbacPrometheus }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "metallb.fullname" . }}-prometheus + namespace: {{ .Release.Namespace | quote }} +rules: + - apiGroups: + - "" + resources: + - pods + - services + - endpoints + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "metallb.fullname" . }}-prometheus + namespace: {{ .Release.Namespace | quote }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "metallb.fullname" . }}-prometheus +subjects: + - kind: ServiceAccount + name: {{ required ".Values.prometheus.serviceAccount must be defined when .Values.prometheus.serviceMonitor.enabled == true" .Values.prometheus.serviceAccount }} + namespace: {{ required ".Values.prometheus.namespace must be defined when .Values.prometheus.serviceMonitor.enabled == true" .Values.prometheus.namespace }} +{{- end }} +{{- end }} diff --git a/metallb-chart/templates/speaker.yaml b/metallb-chart/templates/speaker.yaml new file mode 100644 index 0000000..567d820 --- /dev/null +++ b/metallb-chart/templates/speaker.yaml @@ -0,0 +1,568 @@ +{{- if .Values.speaker.frr.enabled }} +{{- if or .Values.frrk8s.enabled .Values.frrk8s.external }} +{{- fail "speaker.frr.enabled and frrk8s.enabled / external are mutually exclusive!" }} +{{- end }} +{{- end }} + +{{- if and .Values.frrk8s.enabled .Values.frrk8s.external }} +{{- fail "frrk8s.enabled frrk8s.external are mutually exclusive!" }} +{{- end }} + +{{- if .Values.speaker.frr.enabled }} + +# FRR expects to have these files owned by frr:frr on startup. +# Having them in a ConfigMap allows us to modify behaviors: for example enabling more daemons on startup. +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "metallb.fullname" . }}-frr-startup + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: speaker +data: + daemons: | + # This file tells the frr package which daemons to start. + # + # Sample configurations for these daemons can be found in + # /usr/share/doc/frr/examples/. + # + # ATTENTION: + # + # When activating a daemon for the first time, a config file, even if it is + # empty, has to be present *and* be owned by the user and group "frr", else + # the daemon will not be started by /etc/init.d/frr. The permissions should + # be u=rw,g=r,o=. + # When using "vtysh" such a config file is also needed. It should be owned by + # group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too. + # + # The watchfrr and zebra daemons are always started. + # + bgpd=yes + ospfd=no + ospf6d=no + ripd=no + ripngd=no + isisd=no + pimd=no + ldpd=no + nhrpd=no + eigrpd=no + babeld=no + sharpd=no + pbrd=no + bfdd=yes + fabricd=no + vrrpd=no + + # + # If this option is set the /etc/init.d/frr script automatically loads + # the config via "vtysh -b" when the servers are started. + # Check /etc/pam.d/frr if you intend to use "vtysh"! + # + vtysh_enable=yes + zebra_options=" -A 127.0.0.1 -s 90000000" + bgpd_options=" -A 127.0.0.1 -p 0" + ospfd_options=" -A 127.0.0.1" + ospf6d_options=" -A ::1" + ripd_options=" -A 127.0.0.1" + ripngd_options=" -A ::1" + isisd_options=" -A 127.0.0.1" + pimd_options=" -A 127.0.0.1" + ldpd_options=" -A 127.0.0.1" + nhrpd_options=" -A 127.0.0.1" + eigrpd_options=" -A 127.0.0.1" + babeld_options=" -A 127.0.0.1" + sharpd_options=" -A 127.0.0.1" + pbrd_options=" -A 127.0.0.1" + staticd_options="-A 127.0.0.1" + bfdd_options=" -A 127.0.0.1" + fabricd_options="-A 127.0.0.1" + vrrpd_options=" -A 127.0.0.1" + + # configuration profile + # + #frr_profile="traditional" + #frr_profile="datacenter" + + # + # This is the maximum number of FD's that will be available. + # Upon startup this is read by the control files and ulimit + # is called. Uncomment and use a reasonable value for your + # setup if you are expecting a large number of peers in + # say BGP. + #MAX_FDS=1024 + + # The list of daemons to watch is automatically generated by the init script. + #watchfrr_options="" + + # for debugging purposes, you can specify a "wrap" command to start instead + # of starting the daemon directly, e.g. to use valgrind on ospfd: + # ospfd_wrap="/usr/bin/valgrind" + # or you can use "all_wrap" for all daemons, e.g. to use perf record: + # all_wrap="/usr/bin/perf record --call-graph -" + # the normal daemon command is added to this at the end. + vtysh.conf: |+ + service integrated-vtysh-config + frr.conf: |+ + ! This file gets overriden the first time the speaker renders a config. + ! So anything configured here is only temporary. + frr version 8.0 + frr defaults traditional + hostname Router + line vty + log file /etc/frr/frr.log informational +{{- end }} +--- +{{- if .Values.speaker.enabled }} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ template "metallb.fullname" . }}-speaker + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} + app.kubernetes.io/component: speaker + {{- range $key, $value := .Values.speaker.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} +spec: + {{- if .Values.speaker.updateStrategy }} + updateStrategy: {{- toYaml .Values.speaker.updateStrategy | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "metallb.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: speaker + template: + metadata: + {{- if or .Values.prometheus.scrapeAnnotations .Values.speaker.podAnnotations }} + annotations: + {{- if .Values.prometheus.scrapeAnnotations }} + prometheus.io/scrape: "true" + {{- if not .Values.speaker.frr.enabled }} + prometheus.io/port: "{{ .Values.prometheus.metricsPort }}" + {{- end }} + {{- end }} + {{- with .Values.speaker.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + labels: + {{- include "metallb.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: speaker + {{- range $key, $value := .Values.speaker.labels }} + {{ $key }}: {{ $value | quote }} + {{- end }} + spec: + {{- if .Values.speaker.runtimeClassName }} + runtimeClassName: {{ .Values.speaker.runtimeClassName }} + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ template "metallb.speaker.serviceAccountName" . }} + terminationGracePeriodSeconds: 0 + hostNetwork: true + {{- if .Values.speaker.securityContext }} + securityContext: + {{- toYaml .Values.speaker.securityContext | nindent 8 }} + {{- end }} + volumes: + {{- if .Values.prometheus.speakerMetricsTLSSecret }} + - name: metrics-certs + secret: + secretName: {{ .Values.prometheus.speakerMetricsTLSSecret }} + {{- end }} + {{- if .Values.speaker.memberlist.enabled }} + - name: memberlist + secret: + secretName: {{ include "metallb.secretName" . }} + defaultMode: 420 + {{- end }} + {{- if .Values.speaker.excludeInterfaces.enabled }} + - name: metallb-excludel2 + configMap: + defaultMode: 256 + name: metallb-excludel2 + {{- end }} + {{- if .Values.speaker.frr.enabled }} + - name: frr-sockets + emptyDir: {} + - name: frr-startup + configMap: + name: {{ template "metallb.fullname" . }}-frr-startup + - name: frr-conf + emptyDir: {} + - name: reloader + emptyDir: {} + - name: metrics + emptyDir: {} + initContainers: + # Copies the initial config files with the right permissions to the shared volume. + - name: cp-frr-files + image: {{ .Values.speaker.frr.image.repository }}:{{ .Values.speaker.frr.image.tag | default .Chart.AppVersion }} + securityContext: + runAsUser: 100 + runAsGroup: 101 + command: ["/bin/sh", "-c", "cp -rLf /tmp/frr/* /etc/frr/"] + volumeMounts: + - name: frr-startup + mountPath: /tmp/frr + - name: frr-conf + mountPath: /etc/frr + # Copies the reloader to the shared volume between the speaker and reloader. + - name: cp-reloader + image: {{ .Values.speaker.image.repository }}:{{ .Values.speaker.image.tag | default .Chart.AppVersion }} + command: ["/cp-tool","/frr-reloader.sh","/etc/frr_reloader/frr-reloader.sh"] + volumeMounts: + - name: reloader + mountPath: /etc/frr_reloader + # Copies the metrics exporter + - name: cp-metrics + image: {{ .Values.speaker.image.repository }}:{{ .Values.speaker.image.tag | default .Chart.AppVersion }} + command: ["/cp-tool","/frr-metrics","/etc/frr_metrics/frr-metrics"] + volumeMounts: + - name: metrics + mountPath: /etc/frr_metrics + shareProcessNamespace: true + {{- end }} + containers: + - name: speaker + image: {{ .Values.speaker.image.repository }}:{{ .Values.speaker.image.tag | default .Chart.AppVersion }} + {{- if .Values.speaker.image.pullPolicy }} + imagePullPolicy: {{ .Values.speaker.image.pullPolicy }} + {{- end }} + {{- if .Values.speaker.command }} + command: + - {{ .Values.speaker.command }} + {{- end }} + args: + - --port={{ .Values.prometheus.metricsPort }} + {{- with .Values.speaker.logLevel }} + - --log-level={{ . }} + {{- end }} + {{- if .Values.loadBalancerClass }} + - --lb-class={{ .Values.loadBalancerClass }} + {{- end }} + {{- if .Values.speaker.wanConfig }} + - --ml-wan-config + {{- end }} + {{- if .Values.speaker.ignoreExcludeLB}} + - --ignore-exclude-lb + {{- end }} + {{- if .Values.prometheus.secureMetricsPort }} + - --host=localhost + {{- end }} + {{- if .Values.frrk8s.external }} + - --frrk8s-namespace={{ required "namespace is required when frrk8s is external" .Values.frrk8s.namespace }} + {{- end }} + env: + - name: METALLB_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: METALLB_HOST + valueFrom: + fieldRef: + fieldPath: status.hostIP + {{- if .Values.speaker.memberlist.enabled }} + {{- if .Values.speaker.memberlist.mlBindAddrOverride }} + - name: METALLB_ML_BIND_ADDR + value: "{{ .Values.speaker.memberlist.mlBindAddrOverride }}" + {{ else }} + - name: METALLB_ML_BIND_ADDR + valueFrom: + fieldRef: + fieldPath: status.podIP + {{ end }} + - name: METALLB_ML_LABELS + value: "app.kubernetes.io/name={{ include "metallb.name" . }},app.kubernetes.io/component=speaker" + - name: METALLB_ML_BIND_PORT + value: "{{ .Values.speaker.memberlist.mlBindPort }}" + - name: METALLB_ML_SECRET_KEY_PATH + value: "{{ .Values.speaker.memberlist.mlSecretKeyPath }}" + {{- end }} + {{- if .Values.speaker.frr.enabled }} + - name: FRR_CONFIG_FILE + value: /etc/frr_reloader/frr.conf + - name: FRR_RELOADER_PID_FILE + value: /etc/frr_reloader/reloader.pid + - name: METALLB_BGP_TYPE + value: frr + {{- end }} + {{- if or .Values.frrk8s.enabled .Values.frrk8s.external }} + - name: METALLB_BGP_TYPE + value: frr-k8s + {{- end }} + - name: METALLB_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + ports: + - name: monitoring + containerPort: {{ .Values.prometheus.metricsPort }} + {{- if .Values.speaker.memberlist.enabled }} + - name: memberlist-tcp + containerPort: {{ .Values.speaker.memberlist.mlBindPort }} + protocol: TCP + - name: memberlist-udp + containerPort: {{ .Values.speaker.memberlist.mlBindPort }} + protocol: UDP + {{- end }} + {{- if .Values.speaker.livenessProbe.enabled }} + livenessProbe: + httpGet: + {{- if .Values.prometheus.secureMetricsPort }} + host: localhost + {{- end }} + path: /metrics + port: monitoring + initialDelaySeconds: {{ .Values.speaker.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.speaker.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.speaker.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.speaker.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.speaker.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.speaker.readinessProbe.enabled }} + readinessProbe: + httpGet: + {{- if .Values.prometheus.secureMetricsPort }} + host: localhost + {{- end }} + path: /metrics + port: monitoring + initialDelaySeconds: {{ .Values.speaker.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.speaker.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.speaker.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.speaker.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.speaker.readinessProbe.failureThreshold }} + {{- end }} + {{- with .Values.speaker.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + add: + - NET_RAW + {{- if or .Values.speaker.frr.enabled .Values.speaker.memberlist.enabled .Values.speaker.excludeInterfaces.enabled }} + volumeMounts: + {{- if .Values.speaker.memberlist.enabled }} + - name: memberlist + mountPath: {{ .Values.speaker.memberlist.mlSecretKeyPath }} + {{- end }} + {{- if .Values.speaker.frr.enabled }} + - name: reloader + mountPath: /etc/frr_reloader + {{- end }} + {{- if .Values.speaker.excludeInterfaces.enabled }} + - name: metallb-excludel2 + mountPath: /etc/metallb + {{- end }} + {{- end }} + {{- if .Values.speaker.frr.enabled }} + - name: frr + securityContext: + capabilities: + add: + - NET_ADMIN + - NET_RAW + - SYS_ADMIN + - NET_BIND_SERVICE + image: {{ .Values.speaker.frr.image.repository }}:{{ .Values.speaker.frr.image.tag | default .Chart.AppVersion }} + {{- if .Values.speaker.frr.image.pullPolicy }} + imagePullPolicy: {{ .Values.speaker.frr.image.pullPolicy }} + {{- end }} + env: + - name: TINI_SUBREAPER + value: "true" + volumeMounts: + - name: frr-sockets + mountPath: /var/run/frr + - name: frr-conf + mountPath: /etc/frr + # The command is FRR's default entrypoint & waiting for the log file to appear and tailing it. + # If the log file isn't created in 60 seconds the tail fails and the container is restarted. + # This workaround is needed to have the frr logs as part of kubectl logs -c frr < speaker_pod_name >. + command: + - /bin/sh + - -c + - | + /sbin/tini -- /usr/lib/frr/docker-start & + attempts=0 + until [[ -f /etc/frr/frr.log || $attempts -eq 60 ]]; do + sleep 1 + attempts=$(( $attempts + 1 )) + done + tail -f /etc/frr/frr.log + {{- with .Values.speaker.frr.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.speaker.livenessProbe.enabled }} + livenessProbe: + httpGet: + {{- if .Values.prometheus.secureMetricsPort }} + host: localhost + {{- end }} + path: livez + port: {{ .Values.speaker.frr.metricsPort }} + initialDelaySeconds: {{ .Values.speaker.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.speaker.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.speaker.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.speaker.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.speaker.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.speaker.startupProbe.enabled }} + startupProbe: + httpGet: + {{- if .Values.prometheus.secureMetricsPort }} + host: localhost + {{- end }} + path: /livez + port: {{ .Values.speaker.frr.metricsPort }} + failureThreshold: {{ .Values.speaker.startupProbe.failureThreshold }} + periodSeconds: {{ .Values.speaker.startupProbe.periodSeconds }} + {{- end }} + - name: reloader + image: {{ .Values.speaker.frr.image.repository }}:{{ .Values.speaker.frr.image.tag | default .Chart.AppVersion }} + {{- if .Values.speaker.frr.image.pullPolicy }} + imagePullPolicy: {{ .Values.speaker.frr.image.pullPolicy }} + {{- end }} + command: ["/etc/frr_reloader/frr-reloader.sh"] + volumeMounts: + - name: frr-sockets + mountPath: /var/run/frr + - name: frr-conf + mountPath: /etc/frr + - name: reloader + mountPath: /etc/frr_reloader + {{- with .Values.speaker.reloader.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: frr-metrics + image: {{ .Values.speaker.frr.image.repository }}:{{ .Values.speaker.frr.image.tag | default .Chart.AppVersion }} + command: ["/etc/frr_metrics/frr-metrics"] + args: + - --metrics-port={{ .Values.speaker.frr.metricsPort }} + {{- if .Values.prometheus.secureMetricsPort }} + - --host=localhost + {{- end }} + env: + - name: VTYSH_HISTFILE + value: /dev/null + ports: + - containerPort: {{ .Values.speaker.frr.metricsPort }} + name: monitoring + volumeMounts: + - name: frr-sockets + mountPath: /var/run/frr + - name: frr-conf + mountPath: /etc/frr + - name: metrics + mountPath: /etc/frr_metrics + {{- with .Values.speaker.frrMetrics.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.prometheus.secureMetricsPort }} + - name: kube-rbac-proxy + image: {{ .Values.prometheus.rbacProxy.repository }}:{{ .Values.prometheus.rbacProxy.tag }} + imagePullPolicy: {{ .Values.prometheus.rbacProxy.pullPolicy }} + args: + - --logtostderr + - --secure-listen-address=:{{ .Values.prometheus.secureMetricsPort }} + - --upstream=http://localhost:{{ .Values.prometheus.metricsPort }}/ + - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + {{- if .Values.prometheus.speakerMetricsTLSSecret }} + - --tls-private-key-file=/etc/metrics/tls.key + - --tls-cert-file=/etc/metrics/tls.crt + {{- end }} + ports: + - containerPort: {{ .Values.prometheus.secureMetricsPort }} + name: metricshttps + resources: + requests: + cpu: 10m + memory: 20Mi + terminationMessagePolicy: FallbackToLogsOnError + {{- if .Values.prometheus.speakerMetricsTLSSecret }} + volumeMounts: + - name: metrics-certs + mountPath: /etc/metrics + readOnly: true + {{- end }} + {{ end }} + {{- if .Values.speaker.frr.enabled }} + {{- if .Values.speaker.frr.secureMetricsPort }} + - name: kube-rbac-proxy-frr + image: {{ .Values.prometheus.rbacProxy.repository }}:{{ .Values.prometheus.rbacProxy.tag | default .Chart.AppVersion }} + imagePullPolicy: {{ .Values.prometheus.rbacProxy.pullPolicy }} + args: + - --logtostderr + - --secure-listen-address=:{{ .Values.speaker.frr.secureMetricsPort }} + - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + - --upstream=http://localhost:{{ .Values.speaker.frr.metricsPort }}/ + {{- if .Values.prometheus.speakerMetricsTLSSecret }} + - --tls-private-key-file=/etc/metrics/tls.key + - --tls-cert-file=/etc/metrics/tls.crt + {{- end }} + ports: + - containerPort: {{ .Values.speaker.frr.secureMetricsPort }} + name: frrmetricshttps + env: + - name: METALLB_HOST + valueFrom: + fieldRef: + fieldPath: status.hostIP + resources: + requests: + cpu: 10m + memory: 20Mi + terminationMessagePolicy: FallbackToLogsOnError + {{- if .Values.prometheus.speakerMetricsTLSSecret }} + volumeMounts: + - name: metrics-certs + mountPath: /etc/metrics + readOnly: true + {{- end }} + {{ end }} + {{- end }} + {{- if .Values.speaker.extraContainers }} + {{- toYaml .Values.speaker.extraContainers | nindent 6 }} + {{- end }} + nodeSelector: + "kubernetes.io/os": linux + {{- with .Values.speaker.nodeSelector }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.speaker.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if or .Values.speaker.tolerateMaster .Values.speaker.tolerations }} + tolerations: + {{- if .Values.speaker.tolerateMaster }} + - key: node-role.kubernetes.io/master + effect: NoSchedule + operator: Exists + - key: node-role.kubernetes.io/control-plane + effect: NoSchedule + operator: Exists + {{- end }} + {{- with .Values.speaker.tolerations }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- end }} + {{- with .Values.speaker.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} +{{- end }} diff --git a/metallb-chart/templates/webhooks.yaml b/metallb-chart/templates/webhooks.yaml new file mode 100644 index 0000000..3cdac01 --- /dev/null +++ b/metallb-chart/templates/webhooks.yaml @@ -0,0 +1,150 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: metallb-webhook-configuration + labels: + {{- include "metallb.labels" . | nindent 4 }} +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta2-bgppeer + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: bgppeervalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta2 + operations: + - CREATE + - UPDATE + resources: + - bgppeers + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta1-ipaddresspool + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: ipaddresspoolvalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - ipaddresspools + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta1-bgpadvertisement + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: bgpadvertisementvalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - bgpadvertisements + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta1-community + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: communityvalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - communities + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta1-bfdprofile + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: bfdprofilevalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - DELETE + resources: + - bfdprofiles + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: metallb-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-metallb-io-v1beta1-l2advertisement + failurePolicy: {{ .Values.crds.validationFailurePolicy }} + name: l2advertisementvalidationwebhook.metallb.io + rules: + - apiGroups: + - metallb.io + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - l2advertisements + sideEffects: None +--- +apiVersion: v1 +kind: Service +metadata: + name: metallb-webhook-service + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} +spec: + ports: + - port: 443 + targetPort: 9443 + selector: + {{- include "metallb.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: controller +--- +apiVersion: v1 +kind: Secret +metadata: + name: metallb-webhook-cert + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "metallb.labels" . | nindent 4 }} diff --git a/sriov-crd-chart/templates.obscpio b/sriov-crd-chart/templates.obscpio deleted file mode 100644 index 3995b9f..0000000 Binary files a/sriov-crd-chart/templates.obscpio and /dev/null differ diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_ovsnetworks.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_ovsnetworks.yaml new file mode 100644 index 0000000..7e7d9ba --- /dev/null +++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_ovsnetworks.yaml @@ -0,0 +1,105 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: ovsnetworks.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: OVSNetwork + listKind: OVSNetworkList + plural: ovsnetworks + singular: ovsnetwork + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: OVSNetwork is the Schema for the ovsnetworks 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: OVSNetworkSpec defines the desired state of OVSNetwork + properties: + bridge: + description: |- + name of the OVS bridge, if not set OVS will automatically select bridge + based on VF PCI address + type: string + capabilities: + description: |- + Capabilities to be configured for this network. + Capabilities supported: (mac|ips), e.g. '{"mac": true}' + type: string + interfaceType: + description: The type of interface on ovs. + type: string + ipam: + description: IPAM configuration to be used for this network. + type: string + metaPlugins: + description: MetaPluginsConfig configuration to be used in order to + chain metaplugins + type: string + mtu: + description: Mtu for the OVS port + type: integer + networkNamespace: + description: Namespace of the NetworkAttachmentDefinition custom resource + type: string + resourceName: + description: OVS Network device plugin endpoint resource name + type: string + trunk: + description: Trunk configuration for the OVS port + items: + description: TrunkConfig contains configuration for bridge trunk + properties: + id: + maximum: 4095 + minimum: 0 + type: integer + maxID: + maximum: 4095 + minimum: 0 + type: integer + minID: + maximum: 4095 + minimum: 0 + type: integer + type: object + type: array + vlan: + description: Vlan to assign for the OVS port + maximum: 4095 + minimum: 0 + type: integer + required: + - resourceName + type: object + status: + description: OVSNetworkStatus defines the observed state of OVSNetwork + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovibnetworks.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovibnetworks.yaml new file mode 100644 index 0000000..8a4f88c --- /dev/null +++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovibnetworks.yaml @@ -0,0 +1,78 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: sriovibnetworks.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovIBNetwork + listKind: SriovIBNetworkList + plural: sriovibnetworks + singular: sriovibnetwork + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: SriovIBNetwork is the Schema for the sriovibnetworks 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: SriovIBNetworkSpec defines the desired state of SriovIBNetwork + properties: + capabilities: + description: |- + Capabilities to be configured for this network. + Capabilities supported: (infinibandGUID), e.g. '{"infinibandGUID": true}' + type: string + ipam: + description: IPAM configuration to be used for this network. + type: string + linkState: + description: VF link state (enable|disable|auto) + enum: + - auto + - enable + - disable + type: string + metaPlugins: + description: |- + MetaPluginsConfig configuration to be used in order to chain metaplugins to the sriov interface returned + by the operator. + type: string + networkNamespace: + description: Namespace of the NetworkAttachmentDefinition custom resource + type: string + resourceName: + description: SRIOV Network device plugin endpoint resource name + type: string + required: + - resourceName + type: object + status: + description: SriovIBNetworkStatus defines the observed state of SriovIBNetwork + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml new file mode 100644 index 0000000..47aacdd --- /dev/null +++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml @@ -0,0 +1,209 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: sriovnetworknodepolicies.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovNetworkNodePolicy + listKind: SriovNetworkNodePolicyList + plural: sriovnetworknodepolicies + singular: sriovnetworknodepolicy + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: SriovNetworkNodePolicy is the Schema for the sriovnetworknodepolicies + 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: SriovNetworkNodePolicySpec defines the desired state of SriovNetworkNodePolicy + properties: + bridge: + description: |- + contains bridge configuration for matching PFs, + valid only for eSwitchMode==switchdev + properties: + ovs: + description: contains configuration for the OVS bridge, + properties: + bridge: + description: contains bridge level settings + properties: + datapathType: + description: configure datapath_type field in the Bridge + table in OVSDB + type: string + externalIDs: + additionalProperties: + type: string + description: IDs to inject to external_ids field in the + Bridge table in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: additional options to inject to other_config + field in the bridge table in OVSDB + type: object + type: object + uplink: + description: contains settings for uplink (PF) + properties: + interface: + description: contains settings for PF interface in the + OVS bridge + properties: + externalIDs: + additionalProperties: + type: string + description: external_ids field in the Interface table + in OVSDB + type: object + options: + additionalProperties: + type: string + description: options field in the Interface table + in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: other_config field in the Interface table + in OVSDB + type: object + type: + description: type field in the Interface table in + OVSDB + type: string + type: object + type: object + type: object + type: object + deviceType: + default: netdevice + description: The driver type for configured VFs. Allowed value "netdevice", + "vfio-pci". Defaults to netdevice. + enum: + - netdevice + - vfio-pci + type: string + eSwitchMode: + description: NIC Device Mode. Allowed value "legacy","switchdev". + enum: + - legacy + - switchdev + type: string + excludeTopology: + description: Exclude device's NUMA node when advertising this resource + by SRIOV network device plugin. Default to false. + type: boolean + externallyManaged: + description: don't create the virtual function only allocated them + to the device plugin. Defaults to false. + type: boolean + isRdma: + description: RDMA mode. Defaults to false. + type: boolean + linkType: + description: NIC Link Type. Allowed value "eth", "ETH", "ib", and + "IB". + enum: + - eth + - ETH + - ib + - IB + type: string + mtu: + description: MTU of VF + minimum: 1 + type: integer + needVhostNet: + description: mount vhost-net device. Defaults to false. + type: boolean + nicSelector: + description: NicSelector selects the NICs to be configured + properties: + deviceID: + description: The device hex code of SR-IoV device. Allowed value + "0d58", "1572", "158b", "1013", "1015", "1017", "101b". + type: string + netFilter: + description: Infrastructure Networking selection filter. Allowed + value "openstack/NetworkID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + type: string + pfNames: + description: Name of SR-IoV PF. + items: + type: string + type: array + rootDevices: + description: PCI address of SR-IoV PF. + items: + type: string + type: array + vendor: + description: The vendor hex code of SR-IoV device. Allowed value + "8086", "15b3". + type: string + type: object + nodeSelector: + additionalProperties: + type: string + description: NodeSelector selects the nodes to be configured + type: object + numVfs: + description: Number of VFs for each PF + minimum: 0 + type: integer + priority: + description: Priority of the policy, higher priority policies can + override lower ones. + maximum: 99 + minimum: 0 + type: integer + resourceName: + description: SRIOV Network device plugin endpoint resource name + type: string + vdpaType: + description: VDPA device type. Allowed value "virtio", "vhost" + enum: + - virtio + - vhost + type: string + required: + - nicSelector + - nodeSelector + - numVfs + - resourceName + type: object + status: + description: SriovNetworkNodePolicyStatus defines the observed state of + SriovNetworkNodePolicy + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodestates.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodestates.yaml new file mode 100644 index 0000000..6ed2486 --- /dev/null +++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworknodestates.yaml @@ -0,0 +1,343 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: sriovnetworknodestates.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovNetworkNodeState + listKind: SriovNetworkNodeStateList + plural: sriovnetworknodestates + singular: sriovnetworknodestate + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.syncStatus + name: Sync Status + type: string + - jsonPath: .metadata.annotations.sriovnetwork\.openshift\.io/desired-state + name: Desired Sync State + type: string + - jsonPath: .metadata.annotations.sriovnetwork\.openshift\.io/current-state + name: Current Sync State + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: SriovNetworkNodeState is the Schema for the sriovnetworknodestates + 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: SriovNetworkNodeStateSpec defines the desired state of SriovNetworkNodeState + properties: + bridges: + description: Bridges contains list of bridges + properties: + ovs: + items: + description: OVSConfigExt contains configuration for the concrete + OVS bridge + properties: + bridge: + description: bridge-level configuration for the bridge + properties: + datapathType: + description: configure datapath_type field in the Bridge + table in OVSDB + type: string + externalIDs: + additionalProperties: + type: string + description: IDs to inject to external_ids field in + the Bridge table in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: additional options to inject to other_config + field in the bridge table in OVSDB + type: object + type: object + name: + description: name of the bridge + type: string + uplinks: + description: |- + uplink-level bridge configuration for each uplink(PF). + currently must contain only one element + items: + description: OVSUplinkConfigExt contains configuration + for the concrete OVS uplink(PF) + properties: + interface: + description: configuration from the Interface OVS + table for the PF + properties: + externalIDs: + additionalProperties: + type: string + description: external_ids field in the Interface + table in OVSDB + type: object + options: + additionalProperties: + type: string + description: options field in the Interface table + in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: other_config field in the Interface + table in OVSDB + type: object + type: + description: type field in the Interface table + in OVSDB + type: string + type: object + name: + description: name of the PF interface + type: string + pciAddress: + description: pci address of the PF + type: string + required: + - pciAddress + type: object + type: array + required: + - name + type: object + type: array + type: object + interfaces: + items: + properties: + eSwitchMode: + type: string + externallyManaged: + type: boolean + linkType: + type: string + mtu: + type: integer + name: + type: string + numVfs: + type: integer + pciAddress: + type: string + vfGroups: + items: + properties: + deviceType: + type: string + isRdma: + type: boolean + mtu: + type: integer + policyName: + type: string + resourceName: + type: string + vdpaType: + type: string + vfRange: + type: string + type: object + type: array + required: + - pciAddress + type: object + type: array + type: object + status: + description: SriovNetworkNodeStateStatus defines the observed state of + SriovNetworkNodeState + properties: + bridges: + description: Bridges contains list of bridges + properties: + ovs: + items: + description: OVSConfigExt contains configuration for the concrete + OVS bridge + properties: + bridge: + description: bridge-level configuration for the bridge + properties: + datapathType: + description: configure datapath_type field in the Bridge + table in OVSDB + type: string + externalIDs: + additionalProperties: + type: string + description: IDs to inject to external_ids field in + the Bridge table in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: additional options to inject to other_config + field in the bridge table in OVSDB + type: object + type: object + name: + description: name of the bridge + type: string + uplinks: + description: |- + uplink-level bridge configuration for each uplink(PF). + currently must contain only one element + items: + description: OVSUplinkConfigExt contains configuration + for the concrete OVS uplink(PF) + properties: + interface: + description: configuration from the Interface OVS + table for the PF + properties: + externalIDs: + additionalProperties: + type: string + description: external_ids field in the Interface + table in OVSDB + type: object + options: + additionalProperties: + type: string + description: options field in the Interface table + in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: other_config field in the Interface + table in OVSDB + type: object + type: + description: type field in the Interface table + in OVSDB + type: string + type: object + name: + description: name of the PF interface + type: string + pciAddress: + description: pci address of the PF + type: string + required: + - pciAddress + type: object + type: array + required: + - name + type: object + type: array + type: object + interfaces: + items: + properties: + Vfs: + items: + properties: + Vlan: + type: integer + assigned: + type: string + deviceID: + type: string + driver: + type: string + guid: + type: string + mac: + type: string + mtu: + type: integer + name: + type: string + pciAddress: + type: string + representorName: + type: string + vdpaType: + type: string + vendor: + type: string + vfID: + type: integer + required: + - pciAddress + - vfID + type: object + type: array + deviceID: + type: string + driver: + type: string + eSwitchMode: + type: string + externallyManaged: + type: boolean + linkAdminState: + type: string + linkSpeed: + type: string + linkType: + type: string + mac: + type: string + mtu: + type: integer + name: + type: string + netFilter: + type: string + numVfs: + type: integer + pciAddress: + type: string + totalvfs: + type: integer + vendor: + type: string + required: + - pciAddress + type: object + type: array + lastSyncError: + type: string + syncStatus: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworkpoolconfigs.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworkpoolconfigs.yaml new file mode 100644 index 0000000..502e0eb --- /dev/null +++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworkpoolconfigs.yaml @@ -0,0 +1,123 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: sriovnetworkpoolconfigs.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovNetworkPoolConfig + listKind: SriovNetworkPoolConfigList + plural: sriovnetworkpoolconfigs + singular: sriovnetworkpoolconfig + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: SriovNetworkPoolConfig is the Schema for the sriovnetworkpoolconfigs + 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: SriovNetworkPoolConfigSpec defines the desired state of SriovNetworkPoolConfig + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: |- + maxUnavailable defines either an integer number or percentage + of nodes in the pool that can go Unavailable during an update. + + + A value larger than 1 will mean multiple nodes going unavailable during + the update, which may affect your workload stress on the remaining nodes. + Drain will respect Pod Disruption Budgets (PDBs) such as etcd quorum guards, + even if maxUnavailable is greater than one. + x-kubernetes-int-or-string: true + nodeSelector: + description: nodeSelector specifies a label selector for Nodes + 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 + ovsHardwareOffloadConfig: + description: OvsHardwareOffloadConfig describes the OVS HWOL configuration + for selected Nodes + properties: + name: + description: |- + Name is mandatory and must be unique. + On Kubernetes: + Name is the name of OvsHardwareOffloadConfig + On OpenShift: + Name is the name of MachineConfigPool to be enabled with OVS hardware offload + type: string + type: object + type: object + status: + description: SriovNetworkPoolConfigStatus defines the observed state of + SriovNetworkPoolConfig + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworks.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworks.yaml new file mode 100644 index 0000000..cd807f9 --- /dev/null +++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovnetworks.yaml @@ -0,0 +1,136 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: sriovnetworks.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovNetwork + listKind: SriovNetworkList + plural: sriovnetworks + singular: sriovnetwork + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: SriovNetwork is the Schema for the sriovnetworks 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: SriovNetworkSpec defines the desired state of SriovNetwork + properties: + capabilities: + description: |- + Capabilities to be configured for this network. + Capabilities supported: (mac|ips), e.g. '{"mac": true}' + type: string + ipam: + description: IPAM configuration to be used for this network. + type: string + linkState: + description: VF link state (enable|disable|auto) + enum: + - auto + - enable + - disable + type: string + logFile: + description: |- + LogFile sets the log file of the SRIOV CNI plugin logs. If unset (default), this will log to stderr and thus + to multus and container runtime logs. + type: string + logLevel: + default: info + description: |- + LogLevel sets the log level of the SRIOV CNI plugin - either of panic, error, warning, info, debug. Defaults + to info if left blank. + enum: + - panic + - error + - warning + - info + - debug + - "" + type: string + maxTxRate: + description: Maximum tx rate, in Mbps, for the VF. Defaults to 0 (no + rate limiting) + minimum: 0 + type: integer + metaPlugins: + description: |- + MetaPluginsConfig configuration to be used in order to chain metaplugins to the sriov interface returned + by the operator. + type: string + minTxRate: + description: Minimum tx rate, in Mbps, for the VF. Defaults to 0 (no + rate limiting). min_tx_rate should be <= max_tx_rate. + minimum: 0 + type: integer + networkNamespace: + description: Namespace of the NetworkAttachmentDefinition custom resource + type: string + resourceName: + description: SRIOV Network device plugin endpoint resource name + type: string + spoofChk: + description: VF spoof check, (on|off) + enum: + - "on" + - "off" + type: string + trust: + description: VF trust mode (on|off) + enum: + - "on" + - "off" + type: string + vlan: + description: VLAN ID to assign for the VF. Defaults to 0. + maximum: 4096 + minimum: 0 + type: integer + vlanProto: + description: VLAN proto to assign for the VF. Defaults to 802.1q. + enum: + - 802.1q + - 802.1Q + - 802.1ad + - 802.1AD + type: string + vlanQoS: + description: VLAN QoS ID to assign for the VF. Defaults to 0. + maximum: 7 + minimum: 0 + type: integer + required: + - resourceName + type: object + status: + description: SriovNetworkStatus defines the observed state of SriovNetwork + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovoperatorconfigs.yaml b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovoperatorconfigs.yaml new file mode 100644 index 0000000..49d5429 --- /dev/null +++ b/sriov-crd-chart/templates/sriovnetwork.openshift.io_sriovoperatorconfigs.yaml @@ -0,0 +1,114 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: sriovoperatorconfigs.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovOperatorConfig + listKind: SriovOperatorConfigList + plural: sriovoperatorconfigs + singular: sriovoperatorconfig + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: SriovOperatorConfig is the Schema for the sriovoperatorconfigs + 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: SriovOperatorConfigSpec defines the desired state of SriovOperatorConfig + properties: + configDaemonNodeSelector: + additionalProperties: + type: string + description: NodeSelector selects the nodes to be configured + type: object + configurationMode: + description: |- + Flag to enable the sriov-network-config-daemon to use a systemd service to configure SR-IOV devices on boot + Default mode: daemon + enum: + - daemon + - systemd + type: string + disableDrain: + description: Flag to disable nodes drain during debugging + type: boolean + disablePlugins: + description: DisablePlugins is a list of sriov-network-config-daemon + plugins to disable + items: + description: PluginNameValue defines the plugin name + enum: + - mellanox + type: string + type: array + enableInjector: + description: Flag to control whether the network resource injector + webhook shall be deployed + type: boolean + enableOperatorWebhook: + description: Flag to control whether the operator admission controller + webhook shall be deployed + type: boolean + enableOvsOffload: + description: Flag to enable OVS hardware offload. Set to 'true' to + provision switchdev-configuration.service and enable OpenvSwitch + hw-offload on nodes. + type: boolean + featureGates: + additionalProperties: + type: boolean + description: FeatureGates to enable experimental features + type: object + logLevel: + description: Flag to control the log verbose level of the operator. + Set to '0' to show only the basic logs. And set to '2' to show all + the available logs. + maximum: 2 + minimum: 0 + type: integer + useCDI: + description: Flag to enable Container Device Interface mode for SR-IOV + Network Device Plugin + type: boolean + type: object + status: + description: SriovOperatorConfigStatus defines the observed state of SriovOperatorConfig + properties: + injector: + description: Show the runtime status of the network resource injector + webhook + type: string + operatorWebhook: + description: Show the runtime status of the operator admission controller + webhook + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/sriov-network-operator-chart/charts.obscpio b/sriov-network-operator-chart/charts.obscpio deleted file mode 100644 index 829a2b4..0000000 Binary files a/sriov-network-operator-chart/charts.obscpio and /dev/null differ diff --git a/sriov-network-operator-chart/charts/sriov-nfd/.helmignore b/sriov-network-operator-chart/charts/sriov-nfd/.helmignore new file mode 100644 index 0000000..1b9a9cc --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/sriov-network-operator-chart/charts/sriov-nfd/Chart.yaml b/sriov-network-operator-chart/charts/sriov-nfd/Chart.yaml new file mode 100644 index 0000000..5415b0d --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/Chart.yaml @@ -0,0 +1,14 @@ +apiVersion: v2 +appVersion: v0.15.6 +description: Detects hardware features available on each node in a Kubernetes cluster, + and advertises those features using node labels +home: https://github.com/kubernetes-sigs/node-feature-discovery +keywords: +- feature-discovery +- feature-detection +- node-labels +name: sriov-nfd +sources: +- https://github.com/kubernetes-sigs/node-feature-discovery +type: application +version: 0.15.6 diff --git a/sriov-network-operator-chart/charts/sriov-nfd/README.md b/sriov-network-operator-chart/charts/sriov-nfd/README.md new file mode 100644 index 0000000..9aa6c75 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/README.md @@ -0,0 +1,10 @@ +# Node Feature Discovery + +Node Feature Discovery (NFD) is a Kubernetes add-on for detecting hardware +features and system configuration. Detected features are advertised as node +labels. NFD provides flexible configuration and extension points for a wide +range of vendor and application specific node labeling needs. + +See +[NFD documentation](https://kubernetes-sigs.github.io/node-feature-discovery/v0.15/deployment/helm.html) +for deployment instructions. diff --git a/sriov-network-operator-chart/charts/sriov-nfd/crds/nfd-api-crds.yaml b/sriov-network-operator-chart/charts/sriov-nfd/crds/nfd-api-crds.yaml new file mode 100644 index 0000000..0339f35 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/crds/nfd-api-crds.yaml @@ -0,0 +1,426 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + name: nodefeatures.nfd.k8s-sigs.io +spec: + group: nfd.k8s-sigs.io + names: + kind: NodeFeature + listKind: NodeFeatureList + plural: nodefeatures + singular: nodefeature + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: NodeFeature resource holds the features discovered for one node + in the cluster. + 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: NodeFeatureSpec describes a NodeFeature object. + properties: + features: + description: Features is the full "raw" features data that has been + discovered. + properties: + attributes: + additionalProperties: + description: AttributeFeatureSet is a set of features having + string value. + properties: + elements: + additionalProperties: + type: string + type: object + required: + - elements + type: object + description: Attributes contains all the attribute-type features + of the node. + type: object + flags: + additionalProperties: + description: FlagFeatureSet is a set of simple features only + containing names without values. + properties: + elements: + additionalProperties: + description: Nil is a dummy empty struct for protobuf + compatibility + type: object + type: object + required: + - elements + type: object + description: Flags contains all the flag-type features of the + node. + type: object + instances: + additionalProperties: + description: InstanceFeatureSet is a set of features each of + which is an instance having multiple attributes. + properties: + elements: + items: + description: InstanceFeature represents one instance of + a complex features, e.g. a device. + properties: + attributes: + additionalProperties: + type: string + type: object + required: + - attributes + type: object + type: array + required: + - elements + type: object + description: Instances contains all the instance-type features + of the node. + type: object + type: object + labels: + additionalProperties: + type: string + description: Labels is the set of node labels that are requested to + be created. + type: object + type: object + required: + - spec + type: object + served: true + storage: true +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.1 + name: nodefeaturerules.nfd.k8s-sigs.io +spec: + group: nfd.k8s-sigs.io + names: + kind: NodeFeatureRule + listKind: NodeFeatureRuleList + plural: nodefeaturerules + shortNames: + - nfr + 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: + annotations: + additionalProperties: + type: string + description: Annotations to create if the rule matches. + type: object + extendedResources: + additionalProperties: + type: string + description: ExtendedResources to create if the rule matches. + type: object + 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 ([=]) + 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: + description: Feature is the name of the feature + set to match against. + 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. + 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: MatchExpressions is the set of per-element + expressions evaluated. These match against the + value of the specified elements. + type: object + matchName: + description: MatchName in an expression that is + matched against the name of each element in the + feature set. + 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 + required: + - feature + 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: + description: Feature is the name of the feature set to + match against. + 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. + 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: MatchExpressions is the set of per-element + expressions evaluated. These match against the value + of the specified elements. + type: object + matchName: + description: MatchName in an expression that is matched + against the name of each element in the feature set. + 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 + required: + - feature + type: object + type: array + name: + description: Name of the rule. + type: string + taints: + description: Taints to create if the rule matches. + items: + description: The node this Taint is attached to has the "effect" + on any pod that does not tolerate the Taint. + properties: + effect: + description: Required. The effect of the taint on pods + that do not tolerate the taint. Valid effects are NoSchedule, + PreferNoSchedule and NoExecute. + type: string + key: + description: Required. The taint key to be applied to + a node. + type: string + timeAdded: + description: TimeAdded represents the time at which the + taint was added. It is only written for NoExecute taints. + format: date-time + type: string + value: + description: The taint value corresponding to the taint + key. + type: string + required: + - effect + - key + type: object + type: array + 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 ([=]) + separated by newlines. + type: string + required: + - name + type: object + type: array + required: + - rules + type: object + required: + - spec + type: object + served: true + storage: true diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/_helpers.tpl b/sriov-network-operator-chart/charts/sriov-nfd/templates/_helpers.tpl new file mode 100644 index 0000000..f8b1e30 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/_helpers.tpl @@ -0,0 +1,107 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "node-feature-discovery.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "node-feature-discovery.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "node-feature-discovery.namespace" -}} + {{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "node-feature-discovery.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "node-feature-discovery.labels" -}} +helm.sh/chart: {{ include "node-feature-discovery.chart" . }} +{{ include "node-feature-discovery.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "node-feature-discovery.selectorLabels" -}} +app.kubernetes.io/name: {{ include "node-feature-discovery.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account which the nfd master will use +*/}} +{{- define "node-feature-discovery.master.serviceAccountName" -}} +{{- if .Values.master.serviceAccount.create -}} + {{ default (include "node-feature-discovery.fullname" .) .Values.master.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.master.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account which the nfd worker will use +*/}} +{{- define "node-feature-discovery.worker.serviceAccountName" -}} +{{- if .Values.worker.serviceAccount.create -}} + {{ default (printf "%s-worker" (include "node-feature-discovery.fullname" .)) .Values.worker.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.worker.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account which topologyUpdater will use +*/}} +{{- define "node-feature-discovery.topologyUpdater.serviceAccountName" -}} +{{- if .Values.topologyUpdater.serviceAccount.create -}} + {{ default (printf "%s-topology-updater" (include "node-feature-discovery.fullname" .)) .Values.topologyUpdater.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.topologyUpdater.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account which nfd-gc will use +*/}} +{{- define "node-feature-discovery.gc.serviceAccountName" -}} +{{- if .Values.gc.serviceAccount.create -}} + {{ default (printf "%s-gc" (include "node-feature-discovery.fullname" .)) .Values.gc.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.gc.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-certs.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-certs.yaml new file mode 100644 index 0000000..43a647a --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-certs.yaml @@ -0,0 +1,68 @@ +{{- if .Values.tls.certManager }} +{{- if .Values.master.enable }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: nfd-master-cert + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + secretName: nfd-master-cert + subject: + organizations: + - node-feature-discovery + commonName: nfd-master + dnsNames: + # must match the service name + - {{ include "node-feature-discovery.fullname" . }}-master + # first one is configured for use by the worker; below are for completeness + - {{ include "node-feature-discovery.fullname" . }}-master.{{ include "node-feature-discovery.namespace" . }}.svc + - {{ include "node-feature-discovery.fullname" . }}-master.{{ include "node-feature-discovery.namespace" . }}.svc.cluster.local + issuerRef: + name: nfd-ca-issuer + kind: Issuer + group: cert-manager.io +{{- end }} +--- +{{- if .Values.worker.enable }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: nfd-worker-cert + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + secretName: nfd-worker-cert + subject: + organizations: + - node-feature-discovery + commonName: nfd-worker + dnsNames: + - {{ include "node-feature-discovery.fullname" . }}-worker.{{ include "node-feature-discovery.namespace" . }}.svc.cluster.local + issuerRef: + name: nfd-ca-issuer + kind: Issuer + group: cert-manager.io +{{- end }} + +{{- if .Values.topologyUpdater.enable }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: nfd-topology-updater-cert + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + secretName: nfd-topology-updater-cert + subject: + organizations: + - node-feature-discovery + commonName: nfd-topology-updater + dnsNames: + - {{ include "node-feature-discovery.fullname" . }}-topology-updater.{{ include "node-feature-discovery.namespace" . }}.svc.cluster.local + issuerRef: + name: nfd-ca-issuer + kind: Issuer + group: cert-manager.io +{{- end }} + +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-issuer.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-issuer.yaml new file mode 100644 index 0000000..742ebe1 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/cert-manager-issuer.yaml @@ -0,0 +1,42 @@ +{{- if .Values.tls.certManager }} +# See https://cert-manager.io/docs/configuration/selfsigned/#bootstrapping-ca-issuers +# - Create a self signed issuer +# - Use this to create a CA cert +# - Use this to now create a CA issuer +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: nfd-ca-bootstrap + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + selfSigned: {} + +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: nfd-ca-cert + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + isCA: true + secretName: nfd-ca-cert + subject: + organizations: + - node-feature-discovery + commonName: nfd-ca-cert + issuerRef: + name: nfd-ca-bootstrap + kind: Issuer + group: cert-manager.io + +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: nfd-ca-issuer + namespace: {{ include "node-feature-discovery.namespace" . }} +spec: + ca: + secretName: nfd-ca-cert +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrole.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrole.yaml new file mode 100644 index 0000000..8853613 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrole.yaml @@ -0,0 +1,119 @@ +{{- if and .Values.master.enable .Values.master.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "node-feature-discovery.fullname" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - nodes + - nodes/status + verbs: + - get + - patch + - update + - list +- apiGroups: + - nfd.k8s-sigs.io + resources: + - nodefeatures + - nodefeaturerules + verbs: + - get + - list + - watch +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create +- apiGroups: + - coordination.k8s.io + resources: + - leases + resourceNames: + - "nfd-master.nfd.kubernetes.io" + verbs: + - get + - update +{{- end }} + +{{- if and .Values.topologyUpdater.enable .Values.topologyUpdater.rbac.create }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list +- apiGroups: + - "" + resources: + - nodes/proxy + verbs: + - get +- apiGroups: + - "" + resources: + - pods + verbs: + - get +- apiGroups: + - topology.node.k8s.io + resources: + - noderesourcetopologies + verbs: + - create + - get + - update +{{- end }} + +{{- if and .Values.gc.enable .Values.gc.rbac.create (or .Values.enableNodeFeatureApi .Values.topologyUpdater.enable) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-gc + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - nodes + verbs: + - list + - watch +- apiGroups: + - "" + resources: + - nodes/proxy + verbs: + - get +- apiGroups: + - topology.node.k8s.io + resources: + - noderesourcetopologies + verbs: + - delete + - list +- apiGroups: + - nfd.k8s-sigs.io + resources: + - nodefeatures + verbs: + - delete + - list +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrolebinding.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrolebinding.yaml new file mode 100644 index 0000000..1d49ec5 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/clusterrolebinding.yaml @@ -0,0 +1,52 @@ +{{- if and .Values.master.enable .Values.master.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "node-feature-discovery.fullname" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "node-feature-discovery.fullname" . }} +subjects: +- kind: ServiceAccount + name: {{ include "node-feature-discovery.master.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} +{{- end }} + +{{- if and .Values.topologyUpdater.enable .Values.topologyUpdater.rbac.create }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater +subjects: +- kind: ServiceAccount + name: {{ include "node-feature-discovery.topologyUpdater.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} +{{- end }} + +{{- if and .Values.gc.enable .Values.gc.rbac.create (or .Values.enableNodeFeatureApi .Values.topologyUpdater.enable) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-gc + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "node-feature-discovery.fullname" . }}-gc +subjects: +- kind: ServiceAccount + name: {{ include "node-feature-discovery.gc.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/master.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/master.yaml new file mode 100644 index 0000000..19b543a --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/master.yaml @@ -0,0 +1,145 @@ +{{- if .Values.master.enable }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-master + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + role: master + {{- with .Values.master.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.master.replicaCount }} + selector: + matchLabels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 6 }} + role: master + template: + metadata: + labels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 8 }} + role: master + {{- with .Values.master.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "node-feature-discovery.master.serviceAccountName" . }} + enableServiceLinks: false + securityContext: + {{- toYaml .Values.master.podSecurityContext | nindent 8 }} + containers: + - name: master + securityContext: + {{- toYaml .Values.master.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + livenessProbe: + grpc: + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 10 + readinessProbe: + grpc: + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 10 + failureThreshold: 10 + ports: + - containerPort: {{ .Values.master.port | default "8080" }} + name: grpc + - containerPort: {{ .Values.master.metricsPort | default "8081" }} + name: metrics + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + command: + - "nfd-master" + resources: + {{- toYaml .Values.master.resources | nindent 12 }} + args: + {{- if .Values.master.instance | empty | not }} + - "-instance={{ .Values.master.instance }}" + {{- end }} + {{- if not .Values.enableNodeFeatureApi }} + - "-port={{ .Values.master.port | default "8080" }}" + - "-enable-nodefeature-api=false" + {{- else if gt (int .Values.master.replicaCount) 1 }} + - "-enable-leader-election" + {{- end }} + {{- if .Values.master.extraLabelNs | empty | not }} + - "-extra-label-ns={{- join "," .Values.master.extraLabelNs }}" + {{- end }} + {{- if .Values.master.denyLabelNs | empty | not }} + - "-deny-label-ns={{- join "," .Values.master.denyLabelNs }}" + {{- end }} + {{- if .Values.master.resourceLabels | empty | not }} + - "-resource-labels={{- join "," .Values.master.resourceLabels }}" + {{- end }} + {{- if .Values.master.enableTaints }} + - "-enable-taints" + {{- end }} + {{- if .Values.master.crdController | kindIs "invalid" | not }} + - "-crd-controller={{ .Values.master.crdController }}" + {{- else }} + ## By default, disable crd controller for other than the default instances + - "-crd-controller={{ .Values.master.instance | empty }}" + {{- end }} + {{- if .Values.master.featureRulesController | kindIs "invalid" | not }} + - "-featurerules-controller={{ .Values.master.featureRulesController }}" + {{- end }} + {{- if .Values.master.resyncPeriod }} + - "-resync-period={{ .Values.master.resyncPeriod }}" + {{- end }} + {{- if .Values.master.nfdApiParallelism | empty | not }} + - "-nfd-api-parallelism={{ .Values.master.nfdApiParallelism }}" + {{- end }} + {{- if .Values.tls.enable }} + - "-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" + {{- end }} + - "-metrics={{ .Values.master.metricsPort | default "8081" }}" + volumeMounts: + {{- if .Values.tls.enable }} + - name: nfd-master-cert + mountPath: "/etc/kubernetes/node-feature-discovery/certs" + readOnly: true + {{- end }} + - name: nfd-master-conf + mountPath: "/etc/kubernetes/node-feature-discovery" + readOnly: true + volumes: + {{- if .Values.tls.enable }} + - name: nfd-master-cert + secret: + secretName: nfd-master-cert + {{- end }} + - name: nfd-master-conf + configMap: + name: {{ include "node-feature-discovery.fullname" . }}-master-conf + items: + - key: nfd-master.conf + path: nfd-master.conf + {{- with .Values.master.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.master.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.master.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-gc.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-gc.yaml new file mode 100644 index 0000000..641202b --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-gc.yaml @@ -0,0 +1,77 @@ +{{- if and .Values.gc.enable (or .Values.enableNodeFeatureApi .Values.topologyUpdater.enable) -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-gc + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + role: gc + {{- with .Values.gc.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.gc.replicaCount | default 1 }} + selector: + matchLabels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 6 }} + role: gc + template: + metadata: + labels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 8 }} + role: gc + {{- with .Values.gc.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "node-feature-discovery.gc.serviceAccountName" . }} + dnsPolicy: ClusterFirstWithHostNet + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.gc.podSecurityContext | nindent 8 }} + containers: + - name: gc + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + command: + - "nfd-gc" + args: + {{- if .Values.gc.interval | empty | not }} + - "-gc-interval={{ .Values.gc.interval }}" + {{- end }} + resources: + {{- toYaml .Values.gc.resources | nindent 12 }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: [ "ALL" ] + readOnlyRootFilesystem: true + runAsNonRoot: true + ports: + - name: metrics + containerPort: {{ .Values.gc.metricsPort | default "8081"}} + + {{- with .Values.gc.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.gc.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.gc.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-master-conf.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-master-conf.yaml new file mode 100644 index 0000000..be92601 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-master-conf.yaml @@ -0,0 +1,12 @@ +{{- if .Values.master.enable }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-master-conf + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +data: + nfd-master.conf: |- + {{- .Values.master.config | toYaml | nindent 4 }} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-topologyupdater-conf.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-topologyupdater-conf.yaml new file mode 100644 index 0000000..1680d69 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-topologyupdater-conf.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater-conf + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +data: + nfd-topology-updater.conf: |- + {{- .Values.topologyUpdater.config | toYaml | nindent 4 }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-worker-conf.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-worker-conf.yaml new file mode 100644 index 0000000..3e1148d --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/nfd-worker-conf.yaml @@ -0,0 +1,12 @@ +{{- if .Values.worker.enable }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-worker-conf + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +data: + nfd-worker.conf: |- + {{- .Values.worker.config | toYaml | nindent 4 }} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/prometheus.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/prometheus.yaml new file mode 100644 index 0000000..cbc8f85 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/prometheus.yaml @@ -0,0 +1,26 @@ +{{- if .Values.prometheus.enable }} +# Prometheus Monitor Service (Metrics) +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: {{ include "node-feature-discovery.fullname" . }} + labels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 4 }} + {{- with .Values.prometheus.labels }} + {{ toYaml . | nindent 4 }} + {{- end }} +spec: + podMetricsEndpoints: + - honorLabels: true + interval: 10s + path: /metrics + port: metrics + scheme: http + namespaceSelector: + matchNames: + - {{ include "node-feature-discovery.namespace" . }} + selector: + matchExpressions: + - {key: app.kubernetes.io/instance, operator: In, values: ["{{ .Release.Name }}"]} + - {key: app.kubernetes.io/name, operator: In, values: ["{{ include "node-feature-discovery.name" . }}"]} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/role.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/role.yaml new file mode 100644 index 0000000..06ca73e --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/role.yaml @@ -0,0 +1,24 @@ +{{- if and .Values.worker.enable .Values.worker.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-worker + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +rules: +- apiGroups: + - nfd.k8s-sigs.io + resources: + - nodefeatures + verbs: + - create + - get + - update +- apiGroups: + - "" + resources: + - pods + verbs: + - get +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/rolebinding.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/rolebinding.yaml new file mode 100644 index 0000000..46ac7f7 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/rolebinding.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.worker.enable .Values.worker.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-worker + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "node-feature-discovery.fullname" . }}-worker +subjects: +- kind: ServiceAccount + name: {{ include "node-feature-discovery.worker.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} +{{- end }} + diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/service.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/service.yaml new file mode 100644 index 0000000..a82c22d --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/service.yaml @@ -0,0 +1,20 @@ +{{- if and (not .Values.enableNodeFeatureApi) .Values.master.enable }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-master + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + role: master +spec: + type: {{ .Values.master.service.type }} + ports: + - port: {{ .Values.master.service.port | default "8080" }} + targetPort: grpc + protocol: TCP + name: grpc + selector: + {{- include "node-feature-discovery.selectorLabels" . | nindent 4 }} + role: master +{{- end}} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/serviceaccount.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/serviceaccount.yaml new file mode 100644 index 0000000..52706f7 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/serviceaccount.yaml @@ -0,0 +1,58 @@ +{{- if and .Values.master.enable .Values.master.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "node-feature-discovery.master.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + {{- with .Values.master.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + +{{- if and .Values.topologyUpdater.enable .Values.topologyUpdater.serviceAccount.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "node-feature-discovery.topologyUpdater.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + {{- with .Values.topologyUpdater.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + +{{- if and .Values.gc.enable .Values.gc.serviceAccount.create (or .Values.enableNodeFeatureApi .Values.topologyUpdater.enable) }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "node-feature-discovery.gc.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + {{- with .Values.gc.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} + +{{- if and .Values.worker.enable .Values.worker.serviceAccount.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "node-feature-discovery.worker.serviceAccountName" . }} + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + {{- with .Values.worker.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater-crds.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater-crds.yaml new file mode 100644 index 0000000..94b7b35 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater-crds.yaml @@ -0,0 +1,278 @@ +{{- if and .Values.topologyUpdater.enable .Values.topologyUpdater.createCRDs -}} +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 +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater.yaml new file mode 100644 index 0000000..28ed58b --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/topologyupdater.yaml @@ -0,0 +1,156 @@ +{{- if .Values.topologyUpdater.enable -}} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + role: topology-updater + {{- with .Values.topologyUpdater.daemonsetAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 6 }} + role: topology-updater + template: + metadata: + labels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 8 }} + role: topology-updater + {{- with .Values.topologyUpdater.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "node-feature-discovery.topologyUpdater.serviceAccountName" . }} + dnsPolicy: ClusterFirstWithHostNet + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.topologyUpdater.podSecurityContext | nindent 8 }} + containers: + - name: topology-updater + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: NODE_ADDRESS + valueFrom: + fieldRef: + fieldPath: status.hostIP + command: + - "nfd-topology-updater" + args: + - "-podresources-socket=/host-var/lib/kubelet-podresources/kubelet.sock" + {{- if .Values.topologyUpdater.updateInterval | empty | not }} + - "-sleep-interval={{ .Values.topologyUpdater.updateInterval }}" + {{- else }} + - "-sleep-interval=3s" + {{- end }} + {{- if .Values.topologyUpdater.watchNamespace | empty | not }} + - "-watch-namespace={{ .Values.topologyUpdater.watchNamespace }}" + {{- else }} + - "-watch-namespace=*" + {{- end }} + {{- if .Values.tls.enable }} + - "-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" + {{- end }} + {{- if .Values.topologyUpdater.podSetFingerprint }} + - "-pods-fingerprint" + {{- end }} + {{- if .Values.topologyUpdater.kubeletConfigPath | empty | not }} + - "-kubelet-config-uri=file:///host-var/kubelet-config" + {{- end }} + {{- if .Values.topologyUpdater.kubeletStateDir | empty }} + # Disable kubelet state tracking by giving an empty path + - "-kubelet-state-dir=" + {{- end }} + - -metrics={{ .Values.topologyUpdater.metricsPort | default "8081"}} + ports: + - name: metrics + containerPort: {{ .Values.topologyUpdater.metricsPort | default "8081"}} + volumeMounts: + {{- if .Values.topologyUpdater.kubeletConfigPath | empty | not }} + - name: kubelet-config + mountPath: /host-var/kubelet-config + {{- end }} + - name: kubelet-podresources-sock + mountPath: /host-var/lib/kubelet-podresources/kubelet.sock + - name: host-sys + mountPath: /host-sys + {{- if .Values.topologyUpdater.kubeletStateDir | empty | not }} + - name: kubelet-state-files + mountPath: /host-var/lib/kubelet + readOnly: true + {{- end }} + {{- if .Values.tls.enable }} + - name: nfd-topology-updater-cert + mountPath: "/etc/kubernetes/node-feature-discovery/certs" + readOnly: true + {{- end }} + - name: nfd-topology-updater-conf + mountPath: "/etc/kubernetes/node-feature-discovery" + readOnly: true + + resources: + {{- toYaml .Values.topologyUpdater.resources | nindent 12 }} + securityContext: + {{- toYaml .Values.topologyUpdater.securityContext | nindent 12 }} + volumes: + - name: host-sys + hostPath: + path: "/sys" + {{- if .Values.topologyUpdater.kubeletConfigPath | empty | not }} + - name: kubelet-config + hostPath: + path: {{ .Values.topologyUpdater.kubeletConfigPath }} + {{- end }} + - name: kubelet-podresources-sock + hostPath: + {{- if .Values.topologyUpdater.kubeletPodResourcesSockPath | empty | not }} + path: {{ .Values.topologyUpdater.kubeletPodResourcesSockPath }} + {{- else }} + path: /var/lib/kubelet/pod-resources/kubelet.sock + {{- end }} + {{- if .Values.topologyUpdater.kubeletStateDir | empty | not }} + - name: kubelet-state-files + hostPath: + path: {{ .Values.topologyUpdater.kubeletStateDir }} + {{- end }} + - name: nfd-topology-updater-conf + configMap: + name: {{ include "node-feature-discovery.fullname" . }}-topology-updater-conf + items: + - key: nfd-topology-updater.conf + path: nfd-topology-updater.conf + {{- if .Values.tls.enable }} + - name: nfd-topology-updater-cert + secret: + secretName: nfd-topology-updater-cert + {{- end }} + + + {{- with .Values.topologyUpdater.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.topologyUpdater.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.topologyUpdater.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/templates/worker.yaml b/sriov-network-operator-chart/charts/sriov-nfd/templates/worker.yaml new file mode 100644 index 0000000..124e1a0 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/templates/worker.yaml @@ -0,0 +1,162 @@ +{{- if .Values.worker.enable }} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "node-feature-discovery.fullname" . }}-worker + namespace: {{ include "node-feature-discovery.namespace" . }} + labels: + {{- include "node-feature-discovery.labels" . | nindent 4 }} + role: worker + {{- with .Values.worker.daemonsetAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 6 }} + role: worker + template: + metadata: + labels: + {{- include "node-feature-discovery.selectorLabels" . | nindent 8 }} + role: worker + {{- with .Values.worker.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + dnsPolicy: ClusterFirstWithHostNet + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "node-feature-discovery.worker.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.worker.podSecurityContext | nindent 8 }} + containers: + - name: worker + securityContext: + {{- toYaml .Values.worker.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_UID + valueFrom: + fieldRef: + fieldPath: metadata.uid + resources: + {{- toYaml .Values.worker.resources | nindent 12 }} + command: + - "nfd-worker" + args: + {{- if not .Values.enableNodeFeatureApi }} + - "-server={{ include "node-feature-discovery.fullname" . }}-master:{{ .Values.master.service.port }}" + - "-enable-nodefeature-api=false" + {{- end }} +{{- if .Values.tls.enable }} + - "-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" +{{- end }} + - "-metrics={{ .Values.worker.metricsPort | default "8081"}}" + ports: + - name: metrics + containerPort: {{ .Values.worker.metricsPort | default "8081"}} + volumeMounts: + - name: host-boot + mountPath: "/host-boot" + readOnly: true + - name: host-os-release + mountPath: "/host-etc/os-release" + readOnly: true + - name: host-sys + mountPath: "/host-sys" + readOnly: true + - name: host-usr-lib + mountPath: "/host-usr/lib" + readOnly: true + - name: host-lib + mountPath: "/host-lib" + readOnly: true + {{- if .Values.worker.mountUsrSrc }} + - name: host-usr-src + mountPath: "/host-usr/src" + readOnly: true + {{- end }} + - name: source-d + mountPath: "/etc/kubernetes/node-feature-discovery/source.d/" + readOnly: true + - name: features-d + mountPath: "/etc/kubernetes/node-feature-discovery/features.d/" + readOnly: true + - name: nfd-worker-conf + mountPath: "/etc/kubernetes/node-feature-discovery" + readOnly: true +{{- if .Values.tls.enable }} + - name: nfd-worker-cert + mountPath: "/etc/kubernetes/node-feature-discovery/certs" + readOnly: true +{{- end }} + volumes: + - name: host-boot + hostPath: + path: "/boot" + - name: host-os-release + hostPath: + path: "/etc/os-release" + - name: host-sys + hostPath: + path: "/sys" + - name: host-usr-lib + hostPath: + path: "/usr/lib" + - name: host-lib + hostPath: + path: "/lib" + {{- if .Values.worker.mountUsrSrc }} + - name: host-usr-src + hostPath: + path: "/usr/src" + {{- end }} + - name: source-d + hostPath: + path: "/etc/kubernetes/node-feature-discovery/source.d/" + - name: features-d + hostPath: + path: "/etc/kubernetes/node-feature-discovery/features.d/" + - name: nfd-worker-conf + configMap: + name: {{ include "node-feature-discovery.fullname" . }}-worker-conf + items: + - key: nfd-worker.conf + path: nfd-worker.conf +{{- if .Values.tls.enable }} + - name: nfd-worker-cert + secret: + secretName: nfd-worker-cert +{{- end }} + {{- with .Values.worker.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.worker.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.worker.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.worker.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} +{{- end }} diff --git a/sriov-network-operator-chart/charts/sriov-nfd/values.yaml b/sriov-network-operator-chart/charts/sriov-nfd/values.yaml new file mode 100644 index 0000000..9d9aa94 --- /dev/null +++ b/sriov-network-operator-chart/charts/sriov-nfd/values.yaml @@ -0,0 +1,534 @@ +image: + repository: rancher/hardened-node-feature-discovery + # This should be set to 'IfNotPresent' for released version + pullPolicy: IfNotPresent + # tag, if defined will use the given image tag, else Chart.AppVersion will be used + tag: v0.15.6-build20240822 +imagePullSecrets: [] + +nameOverride: "" +fullnameOverride: "" +namespaceOverride: "" + +enableNodeFeatureApi: true + +master: + enable: true + config: ### + # noPublish: false + # autoDefaultNs: true + # extraLabelNs: ["added.ns.io","added.kubernets.io"] + # denyLabelNs: ["denied.ns.io","denied.kubernetes.io"] + # resourceLabels: ["vendor-1.com/feature-1","vendor-2.io/feature-2"] + # enableTaints: false + # labelWhiteList: "foo" + # resyncPeriod: "2h" + # 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-master restart to take effect after being changed + # logDir: + # logFile: + # logFileMaxSize: 1800 + # skipLogHeaders: false + # leaderElection: + # leaseDuration: 15s + # # this value has to be lower than leaseDuration and greater than retryPeriod*1.2 + # renewDeadline: 10s + # # this value has to be greater than 0 + # retryPeriod: 2s + # nfdApiParallelism: 10 + ### + # The TCP port that nfd-master listens for incoming requests. Default: 8080 + # Deprecated this parameter is related to the deprecated gRPC API and will + # be removed with it in a future release + port: 8080 + metricsPort: 8081 + instance: + featureApi: + resyncPeriod: + denyLabelNs: [] + extraLabelNs: [] + resourceLabels: [] + enableTaints: false + crdController: null + featureRulesController: null + nfdApiParallelism: null + deploymentAnnotations: {} + replicaCount: 1 + + podSecurityContext: {} + # fsGroup: 2000 + + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: [ "ALL" ] + readOnlyRootFilesystem: true + runAsNonRoot: true + # runAsUser: 1000 + + serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: + + rbac: + create: true + + service: + type: ClusterIP + port: 8080 + + resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + nodeSelector: {} + + tolerations: + - key: "node-role.kubernetes.io/master" + operator: "Equal" + value: "" + effect: "NoSchedule" + - key: "node-role.kubernetes.io/control-plane" + operator: "Equal" + value: "" + effect: "NoSchedule" + + annotations: {} + + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + 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: [""] + +worker: + enable: true + config: ### + #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" + # - "TDX_GUEST" + # 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" + # local: + # hooksEnabled: false + # custom: + # # The following feature demonstrates the capabilities of the matchFeatures + # - name: "my custom rule" + # labels: + # "vendor.io/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: + # "vendor.io/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"]} + # + # - name: "avx wildcard rule" + # labels: + # "my-avx-feature": "true" + # matchFeatures: + # - feature: cpu.cpuid + # matchName: {op: InRegexp, value: ["^AVX512"]} + # + # # The following features demonstreate label templating capabilities + # - name: "my template rule" + # labelsTemplate: | + # {{ range .system.osrelease }}vendor.io/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 }}vendor.io/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: + # "vendor.io/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: + # "vendor.io/my.backref.feature": "true" + # matchFeatures: + # - feature: rule.matched + # matchExpressions: + # vendor.io/my.kernel.feature: {op: IsTrue} + # my.dummy.var: {op: Gt, value: ["0"]} + # + # - name: "kconfig template rule" + # labelsTemplate: | + # {{ range .kernel.config }}kconfig-{{ .Name }}={{ .Value }} + # {{ end }} + # matchFeatures: + # - feature: kernel.config + # matchName: {op: In, value: ["SWAP", "X86", "ARM"]} +### + + metricsPort: 8081 + daemonsetAnnotations: {} + podSecurityContext: {} + # fsGroup: 2000 + + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: [ "ALL" ] + readOnlyRootFilesystem: true + runAsNonRoot: true + # runAsUser: 1000 + + serviceAccount: + # Specifies whether a service account should be created. + # We create this by default to make it easier for downstream users to apply PodSecurityPolicies. + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: + + rbac: + create: true + + # Allow users to mount the hostPath /usr/src, useful for RHCOS on s390x + # Does not work on systems without /usr/src AND a read-only /usr, such as Talos + mountUsrSrc: false + + resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + nodeSelector: {} + + tolerations: [] + + annotations: {} + + affinity: {} + + priorityClassName: "" + +topologyUpdater: + config: ### + ## key = node name, value = list of resources to be excluded. + ## use * to exclude from all nodes. + ## an example for how the exclude list should looks like + #excludeList: + # node1: [cpu] + # node2: [memory, example/deviceA] + # *: [hugepages-2Mi] +### + + enable: false + createCRDs: false + + serviceAccount: + create: true + annotations: {} + name: + rbac: + create: true + + metricsPort: 8081 + kubeletConfigPath: + kubeletPodResourcesSockPath: + updateInterval: 60s + watchNamespace: "*" + kubeletStateDir: /var/lib/kubelet + + podSecurityContext: {} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: [ "ALL" ] + readOnlyRootFilesystem: true + runAsUser: 0 + + resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + nodeSelector: {} + tolerations: [] + annotations: {} + daemonsetAnnotations: {} + affinity: {} + podSetFingerprint: true + +gc: + enable: true + replicaCount: 1 + + serviceAccount: + create: true + annotations: {} + name: + rbac: + create: true + + interval: 1h + + podSecurityContext: {} + + resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + metricsPort: 8081 + + nodeSelector: {} + tolerations: [] + annotations: {} + deploymentAnnotations: {} + affinity: {} + +# Optionally use encryption for worker <--> master comms +# TODO: verify hostname is not yet supported +# +# If you do not enable certManager (and have it installed) you will +# need to manually, or otherwise, provision the TLS certs as secrets +tls: + enable: false + certManager: false + +prometheus: + enable: false + labels: {} diff --git a/sriov-network-operator-chart/templates.obscpio b/sriov-network-operator-chart/templates.obscpio deleted file mode 100644 index 036de0b..0000000 Binary files a/sriov-network-operator-chart/templates.obscpio and /dev/null differ diff --git a/sriov-network-operator-chart/templates/NOTES.txt b/sriov-network-operator-chart/templates/NOTES.txt new file mode 100644 index 0000000..e246ccd --- /dev/null +++ b/sriov-network-operator-chart/templates/NOTES.txt @@ -0,0 +1,17 @@ +Get Network Operator deployed resources by running the following commands: + +$ kubectl -n {{ .Release.Namespace }} get pods + +For additional instructions on how to use SR-IOV network operator, +refer to: https://github.com/k8snetworkplumbingwg/sriov-network-operator + +{{- if .Values.operator.enableAdmissionController }} +{{- if not .Values.cert_manager }} +Thank you for installing {{ .Chart.Name }}. + +WARNING! Self signed certificates have been generated for webhooks. +These certificates have a one-year validity and will not be rotated +automatically. This should not be a production cluster. Please deploy +and use cert-manager for production clusters. +{{- end }} +{{- end }} diff --git a/sriov-network-operator-chart/templates/_helpers.tpl b/sriov-network-operator-chart/templates/_helpers.tpl new file mode 100644 index 0000000..3a3a9b8 --- /dev/null +++ b/sriov-network-operator-chart/templates/_helpers.tpl @@ -0,0 +1,85 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "sriov-network-operator.name" -}} +{{- default "sriov-network-operator" .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "sriov-network-operator.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default "sriov-network-operator" .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "sriov-network-operator.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "sriov-network-operator.labels" -}} +helm.sh/chart: {{ include "sriov-network-operator.chart" . }} +{{ include "sriov-network-operator.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "sriov-network-operator.selectorLabels" -}} +app.kubernetes.io/name: {{ include "sriov-network-operator.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "sriov-network-operator.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "sriov-network-operator.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{- define "system_default_registry" -}} +{{- if .Values.global.cattle.systemDefaultRegistry -}} +{{- printf "%s/" .Values.global.cattle.systemDefaultRegistry -}} +{{- else -}} +{{- "" -}} +{{- end -}} +{{- end -}} + +{{/* +Windows cluster will add default taint for linux nodes, +add below linux tolerations to workloads could be scheduled to those linux nodes +*/}} +{{- define "linux-node-tolerations" -}} +- key: "cattle.io/os" + value: "linux" + effect: "NoSchedule" + operator: "Equal" +{{- end -}} + +{{- define "linux-node-selector" -}} +kubernetes.io/os: linux +{{- end -}} diff --git a/sriov-network-operator-chart/templates/_webhook-certs.tpl b/sriov-network-operator-chart/templates/_webhook-certs.tpl new file mode 100644 index 0000000..046a174 --- /dev/null +++ b/sriov-network-operator-chart/templates/_webhook-certs.tpl @@ -0,0 +1,31 @@ +{{/* +Generate TLS certificates for webhooks. +Note: these 2 lines, that are repeated several times below, are a trick to +ensure the CA certs are generated only once: + $ca := .ca | default (genCA "sriov-network-operator.k8s.cni.cncf.io" 365) + $_ := set . "ca" $ca +Please, don't try to "simplify" them as without this trick, every generated +certificate would be signed by a different CA. +*/}} +{{- define "sriov_operator_ca_cert" }} +{{- $ca := .ca | default (genCA "sriov-network-operator.k8s.cni.cncf.io" 365) -}} +{{- $_ := set . "ca" $ca -}} +{{- printf "%s" $ca.Cert | b64enc -}} +{{- end }} +{{- define "sriov_operator_cert" }} +{{- $ca := .ca | default (genCA "sriov-network-operator.k8s.cni.cncf.io" 365) -}} +{{- $_ := set . "ca" $ca -}} +{{- $cn := printf "operator-webhook-service.%s.svc" .Release.Namespace -}} +{{- $cert := genSignedCert $cn nil (list $cn) 365 $ca -}} +tls.crt: {{ $cert.Cert | b64enc }} +tls.key: {{ $cert.Key | b64enc }} +{{- end }} +{{- define "sriov_resource_injector_cert" }} +{{- $ca := .ca | default (genCA "sriov-network-operator.k8s.cni.cncf.io" 365) -}} +{{- $_ := set . "ca" $ca -}} +{{- $cn := printf "network-resources-injector-service.%s.svc" .Release.Namespace -}} +{{- $cert := genSignedCert $cn nil (list $cn) 365 $ca -}} +tls.crt: {{ $cert.Cert | b64enc }} +tls.key: {{ $cert.Key | b64enc }} +{{- end }} + diff --git a/sriov-network-operator-chart/templates/certificate.yaml b/sriov-network-operator-chart/templates/certificate.yaml new file mode 100644 index 0000000..1c6a38c --- /dev/null +++ b/sriov-network-operator-chart/templates/certificate.yaml @@ -0,0 +1,71 @@ +{{- if .Values.operator.admissionControllers.enabled }} +{{- if and (.Values.operator.admissionControllers.certificates.certManager.enabled) (.Values.operator.admissionControllers.certificates.certManager.generateSelfSigned) }} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ .Values.operator.admissionControllers.certificates.secretNames.operator }} + namespace: {{ .Release.Namespace }} +spec: + dnsNames: + - operator-webhook-service.{{ .Release.Namespace }}.svc + - operator-webhook-service.{{ .Release.Namespace }}.svc.cluster.local + issuerRef: + kind: Issuer + name: operator-webhook-selfsigned-issuer + secretName: {{ .Values.operator.admissionControllers.certificates.secretNames.operator }} +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: operator-webhook-selfsigned-issuer + namespace: {{ .Release.Namespace }} +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ .Values.operator.admissionControllers.certificates.secretNames.injector }} + namespace: {{ .Release.Namespace }} +spec: + dnsNames: + - network-resources-injector-service.{{ .Release.Namespace }}.svc + - network-resources-injector-service.{{ .Release.Namespace }}.svc.cluster.local + issuerRef: + kind: Issuer + name: network-resources-injector-selfsigned-issuer + secretName: {{ .Values.operator.admissionControllers.certificates.secretNames.injector }} +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: network-resources-injector-selfsigned-issuer + namespace: {{ .Release.Namespace }} +spec: + selfSigned: {} +{{- else if and (not .Values.operator.admissionControllers.certificates.certManager.enabled) (.Values.operator.admissionControllers.certificates.custom.enabled) }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.operator.admissionControllers.certificates.secretNames.operator }} + namespace: {{ .Release.Namespace }} +type: Opaque +data: + ca.crt: {{ .Values.operator.admissionControllers.certificates.custom.operator.caCrt | b64enc | b64enc | quote }} + tls.crt: {{ .Values.operator.admissionControllers.certificates.custom.operator.tlsCrt | b64enc | quote }} + tls.key: {{ .Values.operator.admissionControllers.certificates.custom.operator.tlsKey | b64enc | quote }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.operator.admissionControllers.certificates.secretNames.injector }} + namespace: {{ .Release.Namespace }} +type: Opaque +data: + ca.crt: {{ .Values.operator.admissionControllers.certificates.custom.injector.caCrt | b64enc | b64enc | quote }} + tls.crt: {{ .Values.operator.admissionControllers.certificates.custom.injector.tlsCrt | b64enc | quote }} + tls.key: {{ .Values.operator.admissionControllers.certificates.custom.injector.tlsKey | b64enc | quote }} +{{- end }} +{{- end }} diff --git a/sriov-network-operator-chart/templates/certmanagercerts.yaml b/sriov-network-operator-chart/templates/certmanagercerts.yaml new file mode 100644 index 0000000..6103da6 --- /dev/null +++ b/sriov-network-operator-chart/templates/certmanagercerts.yaml @@ -0,0 +1,41 @@ +{{- if and (.Values.operator.enableAdmissionController) (.Values.cert_manager) -}} +{{- if not (.Capabilities.APIVersions.Has "cert-manager.io/v1") -}} +{{- required "cert-manager is required but not found" "" -}} +{{- end -}} +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: sriov-network-operator-selfsigned-issuer + namespace: {{ .Release.Namespace }} +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: operator-webhook-service + namespace: {{ .Release.Namespace }} +spec: + secretName: operator-webhook-service + dnsNames: + - operator-webhook-service.{{ .Release.Namespace }}.svc + issuerRef: + name: sriov-network-operator-selfsigned-issuer + privateKey: + rotationPolicy: Always +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: network-resources-injector-service + namespace: {{ .Release.Namespace }} +spec: + secretName: network-resources-injector-secret + dnsNames: + - network-resources-injector-service.{{ .Release.Namespace }}.svc + issuerRef: + name: sriov-network-operator-selfsigned-issuer + privateKey: + rotationPolicy: Always +{{- end -}} + diff --git a/sriov-network-operator-chart/templates/clusterrole.yaml b/sriov-network-operator-chart/templates/clusterrole.yaml new file mode 100644 index 0000000..f282fa3 --- /dev/null +++ b/sriov-network-operator-chart/templates/clusterrole.yaml @@ -0,0 +1,111 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "sriov-network-operator.fullname" . }} + labels: + {{- include "sriov-network-operator.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch", "patch", "update"] + - apiGroups: [""] + resources: ["pods"] + verbs: ["*"] + - apiGroups: [""] + resources: ["pods/eviction"] + verbs: ["create"] + - apiGroups: ["apps"] + resources: ["daemonsets"] + verbs: ["get"] + - apiGroups: [""] + resources: ["namespaces", "serviceaccounts"] + verbs: ["*"] + - apiGroups: ["k8s.cni.cncf.io"] + resources: ["network-attachment-definitions"] + verbs: ["*"] + - apiGroups: ["rbac.authorization.k8s.io"] + resources: [clusterroles, clusterrolebindings] + verbs: ["*"] + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["mutatingwebhookconfigurations", "validatingwebhookconfigurations"] + verbs: ["*"] + - apiGroups: ["sriovnetwork.openshift.io"] + resources: ["*"] + verbs: ["*"] + - apiGroups: ["machineconfiguration.openshift.io"] + resources: ["*"] + verbs: ["*"] + - apiGroups: ["config.openshift.io"] + resources: ["infrastructures"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: sriov-network-config-daemon + labels: + {{- include "sriov-network-operator.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch", "patch", "update"] + - apiGroups: [""] + resources: ["pods"] + verbs: ["*"] + - apiGroups: ["apps"] + resources: ["daemonsets"] + verbs: ["get"] + - apiGroups: [ "config.openshift.io" ] + resources: [ "infrastructures" ] + verbs: [ "get", "list", "watch" ] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: sriov-admin + {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} + rbac.authorization.k8s.io/aggregate-to-admin: "true" + {{- end }} +rules: +- apiGroups: + - sriovnetwork.openshift.io + resources: + - '*' + verbs: + - "get" + - "watch" + - "list" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: sriov-edit + {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} + rbac.authorization.k8s.io/aggregate-to-edit: "true" + {{- end }} +rules: +- apiGroups: + - sriovnetwork.openshift.io + resources: + - '*' + verbs: + - "get" + - "watch" + - "list" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: sriov-view + {{- if .Values.global.rbac.userRoles.aggregateToDefaultRoles }} + rbac.authorization.k8s.io/aggregate-to-view: "true" + {{- end }} +rules: +- apiGroups: + - sriovnetwork.openshift.io + resources: + - '*' + verbs: + - "get" + - "watch" + - "list" diff --git a/sriov-network-operator-chart/templates/clusterrolebinding.yaml b/sriov-network-operator-chart/templates/clusterrolebinding.yaml new file mode 100644 index 0000000..56788db --- /dev/null +++ b/sriov-network-operator-chart/templates/clusterrolebinding.yaml @@ -0,0 +1,29 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "sriov-network-operator.fullname" . }} + labels: + {{- include "sriov-network-operator.labels" . | nindent 4 }} +roleRef: + kind: ClusterRole + name: {{ include "sriov-network-operator.fullname" . }} + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + namespace: {{ .Release.Namespace }} + name: {{ include "sriov-network-operator.fullname" . }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: sriov-network-config-daemon + labels: + {{- include "sriov-network-operator.labels" . | nindent 4 }} +roleRef: + kind: ClusterRole + name: sriov-network-config-daemon + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + namespace: {{ .Release.Namespace }} + name: sriov-network-config-daemon diff --git a/sriov-network-operator-chart/templates/configmap.yaml b/sriov-network-operator-chart/templates/configmap.yaml new file mode 100644 index 0000000..d9e6a29 --- /dev/null +++ b/sriov-network-operator-chart/templates/configmap.yaml @@ -0,0 +1,47 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: supported-nic-ids +data: + Intel_i40e_XXV710: "8086 158a 154c" + Intel_i40e_25G_SFP28: "8086 158b 154c" + Intel_i40e_10G_X710_SFP: "8086 1572 154c" + Intel_ixgbe_10G_X550: "8086 1563 1565" + Intel_ixgbe_82576: "8086 10c9 10ca" + Intel_i40e_X710_X557_AT_10G: "8086 1589 154c" + Intel_i40e_10G_X710_BACKPLANE: "8086 1581 154c" + Intel_i40e_10G_X710_BASE_T: "8086 15ff 154c" + Intel_i40e_XXV710_N3000: "8086 0d58 154c" + Intel_i40e_40G_XL710_QSFP: "8086 1583 154c" + Intel_i40e_X550T: "8086 1563 1565" + Intel_i40e_X722: "8086 37d2 37cd" + Intel_i40e_X722_SFP: "8086 37d0 37cd" + Intel_i40e_X722_SFPP: "8086 37d3 37cd" + Intel_ice_Columbiaville_E810-CQDA2_2CQDA2: "8086 1592 1889" + Intel_ice_Columbiaville_E810-XXVDA4: "8086 1593 1889" + Intel_ice_Columbiaville_E810-XXVDA2: "8086 159b 1889" + Intel_ice_Columbiaville_E810: "8086 1591 1889" + Intel_ice_Columbiapark_E823C: "8086 188a 1889" + Nvidia_mlx5_ConnectX-4: "15b3 1013 1014" + Nvidia_mlx5_ConnectX-4LX: "15b3 1015 1016" + Nvidia_mlx5_ConnectX-5: "15b3 1017 1018" + Nvidia_mlx5_ConnectX-5_Ex: "15b3 1019 101a" + Nvidia_mlx5_ConnectX-6: "15b3 101b 101c" + Nvidia_mlx5_ConnectX-6_Dx: "15b3 101d 101e" + Nvidia_mlx5_ConnectX-6_Lx: "15b3 101f 101e" + Nvidia_mlx5_ConnectX-7: "15b3 1021 101e" + Nvidia_mlx5_MT42822_BlueField-2_integrated_ConnectX-6_Dx: "15b3 a2d6 101e" + Nvidia_mlx5_MT43244_BlueField-3_integrated_ConnectX-7_Dx: "15b3 a2dc 101e" + Broadcom_bnxt_BCM57414_2x25G: "14e4 16d7 16dc" + Broadcom_bnxt_BCM75508_2x100G: "14e4 1750 1806" + Qlogic_qede_QL45000_50G: "1077 1654 1664" + Red_Hat_Virtio_network_device: "1af4 1000 1000" + Red_Hat_Virtio_1_0_network_device: "1af4 1041 1041" + Marvell_OCTEON_TX2_CN96XX: "177d b200 b203" + Marvell_OCTEON_TX2_CN98XX: "177d b100 b103" + Marvell_OCTEON_Fusion_CNF95XX: "177d b600 b603" + Marvell_OCTEON10_CN10XXX: "177d b900 b903" + Marvell_OCTEON_Fusion_CNF105XX: "177d ba00 ba03" + {{- range .Values.supportedExtraNICs }} + {{ . }} + {{- end }} diff --git a/sriov-network-operator-chart/templates/operator.yaml b/sriov-network-operator-chart/templates/operator.yaml new file mode 100644 index 0000000..6768e37 --- /dev/null +++ b/sriov-network-operator-chart/templates/operator.yaml @@ -0,0 +1,116 @@ +{{- if not (.Capabilities.APIVersions.Has "k8s.cni.cncf.io/v1/NetworkAttachmentDefinition") -}} +{{- required "rke2-multus is required but not found" "" -}} +{{- end -}} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "sriov-network-operator.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "sriov-network-operator.labels" . | nindent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + name: sriov-network-operator + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 33% + template: + metadata: + labels: + name: sriov-network-operator + spec: + {{- with .Values.operator.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.operator.affinity }} + affinity: + {{- toYaml . | nindent 8}} + {{- end }} + {{- with .Values.operator.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "sriov-network-operator.fullname" . }} + priorityClassName: "system-node-critical" + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} + containers: + - name: {{ include "sriov-network-operator.fullname" . }} + image: {{ include "system_default_registry" . }}{{ .Values.images.operator.repository }}:{{ .Values.images.operator.tag }} + command: + - sriov-network-operator + resources: + requests: + cpu: 100m + memory: 100Mi + env: + - name: WATCH_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: SRIOV_CNI_IMAGE + value: {{ include "system_default_registry" . }}{{ .Values.images.sriovCni.repository }}:{{ .Values.images.sriovCni.tag }} + - name: SRIOV_INFINIBAND_CNI_IMAGE + value: {{ include "system_default_registry" . }}{{ .Values.images.ibSriovCni.repository }}:{{ .Values.images.ibSriovCni.tag }} + - name: SRIOV_DEVICE_PLUGIN_IMAGE + value: {{ include "system_default_registry" . }}{{ .Values.images.sriovDevicePlugin.repository }}:{{ .Values.images.sriovDevicePlugin.tag }} + - name: NETWORK_RESOURCES_INJECTOR_IMAGE + value: {{ include "system_default_registry" . }}{{ .Values.images.resourcesInjector.repository }}:{{ .Values.images.resourcesInjector.tag }} + - name: OPERATOR_NAME + value: sriov-network-operator + - name: SRIOV_NETWORK_CONFIG_DAEMON_IMAGE + value: {{ include "system_default_registry" . }}{{ .Values.images.sriovConfigDaemon.repository }}:{{ .Values.images.sriovConfigDaemon.tag }} + - name: SRIOV_NETWORK_WEBHOOK_IMAGE + value: {{ include "system_default_registry" . }}{{ .Values.images.webhook.repository }}:{{ .Values.images.webhook.tag }} + - name: RESOURCE_PREFIX + value: {{ .Values.operator.resourcePrefix }} + - name: IMAGE_PULL_SECRETS + value: {{ join "," .Values.imagePullSecrets }} + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: RELEASE_VERSION + value: {{ .Release.AppVersion }} + - name: SRIOV_CNI_BIN_PATH + value: {{ .Values.operator.cniBinPath }} + - name: CLUSTER_TYPE + value: {{ .Values.operator.clusterType }} + {{- if .Values.operator.admissionControllers.enabled }} + - name: ADMISSION_CONTROLLERS_CERTIFICATES_OPERATOR_SECRET_NAME + value: {{ .Values.operator.admissionControllers.certificates.secretNames.operator }} + - name: ADMISSION_CONTROLLERS_CERTIFICATES_INJECTOR_SECRET_NAME + value: {{ .Values.operator.admissionControllers.certificates.secretNames.injector }} + {{- if .Values.operator.admissionControllers.certificates.certManager.enabled }} + - name: ADMISSION_CONTROLLERS_CERTIFICATES_CERT_MANAGER_ENABLED + value: {{ .Values.operator.admissionControllers.certificates.certManager.enabled | quote }} + {{- else }} + - name: ADMISSION_CONTROLLERS_CERTIFICATES_OPERATOR_CA_CRT + valueFrom: + secretKeyRef: + name: {{ .Values.operator.admissionControllers.certificates.secretNames.operator }} + key: ca.crt + - name: ADMISSION_CONTROLLERS_CERTIFICATES_INJECTOR_CA_CRT + valueFrom: + secretKeyRef: + name: {{ .Values.operator.admissionControllers.certificates.secretNames.injector }} + key: ca.crt + {{- end }} + {{- end }} diff --git a/sriov-network-operator-chart/templates/role.yaml b/sriov-network-operator-chart/templates/role.yaml new file mode 100644 index 0000000..15c043d --- /dev/null +++ b/sriov-network-operator-chart/templates/role.yaml @@ -0,0 +1,138 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + creationTimestamp: null + name: {{ include "sriov-network-operator.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "sriov-network-operator.labels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - pods + - services + - endpoints + - persistentvolumeclaims + - events + - configmaps + - secrets + verbs: + - '*' + - apiGroups: + - apps + resources: + - deployments + - daemonsets + - replicasets + - statefulsets + verbs: + - '*' + - apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + verbs: + - get + - create + - apiGroups: + - apps + resourceNames: + - sriov-network-operator + resources: + - deployments/finalizers + verbs: + - update + - apiGroups: + - rbac.authorization.k8s.io + resources: + - serviceaccounts + - roles + - rolebindings + verbs: + - '*' + - apiGroups: + - config.openshift.io + resources: + - infrastructures + verbs: + - get + - list + - watch + - apiGroups: + - 'coordination.k8s.io' + resources: + - 'leases' + verbs: + - '*' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: sriov-network-config-daemon + namespace: {{ .Release.Namespace }} + labels: + {{- include "sriov-network-operator.labels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - pods + verbs: + - '*' + - apiGroups: + - apps + resources: + - daemonsets + verbs: + - '*' + - apiGroups: + - sriovnetwork.openshift.io + resources: + - '*' + - sriovnetworknodestates + verbs: + - '*' + - apiGroups: + - security.openshift.io + resourceNames: + - privileged + resources: + - securitycontextconstraints + verbs: + - use + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - update + - apiGroups: + - 'coordination.k8s.io' + resources: + - 'leases' + verbs: + - '*' + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: operator-webhook-sa + namespace: {{ .Release.Namespace }} + labels: + {{- include "sriov-network-operator.labels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get diff --git a/sriov-network-operator-chart/templates/rolebinding.yaml b/sriov-network-operator-chart/templates/rolebinding.yaml new file mode 100644 index 0000000..85df9fe --- /dev/null +++ b/sriov-network-operator-chart/templates/rolebinding.yaml @@ -0,0 +1,44 @@ +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "sriov-network-operator.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "sriov-network-operator.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ include "sriov-network-operator.fullname" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: {{ include "sriov-network-operator.fullname" . }} + apiGroup: rbac.authorization.k8s.io +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: sriov-network-config-daemon + namespace: {{ .Release.Namespace }} + labels: + {{- include "sriov-network-operator.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: sriov-network-config-daemon + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: sriov-network-config-daemon + apiGroup: rbac.authorization.k8s.io +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: operator-webhook-sa + namespace: {{ .Release.Namespace }} +subjects: +- kind: ServiceAccount + name: operator-webhook-sa +roleRef: + kind: Role + name: operator-webhook-sa + apiGroup: rbac.authorization.k8s.io diff --git a/sriov-network-operator-chart/templates/secrets.yaml b/sriov-network-operator-chart/templates/secrets.yaml new file mode 100644 index 0000000..07d7a45 --- /dev/null +++ b/sriov-network-operator-chart/templates/secrets.yaml @@ -0,0 +1,20 @@ +{{- if not .Values.cert_manager -}} +{{- if .Values.operator.enableAdmissionController }} +apiVersion: v1 +kind: Secret +metadata: + name: operator-webhook-service + namespace: {{ .Release.Namespace }} +data: {{ include "sriov_operator_cert" . | nindent 2 }} +{{- end }} +--- +{{- if .Values.operator.enableAdmissionController }} +apiVersion: v1 +kind: Secret +metadata: + name: network-resources-injector-secret + namespace: {{ .Release.Namespace }} +data: {{ include "sriov_resource_injector_cert" . | nindent 2 }} +{{- end }} +{{- end }} + diff --git a/sriov-network-operator-chart/templates/serviceaccount.yaml b/sriov-network-operator-chart/templates/serviceaccount.yaml new file mode 100644 index 0000000..98b7553 --- /dev/null +++ b/sriov-network-operator-chart/templates/serviceaccount.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "sriov-network-operator.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "sriov-network-operator.labels" . | nindent 4 }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: sriov-network-config-daemon + namespace: {{ .Release.Namespace }} + labels: + {{- include "sriov-network-operator.labels" . | nindent 4 }} diff --git a/sriov-network-operator-chart/templates/sriovoperatorconfig.yaml b/sriov-network-operator-chart/templates/sriovoperatorconfig.yaml new file mode 100644 index 0000000..c65aa2d --- /dev/null +++ b/sriov-network-operator-chart/templates/sriovoperatorconfig.yaml @@ -0,0 +1,17 @@ +{{ if .Values.sriovOperatorConfig.deploy }} +apiVersion: sriovnetwork.openshift.io/v1 +kind: SriovOperatorConfig +metadata: + name: default + namespace: {{ .Release.Namespace }} +spec: + enableInjector: {{ .Values.operator.admissionControllers.enabled }} + enableOperatorWebhook: {{ .Values.operator.admissionControllers.enabled }} + {{- with .Values.sriovOperatorConfig.configDaemonNodeSelector }} + configDaemonNodeSelector: + {{- range $k, $v := .}}{{printf "%s: \"%s\"" $k $v | nindent 4 }}{{ end }} + {{- end }} + logLevel: {{ .Values.sriovOperatorConfig.logLevel }} + disableDrain: {{ .Values.sriovOperatorConfig.disableDrain }} + configurationMode: {{ .Values.sriovOperatorConfig.configurationMode }} +{{ end }} \ No newline at end of file diff --git a/sriov-network-operator-chart/templates/validate-install-crd.yaml b/sriov-network-operator-chart/templates/validate-install-crd.yaml new file mode 100644 index 0000000..dca7fa3 --- /dev/null +++ b/sriov-network-operator-chart/templates/validate-install-crd.yaml @@ -0,0 +1,20 @@ +#{{- if gt (len (lookup "rbac.authorization.k8s.io/v1" "ClusterRole" "" "")) 0 -}} +# {{- $found := dict -}} +# {{- set $found "sriovnetwork.openshift.io/v1/OVSNetwork" false -}} +# {{- set $found "sriovnetwork.openshift.io/v1/SriovIBNetwork" false -}} +# {{- set $found "sriovnetwork.openshift.io/v1/SriovNetworkNodePolicy" false -}} +# {{- set $found "sriovnetwork.openshift.io/v1/SriovNetworkNodeState" false -}} +# {{- set $found "sriovnetwork.openshift.io/v1/SriovNetworkPoolConfig" false -}} +# {{- set $found "sriovnetwork.openshift.io/v1/SriovNetwork" false -}} +# {{- set $found "sriovnetwork.openshift.io/v1/SriovOperatorConfig" false -}} +# {{- range .Capabilities.APIVersions -}} +# {{- if hasKey $found (toString .) -}} +# {{- set $found (toString .) true -}} +# {{- end -}} +# {{- end -}} +# {{- range $_, $exists := $found -}} +# {{- if (eq $exists false) -}} +# {{- required "Required CRDs are missing. Please install the corresponding CRD chart before installing this chart." "" -}} +# {{- end -}} +# {{- end -}} +#{{- end -}} \ No newline at end of file diff --git a/upgrade-controller-chart/charts/lifecycle-crds/Chart.yaml b/upgrade-controller-chart/charts/lifecycle-crds/Chart.yaml new file mode 100644 index 0000000..2ac8dc1 --- /dev/null +++ b/upgrade-controller-chart/charts/lifecycle-crds/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: 0.1.0 +description: A Helm chart containing SUSE Lifecycle CRDs +name: lifecycle-crds +type: application +version: 0.1.0 diff --git a/upgrade-controller-chart/charts/lifecycle-crds/templates/release-manifest-crd.yaml b/upgrade-controller-chart/charts/lifecycle-crds/templates/release-manifest-crd.yaml new file mode 100644 index 0000000..5927e10 --- /dev/null +++ b/upgrade-controller-chart/charts/lifecycle-crds/templates/release-manifest-crd.yaml @@ -0,0 +1,135 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: releasemanifests.lifecycle.suse.com +spec: + group: lifecycle.suse.com + names: + kind: ReleaseManifest + listKind: ReleaseManifestList + plural: releasemanifests + singular: releasemanifest + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: ReleaseManifest is the Schema for the releasemanifests 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: ReleaseManifestSpec defines the desired state of ReleaseManifest + properties: + components: + properties: + kubernetes: + properties: + k3s: + properties: + version: + type: string + required: + - version + type: object + rke2: + properties: + version: + type: string + required: + - version + type: object + required: + - k3s + - rke2 + type: object + operatingSystem: + properties: + cpeScheme: + type: string + prettyName: + type: string + supportedArchs: + items: + enum: + - x86_64 + - aarch64 + type: string + minItems: 1 + type: array + version: + type: string + zypperID: + type: string + required: + - cpeScheme + - prettyName + - supportedArchs + - version + - zypperID + type: object + workloads: + properties: + helm: + items: + properties: + addonCharts: + x-kubernetes-preserve-unknown-fields: true + chart: + type: string + dependencyCharts: + x-kubernetes-preserve-unknown-fields: true + prettyName: + type: string + releaseName: + type: string + repository: + type: string + values: + x-kubernetes-preserve-unknown-fields: true + version: + type: string + required: + - chart + - prettyName + - releaseName + - version + type: object + type: array + required: + - helm + type: object + required: + - kubernetes + - operatingSystem + - workloads + type: object + releaseVersion: + type: string + required: + - releaseVersion + type: object + status: + description: ReleaseManifestStatus defines the observed state of ReleaseManifest + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/upgrade-controller-chart/charts.obscpio b/upgrade-controller-chart/charts/lifecycle-crds/templates/upgrade-plan-crd.yaml similarity index 57% rename from upgrade-controller-chart/charts.obscpio rename to upgrade-controller-chart/charts/lifecycle-crds/templates/upgrade-plan-crd.yaml index 9d4e3e8..a115df3 100644 Binary files a/upgrade-controller-chart/charts.obscpio and b/upgrade-controller-chart/charts/lifecycle-crds/templates/upgrade-plan-crd.yaml differ diff --git a/upgrade-controller-chart/templates.obscpio b/upgrade-controller-chart/templates.obscpio deleted file mode 100644 index c619dbc..0000000 Binary files a/upgrade-controller-chart/templates.obscpio and /dev/null differ diff --git a/upgrade-controller-chart/templates/NOTES.txt b/upgrade-controller-chart/templates/NOTES.txt new file mode 100644 index 0000000..473a0f4 diff --git a/upgrade-controller-chart/templates/_helpers.tpl b/upgrade-controller-chart/templates/_helpers.tpl new file mode 100644 index 0000000..892acbd --- /dev/null +++ b/upgrade-controller-chart/templates/_helpers.tpl @@ -0,0 +1,83 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "upgrade-controller.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "upgrade-controller.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "upgrade-controller.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "upgrade-controller.labels" -}} +helm.sh/chart: {{ include "upgrade-controller.chart" . }} +{{ include "upgrade-controller.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "upgrade-controller.selectorLabels" -}} +app.kubernetes.io/name: {{ include "upgrade-controller.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "upgrade-controller.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "upgrade-controller.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Webhook service name +*/}} +{{- define "upgrade-controller.webhookServiceName" -}} +{{ .Release.Name }}-webhook +{{- end }} + +{{/* +Certificate issuer name +*/}} +{{- define "upgrade-controller.certificateIssuer" -}} +{{ .Release.Name }}-self-signed-issuer +{{- end }} + +{{/* +Certificate name +*/}} +{{- define "upgrade-controller.certificate" -}} +{{ .Release.Name }}-serving-cert +{{- end }} diff --git a/upgrade-controller-chart/templates/certificate.yaml b/upgrade-controller-chart/templates/certificate.yaml new file mode 100644 index 0000000..6805cdd --- /dev/null +++ b/upgrade-controller-chart/templates/certificate.yaml @@ -0,0 +1,28 @@ +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} + name: {{ include "upgrade-controller.certificateIssuer" . }} + namespace: {{ .Release.Namespace }} +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} + app.kubernetes.io/component: certificate + name: {{ include "upgrade-controller.certificate" . }} + namespace: {{ .Release.Namespace }} +spec: + dnsNames: + - {{ include "upgrade-controller.webhookServiceName" . }}.{{ .Release.Namespace }}.svc + - {{ include "upgrade-controller.webhookServiceName" . }}.{{ .Release.Namespace }}.svc.cluster.local + issuerRef: + kind: Issuer + name: {{ include "upgrade-controller.certificateIssuer" . }} + {{- with first .Values.volumes }} + secretName: {{ .secret.secretName }} + {{- end }} diff --git a/upgrade-controller-chart/templates/clusterrole.yaml b/upgrade-controller-chart/templates/clusterrole.yaml new file mode 100644 index 0000000..8e9c6e7 --- /dev/null +++ b/upgrade-controller-chart/templates/clusterrole.yaml @@ -0,0 +1,114 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "upgrade-controller.fullname" . }} + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - nodes + verbs: + - list + - watch +- apiGroups: + - "" + resources: + - secrets + verbs: + - create + - delete + - get + - list + - watch +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get +- apiGroups: + - batch + resources: + - jobs + verbs: + - create + - get + - list + - watch +- apiGroups: + - batch + resources: + - jobs/status + verbs: + - get +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +- apiGroups: + - helm.cattle.io + resources: + - helmcharts + verbs: + - create + - get + - list + - update + - watch +- apiGroups: + - helm.cattle.io + resources: + - helmcharts/status + verbs: + - get +- apiGroups: + - lifecycle.suse.com + resources: + - releasemanifests + verbs: + - create + - get + - list + - watch +- apiGroups: + - lifecycle.suse.com + resources: + - upgradeplans + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - lifecycle.suse.com + resources: + - upgradeplans/finalizers + verbs: + - update +- apiGroups: + - lifecycle.suse.com + resources: + - upgradeplans/status + verbs: + - get + - patch + - update +- apiGroups: + - upgrade.cattle.io + resources: + - plans + verbs: + - create + - delete + - get + - list + - watch diff --git a/upgrade-controller-chart/templates/clusterrole_binding.yaml b/upgrade-controller-chart/templates/clusterrole_binding.yaml new file mode 100644 index 0000000..5ef4e17 --- /dev/null +++ b/upgrade-controller-chart/templates/clusterrole_binding.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "upgrade-controller.fullname" . }} + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "upgrade-controller.fullname" . }} +subjects: +- kind: ServiceAccount + name: {{ include "upgrade-controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/upgrade-controller-chart/templates/deployment.yaml b/upgrade-controller-chart/templates/deployment.yaml new file mode 100644 index 0000000..4488189 --- /dev/null +++ b/upgrade-controller-chart/templates/deployment.yaml @@ -0,0 +1,85 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "upgrade-controller.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "upgrade-controller.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "upgrade-controller.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "upgrade-controller.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - --leader-elect + - --health-probe-bind-address=:8081 + env: + - name: WATCH_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: RELEASE_MANIFEST_IMAGE + value: {{ .Values.env.releaseManifest.image }} + - name: KUBECTL_IMAGE + value: {{ .Values.env.kubectl.image }} + - name: KUBECTL_VERSION + value: {{ .Values.env.kubectl.version }} + - name: SERVICE_ACCOUNT_NAME + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + ports: + - name: {{ .Values.webhookService.name }} + containerPort: {{ .Values.webhookService.targetPort }} + protocol: TCP + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/upgrade-controller-chart/templates/leader_election_role.yaml b/upgrade-controller-chart/templates/leader_election_role.yaml new file mode 100644 index 0000000..acebc4f --- /dev/null +++ b/upgrade-controller-chart/templates/leader_election_role.yaml @@ -0,0 +1,40 @@ +# permissions to do leader election. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "upgrade-controller.fullname" . }}-leader-election + namespace: {{ .Release.Namespace }} + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} +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/upgrade-controller-chart/templates/leader_election_role_binding.yaml b/upgrade-controller-chart/templates/leader_election_role_binding.yaml new file mode 100644 index 0000000..1a0e7d2 --- /dev/null +++ b/upgrade-controller-chart/templates/leader_election_role_binding.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "upgrade-controller.fullname" . }}-leader-election + namespace: {{ .Release.Namespace }} + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "upgrade-controller.fullname" . }}-leader-election +subjects: +- kind: ServiceAccount + name: {{ include "upgrade-controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/upgrade-controller-chart/templates/serviceaccount.yaml b/upgrade-controller-chart/templates/serviceaccount.yaml new file mode 100644 index 0000000..f860a12 --- /dev/null +++ b/upgrade-controller-chart/templates/serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "upgrade-controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/upgrade-controller-chart/templates/validating_webhook_configuration.yaml b/upgrade-controller-chart/templates/validating_webhook_configuration.yaml new file mode 100644 index 0000000..43ad580 --- /dev/null +++ b/upgrade-controller-chart/templates/validating_webhook_configuration.yaml @@ -0,0 +1,29 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: {{ include "upgrade-controller.fullname" . }}-validating-webhook-configuration + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} + annotations: + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "upgrade-controller.certificate" . }} +webhooks: + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "upgrade-controller.webhookServiceName" . }} + namespace: {{ .Release.Namespace }} + path: /validate-lifecycle-suse-com-v1alpha1-upgradeplan + failurePolicy: Fail + name: upgrade-plan-policy.suse.com + rules: + - apiGroups: + - lifecycle.suse.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - upgradeplans + sideEffects: None diff --git a/upgrade-controller-chart/templates/webhook_service.yaml b/upgrade-controller-chart/templates/webhook_service.yaml new file mode 100644 index 0000000..f8b48fe --- /dev/null +++ b/upgrade-controller-chart/templates/webhook_service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "upgrade-controller.webhookServiceName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "upgrade-controller.labels" . | nindent 4 }} +spec: + type: {{ .Values.webhookService.type }} + ports: + - port: {{ .Values.webhookService.port }} + targetPort: {{ .Values.webhookService.targetPort }} + protocol: TCP + selector: + {{- include "upgrade-controller.selectorLabels" . | nindent 4 }}