Edit This Page

运行一个单实例有状态应用

本文介绍在Kubernetes中使用PersistentVolume和Deployment如何运行一个单实例有状态应用. 该应用是MySQL.

教程目标

  • 在环境中通过磁盘创建一个PersistentVolume.
  • 创建一个MySQL Deployment.
  • 在集群内以一个已知的 DNS 名将 MySQL 暴露给其他 pods.

准备开始

  • 你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 如果你还没有集群,你可以通过 Minikube 构建一 个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:

要获知版本信息,请输入 kubectl version.

部署MySQL

通过创建Kubernetes Deployment并使用PersistentVolumeClaim将其连接到现已存在的PersistentVolume上来运行一个有状态的应用. 例如, 下面这个YAML文件描述了一个运行MySQL 并引用PersistentVolumeClaim的Deployment. 该文件定义了一个volume其挂载目录为/var/lib/mysql, 然后创建一个内存为20G的卷的PersistentVolumeClaim. 此申领可以通过任 何符合需求的卷来满足, 在本例中满足上面创建的卷.

注意: 在配置的yaml文件中定义密码的做法是不安全的. 具体安全解决方案请参考 Kubernetes Secrets.

application/mysql/mysql-deployment.yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
  - port: 3306
  selector:
    app: mysql
  clusterIP: None
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
          # Use secret in real usage
        - name: MYSQL_ROOT_PASSWORD
          value: password
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim
application/mysql/mysql-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
  1. 部署 YAML 文件中定义的 PV 和 PVC:

    kubectl apply -f https://k8s.io/examples/application/mysql/mysql-pv.yaml
    
  2. 部署 YAML 文件中定义的 Deployment:

    kubectl apply -f https://k8s.io/examples/application/mysql/mysql-deployment.yaml
    
  3. 展示Deployment相关信息:

    kubectl describe deployment mysql

    Name:                 mysql
    Namespace:            default
    CreationTimestamp:    Tue, 01 Nov 2016 11:18:45 -0700
    Labels:               app=mysql
    Annotations:          deployment.kubernetes.io/revision=1
    Selector:             app=mysql
    Replicas:             1 desired | 1 updated | 1 total | 0 available | 1 unavailable
    StrategyType:         Recreate
    MinReadySeconds:      0
    Pod Template:
      Labels:       app=mysql
      Containers:
       mysql:
        Image:      mysql:5.6
        Port:       3306/TCP
        Environment:
          MYSQL_ROOT_PASSWORD:      password
        Mounts:
          /var/lib/mysql from mysql-persistent-storage (rw)
      Volumes:
       mysql-persistent-storage:
        Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
        ClaimName:  mysql-pv-claim
        ReadOnly:   false
    Conditions:
      Type          Status  Reason
      ----          ------  ------
      Available     False   MinimumReplicasUnavailable
      Progressing   True    ReplicaSetUpdated
    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
    
  4. 列举出Deployment创建的pods:

    kubectl get pods -l app=mysql

    NAME                   READY     STATUS    RESTARTS   AGE
    mysql-63082529-2z3ki   1/1       Running   0          3m
    
  5. 查看持久卷:

    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.
    
  6. 查看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.
    

访问MySQL实例

前面YAML文件中创建了一个允许集群内其他pods访问数据库的服务. 该服务中选项 clusterIP: None 让服务DNS名称直接解析为Pod的IP地址. 当在一个服务下只有一个pod 并且不打算增加pods的数量这是最好的.

运行MySQL客户端以连接到服务器:

kubectl run -it --rm --image=mysql:5.6 mysql-client -- mysql -h <pod-ip> -p <password>

此命令在集群内创建一个新的Pod并运行MySQL客户端,并通过服务将其连接到服务器.如果连接成功,你就知道有状态的MySQL database正处于运行状态.

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>

更新

Deployment中镜像或其他部分同往常一样可以通过 kubectl apply 命令更新. 以下是 特定于有状态应用的一些注意事项:

  • 不要弹性伸缩. 弹性伸缩仅适用于单实例应用. 下层的PersistentVolume仅只能挂载一个pod. 对于集群级有状态应用, 请参考StatefulSet文档 StatefulSet documentation.
  • 在Deployment的YAML文件中使用 strategy: type: Recreate . 该选项指示Kubernetes不使用滚动升级. 滚动升级将无法工作, 由于一次不能运行多个pod. 在更新配置文件 创建一个新的pod前 Recreate策略将先停止第一个pod.

删除deployment

通过名称删除部署的对象:

kubectl delete deployment,svc mysql
kubectl delete pvc mysql-pv-claim
kubectl delete pv mysql-pv

如果使用Compute Engine磁盘,也可以使用如下命令:

gcloud compute disks delete mysql-disk

接下来

反馈