diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index 914440f580..edae909760 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -14663,6 +14663,23 @@ spec: - Local maxLength: 10 type: string + ipFamilies: + items: + description: |- + IPFamily represents the IP Family (IPv4 or IPv6). This type is used + to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies). + enum: + - IPv4 + - IPv6 + type: string + type: array + ipFamilyPolicy: + description: 'More info: https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/' + enum: + - SingleStack + - PreferDualStack + - RequireDualStack + type: string metadata: description: Metadata contains metadata for custom resources properties: @@ -15005,6 +15022,23 @@ spec: - Local maxLength: 10 type: string + ipFamilies: + items: + description: |- + IPFamily represents the IP Family (IPv4 or IPv6). This type is used + to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies). + enum: + - IPv4 + - IPv6 + type: string + type: array + ipFamilyPolicy: + description: 'More info: https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/' + enum: + - SingleStack + - PreferDualStack + - RequireDualStack + type: string metadata: description: Metadata contains metadata for custom resources properties: @@ -15053,6 +15087,23 @@ spec: - Local maxLength: 10 type: string + ipFamilies: + items: + description: |- + IPFamily represents the IP Family (IPv4 or IPv6). This type is used + to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies). + enum: + - IPv4 + - IPv6 + type: string + type: array + ipFamilyPolicy: + description: 'More info: https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/' + enum: + - SingleStack + - PreferDualStack + - RequireDualStack + type: string metadata: description: Metadata contains metadata for custom resources properties: @@ -16749,6 +16800,23 @@ spec: - Local maxLength: 10 type: string + ipFamilies: + items: + description: |- + IPFamily represents the IP Family (IPv4 or IPv6). This type is used + to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies). + enum: + - IPv4 + - IPv6 + type: string + type: array + ipFamilyPolicy: + description: 'More info: https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/' + enum: + - SingleStack + - PreferDualStack + - RequireDualStack + type: string metadata: description: Metadata contains metadata for custom resources properties: diff --git a/internal/controller/postgrescluster/cluster.go b/internal/controller/postgrescluster/cluster.go index 7e863fdadf..67544d621b 100644 --- a/internal/controller/postgrescluster/cluster.go +++ b/internal/controller/postgrescluster/cluster.go @@ -267,6 +267,15 @@ func (r *Reconciler) generateClusterReplicaService( } service.Spec.ExternalTrafficPolicy = initialize.FromPointer(spec.ExternalTrafficPolicy) service.Spec.InternalTrafficPolicy = spec.InternalTrafficPolicy + + // Set IPFamilyPolicy and IPFamilies + if spec.IPFamilyPolicy != nil { + service.Spec.IPFamilyPolicy = spec.IPFamilyPolicy + } + if len(spec.IPFamilies) > 0 { + service.Spec.IPFamilies = spec.IPFamilies + } + } service.Spec.Ports = []corev1.ServicePort{servicePort} diff --git a/internal/controller/postgrescluster/patroni.go b/internal/controller/postgrescluster/patroni.go index 293690a77b..995de75b61 100644 --- a/internal/controller/postgrescluster/patroni.go +++ b/internal/controller/postgrescluster/patroni.go @@ -271,6 +271,14 @@ func (r *Reconciler) generatePatroniLeaderLeaseService( } service.Spec.ExternalTrafficPolicy = initialize.FromPointer(spec.ExternalTrafficPolicy) service.Spec.InternalTrafficPolicy = spec.InternalTrafficPolicy + + // Set IPFamilyPolicy and IPFamilies + if spec.IPFamilyPolicy != nil { + service.Spec.IPFamilyPolicy = spec.IPFamilyPolicy + } + if len(spec.IPFamilies) > 0 { + service.Spec.IPFamilies = spec.IPFamilies + } } service.Spec.Ports = []corev1.ServicePort{servicePort} diff --git a/internal/controller/postgrescluster/pgadmin.go b/internal/controller/postgrescluster/pgadmin.go index f102405b47..40874aa1be 100644 --- a/internal/controller/postgrescluster/pgadmin.go +++ b/internal/controller/postgrescluster/pgadmin.go @@ -183,6 +183,14 @@ func (r *Reconciler) generatePGAdminService( } service.Spec.ExternalTrafficPolicy = initialize.FromPointer(spec.ExternalTrafficPolicy) service.Spec.InternalTrafficPolicy = spec.InternalTrafficPolicy + + // Set IPFamilyPolicy and IPFamilies + if spec.IPFamilyPolicy != nil { + service.Spec.IPFamilyPolicy = spec.IPFamilyPolicy + } + if len(spec.IPFamilies) > 0 { + service.Spec.IPFamilies = spec.IPFamilies + } } service.Spec.Ports = []corev1.ServicePort{servicePort} diff --git a/internal/controller/postgrescluster/pgbouncer.go b/internal/controller/postgrescluster/pgbouncer.go index eb71c189f6..1b9bb837f3 100644 --- a/internal/controller/postgrescluster/pgbouncer.go +++ b/internal/controller/postgrescluster/pgbouncer.go @@ -306,6 +306,14 @@ func (r *Reconciler) generatePGBouncerService( } service.Spec.ExternalTrafficPolicy = initialize.FromPointer(spec.ExternalTrafficPolicy) service.Spec.InternalTrafficPolicy = spec.InternalTrafficPolicy + + // Set IPFamilyPolicy and IPFamilies + if spec.IPFamilyPolicy != nil { + service.Spec.IPFamilyPolicy = spec.IPFamilyPolicy + } + if len(spec.IPFamilies) > 0 { + service.Spec.IPFamilies = spec.IPFamilies + } } service.Spec.Ports = []corev1.ServicePort{servicePort} diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go index 6de2b35336..79de9ae5f3 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go @@ -20,6 +20,7 @@ type SchemalessObject map[string]any // DeepCopy creates a new SchemalessObject by copying the receiver. func (in SchemalessObject) DeepCopy() SchemalessObject { return runtime.DeepCopyJSON(in) + } type ServiceSpec struct { @@ -44,6 +45,16 @@ type ServiceSpec struct { // +kubebuilder:validation:Enum={ClusterIP,NodePort,LoadBalancer} Type string `json:"type"` + // More info: https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/ + // --- + // +optional + // +kubebuilder:validation:Enum=SingleStack;PreferDualStack;RequireDualStack + IPFamilyPolicy *corev1.IPFamilyPolicy `json:"ipFamilyPolicy,omitempty"` + + // +optional + // +kubebuilder:validation:items:Enum={IPv4,IPv6} + IPFamilies []corev1.IPFamily `json:"ipFamilies,omitempty"` + // More info: https://kubernetes.io/docs/concepts/services-networking/service/#traffic-policies // --- // Kubernetes assumes the evaluation cost of an enum value is very large. diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go index 5eb63bd867..a9c87a7abd 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go @@ -2213,6 +2213,16 @@ func (in *ServiceSpec) DeepCopyInto(out *ServiceSpec) { *out = new(int32) **out = **in } + if in.IPFamilyPolicy != nil { + in, out := &in.IPFamilyPolicy, &out.IPFamilyPolicy + *out = new(corev1.IPFamilyPolicy) + **out = **in + } + if in.IPFamilies != nil { + in, out := &in.IPFamilies, &out.IPFamilies + *out = make([]corev1.IPFamily, len(*in)) + copy(*out, *in) + } if in.InternalTrafficPolicy != nil { in, out := &in.InternalTrafficPolicy, &out.InternalTrafficPolicy *out = new(corev1.ServiceInternalTrafficPolicy)