<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>

<p>Instead of running <code>schedule:run</code> use K8s kind: Deployment (not Job) and run scheduler as a daemon:</p>
<pre><code>php artisan schedule:work
</code></pre>
<p><a href="https://laravel.com/docs/9.x/scheduling#running-the-scheduler-locally" rel="nofollow noreferrer">https://laravel.com/docs/9.x/scheduling#running-the-scheduler-locally</a></p>
<p>More details:</p>
<p>See: <a href="https://medium.com/@agungdarmanto/how-to-run-a-laravel-application-into-kubernetes-a6d0111dc98d" rel="nofollow noreferrer">https://medium.com/@agungdarmanto/how-to-run-a-laravel-application-into-kubernetes-a6d0111dc98d</a></p>
