so I have a basic minikube cluster configuration for K8s cluster with only 2 pods for Postgres DB and my Spring app. However, I can't get my app to connect to my DB. I know that in Docker such issue could be solved with networking but after a lot of research I can't seem to find the problem and the solution to my issue.
Currently, given my configuration I get a Connection refused error by postgres whenever my Spring App tries to start:
Caused by: org.postgresql.util.PSQLException: Connection to postgres-service:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
So my spring-app is a basic REST API with some open endpoints where I query for some data. The app works completely fine and here is my application.properties:
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
spring.datasource.username=${POSTGRES_USER}
spring.datasource.password=${POSTGRES_PASSWORD}
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update
The way I create my Postgres component is by creating a ConfigMap, a Secret and finally a Deployment with it's Service inside. They look like so:
postgres-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-config
data:
postgres-url: postgres-service
postgres-port: "5432"
postgres-db: "test"
postgres-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: postgres-secret
type: Opaque
data:
postgres_user: cm9vdA== #already encoded in base64
postgres_password: cm9vdA== #already encoded in base64
postgres.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres-deployment
labels:
app: postgres
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgresdb
image: postgres
ports:
- containerPort: 5432
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-secret
key: postgres_user
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: postgres_password
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
name: postgres-config
key: postgres-db
---
apiVersion: v1
kind: Service
metadata:
name: postgres-service
spec:
selector:
app.kubernetes.io/name: postgres
ports:
- protocol: TCP
port: 5432
targetPort: 5432
and finally here's my Deployment with it's Service for my spring app
spring-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-app-deployment
labels:
app: spring-app
spec:
replicas: 1
selector:
matchLabels:
app: spring-app
template:
metadata:
labels:
app: spring-app
spec:
containers:
- name: spring-app
image: app #image is pulled from my docker hub
ports:
- containerPort: 8080
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-secret
key: postgres_user
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: postgres_password
- name: POSTGRES_HOST
valueFrom:
configMapKeyRef:
name: postgres-config
key: postgres-url
- name: POSTGRES_PORT
valueFrom:
configMapKeyRef:
name: postgres-config
key: postgres-port
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
name: postgres-config
key: postgres-db
---
apiVersion: v1
kind: Service
metadata:
name: spring-app-service
spec:
type: NodePort
selector:
app.kubernetes.io/name: spring-app
ports:
- protocol: TCP
port: 8080
targetPort: 8080
nodePort: 30001
A connection refused means that the host you are connecting to, does not have the port you mentioned opened.
This leads me to think that the postgres pod isnt running correctly, or the service is not pointing to those pods correctly.
By checking the Yamls I can see that the service's pod selector isnt configured correctly:
The service is selecting pods with label: app.kubernetes.io/name: postgres
The deployment is configured with pods with label: app: postgres
The correct service manifest should look like:
apiVersion: v1
kind: Service
metadata:
name: postgres-service
spec:
selector:
app: postgres
ports:
- protocol: TCP
port: 5432
targetPort: 5432
You can double check that by describing the service using kubectl describe service postgres-service.
The output should contain the postgres pods IPs for Endpoints.
Related
I am trying to create a deployment from an image that I specify in a Dockerfile. My goal would be to pass the environmental variables so I could access them inside the Dockerfile, so kind of similar to the postgres image available on Dockerhub. Additionally I would need a service so I could access the database in a Spring boot application. The reason why I would like to work it this way, because I would like to have additional content inside the Dockerfile. I am not sure whether I can do it this way, but if yes, what am I doing wrong, and how could I access it from Spring boot?
What I have tried so far:
apiVersion: v1
kind: Namespace
metadata:
name: testns
---
apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-configmap
namespace: testns
data:
dbname: test_database
---
apiVersion: v1
kind: Secret
metadata:
name: postgres-secret
namespace: testns
type: Opaque
data:
username: cG9zdGdyZXN1c2Vy
password: cGFzc3dvcmQxMjM0NTY=
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres-depl
namespace: testns
labels:
app: postgresql
spec:
replicas: 1
selector:
matchLabels:
app: postgresql
template:
metadata:
labels:
app: postgresql
spec:
containers:
- name: postgresdb
image: testpostgres
ports:
- containerPort: 5432
env:
- name: DB
valueFrom:
configMapKeyRef:
name: postgres-configmap
key: dbname
- name: USERNAME
valueFrom:
secretKeyRef:
name: postgres-secret
key: username
- name: PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
---
apiVersion: v1
kind: Service
metadata:
name: postgres-service
namespace: testns
spec:
selector:
app: postgresql
type: LoadBalancer
ports:
- protocol: TCP
port: 7000
targetPort: 5432
nodePort: 30000
And the related Dockerfile that I use to create the testpostgres image:
FROM postgres
ARG DB
ARG USERNAME
ARG PASSWORD
ENV POSTGRES_DB=$DB
ENV POSTGRES_USER=$USERNAME
ENV POSTGRES_PASSWORD=$PASSWORD
EXPOSE 5432
I have a mongo yaml and web-app(NodeJS) yaml set up like this:
mongo-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mongo-config
data:
mongo-url: mongo-service
mongo-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mongo-secret
type: Opaque
data:
mongo-user: bW9uZ291c2Vy
mongo-password: bW9uZ29wYXNzd29yZA==
mongo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongo-deployment
labels:
app: mongo
spec:
replicas: 1
selector:
matchLabels:
app: mongo
# blueprint for pods, creates pods with mongo:5.0 image
template:
metadata:
labels:
app: mongo
spec:
containers:
- name: mongodb
image: mongo:5.0
ports:
- containerPort: 27017
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-user
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-password
---
# kind: service
# name: any
# selector: select pods to forward the requests to
apiVersion: v1
kind: Service
metadata:
name: mongo-service
spec:
selector:
app: mongo
ports:
- protocol: TCP
port: 8080
targetPort: 27017
and the webapp.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp-deployment
labels:
app: webapp
spec:
replicas: 1
selector:
matchLabels:
app: webapp
# blueprint for pods, creates pods with mongo:5.0 image
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: nanajanashia/k8s-demo-app:v1.0
ports:
- containerPort: 3000
env:
- name: USER_NAME
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-user
- name: USER_PWD
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-password
- name: DB_URL
valueFrom:
configMapKeyRef:
name: mongo-config
key: mongo-url
---
# kind: service
# name: any
# selector: select pods to forward the requests to
apiVersion: v1
kind: Service
metadata:
name: webapp-service
spec:
# default ClusterIP
# nodeport = external service
type: NodePort
selector:
app: webapp
ports:
- protocol: TCP
port: 3000
targetPort: 3000
nodePort: 30100
I ran the commands for each file
kubectl apply -f
i checked the status of the webapp which returned:
app listening on port 3000!
I got the IP address by
minikube ip
and the port was 30100
Why cannot not I access this web app?
I get a site cant be reached error.
If you are on Mac, check your minikube driver. I had to stop, delete minikube, then restart while specifying the hyperkit driver like so.
minikube stop
minikube delete
docker start --vm-driver=hyperkit
The information listed here is pretty useful too.
I'm trying to deploy postgres, but am unable to reach postgres through service, using the following domain nametestapp-postgres.default.svc.cluster.local.
However, I get the following response
django.db.utils.OperationalError: could not connect to server: Connection refused
Is the server running on host "testapp-postgres.default.svc.cluster.local" (10.43.31.182) and accepting
TCP/IP connections on port 5432?
The address matches the service
default testapp-postgres ClusterIP 10.43.31.182 5432/TCP 20m
I am using the following deployment and service
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: testapp-postgres
labels:
app: testapp
spec:
replicas: 1
selector:
matchLabels:
app: testapp
template:
metadata:
labels:
app: testapp
spec:
containers:
- name: testapp-postgres
image: library/postgres:12-alpine
ports:
- containerPort: 5432
env:
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
key: DB_NAME
name: testapp-secret
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
key: DB_PASSWORD
name: testapp-secret
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
key: DB_USER
name: testapp-secret
volumeMounts:
- mountPath: /var/lib/postgresql/data/
name: testapp-postgres-data
volumes:
- name: testapp-postgres-data
persistentVolumeClaim:
claimName: testapp-postgres-data
---
apiVersion: v1
kind: Service
metadata:
labels:
app: testapp
name: testapp-postgres
spec:
selector:
app: testapp
ports:
- protocol: TCP
port: 5432
targetPort: 5432
name: postgres
Is it possible to use SSL in Endpoint?
I have an Azure Database for MySQL, which requires an SSL certificate for connection. I use the following:
https://www.digicert.com/CACerts/BaltimoreCyberTrustRoot.crt.pem
On Kubernetes I have run a NodeJS Pod which communicate to MySQL by an Endpoint like that:
kind: Service
apiVersion: v1
metadata:
name: mysql-remote
spec:
ports:
- protocol: TCP
port: 3306
targetPort: 3306
---
kind: Endpoints
apiVersion: v1
metadata:
name: mysql-remote
subsets:
- addresses:
- ip: xx.xxx.xxx.xx
ports:
- port: 3306
My deplomyent.yaml file looks like that:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nodejs
spec:
replicas: 2
template:
metadata:
labels:
app: nodejs
spec:
nodeSelector:
"beta.kubernetes.io/os": linux
containers:
- name: nodejs
image: xxx
ports:
- containerPort: 80
name: nodejs
env:
- name: HOST
value: "mysql-remote"
- name: USER
valueFrom:
secretKeyRef:
name: nodejssecret
key: username
- name: PASSWORD
valueFrom:
secretKeyRef:
name: nodejssecret
key: password
First I tried to mount the certificate as a Volume to NodeJS. That looks very awkward if I use for example 10 different Applications.
Is there an easy way to use the SSL?
Review the Security on Azure Kubernetes Service (AKS) part in deploying-a-stateful-application-on-azure-kubernetes-service-aks article.
The idea is to create secter from BaltimoreCyberTrustRoot.crt.pem cert and use it in the deployment
- name: database__connection__ssl
valueFrom:
secretKeyRef:
name: ssl-cert
key: BaltimoreCyberTrustRoot.crt.pem
I have a deployment running a pod that needs access to a postgres database I am running in the same cluster as the kubernetes cluster. How do I create a service that selects the deployment such that it has access. My pods keep restarting as the connection times out. I have created firewall rules in the vpc subnet to allow internal communication and have modified pg_hba.conf and postgresql.conf
My deployment definition is given below:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
labels:
name: server
app: api
spec:
replicas: 3
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: gcr.io/api:v1
ports:
- containerPort: 80
env:
- name: DB_HOSTNAME
valueFrom:
secretKeyRef:
name: api-config
key: hostname
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: api-config
key: username
- name: DB_NAME
valueFrom:
secretKeyRef:
name: api-config
key: name
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: api-config
key: password
This is my service definition to expose the database but I don't think I am selecting the deployment. I have followed the example here.
kind: Service
apiVersion: v1
metadata:
name: postgres
label:
spec:
type: ClusterIP
ports:
- port: 5432
targetPort: 5432
---
kind: Endpoints
apiVersion: v1
metadata:
name: postgres
subsets:
- addresses:
- ip: 10.0.0.50
ports:
- port: 5432
You can use the following to expose database to deployment on GKE:
$ kubectl expose deployment name-of-db --type=LoadBalancer --port 80 --target-port 8080