fix(build): default Kaniko and init images to Harbor via Helm values
Build and Deploy Platform / build-and-deploy (push) Successful in 14m57s

User-app builds no longer pull gcr.io/docker.io directly when build.images
is configured in values.yaml, fixing ImagePullBackOff on clusters without
upstream registry access.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
keyhan
2026-07-03 14:20:36 +03:30
parent 8163665c86
commit d3bbc0c0a0
10 changed files with 82 additions and 24 deletions
+5
View File
@@ -75,6 +75,11 @@ REGISTRY_PASSWORD=registry_secret
# Build
BUILD_NAMESPACE=cloudhost-builds
BUILD_SERVICE_ACCOUNT=kaniko-builder
# Kaniko job images — defaults pull from Harbor proxy-cache when unset.
# KANIKO_IMAGE=registry.abrban.com/proxy-gcr/kaniko-project/executor:v1.23.2
# BUILD_ALPINE_IMAGE=registry.abrban.com/proxy-dockerhub/library/alpine:3.19
# BUILD_ALPINE_GIT_IMAGE=registry.abrban.com/proxy-dockerhub/alpine/git:2.43.0
# BASE_IMAGE_REGISTRY=registry.abrban.com/proxy-dockerhub/library
# Platform
# Public URL(s) of the frontend — used for CORS and to derive the platform/preview
@@ -113,3 +113,14 @@ PLATFORM_DOMAIN / preview domain from the first entry only. The panel host
{{- define "cloudhost-platform.frontendImage" -}}
{{- printf "%s:%s" .Values.images.frontend.repository .Values.images.frontend.tag }}
{{- end }}
{{- define "cloudhost-platform.buildEnv" -}}
- name: KANIKO_IMAGE
value: {{ .Values.build.images.kaniko | quote }}
- name: BUILD_ALPINE_IMAGE
value: {{ .Values.build.images.alpine | quote }}
- name: BUILD_ALPINE_GIT_IMAGE
value: {{ .Values.build.images.alpineGit | quote }}
- name: BASE_IMAGE_REGISTRY
value: {{ .Values.build.baseImageRegistry | quote }}
{{- end }}
@@ -100,6 +100,7 @@ spec:
key: cluster-kubeconfig-key
- name: FRONTEND_URL
value: {{ include "cloudhost-platform.corsOrigins" . | quote }}
{{- include "cloudhost-platform.buildEnv" . | nindent 12 }}
{{- range $key, $val := .Values.backend.env }}
- name: {{ $key }}
value: {{ $val | quote }}
@@ -22,6 +22,14 @@ images:
tag: "1.0.0"
pullPolicy: Always
# Build job images — override for clusters without Harbor proxy-cache.
build:
images:
kaniko: registry.example.com/proxy-gcr/kaniko-project/executor:v1.23.2
alpine: registry.example.com/proxy-dockerhub/library/alpine:3.19
alpineGit: registry.example.com/proxy-dockerhub/alpine/git:2.43.0
baseImageRegistry: registry.example.com/proxy-dockerhub/library
postgres:
password: "CHANGE_ME_STRONG_POSTGRES_PASSWORD"
# Pull secret for the mirrored postgres image
@@ -58,8 +66,6 @@ backend:
PLATFORM_DOMAIN: apps.example.com
REGISTRY_URL: registry.cloudhost-builds.svc.cluster.local:5000
REGISTRY_PULL_URL: registry.cloudhost-builds.svc.cluster.local:5000
# Mirror prefix for base images in generated Dockerfiles + managed services
BASE_IMAGE_REGISTRY: registry.example.com/mirror
# Elastic log-stack credentials (must match the logging namespace Secret)
ELASTIC_PASSWORD: "CHANGE_ME_ELASTIC_PASSWORD"
FLUENTBIT_PASSWORD: "CHANGE_ME_FLUENTBIT_PASSWORD"
@@ -28,6 +28,16 @@ images:
tag: "1.0.0"
pullPolicy: IfNotPresent
# Kaniko job images — defaults pull from Harbor proxy-cache.
# Override any line for a different registry/tag.
build:
images:
kaniko: registry.abrban.com/proxy-gcr/kaniko-project/executor:v1.23.2
alpine: registry.abrban.com/proxy-dockerhub/library/alpine:3.19
alpineGit: registry.abrban.com/proxy-dockerhub/alpine/git:2.43.0
# Prefix for Docker Hub images in generated user-app Dockerfiles (node, php, …)
baseImageRegistry: registry.abrban.com/proxy-dockerhub/library
postgres:
enabled: true
database: cloudhost
+17 -11
View File
@@ -56,12 +56,6 @@ export class BuildService {
private readonly logger = new Logger(BuildService.name);
private readonly progressMap = new Map<string, BuildProgress>();
private readonly activeBuilds = new Map<string, ActiveBuildSession>();
/**
* Kaniko executor image. Pinned (not `:latest`) so it can be cached on the node
* with imagePullPolicy=IfNotPresent — avoids re-pulling the ~250MB image on every build.
*/
private readonly kanikoImage = process.env.KANIKO_IMAGE || 'gcr.io/kaniko-project/executor:v1.23.2';
constructor(
private configService: ConfigService,
private clustersService: ClustersService,
@@ -85,6 +79,18 @@ export class BuildService {
return `${prefix}/${image}`;
}
/** Kaniko executor — pinned (not :latest) for node-level caching. */
private getKanikoImage(): string {
return this.configService.get<string>('build.images.kaniko')!;
}
/** Init/helper container image — explicit Harbor ref or baseImage() fallback. */
private resolveBuildImage(kind: 'alpine' | 'alpineGit', dockerHubFallback: string): string {
const explicit = this.configService.get<string>(`build.images.${kind}`);
if (explicit) return explicit;
return this.baseImage(dockerHubFallback);
}
/**
* Git branch names come from users and end up in a shell command — accept
* only conservative ref characters and reject anything option-like.
@@ -548,7 +554,7 @@ export class BuildService {
// Add init container that unzips the source code from PVC
initContainers.push({
name: 'unzip-source',
image: this.baseImage('alpine:3.19'),
image: this.resolveBuildImage('alpine', 'alpine:3.19'),
imagePullPolicy: 'IfNotPresent',
command: [
'sh',
@@ -628,7 +634,7 @@ export class BuildService {
// Clone git repo into /workspace/source, then copy our generated Dockerfile
initContainers.push({
name: 'git-clone',
image: this.baseImage('alpine/git:2.43.0'),
image: this.resolveBuildImage('alpineGit', 'alpine/git:2.43.0'),
imagePullPolicy: 'IfNotPresent',
env: [
{ name: 'GIT_URL', value: app.gitUrl! },
@@ -679,7 +685,7 @@ export class BuildService {
// add an init container that creates empty source dir + copies Dockerfile
initContainers.push({
name: 'prepare-workspace',
image: this.baseImage('alpine:3.19'),
image: this.resolveBuildImage('alpine', 'alpine:3.19'),
imagePullPolicy: 'IfNotPresent',
command: [
'sh',
@@ -715,7 +721,7 @@ export class BuildService {
containers: [
{
name: 'kaniko',
image: this.kanikoImage,
image: this.getKanikoImage(),
imagePullPolicy: 'IfNotPresent',
args: kanikoArgs,
volumeMounts: kanikoVolumeMounts,
@@ -950,7 +956,7 @@ export class BuildService {
containers: [
{
name: 'helper',
image: this.baseImage('alpine:3.19'),
image: this.resolveBuildImage('alpine', 'alpine:3.19'),
imagePullPolicy: 'IfNotPresent',
command: ['sh', '-c', 'sleep 3600'],
volumeMounts: [{ name: 'source', mountPath: '/data' }],
+14 -5
View File
@@ -135,12 +135,21 @@ export default () => ({
namespace: process.env.BUILD_NAMESPACE || 'cloudhost-builds',
serviceAccount: process.env.BUILD_SERVICE_ACCOUNT || 'kaniko-builder',
/**
* Optional registry prefix for Docker Hub base images used in generated
* Dockerfiles and managed-service charts (e.g. "mirror.example.com" makes
* `node:20-alpine` → `mirror.example.com/node:20-alpine`). Useful when
* cluster nodes cannot reach docker.io directly.
* Registry prefix for Docker Hub base images used in generated Dockerfiles
* and managed-service charts (e.g. `node:20-alpine` →
* `registry.abrban.com/proxy-dockerhub/library/node:20-alpine`).
*/
baseImageRegistry: (process.env.BASE_IMAGE_REGISTRY || '').trim().replace(/\/+$/, ''),
baseImageRegistry: (process.env.BASE_IMAGE_REGISTRY || 'registry.abrban.com/proxy-dockerhub/library')
.trim()
.replace(/\/+$/, ''),
/** Full image refs for Kaniko jobs — override via Helm values or env. */
images: {
kaniko:
process.env.KANIKO_IMAGE ||
'registry.abrban.com/proxy-gcr/kaniko-project/executor:v1.23.2',
alpine: (process.env.BUILD_ALPINE_IMAGE || 'registry.abrban.com/proxy-dockerhub/library/alpine:3.19').trim(),
alpineGit: (process.env.BUILD_ALPINE_GIT_IMAGE || 'registry.abrban.com/proxy-dockerhub/alpine/git:2.43.0').trim(),
},
/** Kaniko build container resources — tune for large images. */
kaniko: {
cpuRequest: process.env.KANIKO_CPU_REQUEST || '500m',