fix(build): default Kaniko and init images to Harbor via Helm values
Build and Deploy Platform / build-and-deploy (push) Successful in 14m57s
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:
+4
-3
@@ -16,7 +16,7 @@
|
||||
| دسته | تعداد | ✅ | ⚠️ | 🔜 |
|
||||
|------|-------|----|----|-----|
|
||||
| بلاکرهای پروداکشن | 8 | 8 | 0 | 0 |
|
||||
| بیلد و Kaniko | 10 | 8 | 1 | 1 |
|
||||
| بیلد و Kaniko | 10 | 9 | 0 | 1 |
|
||||
| دیپلوی و پیشنمایش | 6 | 6 | 0 | 0 |
|
||||
| دیتابیس / سرویس اختیاری | 9 | 8 | 0 | 1 |
|
||||
| Migration / اسکیما | 4 | 4 | 0 | 0 |
|
||||
@@ -57,7 +57,7 @@
|
||||
| Zip slip در unzip | ✅ | اعتبارسنجی مسیر قبل و بعد از extract |
|
||||
| state بیلد در حافظه | ✅ | Redis session + startup recovery |
|
||||
| دیپلوی همزمان بدون قفل | ✅ | in-flight guard در `triggerDeployment` |
|
||||
| Base image بدون آینه | ⚠️ | `BASE_IMAGE_REGISTRY` اضافه شده؛ باید در env پروداکشن ست شود |
|
||||
| Base image بدون آینه | ✅ | `build.images` در Helm values + پیشفرض Harbor در configuration |
|
||||
| zip bomb (۱۰GiB) | 🔜 | سقف آپلود موجود؛ محدودیت تعداد entry در archive پیشنهاد میشود |
|
||||
|
||||
---
|
||||
@@ -157,7 +157,8 @@
|
||||
|--------|---------|-------|
|
||||
| `CLUSTER_DEPLOY_FALLBACK_ENABLED` | `false` | fallback بین کلاستر |
|
||||
| `CLUSTER_DEPLOY_FALLBACK_ATTEMPTS` | `3` | فقط وقتی fallback فعال |
|
||||
| `BASE_IMAGE_REGISTRY` | — | آینه base imageهای بیلد |
|
||||
| `BASE_IMAGE_REGISTRY` | `registry.abrban.com/proxy-dockerhub/library` | آینه base imageهای بیلد (یا از `build` در Helm values) |
|
||||
| `KANIKO_IMAGE` | `registry.abrban.com/proxy-gcr/...` | Kaniko executor (یا `build.images.kaniko` در values) |
|
||||
| `BUILD_PVC_STORAGE_CLASS` | — | StorageClass برای PVC بیلد |
|
||||
| `BILLING_WALLET_HMAC_SECRET` | — | اجباری در production |
|
||||
| `PAYMENT_GATEWAY_*` | — | اجباری برای charge واقعی |
|
||||
|
||||
@@ -287,7 +287,10 @@ curl -s -o /dev/null -w '%{http_code}\n' https://<frontend.host>
|
||||
| `MIZBANSMS_USERNAME` / `MIZBANSMS_PASSWORD` / `MIZBANSMS_FROM` | OTP SMS credentials (required or OTP send 503s) | — |
|
||||
| `REGISTRY_URL` / `REGISTRY_PULL_URL` | In-cluster registry (push / pull) | `registry.cloudhost-builds.svc.cluster.local:5000` |
|
||||
| `BUILD_NAMESPACE` / `BUILD_SERVICE_ACCOUNT` | Build Jobs namespace + SA | `cloudhost-builds` / `kaniko-builder` |
|
||||
| `KANIKO_IMAGE` | Kaniko executor image | `gcr.io/kaniko-project/executor:v1.23.2` |
|
||||
| `KANIKO_IMAGE` | Kaniko executor image | `registry.abrban.com/proxy-gcr/kaniko-project/executor:v1.23.2` |
|
||||
| `BUILD_ALPINE_IMAGE` | Alpine image for build init/helper pods | `registry.abrban.com/proxy-dockerhub/library/alpine:3.19` |
|
||||
| `BUILD_ALPINE_GIT_IMAGE` | Git-clone init container image | `registry.abrban.com/proxy-dockerhub/alpine/git:2.43.0` |
|
||||
| `BASE_IMAGE_REGISTRY` | Harbor prefix for Docker Hub images in generated Dockerfiles | `registry.abrban.com/proxy-dockerhub/library` |
|
||||
| `UPLOAD_DIR` | Disk path for uploaded source archives | `./uploads` |
|
||||
| `INGRESS_CLASS` | Ingress controller for app Ingress objects | `traefik` |
|
||||
| `PLATFORM_DOMAIN` / `PREVIEW_BASE_DOMAIN` | Base domain for app subdomains / previews | `apps.cloudhost.local` / — |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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' }],
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -28,6 +28,14 @@ images:
|
||||
tag: "1.0.0" # ← CI overwrites on each deploy
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
# Kaniko job images — Harbor proxy-cache (first pull is slow, no manual seed needed).
|
||||
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
|
||||
baseImageRegistry: registry.abrban.com/proxy-dockerhub/library
|
||||
|
||||
postgres:
|
||||
enabled: true
|
||||
database: cloudhost
|
||||
@@ -98,8 +106,6 @@ backend:
|
||||
PLATFORM_STORAGE_PROVISIONER: rancher.io/local-path
|
||||
ELASTICSEARCH_HOST: elasticsearch.logging.svc.cluster.local
|
||||
ELASTICSEARCH_AUTO_PORT_FORWARD: "false"
|
||||
# Mirror prefix for user-app Dockerfiles and managed DB/Redis/RabbitMQ charts
|
||||
BASE_IMAGE_REGISTRY: registry.abrban.com/proxy-dockerhub/library
|
||||
# Must match elasticsearch-credentials Secret in logging namespace (not in Helm chart)
|
||||
ELASTIC_PASSWORD: "CHANGE_VIA_SEALEDSECRET_OR_KUBECTL"
|
||||
FLUENTBIT_PASSWORD: "CHANGE_VIA_SEALEDSECRET_OR_KUBECTL"
|
||||
|
||||
Reference in New Issue
Block a user