0

I would like to create a kubernetes CronJob scheduler which can invoke .netcore console application every minute.

CronJob Spec [cronjob-poc.yml]:

kind: CronJob

metadata:

  name: cronjob-poc

spec:

  schedule: "*/1 * * * *" #Every Minute

  jobTemplate:

    spec:

      template:

        spec:

          containers:

          - name: cronjob-poc

            image: cronjobpoc:dev

            command: ["/usr/local/bin/dotnet", "/app/CronJobPoc.dll"]

          restartPolicy: OnFailure

Kind Commands:

kind create cluster --name=cronjob-poc

kind load docker-image cronjobpoc:dev --name=cronjob-poc

kubectl apply -f .\cronjob-poc.yml

.netcore is a very simple app which just prints hello

using System;

namespace CronJobPoc{

    class Program{

        static void Main(string[] args)
        {
            Console.WriteLine($"{DateTime.Now} - Hello World!");
        }
    }
}

Docker File:

FROM mcr.microsoft.com/dotnet/core/runtime:3.1-buster-slim AS base    
WORKDIR /app    
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build    
WORKDIR /src    
COPY ["CronJobPoc/CronJobPoc.csproj", "CronJobPoc/"]    
RUN dotnet restore "CronJobPoc/CronJobPoc.csproj"    
COPY . .    
WORKDIR "/src/CronJobPoc"    
RUN dotnet build "CronJobPoc.csproj" -c Release -o /app/build    
FROM build AS publish    
RUN dotnet publish "CronJobPoc.csproj" -c Release -o /app/publish    
FROM base AS final    
WORKDIR /app    
COPY --from=publish /app/publish .    
ENTRYPOINT ["dotnet", "CronJobPoc.dll"]

When I do kubectl get pods I see below information.

NAME                           READY   STATUS             RESTARTS   AGE

cronjob-poc-1589463060-9dp8p   0/1     CrashLoopBackOff   4          2m51s

When I try to see logs using kubectl logs cronjob-poc-1589463060-9dp8p I do not see anything. The command returns empty.

Not sure how to see the logs. There is something wrong but not sure what?

I am expecting to see the output " - Hello World!" somewhere in the log. Not sure how to check what went wrong and where can the logs with proper error messages can be seen.

Any quick help on this would be highly appreciated.

I also tried using command argument as shown below in cronjob-poc.yml. I get CrashLoopBackOff status for the pod

command:
- /bin/sh
- -c
- echo Invoking CronJobPoc.dll ...; /usr/local/bin/dotnet CronJobPoc.dll

When I try to check the log using kubectl logs , I see /bin/sh: 1: /usr/local/bin/dotnet: not found

Vit
  • 7,740
  • 15
  • 40
userpkp
  • 21
  • 1
  • 3
  • Any quick help or suggestion would be highly appreciated. I need to design couple of schedulers using kubernetes cronjob and this is becoming kind of blocker. – userpkp May 15 '20 at 10:20

2 Answers2

2

You could simplify the Dockerfile a bit. Here's an example I use in my cron job netcore apps:

# Copy csproj and restore as layer 1
FROM microsoft/dotnet:2.1-sdk-alpine AS build
ARG NUGET=https://api.nuget.org/v3/index.json
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore --source $NUGET

# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out

# Build runtime image
FROM microsoft/dotnet:2.1-runtime-alpine AS final
WORKDIR /app
COPY --from=build /app/out .
CMD ["dotnet", "Custom.MetricScraper.dll"]

It's 3 steps, slightly easier to read. You'll notice the difference is that instead of ENTRYPOINT I'm using CMD at the end. You can modify this to fit your project name and netcore 3.1.

Here's the corresponding YAML:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: metric-scraper-job
  labels:
    app: metric-scraper
spec: # Cron job wrapper around a job
  schedule: "* * * * *"
  jobTemplate:
    spec: # Job definition
      template:
        metadata:
          labels:
            app: metric-scraper
            is-cron: "true"
        spec: # Pod definition
          containers:
          - name: metric-scraper
            image: metricscraper:latest
            imagePullPolicy: IfNotPresent
            env:
              - name: ASPNETCORE_ENVIRONMENT
              value: Production
          restartPolicy: Never
      backoffLimit: 2

This YAML definition will run the image metricscraper:latest every minute.

One thing I noticed though about cron jobs in k8s is that the pods don't get cleaned up (at least on my 1.14 cluster). A workaround is setting a pod limit on a namespace via resourcequotas and sticking the cron jobs in there. Hope this helps!

Ainxty
  • 63
  • 5
  • Thanks for your response @Ainxty.. I already got this issue fixed. There was a problem, I was trying to docker this using Visual Studio which was not installing sdk. When I dockered it manually it worked. Also in the command I simply used 'dotnet CronJobPoc.dll' as dotnet was already there in the path. – userpkp May 21 '20 at 04:31
  • Looking at your solution, I am wondering if the application runs the first time you deploy to a K8s cluster, or is that based on the scaling attribute? And then when the cronjob YAML is deployed, it scales up to 1, runs and then scales down to 0 after completion? – Pavel Brun May 03 '22 at 21:10
2

I was trying to dockerize a dotnetcore app using Visual Studio which was not installing the sdk. When I dockerized it manually using the command docker build -t cronjobpoc ., it worked.

Also in the shell command I simply used dotnet CronJobPoc.dll as dotnet is already in the path

command:

/bin/sh -c echo Invoking CronJobPoc.dll ...; dotnet CronJobPoc.dll
MrE
  • 19,584
  • 12
  • 87
  • 105
userpkp
  • 21
  • 1
  • 3