Home > Net >  Can't connect spring boot to postgres k8s statefulset
Can't connect spring boot to postgres k8s statefulset

Time:10-26

I am new to Kubernetes and I am deploying an application for the first time on Kubernetes. I want to deploy a postgreSQL statefulset and a simple replicaset of spring boot pods. I created a headless service that will be attached to the following statefulset.

    # Headless Service
apiVersion: v1
kind: Service
metadata:
  name: ecom-db-h
spec:
  ports:
  - targetPort: 5432
    port: 80
  clusterIP: None
  selector:
    app: ecom-db
---
# PostgreSQL StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: ecomdb-statefulset
  labels:
    app: ecom-db
spec:
  serviceName: ecom-db-h
  selector:
    matchLabels:
      app: postgresql-db
  replicas: 2
  template:
    # Pod Definition
    metadata:
      labels:
        app: postgresql-db
    spec:
      containers:
        - name: db
          image: postgres:13
          ports:
            - name: postgres
              containerPort: 5432
         # volumeMounts:
          #  - name: ecom-db
           #   mountPath: /var/lib/postgresql/data
          env:
            - name: POSTGRES_DB
              value: ecommerce
            - name: POSTGRES_USER
              value: postgres
            - name: POSTGRES_PASSWORD
              value: <password>
      #volumes:
       # - name: ecom-db
        #  persistentVolumeClaim:
         #   claimName: ecom-pvc

And here is the replicaset I created for the spring boot application pods :

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: ecom-server
  labels:
    app: ecom-server
    tier: backend
spec:
  # modify replicas according to your case
  replicas: 2
  selector:
    matchLabels:
      type: backend
  template:
    # Pod definition
    metadata:
      labels:
        app: ecom-server
        type: backend
    spec:
      containers:
      - name: ecommerce-server
        image: <my.private.repo.url>/spring-server:kubernetes-test
        imagePullPolicy: Always
      imagePullSecrets:
          - name: regcred

I am using the default namespace and here is the application.properties:

spring.datasource.url=jdbc:postgresql://ecom-db-h.default.svc.cluster.local/ecommerce?useSSL=false
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.username=postgres
spring.datasource.password=<password>
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.format_sql=true
spring.jpa.hibernate.id.new_generator_mappings=true
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL95Dialect

But my spring boot containers always exit with the following error :

Caused by: java.net.UnknownHostException: ecom-db-h.default.svc.cluster.local
        at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184)
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
        at java.net.Socket.connect(Socket.java:589)
        at org.postgresql.core.PGStream.createSocket(PGStream.java:231)
        at org.postgresql.core.PGStream.<init>(PGStream.java:95)
        at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:98)
        at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:213)
        ... 136 common frames omitted
  

This means that either the replicaset is not able to find the headless service, or my headless service is not connected to the statefulset pods at all. Did I miss something in the YAML files ? Or am I using the headless service in the wrong way ?


Update:

Thanks to @Thomas and @harsh-manvar I understood that the headless service is not meant to connect to the databases. Instead, I should use a normal ClusterIP service. The problem is I did that and I am still getting the same error. Here is my new YAML files :

application.properties modification:

spring.datasource.url=jdbc:postgresql://db-svc.default.svc.cluster.local/ecommerce?useSSL=false

statefulset.yaml modified

# ClusterIP service instead of the headless service
apiVersion: v1
kind: Service
metadata:
  name: db-svc
spec:
  ports:
  - name: pgql
    port: 80
    targetPort: 5432
    protocol: TCP
  selector:
    app: db
---
# PostgreSQL StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: db-sts
  labels:
    app: db-sts
spec:
  serviceName: db-svc
  selector:
    matchLabels:
      app: db
  replicas: 2
  template:
    # Pod Definition
    metadata:
      labels:
        app: db
    spec:
      containers:
        - name: db
          image: postgres:13
          ports:
            - name: postgres
              containerPort: 5432
         # volumeMounts:
          #  - name: ecom-db
           #   mountPath: /var/lib/postgresql/data
          env:
            - name: POSTGRES_DB
              value: ecommerce
            - name: POSTGRES_USER
              value: postgres
            - name: POSTGRES_PASSWORD
              value: mss#123
      #volumes:
       # - name: ecom-db
        #  persistentVolumeClaim:
         #   claimName: ecom-pvc

Here is the new error :

Caused by: java.net.UnknownHostException: db-svc.default.svc.cluster.local
        at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184)
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
        at java.net.Socket.connect(Socket.java:589)
        at org.postgresql.core.PGStream.createSocket(PGStream.java:231)
        at org.postgresql.core.PGStream.<init>(PGStream.java:95)
        at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:98)
        at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:213)
        ... 136 common frames omitted

My statefulset pods are running smoothly and the service is created :

NAME                      READY   AGE
statefulset.apps/db-sts   2/2     26m

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/db-svc       ClusterIP   10.108.39.189   <none>        5432/TCP   26m
service/kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP    30m

NAME                READY   STATUS             RESTARTS        AGE
db-sts-0            1/1     Running            0               26m
db-sts-1            1/1     Running            0               26m
ecom-server-5jbs2   0/1     CrashLoopBackOff   9 (44s ago)     25m
ecom-server-rtpmg   0/1     CrashLoopBackOff   8 (4m46s ago)   25m

CodePudding user response:

The definition of a headless service is to not provide a DNS record and provide internal load balancing.

A headless service can be used to query the endpoints and handle them separately.

To fix your issue create a regular service.

CodePudding user response:

Headless service won't give you DNS record you should be any of ClusterIP or NodePort or LoadBalancer

A headless service is a service with a service IP but instead of load-balancing it will return the IPs of our associated Pods. This allows us to interact directly with the Pods instead of a proxy. It's as simple as specifying None for .spec.clusterIP and can be utilized with or without selectors - you'll see an example with selectors in a moment.

Read more about headless serivce at : https://dev.to/kaoskater08/building-a-headless-service-in-kubernetes-3bk8

you can follow below YAML file which is creating the serivce type : ClusterIP

apiVersion: v1
kind: Service
metadata:
  name: postgres
spec:
  ports:
  - name: pgql
    port: 5432
    targetPort: 5432
    protocol: TCP
  selector:
    app: postgres
---
apiVersion: apps/v1  
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: "postgres"
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:9.5
        volumeMounts:
        - name: postgres-data
          mountPath: /var/lib/postgresql/data
          subPath: pgdata
        env:
        - name: POSTGRES_USER
          value: root
        - name: POSTGRES_PASSWORD
          value: password
        - name: POSTGRES_DB
          value: kong
        - name: PGDATA
          value: /var/lib/postgresql/data/pgdata
        ports:
        - containerPort: 5432
      terminationGracePeriodSeconds: 60
  volumeClaimTemplates:
  - metadata:
      name: postgres-data
    spec:
      accessModes:
      - "ReadWriteOnce"
      resources:
        requests:
          storage: 10Gi

https://github.com/harsh4870/Keycloack-postgres-kubernetes-deployment/blob/main/postgres.yaml

  • Related