Skip to content

Commit

Permalink
support pre/post reconcile scripts
Browse files Browse the repository at this point in the history
Signed-off-by: Travis Glenn Hansen <travisghansen@yahoo.com>
  • Loading branch information
travisghansen committed Jul 21, 2023
1 parent 12952a2 commit d732779
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 7 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
# v0.4.1

Released 2023-07-21

- add additional packages to container image
- support executing arbitrary pre/post scripts during reconcile (should be
idempotent)
- bump docker base image to `hydrogen-bookworm-slim`

# v0.4.0

Released 2023-07-20

- remove management of `TABLE_NAME` in `/etc/iproute2/rt_tables`
- better management of watches to unsubscribe when appropriate
- more robust reconcile logic to prevent race conditions
- support `RULE_FWMARK`

# v0.3.2

Expand Down
16 changes: 13 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:gallium-bullseye-slim AS build
FROM node:hydrogen-bookworm-slim AS build

ENV DEBIAN_FRONTEND=noninteractive

Expand All @@ -19,7 +19,7 @@ COPY . .
######################
# actual image
######################
FROM node:gallium-bullseye-slim
FROM node:hydrogen-bookworm-slim

LABEL org.opencontainers.image.source https://github.com/travisghansen/metallb-node-route-agent

Expand All @@ -31,7 +31,17 @@ ARG BUILDPLATFORM

RUN echo "I am running on final $BUILDPLATFORM, building for $TARGETPLATFORM"

RUN apt-get update && apt-get install -y iproute2 && rm -rf /var/lib/apt/lists/*
RUN apt-get update && \
cd ~ && \
apt-get install -y iproute2 xz-utils conntrack ipset iptables wget curl jq && \
wget -c https://xyne.dev/projects/idemptables/src/idemptables-2012.tar.xz -O - | tar -Jxv && \
install -o root -g root -m 0755 idemptables-2012/idemptables /usr/sbin/idemptables && \
rm -rf idemptables-2012/ && \
sed -i 's:#!/bin/sh:#!/bin/bash:g' /usr/sbin/idemptables && \
curl -LO https://dl.k8s.io/release/v1.27.3/bin/linux/amd64/kubectl && \
install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl && \
rm -rf kubectl && \
rm -rf /var/lib/apt/lists/*

COPY --from=build /app /app

Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,12 @@ your nodes have the sysctl `net.ipv4.fib_multipath_use_neigh` set to `1`.
- `RULE_FWMARK` - the fwmark to give to the managed rules (show be provided in
hex format exactly as the `ip` output shows)
- default: unset
- `DESTINATION` - the `dst` network of the rule
- `DESTINATION` - the `dst` network of the route
- default: `default`
- `PRE_RECONCILE_SCRIPT_PATH` - path to script (must be marked executable) to
run _before_ the reonciliation happens
- `POST_RECONCILE_SCRIPT_PATH` - path to script (must be marked executable) to
run _after_ the reonciliation happens
- `METALLB_NAMESPACE` - namespace where `metallb` is running
- default: `""`
- will fallback to the value in
Expand All @@ -53,6 +57,8 @@ your nodes have the sysctl `net.ipv4.fib_multipath_use_neigh` set to `1`.
- `METALLB_STATIC_FILE` - a static file on the filesystem to monitor (mostly
for development purposes). If set the k8s watch is disabled entirely.
- `METALLB_USE_CRDS` - prefer `CRDs` over configmap
- `LOG_LEVEL` - `error|warn|info|verbose|debug|silly`
- default: `info`
- `CLEANANDEXIT` - if equals `1` then all rules/tables will be deleted and the
process will exit
- `ONESHOT` - if equals `1` then then reconciliation will complete once and the
Expand Down
36 changes: 36 additions & 0 deletions agent.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const _ = require('lodash');
const cp = require('child_process');
const AsyncMutex = require('async-mutex');
const fs = require('fs');
const { IpAddress, IpRange } = require('cidr-calc');
Expand Down Expand Up @@ -58,6 +59,9 @@ const METALLB_USE_CRDS = process.env.METALLB_USE_CRDS;

const NODE_NAME = process.env.NODE_NAME;

const PRE_RECONCILE_SCRIPT_PATH = process.env.PRE_RECONCILE_SCRIPT_PATH;
const POST_RECONCILE_SCRIPT_PATH = process.env.POST_RECONCILE_SCRIPT_PATH;

// globals
let metallb_loaded = false;

Expand Down Expand Up @@ -128,6 +132,22 @@ async function reconcile() {
return;
}

if (PRE_RECONCILE_SCRIPT_PATH) {
logger.verbose(
`executing PRE_RECONCILE_SCRIPT_PATH: ${PRE_RECONCILE_SCRIPT_PATH}`
);
let res = cp.spawnSync(PRE_RECONCILE_SCRIPT_PATH, [], {
timeout: 10 * 1000
});

let message = `executed ${PRE_RECONCILE_SCRIPT_PATH}: code=${res.status}, signal=${res.signal}, stdout=${res.stdout}, stderr=${res.stderr}`;
if (res.status != 0) {
logger.warn(message);
} else {
logger.debug(message);
}
}

let args = [];

//logger.info('skipping reconcile, development debug');
Expand Down Expand Up @@ -351,6 +371,22 @@ async function reconcile() {
}
}

if (POST_RECONCILE_SCRIPT_PATH) {
logger.verbose(
`executing POST_RECONCILE_SCRIPT_PATH: ${POST_RECONCILE_SCRIPT_PATH}`
);
let res = cp.spawnSync(POST_RECONCILE_SCRIPT_PATH, [], {
timeout: 10 * 1000
});

let message = `executed ${POST_RECONCILE_SCRIPT_PATH}: code=${res.status}, signal=${res.signal}, stdout=${res.stdout}, stderr=${res.stderr}`;
if (res.status != 0) {
logger.warn(message);
} else {
logger.debug(message);
}
}

logger.verbose('reconcile finished');
if (process.env.ONESHOT == '1') {
logger.info('exiting due to ONESHOT');
Expand Down
4 changes: 2 additions & 2 deletions charts/metallb-node-route-agent/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.4.0
version: 0.4.1

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "0.4.0"
appVersion: "0.4.1"
13 changes: 13 additions & 0 deletions charts/metallb-node-route-agent/templates/configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "metallb-node-route-agent.fullname" . }}
labels:
{{- include "metallb-node-route-agent.labels" . | nindent 4 }}
data:
config.yaml: |
foo: bar
{{- with .Values.configMapData }}
{{- toYaml . | nindent 2 }}
{{- end }}
8 changes: 8 additions & 0 deletions charts/metallb-node-route-agent/templates/daemonset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ spec:
volumeMounts:
- name: iproute2
mountPath: /etc/iproute2
- name: configmap
mountPath: /tmp/config
readOnly: true
env:
- name: NODE_NAME
valueFrom:
Expand Down Expand Up @@ -66,3 +69,8 @@ spec:
hostPath:
path: /etc/iproute2
type: Directory
- name: configmap
configMap:
name: {{ include "metallb-node-route-agent.fullname" . }}
# 770 in unix decimal
defaultMode: 504
8 changes: 8 additions & 0 deletions charts/metallb-node-route-agent/templates/rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ include "metallb-node-route-agent.serviceAccountName" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "metallb-node-route-agent.labels" . | nindent 4 }}
rules:
- apiGroups:
- ""
Expand All @@ -41,6 +43,8 @@ apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ include "metallb-node-route-agent.serviceAccountName" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{- include "metallb-node-route-agent.labels" . | nindent 4 }}
subjects:
- kind: ServiceAccount
name: {{ include "metallb-node-route-agent.serviceAccountName" . }}
Expand All @@ -54,6 +58,8 @@ kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ include "metallb-node-route-agent.serviceAccountName" . }}
labels:
{{- include "metallb-node-route-agent.labels" . | nindent 4 }}
rules:
- apiGroups:
- ""
Expand All @@ -68,6 +74,8 @@ kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ include "metallb-node-route-agent.serviceAccountName" . }}
labels:
{{- include "metallb-node-route-agent.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
Expand Down
9 changes: 9 additions & 0 deletions charts/metallb-node-route-agent/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""

# all files get mounted to /tmp/config 770 perms
configMapData: {}
# pre.sh: |
# #/bin/bash
# echo hello world
# post.sh: |
# #/bin/bash
# echo hello world

rbac:
enabled: true

Expand Down
8 changes: 7 additions & 1 deletion lib/ip.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,13 @@ class IpCommand {
});

child.on('close', function (code) {
const result = { code, stdout, stderr, timeout: false };
const result = {
code,
stdout,
stderr,
timeout: false,
command: `${command} ${args.join(' ')}`
};

ip.options.logger.debug('ip command result:', result);
// timeout scenario
Expand Down

0 comments on commit d732779

Please sign in to comment.