demo-go-app's Deployment failed to pull: "dial tcp: lookup harbor-core.harbor.svc.cluster.local on 127.0.0.53:53: server misbehaving". docker push worked from the Jenkins build pod because it has pod-network DNS (CoreDNS); pulling for a real Deployment happens via containerd on the node itself, using the node's host-level resolver, which has no route to *.svc.cluster.local at all. Switches buildDocker.groovy's push target and dind-pod.yaml's --insecure-registry flag to the Contour ingress hostname instead, which resolves via normal public DNS (nip.io) from both pods and the host.
91 lines
4.1 KiB
YAML
91 lines
4.1 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
|
|
# Harbor's ingress serves plain HTTP too (TLS disabled cluster-wide
|
|
# by design — see claude.md's "everything is plain HTTP" note).
|
|
# Docker defaults to attempting HTTPS against any bare registry
|
|
# hostname regardless of network path, so this is needed
|
|
# regardless of which hostname is used — was previously
|
|
# harbor-core.harbor.svc.cluster.local (cluster-internal Service
|
|
# DNS, works from this pod but not from the node's own containerd
|
|
# when pulling for a real Deployment); switched to the Contour
|
|
# ingress hostname so push and pull can share one reference.
|
|
args:
|
|
- "--insecure-registry=harbor.192.168.1.7.nip.io"
|
|
env:
|
|
- name: DOCKER_TLS_CERTDIR
|
|
value: ""
|
|
volumeMounts:
|
|
- name: docker-graph-storage
|
|
mountPath: /var/lib/docker
|
|
- name: docker-cli
|
|
image: docker:27-cli
|
|
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
|