Can't mount python code to local kubernetes pod - docker

I'm trying to setup a local kubernetes development kluster with minikube and can't mount my python file to a pod.
I have a server.py file in my src directory that i mount onto the serverpod:
apiVersion: v1
kind: Pod
metadata:
labels:
app: web
name: serverpod
spec:
containers:
-
imagePullPolicy: IfNotPresent
image: flaskserver
name: testserver
ports:
-
containerPort: 8000
volumeMounts:
- name: src-config
mountPath: /src
volumes:
- name: src-config
hostPath:
path: /home/user/project/src
Dockerfile
FROM python:3
EXPOSE 8000
RUN pip install flask
RUN mkdir /src
CMD [ "python", "src/server.py" ]
The pod does not seem to find the server.py file, not sure if i'm using this right.

Looks like you have not mounted the host folder to the kubernetes volume. Follow this doc to mount a folder in your local to your cluster.

Related

HorizontalPodAutoscaler overwrites volume when releasing a Pod

i have a question to ask you about kubernates. I need to configure a Horizontal Load Balancer on a service with Kubernates. Specifically in my yaml file I used the following kind: HorizontalPodAutoscaler; the problem arises on the logic of uploading files to the volume: in a nutshell, when a pod is released, the data inside is overwritten, so with a new pod the volume is emptied. Am I wrong in configurations?
Specifically, I set the volume in the Dockerfile to build the corresponding image of the service launched with Kubernates.
it's not good idea to store data in Dockerimage however still what you can do is,
Copy data to docker image
Inside the Kubernetes POD create the PVC volume
Attach POD to PVC and use the volume mount
Use the init container to copy data from the docker path to the volume mount file path
Dockerfile
FROM python:latest
COPY data.csv ./tmp/
Kubernetes YAML
apiVersion: apps/v1
kind: Deployment
metadata:
name: POD-name
spec:
replicas: 2
selector:
matchLabels:
app: test
template:
metadata:
labels:
app: test
spec:
initContainers:
- name: copy
image: busybox:1.28
command: ["/bin/sh", "-c", "cp /tmp/data.csv /data/data.csv"]
volumeMounts:
- name: pvc
mountPath: /data/
containers:
- name: test
image: image:tag
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
volumeMounts:
- mountPath: "/data/"
name: pvc
volumes:
- name: pvc
persistentVolumeClaim:
claimName: pvc-claim

kubernetes volumes for nestjs app for hot reloading data

I'm having an issue with volumes on Kubernetes when I'm trying to mount hostPath volumes. (i also tried with PVC, but no success)
Dockerfile:
FROM node:16
WORKDIR /usr/src/app
COPY package.json /usr/src/app
RUN yarn install
COPY . /usr/src/app
EXPOSE 3000
ENTRYPOINT ["yarn", "start:dev"]
docker-compose.yml:
version: '3.8'
services:
api:
container_name: api
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/usr/src/app
- /usr/src/app/node_modules
ports:
- 3000:3000
restart: always
labels:
kompose.volume.type: 'hostPath'
database:
container_name: database
image: postgres:latest
ports:
- 5432:5432
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: task-management
api-development.yml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose -f docker-compose.yml convert
kompose.version: 1.26.1 (HEAD)
kompose.volume.type: hostPath
creationTimestamp: null
labels:
io.kompose.service: api
name: api
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: api
strategy:
type: Recreate
template:
metadata:
annotations:
kompose.cmd: kompose -f docker-compose.yml convert
kompose.version: 1.26.1 (HEAD)
kompose.volume.type: hostPath
creationTimestamp: null
labels:
io.kompose.service: api
spec:
containers:
- image: task-management_api
name: api
imagePullPolicy: Never
ports:
- containerPort: 3000
resources: {}
volumeMounts:
- mountPath: /usr/src/app
name: api-hostpath0
- mountPath: /usr/src/app/node_modules
name: api-hostpath1
restartPolicy: Always
volumes:
- hostPath:
path: /Users/handrei/workspace/devs/nest-ws/task-management
name: api-hostpath0
- hostPath:
name: api-hostpath1
status: {}
the error I received from the pod is the next one:
kubectl logs api-84b56776c5-v86c7
yarn run v1.22.17
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
error Couldn't find a package.json file in "/usr/src/app"
I assume that's something wrong with volumes because applying the deployment and service without volumes it's working
A hostPath volume mounts a file or directory from the host node's filesystem into your Pod.
To the required path property, you can also specify a type for a hostPath volume.
NOTE: HostPath volumes present many security risks, and it is a best practice to avoid the use of HostPaths when possible. When a HostPath volume must be used, it should be scoped to only the required file or directory, and mounted as ReadOnly.
As #David Maze mentioned before, It's better idea to
use Node locally for day-to-day development and use a self-contained image (without any volume mounts at all) in Kubernetes. (...)
The node_modules directory is empty and nothing in Kubernetes will every copy data there. You'll need to delete all of the volume declarations from your Deployment spec for this to run.
This quide will help you to translate a Docker Compose File to Kubernetes Resources.
See also this questions on StackOverflow:
Why node_modules is empty after docker build?
Kubernetes volume for node_modules

Why I cannot read files from a shared PersistentVolumeClaim between containers in Kubernetes?

I have a docker image felipeogutierrez/tpch-dbgen that I build using docker-compose and I push it to docker-hub registry using travis-CI.
version: "3.7"
services:
other-images: ....
tpch-dbgen:
build: ../docker/tpch-dbgen
image: felipeogutierrez/tpch-dbgen
volumes:
- tpch-dbgen-data:/opt/tpch-dbgen/data/
- datarate:/tmp/
stdin_open: true
and this is the Dockerfile to build this image:
FROM gcc AS builder
RUN mkdir -p /opt
COPY ./generate-tpch-dbgen.sh /opt/generate-tpch-dbgen.sh
WORKDIR /opt
RUN chmod +x generate-tpch-dbgen.sh && ./generate-tpch-dbgen.sh
In the end, this scripts creates a directory /opt/tpch-dbgen/data/ with some files that I would like to read from another docker image that I am running on Kubernetes. Then I have a Flink image that I create to run into Kubernetes. This image starts 3 Flink Task Managers and one stream application that reads files from the image tpch-dbgen-data. I think that the right approach is to create a PersistentVolumeClaim so I can share the directory /opt/tpch-dbgen/data/ from image felipeogutierrez/tpch-dbgen to my flink image in Kubernetes. So, first I have this file to create the PersistentVolumeClaim:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: tpch-dbgen-data-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 200Mi
Then, I am creating an initContainers to launch the image felipeogutierrez/tpch-dbgen and after that launch my image felipeogutierrez/explore-flink:1.11.1-scala_2.12:
apiVersion: apps/v1
kind: Deployment
metadata:
name: flink-taskmanager
spec:
replicas: 3
selector:
matchLabels:
app: flink
component: taskmanager
template:
metadata:
labels:
app: flink
component: taskmanager
spec:
initContainers:
- name: tpch-dbgen
image: felipeogutierrez/tpch-dbgen
#imagePullPolicy: Always
env:
command: ["ls"]
# command: ['sh', '-c', 'for i in 1 2 3; do echo "job-1 `date`" && sleep 5s; done;', 'ls']
volumeMounts:
- name: tpch-dbgen-data
mountPath: /opt/tpch-dbgen/data
containers:
- name: taskmanager
image: felipeogutierrez/explore-flink:1.11.1-scala_2.12
#imagePullPolicy: Always
env:
args: ["taskmanager"]
ports:
- containerPort: 6122
name: rpc
- containerPort: 6125
name: query-state
livenessProbe:
tcpSocket:
port: 6122
initialDelaySeconds: 30
periodSeconds: 60
volumeMounts:
- name: flink-config-volume
mountPath: /opt/flink/conf/
- name: tpch-dbgen-data
mountPath: /opt/tpch-dbgen/data
securityContext:
runAsUser: 9999 # refers to user _flink_ from official flink image, change if necessary
volumes:
- name: flink-config-volume
configMap:
name: flink-config
items:
- key: flink-conf.yaml
path: flink-conf.yaml
- key: log4j-console.properties
path: log4j-console.properties
- name: tpch-dbgen-data
persistentVolumeClaim:
claimName: tpch-dbgen-data-pvc
The Flink stream application is starting but it cannot read the files on the directory /opt/tpch-dbgen/data of the image felipeogutierrez/tpch-dbgen. I am getting the error: java.io.FileNotFoundException: /opt/tpch-dbgen/data/orders.tbl (No such file or directory). It is strange because when I try to go into the container felipeogutierrez/tpch-dbgen I can list the files. So I suppose there is something wrong on my Kubernetes configuration. Does anyone know to point what I am missing on the Kubernetes configuration files?
$ docker run -i -t felipeogutierrez/tpch-dbgen /bin/bash
root#10c0944a95f8:/opt# pwd
/opt
root#10c0944a95f8:/opt# ls tpch-dbgen/data/
customer.tbl dbgen dists.dss lineitem.tbl nation.tbl orders.tbl part.tbl partsupp.tbl region.tbl supplier.tbl
Also, when I list the logs of the container tpch-dbgen I can see the directory tpch-dbgen that I want to read. Although I cannot execute the command command: ["ls tpch-dbgen"] inside my Kubernetes config file.
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
flink-jobmanager-n9nws 1/1 Running 2 17m
flink-taskmanager-777cb5bf77-ncdl4 1/1 Running 0 4m54s
flink-taskmanager-777cb5bf77-npmrx 1/1 Running 0 4m54s
flink-taskmanager-777cb5bf77-zc2nw 1/1 Running 0 4m54s
$ kubectl logs flink-taskmanager-777cb5bf77-ncdl4 tpch-dbgen
generate-tpch-dbgen.sh
tpch-dbgen
Docker has an unusual feature where, under some specific circumstances, it will populate a newly created volume from the image. You should not rely on this functionality, since it completely ignores updates in the underlying images and it doesn't work on Kubernetes.
In your Kubernetes setup, you create a new empty PersistentVolumeClaim, and then mount this over your actual data in both the init and main containers. As with all Unix mounts, this hides the data that was previously in that directory. Nothing causes data to get copied into that volume. This works the same way as every other kind of mount, except the Docker named-volume mount: you'll see the same behavior if you change your Compose setup to do a host bind mount, or if you play around with your local development system using a USB drive as a "volume".
You need to make your init container (or something else) explicitly copy data into the directory. For example:
initContainers:
- name: tpch-dbgen
image: felipeogutierrez/tpch-dbgen
command:
- /bin/cp
- -a
- /opt/tpch-dbgen/data
- /data
volumeMounts:
- name: tpch-dbgen-data
mountPath: /data # NOT the same path as in the image
If the main process modifies these files in place, you can make the command be more intelligent, or write a script into your image that only copies the individual files in if they don't exist yet.
It could potentially make more sense to have your image generate the data files at startup time, rather than at image-build time. That could look like:
FROM gcc
COPY ./generate-tpch-dbgen.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/generate-tpch-dbgen.sh
CMD ["generate-tpch-dbgen.sh"]
Then in your init container, you can run the default command (the generate script) with the working directory set to the volume directory
initContainers:
- name: tpch-dbgen
image: felipeogutierrez/tpch-dbgen
volumeMounts:
- name: tpch-dbgen-data
mountPath: /opt/tpch-dbgen/data # or anywhere really
workingDir: /opt/tpch-dbgen/data # matching mountPath
I got to run the PersistentVolumeClaim and share it between pods. Basically I had to use a subPath property which I learned from this answer https://stackoverflow.com/a/43404857/2096986 and I am using a simple Job that I learned from this answer https://stackoverflow.com/a/64023672/2096986. The final results is below:
The Dockerfile:
FROM gcc AS builder
RUN mkdir -p /opt
COPY ./generate-tpch-dbgen.sh /opt/generate-tpch-dbgen.sh
WORKDIR /opt
RUN chmod +x /opt/generate-tpch-dbgen.sh
ENTRYPOINT ["/bin/sh","/opt/generate-tpch-dbgen.sh"]
and the script generate-tpch-dbgen.sh has to have this line in the end sleep infinity & wait to not finalize. The PersistentVolumeClaim is the same of the question. Then I create a Job with the subPath property.
apiVersion: batch/v1
kind: Job
metadata:
name: tpch-dbgen-job
spec:
template:
metadata:
labels:
app: flink
component: tpch-dbgen
spec:
restartPolicy: OnFailure
volumes:
- name: tpch-dbgen-data
persistentVolumeClaim:
claimName: tpch-dbgen-data-pvc
containers:
- name: tpch-dbgen
image: felipeogutierrez/tpch-dbgen
imagePullPolicy: Always
volumeMounts:
- mountPath: /opt/tpch-dbgen/data
name: tpch-dbgen-data
subPath: data
and I use it on the other deployment also with the subPath property.
apiVersion: apps/v1
kind: Deployment
metadata:
name: flink-taskmanager
spec:
replicas: 3
selector:
matchLabels:
app: flink
component: taskmanager
template:
metadata:
labels:
app: flink
component: taskmanager
spec:
volumes:
- name: flink-config-volume
configMap:
name: flink-config
items:
- key: flink-conf.yaml
path: flink-conf.yaml
- key: log4j-console.properties
path: log4j-console.properties
- name: tpch-dbgen-data
persistentVolumeClaim:
claimName: tpch-dbgen-data-pvc
containers:
- name: taskmanager
image: felipeogutierrez/explore-flink:1.11.1-scala_2.12
imagePullPolicy: Always
env:
args: ["taskmanager"]
ports:
- containerPort: 6122
name: rpc
- containerPort: 6125
name: query-state
livenessProbe:
tcpSocket:
port: 6122
initialDelaySeconds: 30
periodSeconds: 60
volumeMounts:
- name: flink-config-volume
mountPath: /opt/flink/conf/
- name: tpch-dbgen-data
mountPath: /opt/tpch-dbgen/data
subPath: data
securityContext:
runAsUser: 9999 # refers to user _flink_ from official flink image, change if necessary
Maybe the issue is the accessMode you set on your PVC. ReadWriteOnce means it can only be mounted by one POD.
See here for Details.
You could try to use ReadWriteMany.
Your generate-tpch-dbgen.sh script is executed while building the docker image resulting those files in /opt/tpch-dbgen/data directory. So, when you run the image, you can see those files.
But the problem with k8s pvc, when you mount the volume (initially empty) to your containers, it replaces the /opt/tpch-dbgen/data directory along with the files in it.
Solution:
Don't execute the generate-tpch-dbgen.sh while building the docker image, rather execute it in the runtime. Then, the files will be created in the shared pv from the init container.
Something like below:
FROM gcc AS builder
RUN mkdir -p /opt
COPY ./generate-tpch-dbgen.sh /opt/generate-tpch-dbgen.sh
RUN chmod +x /opt/generate-tpch-dbgen.sh
ENTRYPOINT ["/bin/sh","/opt/generate-tpch-dbgen.sh"]

How to mount volume from my container in kubenetes

I want to mount directory from SourceContaner to ServerContainer.
ServerContainer:
FROM php:7.2-apache
RUN a2enmod rewrite
# /var/www/html is apache document root.
SourceContaner:
FROM alpine:3.7
# Copy local code to the container image.
COPY ./my_src /var/www/html/my_src
VOLUME /var/www/html/my_src
And, yaml is below.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: test
spec:
...snip...
spec:
containers:
- name: server-container
image: "Server Container image"
ports:
...snip...
volumeMounts:
- name: src-volume
mountPath: /var/www/html/my_src
- name: src-container
image: "Source Container Image"
volumes:
- name: src-volume
hostPath:
path: /var/www/html/my_src
But Source Container "CrashLoopBackOff" occured.
and nothing log is output.
This is not a feature of Kubernetes. There is an old FlexVolume plugin that implements the same behavior as Docker, but it isn’t recommended. You can use an initContainer to copy from the data container into a volume like an emptyDir.

Kubernetes docker volume mounting option

I have a docker image with the option for property file like,
CMD java -jar /opt/test/test-service.war
--spring.config.location=file:/conf/application.properties
I use the -v volume mount in my docker run command as follows.
-v /usr/xyz/props/application.properties:/conf/application.properties
I am not sure how to achieve the same thing in Kubernetes.
I use minikube to run kubernetes in my local mac.
That should be an host path volume, illustrated with this example pod.
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
# directory location on host
path: /data
# this field is optional
type: Directory

Resources