Deploy Lamp Stack on Kubernetes Cluster - ConfigMap Mount Error

I’m getting config map mounting error no matter how many times I try.

Warning Failed 0s (x3 over 16s) kubelet Error: failed to create containerd task: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting “/var/lib/kubelet/pods/ad2a959b-2707-4e00-9939-5beadbffee9c/volumes/kubernetes.io~configmap/php-config-volume” to rootfs at “/opt/docker/etc/php/php.ini”: mount /var/lib/kubelet/pods/ad2a959b-2707-4e00-9939-5beadbffee9c/volumes/kubernetes.io~configmap/php-config-volume:/opt/docker/etc/php/php.ini (via /proc/self/fd/6), flags: 0x5001: not a directory: unknown

spec:
  containers:
  - image: webdevops/php-apache:alpine-3-php7
    name: httpd-php-container
    ports:
    - containerPort: 80
    volumeMounts:
    - name: php-config-volume
      mountPath: /opt/docker/etc/php/php.ini
  - image: mysql:5.6
    name: mysql-container
  volumes:
  - name: php-config-volume
    configMap:
      name: php-config

apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: null
name: php-config
data:
php.ini: |
variables_order = “EGPCS”

Tried using subPath too, but then all I see is failed to restart container and nothing else. I have been at it for few days now, can someone check if my code is incorrect or there is something wrong with the task itself?

Hi @pre.infra17

The error is here

      mountPath: /opt/docker/etc/php/php.ini

mountPath must be a directory not a file, since the file php.ini will be created by the configmap when it mounts

      mountPath: /opt/docker/etc/php

Then the file will mount

controlplane $ k exec -it httpd-php-container -- cat /opt/docker/etc/php/php.ini 
variables_order = "EGPCS"

However fixing the configmap is not the only issue. Once it mounts, the pod will crashloop - probably because you need to do more configuration of apache/php

I got the above test to work by giving the container a sleep command to run instead of whatever its default command is.

I still get the same error.

Code ###

apiVersion: v1
kind: Pod
metadata:
name: lamp-wp
labels:
app: lamp-wp
spec:
containers:
- name: httpd-php-container
image: webdevops/php-apache:alpine-3-php7
command: [“sleep”,“3600”]
ports:
- containerPort: 80
volumeMounts:
- name: php-config-volume
mountPath: /opt/docker/etc/php
subPath: php.ini
- name: mysql-container
image: mysql:5.6
ports:
- containerPort: 3306
volumes:
- name: php-config-volume
configMap:
name: php-config

Events:
Type Reason Age From Message


Normal Scheduled 5m9s default-scheduler Successfully assigned default/lamp-wp to kodekloud-control-plane
Normal Pulling 5m8s kubelet Pulling image “webdevops/php-apache:alpine-3-php7”
Normal Pulled 4m56s kubelet Successfully pulled image “webdevops/php-apache:alpine-3-php7” in 12.013420824s (12.013438626s including waiting)
Normal Pulling 4m56s kubelet Pulling image “mysql:5.6”
Normal Pulled 4m45s kubelet Successfully pulled image “mysql:5.6” in 10.827392783s (10.827411349s including waiting)
Normal Created 4m45s kubelet Created container mysql-container
Normal Started 4m45s kubelet Started container mysql-container
Normal Created 4m2s (x4 over 4m56s) kubelet Created container httpd-php-container
Warning Failed 4m1s (x4 over 4m56s) kubelet Error: failed to create containerd task: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting “/var/lib/kubelet/pods/673307f5-1e00-4c93-8f28-f178c1cc8fe3/volume-subpaths/php-config-volume/httpd-php-container/0” to rootfs at “/opt/docker/etc/php”: mount /var/lib/kubelet/pods/673307f5-1e00-4c93-8f28-f178c1cc8fe3/volume-subpaths/php-config-volume/httpd-php-container/0:/opt/docker/etc/php (via /proc/self/fd/6), flags: 0x5001: not a directory: unknown
Normal Pulled 3m21s (x4 over 4m44s) kubelet Container image “webdevops/php-apache:alpine-3-php7” already present on machine
Warning BackOff 0s (x23 over 4m43s) kubelet Back-off restarting failed container httpd-php-container in pod lamp-wp_default(673307f5-1e00-4c93-8f28-f178c1cc8fe3)

It does not require subPath

And please

use code blocks
when posting code

image

I don’t see code indentation option.

/tmp/index.php on jump host is incorrect. This is what I see.

It is missing ?> towards the end which took me a while to figure out.

I get 502 bad gateway error, I’ve got all resources up and running, don’t see anything in logs. Also index.php file disappears on container every couple of minutes and I’m thrown out of the container with error 137.

Unable to upload all code files, new user limit.

First, you should use variables in php file.

$dbname = $_ENV["MYSQL_DATABASE"];
$dbuser = $_ENV["MYSQL_USER"];
$dbpass = $_ENV["MYSQL_PASSWORD"];
$dbhost = $_ENV["MYSQL_HOST"];

Second, to copy to particular container in pod, you should use something like that:
kubectl cp /tmp/index.php lamp-wp-7d46b7c945-zsh8d:/app/index.php -c httpd-php-container
Same, when you like to exec to it:
kubectl exec -it lamp-wp-7d46b7c945-zsh8d -c httpd-php-container -- /bin/sh
And try to use this yaml for lamp:

apiVersion: v1
kind: Secret
metadata:
  name: mysql-secret
type: Opaque
data:
  mysql-root-password: cm9vdHBhc3M=
  mysql-database: c3FsYmFzZQ==
  mysql-user: dXNlcg==
  mysql-password: dXNlcnBhc3M=
  mysql-host: bXlzcWwtY29udGFpbmVy
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: php-config
data:
  php.ini: |
    variables_order="EGPCS"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: lamp-wp
  labels:
    app: httpd 
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpd 
  template:
    metadata:
      labels:
        app: httpd 
    spec:
      hostname: mysql-container
      containers:
        - name: httpd-php-container
          image: webdevops/php-apache:alpine-3-php7
          ports:
            - containerPort: 80
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: mysql-root-password
            - name: MYSQL_DATABASE
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: mysql-database
            - name: MYSQL_USER
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: mysql-user
            - name: MYSQL_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: mysql-password
            - name: MYSQL_HOST
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: mysql-host
          volumeMounts:
          - name: php-config
            mountPath: /opt/docker/etc/php/php.ini
            subPath: php.ini
        - name: mysql-container
          image: mysql:5.6
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: mysql-root-password
            - name: MYSQL_DATABASE
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: mysql-database
            - name: MYSQL_USER
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: mysql-user
            - name: MYSQL_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: mysql-password
            - name: MYSQL_HOST
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: mysql-host
          ports:
            - containerPort: 3306
      volumes:
        - name: php-config
          configMap:
            name: php-config
---
apiVersion: v1
kind: Service
metadata:
  name: lamp-service
spec:
  selector:
    app: httpd 
  type: NodePort
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30008
---
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  selector:
    app: httpd 
  ports:
    - protocol: TCP
      port: 3306
      targetPort: 3306  

I tried with same code in the past with no luck. Supplied sql values you shared and that didn’t help. I’ve been at this for a while now, not sure what I’m missing.

thor@jump_host ~$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/lamp-wp-5466bc994d-n4gm4 2/2 Running 0 7m35s

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 443/TCP 35m
service/lamp-service NodePort 10.96.89.33 80:30008/TCP 14m
service/mysql-service ClusterIP 10.96.23.175 3306/TCP 14m

NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/lamp-wp 1/1 1 1 7m35s

NAME DESIRED CURRENT READY AGE
replicaset.apps/lamp-wp-5466bc994d 1 1 1 7m35s

/app # cat index.php

<?php $dbname = $_ENV["MYSQL_DATABASE"]; $dbuser = $_ENV["MYSQL_USER"]; $dbpass = $_ENV["MYSQL_PASSWORD"]; $dbhost = $_ENV["MYSQL_HOST"]; $connect = mysqli_connect($dbhost, $dbuser, $dbpass) or die("Unable to Connect to '$dbhost'"); $test_query = "SHOW TABLES FROM $dbname"; $result = mysqli_query($test_query); if ($result->connect_error) { die("Connection failed: " . $conn->connect_error); } echo "Connected successfully"; ?>

Also, can you advise why I don’t see code block button on the top like you guys do? My format disappears as soon as I paste the code in the reply window.

You can type 3 backticks ``` on its own line to start code block, then the text you want formatted, then type ``` again on a new line underneath to close it

```
this is code block
```

Will make

this is code block

Thank you. I still see error 502.

Below is my code.

apiVersion: v1
kind: ConfigMap
metadata:
  name: php-config
data:
  php.ini: |
    variables_order = "EGPCS"
apiVersion: v1
kind: Secret
metadata:
  name: sqlsecrets
type: Opaque
data:
  MYSQL_ROOT_PASSWORD: cm9vdHBhc3M=
  MYSQL_DATABASE: c3FsYmFzZQ==
  MYSQL_USER: dXNlcg==
  MYSQL_PASSWORD: dXNlcnBhc3M=
  MYSQL_HOST: bXlzcWwtY29udGFpbmVy
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: lamp-wp
  name: lamp-wp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: lamp-wp
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: lamp-wp
    spec:
      containers:
        - name: httpd-php-container
          image: webdevops/php-apache:alpine-3-php7
          command: ["sleep","600"]
          ports:
          - containerPort: 80
          volumeMounts:
          - name: php-config-volume
            mountPath: /opt/docker/etc/php
          env:
          - name: MYSQL_ROOT_PASSWORD
            valueFrom:
              secretKeyRef:
                name: sqlsecrets
                key: MYSQL_ROOT_PASSWORD
          - name: MYSQL_PASSWORD
            valueFrom:
              secretKeyRef:
                name: sqlsecrets
                key: MYSQL_PASSWORD
          - name: MYSQL_DATABASE
            valueFrom:
              secretKeyRef:
                name: sqlsecrets
                key: MYSQL_DATABASE
          - name: MYSQL_USER
            valueFrom:
              secretKeyRef:
                name: sqlsecrets
                key: MYSQL_USER
          - name: MYSQL_HOST
            valueFrom:
              secretKeyRef:
                name: sqlsecrets
                key: MYSQL_HOST

        - name: mysql-container
          image: mysql:5.6
          ports:
          - containerPort: 3306
          env:
          - name: MYSQL_ROOT_PASSWORD
            valueFrom:
              secretKeyRef:
                name: sqlsecrets
                key: MYSQL_ROOT_PASSWORD
          - name: MYSQL_PASSWORD
            valueFrom:
              secretKeyRef:
                name: sqlsecrets
                key: MYSQL_PASSWORD
          - name: MYSQL_DATABASE
            valueFrom:
              secretKeyRef:
                name: sqlsecrets
                key: MYSQL_DATABASE
          - name: MYSQL_USER
            valueFrom:
              secretKeyRef:
                name: sqlsecrets
                key: MYSQL_USER
          - name: MYSQL_HOST
            valueFrom:
              secretKeyRef:
                name: sqlsecrets
                key: MYSQL_HOST			  
      volumes:
        - name: php-config-volume
          configMap:
            name: php-config
apiVersion: v1
kind: Service
metadata:
  name: lamp-service
spec:
  type: NodePort
  selector:
    app: lamp-wp
  ports:
    - protocol: TCP
      port: 80         # The port on the service (Cluster IP)
      targetPort: 80   # The port on the pods
      nodePort: 30008  # The static port exposed on each node (you can specify your desired port)
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  selector:
    app: lamp-wp
  ports:
    - protocol: TCP
      port: 3306        # The port on the service (Cluster IP)
      targetPort: 3306   # The port on the pods
<?php
$dbname = $_ENV["MYSQL_DATABASE"];
$dbuser = $_ENV["MYSQL_USER"];
$dbpass = $_ENV["MYSQL_PASSWORD"];
$dbhost = $_ENV["MYSQL_HOST"];

$connect = mysqli_connect($dbhost, $dbuser, $dbpass) or die("Unable to Connect to '$dbhost'");

$test_query = "SHOW TABLES FROM $dbname";
$result = mysqli_query($test_query);

if ($result->connect_error) {
   die("Connection failed: " . $conn->connect_error);
}
  echo "Connected successfully"; 
  
?>
thor@jump_host ~$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/lamp-wp-5466bc994d-n4gm4 2/2 Running 0 7m35s

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 443/TCP 35m
service/lamp-service NodePort 10.96.89.33 80:30008/TCP 14m
service/mysql-service ClusterIP 10.96.23.175 3306/TCP 14m

NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/lamp-wp 1/1 1 1 7m35s

NAME DESIRED CURRENT READY AGE
replicaset.apps/lamp-wp-5466bc994d 1 1 1 7m35s

Try to add subPath: php.ini in volumeMounts:

          volumeMounts:
          - name: php-config
            mountPath: /opt/docker/etc/php/php.ini
            subPath: php.ini

And try to add hostname line. Sometimes I have problems with hostname for database container, so I add this line.

Error restarting httpd-php-container when I add subPath.

  Warning  Failed     3s (x4 over 59s)  kubelet            Error: failed to create containerd task: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting "/var/lib/kubelet/pods/60929f3c-1398-45b9-901f-f28b21f1878b/volume-subpaths/php-config-volume/httpd-php-container/0" to rootfs at "/opt/docker/etc/php": mount /var/lib/kubelet/pods/60929f3c-1398-45b9-901f-f28b21f1878b/volume-subpaths/php-config-volume/httpd-php-container/0:/opt/docker/etc/php (via /proc/self/fd/6), flags: 0x5001: not a directory: unknown
  Normal   Pulled     3s (x3 over 45s)  kubelet            Container image "webdevops/php-apache:alpine-3-php7" already present on machine
  Warning  BackOff    2s (x5 over 44s)  kubelet            Back-off restarting failed container httpd-php-container in pod lamp-wp-56b5cf66d8-5v9rc_default(60929f3c-1398-45b9-901f-f28b21f1878b)

Hostname for mysql-container is set to pod name. Are you referring to configuring mysql hostname with in mysql-container using “mysql -h” command?

Do not use subPath. It will not mount.

We already proved the other day how to mount the file. Pod is not failing due to that. It is something else.

Is it this question?

image

Nope, From Level 3 -

Right. I have now been through this and here is the solution.

#1

Create configmap

thor@jump_host ~$ echo 'variables_order = "EGPCS"' > php.ini
thor@jump_host ~$ k create cm php-config --from-file php.ini

#2/#3

thor@jump_host ~$ k create deployment lamp-wp --image webdevops/php-apache:alpine-3-php7 --dry-run=client -o yaml > lamp-wp.yaml
thor@jump_host ~$ vi lamp-wp.yaml 

Now we have to be careful how we mount php.ini. We are putting it into a directory that already exists and contains files and folders, so if we use a simple mount we are going to knock out all the other stuff.
We need to use a subPath mount, AND extra syntax in the volume declaration.

While we are here, also put in the mysql container.

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: lamp-wp
  name: lamp-wp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: lamp-wp
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: lamp-wp
    spec:
      volumes:
      - name: ini
        configMap:
          name: php-config
          items:            #<- This extra syntax to make subPath work properly
          - key: php.ini
            path: php.ini
      containers:
      - image: webdevops/php-apache:alpine-3-php7
        name: httpd-php-container
        volumeMounts:
        - name: ini
          mountPath: /opt/docker/etc/php/php.ini
          subPath: php.ini
      - image: mysql:5.6
        name: mysql-container

#4

CAREFUL - There is a curveball in this one! We cannot use just anything for MYSQL_HOST or the database will not be able to be connected to. Before creating the secret see task #7

thor@jump_host ~$ k create secret generic mysql-config --from-literal MYSQL_ROOT_PASSWORD=paswd --from-literal MYSQL_DATABASE=lampdb --from-literal MYSQL_USER=thor --from-literal MYSQL_PASSWORD=mjolnir123 --from-literal MYSQL_HOST=mysql-service

#5

Mount the secret’s environment variables. Note that I have used an alias/anchor combination here both for less typing and to avoid errors in duplicating the variables to both containers. This should now be the final edit to the deployment YAML

thor@jump_host ~$ vi lamp-wp.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: lamp-wp
  name: lamp-wp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: lamp-wp
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: lamp-wp
    spec:
      volumes:
      - name: ini
        configMap:
          name: php-config
          items:            #<- This extra syntax to make subPath work properly
          - key: php.ini
            path: php.ini
      containers:
      - image: webdevops/php-apache:alpine-3-php7
        name: httpd-php-container
        env: &environment               #<- ANCHOR
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-config
              key: MYSQL_ROOT_PASSWORD
        - name: MYSQL_DATABASE
          valueFrom:
            secretKeyRef:
              name: mysql-config
              key: MYSQL_DATABASE
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              name: mysql-config
              key: MYSQL_USER
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-config
              key: MYSQL_PASSWORD
        - name: MYSQL_HOST
          valueFrom:
            secretKeyRef:
              name: mysql-config
              key: MYSQL_HOST
        volumeMounts:
        - name: ini
          mountPath: /opt/docker/etc/php/php.ini
          subPath: php.ini
      - image: mysql:5.6
        name: mysql-container
        env: *environment               #<- ALIAS (all environment beneath ANCHOR will be repeated here)

#6

Create nodeport service. First run up the deployment that we have so far so we can use imperative commands to create the services

Spin up the deployment - it should run fine.

thor@jump_host ~$ k create -f lamp-wp.yaml

Create YAML file for nodePort service

thor@jump_host ~$ k expose deployment lamp-wp --port 80 --target-port 80 --type NodePort --name lamp-service --dry-run=client -o yaml > lamp-service.yaml

Edit in the correct nodeport

thor@jump_host ~$ vi lamp-service.yaml 
apiVersion: v1
kind: Service
metadata:
  labels:
    app: lamp-wp
  name: lamp-service
spec:
  ports:
  - port: 80
    protocol: TCP 
    targetPort: 80
    nodePort: 30008  #<- Add this
  selector:
    app: lamp-wp
  type: NodePort

Create service

k create -f lamp-service.yaml

#7

Create mysql-service

thor@jump_host ~$ k expose deployment lamp-wp --port 3306 --target-port 3306 --type ClusterIP --name mysql-service
service/mysql-service exposed

No need to create a YAML file for this service, since we don’t need to make additional edits to a ClusterIP service.

#8

Sort out index.php and place in the container

#8a

thor@jump_host ~$ cp /tmp/index.php .
thor@jump_host ~$ vi index.php 

Edit it to look like this

<?php
$dbname = getenv('MYSQL_DATABASE');
$dbuser = getenv('MYSQL_USER');
$dbpass = getenv('MYSQL_PASSWORD');
$dbhost = getenv('MYSQL_HOST');

$connect = mysqli_connect($dbhost, $dbuser, $dbpass) or die("Unable to Connect to '$dbhost'");

$test_query = "SHOW TABLES FROM $dbname";
$result = mysqli_query($test_query);

if ($result->connect_error) {
   die("Connection failed: " . $conn->connect_error);
}
  echo "Connected successfully";
?>

Now copy it into container

thor@jump_host ~$ k get po
NAME                       READY   STATUS    RESTARTS   AGE
lamp-wp-78cfc8c984-vsjc5   2/2     Running   0          18s

Note pod name. We will need it for the next command

k cp -c httpd-php-container index.php lamp-wp-78cfc8c984-vsjc5:/app/index.php

#8b Test it.

image

Thank you, its working now.

I believe the task instructions should be updated for mysql secrets. Choosing random values for mysql parameters doesn’t work.

This is a level 3 task, right?

I spotted immediately that a random value for MYSQL_HOST is not going to work - and no I didn’t have the solution in front of me, I had to work it out too. I think at level 3, people are kind of expected to draw the same conclusion. Hence my statement for #4 above. A level 1 task might explicitly tell you to use the service you create as the mysql host.

The other values indeed can be whatever you want, because the startup for the mysql container will configure them into the mysql server configuration.