Deploying WordPress and MySQL with Persistent Volumes in Kubernetes

This tutorial shows you how to deploy a WordPress site and a MySQL database using Minikube. Both applications use PersistentVolumes and PersistentVolumeClaims to store data.

PersistentVolume (PV) is a piece of storage in the cluster that has been manually provisioned by an administrator, or dynamically provisioned by Kubernetes using a StorageClass. A PersistentVolumeClaim (PVC) is a request for storage by a user that can be fulfilled by a PV. PersistentVolumes and PersistentVolumeClaims are independent from Pod lifecycles and preserve data through restarting, rescheduling, and even deleting Pods.Warning: This deployment is not suitable for production use cases, as it uses single instance WordPress and MySQL Pods. Consider using WordPress Helm Chart to deploy WordPress in production.Note: The files provided in this tutorial are using GA Deployment APIs and are specific to kubernetes version 1.9 and later. If you wish to use this tutorial with an earlier version of Kubernetes, please update the API version appropriately, or reference earlier versions of this tutorial.

Objectives

  • Create PersistentVolumeClaims and PersistentVolumes
  • Create a kustomization.yaml with
    • a Secret generator
    • MySQL resource configs
    • WordPress resource configs
  • Apply the kustomization directory by kubectl apply -k ./
  • Clean up

Before you begin

You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using Minikube, or you can use one of these Kubernetes playgrounds:

To check the version, enter kubectl version. The example shown on this page works with kubectl 1.14 and above.

Download the following configuration files:

  1. mysql-deployment.yaml
  2. wordpress-deployment.yaml

Create PersistentVolumeClaims and PersistentVolumes

MySQL and WordPress each require a PersistentVolume to store data. Their PersistentVolumeClaims will be created at the deployment step.

Many cluster environments have a default StorageClass installed. When a StorageClass is not specified in the PersistentVolumeClaim, the cluster’s default StorageClass is used instead.

When a PersistentVolumeClaim is created, a PersistentVolume is dynamically provisioned based on the StorageClass configuration.Warning: In local clusters, the default StorageClass uses the hostPath provisioner. hostPath volumes are only suitable for development and testing. With hostPath volumes, your data lives in /tmp on the node the Pod is scheduled onto and does not move between nodes. If a Pod dies and gets scheduled to another node in the cluster, or the node is rebooted, the data is lost.Note: If you are bringing up a cluster that needs to use the hostPath provisioner, the --enable-hostpath-provisioner flag must be set in the controller-manager component.Note: If you have a Kubernetes cluster running on Google Kubernetes Engine, please follow this guide.

Create a kustomization.yaml

Add a Secret generator

Secret is an object that stores a piece of sensitive data like a password or key. Since 1.14, kubectl supports the management of Kubernetes objects using a kustomization file. You can create a Secret by generators in kustomization.yaml.

Add a Secret generator in kustomization.yaml from the following command. You will need to replace YOUR_PASSWORD with the password you want to use.

cat <<EOF >./kustomization.yaml
secretGenerator:
- name: mysql-pass
  literals:
  - password=YOUR_PASSWORD
EOF

Add resource configs for MySQL and WordPress

The following manifest describes a single-instance MySQL Deployment. The MySQL container mounts the PersistentVolume at /var/lib/mysql. The MYSQL_ROOT_PASSWORD environment variable sets the database password from the Secret.

application/wordpress/mysql-deployment.yaml 
apiVersion: v1 kind: Service metadata: name: wordpress labels: app: wordpress spec: ports: - port: 80 selector: app: wordpress tier: frontend type: LoadBalancer --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: wp-pv-claim labels: app: wordpress spec: accessModes: - ReadWriteOnce resources: requests: storage: 20Gi --- apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 kind: Deployment metadata: name: wordpress labels: app: wordpress spec: selector: matchLabels: app: wordpress tier: frontend strategy: type: Recreate template: metadata: labels: app: wordpress tier: frontend spec: containers: - image: wordpress:4.8-apache name: wordpress env: - name: WORDPRESS_DB_HOST value: wordpress-mysql - name: WORDPRESS_DB_PASSWORD valueFrom: secretKeyRef: name: mysql-pass key: password ports: - containerPort: 80 name: wordpress volumeMounts: - name: wordpress-persistent-storage mountPath: /var/www/html volumes: - name: wordpress-persistent-storage persistentVolumeClaim: claimName: wp-pv-claim

The following manifest describes a single-instance WordPress Deployment. The WordPress container mounts the PersistentVolume at /var/www/html for website data files. The WORDPRESS_DB_HOST environment variable sets the name of the MySQL Service defined above, and WordPress will access the database by Service. The WORDPRESS_DB_PASSWORD environment variable sets the database password from the Secret kustomize generated.

application/wordpress/wordpress-deployment.yaml 
apiVersion: v1 kind: Service metadata: name: wordpress labels: app: wordpress spec: ports: - port: 80 selector: app: wordpress tier: frontend type: LoadBalancer --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: wp-pv-claim labels: app: wordpress spec: accessModes: - ReadWriteOnce resources: requests: storage: 20Gi --- apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 kind: Deployment metadata: name: wordpress labels: app: wordpress spec: selector: matchLabels: app: wordpress tier: frontend strategy: type: Recreate template: metadata: labels: app: wordpress tier: frontend spec: containers: - image: wordpress:4.8-apache name: wordpress env: - name: WORDPRESS_DB_HOST value: wordpress-mysql - name: WORDPRESS_DB_PASSWORD valueFrom: secretKeyRef: name: mysql-pass key: password ports: - containerPort: 80 name: wordpress volumeMounts: - name: wordpress-persistent-storage mountPath: /var/www/html volumes: - name: wordpress-persistent-storage persistentVolumeClaim: claimName: wp-pv-claim
  1. Download the MySQL deployment configuration file.curl -LO https://k8s.io/examples/application/wordpress/mysql-deployment.yaml
  2. Download the WordPress configuration file.curl -LO https://k8s.io/examples/application/wordpress/wordpress-deployment.yaml
  3. Add them to kustomization.yaml file.
cat <<EOF >>./kustomization.yaml
resources:
  - mysql-deployment.yaml
  - wordpress-deployment.yaml
EOF

Apply and Verify

The kustomization.yaml contains all the resources for deploying a WordPress site and a MySQL database. You can apply the directory by

kubectl apply -k ./

Now you can verify that all objects exist.

  1. Verify that the Secret exists by running the following command:kubectl get secrets The response should be like this:NAME TYPE DATA AGE mysql-pass-c57bb4t7mf Opaque 1 9s
  2. Verify that a PersistentVolume got dynamically provisioned.kubectl get pvc Note: It can take up to a few minutes for the PVs to be provisioned and bound.The response should be like this:NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE mysql-pv-claim Bound pvc-8cbd7b2e-4044-11e9-b2bb-42010a800002 20Gi RWO standard 77s wp-pv-claim Bound pvc-8cd0df54-4044-11e9-b2bb-42010a800002 20Gi RWO standard 77s
  3. Verify that the Pod is running by running the following command:kubectl get pods Note: It can take up to a few minutes for the Pod’s Status to be RUNNING.The response should be like this:NAME READY STATUS RESTARTS AGE wordpress-mysql-1894417608-x5dzt 1/1 Running 0 40s
  4. Verify that the Service is running by running the following command:kubectl get services wordpress The response should be like this:NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE wordpress LoadBalancer 10.0.0.89 <pending> 80:32406/TCP 4m Note: Minikube can only expose Services through NodePort. The EXTERNAL-IP is always pending.
  5. Run the following command to get the IP Address for the WordPress Service:minikube service wordpress --url The response should be like this:http://1.2.3.4:32406
  6. Copy the IP address, and load the page in your browser to view your site.You should see the WordPress set up page similar to the following screenshot.wordpress-init

Warning: Do not leave your WordPress installation on this page. If another user finds it, they can set up a website on your instance and use it to serve malicious content.

Either install WordPress by creating a username and password or delete your instance.

Cleaning up

  1. Run the following command to delete your Secret, Deployments, Services and PersistentVolumeClaims:kubectl delete -k ./

What’s next

Non so niente

.. Socrate diceva non so niente, proprio perché se non so niente problematizzo tutto. La filosofia nasce dalla problematizzazione dell’ovvio: non accettiamo quello che c’è, perché se lo facciamo, ce lo ricorda ancora Platone, diventeremo gregge, pecore. La filosofia nasce come istanza critica, non accettazione dell’ovvio, non rassegnazione a quello che oggi va di moda chiamare sano realismo. Mi rendo conto che realisticamente uno che si iscrive a filosofia compie un gesto folle, però forse se non ci sono questi folli il mondo resta così com’è… Allora la filosofia svolge un ruolo decisamente importante, non perché sia competente di qualcosa, ma semplicemente perché non accetta qualcosa, e questa non accettazione di ciò che c’è non la esprime attraverso revolverate o rivoluzioni, l’esprime attraverso un tentativo di trovare le contraddizioni del presente e dell’esistente, e argomentare possibilità di soluzioni: in pratica, pensare. E il giorno in cui noi abdichiamo al pensiero abbiamo abdicato a tutto.

Umberto Galimberti
Percorsi di emancipazione, democrazia ed etica

Salutini

Sto per andare via da voi miei piccolini e mi avete spezzato il cuoricino così tanto che ho bisogno di scrivere, la mia valvola di sfogo.
Sono questi i momenti in cui vorrei ci fosse un regista, un regista della mia vita capace d’immortalare il momento che spero rimanga sempre impresso nella mia testa

I vostri faccini pieni di lacrime che m’implorano di rimanere, i vostri abbracci, Simone, il più fisico, che con la manina cerca la mia barba, struscia la manina, ci gioca, cerca un contatto, mi bacia facendomi sentire le sue guanciotte lacrimose umide .
Mi tenete li, sul divano e non volete che mi alzi, ogni secondo un’ora.
E’ li che capisci che il tempo è relativo, il vero senso della frase “Un giorno, tre autunni”.
Sento e posso toccare l’amore vero, quello che sai è per sempre.

Come si fa a spiegare, come?

Come si fa a spiegare.

“Mi mancherai” mi hai detto Simone, con quella sua vocina meravigliosa che il tempo ti cambierà a favore di una voce sempre più matura ma sempre più lontana da me. Si cresce.

Vorrei che alcune cose rimanessero congelate nel tempo, vorrei che voi rimaneste sempre così ma non si può ed in fondo è bello così, ci godiamo un momento che rimarrà una perla nel nostro cuore e per mano continuiamo a crescere.

Ora che avete chiuso la porta e siete andati, tocca piangere a me.

Sempre insieme.

What is CI/CD

Our space is about mobile CI/CD but, let’s start with the basics in this article before going into the details of why mobile CI/CD is actually different than other CI/CD flows in our future articles.

Image for post

What is Continuous Integration?

Continuous Integration (CI) is the building process for every code pushed to a repository automatically.

This is of course a very simplified definition and CI contains a number of different components, which are like the building blocks that come together to become a workflow.

A CI workflow may include operations like compiling the app, static code reviews and unit/UI testing with automated tools.

There are a number of different tools for CI/CD, some of the most popular ones are Jenkins, Travis and CircleCI, but mobile CI/CD requires specialization and in our space, we will be talking more about mobile CI/CD tools like Appcircle and Bitrise.


What is Continuous Delivery (or Deployment)?

Continuous Delivery (CD) is the delivery of the application for use with the components like the generation of environment-specific versions, codesigning, version management and deployment to a certain provider.

For mobile apps, the deployment can be done to a testing platform like TestFlight (for end user testing on actual devices) or Appcircle (for actual or virtual device testing).

Similarly, the release version of the app can be deployed to App Store and Google Play for B2C apps or to an enterprise app store for B2E apps.


Finally, what is a CI and CD pipeline?

With all CI/CD components are in place and connected together in an automated manner, they form an application pipeline. You just push your code and the code is processed through the pipeline.

CI is mainly responsible for processing the contents of the pipeline and CD is mainly responsible for directing the contents of the pipeline in the right direction.

In a well-functioning application pipeline, you don’t see the actual contents, it just flows by itself, but you have a full visibility on what is flowing and to where just like an actual pipeline.