Today, I am learning how to add a simple cron job to a kubernetes environment. The Cron job will ‘ping’ an endpoint of one of the hosted services every 5 minutes.
What's a Cron job?
A cron job a utility program that lets users schedule tasks to run at a specific time.
Users can determine what kind of task they want to automate and when it should be executed.
Help! I’m new to Kubernetes!
So am I, where to start? This looks like as good a place as any.
OK, so do I even have kubernetes installed? I thought I did when I installed DockerDesktop (Windows 11 machine). But it turns out - I missed the checkbox in the docker settings
Then run the following command kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* docker-desktop docker-desktop docker-desktop
Hello World from K8
Let’s just get a simple hello world working…
Source - https://kubernetes.io/docs/tutorials/hello-minikube/
Lets run the create
command
kubectl create deployment hello-node --image=k8s.gcr.io/echoserver:1.4
This next line then exposes the echoserver to port 8080
kubectl expose deployment hello-node --type=LoadBalancer --port=8080
Now you can browse to the service using localhost:8080
Yay!
Where’s the YAML?
BUT, this isn’t quite what I was expecting… Where is the YAML? Ok, fair enough. We need to recreate this using YAML this time.
This is a great video “Kubernetes Tutorial for Beginners” which helped me understand how to get things working.
Deployment File
First we define the myapp.deployment.yaml
file. This is the template for what we are deploying into k8.
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: myapp
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: k8s.gcr.io/echoserver:1.4
ports:
- containerPort: 8080
The file defines what we are deploying called “myapp-deployment”. It is using the container image “k8s.gcr.io/echoserver”. This is being exposed via the port 8080 (via containerPort). The specification is telling kubernetes to spin up 2 replicas (aka Pods).
Service File
Next, we need to create the myapp.service.yaml
file. This defines how the deployed container is wired up in Kubernetes.
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
type: LoadBalancer
allocateLoadBalancerNodePorts: true
externalTrafficPolicy: Cluster
internalTrafficPolicy: Cluster
ports:
- nodePort: 30000
port: 8080
protocol: TCP
targetPort: 8080
This service definition exposes the service to localhost:8080. I had to play around for a bit to get this actually working. The missing bit was around the LoadBalancer
and the targetPort. Internally the Pods are listening to port 8080.
Let’s execute these files.
kubectl apply -f .myapp.deployment.yaml
kubectl apply -f .myapp.service.yaml
OK, so we now have kubernetes running a very simple service across two Pods!
Let’s add a Cron Job
I started with this config from the kubernetes website. This original script just starts a cron job and the task itself just logs to the console.
I changed the original script to use the “buildpack-deps:curl” image. The cron job itself is just a simple curl script with some noise suppression (-sS)
- This runs every minute (* * * * *)
- It simply hits the myapp service on port 8080 with a GET request.
apiVersion: batch/v1
kind: CronJob
metadata:
name: ping
spec:
schedule: "* * * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
metadata:
labels:
app: cronjob
spec:
containers:
- name: ping
image: buildpack-deps:curl
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -ec
- curl -sS http://myapp:8080
restartPolicy: OnFailure
Let’s test the cron job
kubectl apply -f .ping.cron.yaml
From the console we can list the jobs running using kubectl get jobs
kubectl get jobs --watch
NAME COMPLETIONS DURATION AGE
ping-27587963 1/1 5s 2m45s
ping-27587964 1/1 5s 105s
ping-27587965 1/1 5s 45s
From the logs I can see the request being received by the myapp service and I can see the ping job printing out the raw http response.
What’s next?
Well, that was the first time I have played with Kubernetes. I think it is quite amazing what you can do with just some simple scripts. I wonder what real production scripts look like? I can imagine that this would get quite horrible quite quickly if rushed and learning on the job.
All in all? I’m impressed.