Kubernetes initContainers to copy file and execute as part of Lifecycle Hook PostStart

11/19/2021

I am trying to execute some scripts as part of statefulset deployment kind. This script I have added as configmap and I use this as volumeMount inside the pod definition. I use the lifecycle poststart exec command to execute this script. It fails with the permission issue.

based on certain articles, I found that we should copy this file as part of InitContainer and then use that (I am not sure why should we do and what will make a difference) Still, I tried it and that also gives the same error.

Here is my ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-configmap-initscripts
data:
  poststart.sh: |
     #!/bin/bash
     echo "It`s done"

Here is my StatefulSet:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres-statefulset
spec:
  ....
  serviceName: postgres-service
  replicas: 1
  template:
    ...
    spec:
      initContainers:
      - name: "postgres-ghost"
        image: alpine
        volumeMounts:
        - mountPath: /scripts
          name: postgres-scripts
      containers:
      - name: postgres
        image: postgres
        lifecycle:
            postStart:
              exec:
                command: ["/bin/sh", "-c", "/scripts/poststart.sh" ]
        ports:
        - containerPort: 5432
          name: dbport
        ....
        volumeMounts:
        - mountPath: /scripts
          name: postgres-scripts
volumes:
  - name: postgres-scripts
    configMap:
      name: postgres-configmap-initscripts
      items:
      - key: poststart.sh
        path: poststart.sh

The error I am getting:

enter image description here

-- Brijesh Shah
kubernetes
kubernetes-statefulset

1 Answer

11/19/2021

postStart hook will be call at least once but may be call more than once, this is not a good place to run script.

The poststart.sh file that mounted as ConfigMap will not have execute mode hence the permission error.

It is better to run script in initContainers, here's an quick example that do a simple chmod; while in your case you can execute the script instead:

cat << EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  name: busybox
data:
  test.sh: |
    #!/bin/bash
    echo "It's done"
---
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    run: busybox
spec:
  volumes:
  - name: scripts
    configMap:
      name: busybox
      items:
      - key: test.sh
        path: test.sh
  - name: runnable
    emptyDir: {}
  initContainers:
  - name: prepare
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ["ash","-c"]
    args: ["cp /scripts/test.sh /runnable/test.sh && chmod +x /runnable/test.sh"]
    volumeMounts:
    - name: scripts
      mountPath: /scripts
    - name: runnable
      mountPath: /runnable
  containers:
  - name: busybox
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ["ash","-c"]
    args: ["while :; do . /runnable/test.sh; sleep 1; done"]
    volumeMounts:
    - name: scripts
      mountPath: /scripts
    - name: runnable
      mountPath: /runnable
EOF
-- gohm&#39;c
Source: StackOverflow