I'm attempting to create a Kubernetes CronJob to run an application every minute.
A prerequisite is that I need to get my application code onto the container that runs within the CronJob. I figure that the best way to do so is to use a persistent volume, a pvclaim, and then defining the volume and mounting it to the container. I've done this successfully with containers running within a Pod, but it appears to be impossible within a CronJob? Here's my attempted configuration:
apiVersion: batch/v2alpha1 kind: CronJob metadata: name: update_db spec: volumes: - name: application-code persistentVolumeClaim: claimName: application-code-pv-claim schedule: "*/1 * * * *" jobTemplate: spec: template: spec: containers: - name: update-fingerprints image: python:3.6.2-slim command: ["/bin/bash"] args: ["-c", "python /client/test.py"] restartPolicy: OnFailure
The corresponding error:
error: error validating "cron-applications.yaml": error validating data: found invalid field volumes for v2alpha1.CronJobSpec; if you choose to ignore these errors, turn validation off with --validate=false
I can't find any resources that show that this is possible. So, if not possible, how does one solve the problem of getting application code into a running CronJob?
Kubernetes Volumes and volumeMounts The container data in a Pod is deleted or lost when a container crashes or restarts, but when you use a volume, the new container can pick up the data at the state before the container crashes.
To check Cronjob logs, you can list down the cronjob pod and get the logs from the pods in running state or from the finished pods.
Kubernetes CronJobs As the documentation explains, they are useful for periodic and recurring tasks, like running backups, sending emails, or scheduling individual tasks for a specific time, such as when your cluster is likely to be idle.
Mounting the host filesystem into a container as a volume should keep you up at night if you work with Kubernetes. Let me explain why. What is a “volume”? Since containers should be ephemeral and stateless, they need some way to save data outside of the container.
After a container is restarted, the new container can see all the files that were written to the volume by the previous container. Also, if a pod contains multiple containers, the volume can be used by all of them at once. Now you must have a basic idea on Kubernetes Volumes.
A volume can be declared in a pod’s Kubernetes yaml manifest. You can specify .spec.volumes along with .spec.containers [*].volumeMounts to specify what kind of volume it is, and where to mount it inside of the container. Here’s an example of a pod that creates a container that mounts the host’s root directory to /host inside of the container.
One problem is the loss of files when a container crashes. The kubelet restarts the container but with a clean state. A second problem occurs when sharing files between containers running together in a Pod . The Kubernetes volume abstraction solves both of these problems. Familiarity with Pods is suggested.
A CronJob uses a PodTemplate as everything else based on Pods and can use Volumes. You placed your Volume specification directly in the CronJobSpec instead of the PodSpec, use it like this:
apiVersion: batch/v1beta1 kind: CronJob metadata: name: update-db spec: schedule: "*/1 * * * *" jobTemplate: spec: template: spec: containers: - name: update-fingerprints image: python:3.6.2-slim command: ["/bin/bash"] args: ["-c", "python /client/test.py"] volumeMounts: - name: application-code mountPath: /where/ever restartPolicy: OnFailure volumes: - name: application-code persistentVolumeClaim: claimName: application-code-pv-claim
For the other question in there: "how does one solve the problem of getting application code into a running CronJob?"
You build your own image that contains the code. This is how it is normally done.
FROM python:3.6.2-slim ADD test.py /client/test.py CMD ['python','-c','/client/test.py']
Build and push to the docker registry.
docker build -t myorg/updatefingerprints docker push myorg/updatefingerprints
Use this image in the descriptor.
apiVersion: batch/v2alpha1 kind: CronJob metadata: name: update_db spec: volumes: - name: application-code persistentVolumeClaim: claimName: application-code-pv-claim schedule: "*/1 * * * *" jobTemplate: spec: template: spec: containers: - name: update-fingerprints image: myorg/update-fingerprints imagePullPolicy: Always restartPolicy: OnFailure
This requires thinking quite differently about configuration management and version control.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With