Skip to content

GarageCluster v1beta1

API version: garage.rajsingh.info/v1beta1. Scope: Namespaced.

The custom-resource guide explains operational behavior. The JSON schemas are the validation source of truth.

This served version is deprecated; use a newer version for new resources.

Spec

GarageClusterSpec defines the desired state of GarageCluster

Field path Type Constraints Description
admin object Admin configures the admin API endpoint and metrics
admin.adminTokenSecretRef object AdminTokenSecretRef references the secret the operator uses to authenticate with Garage's Admin API. The operator reads this token to manage buckets, keys, and layout on behalf of GarageBucket/GarageKey/GarageNode resources. Required for gateway clusters that use connectTo — the operator needs admin API access to issue ConnectNode commands. If omitted for storage clusters, layout management and bucket/key reconciliation are unavailable. Use GarageAdminToken to create tokens for external tooling; this field is specifically for the operator's own access.
admin.adminTokenSecretRef.key string required The key of the secret to select from. Must be a valid secret key.
admin.adminTokenSecretRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
admin.adminTokenSecretRef.optional boolean Specify whether the Secret or its key must be defined
admin.bindAddress string BindAddress is a custom wildcard TCP bind address for the Admin API. Managed workloads accept "0.0.0.0:3903" or "[::]:3903". Unix sockets, empty hosts, loopback, and specific hosts are rejected because Services and direct Pod probes must reach every Garage process. If set, its port overrides BindPort for all generated endpoints. The effective Admin API TCP port is immutable after GarageCluster creation.
admin.bindPort integer default: 3903; format: "int32"; min: 1; max: 65535 BindPort is the port to bind for admin API. The effective Admin API TCP port is immutable after the GarageCluster is created.
admin.metricsRequireToken boolean MetricsRequireToken requires Bearer token authentication for the /metrics endpoint. When true, Prometheus scrape configs must include the token from metricsTokenSecretRef.
admin.metricsTokenSecretRef object MetricsTokenSecretRef references a secret containing a token that protects the /metrics endpoint. Only used when metricsRequireToken is true.
admin.metricsTokenSecretRef.key string required The key of the secret to select from. Must be a valid secret key.
admin.metricsTokenSecretRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
admin.metricsTokenSecretRef.optional boolean Specify whether the Secret or its key must be defined
admin.traceSink string TraceSink is the OpenTelemetry collector address for tracing Example: "http://localhost:4317"
affinity object Affinity for pod scheduling
affinity.nodeAffinity object Describes node affinity scheduling rules for the pod.
affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution array of object The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred.
affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution[].preference object required A node selector term, associated with the corresponding weight.
affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution[].preference.matchExpressions array of object A list of node selector requirements by node's labels.
affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution[].preference.matchExpressions[].key string required The label key that the selector applies to.
affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution[].preference.matchExpressions[].operator string required Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution[].preference.matchExpressions[].values array of string An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch.
affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution[].preference.matchFields array of object A list of node selector requirements by node's fields.
affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution[].preference.matchFields[].key string required The label key that the selector applies to.
affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution[].preference.matchFields[].operator string required Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution[].preference.matchFields[].values array of string An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch.
affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution[].weight integer required; format: "int32" Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100.
affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution object If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node.
affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms array of object required Required. A list of node selector terms. The terms are ORed.
affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[].matchExpressions array of object A list of node selector requirements by node's labels.
affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[].matchExpressions[].key string required The label key that the selector applies to.
affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[].matchExpressions[].operator string required Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[].matchExpressions[].values array of string An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch.
affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[].matchFields array of object A list of node selector requirements by node's fields.
affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[].matchFields[].key string required The label key that the selector applies to.
affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[].matchFields[].operator string required Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt.
affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[].matchFields[].values array of string An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch.
affinity.podAffinity object Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)).
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution array of object The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred.
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm object required Required. A pod affinity term, associated with the corresponding weight.
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.labelSelector object A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods.
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.labelSelector.matchExpressions array of object matchExpressions is a list of label selector requirements. The requirements are ANDed.
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.labelSelector.matchExpressions[].key string required key is the label key that the selector applies to.
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.labelSelector.matchExpressions[].operator string required operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.labelSelector.matchExpressions[].values array of string values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.labelSelector.matchLabels map of string matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.matchLabelKeys array of string MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with labelSelector as key in (value) to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set.
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.mismatchLabelKeys array of string MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with labelSelector as key notin (value) to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.namespaceSelector object A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces.
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.namespaceSelector.matchExpressions array of object matchExpressions is a list of label selector requirements. The requirements are ANDed.
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.namespaceSelector.matchExpressions[].key string required key is the label key that the selector applies to.
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.namespaceSelector.matchExpressions[].operator string required operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.namespaceSelector.matchExpressions[].values array of string values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.namespaceSelector.matchLabels map of string matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.namespaces array of string namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace".
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.topologyKey string required This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed.
affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution[].weight integer required; format: "int32" weight associated with matching the corresponding podAffinityTerm, in the range 1-100.
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution array of object If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied.
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[].labelSelector object A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods.
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[].labelSelector.matchExpressions array of object matchExpressions is a list of label selector requirements. The requirements are ANDed.
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[].labelSelector.matchExpressions[].key string required key is the label key that the selector applies to.
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[].labelSelector.matchExpressions[].operator string required operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[].labelSelector.matchExpressions[].values array of string values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[].labelSelector.matchLabels map of string matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[].matchLabelKeys array of string MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with labelSelector as key in (value) to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set.
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[].mismatchLabelKeys array of string MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with labelSelector as key notin (value) to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[].namespaceSelector object A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces.
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[].namespaceSelector.matchExpressions array of object matchExpressions is a list of label selector requirements. The requirements are ANDed.
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[].namespaceSelector.matchExpressions[].key string required key is the label key that the selector applies to.
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[].namespaceSelector.matchExpressions[].operator string required operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[].namespaceSelector.matchExpressions[].values array of string values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[].namespaceSelector.matchLabels map of string matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[].namespaces array of string namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace".
affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution[].topologyKey string required This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed.
affinity.podAntiAffinity object Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)).
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution array of object The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and subtracting "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred.
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm object required Required. A pod affinity term, associated with the corresponding weight.
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.labelSelector object A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods.
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.labelSelector.matchExpressions array of object matchExpressions is a list of label selector requirements. The requirements are ANDed.
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.labelSelector.matchExpressions[].key string required key is the label key that the selector applies to.
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.labelSelector.matchExpressions[].operator string required operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.labelSelector.matchExpressions[].values array of string values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.labelSelector.matchLabels map of string matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.matchLabelKeys array of string MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with labelSelector as key in (value) to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set.
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.mismatchLabelKeys array of string MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with labelSelector as key notin (value) to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.namespaceSelector object A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces.
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.namespaceSelector.matchExpressions array of object matchExpressions is a list of label selector requirements. The requirements are ANDed.
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.namespaceSelector.matchExpressions[].key string required key is the label key that the selector applies to.
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.namespaceSelector.matchExpressions[].operator string required operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.namespaceSelector.matchExpressions[].values array of string values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.namespaceSelector.matchLabels map of string matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.namespaces array of string namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace".
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].podAffinityTerm.topologyKey string required This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed.
affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[].weight integer required; format: "int32" weight associated with matching the corresponding podAffinityTerm, in the range 1-100.
affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution array of object If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied.
affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[].labelSelector object A label query over a set of resources, in this case pods. If it's null, this PodAffinityTerm matches with no Pods.
affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[].labelSelector.matchExpressions array of object matchExpressions is a list of label selector requirements. The requirements are ANDed.
affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[].labelSelector.matchExpressions[].key string required key is the label key that the selector applies to.
affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[].labelSelector.matchExpressions[].operator string required operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[].labelSelector.matchExpressions[].values array of string values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[].labelSelector.matchLabels map of string matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[].matchLabelKeys array of string MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with labelSelector as key in (value) to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set.
affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[].mismatchLabelKeys array of string MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the incoming pod labels, those key-value labels are merged with labelSelector as key notin (value) to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set.
affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[].namespaceSelector object A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces.
affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[].namespaceSelector.matchExpressions array of object matchExpressions is a list of label selector requirements. The requirements are ANDed.
affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[].namespaceSelector.matchExpressions[].key string required key is the label key that the selector applies to.
affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[].namespaceSelector.matchExpressions[].operator string required operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[].namespaceSelector.matchExpressions[].values array of string values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[].namespaceSelector.matchLabels map of string matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[].namespaces array of string namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace".
affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution[].topologyKey string required This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed.
blocks object Blocks configures block storage settings
blocks.compressionLevel string pattern: "^(none|0|-?[1-9][0-9]*)$" CompressionLevel is the zstd compression level 1-19: standard, 20-22: ultra, -1 to -99: fast, "none": disabled
blocks.disableScrub boolean DisableScrub disables automatic monthly data directory scrub
blocks.maxConcurrentReads integer min: 1 MaxConcurrentReads is the maximum simultaneous block file reads
blocks.maxConcurrentWritesPerRequest integer min: 1 MaxConcurrentWritesPerRequest is the maximum parallel block writes per PUT request. Higher values improve throughput but increase memory usage. Default: 3. Recommended: 10-30 for NVMe, 3-10 for HDD. Added in Garage v2.2.0.
blocks.ramBufferMax integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" RAMBufferMax is the maximum RAM for buffering blocks
blocks.size integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" Size is the size of data blocks (default: 1M)
blocks.useLocalTZ boolean UseLocalTZ runs lifecycle worker at midnight in local timezone
capacityReservePercent integer min: 0; max: 50 CapacityReservePercent reserves a percentage of PVC capacity for overhead. Only used when LayoutPolicy is "Auto". For example, setting this to 10 will report 90% of PVC size as node capacity. This is useful to reserve headroom for filesystem overhead, snapshots, or growth. Default: 0 (use full PVC size as capacity)
connectTo object ConnectTo specifies the storage cluster this gateway cluster connects to. Required when gateway=true. The gateway cluster will: - Use the same RPC secret as the storage cluster - Connect to the storage cluster's nodes - Register its pods as gateway nodes in the storage cluster's layout
connectTo.adminApiEndpoint string AdminAPIEndpoint is the storage cluster's Admin API URL. Used by the operator to discover nodes and register this gateway's pods. Required when clusterRef is not set or is in a different namespace. Example: "http://garage-storage.other-namespace:3903"
connectTo.adminTokenSecretRef object AdminTokenSecretRef references the storage cluster's admin token. Required when adminApiEndpoint is set and the storage cluster requires auth. If clusterRef is in the same namespace, the operator reads the token automatically.
connectTo.adminTokenSecretRef.key string required The key of the secret to select from. Must be a valid secret key.
connectTo.adminTokenSecretRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
connectTo.adminTokenSecretRef.optional boolean Specify whether the Secret or its key must be defined
connectTo.bootstrapPeers array of string BootstrapPeers are initial peers for cluster formation. Required when clusterRef is not set (the operator can't auto-discover peers). Format: "<64-hex-node-id>@:"
connectTo.clusterRef object ClusterRef references a GarageCluster in the same namespace. When set, the operator automatically reads the RPC secret and admin token from the referenced cluster — no need to set rpcSecretRef or adminTokenSecretRef.
connectTo.clusterRef.kubeConfigSecretRef object KubeConfigSecretRef is reserved for a future remote Kubernetes client integration. It is currently rejected by admission because the operator does not use it.
connectTo.clusterRef.kubeConfigSecretRef.key string required The key of the secret to select from. Must be a valid secret key.
connectTo.clusterRef.kubeConfigSecretRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
connectTo.clusterRef.kubeConfigSecretRef.optional boolean Specify whether the Secret or its key must be defined
connectTo.clusterRef.name string required Name of the GarageCluster resource.
connectTo.clusterRef.namespace string Namespace of the GarageCluster. Defaults to the referencing resource's namespace. Cross-namespace references require a GarageReferenceGrant where supported by the owning resource. GarageNode and GarageAdminToken reject them.
connectTo.rpcSecretRef object RPCSecretRef references a secret containing the shared RPC secret. Required when clusterRef is not set or references a different namespace. The secret must have a key with a 32-byte hex-encoded value.
connectTo.rpcSecretRef.key string required The key of the secret to select from. Must be a valid secret key.
connectTo.rpcSecretRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
connectTo.rpcSecretRef.optional boolean Specify whether the Secret or its key must be defined
containerSecurityContext object ContainerSecurityContext for Garage containers
containerSecurityContext.allowPrivilegeEscalation boolean AllowPrivilegeEscalation controls whether a process can gain more privileges than its parent process. This bool directly controls if the no_new_privs flag will be set on the container process. AllowPrivilegeEscalation is true always when the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN Note that this field cannot be set when spec.os.name is windows.
containerSecurityContext.appArmorProfile object appArmorProfile is the AppArmor options to use by this container. If set, this profile overrides the pod's appArmorProfile. Note that this field cannot be set when spec.os.name is windows.
containerSecurityContext.appArmorProfile.localhostProfile string localhostProfile indicates a profile loaded on the node that should be used. The profile must be preconfigured on the node to work. Must match the loaded name of the profile. Must be set if and only if type is "Localhost".
containerSecurityContext.appArmorProfile.type string required type indicates which kind of AppArmor profile will be applied. Valid options are: Localhost - a profile pre-loaded on the node. RuntimeDefault - the container runtime's default profile. Unconfined - no AppArmor enforcement.
containerSecurityContext.capabilities object The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime. Note that this field cannot be set when spec.os.name is windows.
containerSecurityContext.capabilities.add array of string Added capabilities
containerSecurityContext.capabilities.drop array of string Removed capabilities
containerSecurityContext.privileged boolean Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false. Note that this field cannot be set when spec.os.name is windows.
containerSecurityContext.procMount string procMount denotes the type of proc mount to use for the containers. The default value is Default which uses the container runtime defaults for readonly paths and masked paths. Note that this field cannot be set when spec.os.name is windows.
containerSecurityContext.readOnlyRootFilesystem boolean Whether this container has a read-only root filesystem. Default is false. Note that this field cannot be set when spec.os.name is windows.
containerSecurityContext.runAsGroup integer format: "int64" The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. Note that this field cannot be set when spec.os.name is windows.
containerSecurityContext.runAsNonRoot boolean Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.
containerSecurityContext.runAsUser integer format: "int64" The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. Note that this field cannot be set when spec.os.name is windows.
containerSecurityContext.seLinuxOptions object The SELinux context to be applied to the container. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. Note that this field cannot be set when spec.os.name is windows.
containerSecurityContext.seLinuxOptions.level string Level is SELinux level label that applies to the container.
containerSecurityContext.seLinuxOptions.role string Role is a SELinux role label that applies to the container.
containerSecurityContext.seLinuxOptions.type string Type is a SELinux type label that applies to the container.
containerSecurityContext.seLinuxOptions.user string User is a SELinux user label that applies to the container.
containerSecurityContext.seccompProfile object The seccomp options to use by this container. If seccomp options are provided at both the pod & container level, the container options override the pod options. Note that this field cannot be set when spec.os.name is windows.
containerSecurityContext.seccompProfile.localhostProfile string localhostProfile indicates a profile defined in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile location. Must be set if type is "Localhost". Must NOT be set for any other type.
containerSecurityContext.seccompProfile.type string required type indicates which kind of seccomp profile will be applied. Valid options are: Localhost - a profile defined in a file on the node should be used. RuntimeDefault - the container runtime default profile should be used. Unconfined - no profile should be applied.
containerSecurityContext.windowsOptions object The Windows specific settings applied to all containers. If unspecified, the options from the PodSecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. Note that this field cannot be set when spec.os.name is linux.
containerSecurityContext.windowsOptions.gmsaCredentialSpec string GMSACredentialSpec is where the GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field.
containerSecurityContext.windowsOptions.gmsaCredentialSpecName string GMSACredentialSpecName is the name of the GMSA credential spec to use.
containerSecurityContext.windowsOptions.hostProcess boolean HostProcess determines if a container should be run as a 'Host Process' container. All of a Pod's containers must have the same effective HostProcess value (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). In addition, if HostProcess is true then HostNetwork must also be set to true.
containerSecurityContext.windowsOptions.runAsUserName string The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.
database object Database configures the metadata database engine
database.engine string default: "lmdb"; enum: ["lmdb", "sqlite", "fjall"] Engine specifies the database engine to use
database.fjallBlockCacheSize integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" FjallBlockCacheSize is the block cache size for Fjall
database.lmdbMapSize integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" LMDBMapSize is the virtual memory region size for LMDB
defaultNodeTags array of string DefaultNodeTags are tags applied to all auto-managed nodes. Only used when LayoutPolicy is "Auto". For per-node tags, use LayoutPolicy "Manual" with GarageNode resources.
deletionPolicy string enum: ["Destroy", "Drain"] DeletionPolicy is Destroy for whole-store teardown or Drain for federated site retirement. When omitted, standalone clusters retain legacy Destroy behavior. Federated deletion requires an explicit choice and fails closed as Drain if admission is bypassed.
discovery object Discovery configures peer discovery mechanisms
discovery.consul object Consul configures Consul-based peer discovery
discovery.consul.api string default: "catalog"; enum: ["catalog", "agent"] API specifies the service registration API ("catalog" or "agent")
discovery.consul.caCert string CACert is the CA certificate for TLS connection
discovery.consul.caCertSecretRef object CACertSecretRef references a secret containing the CA certificate
discovery.consul.caCertSecretRef.key string required The key of the secret to select from. Must be a valid secret key.
discovery.consul.caCertSecretRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
discovery.consul.caCertSecretRef.optional boolean Specify whether the Secret or its key must be defined
discovery.consul.clientCertSecretRef object ClientCertSecretRef references a secret containing client TLS cert
discovery.consul.clientCertSecretRef.key string required The key of the secret to select from. Must be a valid secret key.
discovery.consul.clientCertSecretRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
discovery.consul.clientCertSecretRef.optional boolean Specify whether the Secret or its key must be defined
discovery.consul.clientKeySecretRef object ClientKeySecretRef references a secret containing client TLS key
discovery.consul.clientKeySecretRef.key string required The key of the secret to select from. Must be a valid secret key.
discovery.consul.clientKeySecretRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
discovery.consul.clientKeySecretRef.optional boolean Specify whether the Secret or its key must be defined
discovery.consul.datacenters array of string Datacenters for WAN federation
discovery.consul.enabled boolean Enabled enables Consul-based discovery
discovery.consul.httpAddr string HTTPAddr is the full HTTP(S) address of Consul server
discovery.consul.meta map of string Meta is service metadata key-value pairs
discovery.consul.serviceName string ServiceName for Garage RPC port registration
discovery.consul.tags array of string Tags are additional service tags
discovery.consul.tlsSkipVerify boolean TLSSkipVerify skips TLS hostname verification
discovery.consul.tokenSecretRef object TokenSecretRef references a secret containing the bearer token
discovery.consul.tokenSecretRef.key string required The key of the secret to select from. Must be a valid secret key.
discovery.consul.tokenSecretRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
discovery.consul.tokenSecretRef.optional boolean Specify whether the Secret or its key must be defined
discovery.kubernetes object Kubernetes configures Kubernetes-based peer discovery
discovery.kubernetes.enabled boolean Enabled enables Kubernetes-based discovery
discovery.kubernetes.namespace string Namespace for Garage custom resources
discovery.kubernetes.serviceName string ServiceName label to filter custom resources
discovery.kubernetes.skipCRD boolean SkipCRD skips automatic CRD creation/patching
extraContainers array of object max items: 16; validation: container name is operator-reserved ExtraContainers run beside the Garage container in the same pod and network namespace. They cannot mount operator-owned volumes.
extraContainers[].name string required; min length: 1; max length: 63; pattern: "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" Name of the container. It must be unique across initContainers and extraContainers, a DNS-1123 label, and not an operator-reserved name.
extraVolumes array of object max items: 32; validation: volume name is operator-reserved ExtraVolumes are added to the pod. Operator-owned volume names are reserved (config, metadata, data, data-, rpc-secret, admin-token, metrics-token).
extraVolumes[].name string required; min length: 1; max length: 63; pattern: "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" Name of the volume. It must be unique across extraVolumes, a DNS-1123 label, and not an operator-reserved volume name.
gateway boolean Gateway marks this cluster as a gateway-only cluster. Gateway clusters don't store data - they only handle API requests. When true: - Creates a StatefulSet with metadata PVC only (for node identity persistence) - Data storage uses EmptyDir (gateways don't store blocks) - Pods are registered as gateway nodes in the layout (capacity=null) - Must specify connectTo to reference a storage cluster
image string Image specifies the Garage container image to use. Takes precedence over imageRepository if both are set.
imagePullPolicy string default: "IfNotPresent" ImagePullPolicy specifies the image pull policy
imagePullSecrets array of object ImagePullSecrets specifies secrets for pulling images from private registries
imagePullSecrets[].name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
imageRepository string ImageRepository overrides just the repository portion of the default Garage image, preserving the default tag for automatic version upgrades. For example, setting this to "my-mirror/garage" with the default tag v2.4.0 produces "my-mirror/garage:v2.4.0". Ignored if image is set.
initContainers array of object max items: 16; validation: container name is operator-reserved InitContainers run before the Garage container, after any operator-injected init containers. Entries with restartPolicy: Always are native sidecars (Kubernetes 1.29+ beta, GA in 1.33). Names garage, purge-cluster-layout and the prefix garage-operator- are reserved. Applies to the Garage pods of this cluster (the gateway tier when gateway is true).
initContainers[].name string required; min length: 1; max length: 63; pattern: "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" Name of the container. It must be unique across initContainers and extraContainers, a DNS-1123 label, and not an operator-reserved name.
k2vApi object K2VAPI configures the K2V (key-value) API endpoint. Omit to disable K2V.
k2vApi.bindAddress string BindAddress is a custom wildcard TCP bind address for the K2V API. If set, this overrides BindPort.
k2vApi.bindPort integer default: 3904; format: "int32"; min: 1; max: 65535 BindPort is the port to bind for K2V API
layoutManagement object LayoutManagement controls automatic layout application behavior. With autoApply disabled, gateway tombstones are reported but are neither staged nor applied; remove those exact roles with the Garage CLI or enable autoApply. The force-layout-apply annotation is only a legacy/bootstrap below-replication-factor override and does not approve tombstones.
layoutManagement.autoApply boolean AutoApply automatically applies staged layout changes
layoutManagement.drain object Drain is the layout-wide positive-capacity removal policy. It mirrors the v1beta2 hub so conversion preserves external/federated assertions even on connection-only management handles.
layoutManagement.drain.unverifiedPeersPolicy string default: "Block"; enum: ["Block", "AssumeConsistent"] UnverifiedPeersPolicy defaults to Block. AssumeConsistent is required for federated or externally managed processes and is a deliberate maintenance assertion, not an online safety guarantee.
layoutManagement.minNodesHealthy integer MinNodesHealthy is the minimum healthy nodes required before applying layout changes
layoutManagement.redundancyVerification object RedundancyVerification configures the FullyReplicated proof (#474).
layoutManagement.redundancyVerification.onTopologyChange boolean OnTopologyChange starts a blocks-only proof, one local storage node at a time, when the storage nodes, zones or capacities of the layout change after the operator recorded its baseline. Off by default: proofs then run only from the annotation. Ignored on a Follower site.
layoutManagement.siteRole string enum: ["Writer", "Follower"] SiteRole selects whether this GarageCluster may change the shared Garage layout. Absent is equivalent to Writer, the behavior of every release before this field existed. A Follower never stages, applies, reverts, or removes roles; it only reconciles its own workloads and reports status. Exactly one site in a federation should be the Writer.
layoutPolicy string default: "Auto"; enum: ["Auto", "Manual"] LayoutPolicy controls whether node layouts are automatically managed or manually configured. - "Auto": The controller automatically assigns all local pods to the layout using the cluster's zone and derives capacity from data PVC size. No GarageNode resources needed. - "Manual": You must create GarageNode resources for each node you want in the layout. Use this for fine-grained control over zones, capacities, or external nodes.
logging object Logging configures logging behavior for Garage nodes
logging.journald boolean Journald enables logging to systemd journald (requires Garage built with journald feature)
logging.level string Level sets the log level using RUST_LOG format. Examples: - "info": Default info level for all components - "debug": Debug level for all components - "garage=debug": Debug only for garage module - "garage=debug,netapp=info": Fine-grained per-component levels - "garage=trace,netapp=debug,rusoto=warn": Multiple components See https://docs.rs/env_logger for full syntax.
logging.syslog boolean Syslog enables logging to syslog (requires Garage built with syslog feature)
maintenance object Maintenance configures maintenance mode for this cluster.
maintenance.suspended boolean Suspended pauses all reconciliation for this cluster. The operator will not make any changes while suspended.
monitoring object Monitoring configures Prometheus integration for this cluster.
monitoring.additionalLabels map of string AdditionalLabels are added to the ServiceMonitor metadata.
monitoring.enabled boolean Enabled creates a ServiceMonitor targeting the admin API /metrics endpoint. Requires prometheus-operator to be installed in the cluster.
monitoring.interval string Interval is the Prometheus scrape interval (e.g. "30s", "1m"). Defaults to the Prometheus global scrape interval when unset.
monitoring.metricRelabelings array of object MetricRelabelings are applied to samples scraped from the admin /metrics endpoint before ingestion (set as the ServiceMonitor endpoint's metricRelabelings). Use them to drop high-cardinality series that nothing queries — e.g. the per-method rpc_duration_* histograms, which dominate a Garage node's metric series count.
monitoring.metricRelabelings[].action string default: "replace"; enum: ["replace", "Replace", "keep", "Keep", "drop", "Drop", "hashmod", "HashMod", "labelmap", "LabelMap", "labeldrop", "LabelDrop", "labelkeep", "LabelKeep", "lowercase", "Lowercase", "uppercase", "Uppercase", "keepequal", "KeepEqual", "dropequal", "DropEqual"] action to perform based on the regex matching. Uppercase and Lowercase actions require Prometheus >= v2.36.0. DropEqual and KeepEqual actions require Prometheus >= v2.41.0. Default: "Replace"
monitoring.metricRelabelings[].modulus integer format: "int64"; min: 0 modulus to take of the hash of the source label values. Only applicable when the action is HashMod.
monitoring.metricRelabelings[].regex string regex defines the regular expression against which the extracted value is matched.
monitoring.metricRelabelings[].replacement string replacement value against which a Replace action is performed if the regular expression matches. Regex capture groups are available.
monitoring.metricRelabelings[].separator string separator defines the string between concatenated SourceLabels.
monitoring.metricRelabelings[].sourceLabels array of string sourceLabels defines the source labels select values from existing labels. Their content is concatenated using the configured Separator and matched against the configured regular expression.
monitoring.metricRelabelings[].targetLabel string targetLabel defines the label to which the resulting string is written in a replacement. It is mandatory for Replace, HashMod, Lowercase, Uppercase, KeepEqual and DropEqual actions. Regex capture groups are available.
network object Network configures RPC and API networking
network.bootstrapPeers array of string BootstrapPeers lists initial peers for cluster formation. Format: "@:" Example: - "563e1ac825ee3323aa441e72c26d1030d6d4414aeb3dd25287c531e7fc2bc95d@10.0.0.1:3901" - "ec79480e0ce52ae26fd00c9da684e4fa56f77571b9b8560382f859930e63571d@garage-2.example.com:3901"
network.rpcBindAddress string RPCBindAddress is a custom wildcard TCP bind address for the RPC server. Managed workloads accept "0.0.0.0:3901" or "[::]:3901" so the generated Service can reach every Garage process. If set, this overrides RPCBindPort.
network.rpcBindOutgoing boolean RPCBindOutgoing pre-binds outgoing sockets to same IP
network.rpcBindPort integer default: 3901; format: "int32"; min: 1; max: 65535 RPCBindPort is the port for inter-cluster RPC
network.rpcPingTimeout string RPCPingTimeout sets the RPC ping timeout (e.g. "10s", "500ms").
network.rpcPublicAddr string RPCPublicAddr is the external address for other nodes to contact this node
network.rpcPublicAddrSubnet string RPCPublicAddrSubnet filters autodiscovered IPs to specific subnet
network.rpcSecretRef object RPCSecret is a reference to a secret containing the RPC secret The secret must have a key 'rpc-secret' with a 32-byte hex-encoded value
network.rpcSecretRef.key string required The key of the secret to select from. Must be a valid secret key.
network.rpcSecretRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
network.rpcSecretRef.optional boolean Specify whether the Secret or its key must be defined
network.rpcTimeout string RPCTimeout sets the RPC call timeout (e.g. "30s").
network.service object Service configures the Kubernetes Service for the cluster
network.service.annotations map of string Annotations to add to the service.
network.service.externalTrafficPolicy string ExternalTrafficPolicy for LoadBalancer/NodePort
network.service.labels map of string Labels to add to the service. Operator-managed labels take precedence on conflict.
network.service.loadBalancerIP string LoadBalancerIP for LoadBalancer type
network.service.loadBalancerSourceRanges array of string LoadBalancerSourceRanges for LoadBalancer type
network.service.type string default: "ClusterIP"; enum: ["ClusterIP", "NodePort", "LoadBalancer"] Type of service
nodeSelector map of string NodeSelector for pod scheduling
podAnnotations map of string PodAnnotations to add to Garage pods
podDisruptionBudget object PodDisruptionBudget configures a PodDisruptionBudget for the cluster's StatefulSet. When set, the operator creates a PDB to limit voluntary pod disruptions during node maintenance, rolling updates, or cluster autoscaler actions. If omitted, no PDB is created.
podDisruptionBudget.enabled boolean default: true Enabled enables PodDisruptionBudget creation
podDisruptionBudget.maxUnavailable integer or string MaxUnavailable specifies the maximum number of pods that can be unavailable. Can be an absolute number (e.g., 1) or a percentage (e.g., "25%"). Mutually exclusive with MinAvailable.
podDisruptionBudget.minAvailable integer or string MinAvailable specifies the minimum number of pods that must be available. Can be an absolute number (e.g., 2) or a percentage (e.g., "50%"). Mutually exclusive with MaxUnavailable.
podLabels map of string PodLabels to add to Garage pods
priorityClassName string PriorityClassName for Garage pods
publicEndpoint object PublicEndpoint configures how remote clusters reach this cluster's nodes Required for multi-cluster federation
publicEndpoint.externalIP object ExternalIP is retained for API compatibility but is not supported. Setting it is rejected because the operator does not consume the explicit address mapping or template.
publicEndpoint.externalIP.addressTemplate string AddressTemplate is retained for API compatibility but is unsupported.
publicEndpoint.externalIP.addresses map of string Addresses is retained for API compatibility but is unsupported.
publicEndpoint.loadBalancer object LoadBalancer configuration
publicEndpoint.loadBalancer.annotations map of string Annotations to add to the service.
publicEndpoint.loadBalancer.labels map of string Labels to add to the service. Operator-managed labels take precedence on conflict.
publicEndpoint.loadBalancer.perNode boolean PerNode creates a separate LoadBalancer service per GarageCluster pod instead of one shared LoadBalancer service. In auto-layout GarageCluster mode, those services are used for operator-driven reverse ConnectClusterNodes calls; the pods still share one Garage ConfigMap, so distinct per-pod rpc_public_addr values are not written into Garage config. Use Manual layout with GarageNode resources when each node also needs its own advertised rpc_public_addr.
publicEndpoint.nodePort object NodePort configuration
publicEndpoint.nodePort.annotations map of string Annotations to add to the service.
publicEndpoint.nodePort.basePort integer format: "int32"; min: 30000; max: 32767 BasePort is the starting NodePort; Garage pod N is exposed on BasePort+N. If omitted, the controller allocates starting from the RPC port base (30901).
publicEndpoint.nodePort.externalAddresses array of string required ExternalAddresses are the externally-reachable IPs or hostnames of the Kubernetes nodes. The operator maps Garage pod N to ExternalAddresses[N % len(ExternalAddresses)], so the order should be stable. Must have at least one entry.
publicEndpoint.nodePort.labels map of string Labels to add to the service. Operator-managed labels take precedence on conflict.
publicEndpoint.type string required; enum: ["LoadBalancer", "NodePort", "ExternalIP", "Headless"] Type specifies how nodes are exposed to remote clusters for RPC
remoteClusters array of object RemoteClusters lists Garage clusters in other Kubernetes clusters to federate with. The operator connects to each remote cluster's Admin API to discover its nodes, merge them into the shared layout, and keep the layout in sync as nodes come and go. All clusters in a federation must share the same RPC secret.
remoteClusters[].connection object required Connection defines how to connect to this remote cluster
remoteClusters[].connection.adminApiEndpoint string required; min length: 1 AdminAPIEndpoint is the admin API endpoint of the remote cluster This should be a reachable HTTP/HTTPS URL (e.g., via Tailscale, LoadBalancer, or port-forward) Example: "http://garage-remote.tailscale:3903"
remoteClusters[].connection.adminTokenSecretRef object AdminTokenSecretRef references the admin token for the remote cluster's API If not specified, uses the local cluster's admin token (for shared-token setups)
remoteClusters[].connection.adminTokenSecretRef.key string required The key of the secret to select from. Must be a valid secret key.
remoteClusters[].connection.adminTokenSecretRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
remoteClusters[].connection.adminTokenSecretRef.optional boolean Specify whether the Secret or its key must be defined
remoteClusters[].connection.gatewayRpcEndpointTemplate string GatewayRPCEndpointTemplate is a hostname:port template used by federation to connect to remote gateway pods individually. The literal {ordinal} is replaced with each remote gateway pod's ordinal (0, 1, ...). Example: "ottawa-garage-gw-{ordinal}.keiretsu.ts.net:3901"
remoteClusters[].defaultCapacity integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" DefaultCapacity is retained for API compatibility but is not supported. Remote role capacity is copied from the source cluster's committed or staged layout and cannot be overridden by the importing cluster.
remoteClusters[].name string required; min length: 1 Name is a friendly name for this remote cluster
remoteClusters[].zone string required; min length: 1 Zone is the zone name for nodes in this remote cluster
replicas integer required; default: 3; format: "int32"; min: 0 Replicas controls the legacy operator-managed storage or gateway group. Set it to 0 to disable that group. Ordinary Manual GarageNodes remain independently declared, as do v1beta2 node-local pools preserved through the conversion payload.
replication object Replication configures data replication settings. If omitted, defaults to factor: 3 and consistencyMode: consistent.
replication.consistencyMode string default: "consistent"; enum: ["consistent", "degraded", "dangerous"] ConsistencyMode controls quorum behavior for read/write operations. Values: - "consistent" (default): Require quorum for both reads and writes. Safest option, ensures strong consistency. - "degraded": Allow reads from single node when quorum unavailable. May return stale data during network partitions. - "dangerous": Allow reads AND writes without quorum. WARNING: May lose data during failures!
replication.factor integer required; default: 3; min: 1; max: 7 Factor is the replication factor (1, 2, 3, 5, 7, etc.) Must be the same on all nodes in the cluster
replication.zoneRedundancyMinZones integer min: 1; max: 7 ZoneRedundancyMinZones is the minimum number of zones required. Only valid when ZoneRedundancyMode is "AtLeast". Must not exceed the replication factor.
replication.zoneRedundancyMode string enum: ["Maximum", "AtLeast"] ZoneRedundancyMode controls how data is distributed across zones. "Maximum": spread replicas across as many zones as possible (default). "AtLeast": require replicas in at least ZoneRedundancyMinZones zones.
resources object Resources specifies compute resources for Garage pods
resources.claims array of object Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers.
resources.claims[].name string required Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container.
resources.claims[].request string Request is the name chosen for a request in the referenced claim. If empty, everything from the claim is made available, otherwise only the result of this request.
resources.limits map of integer or string Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
resources.requests map of integer or string Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
s3Api object S3API configures the S3-compatible API endpoint
s3Api.bindAddress string BindAddress is a custom wildcard TCP bind address for the S3 API. Managed workloads accept "0.0.0.0:3900" or "[::]:3900" so the generated Service and probes can reach every Garage process. If set, this overrides BindPort.
s3Api.bindPort integer default: 3900; format: "int32"; min: 1; max: 65535 BindPort is the port to bind for S3 API
s3Api.region string required; default: "garage" Region is the AWS S3 region name to use
s3Api.rootDomain string RootDomain is the root domain suffix for vhost-style S3 access. When set, buckets can be accessed via .. Examples: - ".s3.garage.tld" -> Access bucket "mybucket" at "mybucket.s3.garage.tld" - ".s3.example.com" -> Access bucket "data" at "data.s3.example.com" Note: Include the leading dot.
security object Security configures security-related settings
security.allowInsecureSecretPermissions boolean AllowInsecureSecretPermissions bypasses Garage's check that secret files (RPC secret, admin token) are not world-readable on disk. Only enable if your container security model handles file permissions externally. Enabling this weakens the defense-in-depth for credential exposure.
security.allowPunycode boolean AllowPunycode allows punycode in bucket names
security.tls object TLS configures TLS settings
security.tls.caSecretRef object CASecretRef references a secret containing the CA certificate for verifying peer nodes
security.tls.caSecretRef.key string required The key of the secret to select from. Must be a valid secret key.
security.tls.caSecretRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
security.tls.caSecretRef.optional boolean Specify whether the Secret or its key must be defined
security.tls.certSecretRef object CertSecretRef references a secret containing the TLS certificate for RPC
security.tls.certSecretRef.key string required The key of the secret to select from. Must be a valid secret key.
security.tls.certSecretRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
security.tls.certSecretRef.optional boolean Specify whether the Secret or its key must be defined
security.tls.enabled boolean Enabled enables TLS for inter-node RPC communication. NOTE: This does NOT enable TLS for S3/Admin APIs - use a service mesh or load balancer for that.
security.tls.keySecretRef object KeySecretRef references a secret containing the TLS private key for RPC
security.tls.keySecretRef.key string required The key of the secret to select from. Must be a valid secret key.
security.tls.keySecretRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
security.tls.keySecretRef.optional boolean Specify whether the Secret or its key must be defined
securityContext object SecurityContext for Garage pods
securityContext.appArmorProfile object appArmorProfile is the AppArmor options to use by the containers in this pod. Note that this field cannot be set when spec.os.name is windows.
securityContext.appArmorProfile.localhostProfile string localhostProfile indicates a profile loaded on the node that should be used. The profile must be preconfigured on the node to work. Must match the loaded name of the profile. Must be set if and only if type is "Localhost".
securityContext.appArmorProfile.type string required type indicates which kind of AppArmor profile will be applied. Valid options are: Localhost - a profile pre-loaded on the node. RuntimeDefault - the container runtime's default profile. Unconfined - no AppArmor enforcement.
securityContext.fsGroup integer format: "int64" A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod: 1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw---- If unset, the Kubelet will not modify the ownership and permissions of any volume. Note that this field cannot be set when spec.os.name is windows.
securityContext.fsGroupChangePolicy string fsGroupChangePolicy defines behavior of changing ownership and permission of the volume before being exposed inside Pod. This field will only apply to volume types which support fsGroup based ownership(and permissions). It will have no effect on ephemeral volume types such as: secret, configmaps and emptydir. Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. Note that this field cannot be set when spec.os.name is windows.
securityContext.runAsGroup integer format: "int64" The GID to run the entrypoint of the container process. Uses runtime default if unset. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container. Note that this field cannot be set when spec.os.name is windows.
securityContext.runAsNonRoot boolean Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.
securityContext.runAsUser integer format: "int64" The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container. Note that this field cannot be set when spec.os.name is windows.
securityContext.seLinuxChangePolicy string seLinuxChangePolicy defines how the container's SELinux label is applied to all volumes used by the Pod. It has no effect on nodes that do not support SELinux or to volumes does not support SELinux. Valid values are "MountOption" and "Recursive". "Recursive" means relabeling of all files on all Pod volumes by the container runtime. This may be slow for large volumes, but allows mixing privileged and unprivileged Pods sharing the same volume on the same node. "MountOption" mounts all eligible Pod volumes with -o context mount option. This requires all Pods that share the same volume to use the same SELinux label. It is not possible to share the same volume among privileged and unprivileged Pods. Eligible volumes are in-tree FibreChannel and iSCSI volumes, and all CSI volumes whose CSI driver announces SELinux support by setting spec.seLinuxMount: true in their CSIDriver instance. Other volumes are always re-labelled recursively. If not specified, "MountOption" is used. This field affects only Pods that have SELinux label set, either in PodSecurityContext or in SecurityContext of all containers. All Pods that use the same volume should use the same seLinuxChangePolicy, otherwise some pods can get stuck in ContainerCreating state. Note that this field cannot be set when spec.os.name is windows.
securityContext.seLinuxOptions object The SELinux context to be applied to all containers. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container. Note that this field cannot be set when spec.os.name is windows.
securityContext.seLinuxOptions.level string Level is SELinux level label that applies to the container.
securityContext.seLinuxOptions.role string Role is a SELinux role label that applies to the container.
securityContext.seLinuxOptions.type string Type is a SELinux type label that applies to the container.
securityContext.seLinuxOptions.user string User is a SELinux user label that applies to the container.
securityContext.seccompProfile object The seccomp options to use by the containers in this pod. Note that this field cannot be set when spec.os.name is windows.
securityContext.seccompProfile.localhostProfile string localhostProfile indicates a profile defined in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile location. Must be set if type is "Localhost". Must NOT be set for any other type.
securityContext.seccompProfile.type string required type indicates which kind of seccomp profile will be applied. Valid options are: Localhost - a profile defined in a file on the node should be used. RuntimeDefault - the container runtime default profile should be used. Unconfined - no profile should be applied.
securityContext.supplementalGroups array of integer A list of groups applied to the first process run in each container, in addition to the container's primary GID and fsGroup (if specified). If the SupplementalGroupsPolicy feature is enabled, the supplementalGroupsPolicy field determines whether these are in addition to or instead of any group memberships defined in the container image. If unspecified, no additional groups are added, though group memberships defined in the container image may still be used, depending on the supplementalGroupsPolicy field. Note that this field cannot be set when spec.os.name is windows.
securityContext.supplementalGroupsPolicy string Defines how supplemental groups of the first container processes are calculated. Valid values are "Merge" and "Strict". If not specified, "Merge" is used. (Alpha) Using the field requires the SupplementalGroupsPolicy feature gate to be enabled and the container runtime must implement support for this feature. Note that this field cannot be set when spec.os.name is windows.
securityContext.sysctls array of object Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch. Note that this field cannot be set when spec.os.name is windows.
securityContext.sysctls[].name string required Name of a property to set
securityContext.sysctls[].value string required Value of a property to set
securityContext.windowsOptions object The Windows specific settings applied to all containers. If unspecified, the options within a container's SecurityContext will be used. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. Note that this field cannot be set when spec.os.name is linux.
securityContext.windowsOptions.gmsaCredentialSpec string GMSACredentialSpec is where the GMSA admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the GMSA credential spec named by the GMSACredentialSpecName field.
securityContext.windowsOptions.gmsaCredentialSpecName string GMSACredentialSpecName is the name of the GMSA credential spec to use.
securityContext.windowsOptions.hostProcess boolean HostProcess determines if a container should be run as a 'Host Process' container. All of a Pod's containers must have the same effective HostProcess value (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). In addition, if HostProcess is true then HostNetwork must also be set to true.
securityContext.windowsOptions.runAsUserName string The UserName in Windows to run the entrypoint of the container process. Defaults to the user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.
serviceAccountName string ServiceAccountName for Garage pods
storage object Storage configures storage settings for metadata and data. Optional - sensible defaults are provided: - Storage clusters: 10Gi metadata, 100Gi data - Gateway clusters: 1Gi metadata only (data uses EmptyDir)
storage.data object validation: volumeAttributesClassName is only valid for PersistentVolumeClaim volumes Data configures data block storage
storage.data.accessModes array of string AccessModes for the PVC. Only valid when Type=PersistentVolumeClaim.
storage.data.annotations map of string Annotations to set on the PVC. Only valid when Type=PersistentVolumeClaim.
storage.data.dataSourceRef object DataSourceRef is the opt-in restore source for every generated PVC of this volume role. Setting it copies the same same-namespace, non-core group populator onto each Auto ordinal of this role; the populator must map target claim i to source-group member i. A core PVC or single-volume clone is not a safe source. Metadata and data are independent roles: restore identity by setting this on metadata, object blocks by setting it on data. It is immutable after the GarageCluster is created.
storage.data.dataSourceRef.apiGroup string APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.
storage.data.dataSourceRef.kind string required Kind is the type of resource being referenced
storage.data.dataSourceRef.name string required Name is the name of resource being referenced
storage.data.dataSourceRef.namespace string Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
storage.data.labels map of string Labels to set on the PVC. Only valid when Type=PersistentVolumeClaim.
storage.data.paths array of object Paths configures multiple data directories for multi-disk setups. Only valid for data volumes — webhook rejects this on metadata volumes. Only valid when Type=PersistentVolumeClaim.
storage.data.paths[].capacity integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" Capacity of the drive (required unless readOnly)
storage.data.paths[].path string required Path to the data directory
storage.data.paths[].readOnly boolean ReadOnly marks directory as legacy read-only for migrations
storage.data.paths[].volume object validation: volumeAttributesClassName is only valid for PersistentVolumeClaim volumes Volume configuration if using PVC
storage.data.paths[].volume.accessModes array of string AccessModes for the PVC.
storage.data.paths[].volume.annotations map of string Annotations to set on the PVC.
storage.data.paths[].volume.dataSourceRef object DataSourceRef is the opt-in restore source for this data path's PVC across every Auto ordinal. Same group-populator contract as VolumeConfig.dataSourceRef.
storage.data.paths[].volume.dataSourceRef.apiGroup string APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.
storage.data.paths[].volume.dataSourceRef.kind string required Kind is the type of resource being referenced
storage.data.paths[].volume.dataSourceRef.name string required Name is the name of resource being referenced
storage.data.paths[].volume.dataSourceRef.namespace string Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
storage.data.paths[].volume.labels map of string Labels to set on the PVC.
storage.data.paths[].volume.selector object Selector matches pre-provisioned PVs for newly created claims. Kubernetes does not dynamically provision a PV when this is set; StorageClassName must also match the target PV.
storage.data.paths[].volume.selector.matchExpressions array of object matchExpressions is a list of label selector requirements. The requirements are ANDed.
storage.data.paths[].volume.selector.matchExpressions[].key string required key is the label key that the selector applies to.
storage.data.paths[].volume.selector.matchExpressions[].operator string required operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
storage.data.paths[].volume.selector.matchExpressions[].values array of string values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
storage.data.paths[].volume.selector.matchLabels map of string matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
storage.data.paths[].volume.size integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" Size of the volume (storage request).
storage.data.paths[].volume.storageClassName string StorageClassName for the PVC.
storage.data.paths[].volume.type string default: "PersistentVolumeClaim"; enum: ["PersistentVolumeClaim", "EmptyDir"] Type specifies the volume type: PersistentVolumeClaim (default) or EmptyDir.
storage.data.paths[].volume.volumeAttributesClassName string min length: 1; max length: 253; pattern: "^[a-z0-9]([-a-z0-9][a-z0-9])?(\.[a-z0-9]([-a-z0-9][a-z0-9])?)*$" VolumeAttributesClassName is the name of a cluster-scoped Kubernetes VolumeAttributesClass applied to every PVC generated for this volume role. The class's driver must match the StorageClass provisioner; the operator does not check that or whether the class exists. Valid only for PersistentVolumeClaim volumes. Unlike storageClassName it may be changed while replicas are live: the operator updates bound claims in place, which asks the CSI driver to modify the volume. Requires Kubernetes 1.34+ (or 1.31-1.33 with the VolumeAttributesClass feature enabled) and a driver that supports ModifyVolume. Removing a configured value from a live volume is rejected.
storage.data.paths[].volume.volumeClaimTemplateSpec object VolumeClaimTemplateSpec is retained for API compatibility but is not supported by operator-managed workloads. Admission rejects new or changed values; an unchanged legacy value is tolerated only so it can be removed. Use the explicit PVC fields above, or pre-provision a PVC and reference it from an ordinary GarageNode storage existingClaim. Deprecated: use explicit PVC fields or GarageNode existingClaim.
storage.data.paths[].volume.volumeClaimTemplateSpec.accessModes array of string accessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1
storage.data.paths[].volume.volumeClaimTemplateSpec.dataSource object dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource.
storage.data.paths[].volume.volumeClaimTemplateSpec.dataSource.apiGroup string APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.
storage.data.paths[].volume.volumeClaimTemplateSpec.dataSource.kind string required Kind is the type of resource being referenced
storage.data.paths[].volume.volumeClaimTemplateSpec.dataSource.name string required Name is the name of resource being referenced
storage.data.paths[].volume.volumeClaimTemplateSpec.dataSourceRef object dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn't specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn't set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While dataSource ignores disallowed values (dropping them), dataSourceRef preserves all values, and generates an error if a disallowed value is specified. * While dataSource only allows local objects, dataSourceRef allows objects in any namespaces. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
storage.data.paths[].volume.volumeClaimTemplateSpec.dataSourceRef.apiGroup string APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.
storage.data.paths[].volume.volumeClaimTemplateSpec.dataSourceRef.kind string required Kind is the type of resource being referenced
storage.data.paths[].volume.volumeClaimTemplateSpec.dataSourceRef.name string required Name is the name of resource being referenced
storage.data.paths[].volume.volumeClaimTemplateSpec.dataSourceRef.namespace string Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
storage.data.paths[].volume.volumeClaimTemplateSpec.resources object resources represents the minimum resources the volume should have. Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources
storage.data.paths[].volume.volumeClaimTemplateSpec.resources.limits map of integer or string Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
storage.data.paths[].volume.volumeClaimTemplateSpec.resources.requests map of integer or string Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
storage.data.paths[].volume.volumeClaimTemplateSpec.selector object selector is a label query over volumes to consider for binding.
storage.data.paths[].volume.volumeClaimTemplateSpec.selector.matchExpressions array of object matchExpressions is a list of label selector requirements. The requirements are ANDed.
storage.data.paths[].volume.volumeClaimTemplateSpec.selector.matchExpressions[].key string required key is the label key that the selector applies to.
storage.data.paths[].volume.volumeClaimTemplateSpec.selector.matchExpressions[].operator string required operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
storage.data.paths[].volume.volumeClaimTemplateSpec.selector.matchExpressions[].values array of string values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
storage.data.paths[].volume.volumeClaimTemplateSpec.selector.matchLabels map of string matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
storage.data.paths[].volume.volumeClaimTemplateSpec.storageClassName string storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1
storage.data.paths[].volume.volumeClaimTemplateSpec.volumeAttributesClassName string volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, it can be changed after the claim is created. An empty string or nil value indicates that no VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
storage.data.paths[].volume.volumeClaimTemplateSpec.volumeMode string volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec.
storage.data.paths[].volume.volumeClaimTemplateSpec.volumeName string volumeName is the binding reference to the PersistentVolume backing this claim.
storage.data.selector object Selector matches pre-provisioned PVs for newly created claims. Kubernetes does not dynamically provision a PV when this is set. Only valid when Type=PersistentVolumeClaim; StorageClassName must also match the target PV.
storage.data.selector.matchExpressions array of object matchExpressions is a list of label selector requirements. The requirements are ANDed.
storage.data.selector.matchExpressions[].key string required key is the label key that the selector applies to.
storage.data.selector.matchExpressions[].operator string required operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
storage.data.selector.matchExpressions[].values array of string values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
storage.data.selector.matchLabels map of string matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
storage.data.size integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" Size of the volume. - For PVC: storage request (defaults to 10Gi for metadata if not specified) - For EmptyDir: optional sizeLimit (if omitted, uses available node resources)
storage.data.storageClassName string StorageClassName for the PVC. Only valid when Type=PersistentVolumeClaim.
storage.data.type string default: "PersistentVolumeClaim"; enum: ["PersistentVolumeClaim", "EmptyDir"] Type specifies the volume type: PersistentVolumeClaim (default) or EmptyDir. When EmptyDir, data is lost on pod restart - only use for testing.
storage.data.volumeAttributesClassName string min length: 1; max length: 253; pattern: "^[a-z0-9]([-a-z0-9][a-z0-9])?(\.[a-z0-9]([-a-z0-9][a-z0-9])?)*$" VolumeAttributesClassName is the name of a cluster-scoped Kubernetes VolumeAttributesClass applied to every PVC generated for this volume role. The class's driver must match the StorageClass provisioner; the operator does not check that or whether the class exists. Valid only for PersistentVolumeClaim volumes. Unlike storageClassName it may be changed while replicas are live: the operator updates bound claims in place, which asks the CSI driver to modify the volume. Requires Kubernetes 1.34+ (or 1.31-1.33 with the VolumeAttributesClass feature enabled) and a driver that supports ModifyVolume. Removing a configured value from a live volume is rejected.
storage.data.volumeClaimTemplateSpec object VolumeClaimTemplateSpec is retained for API compatibility but is not supported by operator-managed workloads. Admission rejects new or changed values; an unchanged legacy value is tolerated only so it can be removed. Arbitrary claim-template dataSource or volumeName settings can clone a metadata node_key or bind multiple Garage identities to one disk. Use the explicit PVC fields above, or pre-provision a PVC and reference it from an ordinary GarageNode storage existingClaim. Deprecated: use explicit PVC fields or GarageNode existingClaim.
storage.data.volumeClaimTemplateSpec.accessModes array of string accessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1
storage.data.volumeClaimTemplateSpec.dataSource object dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource.
storage.data.volumeClaimTemplateSpec.dataSource.apiGroup string APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.
storage.data.volumeClaimTemplateSpec.dataSource.kind string required Kind is the type of resource being referenced
storage.data.volumeClaimTemplateSpec.dataSource.name string required Name is the name of resource being referenced
storage.data.volumeClaimTemplateSpec.dataSourceRef object dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn't specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn't set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While dataSource ignores disallowed values (dropping them), dataSourceRef preserves all values, and generates an error if a disallowed value is specified. * While dataSource only allows local objects, dataSourceRef allows objects in any namespaces. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
storage.data.volumeClaimTemplateSpec.dataSourceRef.apiGroup string APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.
storage.data.volumeClaimTemplateSpec.dataSourceRef.kind string required Kind is the type of resource being referenced
storage.data.volumeClaimTemplateSpec.dataSourceRef.name string required Name is the name of resource being referenced
storage.data.volumeClaimTemplateSpec.dataSourceRef.namespace string Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
storage.data.volumeClaimTemplateSpec.resources object resources represents the minimum resources the volume should have. Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources
storage.data.volumeClaimTemplateSpec.resources.limits map of integer or string Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
storage.data.volumeClaimTemplateSpec.resources.requests map of integer or string Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
storage.data.volumeClaimTemplateSpec.selector object selector is a label query over volumes to consider for binding.
storage.data.volumeClaimTemplateSpec.selector.matchExpressions array of object matchExpressions is a list of label selector requirements. The requirements are ANDed.
storage.data.volumeClaimTemplateSpec.selector.matchExpressions[].key string required key is the label key that the selector applies to.
storage.data.volumeClaimTemplateSpec.selector.matchExpressions[].operator string required operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
storage.data.volumeClaimTemplateSpec.selector.matchExpressions[].values array of string values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
storage.data.volumeClaimTemplateSpec.selector.matchLabels map of string matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
storage.data.volumeClaimTemplateSpec.storageClassName string storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1
storage.data.volumeClaimTemplateSpec.volumeAttributesClassName string volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, it can be changed after the claim is created. An empty string or nil value indicates that no VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
storage.data.volumeClaimTemplateSpec.volumeMode string volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec.
storage.data.volumeClaimTemplateSpec.volumeName string volumeName is the binding reference to the PersistentVolume backing this claim.
storage.dataFsync boolean DataFsync enables fsync for data block writes
storage.env array of object Env is a list of environment variables to set on the Garage container in the storage tier. Garage config-path and RPC/Admin/metrics credential variables are operator-reserved because drain safety and mesh identity rely on the rendered config and pinned immutable Secrets.
storage.env[].name string required Name of the environment variable. May consist of any printable ASCII characters except '='.
storage.env[].value string Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".
storage.env[].valueFrom object Source for the environment variable's value. Cannot be used if value is not empty.
storage.env[].valueFrom.configMapKeyRef object Selects a key of a ConfigMap.
storage.env[].valueFrom.configMapKeyRef.key string required The key to select from the ConfigMap's Data field. Keys in the BinaryData field are not currently propagated to container env vars.
storage.env[].valueFrom.configMapKeyRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
storage.env[].valueFrom.configMapKeyRef.optional boolean Specify whether the ConfigMap or its key must be defined
storage.env[].valueFrom.fieldRef object Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels\['<KEY>'\], metadata.annotations\['<KEY>'\], spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.
storage.env[].valueFrom.fieldRef.apiVersion string Version of the schema the FieldPath is written in terms of, defaults to "v1".
storage.env[].valueFrom.fieldRef.fieldPath string required Path of the field to select in the specified API version.
storage.env[].valueFrom.fileKeyRef object FileKeyRef selects a key of the env file. Requires the EnvFiles feature gate to be enabled.
storage.env[].valueFrom.fileKeyRef.key string required The key within the env file. An invalid key will prevent the pod from starting. The keys defined within a source may consist of any printable ASCII characters except '='. During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters.
storage.env[].valueFrom.fileKeyRef.optional boolean default: false Specify whether the file or its key must be defined. If the file or key does not exist, then the env var is not published. If optional is set to true and the specified key does not exist, the environment variable will not be set in the Pod's containers. If optional is set to false and the specified key does not exist, an error will be returned during Pod creation.
storage.env[].valueFrom.fileKeyRef.path string required The path within the volume from which to select the file. Must be relative and may not contain the '..' path or start with '..'.
storage.env[].valueFrom.fileKeyRef.volumeName string required The name of the volume mount containing the env file.
storage.env[].valueFrom.resourceFieldRef object Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.
storage.env[].valueFrom.resourceFieldRef.containerName string Container name: required for volumes, optional for env vars
storage.env[].valueFrom.resourceFieldRef.divisor integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" Specifies the output format of the exposed resources, defaults to "1"
storage.env[].valueFrom.resourceFieldRef.resource string required Required: resource to select
storage.env[].valueFrom.secretKeyRef object Selects a key of a secret in the pod's namespace
storage.env[].valueFrom.secretKeyRef.key string required The key of the secret to select from. Must be a valid secret key.
storage.env[].valueFrom.secretKeyRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
storage.env[].valueFrom.secretKeyRef.optional boolean Specify whether the Secret or its key must be defined
storage.envFrom array of object EnvFrom is a list of sources to populate environment variables in the Garage container for the storage tier. A source prefix must not be capable of injecting an operator-reserved Garage variable.
storage.envFrom[].configMapRef object The ConfigMap to select from
storage.envFrom[].configMapRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
storage.envFrom[].configMapRef.optional boolean Specify whether the ConfigMap must be defined
storage.envFrom[].prefix string Optional text to prepend to the name of each environment variable. May consist of any printable ASCII characters except '='.
storage.envFrom[].secretRef object The Secret to select from
storage.envFrom[].secretRef.name string default: "" Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
storage.envFrom[].secretRef.optional boolean Specify whether the Secret must be defined
storage.layoutPolicy string LayoutPolicy overrides the cluster layoutPolicy for the storage tier only (Auto/Manual). Round-trips losslessly with v1beta2 spec.storage.layoutPolicy.
storage.metadata object validation: volumeAttributesClassName is only valid for PersistentVolumeClaim volumes Metadata configures metadata storage
storage.metadata.accessModes array of string AccessModes for the PVC. Only valid when Type=PersistentVolumeClaim.
storage.metadata.annotations map of string Annotations to set on the PVC. Only valid when Type=PersistentVolumeClaim.
storage.metadata.dataSourceRef object DataSourceRef is the opt-in restore source for every generated PVC of this volume role. Setting it copies the same same-namespace, non-core group populator onto each Auto ordinal of this role; the populator must map target claim i to source-group member i. A core PVC or single-volume clone is not a safe source. Metadata and data are independent roles: restore identity by setting this on metadata, object blocks by setting it on data. It is immutable after the GarageCluster is created.
storage.metadata.dataSourceRef.apiGroup string APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.
storage.metadata.dataSourceRef.kind string required Kind is the type of resource being referenced
storage.metadata.dataSourceRef.name string required Name is the name of resource being referenced
storage.metadata.dataSourceRef.namespace string Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
storage.metadata.labels map of string Labels to set on the PVC. Only valid when Type=PersistentVolumeClaim.
storage.metadata.paths array of object Paths configures multiple data directories for multi-disk setups. Only valid for data volumes — webhook rejects this on metadata volumes. Only valid when Type=PersistentVolumeClaim.
storage.metadata.paths[].capacity integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" Capacity of the drive (required unless readOnly)
storage.metadata.paths[].path string required Path to the data directory
storage.metadata.paths[].readOnly boolean ReadOnly marks directory as legacy read-only for migrations
storage.metadata.paths[].volume object validation: volumeAttributesClassName is only valid for PersistentVolumeClaim volumes Volume configuration if using PVC
storage.metadata.paths[].volume.accessModes array of string AccessModes for the PVC.
storage.metadata.paths[].volume.annotations map of string Annotations to set on the PVC.
storage.metadata.paths[].volume.dataSourceRef object DataSourceRef is the opt-in restore source for this data path's PVC across every Auto ordinal. Same group-populator contract as VolumeConfig.dataSourceRef.
storage.metadata.paths[].volume.dataSourceRef.apiGroup string APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.
storage.metadata.paths[].volume.dataSourceRef.kind string required Kind is the type of resource being referenced
storage.metadata.paths[].volume.dataSourceRef.name string required Name is the name of resource being referenced
storage.metadata.paths[].volume.dataSourceRef.namespace string Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
storage.metadata.paths[].volume.labels map of string Labels to set on the PVC.
storage.metadata.paths[].volume.selector object Selector matches pre-provisioned PVs for newly created claims. Kubernetes does not dynamically provision a PV when this is set; StorageClassName must also match the target PV.
storage.metadata.paths[].volume.selector.matchExpressions array of object matchExpressions is a list of label selector requirements. The requirements are ANDed.
storage.metadata.paths[].volume.selector.matchExpressions[].key string required key is the label key that the selector applies to.
storage.metadata.paths[].volume.selector.matchExpressions[].operator string required operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
storage.metadata.paths[].volume.selector.matchExpressions[].values array of string values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
storage.metadata.paths[].volume.selector.matchLabels map of string matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
storage.metadata.paths[].volume.size integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" Size of the volume (storage request).
storage.metadata.paths[].volume.storageClassName string StorageClassName for the PVC.
storage.metadata.paths[].volume.type string default: "PersistentVolumeClaim"; enum: ["PersistentVolumeClaim", "EmptyDir"] Type specifies the volume type: PersistentVolumeClaim (default) or EmptyDir.
storage.metadata.paths[].volume.volumeAttributesClassName string min length: 1; max length: 253; pattern: "^[a-z0-9]([-a-z0-9][a-z0-9])?(\.[a-z0-9]([-a-z0-9][a-z0-9])?)*$" VolumeAttributesClassName is the name of a cluster-scoped Kubernetes VolumeAttributesClass applied to every PVC generated for this volume role. The class's driver must match the StorageClass provisioner; the operator does not check that or whether the class exists. Valid only for PersistentVolumeClaim volumes. Unlike storageClassName it may be changed while replicas are live: the operator updates bound claims in place, which asks the CSI driver to modify the volume. Requires Kubernetes 1.34+ (or 1.31-1.33 with the VolumeAttributesClass feature enabled) and a driver that supports ModifyVolume. Removing a configured value from a live volume is rejected.
storage.metadata.paths[].volume.volumeClaimTemplateSpec object VolumeClaimTemplateSpec is retained for API compatibility but is not supported by operator-managed workloads. Admission rejects new or changed values; an unchanged legacy value is tolerated only so it can be removed. Use the explicit PVC fields above, or pre-provision a PVC and reference it from an ordinary GarageNode storage existingClaim. Deprecated: use explicit PVC fields or GarageNode existingClaim.
storage.metadata.paths[].volume.volumeClaimTemplateSpec.accessModes array of string accessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1
storage.metadata.paths[].volume.volumeClaimTemplateSpec.dataSource object dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource.
storage.metadata.paths[].volume.volumeClaimTemplateSpec.dataSource.apiGroup string APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.
storage.metadata.paths[].volume.volumeClaimTemplateSpec.dataSource.kind string required Kind is the type of resource being referenced
storage.metadata.paths[].volume.volumeClaimTemplateSpec.dataSource.name string required Name is the name of resource being referenced
storage.metadata.paths[].volume.volumeClaimTemplateSpec.dataSourceRef object dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn't specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn't set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While dataSource ignores disallowed values (dropping them), dataSourceRef preserves all values, and generates an error if a disallowed value is specified. * While dataSource only allows local objects, dataSourceRef allows objects in any namespaces. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
storage.metadata.paths[].volume.volumeClaimTemplateSpec.dataSourceRef.apiGroup string APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.
storage.metadata.paths[].volume.volumeClaimTemplateSpec.dataSourceRef.kind string required Kind is the type of resource being referenced
storage.metadata.paths[].volume.volumeClaimTemplateSpec.dataSourceRef.name string required Name is the name of resource being referenced
storage.metadata.paths[].volume.volumeClaimTemplateSpec.dataSourceRef.namespace string Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
storage.metadata.paths[].volume.volumeClaimTemplateSpec.resources object resources represents the minimum resources the volume should have. Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources
storage.metadata.paths[].volume.volumeClaimTemplateSpec.resources.limits map of integer or string Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
storage.metadata.paths[].volume.volumeClaimTemplateSpec.resources.requests map of integer or string Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
storage.metadata.paths[].volume.volumeClaimTemplateSpec.selector object selector is a label query over volumes to consider for binding.
storage.metadata.paths[].volume.volumeClaimTemplateSpec.selector.matchExpressions array of object matchExpressions is a list of label selector requirements. The requirements are ANDed.
storage.metadata.paths[].volume.volumeClaimTemplateSpec.selector.matchExpressions[].key string required key is the label key that the selector applies to.
storage.metadata.paths[].volume.volumeClaimTemplateSpec.selector.matchExpressions[].operator string required operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
storage.metadata.paths[].volume.volumeClaimTemplateSpec.selector.matchExpressions[].values array of string values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
storage.metadata.paths[].volume.volumeClaimTemplateSpec.selector.matchLabels map of string matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
storage.metadata.paths[].volume.volumeClaimTemplateSpec.storageClassName string storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1
storage.metadata.paths[].volume.volumeClaimTemplateSpec.volumeAttributesClassName string volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, it can be changed after the claim is created. An empty string or nil value indicates that no VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
storage.metadata.paths[].volume.volumeClaimTemplateSpec.volumeMode string volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec.
storage.metadata.paths[].volume.volumeClaimTemplateSpec.volumeName string volumeName is the binding reference to the PersistentVolume backing this claim.
storage.metadata.selector object Selector matches pre-provisioned PVs for newly created claims. Kubernetes does not dynamically provision a PV when this is set. Only valid when Type=PersistentVolumeClaim; StorageClassName must also match the target PV.
storage.metadata.selector.matchExpressions array of object matchExpressions is a list of label selector requirements. The requirements are ANDed.
storage.metadata.selector.matchExpressions[].key string required key is the label key that the selector applies to.
storage.metadata.selector.matchExpressions[].operator string required operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
storage.metadata.selector.matchExpressions[].values array of string values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
storage.metadata.selector.matchLabels map of string matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
storage.metadata.size integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" Size of the volume. - For PVC: storage request (defaults to 10Gi for metadata if not specified) - For EmptyDir: optional sizeLimit (if omitted, uses available node resources)
storage.metadata.storageClassName string StorageClassName for the PVC. Only valid when Type=PersistentVolumeClaim.
storage.metadata.type string default: "PersistentVolumeClaim"; enum: ["PersistentVolumeClaim", "EmptyDir"] Type specifies the volume type: PersistentVolumeClaim (default) or EmptyDir. When EmptyDir, data is lost on pod restart - only use for testing.
storage.metadata.volumeAttributesClassName string min length: 1; max length: 253; pattern: "^[a-z0-9]([-a-z0-9][a-z0-9])?(\.[a-z0-9]([-a-z0-9][a-z0-9])?)*$" VolumeAttributesClassName is the name of a cluster-scoped Kubernetes VolumeAttributesClass applied to every PVC generated for this volume role. The class's driver must match the StorageClass provisioner; the operator does not check that or whether the class exists. Valid only for PersistentVolumeClaim volumes. Unlike storageClassName it may be changed while replicas are live: the operator updates bound claims in place, which asks the CSI driver to modify the volume. Requires Kubernetes 1.34+ (or 1.31-1.33 with the VolumeAttributesClass feature enabled) and a driver that supports ModifyVolume. Removing a configured value from a live volume is rejected.
storage.metadata.volumeClaimTemplateSpec object VolumeClaimTemplateSpec is retained for API compatibility but is not supported by operator-managed workloads. Admission rejects new or changed values; an unchanged legacy value is tolerated only so it can be removed. Arbitrary claim-template dataSource or volumeName settings can clone a metadata node_key or bind multiple Garage identities to one disk. Use the explicit PVC fields above, or pre-provision a PVC and reference it from an ordinary GarageNode storage existingClaim. Deprecated: use explicit PVC fields or GarageNode existingClaim.
storage.metadata.volumeClaimTemplateSpec.accessModes array of string accessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1
storage.metadata.volumeClaimTemplateSpec.dataSource object dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource.
storage.metadata.volumeClaimTemplateSpec.dataSource.apiGroup string APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.
storage.metadata.volumeClaimTemplateSpec.dataSource.kind string required Kind is the type of resource being referenced
storage.metadata.volumeClaimTemplateSpec.dataSource.name string required Name is the name of resource being referenced
storage.metadata.volumeClaimTemplateSpec.dataSourceRef object dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn't specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn't set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While dataSource ignores disallowed values (dropping them), dataSourceRef preserves all values, and generates an error if a disallowed value is specified. * While dataSource only allows local objects, dataSourceRef allows objects in any namespaces. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
storage.metadata.volumeClaimTemplateSpec.dataSourceRef.apiGroup string APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.
storage.metadata.volumeClaimTemplateSpec.dataSourceRef.kind string required Kind is the type of resource being referenced
storage.metadata.volumeClaimTemplateSpec.dataSourceRef.name string required Name is the name of resource being referenced
storage.metadata.volumeClaimTemplateSpec.dataSourceRef.namespace string Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
storage.metadata.volumeClaimTemplateSpec.resources object resources represents the minimum resources the volume should have. Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources
storage.metadata.volumeClaimTemplateSpec.resources.limits map of integer or string Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
storage.metadata.volumeClaimTemplateSpec.resources.requests map of integer or string Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
storage.metadata.volumeClaimTemplateSpec.selector object selector is a label query over volumes to consider for binding.
storage.metadata.volumeClaimTemplateSpec.selector.matchExpressions array of object matchExpressions is a list of label selector requirements. The requirements are ANDed.
storage.metadata.volumeClaimTemplateSpec.selector.matchExpressions[].key string required key is the label key that the selector applies to.
storage.metadata.volumeClaimTemplateSpec.selector.matchExpressions[].operator string required operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
storage.metadata.volumeClaimTemplateSpec.selector.matchExpressions[].values array of string values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
storage.metadata.volumeClaimTemplateSpec.selector.matchLabels map of string matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
storage.metadata.volumeClaimTemplateSpec.storageClassName string storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1
storage.metadata.volumeClaimTemplateSpec.volumeAttributesClassName string volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, it can be changed after the claim is created. An empty string or nil value indicates that no VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/
storage.metadata.volumeClaimTemplateSpec.volumeMode string volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec.
storage.metadata.volumeClaimTemplateSpec.volumeName string volumeName is the binding reference to the PersistentVolume backing this claim.
storage.metadataAutoSnapshotInterval string pattern: "^(\d+(\.\d+)?\s*(ns|us|ms|s|m|h|d|w|M|y)\s*)+$" MetadataAutoSnapshotInterval enables automatic metadata snapshots. Uses Garage duration format: "6h", "1d", "1w", etc.
storage.metadataFsync boolean MetadataFsync enables fsync on metadata writes for this node.
storage.metadataSnapshotsDir string MetadataSnapshotsDir specifies directory for metadata snapshots
storage.pvcRetentionPolicy object PVCRetentionPolicy controls whether PVCs are deleted when the StatefulSet is deleted or scaled down. Requires Kubernetes 1.23+. If not specified, defaults to Retain for both policies.
storage.pvcRetentionPolicy.whenDeleted string default: "Retain"; enum: ["Retain", "Delete"] WhenDeleted specifies what happens to PVCs when the StatefulSet is deleted. - "Retain" (default): PVCs are kept for manual cleanup or data recovery - "Delete": PVCs are automatically deleted with the StatefulSet
storage.pvcRetentionPolicy.whenScaled string default: "Retain"; enum: ["Retain", "Delete"] WhenScaled specifies what happens to PVCs when the StatefulSet is scaled down. - "Retain" (default): PVCs are kept when scaling down (allows scale back up) - "Delete": PVCs for removed replicas are deleted
storage.rpcPublicAddr string RPCPublicAddr is the externally-routable rpc_public_addr advertised by storage pods. Supports an {ordinal} placeholder for per-pod addresses. Round-trips losslessly with v1beta2 spec.storage.rpcPublicAddr.
tolerations array of object Tolerations for pod scheduling
tolerations[].effect string Effect indicates the taint effect to match. Empty means match all taint effects. When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute.
tolerations[].key string Key is the taint key that the toleration applies to. Empty means match all taint keys. If the key is empty, operator must be Exists; this combination means to match all values and all keys.
tolerations[].operator string Operator represents a key's relationship to the value. Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators).
tolerations[].tolerationSeconds integer format: "int64" TolerationSeconds represents the period of time the toleration (which must be of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, it is not set, which means tolerate the taint forever (do not evict). Zero and negative values will be treated as 0 (evict immediately) by the system.
tolerations[].value string Value is the taint value the toleration matches to. If the operator is Exists, the value should be empty, otherwise just a regular string.
topologySpreadConstraints array of object TopologySpreadConstraints for pod scheduling
topologySpreadConstraints[].labelSelector object LabelSelector is used to find matching pods. Pods that match this label selector are counted to determine the number of pods in their corresponding topology domain.
topologySpreadConstraints[].labelSelector.matchExpressions array of object matchExpressions is a list of label selector requirements. The requirements are ANDed.
topologySpreadConstraints[].labelSelector.matchExpressions[].key string required key is the label key that the selector applies to.
topologySpreadConstraints[].labelSelector.matchExpressions[].operator string required operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.
topologySpreadConstraints[].labelSelector.matchExpressions[].values array of string values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.
topologySpreadConstraints[].labelSelector.matchLabels map of string matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed.
topologySpreadConstraints[].matchLabelKeys array of string MatchLabelKeys is a set of pod label keys to select the pods over which spreading will be calculated. The keys are used to lookup values from the incoming pod labels, those key-value labels are ANDed with labelSelector to select the group of existing pods over which spreading will be calculated for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. MatchLabelKeys cannot be set when LabelSelector isn't set. Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector. This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default).
topologySpreadConstraints[].maxSkew integer required; format: "int32" MaxSkew describes the degree to which pods may be unevenly distributed. When whenUnsatisfiable=DoNotSchedule, it is the maximum permitted difference between the number of matching pods in the target topology and the global minimum. The global minimum is the minimum number of matching pods in an eligible domain or zero if the number of eligible domains is less than MinDomains. For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same labelSelector spread as 2/2/1: In this case, the global minimum is 1. | zone1 | zone2 | zone3 | | P P | P P | P | - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) violate MaxSkew(1). - if MaxSkew is 2, incoming pod can be scheduled onto any zone. When whenUnsatisfiable=ScheduleAnyway, it is used to give higher precedence to topologies that satisfy it. It's a required field. Default value is 1 and 0 is not allowed.
topologySpreadConstraints[].minDomains integer format: "int32" MinDomains indicates a minimum number of eligible domains. When the number of eligible domains with matching topology keys is less than minDomains, Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. And when the number of eligible domains with matching topology keys equals or greater than minDomains, this value has no effect on scheduling. As a result, when the number of eligible domains is less than minDomains, scheduler won't schedule more than maxSkew Pods to those domains. If value is nil, the constraint behaves as if MinDomains is equal to 1. Valid values are integers greater than 0. When value is not nil, WhenUnsatisfiable must be DoNotSchedule. For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same labelSelector spread as 2/2/2: | zone1 | zone2 | zone3 | | P P | P P | P P | The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. In this situation, new pod with the same labelSelector cannot be scheduled, because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, it will violate MaxSkew.
topologySpreadConstraints[].nodeAffinityPolicy string NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy.
topologySpreadConstraints[].nodeTaintsPolicy string NodeTaintsPolicy indicates how we will treat node taints when calculating pod topology spread skew. Options are: - Honor: nodes without taints, along with tainted nodes for which the incoming pod has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy.
topologySpreadConstraints[].topologyKey string required TopologyKey is the key of node labels. Nodes that have a label with this key and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. We define a domain as a particular instance of a topology. Also, we define an eligible domain as a domain whose nodes meet the requirements of nodeAffinityPolicy and nodeTaintsPolicy. e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. It's a required field.
topologySpreadConstraints[].whenUnsatisfiable string required WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. - ScheduleAnyway tells the scheduler to schedule the pod in any location, but giving higher precedence to topologies that would help reduce the skew. A constraint is considered "Unsatisfiable" for an incoming pod if and only if every possible node assignment for that pod would violate "MaxSkew" on some topology. For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same labelSelector spread as 3/1/1: | zone1 | zone2 | zone3 | | P P P | P | P | If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler won't make it more imbalanced. It's a required field.
webApi object WebAPI configures the static website hosting endpoint. Enabled by default with rootDomain "...svc". Set webApi.enabled: false to turn off.
webApi.addHostToMetrics boolean AddHostToMetrics adds the domain name to metrics labels for per-domain tracking.
webApi.bindAddress string BindAddress is a custom wildcard TCP bind address for the Web API. If set, this overrides BindPort.
webApi.bindPort integer default: 3902; format: "int32"; min: 1; max: 65535 BindPort is the port to bind for web serving
webApi.enabled boolean Enabled controls whether the web endpoint is active. Defaults to true. Set to false to disable.
webApi.rootDomain string RootDomain is the root domain suffix for bucket website access. Bucket websites are accessible via .. Defaults to "...svc" if not specified. Examples: - ".web.garage.tld" -> Access bucket "site" website at "site.web.garage.tld" - ".sites.example.com" -> Access bucket "blog" at "blog.sites.example.com" Note: Include the leading dot.
webApi.scheme string default: "http"; enum: ["http", "https"] Scheme is the URL scheme used when publishing bucket website URLs. Set to https when TLS is terminated in front of the Garage Web API. Defaults to http.
workers object Workers configures Garage background worker behavior. Settings are applied to all nodes on every reconcile via the Admin API. Unset fields leave the corresponding worker variable at its Garage default.
workers.resyncTranquility integer format: "int32"; min: 0 ResyncTranquility controls how aggressively the block resync worker runs. Higher values add more pauses between block resyncs. Maps to the "resync-tranquility" worker variable.
workers.resyncWorkerCount integer format: "int32"; min: 1; max: 8 ResyncWorkerCount sets the number of parallel block resync worker goroutines. Higher values increase resync throughput at the cost of disk I/O. Maps to the "resync-worker-count" worker variable.
workers.scrubTranquility integer format: "int32"; min: 0 ScrubTranquility controls how aggressively the block integrity scrub runs. Higher values add more pauses between block checks, reducing disk I/O at the cost of longer scrub duration. Maps to the "scrub-tranquility" worker variable.
zone string Zone is the static Garage layout zone used by members of this cluster and the fallback for storage members whose ZoneFrom label cannot be resolved. Garage distributes object replicas across actual layout zones for fault tolerance. When ZoneFrom is configured, one workload-owning cluster may contain roles in multiple zones. Single-zone deployments may omit this (Garage uses a default zone). Examples: "us-east-1", "rack-a", "dc1", "zone-a"
zoneFrom object ZoneFrom derives each storage node's layout zone from a label on the Kubernetes Node its pod is scheduled to, instead of using the single cluster-wide Zone above. Zone remains the fallback.
zoneFrom.nodeLabel string required; min length: 1; max length: 316 NodeLabel is the label key on the Kubernetes Node whose value becomes the Garage layout zone.

Cross-field validation

  • connectTo is required when gateway is true: !has(self.gateway) || !self.gateway || has(self.connectTo)

  • connectTo can only be specified when gateway is true: (has(self.gateway) && self.gateway) || !has(self.connectTo)

  • layoutManagement.siteRole: Follower requires at least one remoteClusters entry (a Follower with nothing to follow is a cluster nobody can assign roles to): !has(self.layoutManagement) || !has(self.layoutManagement.siteRole) || self.layoutManagement.siteRole != 'Follower' || (has(self.remoteClusters) && size(self.remoteClusters) > 0)

  • layoutManagement.siteRole: Follower is not supported with connectTo; edge gateways and management handles act on their layout owner: !has(self.layoutManagement) || !has(self.layoutManagement.siteRole) || self.layoutManagement.siteRole != 'Follower' || !has(self.connectTo)

  • initContainers and extraContainers names must be unique across both lists: !has(self.initContainers) || !has(self.extraContainers) || !self.initContainers.exists(i, self.extraContainers.exists(e, e.name == i.name))

Status

GarageClusterStatus defines the observed state of GarageCluster

Field path Type Constraints Description
activeRepairs array of object ActiveRepairs contains currently running repair operations Deprecated: never populated by the operator. It will be removed in the next API version.
activeRepairs[].nodeId string NodeID is the node running this repair
activeRepairs[].progress string Progress is a human-readable progress description
activeRepairs[].startedAt string format: "date-time" StartedAt is when the repair started
activeRepairs[].type string Type is the repair operation type (Tables, Blocks, Scrub, Rebalance, etc.)
autoModePvcHandoffs array of object AutoModePVCHandoffs mirrors the hub version's controller-owned retained PVC identity handoffs so conversion cannot erase an in-flight replacement.
autoModePvcHandoffs[].previousGarageNodeUid string required
autoModePvcHandoffs[].pvcName string required
autoModePvcHandoffs[].pvcUid string required
autoModePvcHandoffs[].replacementGarageNodeUid string
autoModePvcHandoffs[].replacementReservationHash string
autoModePvcHandoffs[].slotName string required
blockErrorDetails object BlockErrorDetails provides detailed information about block errors
blockErrorDetails.count integer format: "int32" Count is the total number of blocks with errors
blockErrorDetails.lastErrorAt string format: "date-time" LastErrorAt is when the most recent block error occurred
blockErrorDetails.topErrors array of object TopErrors contains details about the most problematic blocks Limited to top 10 blocks by error count
blockErrorDetails.topErrors[].blockHash string BlockHash is the hash of the affected block
blockErrorDetails.topErrors[].errorCount integer format: "int32" ErrorCount is the number of times this block failed to sync
blockErrorDetails.topErrors[].lastAttempt string format: "date-time" LastAttempt is when the last sync attempt occurred
blockErrorDetails.topErrors[].lastError string LastError is the most recent error message for this block
blockErrorDetails.topErrors[].nextRetry string format: "date-time" NextRetry is when the next sync retry is scheduled
blockErrors integer format: "int32" BlockErrors is the count of blocks with sync errors across all nodes. Absent means not observed (Admin API unreachable, or a node that can hold blocks did not answer; silent capacityless gateways are ignored). 0 means observed with no errors.
buildInfo object BuildInfo contains Garage build information
buildInfo.features array of string Features lists enabled Cargo features
buildInfo.rustVersion string RustVersion is the Rust compiler version used to build Garage
buildInfo.version string Version is the Garage version string (e.g., "v1.0.1")
clusterId string ClusterID is the unique identifier of the Garage cluster
conditions array of object Conditions represent the current state of the cluster
conditions[].lastTransitionTime string required; format: "date-time" lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
conditions[].message string required; max length: 32768 message is a human readable message indicating details about the transition. This may be an empty string.
conditions[].observedGeneration integer format: "int64"; min: 0 observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
conditions[].reason string required; min length: 1; max length: 1024; pattern: "^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$" reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
conditions[].status string required; enum: ["True", "False", "Unknown"] status of the condition, one of True, False, Unknown.
conditions[].type string required; max length: 316; pattern: "^([a-z0-9]([-a-z0-9][a-z0-9])?(\.[a-z0-9]([-a-z0-9][a-z0-9])?)/)?(([A-Za-z0-9][-A-Za-z0-9_.])?[A-Za-z0-9])$" type of condition in CamelCase or in foo.example.com/CamelCase.
drainingNodes integer DrainingNodes is the count of nodes that are draining data from an older layout version. These nodes had a storage role in a previous layout and are migrating data to other nodes. A non-zero value indicates a layout transition is in progress.
endpoints object Endpoints contains service endpoints
endpoints.admin string Admin is the admin API endpoint
endpoints.k2v string K2V is the K2V API endpoint
endpoints.metrics string Metrics is the Prometheus metrics endpoint (typically Admin + /metrics)
endpoints.rpc string RPC is the internal RPC endpoint
endpoints.s3 string S3 is the S3 API endpoint
endpoints.web string Web is the web hosting endpoint
factorMigration object FactorMigration is mirrored from the storage version so v1beta1 status conversion and delete admission cannot erase or overlook an in-flight replication-factor migration.
factorMigration.completedAt string format: "date-time"
factorMigration.force boolean
factorMigration.fromFactor integer
factorMigration.message string
factorMigration.phase string enum: ["Validating", "ScalingDown", "Purging", "Verifying", "RebuildingLayout", "Converging", "Completed", "Failed"]
factorMigration.phaseStartedAt string format: "date-time"
factorMigration.purgeId string
factorMigration.startedAt string format: "date-time"
factorMigration.toFactor integer
health object Health contains cluster health information
health.available boolean Available indicates if quorum is available
health.connectedNodes integer ConnectedNodes is the number of currently connected nodes
health.healthy boolean Healthy indicates if all nodes are connected
health.knownNodes integer KnownNodes is the number of nodes seen in cluster
health.partitions integer Partitions is the total partitions in layout
health.partitionsAllOk integer PartitionsAllOK is partitions with all nodes connected
health.partitionsQuorum integer PartitionsQuorum is partitions with quorum connectivity
health.status string Status is the overall cluster status
health.storageNodes integer StorageNodes is the number of storage nodes in layout
health.storageNodesOk integer StorageNodesOK is the number of connected storage nodes
lastOperation object LastOperation records the result of the most recently triggered operational annotation (trigger-snapshot, trigger-repair, scrub-command)
lastOperation.error string Error contains the error message when Succeeded is false
lastOperation.succeeded boolean Succeeded indicates the operation completed without error
lastOperation.triggeredAt string format: "date-time" TriggeredAt is when the operation was triggered
lastOperation.type string Type is the operation type (e.g. "Snapshot", "Repair:Blocks", "Scrub:start")
layoutHistory object LayoutHistory contains layout version history
layoutHistory.currentVersion integer format: "int64" CurrentVersion is the current layout version
layoutHistory.minAck integer format: "int64" MinAck is the minimum acknowledged layout version by all nodes
layoutHistory.versions array of object max items: 64 Versions contains at most 64 current, draining, and recent historical layout versions for diagnosis. Controller safety decisions read Garage's complete live layout history instead of relying on this bounded projection.
layoutHistory.versions[].gatewayNodes integer GatewayNodes is the number of gateway nodes in this version
layoutHistory.versions[].status string Status is the version status (Current, Draining, Historical)
layoutHistory.versions[].storageNodes integer StorageNodes is the number of storage nodes in this version
layoutHistory.versions[].version integer format: "int64" Version is the layout version number
layoutPreview object LayoutPreview shows what would change if staged layout is applied
layoutPreview.dataTransferEstimate string DataTransferEstimate is a human-readable estimate of data movement (e.g., "~50 GB")
layoutPreview.nodesAdded array of string NodesAdded shows node IDs that would be added to the layout
layoutPreview.nodesModified array of string NodesModified shows node IDs with changed configuration (zone, capacity, tags)
layoutPreview.nodesRemoved array of string NodesRemoved shows node IDs that would be removed from the layout
layoutPreview.partitionTransfers integer format: "int32" PartitionTransfers is the estimated number of partition transfers
layoutPreview.zonesAffected array of string ZonesAffected shows which zones would be affected by the changes
layoutVersion integer format: "int64" LayoutVersion is the current layout version
layoutWriter object LayoutWriter reports the layout role the controller is currently enforcing for this site. Nil until the controller first records it.
layoutWriter.role string required; enum: ["Writer", "Follower"] Role is the role the controller is currently enforcing.
lifecycleStatus object LifecycleStatus contains the status of bucket lifecycle operations Deprecated: never populated by the operator. It will be removed in the next API version.
lifecycleStatus.lastCompleted string format: "date-time" LastCompleted is when the last lifecycle worker run completed (from lifecycle-last-completed worker variable)
nodes array of object Nodes contains status information for each node Deprecated: never populated by the operator. It will be removed in the next API version.
nodes[].capacity integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" Capacity is the storage capacity of the node
nodes[].connected boolean Connected indicates if the node is connected to the cluster
nodes[].dataDiskAvailable integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" DataDiskAvailable is the available space on data disk
nodes[].dataDiskTotal integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" DataDiskTotal is the total space on data disk
nodes[].gateway boolean Gateway indicates if the node is gateway-only
nodes[].metadataDiskAvailable integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" MetadataDiskAvailable is the available space on metadata disk
nodes[].metadataDiskTotal integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" MetadataDiskTotal is the total space on metadata disk
nodes[].nodeId string NodeID is the public key of the node
nodes[].podName string PodName is the name of the pod running this node
nodes[].version string Version is the Garage version running on this node
nodes[].zone string Zone is the zone assignment of the node
observedGeneration integer format: "int64" ObservedGeneration is the last observed generation
phase string enum: ["Pending", "Creating", "Running", "Ready", "Degraded", "Updating", "Deleting", "Failed", "Unknown"] Phase represents the current phase of the cluster
readyReplicas integer format: "int32" ReadyReplicas is the number of ready Garage pods
redundancy object Redundancy reports block-resync progress and the last full-redundancy proof. Absent on clusters without a storage tier, on connectTo clusters, and until the controller first observes Garage.
redundancy.coordination object Coordination is what this site last saw of other sites' repairs. It serializes proofs across a federation. Absent on a cluster that is not federated.
redundancy.coordination.lastRemoteRepairAt string format: "date-time" LastRemoteRepairAt is when a blocks repair on a remote storage node was last seen starting or running, or when this site started watching.
redundancy.coordination.lastRemoteRepairNodeId string pattern: "^[0-9a-f]{64}$" LastRemoteRepairNodeID is the remote node of that repair.
redundancy.coordination.remoteRepairWorkerIds map of integer RemoteRepairWorkerIDs maps each remote storage node ID to the highest Block repair worker ID seen on it.
redundancy.deferredNodes array of object max items: 256 DeferredNodes lists owned storage nodes the current proof skipped. Down and NotReporting nodes are retried once they are back, no sooner than retryAfter.
redundancy.deferredNodes[].nodeId string required; pattern: "^[0-9a-f]{64}$" NodeID is the full Garage node ID.
redundancy.deferredNodes[].reason string required; enum: ["Down", "NotReporting", "RepairFailed"] Reason says why the node was skipped.
redundancy.deferredNodes[].retryAfter string format: "date-time" RetryAfter is the earliest time the operator retries the node. Absent for RepairFailed, which only a new verify-redundancy value retries.
redundancy.deferredNodes[].since string required; format: "date-time" Since is when the node was skipped.
redundancy.lastProgressAt string format: "date-time" LastProgressAt is the last time remaining work decreased (a resync or table sync queue shrank, a repair scan advanced, or the proof moved to a later step). It moves forward in steps of at least one minute.
redundancy.nodes array of object max items: 256 Nodes holds per-node progress for every current storage node and every other node that reports block errors, sorted by nodeId.
redundancy.nodes[].blockErrors integer format: "int32" BlockErrors is the node's number of blocks with resync errors.
redundancy.nodes[].blockRepairProgress string max length: 64 BlockRepairProgress is Garage's progress string for the exact verification repair worker on this node while it runs.
redundancy.nodes[].metadataQueueLength integer format: "int64" MetadataQueueLength is the sum of the Merkle-updater and insert queues.
redundancy.nodes[].metadataSyncPartitions integer format: "int32" MetadataSyncPartitions is the sum over tables of partitions left in the current full-sync pass. It is 0 between passes.
redundancy.nodes[].nodeId string required; pattern: "^[0-9a-f]{64}$" NodeID is the full Garage node ID.
redundancy.nodes[].observed boolean required Observed is false when the node did not answer this pass; the counters then keep their previous values.
redundancy.nodes[].resyncIdle boolean ResyncIdle is true when every enabled resync worker is idle.
redundancy.nodes[].resyncQueueLength integer format: "int64" ResyncQueueLength is the node's block resync queue, including delayed rechecks.
redundancy.progressObservedAt string format: "date-time" ProgressObservedAt is when nodes[] was last rewritten. Progress is rewritten at most once per minute unless another redundancy field changes in the same pass, and only when a value changed.
redundancy.scope string enum: ["Cluster", "Local"] Scope is Cluster when every storage role of the layout runs at this site, and Local when other sites run some of them; the proof covers only this site's local storage nodes.
redundancy.storageNodes object StorageNodes counts the layout's storage roles for this site.
redundancy.storageNodes.local integer required; format: "int32"; min: 0 Local is the number of storage roles that run at this site.
redundancy.storageNodes.remote integer required; format: "int32"; min: 0 Remote is the number of storage roles that run at other sites.
redundancy.storageNodes.total integer required; format: "int32"; min: 0 Total is the number of storage roles across all sites.
redundancy.storageNodes.verified integer required; format: "int32"; min: 0 Verified is the number of local storage nodes the current or last proof has completed.
redundancy.verification object Verification is the proof state. Absent on a federated site without spec.layoutManagement.siteRole.
redundancy.verification.completedNodeIds array of string max items: 256 CompletedNodeIDs are the owned storage nodes that finished this proof, sorted.
redundancy.verification.currentNodeId string pattern: "^[0-9a-f]{64}$" CurrentNodeID is the owned storage node whose turn it is. Repairs run on one storage node at a time.
redundancy.verification.evidence object Evidence is the internal proof state. Its shape may change between operator releases; an unrecognized shape restarts the current node.
redundancy.verification.evidence.blockErrorsBaseline integer format: "int64" BlockErrorsBaseline is the block-error count at the start of the current 30-minute window used to detect a growing count.
redundancy.verification.evidence.blockErrorsBaselineAt string format: "date-time" BlockErrorsBaselineAt is when the current block-error window opened.
redundancy.verification.evidence.idleSince string format: "date-time" IdleSince is the first pass, after the tables launch, at which the current node's sync workers were idle and its metadata queues empty.
redundancy.verification.evidence.launches integer format: "int32"; min: 0; max: 3 Launches counts the launches of the current node's stage. After three the node is deferred as RepairFailed.
redundancy.verification.evidence.nodeStage string enum: ["Tables", "Blocks", "Pause"] NodeStage is the current node's step.
redundancy.verification.evidence.pauseUntil string format: "date-time" PauseUntil ends the pause after the current node finished.
redundancy.verification.evidence.peerDownSeen boolean PeerDownSeen is true when some storage node was down during the current node's table sync. Sync errors are then expected; the node is rechecked with a tables-only pass once every node is up.
redundancy.verification.evidence.quietSince string format: "date-time" QuietSince starts the final quiet period.
redundancy.verification.evidence.repairWorkerId integer format: "int64" RepairWorkerID is the blocks repair worker adopted on the current node.
redundancy.verification.evidence.resyncErrorBaselines map of integer ResyncErrorBaselines is the persistent-error counter of every block resync worker on the owned nodes when the quiet period started.
redundancy.verification.evidence.skipTables boolean SkipTables is true for a proof started by a layout change: Garage's settled layout history already proves a full table sync on every node.
redundancy.verification.evidence.stageLaunchedAt string format: "date-time" StageLaunchedAt is when the current node's repair was launched.
redundancy.verification.evidence.syncErrorBaselines map of integer SyncErrorBaselines is the errors counter of each of the five " sync" workers of the current node at the tables launch.
redundancy.verification.evidence.tablesRecheckNodeIds array of string max items: 256 TablesRecheckNodeIDs are completed nodes whose table sync ran while a peer was down; each gets a tables-only pass once every node is up.
redundancy.verification.evidence.workerBaseline integer format: "int64" WorkerBaseline is the current node's highest worker ID at the launch. A lower maximum later means Garage restarted.
redundancy.verification.layoutVersion integer format: "int64"; min: 0 LayoutVersion is the Garage layout version last observed.
redundancy.verification.phase string required; enum: ["Idle", "Pending", "SyncingMetadata", "ScanningBlocks", "Settling", "Partial", "Verified"] Phase is the proof step.
redundancy.verification.phaseStartedAt string format: "date-time" PhaseStartedAt is when Phase was entered.
redundancy.verification.requestToken string max length: 253 RequestToken is the last handled value of the garage.rajsingh.info/verify-redundancy annotation.
redundancy.verification.startedAt string format: "date-time" StartedAt is when the current proof attempt began.
redundancy.verification.topologyHash string max length: 64 TopologyHash fingerprints the ID, zone and capacity of every storage role in the current layout. A change after the baseline starts a proof; tag-only layout changes and Pod restarts do not change it.
redundancy.verification.trigger string enum: ["Requested", "LayoutChanged", "NodeChanged"] Trigger is what started the current proof. Absent while Idle.
redundancy.verification.verifiedAt string format: "date-time" VerifiedAt is when the last proof completed. It survives later proofs and outages, so it records the last time full redundancy was proven.
remoteClusters array of object RemoteClusters contains status of remote clusters in the federation
remoteClusters[].connected boolean Connected indicates if we can reach this cluster
remoteClusters[].healthyNodes integer HealthyNodes is the number of healthy nodes
remoteClusters[].lastSeen string format: "date-time" LastSeen is when we last successfully connected
remoteClusters[].name string Name is the cluster name
remoteClusters[].nodes integer Nodes is the number of nodes in this cluster
remoteClusters[].zone string Zone is the cluster's zone
replicas integer required; format: "int32" Replicas is the total number of Garage pods targeted by this cluster
resyncQueueLength integer format: "int64" ResyncQueueLength is the total block resync queue depth across all nodes. Absent means not observed (Admin API unreachable, or a node that can hold blocks did not answer; silent capacityless gateways are ignored). 0 means observed and drained.
scaleReplicas integer format: "int32" ScaleReplicas is the actual number of non-terminating Pods selected by ScaleSelector. For a storage view this includes only the default StatefulSet/PVC group and excludes node-local pools and gateways. For a v1beta1 edge-gateway view it includes the gateway Pods.
scaleSelector string ScaleSelector is the serialized exact Pod selector paired with ScaleReplicas by the scale subresource. It is deliberately narrower than Selector so hidden v1beta2 node-local pools or unified gateways do not contaminate v1beta1 scale status.
scrubStatus object ScrubStatus contains the status of data scrub operations Deprecated: never populated by the operator. It will be removed in the next API version.
scrubStatus.corruptedBlocks integer format: "int32" CorruptedBlocks is the number of corrupted blocks found in the last scrub (from scrub-corruptions_detected worker variable)
scrubStatus.lastCompleted string format: "date-time" LastCompleted is when the last scrub completed (from scrub-last-completed worker variable)
scrubStatus.nextRun string format: "date-time" NextRun is when the next scrub is scheduled to run (from scrub-next-run worker variable)
scrubStatus.nodeStatuses array of object NodeStatuses contains per-node scrub status
scrubStatus.nodeStatuses[].errorsFound integer format: "int32" ErrorsFound is the number of errors found on this node
scrubStatus.nodeStatuses[].itemsChecked integer format: "int64" ItemsChecked is the number of items checked
scrubStatus.nodeStatuses[].nodeId string NodeID is the node identifier
scrubStatus.nodeStatuses[].progress integer Progress percentage (0-100)
scrubStatus.nodeStatuses[].running boolean Running indicates if scrub is running on this node
scrubStatus.paused boolean Paused indicates if the scrub is paused
scrubStatus.progress string Progress is a human-readable progress description (e.g., "45% complete")
scrubStatus.running boolean Running indicates if a scrub is currently running on any node
scrubStatus.tranquilityLevel integer TranquilityLevel is the current tranquility setting (higher = less aggressive)
selector string required Selector is the serialized label selector for pods managed by this cluster. This is the aggregate cluster selector and is not used by the scale subresource.
stagedLayoutVersion integer format: "int64" StagedLayoutVersion is the staged layout version pending application
stagedRoles integer format: "int32" StagedRoles is the number of roles in the staged layout
storageDrain object StorageDrain records the single cluster-wide positive-capacity removal and block-migration proof.
storageDrain.actor object required StorageDrainActorStatus identifies the exact object authorized to advance a cluster-wide storage-drain transaction.
storageDrain.actor.apiVersion string required
storageDrain.actor.kind string required; enum: ["GarageCluster", "GarageNode"]
storageDrain.actor.name string required
storageDrain.actor.namespace string required
storageDrain.actor.uid string required
storageDrain.completedAt string format: "date-time"
storageDrain.errorCount integer required; format: "int64"
storageDrain.layoutVersion integer required; format: "int64"
storageDrain.managedPodUids map of string
storageDrain.queueLength integer required; format: "int64"
storageDrain.quietSince string format: "date-time"
storageDrain.removedStorageNodeIds array of string required
storageDrain.repairBaselines map of integer
storageDrain.repairWorkerIds map of integer
storageDrain.requiresEmptyQueue boolean required
storageDrain.resyncErrorBaselines map of integer
storageDrain.roleRemovalNodeIds array of string required
storageDrain.startedAt string required; format: "date-time"
storageDrain.targetHash string required
storageDrain.transactionId string required
storageDrain.unavailableSourceNodeIds array of string
storageDrain.verificationNodeIds array of string
storageRollout object StorageRollout is controller-owned durable state for the single managed pod handoff currently in progress.
storageRollout.clusterGeneration integer format: "int64"
storageRollout.desiredConfigHash string required
storageRollout.desiredPodSpecHash string required
storageRollout.garageNodeGeneration integer format: "int64"
storageRollout.garageNodeId string required
storageRollout.garageNodeName string
storageRollout.garageNodeUid string required
storageRollout.kubernetesNodeName string
storageRollout.kubernetesNodeUid string
storageRollout.nodeLocalPoolName string
storageRollout.persistentVolumeClaims array of object
storageRollout.persistentVolumeClaims[].name string required
storageRollout.persistentVolumeClaims[].uid string required
storageRollout.previousPodUid string required
storageRollout.recoveryPodName string
storageRollout.recoveryPodUid string
storageRollout.recoveryRequest string
storageRollout.retiredWorkloadUids array of string max items: 32 Recovery fails closed before a 33rd retired controller incarnation so the exact old-Pod exclusion set remains bounded in the conversion transport.
storageRollout.statefulSetWorkloadRecreationSafe boolean
storageRollout.workloadFenced boolean
storageRollout.workloadUid string required
storageStats object StorageStats contains cluster-wide storage statistics
storageStats.availableCapacity integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" AvailableCapacity is the available storage across all nodes
storageStats.healthyPartitions integer format: "int32" HealthyPartitions is the number of partitions with full redundancy
storageStats.totalCapacity integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" TotalCapacity is the total storage capacity across all nodes
storageStats.totalPartitions integer format: "int32" TotalPartitions is the total number of partitions in the layout
storageStats.usedCapacity integer or string pattern: "^(\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9])?)|(\.[0-9]+))))?$" UsedCapacity is the used storage across all nodes
totalNodes integer TotalNodes is the total nodes across all clusters (local + remote) Deprecated: never populated by the operator. It will be removed in the next API version.
workerCount integer format: "int32" WorkerCount is the total number of background workers Deprecated: never populated by the operator. It will be removed in the next API version.
workers object Workers contains detailed information about background workers Deprecated: never populated by the operator. It will be removed in the next API version.
workers.busy integer format: "int32" Busy is the number of busy/active workers
workers.errored integer format: "int32" Errored is the number of workers with errors
workers.errors array of object Errors contains details about worker errors
workers.errors[].consecutiveErrors integer format: "int32" ConsecutiveErrors is the count of consecutive errors
workers.errors[].lastError string LastError is the last error message
workers.errors[].lastErrorSecsAgo integer format: "int64" LastErrorSecsAgo is seconds since the last error
workers.errors[].name string Name is the worker name
workers.errors[].workerId integer format: "int64" WorkerID is the worker identifier
workers.idle integer format: "int32" Idle is the number of idle workers
workers.total integer format: "int32" Total is the total number of background workers
workers.variables map of string Variables contains runtime worker configuration variables These can be adjusted through the Admin API to tune background worker behavior
workersFailed integer format: "int32" WorkersFailed is the number of failed workers Deprecated: never populated by the operator. It will be removed in the next API version.