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

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

教程目标

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

准备开始

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

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

部署MySQL

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

application/mysql/mysql-deployment.yaml 运行一个单实例有状态应用 - 图1
  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: mysql
  5. spec:
  6. ports:
  7. - port: 3306
  8. selector:
  9. app: mysql
  10. clusterIP: None
  11. —-
  12. apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
  13. kind: Deployment
  14. metadata:
  15. name: mysql
  16. spec:
  17. selector:
  18. matchLabels:
  19. app: mysql
  20. strategy:
  21. type: Recreate
  22. template:
  23. metadata:
  24. labels:
  25. app: mysql
  26. spec:
  27. containers:
  28. - image: mysql:5.6
  29. name: mysql
  30. env:
  31. # Use secret in real usage
  32. - name: MYSQL_ROOT_PASSWORD
  33. value: password
  34. ports:
  35. - containerPort: 3306
  36. name: mysql
  37. volumeMounts:
  38. - name: mysql-persistent-storage
  39. mountPath: /var/lib/mysql
  40. volumes:
  41. - name: mysql-persistent-storage
  42. persistentVolumeClaim:
  43. claimName: mysql-pv-claim
application/mysql/mysql-pv.yaml 运行一个单实例有状态应用 - 图2
  1. apiVersion: v1
  2. kind: PersistentVolume
  3. metadata:
  4. name: mysql-pv-volume
  5. labels:
  6. type: local
  7. spec:
  8. storageClassName: manual
  9. capacity:
  10. storage: 20Gi
  11. accessModes:
  12. - ReadWriteOnce
  13. hostPath:
  14. path: “/mnt/data
  15. —-
  16. apiVersion: v1
  17. kind: PersistentVolumeClaim
  18. metadata:
  19. name: mysql-pv-claim
  20. spec:
  21. storageClassName: manual
  22. accessModes:
  23. - ReadWriteOnce
  24. resources:
  25. requests:
  26. storage: 20Gi
  1. 部署 YAML 文件中定义的 PV 和 PVC:

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

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

    1. kubectl describe deployment mysql
    2. Name: mysql
    3. Namespace: default
    4. CreationTimestamp: Tue, 01 Nov 2016 11:18:45 -0700
    5. Labels: app=mysql
    6. Annotations: deployment.kubernetes.io/revision=1
    7. Selector: app=mysql
    8. Replicas: 1 desired | 1 updated | 1 total | 0 available | 1 unavailable
    9. StrategyType: Recreate
    10. MinReadySeconds: 0
    11. Pod Template:
    12. Labels: app=mysql
    13. Containers:
    14. mysql:
    15. Image: mysql:5.6
    16. Port: 3306/TCP
    17. Environment:
    18. MYSQL_ROOT_PASSWORD: password
    19. Mounts:
    20. /var/lib/mysql from mysql-persistent-storage (rw)
    21. Volumes:
    22. mysql-persistent-storage:
    23. Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    24. ClaimName: mysql-pv-claim
    25. ReadOnly: false
    26. Conditions:
    27. Type Status Reason
    28. ---- ------ ------
    29. Available False MinimumReplicasUnavailable
    30. Progressing True ReplicaSetUpdated
    31. OldReplicaSets: <none>
    32. NewReplicaSet: mysql-63082529 (1/1 replicas created)
    33. Events:
    34. FirstSeen LastSeen Count From SubobjectPath Type Reason Message
    35. --------- -------- ----- ---- ------------- -------- ------ -------
    36. 33s 33s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set mysql-63082529 to 1
  4. 列举出 Deployment 创建的 pods:

    1. kubectl get pods -l app=mysql
    2. NAME READY STATUS RESTARTS AGE
    3. mysql-63082529-2z3ki 1/1 Running 0 3m
  5. 查看 PersistentVolumeClaim:

    1. kubectl describe pvc mysql-pv-claim
    2. Name: mysql-pv-claim
    3. Namespace: default
    4. StorageClass:
    5. Status: Bound
    6. Volume: mysql-pv-volume
    7. Labels: <none>
    8. Annotations: pv.kubernetes.io/bind-completed=yes
    9. pv.kubernetes.io/bound-by-controller=yes
    10. Capacity: 20Gi
    11. Access Modes: RWO
    12. Events: <none>

访问 MySQL 实例

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

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

  1. kubectl run -it --rm --image=mysql:5.6 --restart=Never mysql-client -- mysql -h mysql -ppassword

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

  1. Waiting for pod default/mysql-client-274442439-zyp6i to be running, status is Pending, pod ready: false
  2. If you don't see a command prompt, try pressing enter.
  3. mysql>

更新

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

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

删除 Deployment

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

  1. kubectl delete deployment,svc mysql
  2. kubectl delete pvc mysql-pv-claim
  3. kubectl delete pv mysql-pv-volume

如果通过手动的方式分配 PersistentVolume, 那么也需要手动的删除它,以及释放下层资源. 如果是用过动态分配 PersistentVolume 的方式,在删除 PersistentVolumeClaim 后 PersistentVolume 将被自动的删除. 一些存储服务(比如 EBS 和 PD)也会在 PersistentVolume 被删除时自动回收下层资源.

接下来