| {{- 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 }} |