feat(builder): add REGISTRY_PROJECT for easy registry migration

DockerHub (flat): REGISTRY_HOST=naeel, REGISTRY_PROJECT=<empty>
  -> naeel/{nsPrefix}-{func}:{tag}
Harbor/GCR (project): REGISTRY_HOST=host, REGISTRY_PROJECT=proj
  -> host/proj/{func}:{tag}

Switch registry by changing 2 env vars only.
This commit is contained in:
Naeel
2026-03-22 17:51:05 +03:00
parent c762047234
commit 7023e0e6fc
3 changed files with 48 additions and 18 deletions
+35 -15
View File
@@ -28,10 +28,11 @@ type Projecter interface {
// Builder — управляет сборкой Docker образов через kaniko Jobs в k8s. // Builder — управляет сборкой Docker образов через kaniko Jobs в k8s.
type Builder struct { type Builder struct {
client client.Client client client.Client
builderImage string // образ kaniko builderImage string // образ kaniko
registryHost string // куда пушим образ (Harbor: host; DockerHub: user/org) registryHost string // куда пушим образ (DockerHub: "naeel"; Harbor: "host")
registrySecret string // имя k8s Secret с docker-кредами для kaniko registryProject string // проект/org внутри registry (Harbor: project; DockerHub: пусто)
registrySecret string // имя k8s Secret с docker-кредами для kaniko
s3Endpoint string // откуда kaniko берёт код s3Endpoint string // откуда kaniko берёт код
s3AccessKey string s3AccessKey string
s3SecretKey string s3SecretKey string
@@ -42,9 +43,10 @@ type Builder struct {
// Config — параметры для создания Builder'а. // Config — параметры для создания Builder'а.
type Config struct { type Config struct {
BuilderImage string BuilderImage string
RegistryHost string RegistryHost string
RegistrySecret string // имя k8s Secret с .dockerconfigjson для пуша образов RegistryProject string // пусто = DockerHub-режим (2 уровня); задан = project-режим (3 уровня)
RegistrySecret string // имя k8s Secret с .dockerconfigjson для пуша образов
S3Endpoint string S3Endpoint string
S3AccessKey string S3AccessKey string
S3SecretKey string S3SecretKey string
@@ -56,10 +58,11 @@ type Config struct {
// New создаёт новый Builder. // New создаёт новый Builder.
func New(c client.Client, cfg Config) *Builder { func New(c client.Client, cfg Config) *Builder {
return &Builder{ return &Builder{
client: c, client: c,
builderImage: cfg.BuilderImage, builderImage: cfg.BuilderImage,
registryHost: cfg.RegistryHost, registryHost: cfg.RegistryHost,
registrySecret: cfg.RegistrySecret, registryProject: cfg.RegistryProject,
registrySecret: cfg.RegistrySecret,
s3Endpoint: cfg.S3Endpoint, s3Endpoint: cfg.S3Endpoint,
s3AccessKey: cfg.S3AccessKey, s3AccessKey: cfg.S3AccessKey,
s3SecretKey: cfg.S3SecretKey, s3SecretKey: cfg.S3SecretKey,
@@ -72,15 +75,32 @@ func New(c client.Client, cfg Config) *Builder {
// ImageRef возвращает полный путь к образу в registry для данной функции и версии. // ImageRef возвращает полный путь к образу в registry для данной функции и версии.
// Тег = первые 12 символов sha256(s3Key): уникален per build, не меняется при // Тег = первые 12 символов sha256(s3Key): уникален per build, не меняется при
// повторном reconcile с тем же s3Key, не требует хаков с :latest. // повторном reconcile с тем же s3Key, не требует хаков с :latest.
// Формат: {registryHost}/{namespace}/{funcName}:{tag}
// //
// Harbor: pearlharbor.registryk8s.services.ngcloud.ru/{ns}/{func}:{tag} // Два режима — переключаются через REGISTRY_PROJECT env без пересборки оператора:
// //
// Чтобы сменить реестр — достаточно изменить REGISTRY_HOST в одном месте (ConfigMap). // project-режим (REGISTRY_PROJECT задан):
// {host}/{project}/{func}:{tag}
// Для: Harbor, GCR, GHCR, любой registry с project-изоляцией
// Пример: pearlharbor.host/myproject/chaos-echo:abc123
//
// flat-режим (REGISTRY_PROJECT пуст):
// {host}/{nsPrefix}-{func}:{tag}
// Для: DockerHub (max 2 уровня: user/repo)
// nsPrefix = первые 8 символов namespace — tenant-изоляция в имени репо
// Пример: naeel/slessffd1-chaos-echo:abc123
func (b *Builder) ImageRef(namespace, funcName, s3Key string) string { func (b *Builder) ImageRef(namespace, funcName, s3Key string) string {
h := sha256.Sum256([]byte(s3Key)) h := sha256.Sum256([]byte(s3Key))
tag := fmt.Sprintf("%x", h[:6]) // 12 hex-символов tag := fmt.Sprintf("%x", h[:6]) // 12 hex-символов
return fmt.Sprintf("%s/%s/%s:%s", b.registryHost, namespace, funcName, tag) if b.registryProject != "" {
// project-режим: Harbor / GCR / GHCR
return fmt.Sprintf("%s/%s/%s:%s", b.registryHost, b.registryProject, funcName, tag)
}
// flat-режим: DockerHub (только 2 уровня)
nsPrefix := namespace
if len(nsPrefix) > 8 {
nsPrefix = nsPrefix[:8]
}
return fmt.Sprintf("%s/%s-%s:%s", b.registryHost, nsPrefix, funcName, tag)
} }
// Build запускает kaniko Job для сборки образа функции. // Build запускает kaniko Job для сборки образа функции.
+9
View File
@@ -29,6 +29,12 @@ type Config struct {
// Registry — куда пушим собранные образы функций (DockerHub: "naeel", приватный: "host:port/prefix") // Registry — куда пушим собранные образы функций (DockerHub: "naeel", приватный: "host:port/prefix")
RegistryHost string RegistryHost string
// RegistryProject — опциональный проект/организация внутри registry.
// Если задан, imageRef = {host}/{project}/{func}:{tag} (Harbor, GCR, GHCR, любой с project-изоляцией)
// Если пуст, imageRef = {host}/{nsPrefix}-{func}:{tag} (DockerHub — только 2 уровня)
// Смена реестра = смена REGISTRY_HOST + REGISTRY_PROJECT без пересборки оператора.
RegistryProject string
// RegistrySecret — имя k8s Secret типа kubernetes.io/dockerconfigjson // RegistrySecret — имя k8s Secret типа kubernetes.io/dockerconfigjson
// Монтируется в kaniko Job для авторизации в registry. // Монтируется в kaniko Job для авторизации в registry.
// Создаётся через hack/create-registry-secret.sh // Создаётся через hack/create-registry-secret.sh
@@ -113,6 +119,9 @@ func Load() (*Config, error) {
return nil, fmt.Errorf("REGISTRY_HOST is required") return nil, fmt.Errorf("REGISTRY_HOST is required")
} }
// REGISTRY_PROJECT — опциональный проект/org (Harbor: namespace; DockerHub: пусто)
cfg.RegistryProject = os.Getenv("REGISTRY_PROJECT")
// Secret с docker-кредами для kaniko (опционально — без него push в приватный registry упадёт) // Secret с docker-кредами для kaniko (опционально — без него push в приватный registry упадёт)
cfg.RegistrySecret = os.Getenv("REGISTRY_SECRET") cfg.RegistrySecret = os.Getenv("REGISTRY_SECRET")
if cfg.RegistrySecret == "" { if cfg.RegistrySecret == "" {
+4 -3
View File
@@ -131,9 +131,10 @@ func main() {
} }
bldr := builder.New(mgr.GetClient(), builder.Config{ bldr := builder.New(mgr.GetClient(), builder.Config{
BuilderImage: cfg.BuilderImage, BuilderImage: cfg.BuilderImage,
RegistryHost: cfg.RegistryHost, RegistryHost: cfg.RegistryHost,
RegistrySecret: cfg.RegistrySecret, RegistryProject: cfg.RegistryProject,
RegistrySecret: cfg.RegistrySecret,
S3Endpoint: cfg.S3Endpoint, S3Endpoint: cfg.S3Endpoint,
S3AccessKey: cfg.S3AccessKey, S3AccessKey: cfg.S3AccessKey,
S3SecretKey: cfg.S3SecretKey, S3SecretKey: cfg.S3SecretKey,