diff --git a/.github/workflows/helm_release.yaml b/.github/workflows/helm_release.yaml index 4263e76d..c9e1b8ac 100644 --- a/.github/workflows/helm_release.yaml +++ b/.github/workflows/helm_release.yaml @@ -20,7 +20,7 @@ jobs: git config user.email "$GITHUB_ACTOR@users.noreply.github.com" - name: Install chart-releaser - uses: helm/chart-releaser-action@v1.6.0 + uses: helm/chart-releaser-action@v1.7.0 with: install_only: true diff --git a/.github/workflows/pr_diff.yaml b/.github/workflows/pr_diff.yaml index 52f6a420..a7b20ff4 100644 --- a/.github/workflows/pr_diff.yaml +++ b/.github/workflows/pr_diff.yaml @@ -44,7 +44,7 @@ jobs: echo 'HELM_DIFF<> $GITHUB_ENV echo "$(diff -ur before after)" >> $GITHUB_ENV echo 'EOF' >> $GITHUB_ENV - - uses: marocchino/sticky-pull-request-comment@39c5b5dc7717447d0cba270cd115037d32d28443 + - uses: marocchino/sticky-pull-request-comment@d2ad0de260ae8b0235ce059e63f2949ba9e05943 with: message: | Running a `helm template` smoketest on commit ${{ github.ref }} results in the following diff against `${{ github.base_ref }}`: diff --git a/.github/workflows/publish-chart.yaml b/.github/workflows/publish-chart.yaml new file mode 100644 index 00000000..d002fe20 --- /dev/null +++ b/.github/workflows/publish-chart.yaml @@ -0,0 +1,43 @@ +name: Publish Helm Chart to GHCR + +on: + push: + tags: + - '*-kpp*' + - 'v*-kpp*' + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Helm + uses: azure/setup-helm@v4 + + - name: Package and Push to GHCR + env: + HELM_EXPERIMENTAL_OCI: 1 + run: | + # GHCR requires repository and owner names to be strictly lowercase + OWNER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') + TAG="${{ github.ref_name }}" + + # Strip optional leading 'v' to get valid SemVer (e.g. v2.2.2-kpp-2023-08-24 -> 2.2.2-kpp-2023-08-24) + VERSION="${TAG#v}" + + echo "Packaging chart version: ${VERSION}" + mkdir -p dist + helm package . --version "${VERSION}" --destination dist/ + + # Log in to GHCR + echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io -u "${{ github.actor }}" --password-stdin + + # Push to GHCR + PKG=$(find dist -name "*.tgz" | head -n 1) + echo "Pushing ${PKG} to oci://ghcr.io/${OWNER}..." + helm push "${PKG}" "oci://ghcr.io/${OWNER}" diff --git a/Chart.yaml b/Chart.yaml index b0e582ab..07887125 100644 --- a/Chart.yaml +++ b/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v1 description: A Helm chart for Docker Registry name: docker-registry -version: 2.2.3 -appVersion: 2.8.1 +version: 3.0.0 +appVersion: 3.0.0 home: https://hub.docker.com/_/registry/ icon: https://helm.twun.io/docker-registry.png maintainers: diff --git a/README.md b/README.md index 7e7e86b7..8fdb9510 100644 --- a/README.md +++ b/README.md @@ -11,13 +11,29 @@ This directory contains a Kubernetes chart to deploy a private Docker Registry. This chart will do the following: * Implement a Docker registry deployment +* Optionally deploy a DaemonSet to add registry service names to /etc/hosts on each node + +## ⚠️ Repo Migration and Deprecation Notice + +The following change only affects attempts to install or update the chart via the https://helm.twun.io repo. + +The https://helm.twun.io repo has been migrated to https://twuni.github.io/docker-registry.helm. + +To update your configuration, remove and re-add the repo with the new URL: + +```console +helm repo remove twuni +helm repo add twuni https://twuni.github.io/docker-registry.helm +``` + +The deprecated repo URL, https://helm.twun.io, may become unavailable as early as **October 16, 2025**. ## Installing the Chart First, add the repo: ```console -helm repo add twuni https://helm.twun.io +helm repo add twuni https://twuni.github.io/docker-registry.helm ``` To install the chart, use the following: @@ -37,6 +53,9 @@ their default values. | `image.repository` | Container image to use | `registry` | | `image.tag` | Container image tag to deploy | `2.8.1` | | `imagePullSecrets` | Specify image pull secrets | `nil` (does not add image pull secrets to deployed pods) | +| `daemonset.enabled` | Deploy a DaemonSet that adds registry service domain names to /etc/hosts on each node | `false` | +| `daemonset.priorityClassName` | Priority class for the hosts updater DaemonSet pods | `""` | +| `daemonset.annotations` | Annotations to add to the DaemonSet | `{}` | | `persistence.accessMode` | Access mode to use for PVC | `ReadWriteOnce` | | `persistence.enabled` | Whether to use a PVC for the Docker storage | `false` | | `persistence.deleteEnabled` | Enable the deletion of image blobs and manifests by digest | `nil` | @@ -57,8 +76,8 @@ their default values. | `service.sessionAffinityConfig` | service session affinity config | `nil` | | `replicaCount` | k8s replicas | `1` | | `updateStrategy` | update strategy for deployment | `{}` | -| `podAnnotations` | Annotations for pod | `{}` | -| `podLabels` | Labels for pod | `{}` | +| `podAnnotations` | Annotations for deployment pod, and `garbageCollect` pod unless set explicitly there. See `garbageCollect` | `{}` | +| `podLabels` | Labels for deployment pod, and `garbageCollect` pod unless set explicitly there. See `garbageCollect` | `{}` | | `podDisruptionBudget` | Pod disruption budget | `{}` | | `resources.limits.cpu` | Container requested CPU | `nil` | | `resources.limits.memory` | Container requested memory | `nil` | @@ -79,12 +98,15 @@ their default values. | `secrets.swift.password` | Password for Swift configuration | `nil` | | `secrets.haSharedSecret` | Shared secret for Registry | `nil` | | `configData` | Configuration hash for docker | `nil` | +| `configPath` | Configuration mount point in docker, `/etc/docker/registry` for registry version 2, `/etc/distribution` for version 3 | `/etc/docker/registry` | | `s3.region` | S3 region | `nil` | | `s3.regionEndpoint` | S3 region endpoint | `nil` | | `s3.bucket` | S3 bucket name | `nil` | | `s3.rootdirectory` | S3 prefix that is applied to allow you to segment data | `nil` | | `s3.encrypt` | Store images in encrypted format | `nil` | | `s3.secure` | Use HTTPS | `nil` | +| `s3.forcepathstyle` | Use path-style addressing, needed for some s3 compatible storage (minio) | `nil` | +| `s3.skipverify` | Allows connection to s3 storage using TLS with untrusted/self-signed certificate | `nil` | | `swift.authurl` | Swift authurl | `nil` | | `swift.container` | Swift container | `nil` | | `proxy.enabled` | If true, registry will function as a proxy/mirror | `false` | @@ -119,6 +141,8 @@ their default values. | `garbageCollect.enabled` | If true, will deploy garbage-collector cronjob | `false` | | `garbageCollect.deleteUntagged` | If true, garbage-collector will delete manifests that are not currently referenced via tag | `true` | | `garbageCollect.schedule` | CronTab schedule, please use standard crontab format | `0 1 * * *` | +| `garbageCollect.podAnnotations` | CronJob pod Annotations. If left empty and chart `podAnnotations` are set, will use those. If both are set, these take precedence for the `garbageCollect` pods. | `{}` | +| `garbageCollect.podLabels` | CronJob pod Annotations. If left empty and chart `podLabels` are set, will use those. If both are set, these take precedence for the `garbageCollect` pods. | `{}` | | `garbageCollect.resources` | garbage-collector requested resources | `{}` | Specify each parameter using the `--set key=value[,key=value]` argument to diff --git a/files/host-setup.sh b/files/host-setup.sh new file mode 100644 index 00000000..ecddf961 --- /dev/null +++ b/files/host-setup.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env sh + +set -xeu + +CONFIG_FILE="/host/etc/containerd/config.toml" +BACKUP_FILE="/host/etc/containerd/config.toml.backup.$(date +%Y%m%d-%H%M%S)" +CONFIG_PATH="/etc/containerd/certs.d" + +# Check if config file exists +if [ ! -f "$CONFIG_FILE" ]; then + echo "Error: $CONFIG_FILE not found" + exit 1 +fi + +# Create backup +echo "Creating backup: $BACKUP_FILE" +cp "$CONFIG_FILE" "$BACKUP_FILE" + +restart_needed=1 +if grep -q "config_path.*=.*\"$CONFIG_PATH\"" "$CONFIG_FILE"; then + restart_needed=0 + echo "config_path is already set correctly in $CONFIG_FILE" +elif grep -q '^\[plugins\."io\.containerd\.grpc\.v1\.cri"\.registry\]' "$CONFIG_FILE"; then + echo "Registry section found, checking for config_path..." + + # Check if config_path exists but with wrong value + if grep -q "config_path.*=" "$CONFIG_FILE"; then + echo "Updating existing config_path..." + sed -i "s|config_path.*=.*|config_path = \"$CONFIG_PATH\"|" "$CONFIG_FILE" + else + echo "Adding config_path to existing registry section..." + # Add config_path after the registry section line + sed -i '/^\[plugins\."io\.containerd\.grpc\.v1\.cri"\.registry\]/a\ config_path = "'"$CONFIG_PATH"'"' "$CONFIG_FILE" + fi +else + echo "Registry section not found, adding complete section..." + # Add the entire registry section at the end + cat >> "$CONFIG_FILE" << EOF + +[plugins."io.containerd.grpc.v1.cri".registry] + config_path = "$CONFIG_PATH" +EOF +fi + +if [ "$restart_needed" -eq 1 ]; then + echo "Containerd configuration changed, restart may be required." +else + echo "No changes made to containerd configuration, restart not needed." +fi + +echo "Configuration updated successfully!" + +# Show the relevant section +echo "" +echo "Current registry configuration:" +grep -A 5 '^\[plugins\."io\.containerd\.grpc\.v1\.cri"\.registry\]' "$CONFIG_FILE" || echo "Section not found in output" + +# Verify required environment variables +if [ -z "$NAMESPACE" ]; then + echo "ERROR: NAMESPACE environment variable is not set or empty" + exit 1 +fi + +if [ -z "$SERVICE_NAME" ]; then + echo "ERROR: SERVICE_NAME environment variable is not set or empty" + exit 1 +fi + +if [ -z "$SERVICE_PORT" ]; then + echo "ERROR: SERVICE_PORT environment variable is not set or empty" + exit 1 +fi + +echo "Using NAMESPACE=$NAMESPACE, SERVICE_NAME=$SERVICE_NAME, SERVICE_PORT=$SERVICE_PORT" + +# Extract cluster domain from pod resolv.conf +cluster_domain="cluster.local" +if search_line=$(grep -E "^search|^domain" /etc/resolv.conf | head -1); then + if echo "$search_line" | grep -q "${NAMESPACE}.svc"; then + cluster_domain=$(echo "$search_line" | grep -o "${NAMESPACE}.svc.[^ ]*" | sed "s/${NAMESPACE}.svc.//") + fi +fi +echo "Detected cluster domain: ${cluster_domain}" + +prefixes="${SERVICE_NAME} ${SERVICE_NAME}.${NAMESPACE} ${SERVICE_NAME}.${NAMESPACE}.svc ${SERVICE_NAME}.${NAMESPACE}.svc.${cluster_domain}" + +hosts_entry="127.0.0.1 ${prefixes}" + +# Create a new hosts file without the old entries and with the new entry +grep -v "${SERVICE_NAME}" /host/etc/hosts > /tmp/hosts.new +echo "$hosts_entry" >> /tmp/hosts.new + +# Replace the hosts file with the new content +cat /tmp/hosts.new > /host/etc/hosts +rm /tmp/hosts.new + +echo "Added/Updated hosts entries for registry service: $hosts_entry" + +echo "Configuring containerd to allow insecure registries..." + +for prefix in $prefixes; do + cert_dir="/host/${CONFIG_PATH}/${prefix}:${SERVICE_PORT}" + echo "Creating directory: ${cert_dir}" + mkdir -p "${cert_dir}" + + echo "Writing hosts.toml for ${prefix}:${SERVICE_PORT}" + echo "[host.\"http://${prefix}:${SERVICE_PORT}\"]" > "${cert_dir}/hosts.toml" + echo "capabilities = [\"pull\", \"resolve\"]" >> "${cert_dir}/hosts.toml" + echo "plain-http = true" >> "${cert_dir}/hosts.toml" +done + +sleep infinity diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl index d9d7531b..02bb06e5 100644 --- a/templates/_helpers.tpl +++ b/templates/_helpers.tpl @@ -75,12 +75,12 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this valueFrom: secretKeyRef: name: {{ if .Values.secrets.s3.secretRef }}{{ .Values.secrets.s3.secretRef }}{{ else }}{{ template "docker-registry.fullname" . }}-secret{{ end }} - key: s3AccessKey + key: {{ if .Values.secrets.s3.accessKeyName }}{{ .Values.secrets.s3.accessKeyName }}{{ else }} s3AccessKey {{ end }} - name: REGISTRY_STORAGE_S3_SECRETKEY valueFrom: secretKeyRef: name: {{ if .Values.secrets.s3.secretRef }}{{ .Values.secrets.s3.secretRef }}{{ else }}{{ template "docker-registry.fullname" . }}-secret{{ end }} - key: s3SecretKey + key: {{ if .Values.secrets.s3.secretKeyName}}{{ .Values.secrets.s3.secretKeyName}}{{ else }} s3SecretKey {{ end }} {{- end -}} {{- if .Values.s3.regionEndpoint }} @@ -103,6 +103,36 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this value: {{ .Values.s3.secure | quote }} {{- end -}} +{{- if .Values.s3.chunksize }} +- name: REGISTRY_STORAGE_S3_CHUNKSIZE + value: {{ .Values.s3.chunksize | quote }} +{{- end -}} + +{{- if .Values.s3.multipartcopychunksize }} +- name: REGISTRY_STORAGE_S3_MULTIPARTCOPYCHUNKSIZE + value: {{ .Values.s3.multipartcopychunksize | quote }} +{{- end -}} + +{{- if .Values.s3.multipartcopymaxconcurrency }} +- name: REGISTRY_STORAGE_S3_MULTIPARTCOPYMAXCONCURRENCY + value: {{ .Values.s3.multipartcopymaxconcurrency | quote }} +{{- end -}} + +{{- if .Values.s3.multipartcopythresholdsize }} +- name: REGISTRY_STORAGE_S3_MULTIPARTCOPYTHRESHOLDSIZE + value: {{ .Values.s3.multipartcopythresholdsize | quote }} +{{- end -}} + +{{- if .Values.s3.forcepathstyle }} +- name: REGISTRY_STORAGE_S3_FORCEPATHSTYLE + value: {{ .Values.s3.forcepathstyle | quote }} +{{- end -}} + +{{- if .Values.s3.skipverify }} +- name: REGISTRY_STORAGE_S3_SKIPVERIFY + value: {{ .Values.s3.skipverify | quote }} +{{- end -}} + {{- else if eq .Values.storage "swift" }} - name: REGISTRY_STORAGE_SWIFT_AUTHURL value: {{ required ".Values.swift.authurl is required" .Values.swift.authurl }} @@ -123,16 +153,20 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this {{- if .Values.proxy.enabled }} - name: REGISTRY_PROXY_REMOTEURL value: {{ required ".Values.proxy.remoteurl is required" .Values.proxy.remoteurl }} +{{- if .Values.proxy.username }} - name: REGISTRY_PROXY_USERNAME valueFrom: secretKeyRef: name: {{ if .Values.proxy.secretRef }}{{ .Values.proxy.secretRef }}{{ else }}{{ template "docker-registry.fullname" . }}-secret{{ end }} key: proxyUsername +{{- end }} +{{- if .Values.proxy.password }} - name: REGISTRY_PROXY_PASSWORD valueFrom: secretKeyRef: name: {{ if .Values.proxy.secretRef }}{{ .Values.proxy.secretRef }}{{ else }}{{ template "docker-registry.fullname" . }}-secret{{ end }} key: proxyPassword +{{- end }} {{- end -}} {{- if .Values.persistence.deleteEnabled }} @@ -148,7 +182,7 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this {{- define "docker-registry.volumeMounts" -}} - name: "{{ template "docker-registry.fullname" . }}-config" - mountPath: "/etc/docker/registry" + mountPath: {{ .Values.configPath }} {{- if .Values.secrets.htpasswd }} - name: auth diff --git a/templates/configmap.yaml b/templates/configmap.yaml index 0f046ea7..db722106 100644 --- a/templates/configmap.yaml +++ b/templates/configmap.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Values.namespace | default .Release.Namespace }} labels: app: {{ template "docker-registry.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} heritage: {{ .Release.Service }} release: {{ .Release.Name }} data: diff --git a/templates/cronjob.yaml b/templates/cronjob.yaml index 780cf875..a5419590 100644 --- a/templates/cronjob.yaml +++ b/templates/cronjob.yaml @@ -17,16 +17,26 @@ spec: app: {{ template "docker-registry.name" . }} release: {{ .Release.Name }} {{- with .Values.podLabels }} - {{ toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} annotations: checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} {{- if .Values.podAnnotations }} - {{ toYaml .Values.podAnnotations | nindent 8 }} + {{- toYaml .Values.podAnnotations | nindent 8 }} {{- end }} spec: template: + metadata: + labels: + release: {{ .Release.Name }} + {{- if or .Values.podLabels .Values.garbageCollect.podLabels }} + {{- toYaml (merge (.Values.garbageCollect.podLabels | default (dict)) (.Values.podLabels | default (dict))) | nindent 12 }} + {{- end }} + {{- if or .Values.podAnnotations .Values.garbageCollect.podAnnotations }} + annotations: + {{- toYaml (merge (.Values.garbageCollect.podAnnotations | default (dict)) (.Values.podAnnotations | default (dict))) | nindent 12 }} + {{- end}} spec: {{- if or (eq .Values.serviceAccount.create true) (ne .Values.serviceAccount.name "") }} serviceAccountName: {{ .Values.serviceAccount.name | default (include "docker-registry.fullname" .) }} @@ -48,8 +58,11 @@ spec: - /bin/registry - garbage-collect - --delete-untagged={{ .Values.garbageCollect.deleteUntagged }} - - /etc/docker/registry/config.yml - resources: {{ toYaml .Values.garbageCollect.resources | nindent 12 }} + - {{ .Values.configPath }}/config.yml + {{- if .Values.garbageCollect.resources }} + resources: + {{- toYaml .Values.garbageCollect.resources | nindent 16 }} + {{- end }} env: {{ include "docker-registry.envs" . | nindent 16 }} {{- if .Values.containerSecurityContext.enabled }} securityContext: {{ omit .Values.containerSecurityContext "enabled" | toYaml | nindent 16 }} diff --git a/templates/daemonset.yaml b/templates/daemonset.yaml new file mode 100644 index 00000000..07231c17 --- /dev/null +++ b/templates/daemonset.yaml @@ -0,0 +1,87 @@ +{{- if .Values.daemonset.enabled }} +{{- $hostSetupSh := .Files.Get "files/host-setup.sh" }} +{{- $cmData := dict "host-setup.sh" $hostSetupSh }} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ template "docker-registry.fullname" . }}-hostconfig + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + app: {{ template "docker-registry.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- if .Values.daemonset.annotations }} + annotations: + {{- toYaml .Values.daemonset.annotations | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + app: {{ template "docker-registry.name" . }}-hostconfig + release: {{ .Release.Name }} + template: + metadata: + labels: + app: {{ template "docker-registry.name" . }}-hostconfig + release: {{ .Release.Name }} + annotations: + configmap-hash: {{ $cmData | toYaml | sha256sum }} + spec: + hostNetwork: true + {{- if .Values.daemonset.priorityClassName }} + priorityClassName: "{{ .Values.daemonset.priorityClassName }}" + {{- end }} + containers: + - name: registry-host-config + image: busybox:latest + imagePullPolicy: IfNotPresent + command: + - sh + - /configmap/host-setup.sh + env: + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: SERVICE_NAME + value: {{ template "docker-registry.fullname" . }} + - name: SERVICE_PORT + value: "{{ .Values.service.nodePort | default "" | required "service.nodePort required for daemonset to work" }}" + securityContext: + privileged: true + volumeMounts: + - name: etc + mountPath: /host/etc/hosts + subPath: hosts + - name: etc + mountPath: /host/etc/containerd + subPath: containerd + - name: configmap + mountPath: /configmap + readOnly: true + volumes: + - name: etc + hostPath: + path: /etc + - name: configmap + configMap: + name: {{ template "docker-registry.fullname" . }}-hostconfig + terminationGracePeriodSeconds: 5 +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "docker-registry.fullname" . }}-hostconfig + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + app: {{ template "docker-registry.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- if .Values.daemonset.annotations }} + annotations: + {{- toYaml .Values.daemonset.annotations | nindent 4 }} + {{- end }} +{{ dict "data" $cmData | toYaml }} +{{- end }} diff --git a/templates/deployment.yaml b/templates/deployment.yaml index dff79cb5..dac26835 100644 --- a/templates/deployment.yaml +++ b/templates/deployment.yaml @@ -60,7 +60,7 @@ spec: command: - /bin/registry - serve - - /etc/docker/registry/config.yml + - {{ .Values.configPath }}/config.yml ports: - containerPort: 5000 {{- if .Values.metrics.enabled }} @@ -88,6 +88,9 @@ spec: securityContext: {{ omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} {{- end }} volumeMounts: {{ include "docker-registry.volumeMounts" . | nindent 12 }} + {{- if .Values.extraContainers }} + {{- .Values.extraContainers | toYaml | nindent 8 }} + {{- end }} {{- if .Values.nodeSelector }} nodeSelector: {{ toYaml .Values.nodeSelector | nindent 8 }} {{- end }} diff --git a/templates/localregistry.yaml b/templates/localregistry.yaml new file mode 100644 index 00000000..8954b7e6 --- /dev/null +++ b/templates/localregistry.yaml @@ -0,0 +1,15 @@ +{{- if .Values.localRegistryHosting.enabled }} +{{- $clusterHost := printf "%s.%s" .Values.service.name .Release.Namespace }} +{{- $clusterAddr := printf "%s:%d" $clusterHost (.Values.service.port | int) }} +{{- $nodeAddr := printf "%s:%d" $clusterHost (.Values.service.nodePort | default .Values.service.port | int) }} +{{- $externalAddr := .Values.localRegistryHosting.externalAddr | required "service.externalAddr required for local registry hosting" }} +{{- $data := dict "host" $externalAddr "hostFromContainerRuntime" $nodeAddr "hostFromClusterNetwork" $clusterAddr }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: local-registry-hosting + namespace: kube-public +data: + localRegistryHosting.v1: | + {{- $data | toYaml | nindent 4 }} +{{- end }} diff --git a/templates/pvc.yaml b/templates/pvc.yaml index dea05397..74af4b20 100644 --- a/templates/pvc.yaml +++ b/templates/pvc.yaml @@ -7,7 +7,7 @@ metadata: namespace: {{ .Values.namespace | default .Release.Namespace }} labels: app: {{ template "docker-registry.fullname" . }} - chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" spec: diff --git a/templates/secret.yaml b/templates/secret.yaml index 6265dc84..9b0245f5 100644 --- a/templates/secret.yaml +++ b/templates/secret.yaml @@ -5,7 +5,7 @@ metadata: namespace: {{ .Values.namespace | default .Release.Namespace }} labels: app: {{ template "docker-registry.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} heritage: {{ .Release.Service }} release: {{ .Release.Name }} type: Opaque @@ -18,7 +18,7 @@ data: {{- else }} haSharedSecret: {{ randAlphaNum 16 | b64enc | quote }} {{- end }} - + {{- if eq .Values.storage "azure" }} {{- if and .Values.secrets.azure.accountName .Values.secrets.azure.accountKey .Values.secrets.azure.container }} azureAccountName: {{ .Values.secrets.azure.accountName | b64enc | quote }} @@ -26,6 +26,9 @@ data: azureContainer: {{ .Values.secrets.azure.container | b64enc | quote }} {{- end }} {{- else if eq .Values.storage "s3" }} + {{- if and .Values.secrets.s3.secretRef }} + secretRef: {{ .Values.secrets.s3.secretRef | b64enc | quote }} + {{- end }} {{- if and .Values.secrets.s3.secretKey .Values.secrets.s3.accessKey }} s3AccessKey: {{ .Values.secrets.s3.accessKey | b64enc | quote }} s3SecretKey: {{ .Values.secrets.s3.secretKey | b64enc | quote }} @@ -38,3 +41,21 @@ data: {{- end }} proxyUsername: {{ .Values.proxy.username | default "" | b64enc | quote }} proxyPassword: {{ .Values.proxy.password | default "" | b64enc | quote }} +{{- if .Values.proxy.tls }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "docker-registry.fullname" . }}-proxy + namespace: {{ .Values.namespace | default .Release.Namespace }} + labels: + app: {{ template "docker-registry.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} +type: kubernetes.io/tls +data: + ca.crt: {{ index .Values.proxy.tls "ca.crt" | b64enc | quote }} + tls.crt: {{ index .Values.proxy.tls "tls.crt" | b64enc | quote }} + tls.key: {{ index .Values.proxy.tls "tls.key" | b64enc | quote }} +{{- end }} diff --git a/templates/serviceaccount.yaml b/templates/serviceaccount.yaml index 6cef434f..0e50b6ab 100644 --- a/templates/serviceaccount.yaml +++ b/templates/serviceaccount.yaml @@ -4,7 +4,7 @@ kind: ServiceAccount metadata: labels: app: {{ template "docker-registry.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} heritage: {{ .Release.Service }} release: {{ .Release.Name }} namespace: {{ .Values.namespace | default .Release.Namespace }} diff --git a/values.yaml b/values.yaml index 4bdab458..5cf42765 100644 --- a/values.yaml +++ b/values.yaml @@ -12,6 +12,17 @@ updateStrategy: {} podAnnotations: {} podLabels: {} +localRegistryHosting: + enabled: false + # It's hard to infer an external address from helm. + externalAddr: ~ + +# DaemonSet for host configuration +daemonset: + enabled: false + priorityClassName: system-node-critical + annotations: {} + serviceAccount: create: false name: "" @@ -19,7 +30,7 @@ serviceAccount: image: repository: registry - tag: 2.8.1 + tag: 3.0.0 pullPolicy: IfNotPresent # imagePullSecrets: # - name: docker @@ -61,11 +72,11 @@ resources: {} # resources, such as Minikube. If you do want to specify resources, uncomment the following # lines, adjust them as necessary, and remove the curly braces after 'resources:'. # limits: - # cpu: 100m - # memory: 128Mi + # cpu: 100m + # memory: 128Mi # requests: - # cpu: 100m - # memory: 128Mi + # cpu: 100m + # memory: 128Mi persistence: accessMode: 'ReadWriteOnce' enabled: false @@ -89,6 +100,8 @@ secrets: # Use a secretRef with keys (accessKey, secretKey) for secrets stored outside the chart # s3: # secretRef: "" +# secretKeyName: "" # defaults to s3SecretKey if not specified +# accessKeyName: "" # defaults to s3AccessKey if not specified # accessKey: "" # secretKey: "" # Secrets for Swift username and password @@ -98,17 +111,23 @@ secrets: # Options for s3 storage type: # s3: -# region: us-east-1 -# regionEndpoint: https://s3.us-east-1.amazonaws.com -# bucket: my-bucket -# rootdirectory: /object/prefix -# encrypt: false -# secure: true +# region: us-east-1 +# regionEndpoint: https://s3.us-east-1.amazonaws.com +# bucket: my-bucket +# rootdirectory: /object/prefix +# encrypt: false +# secure: true +# chunksize: 5242880 +# multipartcopychunksize: 33554432 +# multipartcopymaxconcurrency: 100 +# multipartcopythresholdsize: 33554432 +# forcepathstyle: true +# skipverify: true # Options for swift storage type: # swift: -# authurl: http://swift.example.com/ -# container: my-container +# authurl: http://swift.example.com/ +# container: my-container # https://docs.docker.com/registry/recipes/mirror/ proxy: @@ -119,6 +138,10 @@ proxy: # the ref for a secret stored outside of this chart # Keys: proxyUsername, proxyPassword secretRef: "" + tls: {} + # ca.crt: "" + # tls.crt: "" + # tls.key: "" metrics: enabled: false @@ -133,6 +156,7 @@ metrics: labels: {} rules: {} +configPath: /etc/distribution configData: version: 0.1 log: @@ -176,6 +200,7 @@ securityContext: fsGroupChangePolicy: Always sysctls: [] supplementalGroups: [] + runAsUser: 1000 fsGroup: 1000 priorityClassName: "" @@ -241,8 +266,30 @@ initContainers: [] # image: busybox # command: [] +extraContainers: [] +## Extra containers to add to the Deployment +# - name: istio-proxy +# image: auto +# securityContext: +# allowPrivilegeEscalation: false +# capabilities: +# drop: +# - ALL + garbageCollect: enabled: false deleteUntagged: true schedule: "0 1 * * *" + podAnnotations: {} + podLabels: {} resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi