Create Kubernetes deployment and service from image using configmap and secret - postgresql

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

Related

Minikube Kubernetes, Postgres, Spring Boot Cluster - Postgres connection refused

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.

Cannot connect to my MiniKube external service ip/port?

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.

"Failed to connect to database" : Keycloak Operator external database Config not working

I checked this How to use for Keycloak operator custom resource using external database connection. I am using CloudSQL from Google platform as the external database source.
My configurations are
keycloak-idm
apiVersion: keycloak.org/v1alpha1
kind: Keycloak
metadata:
name: kiwigrid-keycloak-idm
spec:
instances: 3
externalAccess:
enabled: false
externalDatabase:
enabled: true
external db storage secret
apiVersion: v1
kind: Secret
metadata:
name: keycloak-db-secret
namespace: kiwios-application
type: Opaque
stringData:
POSTGRES_DATABASE: keycloak-storage
POSTGRES_EXTERNAL_ADDRESS: pgsqlproxy.infra
POSTGRES_EXTERNAL_PORT: "5432"
POSTGRES_HOST: keycloak-postgresql
POSTGRES_USERNAME: keycloak-user
POSTGRES_PASSWORD: S1ly3AValJYBNR-fsptLYdT74
POSTGRES_SUPERUSER: "true"
storage database
apiVersion: sql.cnrm.cloud.google.com/v1beta1
kind: SQLDatabase
metadata:
name: keycloak-storage
namespace: kiwios-application
annotations:
cnrm.cloud.google.com/deletion-policy: "abandon"
spec:
charset: UTF8
collation: en_US.UTF8
instanceRef:
name: keycloak-storage-instance-pg
namespace: infra
storage users
apiVersion: sql.cnrm.cloud.google.com/v1beta1
kind: SQLUser
metadata:
name: keycloak-user
namespace: kiwios-application
annotations:
cnrm.cloud.google.com/deletion-policy: "abandon"
spec:
instanceRef:
name: keycloak-storage-instance-pg
namespace: infra
password:
valueFrom:
secretKeyRef:
name: keycloak-db-secret
key: POSTGRES_PASSWORD
And the error shown in Kubernetes console
It is not working. Anyone please help me to figure out what I am doing wrong.
Update: I deep dived with k9s console. As per keycloak-operator functionality it creates a external name for the database connection.
which is here keycloak-postgresql
check image below
There is no error showing in keycloak-operator console. Only the keycloak-idm is not able to make a connection using this external name. It shows the below error.
This is what i am using for keycloak setup, also if you have read the question he has mention secret issue issue in update section
apiVersion: v1
kind: Service
metadata:
name: keycloak
labels:
app: keycloak
spec:
ports:
- name: http
port: 8080
targetPort: 8080
selector:
app: keycloak
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: keycloak
namespace: default
labels:
app: keycloak
spec:
replicas: 1
selector:
matchLabels:
app: keycloak
template:
metadata:
labels:
app: keycloak
spec:
containers:
- name: keycloak
image: quay.io/keycloak/keycloak:10.0.0
env:
- name: KEYCLOAK_USER
value: "admin"
- name: KEYCLOAK_PASSWORD
value: "admin"
- name: PROXY_ADDRESS_FORWARDING
value: "true"
- name: DB_VENDOR
value: POSTGRES
- name: DB_ADDR
value: postgres
- name: DB_DATABASE
value: keycloak
- name: DB_USER
value: root
- name: DB_PASSWORD
value: password
- name : KEYCLOAK_HTTP_PORT
value : "80"
- name: KEYCLOAK_HTTPS_PORT
value: "443"
- name : KEYCLOAK_HOSTNAME
value : keycloak.harshmanvar.tk #replace with ingress URL
ports:
- name: http
containerPort: 8080
- name: https
containerPort: 8443
readinessProbe:
httpGet:
path: /auth/realms/master
port: 8080
You can try changing the ENV variables into the secret you are using.
Example files : https://github.com/harsh4870/Keycloack-postgres-kubernetes-deployment
Environment variables that Keycloak support : https://github.com/keycloak/keycloak-containers/blob/master/server/README.md#environment-variables
Have you tried this way..!
apiVersion: v1
kind: Secret
metadata:
name: keycloak-db-secret
namespace: kiwios-application
type: Opaque
stringData:
POSTGRES_DATABASE: "keycloak-storage"
POSTGRES_EXTERNAL_ADDRESS: "pgsqlproxy.infra"
POSTGRES_EXTERNAL_PORT: "5432"
POSTGRES_HOST: "keycloak-postgresql"
POSTGRES_USERNAME: "keycloak-user"
POSTGRES_PASSWORD: "S1ly3AValJYBNR-fsptLYdT74"
POSTGRES_SUPERUSER: "true"

How to set Kubernetes config map and secret to mongodb environment variables

I am trying to set the two env variables of mongo namely - MONGO_INITDB_ROOT_USERNAME and MONGO_INITDB_ROOT_PASSWORD using kubernetes ConfigMap and Secret as follows:
When I don't use the config map and password, i.e. I hardcode the username and password, it works, but when I try to replace it with configmap and secret, it says
'Authentication failed.'
my username and password is the same, which is admin
Here's the yaml definition for these obects, can someone help me what is wrong?
apiVersion: v1
kind: ConfigMap
metadata:
name: mongodb-username
data:
username: admin
---
apiVersion: v1
kind: Secret
metadata:
name: mongodb-password
data:
password: YWRtaW4K
type: Opaque
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongodbtest
spec:
# serviceName: mongodbtest
replicas: 1
selector:
matchLabels:
app: mongodbtest
template:
metadata:
labels:
app: mongodbtest
selector: mongodbtest
spec:
containers:
- name: mongodbtest
image: mongo:3
# env:
# - name: MONGO_INITDB_ROOT_USERNAME
# value: admin
# - name: MONGO_INITDB_ROOT_PASSWORD
# value: admin
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
configMapKeyRef:
name: mongodb-username
key: username
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mongodb-password
key: password
Finally I was able to find the solution after hours, it is not something I did from kubernetes side, it is when I did base64 encode.
The correct way to encode is with following command:
echo -n 'admin' | base64
and this was the issue with me.
Your deployment yaml is fine, just change spec.containers[0].env to spec.containers[0].envFrom:
spec:
containers:
- name: mongodbtest
image: mongo:3
envFrom:
- configMapRef:
name: mongodb-username
- secretRef:
name: mongodb-password
That will put all keys of your secret and configmap as environment variables in the deployment.
apiVersion: v1
data:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD : password
kind: ConfigMap
metadata:
name: mongo-cred
namespace: default
inject it to deployment like
envFrom:
- configMapRef:
name: mongo-cred
the deployment will be something like
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongodbtest
spec:
# serviceName: mongodbtest
replicas: 1
selector:
matchLabels:
app: mongodbtest
template:
metadata:
labels:
app: mongodbtest
selector: mongodbtest
spec:
containers:
- name: mongodbtest
image: mongo:3
envFrom:
- configMapRef:
name: mongo-cred
if you want to save the data in secret, the secret is best practice to store data with encryption base64 and sensitive data.
envFrom:
- secretRef:
name: mongo-cred
you can create the secret with
apiVersion: v1
data:
MONGO_INITDB_ROOT_USERNAME: YWRtaW4K #base 64 encoded
MONGO_INITDB_ROOT_PASSWORD : YWRtaW4K
kind: secret
type: Opaque
metadata:
name: mongo-cred
namespace: default

Expose database to deployment on GKE

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