Added amnezia exporter
Update Kubernetes Services Wiki / Generate and Update K8s Wiki (push) Successful in 8s
Check with kubeconform / lint (push) Successful in 7s
Auto-update README / Generate README and Create MR (push) Successful in 11s

This commit is contained in:
Ultradesu
2026-06-29 20:46:07 +03:00
parent 976ea1fbe1
commit 67104123a5
7 changed files with 273 additions and 8 deletions
+102 -6
View File
@@ -128,6 +128,9 @@ data:
SERVER_CONFIG="/etc/amnezia/server/awg0.conf"
CLIENTS_DIR="/etc/amnezia/clients"
RUNTIME_CONFIG="/run/amnezia/awg0.conf"
SYNC_CONFIG="/run/amnezia/awg0.sync.conf"
STATUS_FILE="/run/amnezia/reload-status"
RELOAD_INTERVAL="${AMNEZIAWG_RELOAD_INTERVAL:-10}"
cleanup() {
if awg show awg0 >/dev/null 2>&1; then
@@ -137,32 +140,125 @@ data:
render_config() {
mkdir -p "$(dirname "${RUNTIME_CONFIG}")"
cp "${SERVER_CONFIG}" "${RUNTIME_CONFIG}"
chmod 0600 "${RUNTIME_CONFIG}"
local tmp_config="${RUNTIME_CONFIG}.tmp"
cp "${SERVER_CONFIG}" "${tmp_config}"
chmod 0600 "${tmp_config}"
local clients_found=0
for client_config in "${CLIENTS_DIR}"/*; do
[ -f "${client_config}" ] || continue
[ -s "${client_config}" ] || continue
printf '\n' >> "${RUNTIME_CONFIG}"
cat "${client_config}" >> "${RUNTIME_CONFIG}"
printf '\n' >> "${tmp_config}"
cat "${client_config}" >> "${tmp_config}"
clients_found=1
done
if [ "${clients_found}" = "0" ]; then
echo "No client peer configs found in ${CLIENTS_DIR}; starting without peers"
fi
mv "${tmp_config}" "${RUNTIME_CONFIG}"
chmod 0600 "${RUNTIME_CONFIG}"
}
client_config_hash() {
{
for client_config in "${CLIENTS_DIR}"/*; do
[ -f "${client_config}" ] || continue
sha256sum "${client_config}"
done
} | sha256sum | awk '{print $1}'
}
write_reload_status() {
local state="${1}"
local hash="${2:-}"
local applied_at_ms=""
if [ "${state}" = "applied" ]; then
applied_at_ms="$(($(date +%s) * 1000))"
fi
mkdir -p "$(dirname "${STATUS_FILE}")"
{
printf 'state=%s\n' "${state}"
printf 'hash=%s\n' "${hash}"
printf 'applied_at_ms=%s\n' "${applied_at_ms}"
} > "${STATUS_FILE}.tmp"
mv "${STATUS_FILE}.tmp" "${STATUS_FILE}"
}
apply_live_config() {
render_config
awg-quick strip "${RUNTIME_CONFIG}" > "${SYNC_CONFIG}"
chmod 0600 "${SYNC_CONFIG}"
awg syncconf awg0 "${SYNC_CONFIG}"
}
watch_client_config() {
local last_hash="${1}"
while true; do
sleep "${RELOAD_INTERVAL}" &
wait "$!" || return 0
local current_hash
current_hash="$(client_config_hash)"
if [ "${current_hash}" = "${last_hash}" ]; then
continue
fi
echo "Detected AmneziaWG client peer config change; applying with awg syncconf"
if apply_live_config; then
last_hash="${current_hash}"
write_reload_status applied "${current_hash}"
awg show awg0 || true
else
echo "ERROR: failed to hot-reload AmneziaWG client peer config" >&2
write_reload_status error "${current_hash}"
fi
done
}
trap cleanup EXIT
trap 'exit 0' TERM INT
initial_hash="$(client_config_hash)"
render_config
cleanup
awg-quick up "${RUNTIME_CONFIG}"
awg show awg0 || true
write_reload_status applied "${initial_hash}"
watch_client_config "${initial_hash}"
status-patch.sh: |
#!/usr/bin/env bash
set -euo pipefail
STATUS_FILE="/run/amnezia/reload-status"
PATCH_INTERVAL="${AMNEZIAWG_STATUS_PATCH_INTERVAL:-5}"
NAMESPACE="${POD_NAMESPACE:-$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)}"
: "${POD_NAME:?POD_NAME is required}"
last_file_hash=""
patch_status() {
local state="unknown"
local hash=""
local applied_at_ms=""
# The file is generated by run.sh and contains only shell assignments.
# shellcheck disable=SC1090
source "${STATUS_FILE}"
kubectl patch pod "${POD_NAME}" -n "${NAMESPACE}" --type merge -p "{\"metadata\":{\"annotations\":{\"amnezia-fellow.hexor.cy/client-secret-reload-status\":\"${state}\",\"amnezia-fellow.hexor.cy/client-secret-applied-at-ms\":\"${applied_at_ms}\",\"amnezia-fellow.hexor.cy/client-secret-applied-hash\":\"${hash}\"}}}"
}
while true; do
sleep 3600 &
wait "$!"
if [ -f "${STATUS_FILE}" ]; then
file_hash="$(sha256sum "${STATUS_FILE}" | awk '{print $1}')"
if [ "${file_hash}" != "${last_file_hash}" ]; then
patch_status || true
last_file_hash="${file_hash}"
fi
fi
sleep "${PATCH_INTERVAL}"
done
+97 -2
View File
@@ -6,8 +6,8 @@ metadata:
labels:
app: amneziawg
annotations:
reloader.stakater.com/auto: "true"
secret.reloader.stakater.com/reload: "amneziawg-server,amneziawg-clients"
secret.reloader.stakater.com/reload: "amneziawg-server"
configmap.reloader.stakater.com/reload: "amneziawg-scripts"
spec:
selector:
matchLabels:
@@ -27,6 +27,19 @@ spec:
tolerations:
- operator: Exists
initContainers:
- name: install-awg
image: amneziavpn/amneziawg-go:latest
imagePullPolicy: IfNotPresent
command:
- /bin/bash
- -lc
- |
set -euo pipefail
cp /usr/bin/awg /shared-bin/awg
chmod 0755 /shared-bin/awg
volumeMounts:
- name: awg-bin
mountPath: /shared-bin
- name: register-endpoint
image: bitnami/kubectl:latest
imagePullPolicy: IfNotPresent
@@ -123,6 +136,81 @@ spec:
mountPath: /run/amnezia
- name: dev-net-tun
mountPath: /dev/net/tun
- name: reload-status
image: bitnami/kubectl:latest
imagePullPolicy: IfNotPresent
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
command:
- /bin/bash
- /scripts/status-patch.sh
resources:
requests:
memory: "32Mi"
cpu: "10m"
limits:
memory: "128Mi"
cpu: "100m"
volumeMounts:
- name: scripts
mountPath: /scripts
readOnly: true
- name: runtime-config
mountPath: /run/amnezia
- name: amneziawg-exporter-redis
image: redis:alpine
imagePullPolicy: IfNotPresent
command:
- redis-server
- /etc/redis/redis.conf
ports:
- name: redis
containerPort: 6379
protocol: TCP
resources:
requests:
memory: "32Mi"
cpu: "10m"
limits:
memory: "128Mi"
cpu: "100m"
volumeMounts:
- name: exporter-redis-config
mountPath: /etc/redis
readOnly: true
- name: exporter-redis-data
mountPath: /data
- name: amneziawg-exporter
image: amneziavpn/amneziawg-exporter:latest
imagePullPolicy: IfNotPresent
securityContext:
capabilities:
add:
- NET_ADMIN
env:
- name: AWG_EXPORTER_REDIS_HOST
value: "127.0.0.1"
- name: AWG_EXPORTER_REDIS_PORT
value: "6379"
ports:
- name: metrics
containerPort: 9351
protocol: TCP
resources:
requests:
memory: "64Mi"
cpu: "25m"
limits:
memory: "256Mi"
cpu: "200m"
volumeMounts:
- name: awg-bin
mountPath: /usr/bin/awg
subPath: awg
readOnly: true
volumes:
- name: server-config
secret:
@@ -142,6 +230,13 @@ spec:
defaultMode: 0755
- name: runtime-config
emptyDir: {}
- name: awg-bin
emptyDir: {}
- name: exporter-redis-config
configMap:
name: amneziawg-exporter-redis
- name: exporter-redis-data
emptyDir: {}
- name: dev-net-tun
hostPath:
path: /dev/net/tun
@@ -0,0 +1,28 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: amneziawg-exporter-redis
labels:
app: amneziawg
component: exporter
data:
redis.conf: |
bind 0.0.0.0
protected-mode no
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
pidfile /run/redis.pid
loglevel warning
logfile ""
databases 16
always-show-logo no
set-proc-title no
save 3600 1
stop-writes-on-bgsave-error no
rdbcompression yes
rdbchecksum yes
dir /data
+17
View File
@@ -0,0 +1,17 @@
---
apiVersion: v1
kind: Service
metadata:
name: amneziawg-exporter
labels:
app: amneziawg
component: exporter
spec:
type: ClusterIP
selector:
app: amneziawg
ports:
- name: metrics
protocol: TCP
port: 9351
targetPort: 9351
+3
View File
@@ -12,4 +12,7 @@ resources:
- fellow-service.yaml
- fellow-ingress.yaml
- fellow-deployment.yaml
- exporter-redis-configmap.yaml
- exporter-service.yaml
- servicemonitor.yaml
- daemonset.yaml
+3
View File
@@ -42,6 +42,9 @@ rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "create", "patch"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
+23
View File
@@ -0,0 +1,23 @@
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: amneziawg-exporter
labels:
app: amneziawg
component: exporter
release: prometheus
spec:
selector:
matchLabels:
app: amneziawg
component: exporter
endpoints:
- port: metrics
path: /metrics
interval: 30s
scrapeTimeout: 10s
honorLabels: true
namespaceSelector:
matchNames:
- amnezia