Make sure that you've taken a look at the following tutorial(s) before you continue:
Your one node cluster should be up and running. Persistent storage for MySQL should be created by now. Persistent disk should be formatted and detached from the instance.
In case of errors first of all check if it's not a badly formatted YAML file. Check the number of spaces in an indent. Count spaces in the line indicated if you have to.
error: yaml: line XX: did not find expected key
Next step is to consult last two articles in Useful links section. It's a two part series by Ross Kukulinski about solving issues with Kubernetes.
Commands presented in this tutorial should be executed from the root of tutorial's git repository.
You are going to learn
- how to run something using Kubernetes inside your own node cluster deployed in the cloud
- how to create a Namespace, Secret, Persistent Volume, Persistent Volume Claim, Deployment and Service
- MySQL relational database on Kubernetes
- 1Clone git repository
- 2Add custom namespace to the cluster
- 3Get the name of your cluster and user
- 4Create a context for your namespace
- 5Create a Secret
- 6Create a Persistent Volume
- 7Create and view a Persistent Volume Claim
- 8Create a Deployment
- 9Examine Pod created by the Deployment
- 10Create a Service and connect to MySQL
MySQL relational database on Kubernetes
Data source is usually the first thing one sets up on a new project. This tutorial will guide you through the process of running a MySQL container on Kubernetes. MySQL will keep it’s files on the formatted persistent storage prepared during the previous tutorial. Enough talk ! Let’s do it !
Download all the code that you will need for this tutorial from GitHub. All the
kubectl commands presented in this tutorial should be executed from the root of this git repository.
are virtual clusters inside your cluster. You use them whether you want or not. If you do not declare your own namespace then everything you create will live in a namespace called default. This might become problematic (Limit Range) so create your own. Newly created namespace will have no set so you don't have to worry about it in this tutorial.
List all the namespaces in your cluster.
Show details of the namespace that has just been created. Instead of using full name of the object in your commands, you can use abbreviated alias ns.
View configuration of
You should see a section that looks like this.
cluster - name of your cluster,
user - user who has access to the cluster,
name - name of the context
– context: cluster: gke_projectname_europe-west1-d_clustername user: gke_projectname_europe-west1-d_clustername name: gke_projectname_europe-west1-d_clustername
Contexts are a way to send requests to specific cluster. Imagine that you manage multiple clusters. You can comfortably switch between the contexts using
kubectl and underneath all the authentication required is done for you. Furthermore you can pass a namespace to the context.
You can switch between contexts with
View currently used context
Check how the configuration has changed after your context was added
If the namespace is not declared inside .yaml file then Kubernetes object will be created in current context/namespace.
The only time I had to explicitly declare the namespace was with containing a reference to a (
in Kubernetes hold data of sensitive nature such as passwords, usernames, API tokens etc.
Create MySQL Secret that will hold password of MySQL's root user. First you will need to base64 encode the data. Newlines are not valid withing base64 string.
base64 your desired MySQL root's password. If you worry about security then create a file and put the password inside it before encoding.
Create and view a Secret.
Remember that you can double tap TAB key to autocomplete pretty much anything.
First you need to let know which persistent disk should be used. Modify
k8s/mysql/volume.yaml and paste your MySQL disk's name into
pdName. Persistent Volumes are not namespaced objects. When you choose their name, prefix it with project's or application's name for example. It will save you some trouble in the future.
gcePersistentDisk: pdName: MYSQL_DISK_NAME fsType: ext4
Create and view a Persistent Volume
Namespace main is mentioned explicitly inside
k8s/mysql/volume.yaml but not in the rest of the files. This is required if you want to point to specific Persistent Volume Claim because their names are unique only within a namespace.
Create a that was referenced inside our Persistent Volume in
claimRef. After creation, the Claim will "consume" Persistent Volume resource. Those two objects will become bound. Status of both resources will change to Bound at that moment.
Deleting Persistent Volume or Persistent Volume Claim does not remove the files on the persistent disks unless Persistent Volume's
persistentVolumeReclaimPolicy is set to Delete. Use Recycle policy for most cases.
Think of as a way to run images (containers) inside Kubernetes namespace. In the Kubernetes documentation you will find a lot of references to. For the sake of simplicity assume for now that a Deployment equals one Pod which equals one docker container. It could not be further from the truth but just use your imagination.
The Deployment declared there will contain one container which will be created using an image pulled from Docker Hub. The image used is an official MySQL docker image (https://hub.docker.com/_/mysql/).
After pulling specified image, Kubernetes will try to run it. If everything is fine then the Deployment will become available.
Notice that the Deployment is using the Secret containing the MySQL root password. This secret will be available inside the running container as an environment variable called
MYSQL_ROOT_PASSWORD. MySQL official docker image knows what to do with it.
Also a volume is mounted to the Deployment which references Persistent Volume Claim that has just been created. Effectively
/var/lib/mysql directory where MySQL keeps it's data will reside on the persistent disk that was named inside the Perisitent Volume declaration. If you ever decide to move to a cloud platform supplier other than Google then all you have to do is transfer your data.
tier: mysql has been assigned to the Deployment.
Deployment details will be discussed in depth in the next part of this tutorial.
Create and view the Deployment
Your Deployment should have no problem becoming available. If it is not so then check what is wrong using previously listed commands or in the status part of the output of following command
Creating the Deployment has also created a corresponding Pod in the process
You can execute something on that Pod. Let's connect to it and start bash login shell.
You can view the logs of a Pod.
You can copy files between your local machine and the Pod.
You need to create a now. It is an abstraction that protects you against the case where something underneath it (eg. a Pod) dies and is not available. This Service exposes MySQL's standard port 3306 and points to Pods matching the selector
tier: mysql. Deployment created before has that exact label. Get it ? In Kubernetes you can connect and group objects using labels. By adding another label in both declarations, you could for example target MySQL Deployments that are in production or development environment. You will learn all about it in next parts of this tutorial series.
Now let's connect to our MySQL running Pod and run bash first. Then connect to the MySQL database and use the name of the Service as host name (wordpress-mysql). Give MySQL root's password when asked.
As you can see Service name becomes a host name inside your namespace. Simple, right ? You can use that name to connect from anywhere within your namespace.
exit twice to leave MySQL prompt and then bash.