Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Config Server

This project's own server — the aggregation answer. The server side speaks all nine store crates (including the async three the agent cannot drive yet) and merges files, profiles and remote stores into one document per <application>/<profile>; the agent then speaks the server. The remote book owns the server's full story; what follows is the k8s-side wiring.

Two reasons to put it between the pods and the stores:

  • Credential concentration. A fleet of pods each holding a vault token is a fleet of tokens to rotate. The server holds the store credentials once; the pods hold short client tokens that grant exactly one application's sections.
  • The async stores today. etcd, NATS and S3 reach the agent in 0.2.0 — through the server they work now.

The wiring

The key is <application>/<profile>:

apiVersion: v1
kind: Pod
metadata:
  name: billing
  annotations:
    dynamic-config.rs/inject: "true"
    dynamic-config.rs/source: "config-server"
    dynamic-config.rs/endpoint: "http://config-server.infra.svc:8888"
    dynamic-config.rs/key: "billing/prod"
    dynamic-config.rs/path: "/config/rendered.json"
spec:
  containers:
    - name: app
      image: myapp:1

The bearer token

The server's [[server.clients]] blocks name each client and the applications it may read. The token is a secret; it rides a Secret:

# server.toml, server side
[[server.clients]]
name = "billing-pods"
token = "…at least 32 bytes…"
applications = ["billing"]
kubectl create secret generic config-server-token --from-literal=token=…
    dynamic-config.rs/token-secret: "config-server-token/token"

There is no other method on this store — one bearer, scoped server-side, is the whole model. Asking for auth: anything is refused by the agent with a sentence saying exactly that.

TLS

The server behind TLS from an internal PKI is the same one annotation as everywhere:

    dynamic-config.rs/endpoint: "https://config-server.infra.svc:8443"
    dynamic-config.rs/ca-configmap: "internal-ca"

A server requiring client certificates takes tls-secret alongside.

When it fails

symptomlook atusual cause
401server logthe token is not in any [[server.clients]] block
403server log, applications = […]the client's list does not include this application
404curl $SERVER/billing/prod with the tokenno [[server.sections]] matches the pair
stale valuesthe server's own watch configthe server polls its stores on its own cadence — two intervals stack