init: registry server + operator from VM

This commit is contained in:
“Naeel”
2026-07-01 17:37:08 +04:00
commit dd1007d24c
67 changed files with 3293 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
apiVersion: v2
name: terraform-registry
description: Helm chart for Terraform Provider Registry (registry-server + operator)
type: application
version: 0.1.0
appVersion: "1.0.0"
keywords:
- terraform
- registry
- nubes
home: https://terra.k8c.ru
maintainers:
- name: Naeel
+42
View File
@@ -0,0 +1,42 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "terraform-registry.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "terraform-registry.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- printf "%s" $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{/*
Create chart label.
*/}}
{{- define "terraform-registry.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels.
*/}}
{{- define "terraform-registry.labels" -}}
helm.sh/chart: {{ include "terraform-registry.chart" . }}
{{ include "terraform-registry.selectorLabels" . }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels.
*/}}
{{- define "terraform-registry.selectorLabels" -}}
app.kubernetes.io/name: {{ include "terraform-registry.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
@@ -0,0 +1,61 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: builder-script
namespace: {{ .Values.global.namespace }}
labels:
{{- include "terraform-registry.labels" . | nindent 4 }}
data:
build.sh: |
#!/bin/sh
set -e
echo ">>> Starting Build for $PROVIDER_NAME $VERSION"
# 1. Setup Environment
# Inputs: GIT_REPO, GIT_REF, PROVIDER_NAME, VERSION
WORK_DIR="/workspace"
ARTIFACTS_DIR="/artifacts"
mkdir -p $WORK_DIR $ARTIFACTS_DIR
# 2. Clone Repository
echo ">>> Cloning $GIT_REPO ($GIT_REF)..."
git clone $GIT_REPO $WORK_DIR/src
cd $WORK_DIR/src
git checkout $GIT_REF
# 3. Build for Platforms
echo ">>> Building binaries..."
# Linux amd64
echo "--> linux/amd64"
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o terraform-provider-${PROVIDER_NAME}_v${VERSION}
zip ${ARTIFACTS_DIR}/terraform-provider-${PROVIDER_NAME}_${VERSION}_linux_amd64.zip terraform-provider-${PROVIDER_NAME}_v${VERSION}
rm terraform-provider-${PROVIDER_NAME}_v${VERSION}
# Windows amd64
echo "--> windows/amd64"
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -o terraform-provider-${PROVIDER_NAME}_v${VERSION}.exe
zip ${ARTIFACTS_DIR}/terraform-provider-${PROVIDER_NAME}_${VERSION}_windows_amd64.zip terraform-provider-${PROVIDER_NAME}_v${VERSION}.exe
rm terraform-provider-${PROVIDER_NAME}_v${VERSION}.exe
# 4. Checksums
cd $ARTIFACTS_DIR
sha256sum *.zip > terraform-provider-${PROVIDER_NAME}_${VERSION}_SHA256SUMS
# 5. GPG Sign
touch terraform-provider-${PROVIDER_NAME}_${VERSION}_SHA256SUMS.sig
# 6. Upload to S3
if [ -z "$REGISTRY_HOSTNAME" ]; then
REGISTRY_HOSTNAME="{{ .Values.global.registryHostname }}"
fi
TARGET_PATH="terraform-providers/$REGISTRY_HOSTNAME/${NAMESPACE}/${PROVIDER_NAME}/${VERSION}"
echo ">>> Uploading to S3 path: $TARGET_PATH"
mc alias set nubes_s3 https://$S3_ENDPOINT $S3_ACCESS_KEY $S3_SECRET_KEY
mc cp --recursive $ARTIFACTS_DIR/ nubes_s3/$TARGET_PATH/
echo ">>> Build Complete!"
+79
View File
@@ -0,0 +1,79 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: providerreleases.terra.core.nubes.ru
annotations:
app.kubernetes.io/managed-by: Helm
spec:
group: terra.core.nubes.ru
versions:
- name: v1alpha1
served: true
storage: true
subresources:
status: {}
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
required:
- providerName
- version
- gitRepo
- gitRef
properties:
providerName:
type: string
description: "Name of the provider (e.g. 'mycloud')"
namespace:
type: string
default: "mycloud"
description: "Terraform registry namespace (e.g. 'nubes')"
version:
type: string
description: "Semantic version without v (e.g. '1.0.1')"
gitRepo:
type: string
description: "Git repository URL to clone"
gitRef:
type: string
description: "Git tag, commit SHA or branch"
platforms:
type: array
items:
type: string
default: ["linux_amd64", "windows_amd64"]
description: "Target platforms for build"
status:
type: object
properties:
phase:
type: string
description: "Current phase: Pending, Building, Publishing, Ready, Failed"
downloadUrl:
type: string
conditions:
type: array
items:
type: object
properties:
type:
type: string
status:
type: string
lastTransitionTime:
type: string
format: date-time
reason:
type: string
message:
type: string
scope: Namespaced
names:
plural: providerreleases
singular: providerrelease
kind: TerraformProviderRelease
shortNames:
- tpr
@@ -0,0 +1,52 @@
{{- if .Values.docs.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: registry-server-docs
namespace: {{ .Values.global.namespace }}
labels:
app: registry-server-docs
{{- include "terraform-registry.labels" . | nindent 4 }}
spec:
replicas: 1
selector:
matchLabels:
app: registry-server-docs
template:
metadata:
labels:
app: registry-server-docs
spec:
containers:
- name: registry-server
image: "{{ .Values.docs.image.repository }}:{{ .Values.docs.image.tag }}"
imagePullPolicy: {{ .Values.docs.image.pullPolicy }}
env:
- name: REGISTRY_HOSTNAME
value: {{ .Values.global.registryHostname | quote }}
- name: S3_ENDPOINT
value: {{ .Values.s3.endpoint | quote }}
- name: S3_ACCESS_KEY
valueFrom:
secretKeyRef:
name: {{ .Values.s3.existingSecret }}
key: {{ .Values.s3.accessKeyField }}
- name: S3_SECRET_KEY
valueFrom:
secretKeyRef:
name: {{ .Values.s3.existingSecret }}
key: {{ .Values.s3.secretKeyField }}
- name: S3_BUCKET
value: {{ .Values.s3.bucket | quote }}
- name: S3_USE_SSL
value: {{ .Values.s3.useSSL | quote }}
ports:
- containerPort: 8080
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 500m
memory: 128Mi
{{- end }}
+37
View File
@@ -0,0 +1,37 @@
{{- if .Values.ingress.enabled }}
# WARNING: Do NOT apply to existing clusters without confirming TLS issuer.
# LetsEncrypt rate limits apply. For testing, use a self-signed issuer.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: registry-ingress
namespace: {{ .Values.global.namespace }}
annotations:
{{- if .Values.ingress.tls.enabled }}
cert-manager.io/cluster-issuer: {{ .Values.ingress.tls.issuer | quote }}
{{- end }}
{{- range $key, $value := .Values.ingress.annotations }}
{{ $key }}: {{ $value | quote }}
{{- end }}
labels:
{{- include "terraform-registry.labels" . | nindent 4 }}
spec:
ingressClassName: {{ .Values.ingress.className | quote }}
{{- if .Values.ingress.tls.enabled }}
tls:
- hosts:
- {{ .Values.ingress.host | quote }}
secretName: {{ .Values.ingress.tls.secretName }}
{{- end }}
rules:
- host: {{ .Values.ingress.host | quote }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: registry-server
port:
number: {{ .Values.registry.service.port }}
{{- end }}
+7
View File
@@ -0,0 +1,7 @@
apiVersion: v1
kind: Namespace
metadata:
name: {{ .Values.global.namespace }}
labels:
name: {{ .Values.global.namespace }}
{{- include "terraform-registry.labels" . | nindent 4 }}
+31
View File
@@ -0,0 +1,31 @@
{{- if .Values.networkPolicy.enabled }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ include "terraform-registry.fullname" . }}-netpol
namespace: {{ .Values.global.namespace }}
labels:
{{- include "terraform-registry.labels" . | nindent 4 }}
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
ports:
- port: {{ .Values.registry.service.targetPort }}
protocol: TCP
egress:
- to: []
ports:
- port: 443 # S3, Vault
protocol: TCP
- port: 53 # DNS
protocol: UDP
- port: 53
protocol: TCP
{{- end }}
+33
View File
@@ -0,0 +1,33 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: terraform-operator
namespace: {{ .Values.global.namespace }}
labels:
app: terraform-operator
{{- include "terraform-registry.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.operator.replicas }}
selector:
matchLabels:
app: terraform-operator
template:
metadata:
labels:
app: terraform-operator
spec:
serviceAccountName: terraform-operator
containers:
- name: operator
image: "{{ .Values.operator.image.repository }}:{{ .Values.operator.image.tag }}"
imagePullPolicy: IfNotPresent
env:
- name: REGISTRY_HOSTNAME
value: {{ .Values.global.registryHostname | quote }}
resources:
requests:
cpu: {{ .Values.operator.resources.requests.cpu }}
memory: {{ .Values.operator.resources.requests.memory }}
limits:
cpu: {{ .Values.operator.resources.limits.cpu }}
memory: {{ .Values.operator.resources.limits.memory }}
+14
View File
@@ -0,0 +1,14 @@
{{- if .Values.pdb.enabled }}
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: {{ include "terraform-registry.fullname" . }}-registry
namespace: {{ .Values.global.namespace }}
labels:
{{- include "terraform-registry.labels" . | nindent 4 }}
spec:
minAvailable: {{ .Values.pdb.minAvailable }}
selector:
matchLabels:
app: registry-server
{{- end }}
+41
View File
@@ -0,0 +1,41 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: terraform-operator
namespace: {{ .Values.global.namespace }}
labels:
{{- include "terraform-registry.labels" . | nindent 4 }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: terraform-operator
namespace: {{ .Values.global.namespace }}
labels:
{{- include "terraform-registry.labels" . | nindent 4 }}
rules:
- apiGroups: ["terra.core.nubes.ru"]
resources: ["providerreleases", "providerreleases/status"]
verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["create", "get", "list", "watch", "delete"]
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: terraform-operator
namespace: {{ .Values.global.namespace }}
labels:
{{- include "terraform-registry.labels" . | nindent 4 }}
subjects:
- kind: ServiceAccount
name: terraform-operator
namespace: {{ .Values.global.namespace }}
roleRef:
kind: Role
name: terraform-operator
apiGroup: rbac.authorization.k8s.io
@@ -0,0 +1,64 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: registry-server
namespace: {{ .Values.global.namespace }}
labels:
app: registry-server
{{- include "terraform-registry.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.registry.replicas }}
selector:
matchLabels:
app: registry-server
template:
metadata:
labels:
app: registry-server
spec:
containers:
- name: registry-server
image: "{{ .Values.registry.image.repository }}:{{ .Values.registry.image.tag }}"
imagePullPolicy: {{ .Values.registry.image.pullPolicy }}
ports:
- containerPort: {{ .Values.registry.service.targetPort }}
env:
- name: REGISTRY_HOSTNAME
value: {{ .Values.global.registryHostname | quote }}
- name: S3_ENDPOINT
value: {{ .Values.s3.endpoint | quote }}
- name: S3_ACCESS_KEY
valueFrom:
secretKeyRef:
name: {{ .Values.s3.existingSecret }}
key: {{ .Values.s3.accessKeyField }}
- name: S3_SECRET_KEY
valueFrom:
secretKeyRef:
name: {{ .Values.s3.existingSecret }}
key: {{ .Values.s3.secretKeyField }}
- name: S3_BUCKET
value: {{ .Values.s3.bucket | quote }}
- name: S3_USE_SSL
value: {{ .Values.s3.useSSL | quote }}
resources:
requests:
cpu: {{ .Values.registry.resources.requests.cpu }}
memory: {{ .Values.registry.resources.requests.memory }}
limits:
cpu: {{ .Values.registry.resources.limits.cpu }}
memory: {{ .Values.registry.resources.limits.memory }}
{{- if .Values.registry.healthcheck.enabled }}
livenessProbe:
httpGet:
path: {{ .Values.registry.healthcheck.path }}
port: {{ .Values.registry.healthcheck.port }}
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: {{ .Values.registry.healthcheck.path }}
port: {{ .Values.registry.healthcheck.port }}
initialDelaySeconds: 5
periodSeconds: 10
{{- end }}
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: registry-server
namespace: {{ .Values.global.namespace }}
labels:
app: registry-server
{{- include "terraform-registry.labels" . | nindent 4 }}
spec:
selector:
app: registry-server
ports:
- port: {{ .Values.registry.service.port }}
targetPort: {{ .Values.registry.service.targetPort }}
+6
View File
@@ -0,0 +1,6 @@
global:
registryHostname: "terra.k8c.ru"
registry:
replicas: 1
pdb:
enabled: false
+14
View File
@@ -0,0 +1,14 @@
global:
registryHostname: "registry.nubes.ru" # Целевой домен
registry:
image:
repository: "pearlharbor.registryk8s.services.ngcloud.ru/terraform/registry-server"
replicas: 2
operator:
image:
repository: "pearlharbor.registryk8s.services.ngcloud.ru/terraform/registry-operator"
pdb:
enabled: true
minAvailable: 1
networkPolicy:
enabled: true
+71
View File
@@ -0,0 +1,71 @@
global:
registryHostname: "terra.k8c.ru" # Переопределяется при миграции
namespace: "terraform-registry"
registry:
image:
repository: "naeel/terraform-registry-server" # → Harbor при миграции
tag: "latest"
pullPolicy: IfNotPresent
replicas: 1 # → 2 в prod
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
service:
port: 80
targetPort: 8080
healthcheck:
enabled: true
path: /healthz
port: 8080
operator:
image:
repository: "naeel/terraform-registry-operator"
tag: "latest"
replicas: 1
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 500m
memory: 128Mi
docs:
enabled: false
image:
repository: "naeel/terraform-registry-server"
tag: "docs-dev-fixed"
pullPolicy: IfNotPresent
ingress:
enabled: true
className: "nginx"
host: "terra.k8c.ru" # Переопределяется
tls:
enabled: true
issuer: "letsencrypt-prod" # НЕ ТРОГАТЬ LetsEncrypt issuer!
secretName: "registry-tls"
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
s3:
endpoint: "s3.msk-1.ngcloud.ru"
bucket: "terraform-registry"
useSSL: true
# credentials через existingSecret
existingSecret: "s3-credentials"
accessKeyField: "access-key"
secretKeyField: "secret-key"
pdb:
enabled: false # → true в prod
minAvailable: 1
networkPolicy:
enabled: false # → true при миграции