title: Good practice to run 'php artisan schedule:run' for Laravel in Kubernetes
body: <p>I am working on integrating a few Laravel PHP applications into a new Kubernetes architecture, and still struggling on how I can run <code>php artisan schedule:run</code> in a nice manner.</p>
  <p>In the official Laravel manual, we are advised to set up the cronjob like this.</p>
  <pre><code>* * * * * cd /path-to-your-project &amp;&amp; php artisan schedule:run &gt;&gt; /dev/null 2&gt;&amp;1
  </code></pre>
  <p>ref. <a href="https://readouble.com/laravel/5.7/en/scheduling.html" rel="nofollow noreferrer">https://readouble.com/laravel/5.7/en/scheduling.html</a></p>
  <p><strong>Cronjob</strong></p>
  <p>Initially, I came up with the idea of using cronjob in Kubernetes, and it works fine for now but started worried about the current architecture.</p>
  <p>(One deployment for web service, and one cronjob for the task scheduling.)</p>
  <pre><code>---
  apiVersion: batch/v1beta1
  kind: CronJob
  metadata:
    name: cron
    namespace: my-laravel-app
  spec:
    concurrencyPolicy: Replace
    schedule: &quot;*/1 * * * *&quot;
    jobTemplate:
      spec:
        template:
          spec:
            containers:
            - image: my_laravel_app_image:latest
              name: cron
              command: [&quot;php&quot;, &quot;artisan&quot;, &quot;schedule:run&quot;]
              imagePullPolicy: Always
              envFrom:
              - configMapRef:
                  name: laravel-app-config
              - secretRef:
                  name: laravel-app-secret
            restartPolicy: Never
  </code></pre>
  <p>However, since I use <code>concurrencyPolicy: Replace</code> here the pod itself might be terminated even the job is still running (for more than 1 minute). To avoid this issue, I could use the default value <code>concurrencyPolicy: Allow</code> but it introduces another issue - Even I set <code>failedJobsHistoryLimit</code> at 1 and <code>successfulJobsHistoryLimit</code> at 1 the pod associated with the job are not properly terminated in the current running in-house Kubernetes cluster, and it reaches quota limit.</p>
  <pre><code>NAME                        READY   STATUS      RESTARTS   AGE
  pod/test-cronjob-a           0/1     Completed   0          4m30s
  pod/test-cronjob-b           0/1     Completed   0          3m30s
  pod/test-cronjob-c           0/1     Completed   0          2m29s
  pod/test-cronjob-d           0/1     Completed   0          88s
  pod/test-cronjob-e           0/1     Completed   0          28s
  </code></pre>
  <p>ref. <a href="https://github.com/kubernetes/kubernetes/issues/74741#issuecomment-712707783" rel="nofollow noreferrer">https://github.com/kubernetes/kubernetes/issues/74741#issuecomment-712707783</a></p>
  <p>Also, I feel It's a bit tricky to configure the monitoring and logging stack for those one-off jobs.</p>
  <p><strong>Deployment</strong></p>
  <p>Instead of using cronjob, I'm thinking to try to deploy the scheduler as another pod having the cron setting in the container using deployment resource.</p>
  <p>(One deployment for web service, and one deployment for the task scheduling.)</p>
  <p><strong>I just wonder how you guys normally work around this issue in a scalable manner.</strong></p>