# Let a Job finish: turn its log shipper into a native sidecar

> A nightly export Job never completes because its log shipper keeps running. Make the shipper a native sidecar, stable since Kubernetes 1.33.

Level: Intermediate · Topic: Workloads · About 10 minutes
Try it in the browser: https://k8wiz.com/playground/native-sidecar-containers

The playground is a simulated Kubernetes cluster that runs in the browser. kubectl output and errors follow the real ones.

## The situation

The export Job runs a log shipper as a second container next to the exporter. The exporter is done in a few seconds, but the shipper never exits, so the Pod stays Running and the Job never completes.

Native sidecars are stable since Kubernetes 1.33: an init container with `restartPolicy: Always` starts before the main containers, runs next to them, and is stopped once they finish. Turn the shipper into one.

## Objectives

1. See why the Job never completes (`kubectl get pods` and `kubectl get job export`)
2. Make log-shipper a native sidecar (An init container with `restartPolicy: Always`)
3. The export Job completes

## Hints

1. `kubectl get pods` shows the export Pod at 1/2 READY: the exporter has finished and the shipper is still running. `kubectl get job export` stays at 0/1.
2. A Job's Pod template can't be changed. In export-job.yaml, move the log-shipper container under `initContainers:` and give it `restartPolicy: Always`. Then `kubectl delete job export` and `kubectl apply -f export-job.yaml`.
3. READY counts the sidecar. Once the exporter finishes, the kubelet stops the shipper and the Pod ends as Completed.

## Solution

```bash
kubectl get pods
```
```bash
kubectl delete job export
```
```bash
cat <<EOF | kubectl apply -f -
apiVersion: batch/v1
kind: Job
metadata:
  name: export
spec:
  backoffLimit: 0
  template:
    spec:
      restartPolicy: Never
      terminationGracePeriodSeconds: 5
      initContainers:
      - name: log-shipper
        image: busybox:1.37
        restartPolicy: Always
        command: ["sh", "-c", "while true; do echo shipping logs; sleep 5; done"]
      containers:
      - name: export
        image: busybox:1.37
        command: ["sh", "-c", "echo exporting rows; sleep 8; echo export done"]
EOF
```
```bash
kubectl wait --for=condition=complete job/export --timeout=60s
```
```bash
kubectl logs job/export -c log-shipper | head -3
```

## What it teaches

- A second container that never exits keeps a Job's Pod running, so the Job never completes. Native sidecars, alpha in 1.28 and stable in 1.33, fix that.
- A native sidecar is an init container with `restartPolicy: Always`. It starts before the main containers, keeps running (and restarting) next to them, and doesn't block the Pod from finishing.
- When a Job Pod's main containers finish, the kubelet stops its sidecars. A sidecar that ignores SIGTERM holds the Pod until `terminationGracePeriodSeconds` runs out.
- kubectl counts sidecars in the READY column, and the scheduler adds their requests to the Pod's.
