How to run WordPress on Kubernetes

WordPress is a popular open-source content management system (CMS) for creating websites, blogs, and e-commerce platforms. Running WordPress on Kubernetes can be a powerful way to manage our WordPress deployment, ensuring scalability, resilience, and ease of management.

In this Answer, we’ll discuss the steps required to run WordPress on Kubernetes.

Deploying WordPress

Firstly, we will talk about the main step: deploying WordPress. To do this, we will define the specifications of the WordPress resource in the YAML file, such as the apiVersion, the kind of deployment, and the desired state of deployment:

# wordpress.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress
spec:
replicas: 1
selector:
matchLabels:
app: wordpress
template:
metadata:
labels:
app: wordpress
spec:
containers:
- name: wordpress
image: wordpress:latest
ports:
- containerPort: 80
env:
- name: WORDPRESS_DB_HOST
value: mysql
- name: WORDPRESS_DB_NAME
value: wordpress
- name: WORDPRESS_DB_USER
value: root
- name: WORDPRESS_DB_PASSWORD
value: password

Explanation

The line-by-line explanation of the code section above is as follows:

  • Lines 2–5: The apiVersion being equal to v1 is defined here, along with the kind of resource being created, which is Deployment and the name of the resource wordpress is defined inside the metadata section.

  • Lines 6–10: The desired number of replicas for deployment is set to one, as well as the labels that the pods must have to be selected during deployment under the selector section.

  • Lines 11–14: The pod template is used to create new pods with its metadata and labels.

  • Lines 15–29: The specification for the containers running in the pod is defined, consisting of its name, image label, port numbers and environment variables for the container including database connection details.

Defining the WordPress service

Next, we will define the WordPress service as shown below:

apiVersion: v1
kind: Service
metadata:
name: wordpress
spec:
selector:
app: wordpress
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer

We define the apiVersion , kind, and metadata with the only difference being in the type of deployment, which is Service.

Here, we are defining a Kubernetes service to expose the WordPress deployment externally by describing the desire state of the service. This is done by the selector (this specifies how the service selects which pods to route traffic to) ports, and type of service, which is LoadBalancer in this case.

Deploying MySQL

We move to the steps where we need a database to store WordPress' content, configuration and other essential data. Here, we choose MySQL to be that database:

apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:latest
env:
- name: MYSQL_ROOT_PASSWORD
value: password
- name: MYSQL_DATABASE
value: wordpress
ports:
- containerPort: 3306

Similar to deploying WordPress, we start off by defining the apiVersion, kind of deployment and the metadata containing the name of the resource (mysql in this case). A similar structure to the WordPress deployment is followed, including the environment variables for the MySQL root password and name of the WordPress database (lines 18–22).

Defining the MySQL service

Finally, we define the MySQL service to expose the MySQL deployment internally. This service allows other components in the Kubernetes cluster to access the MySQL database:

apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
selector:
app: mysql
ports:
- protocol: TCP
port: 3306
targetPort: 3306

Similar to defining the WordPress service, we define a Kubernetes service to expose the WordPress deployment via the selector and ports having port and targetPort numbers equal to 3306 and the TCP protocol.

Code

By combining all of the steps explained above, we can test our WordPress deployment in Kubernetes below. Run the code to see it in action.

# wordpress.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      containers:
        - name: wordpress
          image: wordpress:latest
          ports:
            - containerPort: 80
          env:
            - name: WORDPRESS_DB_HOST
              value: mysql
            - name: WORDPRESS_DB_NAME
              value: wordpress
            - name: WORDPRESS_DB_USER
              value: root
            - name: WORDPRESS_DB_PASSWORD
              value: password
---
apiVersion: v1
kind: Service
metadata:
  name: wordpress
spec:
  selector:
    app: wordpress
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:latest
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: password
            - name: MYSQL_DATABASE
              value: wordpress
          ports:
            - containerPort: 3306
---
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  selector:
    app: mysql
  ports:
    - protocol: TCP
      port: 3306
      targetPort: 3306
Running WordPress in Kubernetes

Conclusion

Its important to remember that deploying WordPress on Kubernetes can be complex, especially if one is new to Kubernetes. It's a good idea to start small, gradually adding complexity as one becomes more comfortable with the technologies involved. Tools such as Helm charts are available to help simplify the deployment process.

Unlock your potential: Kubernetes Deployment and Advanced Operations series, all in one place!

If you've missed any part of the series, you can always go back and check out the previous Answers:

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved