Gitea #143. Additive, default false, so the render is byte-identical to the previous release - proven by diffing both renders against origin/main rather than asserted. Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying the probe port, and - inside that rule's source-restricted branch - 169.254.7.127/32, the address the kubelet's probes arrive from once the pod is in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the port a pod whose namespace has joined the mesh is unreachable. The two halves are one value because the second is the one nobody thinks of: 15008 added by hand leaves a policy that passes review and drops every probe the first time probeSources is narrowed, and a pod that never becomes Ready reads as a broken application rather than as a policy. Minor, not major: additive value, unchanged default, unchanged render. Port half only: this chart offers no networkPolicy.probeSources - its probes put no packet on the network - so there is no redirected probe to allow and an ipBlock for one would match nothing while making the rule look like it did something. ci/run-networkpolicy-test.sh ties that exemption to the absence of probeSources, not to a chart name.
235 lines
11 KiB
JSON
235 lines
11 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft-07/schema#",
|
|
"title": "valkey values",
|
|
"description": "Values schema for the valkey chart (issue #68, guideline 12). additionalProperties is false on every chart-owned object level, so a misspelled key fails the render instead of being silently ignored. The objects that go verbatim into the pod spec (probes, security contexts, global) stay open, because the chart does not interpret their contents. secrets.authSecretRef has no valid default and is therefore enforced by required() in the template, not here - a required array next to a key that ships as null could never fire.",
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"global": {
|
|
"description": "Helm's conventional cross-chart values. Unused by this chart, kept open so an umbrella install cannot break on it.",
|
|
"type": "object"
|
|
},
|
|
"scaleDown": {
|
|
"description": "true renders the StatefulSet with replicas: 0 and overrides valkey.replicas. PVC, Secret, Service and NetworkPolicy stay in place.",
|
|
"type": "boolean"
|
|
},
|
|
"secrets": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"authSecretRef": {
|
|
"description": "REQUIRED (enforced by required() in the template). op:// path of the 1Password item carrying the field 'auth-conf' with the complete configuration line 'requirepass <password>'.",
|
|
"type": ["string", "null"]
|
|
}
|
|
}
|
|
},
|
|
"valkey": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"replicas": {
|
|
"description": "0 or 1. This chart runs exactly one Valkey: a second pod would fight over the same ReadWriteOnce volume, and clients behind the Service would silently see two different datasets.",
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"maximum": 1
|
|
},
|
|
"resources": {
|
|
"$ref": "#/definitions/resources"
|
|
},
|
|
"maxmemoryFactor": {
|
|
"description": "Fraction of the container's computed memory limit that Valkey may fill with data. The rest covers what maxmemory does not: client buffers, the AOF buffer and the copy-on-write pages of the snapshot/AOF-rewrite fork. Ignored when valkey.maxmemory is set.",
|
|
"type": ["number", "null"],
|
|
"exclusiveMinimum": 0,
|
|
"maximum": 1
|
|
},
|
|
"maxmemory": {
|
|
"description": "Explicit maxmemory as a Kubernetes quantity (e.g. '512Mi'), overriding maxmemoryFactor. A value above the container's memory limit aborts the render. Valkey's own spellings ('512mb') are rejected on purpose - one quantity syntax per chart.",
|
|
"type": ["string", "null"],
|
|
"pattern": "^[0-9]+(\\.[0-9]+)?(k|M|G|T|Ki|Mi|Gi|Ti)?$"
|
|
},
|
|
"maxmemoryPolicy": {
|
|
"description": "Valkey's maxmemory-policy. Enumerated rather than free text: a typo would make the server refuse to start, and the enum names the value instead. 'noeviction' for queues (the default), 'allkeys-lru' for caches.",
|
|
"type": "string",
|
|
"enum": [
|
|
"noeviction",
|
|
"allkeys-lru",
|
|
"allkeys-lfu",
|
|
"allkeys-random",
|
|
"volatile-lru",
|
|
"volatile-lfu",
|
|
"volatile-random",
|
|
"volatile-ttl"
|
|
]
|
|
},
|
|
"extraConfig": {
|
|
"description": "Extra configuration lines, appended verbatim (rendered through tpl). Cannot switch the password off: the auth include is rendered after it and the last directive wins.",
|
|
"type": ["string", "null"]
|
|
},
|
|
"livenessProbe": {
|
|
"$ref": "#/definitions/probe"
|
|
},
|
|
"readinessProbe": {
|
|
"$ref": "#/definitions/probe"
|
|
},
|
|
"startupProbe": {
|
|
"$ref": "#/definitions/probe"
|
|
},
|
|
"securityContext": {
|
|
"$ref": "#/definitions/securityContext"
|
|
},
|
|
"env": {
|
|
"$ref": "#/definitions/env"
|
|
}
|
|
}
|
|
},
|
|
"persistence": {
|
|
"description": "The data volume. Deliberately NOT null-safe: an erased block yields an invalid PVC, which fails at apply time instead of sizing somebody's queue volume by chart default. Issue #99 covers the silent class of failure, and this one is loud.",
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"enabled": {
|
|
"description": "true = PVC, false = emptyDir (and the chart then switches AOF and the RDB save points off). Pairs with valkey.maxmemoryPolicy - see values.yaml.",
|
|
"type": "boolean"
|
|
},
|
|
"appendonly": {
|
|
"description": "AOF instead of RDB-only. Has no effect while persistence.enabled is false: there is nothing to append to, and the chart writes 'appendonly no' plus 'save \"\"'.",
|
|
"type": "boolean"
|
|
},
|
|
"size": {
|
|
"type": ["string", "null"]
|
|
},
|
|
"storageClass": {
|
|
"description": "null uses the cluster's default class - which on this cluster is NOT encrypted, so leaving the default 'longhorn-encrypted-ns' is a decision about data at rest.",
|
|
"type": ["string", "null"]
|
|
}
|
|
}
|
|
},
|
|
"networkPolicy": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"ingress": {
|
|
"description": "The policy's INBOUND side. Three names here overlap as substrings and are not the same thing: the top-level ingress is the Ingress OBJECT this chart renders, networkPolicy.ingress is this block, and networkPolicy.ingressController is the SOURCE SELECTOR for the ingress controller's pods - a SIBLING of this block and no part of it.",
|
|
"type": ["object", "null"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"ambientMesh": {
|
|
"description": "Opens the pod for Istio's ambient mesh; off by default and additive, so the render is byte-identical while it is false. Renders 15008/TCP inbound - ztunnel's HBONE tunnel, which ambient explicitly does not let bypass NetworkPolicy enforcement - AND, where probeSources is non-empty, 169.254.7.127/32 as an additional probe source, because inside the mesh the kubelet's probes are redirected away from the worker node's address. The two halves are inseparable on purpose: whoever opens 15008 by hand has not added the probe address, and the first narrowed probeSources then drops every probe, so the pod never becomes Ready and the symptom reads as a broken application rather than as a policy. Unproven in operation: that 15008 alone suffices comes from Istio's documentation, and no namespace of this cluster carries istio.io/dataplane-mode yet.",
|
|
"type": ["boolean", "null"]
|
|
}
|
|
}
|
|
},
|
|
"enabled": {
|
|
"description": "On by default. Only a real boundary where the cluster's CNI enforces NetworkPolicies - an unenforced policy is accepted by the API server and filters nothing.",
|
|
"type": "boolean"
|
|
},
|
|
"allowedNamespaces": {
|
|
"description": "Namespaces allowed in addition to the release's own, matched on the kubernetes.io/metadata.name label Kubernetes sets itself. A name that does not exist matches nothing and is silently ineffective.",
|
|
"type": ["array", "null"],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"definitions": {
|
|
"resources": {
|
|
"description": "May be null / empty: the chart then falls back to its default requests and computed limits (issue #99) instead of rendering a container without resource accounting. The memory limit computed here is also what valkey.maxmemory is derived from and checked against.",
|
|
"type": ["object", "null"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"limitFactor": {
|
|
"type": "number",
|
|
"exclusiveMinimum": 0
|
|
},
|
|
"requests": {
|
|
"$ref": "#/definitions/resourceList"
|
|
},
|
|
"limits": {
|
|
"$ref": "#/definitions/resourceList"
|
|
}
|
|
}
|
|
},
|
|
"resourceList": {
|
|
"description": "Both spellings of the ephemeral-storage key are accepted because the resources helper normalizes camelCase to the Kubernetes key.",
|
|
"type": ["object", "null"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"cpu": {
|
|
"type": ["string", "number", "null"]
|
|
},
|
|
"memory": {
|
|
"type": ["string", "number", "null"]
|
|
},
|
|
"ephemeral-storage": {
|
|
"type": ["string", "number", "null"]
|
|
},
|
|
"ephemeralStorage": {
|
|
"type": ["string", "number", "null"]
|
|
}
|
|
}
|
|
},
|
|
"env": {
|
|
"type": ["array", "null"],
|
|
"items": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["name"],
|
|
"properties": {
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"value": {
|
|
"type": "string"
|
|
},
|
|
"valueFrom": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"secretKeyRef": {
|
|
"$ref": "#/definitions/keyRef"
|
|
},
|
|
"configMapKeyRef": {
|
|
"$ref": "#/definitions/keyRef"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"keyRef": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["name", "key"],
|
|
"properties": {
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"key": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"securityContext": {
|
|
"description": "May be null / empty at any level: the chart then falls back to its hardening defaults (issue #99). This chart's fallback reproduces ITS deviation, not the repo standard - uid 999 / gid 1000 are the image's own 'valkey' user, and fsGroup has to keep matching runAsGroup or the data volume is not writable.",
|
|
"type": ["object", "null"],
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"pod": {
|
|
"description": "Merged onto the chart's pod hardening defaults; kept open because the chart does not interpret the individual fields. seccompProfile lives here so it also covers the init container.",
|
|
"type": ["object", "null"]
|
|
},
|
|
"container": {
|
|
"description": "Merged onto the chart's container hardening defaults and applied to BOTH the server and the auth-check init container; kept open because the chart does not interpret the individual fields.",
|
|
"type": ["object", "null"]
|
|
}
|
|
}
|
|
},
|
|
"probe": {
|
|
"description": "Merged onto the chart's probe defaults and rendered as a container probe; kept open because the chart does not interpret the individual fields. May be null / empty, which means the defaults apply (issue #99) rather than the probe disappearing. The default carries the exec command - for these probes the command IS the check (guideline 12.5).",
|
|
"type": ["object", "null"]
|
|
}
|
|
}
|
|
}
|