Public Access
Enhance Helm chart with ServiceAccount support and configurable ports
- Updated Chart.yaml to version 0.2.0 and added annotations for changes. - Modified release-chart.yaml to trigger releases via Gitea and handle pre-releases. - Introduced ServiceAccount configuration in values.yaml and related templates. - Adjusted internal container ports to prevent conflicts between nginx and aptly. - Updated README.md and NOTES.txt to reflect new configurations and usage instructions.
This commit is contained in:
+11
-2
@@ -5,7 +5,7 @@ description: >-
|
||||
an nginx read/auth sidecar, a fully aptly-native values API, and declarative
|
||||
repo/mirror/publish state reconciled via a Helm hook.
|
||||
type: application
|
||||
version: 0.1.0
|
||||
version: 0.2.0
|
||||
appVersion: "1.6.3-1"
|
||||
home: https://git.morlana.online/f.weber/aptly-containerized
|
||||
sources:
|
||||
@@ -20,7 +20,7 @@ keywords:
|
||||
maintainers:
|
||||
- name: Florian Weber
|
||||
email: f.weber@flweber.me
|
||||
icon: https://www.aptly.info/img/aptly_medium.png
|
||||
icon: https://www.aptly.info/img/logo.png
|
||||
annotations:
|
||||
artifacthub.io/license: MIT
|
||||
artifacthub.io/links: |
|
||||
@@ -31,3 +31,12 @@ annotations:
|
||||
artifacthub.io/signKey: |
|
||||
fingerprint: FC35C0FAA26605C4C21C7BBFBF43884145E5AA94
|
||||
url: https://git.morlana.online/f.weber/aptly-containerized/raw/branch/main/pubkeys/chart-signing.asc
|
||||
artifacthub.io/changes: |
|
||||
- kind: added
|
||||
description: Configurable ServiceAccount (serviceAccount.create/name/annotations/automountServiceAccountToken), defaulting to a dedicated ServiceAccount per release.
|
||||
- kind: added
|
||||
description: Configurable internal container ports (ports.aptly/nginx/metrics).
|
||||
- kind: fixed
|
||||
description: nginx and aptly no longer both listen on port 8080 inside the same pod, which made nginx fail to start with "address already in use". nginx now defaults to 8081 internally; external service.port is unchanged.
|
||||
- kind: changed
|
||||
description: Chart releases are now triggered by publishing a Gitea Release (instead of a bare tag push), so pre-releases can be flagged for ArtifactHub.
|
||||
|
||||
+13
-1
@@ -311,6 +311,15 @@ plain, supported operation.
|
||||
| `persistence.size` | `20Gi` | immutable once installed unless using `existingClaim` |
|
||||
| `persistence.annotations` | `{}` | |
|
||||
|
||||
### ServiceAccount
|
||||
|
||||
| Key | Default | Description |
|
||||
|---|---|---|
|
||||
| `serviceAccount.create` | `true` | creates a dedicated `ServiceAccount` for this release |
|
||||
| `serviceAccount.name` | `""` | `create: true` → defaults to the release's fullname; `create: false` → set this to bind an existing `ServiceAccount`, or leave `""` to use the namespace's `default` one |
|
||||
| `serviceAccount.annotations` | `{}` | e.g. for IRSA/Workload Identity |
|
||||
| `serviceAccount.automountServiceAccountToken` | `true` | |
|
||||
|
||||
### Workload
|
||||
|
||||
| Key | Default | Description |
|
||||
@@ -330,8 +339,11 @@ plain, supported operation.
|
||||
| Key | Default | Description |
|
||||
|---|---|---|
|
||||
| `service.type` | `ClusterIP` | |
|
||||
| `service.port` | `8080` | |
|
||||
| `service.port` | `8080` | external port — unaffected by `ports.*` below, which are internal-only |
|
||||
| `service.annotations` | `{}` | |
|
||||
| `ports.aptly` | `8080` | container port aptly itself listens on (loopback-only unless `proxy.enabled: false`) |
|
||||
| `ports.nginx` | `8081` | container port nginx listens on for repo + API traffic; must differ from `ports.aptly` — they're two containers sharing one pod network namespace, and a clash makes nginx fail to start with "address already in use" |
|
||||
| `ports.metrics` | `9090` | container port nginx listens on for the `/api/metrics` passthrough, when `metrics.service.enabled` |
|
||||
| `ingress.enabled` | `false` | |
|
||||
| `ingress.mode` | `single` | `single` \| `split` — see [docs/security.md](https://git.morlana.online/f.weber/aptly-containerized/src/branch/main/docs/security.md) |
|
||||
| `ingress.className` | `""` | |
|
||||
|
||||
@@ -15,7 +15,7 @@ aptly ({{ .Chart.AppVersion }}, chart {{ .Chart.Version }}) is deploying as {{ $
|
||||
--- Check it's up -------------------------------------------------------
|
||||
|
||||
kubectl exec -n {{ .Release.Namespace }} {{ $fullname }}-0 -c aptly -- \
|
||||
curl -fsS http://127.0.0.1:8080/api/ready
|
||||
curl -fsS http://127.0.0.1:{{ .Values.ports.aptly }}/api/ready
|
||||
|
||||
kubectl logs -n {{ .Release.Namespace }} job/{{ $fullname }}-reconcile
|
||||
# (only present right after install/upgrade in `hook` mode)
|
||||
|
||||
@@ -73,6 +73,19 @@ confirms it's intended.
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Resolves to the ServiceAccount name the pod should bind to: a generated or
|
||||
overridden name when serviceAccount.create is true, the explicit override
|
||||
when false, or "" (falls back to the namespace's "default" SA) otherwise.
|
||||
*/}}
|
||||
{{- define "aptly.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
{{- default (include "aptly.fullname" .) .Values.serviceAccount.name -}}
|
||||
{{- else -}}
|
||||
{{- .Values.serviceAccount.name -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "aptly.imagePullSecrets" -}}
|
||||
{{- $secrets := concat (.Values.global.imagePullSecrets | default list) (.Values.image.pullSecrets | default list) -}}
|
||||
{{- if $secrets }}
|
||||
@@ -94,7 +107,7 @@ templates/statefulset.yaml (the aptly config) and templates/ingress.yaml
|
||||
{{- end -}}
|
||||
|
||||
{{- define "aptly.apiListen" -}}
|
||||
{{- if .Values.proxy.enabled -}}127.0.0.1:8080{{- else -}}0.0.0.0:8080{{- end -}}
|
||||
{{- if .Values.proxy.enabled -}}127.0.0.1:{{ .Values.ports.aptly }}{{- else -}}0.0.0.0:{{ .Values.ports.aptly }}{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
@@ -163,7 +176,7 @@ compose/config/nginx.*.conf for the same constraint hit empirically).
|
||||
{{- $sec := include "aptly.security" . | fromJson -}}
|
||||
{{- $p := .Values.proxy -}}
|
||||
server {
|
||||
listen 8080;
|
||||
listen {{ .Values.ports.nginx }};
|
||||
server_name _;
|
||||
client_max_body_size {{ $p.maxUploadSize }};
|
||||
absolute_redirect off;
|
||||
@@ -176,8 +189,8 @@ server {
|
||||
{{- end }}
|
||||
|
||||
location = /healthz { access_log off; return 200 "ok\n"; }
|
||||
location = /api/ready { access_log off; proxy_pass http://127.0.0.1:8080; }
|
||||
location = /api/healthy { access_log off; proxy_pass http://127.0.0.1:8080; }
|
||||
location = /api/ready { access_log off; proxy_pass http://127.0.0.1:{{ .Values.ports.aptly }}; }
|
||||
location = /api/healthy { access_log off; proxy_pass http://127.0.0.1:{{ .Values.ports.aptly }}; }
|
||||
|
||||
{{- if $sec.w }}
|
||||
location /api/ {
|
||||
@@ -200,7 +213,7 @@ server {
|
||||
{{- else }}
|
||||
auth_basic off;
|
||||
{{- end }}
|
||||
proxy_pass http://127.0.0.1:8080;
|
||||
proxy_pass http://127.0.0.1:{{ .Values.ports.aptly }};
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_request_buffering off;
|
||||
@@ -254,9 +267,9 @@ server {
|
||||
# Separate, unauthenticated listener so scraping never needs the write-path
|
||||
# credentials and a ServiceMonitor never needs a basicAuth secret.
|
||||
server {
|
||||
listen 9090;
|
||||
listen {{ .Values.ports.metrics }};
|
||||
server_name _;
|
||||
location = /api/metrics { proxy_pass http://127.0.0.1:8080; }
|
||||
location = /api/metrics { proxy_pass http://127.0.0.1:{{ .Values.ports.aptly }}; }
|
||||
location / { return 404; }
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
@@ -39,6 +39,10 @@ spec:
|
||||
spec:
|
||||
restartPolicy: Never
|
||||
{{- include "aptly.imagePullSecrets" . | nindent 6 }}
|
||||
{{- with include "aptly.serviceAccountName" . }}
|
||||
serviceAccountName: {{ . }}
|
||||
{{- end }}
|
||||
automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
containers:
|
||||
|
||||
@@ -15,7 +15,7 @@ spec:
|
||||
ingress:
|
||||
{{- if .Values.networkPolicy.allowedNamespaces }}
|
||||
# Restricted to these namespaces (plus this one). NOTE: this applies to
|
||||
# the whole nginx:8080 endpoint — read and write share one port, so this
|
||||
# the whole nginx endpoint — read and write share one port, so this
|
||||
# cannot itself express "reads are public, writes are cluster-only" any
|
||||
# more precisely than security.write.allowCIDRs can (see the warning
|
||||
# rendered into nginx.conf for that). Use it to fence the Service off
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "aptly.serviceAccountName" . }}
|
||||
labels:
|
||||
{{- include "aptly.labels" . | nindent 4 }}
|
||||
{{- with .Values.serviceAccount.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }}
|
||||
{{- end -}}
|
||||
@@ -41,6 +41,10 @@ spec:
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- include "aptly.imagePullSecrets" . | nindent 6 }}
|
||||
{{- with include "aptly.serviceAccountName" . }}
|
||||
serviceAccountName: {{ . }}
|
||||
{{- end }}
|
||||
automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }}
|
||||
terminationGracePeriodSeconds: {{ .Values.workload.terminationGracePeriodSeconds }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
@@ -165,7 +169,7 @@ spec:
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: aptly
|
||||
containerPort: 8080
|
||||
containerPort: {{ .Values.ports.aptly }}
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/aptly
|
||||
@@ -199,10 +203,10 @@ spec:
|
||||
{{- toYaml .Values.nginx.securityContext | nindent 12 }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
containerPort: {{ .Values.ports.nginx }}
|
||||
{{- if .Values.metrics.service.enabled }}
|
||||
- name: metrics
|
||||
containerPort: 9090
|
||||
containerPort: {{ .Values.ports.metrics }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
- name: data
|
||||
|
||||
@@ -226,6 +226,15 @@
|
||||
"publishEndpointName": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"ports": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"aptly": { "type": "integer" },
|
||||
"nginx": { "type": "integer" },
|
||||
"metrics": { "type": "integer" }
|
||||
}
|
||||
},
|
||||
"persistence": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
@@ -255,6 +264,16 @@
|
||||
"podLabels": { "type": "object" }
|
||||
}
|
||||
},
|
||||
"serviceAccount": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"create": { "type": "boolean" },
|
||||
"name": { "type": "string" },
|
||||
"annotations": { "type": "object" },
|
||||
"automountServiceAccountToken": { "type": "boolean" }
|
||||
}
|
||||
},
|
||||
"podSecurityContext": { "type": "object" },
|
||||
"containerSecurityContext": { "type": "object" },
|
||||
"resources": { "type": "object" },
|
||||
|
||||
@@ -176,6 +176,16 @@ proxy:
|
||||
readTimeout: "3600s"
|
||||
publishEndpointName: public
|
||||
|
||||
# Container ports inside the pod. aptly and nginx are two containers sharing
|
||||
# one pod network namespace — they MUST NOT use the same port (nginx would
|
||||
# fail to start with "address already in use"). These are internal-only;
|
||||
# external access is still controlled by service.port / metrics.service.port,
|
||||
# which stay decoupled from these via named ports (targetPort: http/metrics).
|
||||
ports:
|
||||
aptly: 8080 # aptly's own listener (loopback-only, or 0.0.0.0 when proxy.enabled=false)
|
||||
nginx: 8081 # nginx's main (repo + API) listener
|
||||
metrics: 9090 # nginx's /api/metrics passthrough listener, when metrics.service.enabled
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
existingClaim: "" # set this in production — see docs/operations.md
|
||||
@@ -184,6 +194,17 @@ persistence:
|
||||
size: 20Gi
|
||||
annotations: {}
|
||||
|
||||
serviceAccount:
|
||||
# Own ServiceAccount per release, so RBAC (if you grant any) is scoped to
|
||||
# this instance rather than the namespace's shared "default" identity.
|
||||
create: true
|
||||
# "" -> aptly.fullname (this release's name) when create=true. When
|
||||
# create=false, set this to bind to a ServiceAccount you already manage;
|
||||
# leave "" to fall back to the namespace's "default" ServiceAccount.
|
||||
name: ""
|
||||
annotations: {}
|
||||
automountServiceAccountToken: true
|
||||
|
||||
workload:
|
||||
updateStrategy:
|
||||
type: RollingUpdate # safe here: a StatefulSet with replicas=1 always
|
||||
|
||||
Reference in New Issue
Block a user