update
diff --git a/charts/metallb/templates/NOTES.txt b/charts/metallb/templates/NOTES.txt
new file mode 100644
index 0000000..23d1d5b
--- /dev/null
+++ b/charts/metallb/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/charts/metallb/templates/_helpers.tpl b/charts/metallb/templates/_helpers.tpl
new file mode 100644
index 0000000..53d9528
--- /dev/null
+++ b/charts/metallb/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/charts/metallb/templates/controller.yaml b/charts/metallb/templates/controller.yaml
new file mode 100644
index 0000000..2b522d1
--- /dev/null
+++ b/charts/metallb/templates/controller.yaml
@@ -0,0 +1,182 @@
+{{- 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 }}
+ - --cert-service-name=metallb-webhook-service
+ {{- if .Values.loadBalancerClass }}
+ - --lb-class={{ .Values.loadBalancerClass }}
+ {{- end }}
+ {{- if .Values.controller.webhookMode }}
+ - --webhook-mode={{ .Values.controller.webhookMode }}
+ {{- 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 }}
+ 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 }}
+ 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: webhook-server-cert
+ {{- if .Values.prometheus.controllerMetricsTLSSecret }}
+ - name: metrics-certs
+ secret:
+ secretName: {{ .Values.prometheus.controllerMetricsTLSSecret }}
+ {{- end }}
+{{- end }}
diff --git a/charts/metallb/templates/deprecated_configInline.yaml b/charts/metallb/templates/deprecated_configInline.yaml
new file mode 100644
index 0000000..8a1a551
--- /dev/null
+++ b/charts/metallb/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/charts/metallb/templates/exclude-l2-config.yaml b/charts/metallb/templates/exclude-l2-config.yaml
new file mode 100644
index 0000000..cacea8f
--- /dev/null
+++ b/charts/metallb/templates/exclude-l2-config.yaml
@@ -0,0 +1,23 @@
+{{- if .Values.speaker.excludeInterfaces.enabled }}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: metallb-excludel2
+ namespace: {{ .Release.Namespace | quote }}
+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/charts/metallb/templates/podmonitor.yaml b/charts/metallb/templates/podmonitor.yaml
new file mode 100644
index 0000000..93a7fd6
--- /dev/null
+++ b/charts/metallb/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/charts/metallb/templates/prometheusrules.yaml b/charts/metallb/templates/prometheusrules.yaml
new file mode 100644
index 0000000..463aaca
--- /dev/null
+++ b/charts/metallb/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="{{ include "metallb.name" . }}"} == 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="{{ include "metallb.name" . }}"} == 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="{{ include "metallb.name" . }}"} == 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/charts/metallb/templates/rbac.yaml b/charts/metallb/templates/rbac.yaml
new file mode 100644
index 0000000..ed6b826
--- /dev/null
+++ b/charts/metallb/templates/rbac.yaml
@@ -0,0 +1,210 @@
+{{- 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: ["addresspools.metallb.io","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"]
+{{- 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: Role
+metadata:
+ name: {{ include "metallb.fullname" . }}-pod-lister
+ namespace: {{ .Release.Namespace | quote }}
+ labels: {{- include "metallb.labels" . | nindent 4 }}
+rules:
+- apiGroups: [""]
+ resources: ["pods"]
+ verbs: ["list"]
+- apiGroups: [""]
+ resources: ["secrets"]
+ verbs: ["get", "list", "watch"]
+- apiGroups: [""]
+ resources: ["configmaps"]
+ verbs: ["get", "list", "watch"]
+- apiGroups: ["metallb.io"]
+ resources: ["addresspools"]
+ 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: ["addresspools"]
+ verbs: ["get", "list", "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/charts/metallb/templates/service-accounts.yaml b/charts/metallb/templates/service-accounts.yaml
new file mode 100644
index 0000000..9615acf
--- /dev/null
+++ b/charts/metallb/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/charts/metallb/templates/servicemonitor.yaml b/charts/metallb/templates/servicemonitor.yaml
new file mode 100644
index 0000000..1cfc0c4
--- /dev/null
+++ b/charts/metallb/templates/servicemonitor.yaml
@@ -0,0 +1,193 @@
+{{- 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
+ 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/charts/metallb/templates/speaker.yaml b/charts/metallb/templates/speaker.yaml
new file mode 100644
index 0000000..1a4c7b2
--- /dev/null
+++ b/charts/metallb/templates/speaker.yaml
@@ -0,0 +1,510 @@
+{{- 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 7.5.1
+ 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
+ volumes:
+ {{- 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: {}
+ {{- if .Values.prometheus.speakerMetricsTLSSecret }}
+ - name: metrics-certs
+ secret:
+ secretName: {{ .Values.prometheus.speakerMetricsTLSSecret }}
+ {{- end }}
+ 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: ["/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.speaker.image.repository }}:{{ .Values.speaker.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
+ {{- 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 }}
+ env:
+ - name: METALLB_NODE_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: spec.nodeName
+ - name: METALLB_HOST
+ valueFrom:
+ fieldRef:
+ fieldPath: status.hostIP
+ {{- if .Values.speaker.memberlist.enabled }}
+ - name: METALLB_ML_BIND_ADDR
+ valueFrom:
+ fieldRef:
+ fieldPath: status.podIP
+ - 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 }}
+ 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:
+ 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:
+ 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:
+ 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:
+ 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 }}
+ 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://$(METALLB_HOST):{{ .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
+ 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 }}
+ {{- 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://$(METALLB_HOST):{{ .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: metricshttps
+ 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 }}
+ 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/charts/metallb/templates/webhooks.yaml b/charts/metallb/templates/webhooks.yaml
new file mode 100644
index 0000000..3b587a4
--- /dev/null
+++ b/charts/metallb/templates/webhooks.yaml
@@ -0,0 +1,170 @@
+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-v1beta1-addresspool
+ failurePolicy: {{ .Values.crds.validationFailurePolicy }}
+ name: addresspoolvalidationwebhook.metallb.io
+ rules:
+ - apiGroups:
+ - metallb.io
+ apiVersions:
+ - v1beta1
+ operations:
+ - CREATE
+ - UPDATE
+ resources:
+ - addresspools
+ sideEffects: None
+- 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: webhook-server-cert
+ namespace: {{ .Release.Namespace | quote }}
+ labels:
+ {{- include "metallb.labels" . | nindent 4 }}