Detailed walkthroughs of common Kubernetes operations and workflows.

Documentation for Kubernetes v1.5 is no longer actively maintained. The version you are currently viewing is a static snapshot. For up-to-date documentation, see the latest version.

Edit This Page

Running a Single-Instance Stateful Application

This page shows you how to run a single-instance stateful application in Kubernetes using a PersistentVolume and a Deployment. The application is MySQL.


Before you begin

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:

apiVersion: v1
kind: PersistentVolume
  name: mysql-pv
    storage: 20Gi
    - ReadWriteOnce
    pdName: mysql-disk
    fsType: ext4

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 http://k8s.io/docs/tutorials/stateful-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.

apiVersion: v1
kind: Service
  name: mysql
    - port: 3306
    app: mysql
  clusterIP: None
apiVersion: v1
kind: PersistentVolumeClaim
  name: mysql-pv-claim
    - ReadWriteOnce
      storage: 20Gi
apiVersion: extensions/v1beta1
kind: Deployment
  name: mysql
    type: Recreate
        app: mysql
      - image: mysql:5.6
        name: mysql
          # Use secret in real usage
        - name: MYSQL_ROOT_PASSWORD
          value: password
        - containerPort: 3306
          name: mysql
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      - name: mysql-persistent-storage
          claimName: mysql-pv-claim
  1. Deploy the contents of the YAML file:

     kubectl create -f http://k8s.io/docs/tutorials/stateful-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)
       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
         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 mysql -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.



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:

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

What’s next


Create an Issue Edit this Page