zalando / zalando/postgres-operator

Leader-Service gets not properly resolved in DualStack Cluster

Open
#1,562 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
5.2k
Forks
1.1k
Avg merge
2d 16h
Merged PRs (30d)
3

Description

This issue is a bit meddled between the assignment of pod ips from the CNI and the assignment of ClusterIPs within the service.

It all starts within the pods, which get a primary IPv4 address and an additional IPv6 address. However, status.podIp and in the postgres.yml the connect_address are set to the v4 address.

However, the service is automatically assigned an IPv6 address and created as SingleStack IPv6. As a consequence the service becomes this monstrosity:

$ kubectl describe service -n reqbaz reqbaz-postgres
Name:              reqbaz-postgres
Namespace:         reqbaz
Labels:            application=spilo
                   database.selfnet.de/cluster=reqbaz-postgres
                   spilo-role=master
                   team=reqbaz
Annotations:       <none>
Selector:          <none>
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv6
IP:                2001:7c7:2100:406::9395
IPs:               2001:7c7:2100:406::9395
Port:              postgresql  5432/TCP
TargetPort:        5432/TCP
Endpoints:         100.126.17.49:5432
Session Affinity:  None
Events:            <none>

This unfortunately causes every connection attempt (from services as well as the operator to end up in a refused connection.

time="2021-07-16T16:53:32Z" level=warning msg="could not connect to Postgres database: dial tcp [2001:7c7:2100:406::9395]:5432: connect: connection refused" cluster-name=reqbaz/reqbaz-postgres pkg=cluster worker=3

I have tried to fiddle with the respective code, but haven't figured out yet how the created endpoint gets associated with the service.
Otherwise I'd have attempted to just botch in an ip version detection on the endpoint and set the ServiceClass and IPFamly accordingly. The creation of the service and the endpoint however seem to be too disentangled to do so. Also I'm not sure how this would affect clusters without the feature gate.

Another possibility might be to provide a config option to define the IPFamilyPolicy, and the default family. But this takes a strong assumption on the cluster behaving deterministically and might have even weirder side effects.

Cluster Info

  • Which image of the operator are you using? registry.opensource.zalan.do/acid/postgres-operator:v1.6.3
  • Where do you run it - cloud or metal? Kubernetes or OpenShift? Self-homed VMs
  • Are you running Postgres Operator in production? yes
  • Type of issue? Bug report

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with postgres.yml and trace the paths that set status.podIp and connect_address, then follow how the operator creates the Service and its Endpoint. Reproduce the dual-stack output with kubectl describe service and the recorded connection error. Done means the service family and endpoint address are compatible, and operator and service connections reach PostgreSQL.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, kubernetes, postgresql
Domain
databases, infrastructure, networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.