Deploy LAMP Stack on Kubernetes

Rajesh PetheRajesh Pethe
4 min read

Problem detailed

This is part two of a series of lab tasks from KodeKloud for Kubernetes. Master blog listing all parts can be seen here.

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.

$ echo 'variables_order = "EGPCS"' > php.ini
$ kubectl create configmap php-config --from-file php.ini
$ # Verify
$ kubectl get configmaps
NAME               DATA   AGE
kube-root-ca.crt   1      2d20h
php-config         1      11s

$ kubectl describe configmap php-config
Name:         php-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
php.ini:
----
variables_order = "EGPCS"


BinaryData
====

Events:  <none>

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.

For tasks 2 and 3 above, we'll create a deployment YAML using dry-run edit and then apply the deployment.

$ kubectl create deployment lamp-wp \
    --image=webdevops/php-apache:alpine-3-php7 \
    --dry-run=client -o yaml > lamp-wp.yaml

You can get the fully modified YAML from GitHub link. Use the following command to apply/create deployment:

$ kubectl apply -f deploy-lamp-stack-on-k8/lamp-wp.yaml 
deployment.apps/lamp-wp created
$ kubectl get deployments
NAME      READY   UP-TO-DATE   AVAILABLE   AGE
lamp-wp   0/1     1            0           11s

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.

$ kubectl create secret generic db-config \
    --from-literal=MYSQL_ROOT_PASSWORD=kodekloud_root \
    --from-literal=MYSQL_DATABASE=kodekloud \
    --from-literal=MYSQL_USER=kodekloud_user \
    --from-literal=MYSQL_PASSWORD=kodekloud_user \
    --from-literal=MYSQL_HOST=mysql-service
$ kubectl get secrets
NAME        TYPE     DATA   AGE
db-config   Opaque   5      9s

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.

💡
Environment variables listed above have already been added to the deployments YAML in previous task.
  1. Create a node port type service lamp-service to expose the web application, nodePort must be 30008.
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: lamp-wp
  name: lamp-service # Same as mentioned above
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30008 # Same as mentioned above
  selector:
    app: lamp-wp
  type: NodePort
status:
  loadBalancer: {}

Create and verify the service:

$ kubectl apply -f deploy-lamp-stack-on-k8/lamp-service.yaml 
service/lamp-service created
$ kubectl get svc
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes     ClusterIP   10.96.0.1       <none>        443/TCP        2d20h
lamp-service   NodePort    10.100.48.196   <none>        80:30008/TCP   4s
  1. Create a service for mysql named mysql-service and its port must be 3306.
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  selector:
    app: lamp-wp
  ports:
    - protocol: TCP
      port: 3306
      targetPort: 3306 # Important!

Create and verify MySQL service:

$ kubectl apply -f deploy-lamp-stack-on-k8/mysql-service.yaml 
service/mysql-service created
$ kubectl get svc
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP        2d20h
lamp-service    NodePort    10.100.48.196   <none>        80:30008/TCP   2m24s
mysql-service   ClusterIP   10.109.198.49   <none>        3306/TCP       3s
  1. We already have /tmp/index.php file on jump_host server. For this get the index.php file from GitHub link.

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.

💡
Copy the index.php file using following kubectl command. also note the next command that helps you get the URL for testing.
$ kubectl get pods
NAME                       READY   STATUS    RESTARTS   AGE
lamp-wp-7ccc648dc8-kv2sg   2/2     Running   0          29m
$ kubectl cp deploy-lamp-stack-on-k8/index.php <REPALCE_WITH_POD_NAME>:/app/ -c httpd-php-container
$ minikube service lamp-service --url

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.

💡
Visit http://192.168.49.2:30008 to see it working. URL might be slightly different.

Clean Up

$ kubectl delete deployment lamp-wp
deployment.apps "lamp-wp" deleted
$ kubectl delete svc lamp-service mysql-service
service "lamp-service" deleted
service "mysql-service" deleted
0
Subscribe to my newsletter

Read articles from Rajesh Pethe directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Rajesh Pethe
Rajesh Pethe

Passionate software engineer with 17+ years of experience in design and development of full life cycle commercial applications. Functional experience include Financial, Telecom and E-Commerce applications. Primary technical stack includes but not limited to Python, Django, REST, SQL, Perl, Unix/Linux. Secondary technical skills include Java, Angular and React JS. DevOps skills include CiCD, AWS, Docker, Kubernetes and Terraform.