Persistance of Linux Users in Kubernetes Pods

Problem statement:

Linux users which are dynamically created in Kubernetes Containers are not persistant. Therefore, whenever a Kubernetes Pod gets restarted, the dynamically created users are lost.

For example, if you want to run multiple vhosts in a Kubernetes Container under separate UIDs and GIDs with apache2-mpm-itk (which is an MPM – Multi-Processing Module for the Apache web server), a solution for persisting Linux users like the following is required:

Solution:

This solution desribes how to survive Kubernetes Pod restarts by dynamically recreating Linux users in a Kubernetes container whenever a new pod is created.

  1. Create a Kubernetes ConfigMap (or Secret) for storing custom users:
    apiVersion: v1
    kind: ConfigMap
    metadata:
     name: my-linux-users
    data:
     linux-users: ""
  2. Create a script which reads the custom users from the ConfigMap mounted in /etc/linux-users and which recreates the users when the pod is restarted. Store the script in another Kubernetes ConfigMap as follows:
    apiVersion: v1
    kind: ConfigMap
    metadata:
     name: my-sync-script
    data:
     install-linux-users.sh: |
       # Install existing linux users mounted from configmap in /etc/linux-users - file
       echo "Install Linux Users..."
       cat /etc/linux-users | awk -F ":" '{ system("groupadd "$1""); system("useradd -c "$5" -s /usr/sbin/nologin -d "$6" -m -g "$4" "$1"")}'
  3. Mount the Kubernetes ConfigMaps in your StatefulSet (or Deployment) where your container resides (excerpt)
    apiVersion: apps/v1
    kind: StatefulSet
    spec:
     containers:
     - image: ...
       name: ...
       volumeMounts:
       - name: linux-users
         mountPath: /etc/linux-users
         subPath: linux-users
         readOnly: true
       - name: install-conf
         mountPath: /usr/local/bin/install-linux-users.sh
         subPath: install-linux-users.sh
         readOnly: true
     volumes:
     - name: linux-users
         configMap:
         name: my-linux-users
         items:
         - key: www-users
           path: www-users
     - name: install-conf
         configMap:
         name: my-sync-script
         items:
         - key: install-linux-users.sh
           path: install-linux-users.sh
  4.  Hook into the postStart – Event when a container is created and run the script which recreates the users
    ....
     lifecycle:
       postStart:
         exec:
           command:
           - "/bin/bash"
           - "-eu"
           - "/usr/local/bin/install-linux-users.sh"
  5. Whenever you create a Linux user in your Kubernetes container, get a custom user list from the /etc/passed -file and save in a temp directory.
     # Create linux user
     groupadd ${WWW_GROUP}"
     useradd -c ${WWW_COMMENT} -s /bin/false -d /home/${LINUX_USER} -m -g ${WWW_GROUP} ${WWW_USER}"
     # Save custom linux-users (filtered by a common comment) in a temp directory.
     grep ${WWW_COMMENT} /etc/passwd >${LINUX_USERS_FILE}
  6. Get the list of your linux users from the container
    kubectl cp ${NAMESPACE}/${WEBSERVER_POD}:${LINUX_USERS_FILE} ${LOCAL_LINUX_USERS_FILE} -c ${WEBSERVER_CONTAINER}
  7. # Update the configmap with the linux-users – file
    kubectl create configmap my-linux-users --namespace=${NAMESPACE} --from-file=${LOCAL_LINUX_USERS_FILE} --save-config -o=yaml --dry-run | kubectl apply -f -

 

Need further support or Kubernetes Consulting?

Please checkout our Consulting hours.

You don’t want to go into technical details anymore?

Check out the Blue Antoinette Commerce Cloud, which is built on and abstracts away the complexities of Kubernetes.