website/docs/tasks/run-application/run-single-instance-statefu...

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" %}

  1. Deploy the contents of the YAML file:

     kubectl create -f https://k8s.io/docs/tasks/run-application/mysql-deployment.yaml
    
  2. 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
    
  3. 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
    
  4. 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.
    
  5. 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. The Recreate 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 %}

{% endcapture %}

{% include templates/tutorial.md %}