DEV Community

Cover image for 2.Deploy Lamp Stack on Kubernetes Cluster
Thu Kha Kyawe
Thu Kha Kyawe

Posted on

2.Deploy Lamp Stack on Kubernetes Cluster

Lab Information

The Nautilus DevOps team want to deploy a PHP website on Kubernetes cluster. They are going to use Apache as a web server and Mysql for database. The team had already gathered the requirements and now they want to make this website live. Below you can find more details:

1) Create a config map php-config for php.ini with variables_order = "EGPCS" data.

2) Create a deployment named lamp-wp.

3) Create two containers under it. First container must be httpd-php-container using image webdevops/php-apache:alpine-3-php7 and second container must be mysql-container from image mysql:5.6. Mount php-config configmap in httpd container at /opt/docker/etc/php/php.ini location.

4) Create kubernetes generic secrets for mysql related values like myql root password, mysql user, mysql password, mysql host and mysql database. Set any values of your choice.

5) Add some environment variables for both containers:

a) MYSQL_ROOT_PASSWORD, MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD and MYSQL_HOST. Take their values from the secrets you created. Please make sure to use env field (do not use envFrom) to define the name-value pair of environment variables.

6) Create a node port type service lamp-service to expose the web application, nodePort must be 30008.

7) Create a service for mysql named mysql-service and its port must be 3306.

8) We already have /tmp/index.php file on jump_host server.

a) Copy this file into httpd container under Apache document root i.e /app and replace the dummy values for mysql related variables with the environment variables you have set for mysql related parameters. Please make sure you do not hard code the mysql related details in this file, you must use the environment variables to fetch those values.

b) You must be able to access this index.php on node port 30008 at the end, please note that you should see Connected successfully message while accessing this page.

Note:

The kubectl utility on jump_host has been configured to work with the kubernetes cluster.


Lab Solutions

Step 1: Create the ConfigMap for php.ini

First, create the php-config ConfigMap with the required php.ini setting:

kubectl create configmap php-config --from-literal=php.ini='variables_order = "EGPCS"'
Enter fullscreen mode Exit fullscreen mode

Verify the ConfigMap was created:

kubectl get configmap php-config -o yaml
Enter fullscreen mode Exit fullscreen mode

ဋ Step 2: Create MySQL Secrets

Create a generic secret for MySQL credentials:

kubectl create secret generic mysql-secrets \
  --from-literal=mysql-root-password=rootpass123 \
  --from-literal=mysql-user=wpuser \
  --from-literal=mysql-password=wppass123 \
  --from-literal=mysql-database=wordpress \
  --from-literal=mysql-host=mysql-service
Enter fullscreen mode Exit fullscreen mode

Verify the secret:

kubectl get secret mysql-secrets -o yaml
Enter fullscreen mode Exit fullscreen mode

Step 3: Create the Deployment

Create a file named lamp-wp-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: lamp-wp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: lamp-wp
  template:
    metadata:
      labels:
        app: lamp-wp
    spec:
      containers:
      - name: httpd-php-container
        image: webdevops/php-apache:alpine-3-php7
        ports:
        - containerPort: 80
        volumeMounts:
        - name: php-config
          mountPath: /opt/docker/etc/php/php.ini
          subPath: php.ini
        - name: app-volume
          mountPath: /app
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secrets
              key: mysql-root-password
        - name: MYSQL_DATABASE
          valueFrom:
            secretKeyRef:
              name: mysql-secrets
              key: mysql-database
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              name: mysql-secrets
              key: mysql-user
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secrets
              key: mysql-password
        - name: MYSQL_HOST
          valueFrom:
            secretKeyRef:
              name: mysql-secrets
              key: mysql-host
      - name: mysql-container
        image: mysql:5.6
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secrets
              key: mysql-root-password
        - name: MYSQL_DATABASE
          valueFrom:
            secretKeyRef:
              name: mysql-secrets
              key: mysql-database
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              name: mysql-secrets
              key: mysql-user
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secrets
              key: mysql-password
      volumes:
      - name: php-config
        configMap:
          name: php-config
      - name: app-volume
        emptyDir: {}
Enter fullscreen mode Exit fullscreen mode

Apply the deployment:

kubectl apply -f lamp-wp-deployment.yaml
Enter fullscreen mode Exit fullscreen mode

Step 4: Create the Services

Create a file named services.yaml:

apiVersion: v1
kind: Service
metadata:
  name: lamp-service
spec:
  type: NodePort
  selector:
    app: lamp-wp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30008
---
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  selector:
    app: lamp-wp
  ports:
    - protocol: TCP
      port: 3306
      targetPort: 3306
Enter fullscreen mode Exit fullscreen mode

Apply the services:

kubectl apply -f services.yaml
Enter fullscreen mode Exit fullscreen mode

Step 5: Prepare and Copy index.php

First, let's check the original index.php file:

cat /tmp/index.php
Enter fullscreen mode Exit fullscreen mode

Output

Now, let's update modified version that uses environment variables. Create a new file /tmp/index-modified.php:

<?php
$servername = getenv("MYSQL_HOST");
$username = getenv("MYSQL_USER");
$password = getenv("MYSQL_PASSWORD");
$dbname = getenv("MYSQL_DATABASE");

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);

// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}
echo "Connected successfully";
?>
Enter fullscreen mode Exit fullscreen mode

If permission issues occur, fix them:

sudo chmod 777 /tmp/index.php
Enter fullscreen mode Exit fullscreen mode

Password: mjolnir123

Step 6: Copy index.php to Apache Container

kubectl cp /tmp/index.php lamp-wp-7ccc97bf65-6nhv6:/app/index.php -c httpd-php-container
Enter fullscreen mode Exit fullscreen mode
Explanation of Commands:

    Command 1: POD=$(kubectl get pod -l app=lamp-app -o jsonpath='{.items[0].metadata.name}')
        Purpose: Retrieves the name of the first pod with the label app=lamp-app and stores it in the POD variable.
        Details:
            kubectl get pod: Lists pods in the current namespace.
            -l app=lamp-app: Filters pods with the label app=lamp-app, matching the deployment's selector.
            -o jsonpath='{.items[0].metadata.name}': Extracts the name of the first pod using JSONPath.
            POD=$(): Stores the pod name (e.g., lamp-wp-5f7b8d4c5-xyz12) in the POD variable.
        Why Needed: Pod names are dynamically generated by Kubernetes, so this command dynamically retrieves the correct pod name for the file copy operation.

    Command 2: kubectl cp /tmp/index.php $POD:/app -c httpd-php-container
        Purpose: Copies the index.php file from the jump host's /tmp directory to the /app directory in the httpd-php-container of the specified pod.
        Details:
            kubectl cp: Copies files between the local filesystem and a container.
            /tmp/index.php: Source file on the jump host.
            $POD:/app: Destination path, where $POD is the pod name and /app is the Apache document root.
            -c httpd-php-container: Specifies the target container within the pod (since the pod has both httpd-php-container and mysql-container).
        Why Needed: The index.php file contains the PHP code for the website, which must be placed in the Apache document root to make the application functional.
Enter fullscreen mode Exit fullscreen mode

Step 7: Verify Deployment and Services

kubectl get configmap php-config
kubectl get secret mysql-secrets
kubectl get deploy lamp-wp
kubectl get pods
kubectl get svc
Enter fullscreen mode Exit fullscreen mode

Step 8: Verify Application Accessibility

Access the Application:

Click on the App button in the lab interface.


Resources & Next Steps
📦 Full Code Repository: KodeKloud Learning Labs
💬 Join Discussion: DEV Community - Share your thoughts and questions
💼 Let's Connect: LinkedIn - I'd love to connect with you

Credits
• All labs are from: KodeKloud
• I sincerely appreciate your provision of these valuable resources.

Top comments (0)