Database Connection

Configuring BookNest's Database Connection

BookNest's connection settings split cleanly: host, port and database name are configuration; the user name and password are credentials. The ConfigMap goes into Git 1,932 :

k8s/api-config.yaml: the API's non-secret settingsYAML
apiVersion: v1
kind: ConfigMap
metadata: { name: api-config, labels: { app: booknest, tier: api } }
data: { PGHOST: db, PGPORT: "5432", PGDATABASE: booknest, NODE_ENV: production }

The Secret does not. Docker's db/index.js already reads the password from the file named by PGPASSWORD_FILE, so the Deployment mounts the Secret as a volume. In k8s/api-deployment.yaml, the container's env list becomes the following, with the Pod-level fsGroup letting the non-root user read the mounted file:

The API's configuration in k8s/api-deployment.yamlYAML
    spec:
      securityContext: { fsGroup: 1000 }
      containers:
      - name: api
        ...
        envFrom: [{ configMapRef: { name: api-config } }]
        env:
        - name: PGUSER
          valueFrom: { secretKeyRef: { name: db-credentials, key: username } }
        - { name: PGPASSWORD_FILE, value: /run/secrets/db/password }
        volumeMounts: [{ name: db-credentials, mountPath: /run/secrets/db, readOnly: true }]
        ...
      volumes:
      - { name: db-credentials, secret: { secretName: db-credentials, defaultMode: 0440 } }
Creating the Secret, rolling out the new configuration and checking itShell
kubectl create secret generic db-credentials --from-literal=username=booknest \
  --from-literal=password=booknest
kubectl apply -f k8s/api-config.yaml -f k8s/api-deployment.yaml
kubectl rollout status deployment/api --timeout=120s | tail -1
kubectl exec deploy/api -- sh -c 'env | grep ^PG | sort; ls -lL /run/secrets/db'
kubectl exec deploy/api -- node -e "fetch('http://127.0.0.1:3000/ready').then(r => r.text())
  .then(console.log)"
git add k8s/api-config.yaml k8s/api-deployment.yaml
git commit -qm "Move the API's database settings into a ConfigMap and a Secret"
Output
secret/db-credentials created
configmap/api-config created
deployment.apps/api configured
deployment "api" successfully rolled out
PGDATABASE=booknest
PGHOST=db
PGPASSWORD_FILE=/run/secrets/db/password
PGPORT=5432
PGUSER=booknest
total 8
-r--r----- 1 root node 8 Sep 25 16:04 password
-r--r----- 1 root node 8 Sep 25 16:04 username
{"status":"ready"}

The password is no longer in any manifest, in kubectl 5,150 describe or in the process environment, and /ready proves the API reached PostgreSQL 1,289 with it. The value is still the throwaway database's booknest; StatefulSets and PostgreSQL replaces that database with a StatefulSet and a generated password stored in this same Secret.