7.2 KiB
title |
---|
Run a Single-Instance Stateful Application |
{% capture overview %}
This page shows you how to run a single-instance stateful application in Kubernetes using a PersistentVolume and a Deployment. The application is MySQL.
{% endcapture %}
{% capture objectives %}
- Create a PersistentVolume referencing a disk in your environment.
- Create a MySQL Deployment.
- Expose MySQL to other pods in the cluster at a known DNS name.
{% endcapture %}
{% capture prerequisites %}
-
{% include task-tutorial-prereqs.md %}
-
For data persistence we will create a Persistent Volume that references a disk in your environment. See here for the types of environments supported. This Tutorial will demonstrate
GCEPersistentDisk
but any type will work.GCEPersistentDisk
volumes only work on Google Compute Engine.
{% endcapture %}
{% capture lessoncontent %}
Set up a disk in your environment
You can use any type of persistent volume for your stateful app. See Types of Persistent Volumes for a list of supported environment disks. For Google Compute Engine, run:
gcloud compute disks create --size=20GB mysql-disk
Next create a PersistentVolume that points to the mysql-disk
disk just created. Here is a configuration file for a PersistentVolume
that points to the Compute Engine disk above:
{% include code.html language="yaml" file="gce-volume.yaml" ghlink="/docs/tasks/run-application/gce-volume.yaml" %}
Notice that the pdName: mysql-disk
line matches the name of the disk
in the Compute Engine environment. See the
Persistent Volumes
for details on writing a PersistentVolume configuration file for other
environments.
Create the persistent volume:
kubectl create -f https://k8s.io/docs/tasks/run-application/gce-volume.yaml
Deploy MySQL
You can run a stateful application by creating a Kubernetes Deployment and connecting it to an existing PersistentVolume using a PersistentVolumeClaim. For example, this YAML file describes a Deployment that runs MySQL and references the PersistentVolumeClaim. The file defines a volume mount for /var/lib/mysql, and then creates a PersistentVolumeClaim that looks for a 20G volume. This claim is satisfied by any volume that meets the requirements, in this case, the volume created above.
Note: The password is defined in the config yaml, and this is insecure. See Kubernetes Secrets for a secure solution.
{% include code.html language="yaml" file="mysql-deployment.yaml" ghlink="/docs/tasks/run-application/mysql-deployment.yaml" %}
-
Deploy the contents of the YAML file:
kubectl create -f https://k8s.io/docs/tasks/run-application/mysql-deployment.yaml
-
Display information about the Deployment:
kubectl describe deployment mysql Name: mysql Namespace: default CreationTimestamp: Tue, 01 Nov 2016 11:18:45 -0700 Labels: app=mysql Selector: app=mysql Replicas: 1 updated | 1 total | 0 available | 1 unavailable StrategyType: Recreate MinReadySeconds: 0 OldReplicaSets: <none> NewReplicaSet: mysql-63082529 (1/1 replicas created) Events: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 33s 33s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set mysql-63082529 to 1
-
List the pods created by the Deployment:
kubectl get pods -l app=mysql NAME READY STATUS RESTARTS AGE mysql-63082529-2z3ki 1/1 Running 0 3m
-
Inspect the Persistent Volume:
kubectl describe pv mysql-pv Name: mysql-pv Labels: <none> Status: Bound Claim: default/mysql-pv-claim Reclaim Policy: Retain Access Modes: RWO Capacity: 20Gi Message: Source: Type: GCEPersistentDisk (a Persistent Disk resource in Google Compute Engine) PDName: mysql-disk FSType: ext4 Partition: 0 ReadOnly: false No events.
-
Inspect the PersistentVolumeClaim:
kubectl describe pvc mysql-pv-claim Name: mysql-pv-claim Namespace: default Status: Bound Volume: mysql-pv Labels: <none> Capacity: 20Gi Access Modes: RWO No events.
Accessing the MySQL instance
The preceding YAML file creates a service that
allows other Pods in the cluster to access the database. The Service option
clusterIP: None
lets the Service DNS name resolve directly to the
Pod's IP address. This is optimal when you have only one Pod
behind a Service and you don't intend to increase the number of Pods.
Run a MySQL client to connect to the server:
kubectl run -it --rm --image=mysql:5.6 mysql-client -- mysql -h <pod-ip> -ppassword
This command creates a new Pod in the cluster running a mysql client and connects it to the server through the Service. If it connects, you know your stateful MySQL database is up and running.
Waiting for pod default/mysql-client-274442439-zyp6i to be running, status is Pending, pod ready: false
If you don't see a command prompt, try pressing enter.
mysql>
Updating
The image or any other part of the Deployment can be updated as usual
with the kubectl apply
command. Here are some precautions that are
specific to stateful apps:
- Don't scale the app. This setup is for single-instance apps only. The underlying PersistentVolume can only be mounted to one Pod. For clustered stateful apps, see the StatefulSet documentation.
- Use
strategy:
type: Recreate
in the Deployment configuration YAML file. This instructs Kubernetes to not use rolling updates. Rolling updates will not work, as you cannot have more than one Pod running at a time. TheRecreate
strategy will stop the first pod before creating a new one with the updated configuration.
Deleting a deployment
Delete the deployed objects by name:
kubectl delete deployment,svc mysql
kubectl delete pvc mysql-pv-claim
kubectl delete pv mysql-pv
Also, if you are using Compute Engine disks:
gcloud compute disks delete mysql-disk
{% endcapture %}
{% capture whatsnext %}
-
Learn more about Deployment objects.
-
Learn more about Deploying applications
{% endcapture %}
{% include templates/tutorial.md %}