GKE: point the pipeline at this cluster's registry, over TLS

The GCP counterpart of devops-lib. Registered in Jenkins under the same
name, so consuming repos need no change: the two-line Jenkinsfile is
identical on both clusters, and which library it resolves to is a property
of the Jenkins running it.

Substantive changes, all consequences of GKE being a real cloud:

- Harbor speaks TLS here, so dind no longer passes --insecure-registry.
  It mounts the private CA at
  /etc/docker/certs.d/harbor.35.238.248.203.nip.io/ca.crt instead, from the
  registry-ca ConfigMap. This is not redundant with the node pool's trust:
  that covers pulls, performed by containerd on the node, while the push
  comes from dockerd in the build pod with its own trust store. Without it,
  pushes fail TLS verification while pulls of the same image succeed —
  which reads like a broken registry rather than a missing trust anchor.

- The registry hostname changes in the push target and all five fallback
  Dockerfiles. It still must be spelled identically everywhere, because
  Docker matches credentials and trust by exact hostname.

- helm_repo_url moves to cluster DNS. That clone runs in a build pod, so
  sending it out through the ingress and back would make the pipeline
  depend on Contour for pod-to-pod traffic. syncArgoApp already addressed
  ArgoCD this way and needed no change.

- build-tools.Dockerfile is removed: devops-base-images-gcp owns it now,
  next to the mirrored base images, and the pod references the result by
  tag at base-images/build-tools:1. The base-images project is public, so
  the pod can pull it before it has any credentials.

Verified: no homelab addresses remain; the pod template parses with the CA
mount, the new image and no insecure-registry flag; and every fallback
template's base image, with the default version buildDocker would pick, is
present in the mirror manifest — an unmirrored tag now fails the build
rather than silently falling back to Docker Hub.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LEsTefWWifp4ikvhHF5s6N
This commit is contained in:
Mukul Sharma
2026-09-13 01:27:05 +05:30
co-authored by Claude Opus 5
parent 43ca78e83e
commit 3e09eecbfe
11 changed files with 127 additions and 65 deletions
+58 -14
View File
@@ -1,11 +1,32 @@
# devops-lib
# devops-lib (GKE)
Jenkins Shared Library for this homelab's CI/CD pipeline. Adapted from a
much larger, company-wide library — everything not needed for a
single-node homelab (GKE/EKS, JFrog, S3, Sonar, org-specific BU/team
validation, and ~65 other files covering languages/deploy-targets this
setup never uses) has been removed rather than carried along unused; see
git history if any of that is ever worth reviving.
Jenkins Shared Library for the CI/CD pipeline on the GKE cluster. The GCP
counterpart of the homelab repo of the same name, and a copy rather than a
shared repo because several values here are cluster-specific in ways that
would break the other cluster if crossed over.
Register it in Jenkins under the name `devops-lib`, exactly as on the
homelab. Consuming repos then need no change at all — the same two-line
Jenkinsfile works on either cluster, and which library it resolves to is a
property of the Jenkins it runs on.
**What differs from the homelab copy**, all of it a consequence of GKE
being a real cloud rather than one VM:
- **The registry hostname** is `harbor.35.238.248.203.nip.io`, in the push
target and in all five fallback Dockerfiles.
- **Harbor speaks TLS.** The homelab's dind passes `--insecure-registry`;
here the pod mounts the private CA into dockerd's trust store instead.
Node trust covers pulls only — a push is a separate client.
- **`helm_repo_url` uses cluster DNS**, since the clone happens inside a
build pod. The homelab points it at an ingress hostname.
- **`build-tools` is not in this repo.** It lives in
`devops-base-images-gcp` alongside the mirrored base images, and is
referenced here only by tag.
Everything else — the stage flow, the fallback templates, the hooks
contract — is unchanged. The library was already adapted from a much
larger, company-wide one; see git history for what was removed.
## Using it in a service repo
@@ -26,7 +47,7 @@ in after checkout; repo-committed values win over the Jenkinsfile call).
| `service_name` | `repo_name` | Second path segment under `devops-helm-charts/values/` |
| `argo_app_name` | `repo_name` | Must match the ArgoCD Application's `metadata.name` |
| `harbor_project` | `homelab` | Must be an existing, public Harbor project |
| `helm_repo_url` | `devops-helm-charts` on this Gitea | — |
| `helm_repo_url` | `devops-helm-charts-gcp`, over cluster DNS | `http://gitea-http.gitea.svc.cluster.local:3000/gitadmin/…` — pod-to-pod, so it never leaves the cluster and comes back through the ingress |
| `image_tag_yq_path` | `.deployment.image.tag` | **Override this if the app's chart isn't `1.0.0`** — e.g. `sts-2.0.0` uses `.podtemplate.image.tag` instead. Getting this wrong doesn't fail loudly: `yq -i` creates the path if missing rather than erroring, silently leaving the real field un-bumped. |
| `dockerBuildVersion` | none | Only read when the repo has **no Dockerfile of its own** — picks a fallback template (see below). No default; either ship a Dockerfile or set this. |
@@ -49,7 +70,9 @@ a `podTemplate` (`resources/org/homelab/dind-pod.yaml`) via
based on `dockerBuildVersion` (e.g. `go-1.22`, `node-20`,
`python-3.12`, `java-21`, `php-8.3`). All fallback templates pull base
images from Harbor's `base-images` project (mirrored via the separate
`devops-base-images` repo), not Docker Hub directly.
`devops-base-images-gcp` repo), not Docker Hub directly. Only versions
actually mirrored there resolve — an unmirrored tag fails the build
rather than silently falling back to Docker Hub.
- **`updateHelmTag`** — clones `devops-helm-charts`, bumps the image tag
via `yq` at `image_tag_yq_path`, commits, pushes to `main`.
- **`syncArgoApp`** — calls the ArgoCD REST API to sync `argo_app_name`.
@@ -65,8 +88,29 @@ a `podTemplate` (`resources/org/homelab/dind-pod.yaml`) via
## Build-tools image
`resources/org/homelab/build-tools.Dockerfile` bakes git/yq/bash/
python3+pip/venv/curl into the `docker-cli` container's image, so
nothing gets installed on demand on every single build. Built and pushed
manually (not through any Jenkins job) — see that file's own header
comment.
The `docker-cli` container runs
`harbor.35.238.248.203.nip.io/base-images/build-tools:1`, which bakes in
git, yq, bash, python3 with pip and venv, and curl, so nothing is installed
on demand on every build.
**It is not built here.** The Dockerfile lives in `devops-base-images-gcp`,
next to the mirrored base images, because it is the same kind of artefact:
built by hand, occasionally, and pushed to Harbor. A Jenkins job could not
build it anyway — it is the image Jenkins builds *in*.
`dind-pod.yaml` pins the tag, so rebuilding the image rolls nothing out
until that pin is bumped. Bump the tag rather than overwriting one.
## Registry trust
`dind-pod.yaml` mounts the `registry-ca` ConfigMap (published by
`devops-infra-argo-config-gcp`) into the dind container at
`/etc/docker/certs.d/harbor.35.238.248.203.nip.io/ca.crt`.
Without it, pushes fail TLS verification while pulls of the same image
succeed, which reads like a broken registry. The reason is that the two are
different clients: pulls are performed by containerd on the node, which was
told to trust this CA when the node pool was created, whereas the push comes
from dockerd inside the build pod, which has its own trust store. The
directory name must be the registry hostname exactly — dockerd looks the
path up by host and silently ignores a mismatch.