<p>I am testing lifecycle hooks, and post-start works pretty well, but I think pre-stop never gets executed. There is another <a href="https://stackoverflow.com/questions/49670761/prestop-hook-in-kubernetes-never-gets-executed">answer</a>, but it is not working, and actually if it would work, it would contradict k8s documentation. So, from the docs:</p>
<blockquote>
<p>PreStop</p>
<p>This hook is called immediately before a container is terminated due
to an <strong>API request</strong> or management event such as liveness probe failure,
preemption, resource contention and others. A call to the preStop hook
fails if the container is already in terminated or completed state.</p>
</blockquote>
<p>So, the API request makes me think I can simply do <code>kubectl delete pod POD</code>, and I am good.</p>
<p>More from the docs (<a href="https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods" rel="nofollow noreferrer">pod shutdown process</a>):</p>
<blockquote>
<p>1.- User sends command to delete Pod, with default grace period (30s)</p>
<p>2.- The Pod in the API server is updated with the time beyond which the Pod is considered “dead” along with the grace period.</p>
<p>3.- Pod shows up as “Terminating” when listed in client commands</p>
<p>4.- (simultaneous with 3) When the Kubelet sees that a Pod has been marked as terminating because the time in 2 has been set, it begins the pod shutdown process.</p>
<p>4.1.- If one of the Pod’s containers has defined a preStop hook, it is invoked inside of the container. If the preStop hook is still running after the grace period expires, step 2 is then invoked with a small (2 second) extended grace period.</p>
<p>4.2.- The container is sent the TERM signal. Note that not all containers in the Pod will receive the TERM signal at the same time and may each require a preStop hook if the order in which they shut down matters.</p>
<p>...</p>
</blockquote>
<p>So, since when you do <code>kubectl delete pod POD</code>, the pod gets on <code>Terminating</code>, I assume I can do it.</p>
<p>From the other answer, I can't do this, but the way is to do a rolling-update. Well, I tried in all possible ways and it didn't work either.</p>
<p>My tests:</p>
<p>I have a deployment:</p>
<pre><code>apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-deploy
spec:
  replicas: 1
  template:
    metadata:
      name: lifecycle-demo
      labels:
        lifecycle: demo
    spec:
      containers:
      - name: nginx
        image: nginx
        lifecycle:
          postStart:
            exec:
              command:
              - /bin/sh 
              - -c
              - echo &quot;Hello at&quot; `date` &gt; /usr/share/post-start
          preStop:
            exec:
              command:
              - /bin/sh&quot;
              - -c
              - echo &quot;Goodbye at&quot; `date` &gt; /usr/share/pre-stop
        volumeMounts:
        - name: hooks
          mountPath: /usr/share/
      volumes:
      - name: hooks
        hostPath:
          path: /usr/hooks/
</code></pre>
<p>I expect the <code>pre-stop</code> and <code>post-start</code> files to be created in <code>/usr/hooks/</code>, on the host (node where the pod is running). post-start is there, but pre-stop, never.</p>
<ul>
<li>I tried <code>kubectl delete pod POD</code>, and it didn't work.</li>
<li>I tried <code>kubectl replace -f deploy.yaml</code>, with a different image, and when I do <code>kubectl get rs</code>, I can see the new replicaSet created, but the file isn't there.</li>
<li>I tried <code>kubectl set image ...</code>, and again, I can see the new <code>replicaSet</code> created, but the file isn't there.</li>
<li>I even tried putting them in a completely separated volumes, as I thought may be when I kill the pod and it gets re-created it re-creates the folder where the files should be created, so it deletes the folder and the pre-stop file, but that was not the case.
Note: It always get re-created on the same node. I made sure on that.</li>
</ul>
<p>What I have not tried is to bomb the container and break it by setting low CPU limit, but that's not what I need.</p>
<p>Any idea what are the circumstances under which <code>preStop</code> hook would get triggered?</p>

<p>Posting this as community wiki for a better visibility.</p>
<blockquote>
<p>There is a typo in the second &quot;/bin/sh&quot;; for preStop. There is an extra double quote (&quot;). It was letting me to create the deployment, but was the cause it was not creating the file. All works fine now.</p>
</blockquote>
<p>The exact point where the issue lied was here:</p>
<pre class="lang-yaml prettyprint-override"><code>          preStop:
            exec:
              command:
              - /bin/sh&quot; # &lt;- this quotation
              - -c
              - echo &quot;Goodbye at&quot; `date` &gt; /usr/share/pre-stop
</code></pre>
<p><strong>To be correct it should look like that:</strong></p>
<pre class="lang-yaml prettyprint-override"><code>          preStop:
            exec:
              command:
              - /bin/sh
              - -c
              - echo &quot;Goodbye at&quot; `date` &gt; /usr/share/pre-stop
</code></pre>
<hr />
<p>For the time of writing this community wiki post, this <code>Deployment</code> manifest is outdated. Following changes were needed to be able to run this manifest:</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: good-deployment
spec:
  selector:
    matchLabels:
      lifecycle: demo 
  replicas: 1
  template:
    metadata:
      labels:
        lifecycle: demo
    spec:
      containers:
      - name: nginx
        image: nginx
        lifecycle:
          postStart:
            exec:
              command:
              - /bin/sh 
              - -c
              - echo &quot;Hello at&quot; `date` &gt; /usr/share/post-start
          preStop:
            exec:
              command:
              - /bin/sh
              - -c
              - echo &quot;Goodbye at&quot; `date` &gt; /usr/share/pre-stop
        volumeMounts:
        - name: hooks
          mountPath: /usr/share/
      volumes:
      - name: hooks
        hostPath:
          path: /usr/hooks/
</code></pre>
<p>Changes were following:</p>
<h3>1. <code>apiVersion</code></h3>
<pre><code>+--------------------------------+---------------------+
|               Old              |          New        |
+--------------------------------+---------------------+
| apiVersion: extensions/v1beta1 | apiVersion: apps/v1 |
+--------------------------------+---------------------+
</code></pre>
<p>StackOverflow answer for more reference:</p>
<ul>
<li><em><a href="https://stackoverflow.com/a/58482194/12257134">Stackoverflow.com: Questions: No matches for kind “Deployment” in version extensions/v1beta1
</a></em></li>
</ul>
<h3>2. <code>selector</code></h3>
<p>Added <code>selector</code> section under <code>spec</code>:</p>
<pre><code>spec:
  selector:
    matchLabels:
      lifecycle: demo 
</code></pre>
<p>Additional links with reference:</p>
<ul>
<li><em><a href="https://serverfault.com/a/917359/545585">What is spec - selector - matchLabels used for while creating a deployment?</a></em></li>
<li><em><a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#selector" rel="nofollow noreferrer">Kubernetes.io: Docs: Concepts: Workloads: Controllers: Deployment: Selector</a></em></li>
</ul>
