Files
devops-lib-gcp/resources/org/homelab/dind-pod.yaml
T
Mukul SharmaandClaude Opus 5 6d743cbe48 Make the registry hostname configurable and drop the CA mount
buildDocker.groovy hardcoded harbor.35.238.248.203.nip.io as the push
target, so the registry could not move without editing this shared library
and every consumer moving in the same commit. It now reads
config.harbor_registry, whose default lives in homelabPipeline.groovy
beside harbor_project and every other key.

The stage errors rather than defaulting when the value is missing. Carrying
a second copy of the literal would leave two defaults free to disagree, and
an unset value would otherwise build an image named "null/<project>/<repo>"
— which docker accepts as a hostname and then fails to resolve, pointing
nowhere near the cause.

The dind pod no longer mounts the registry CA. That mount existed because
the registry was a nip.io name, which no public CA will issue for, so
cert-manager signed Harbor from a private CA; the node pool was told to
trust it for pulls, but a push comes from dockerd inside the build pod,
which has its own trust store. harbor.infra.deployshed.com carries a Let's
Encrypt certificate that both already trust, so the mount, its volume and
the whole arrangement go away rather than being repointed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LEsTefWWifp4ikvhHF5s6N
2026-09-17 09:31:32 +05:30

112 lines
5.4 KiB
YAML

# New resource — didn't exist in the original devops-lib. Homelab's real
# pipelines built on static agents (node('slave02')) with Docker already
# available; this homelab's Jenkins uses dynamic per-build Kubernetes
# agents (agent.enabled in the jenkins chart), which don't have a Docker
# daemon by default. This pod template adds one as a sidecar container —
# the "docker" container runs privileged dind, "docker-cli" is what the
# pipeline actually execs into via container('docker-cli'), talking to
# its sibling over localhost since containers in one pod share a network
# namespace.
apiVersion: v1
kind: Pod
spec:
containers:
- name: docker
image: docker:27-dind
securityContext:
privileged: true
# No --insecure-registry and no mounted CA: Harbor is reached at
# harbor.infra.deployshed.com, which carries a publicly trusted Let's
# Encrypt certificate, so dockerd's own trust store already accepts it
# with nothing configured.
#
# This previously mounted the private registry CA here, because the
# registry was a nip.io name that no public CA can issue for (nip.io is
# not on the public suffix list, and every *.nip.io certificate shares
# one rate limit), so cert-manager signed it from a private CA instead.
# A pull was fine — the node pool was told to trust that CA and
# containerd performs pulls — but a push is a different client with its
# own trust store, which is why dockerd needed the CA at
# /etc/docker/certs.d/<registry host>/ca.crt. Moving to a real domain
# removes the whole arrangement rather than repointing it.
#
# The registry is still named by its ingress hostname rather than
# harbor-core.harbor.svc.cluster.local, for a reason that still holds:
# cluster DNS resolves from this pod but not from the node's containerd
# doing the real Deployment pull, and Docker matches both stored
# credentials and trust by exact hostname — so push and pull have to
# name the registry identically.
env:
- name: DOCKER_TLS_CERTDIR
value: ""
volumeMounts:
- name: docker-graph-storage
mountPath: /var/lib/docker
- name: docker-cli
# Custom image, built and pushed by hand from devops-base-images-gcp
# (build-tools.Dockerfile there) — bakes in git/yq/bash/python3 with
# pip and venv/curl so nothing needs installing on every single build,
# which was slow and quietly undermined reproducibility.
#
# It lives in the base-images project rather than homelab because that
# project is public: this pod pulls the image before any credential is
# available to it.
#
# Versioned tag, never :latest — rebuilding the tools image must not
# roll out until this pin is bumped deliberately.
image: harbor.infra.deployshed.com/base-images/build-tools:1
command: ["cat"]
tty: true
env:
- name: DOCKER_HOST
value: tcp://localhost:2375
# docker-config below mounts the Harbor push-auth secret
# read-only at /root/.docker (needed so `docker push` finds
# config.json without an explicit `docker login` step) — but
# modern `docker build` defaults to BuildKit/buildx, which wants
# to create its own state dir at /root/.docker/buildx and fails
# with "read-only file system" since the whole mount is
# read-only. Forcing the classic builder avoids needing to write
# there at all.
- name: DOCKER_BUILDKIT
value: "0"
# For syncArgoApp.groovy — read directly from the ESO-managed
# Secret, not a Jenkins-native credential (nothing in this
# pipeline uses Jenkins' own credential store; staying consistent
# rather than mixing the two approaches).
- name: ARGOCD_TOKEN
valueFrom:
secretKeyRef:
name: argocd-jenkins-ci-token
key: token
# Without this, every build using this pod template hard-fails
# to even start until the token secret exists — including the
# very first demo-go-app run, before the manual
# `argocd account generate-token` bootstrap step has happened.
optional: true
volumeMounts:
- name: docker-config
mountPath: /root/.docker
readOnly: true
volumes:
- name: docker-graph-storage
emptyDir: {}
- name: docker-config
secret:
secretName: harbor-robot-dockerconfig
# kubernetes.io/dockerconfigjson secrets store their data under
# the fixed key `.dockerconfigjson` (mandated, since that's what
# kubelet reads for imagePullSecrets) — without this remap, the
# mounted file at /root/.docker is literally named
# `.dockerconfigjson`, not `config.json`, which is the only
# filename the docker CLI itself ever reads for stored
# credentials. Docker found nothing there and silently pushed
# unauthenticated, which Harbor correctly rejected as
# unauthorized — confirmed the robot account/credentials
# themselves were fine the whole time by requesting a push token
# directly from Harbor's token endpoint with the same username/
# password and getting one back with push access granted.
items:
- key: .dockerconfigjson
path: config.json