Can't connect database container with server container using a single pod

1/2/2022

I am creating a POD file with multiple containers. One is a webserver container and another is my PostgreSQL container. Here is my pod file named simple.yaml

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2022-01-01T16:28:15Z"
  labels:
    app: eltask
  name: eltask
spec:
  containers:
  - name: el_web
    command:
      - ./entrypoints/entrypoint.sh
    env:
    - name: PATH
      value: /usr/local/bundle/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    - name: TERM
      value: xterm
    - name: container
      value: podman
    - name: RUBY_MAJOR
      value: "2.7"
    - name: BUNDLE_SILENCE_ROOT_WARNING
      value: "1"
    - name: BUNDLE_APP_CONFIG
      value: /usr/local/bundle
    - name: LANG
      value: C.UTF-8
    - name: RUBY_VERSION
      value: 2.7.2
    - name: RUBY_DOWNLOAD_SHA256
      value: 1b95ab193cc8f5b5e59d2686cb3d5dcf1ddf2a86cb6950e0b4bdaae5040ec0d6
    - name: GEM_HOME
      value: /usr/local/bundle
    image: docker.io/hmtanbir/elearniotask
    ports:
    - containerPort: 3000
      hostPort: 3000
      protocol: TCP
    resources: {}
    securityContext:
      allowPrivilegeEscalation: true
      capabilities:
        drop:
        - CAP_MKNOD
        - CAP_NET_RAW
        - CAP_AUDIT_WRITE
      privileged: false
      readOnlyRootFilesystem: false
      seLinuxOptions: {}
    tty: true
    workingDir: /app
  - name: el_db
    image: docker.io/library/postgres:10-alpine3.13
    env:
      - name: PATH
        value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
      - name: TERM
        value: xterm
      - name: container
        value: podman
      - name: PG_MAJOR
        value: "10"
      - name: PG_VERSION
        value: "10.17"
      - name: PGDATA
        value: /var/lib/postgresql/data
      - name: LANG
        value: en_US.utf8
      - name: PG_SHA256
        value: 5af28071606c9cd82212c19ba584657a9d240e1c4c2da28fc1f3998a2754b26c
      - name: POSTGRES_PASSWORD
        value: password
    args:
      - postgres
    command:
      - docker-entrypoint.sh
    ports:
      - containerPort: 5432
        hostPort: 9876
        protocol: TCP
    resources: {}
    securityContext:
      allowPrivilegeEscalation: true
      capabilities:
        drop:
          - CAP_MKNOD
          - CAP_NET_RAW
          - CAP_AUDIT_WRITE
        privileged: false
        readOnlyRootFilesystem: false
        seLinuxOptions: {}
    tty: true
    workingDir: /
  dnsConfig: {}
  restartPolicy: Never
status: {}

I am running a webserver container in 3000:3000 port and the DB container port is 9876:5432. But when I run cmd using PODMAN podman play kube simple.yaml, DB container is running 127.0.0.0:9876 but webserver can't connect with the DB server.

enter image description here

My webserver DB config:

ELTASK_DATABASE_HOST=localhost
ELTASK_DATABASE_PORT=9876
ELTASK_DATABASE_USERNAME=postgres
ELTASK_DATABASE_PASSWORD=password

If I run the webserver without Podman, the server can connect with the DB using 9876 port.

So, Why the webserver can't connect with the database container while it is running through Podman?

-- HM Tanbir
kubernetes
podman

2 Answers

1/2/2022

For your web container to connect to the postgresql container within the pod, use ELTASK_DATABASE_PORT=5432 instead of ELTASK_DATABASE_PORT=9876.

-- gohm'c
Source: StackOverflow

1/3/2022

Posting this as a community wiki, feel free to edit and expand.


There are two parts of the answer:

  1. Which port to use and why

For postgresql as a backend service, you can omit the hostPort since podman as a frontend service will access postresql using Cluster-IP and therefore it will be available on port 5432. Completely deleting this part is not recommended approach, when you have a lot of pods with containers inside, it's much better to be able to quickly see which container is exposed on which port.

Also in general hostPort shouldn't be used unless it's the only way, consider using NodePort:

Don't specify a hostPort for a Pod unless it is absolutely necessary. When you bind a Pod to a hostPort, it limits the number of places the Pod can be scheduled, because each <hostIP, hostPort, protocol> combination must be unique.

See best practices.

  1. Frontend and backend deployment

It's always advisable and a best practice to separate backend and frontend into different deployments, so they can be managed fully separately like upgrades, replicas and etc. As well as services - you don't need to expose backend service outside the cluster.

See an frontend and backend example.

Also @David Maze correctly said that database should use a statefulSet - see more details about Statefulset.

-- moonkotte
Source: StackOverflow