This tutorial shows how to prepare and deploy WordPress with all required dependencies (MySQL, etc) in Kubernetes.
Why WordPress? WordPress is usually chosen as the de facto application when explaining how to handle a process with a server software stack.
One of the challenges Kubernetes users face is deploying and re-deploying the same components required by their applications: databases like MySQL or MariaDB, MongoDB, Redis, Memcached, Elasticsearch; frontend servers like Nginx; or just a load balancer with HAproxy, to name a few examples.
If you have a CI/CD workflow in place, you probably have Jenkins or any other similar software deploying to Kubernetes via kubectl
: Services, Deployments, ConfigMaps, Ingress controller and maybe even persistent storage. But if you are looking for something easier and more simple, there is a Kubernetes package manager that can help you: Helm.
Helm package manager and Kubernetes Charts
Helm is a Kubernetes package manager that allows you to package an application and handle all the required dependencies, including other services, and the configuration. The packages are called Charts. The idea is that instead of running kubectl
to create the different deployments, services, etc. all the resources are defined in manifest templates that Helm installs as an atomic operation. Think of dpkg or yum, cpan or pip, but for Kubernetes apps.
Kubernetes Charts is the official repository that offers a central reference location for already packaged applications; at this time 60 apps are available in the stable branch.
Installing Helm in OSX or Linux
As a prerequisite, you will need kubectl
authenticated and working against your Kubernetes instance in your cloud provider or you can use Minikube for testing in your local laptop.
On OSX, we recommend using Homebrew to install Helm:
% brew install kubernetes-helm
On Linux, you can download the latest release and unpack it:
% wget https://kubernetes-helm.storage.googleapis.com/helm-v2.2.0-linux-amd64.tar.gz
% tar xvzf helm-v2.2.0-linux-amd64.tar.gz
% sudo mv linux-amd64/helm /usr/local/bin/helm
Code language: JavaScript (javascript)
Init Helm in your Kubernetes cluster
Before moving along, Helm needs to be installed in your Kubernetes cluster as well. This is a very straightforward process and you just need to init Helm:
% helm init
$HELM_HOME has been configured at /home/bencer/.helm.
Tiller (the helm server side component) has been installed into your Kubernetes Cluster.
Happy Helming!
Code language: PHP (php)
This will create a containerized service in Kubernetes known as Tiller. From this point on, the Helm package manager installed in your laptop will communicate with Tiller running in Kubernetes via gRPC, and Tiller will be in charge of deploying, upgrading and deleting the apps in your cluster:
% kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system kube-addon-manager-minikube 1/1 Running 0 3m
kube-system kube-dns-v20-qzkhp 3/3 Running 0 2m
kube-system kubernetes-dashboard-mtrl3 1/1 Running 0 2m
kube-system tiller-deploy-2923173008-n21pw 1/1 Running 0 18s
Code language: JavaScript (javascript)
If you want to update the Chats database, like apt update
, simply:
% helm repo update
And if you want to upgrade Tiller:
% helm init --upgrade
WordPress Deployment in Kubernetes
With Helm configured and Tiller up and running you can start deploying your favorite apps. For instance, let’s search for WordPress Charts:
% helm search wordpress
NAME VERSION DESCRIPTION
stable/wordpress 0.4.2 Web publishing platform for building blogs and ...
And you can get more information about this Chart in a similar fashion to apt-cache
:
% helm inspect stable/wordpress
description: Web publishing platform for building blogs and websites.
engine: gotpl
home: http://www.wordpress.com/
icon: https://bitnami.com/assets/stacks/wordpress/img/wordpress-stack-220x234.png
keywords:
- wordpress
- cms
- blog
- http
- web
- application
- php
maintainers:
- email: [email protected]
name: Bitnami
name: wordpress
sources:
- https://github.com/bitnami/bitnami-docker-wordpress
version: 0.4.2
---
## Bitnami WordPress image version
## ref: https://hub.docker.com/r/bitnami/wordpress/tags/
##
image: bitnami/wordpress:4.7-r0
[...]
Code language: PHP (php)
Since we want our WordPress running in its own namespace, let’s create one as we install the application:
% helm install --namespace wordpress --name wordpress stable/wordpress
NAME: wordpress
LAST DEPLOYED: Mon Mar 6 17:38:30 2017
NAMESPACE: wordpress
STATUS: DEPLOYED
RESOURCES:
==> v1/Service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
wordpress-wordpress 10.109.108.55 <pending> 80:32435/TCP,443:30044/TCP 2s
wordpress-mariadb 10.102.199.160 <none> 3306/TCP 1s
==> extensions/v1beta1/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
wordpress-mariadb 1 1 1 0 1s
wordpress-wordpress 1 1 1 0 1s
==> v1/Secret
NAME TYPE DATA AGE
wordpress-wordpress Opaque 2 2s
wordpress-mariadb Opaque 2 2s
==> v1/ConfigMap
NAME DATA AGE
wordpress-mariadb 1 2s
==> v1/PersistentVolumeClaim
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
wordpress-wordpress-apache Bound pvc-551b2739-028b-11e7-ad79-12182a6edca4 1Gi RWO 2s
wordpress-wordpress-wordpress Bound pvc-551b9867-028b-11e7-ad79-12182a6edca4 8Gi RWO 2s
wordpress-mariadb Bound pvc-551c0c25-028b-11e7-ad79-12182a6edca4 8Gi RWO 2s
NOTES:
1. Get the WordPress URL:
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
Watch the status with: 'kubectl get svc --namespace wordpress -w wordpress-wordpress'
export SERVICE_IP=$(kubectl get svc --namespace wordpress wordpress-wordpress -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo http://$SERVICE_IP/admin
2. Login with the following credentials to see your blog
echo Username: user
echo Password: $(kubectl get secret --namespace wordpress wordpress-wordpress -o jsonpath="{.data.wordpress-password}" | base64 --decode)
</none></pending>
Code language: HTML, XML (xml)
You can find all the available configuration options here, and you can set these either using the command line --set
or in a YAML file. Also, all Charts output some instructions on how to proceed after the package is installed. In this case, you should see how to get the WordPress Ingress controller URL with:
% kubectl get svc --namespace wordpress wordpress-wordpress -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'
Note: using .status.loadBalancer.ingress[0].ip
didn’t work for me as expected an IP address and I had a hostname instead, but you can always inspect the wordpress service with kubectl
to get full details:
% kubectl describe svc wordpress-wordpress --namespace wordpress
Name: wordpress-wordpress
Namespace: wordpress
Labels: app=wordpress-wordpress
chart=wordpress-0.4.2
heritage=Tiller
release=wordpress
Selector: app=wordpress-wordpress
Type: LoadBalancer
IP: 10.109.108.55
LoadBalancer Ingress: a55201964028b11e7ad7912182a6edca-1068550576.us-east-1.elb.amazonaws.com
Port: http 80/TCP
NodePort: http 32435/TCP
Endpoints: 192.168.224.67:80
Port: https 443/TCP
NodePort: https 30044/TCP
Endpoints: 192.168.224.67:443
Session Affinity: None
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
9m 9m 1 {service-controller } Normal CreatingLoadBalancer Creating load balancer
9m 9m 1 {service-controller } Normal CreatedLoadBalancer Created load balancer
So just head to: https://a55201964028b11e7ad7912182a6edca-1068550576.us-east-1.elb.amazonaws.com and you will be able to access your new WordPress blog.
You can also check the administrator user credentials that are stored in a Kubernetes secret:
% kubectl get secret --namespace wordpress wordpress-wordpress -o jsonpath="{.data.wordpress-password}" | base64 --decode
And if you want to see this information at any point, you can use helm status wordpress
to show it again.
Helm can install and handle multiple apps, and can list the different apps installed:
% helm ls
NAME REVISION UPDATED STATUS CHART NAMESPACE
sysdig 1 Mon Mar 6 12:40:22 2017 DEPLOYED sysdig-0.2.0 default
wordpress 1 Mon Mar 6 12:48:11 2017 DEPLOYED wordpress-0.4.2 wordpress
Code language: CSS (css)
And you can also delete them once you have finished with helm delete
.
Monitoring WordPress in Kubernetes
Along with your app stack, monitoring with telemetry and performance metrics for troubleshooting, dashboards and alerts is a must. Sysdig Monitor is probably your best bet for doing all this with one tool in Kubernetes and in less than 5 minutes!
Sysdig Monitor agent has always been very easy to install, either running the plain Docker command or deploying it using a DaemonSet, but now Sysdig can also be deployed with Helm since it’s available in the official Kubernetes Charts repository.
You just need to run the following command, including the AccessKey, which you will find in your Sysdig Monitor user account settings.
% helm install --namespace sysdig --set sysdig.AccessKey="YOUR-ACCESS-KEY",sysdig.AgentTags="cluster:kubernetes-dev" stable/sysdig
NAME: needled-quoll
LAST DEPLOYED: Mon Mar 6 16:02:49 2017
NAMESPACE: sysdig
STATUS: DEPLOYED
RESOURCES:
==> v1/Secret
NAME TYPE DATA AGE
needled-quoll-sysdig Opaque 2 1s
==> extensions/v1beta1/DaemonSet
NAME DESIRED CURRENT READY NODE-SELECTOR AGE
needled-quoll-sysdig 3 3 0 <none> 1s
NOTES:
Sysdig Monitor agents are spinning up on each node in your cluster. After a few seconds, you should see your hosts appearing in the Explore tab:
https://app.sysdigcloud.com/#/explore/overview/l:10
No further action should be required.
</none>
Code language: HTML, XML (xml)
That’s it.
Now you can list both Charts running:
% helm list
NAME REVISION UPDATED STATUS CHART NAMESPACE
needled-quoll 1 Mon Mar 6 16:02:49 2017 DEPLOYED sysdig-0.2.0 sysdig
wordpress 1 Mon Mar 6 15:28:10 2017 DEPLOYED wordpress-0.4.2 mywordpress
Code language: CSS (css)
To start monitoring your Kubernetes deployment, go to Sysdig Monitor and from there you can visualize your deployment topology, configure dashboards and set up alerts. Through the Explore tab you can browse your infrastructure. Not only can you see hosts and containers running on them, you can also group containers using Kubernetes logic: cluster > namespaces > deployments or services > pods and containers.
Thanks to Sysdig’s ability to autodiscover the services running in your containers you will automatically get views of your WordPress containers, including application-layer metrics such as: HTTP requests and HTTP error count per second, average and max response time for each microservice, and also which are the top requested URLs or which are the slowest ones!
Recommended alerts for WordPress in Kubernetes
Monitoring any service running in Kubernetes is a little more tricky that monitoring the same service in a bare metal static infrastructure. Now you have to monitor not only the host and the services but also the containers and the orchestration platform. There is no rule that fits all scenarios, but we are going to throw out a few suggestions here of what should probably be in your alerts list.
Host-level alerts
Is any of your hosts down? If its a minion it’s probably not too bad because Kubernetes will reschedule the containers somewhere else. If it’s your master and you only have one you will probably want to know ASAP.
You might want to add some other host-level resource consumption alerts like disk usage over 80%, if you have been swapping for a few minutes and the load is way above normal. But remember, it’s not worth waking you up if there isn’t anything broken.
Kubernetes alerts
This is the new layer and basically you want to make sure the resources defined by Kubernetes are running. For our WordPress example, I’m pretty sure that everyone would like to know if there are no containers running for a given service, which should never happen!
kubernetes.replicaSet.replicas.running < 1
</code>
But also, you will want to know if the number of container running is lower that the number of replicas you wanted. This can be triggered with the following condition:
kubernetes.replicaSet.replicas.running < kubernetes.replicaSet.replicas.desired
</code>
This should be applied to both the wordpress and mysql service.
Just making sure the containers are alive is not enough; you need to make sure they are not being continuously restarted because the process running inside is crashing. This is known as CrashLoopBackOff, and you can receive an alert when this happens using the restart count metric or an alert on the event:
We will apply this alert across everything in your cluster, making it trigger for each pod that matches this condition: kubernetes.pod.restart.count > 4 over the last 2 minutes.
Service level alerts
You still need to make sure that your services are running: that the WordPress webserver is responding to HTTP requests properly and queries are going through the MySQL database. Defining alerts at this level depends heavily on your traffic patterns. If you have a regular, sustained number of visits it is easy to set a minimum threshold of HTTP requests or MySQL queries, but if your traffic is random these kind of alerts will trigger many false positives.
In general, alerting should be configured using your working metrics (those that are a clear indicator that your app is working), triggering notifications to show that something has stopped working. Still, in most cases, you should set up a few alerts based on infrastructure availability or resources that always need to be there. If you want to learn more about Kubernetes alerting, don’t miss our Monitoring Kubernetes (part 2): Best practices for alerting on Kubernetes.
Next steps
We think Helm is great for quickly and easily deploying the services you need for running your app in Kubernetes. Now you can also deploy the Sysdig Monitor agent with Helm too. If you want to close the circle you can create your own Chart package for your app and host it in your private repository, with everything still handled by Helm.
If you are looking at an even more user-friendly way to expose Helm to your Kubernetes users, check out Monocular, a Helm UI that you can also self-host in your Kubernetes.