Information in this document may be out of date
This document has an older update date than the original, so the information it contains may be out of date. If you're able to read English, see the English version for the most up-to-date information: Run a Single-Instance Stateful Application
运行一个单实例有状态应用
本文介绍在 Kubernetes 中如何使用 PersistentVolume 和 Deployment 运行一个单实例有状态应用。 该示例应用是 MySQL。
教程目标
- 在你的环境中创建一个引用磁盘的 PersistentVolume。
- 创建一个 MySQL Deployment。
- 在集群内以一个已知的 DNS 名称将 MySQL 暴露给其他 Pod。
准备开始
你必须拥有一个 Kubernetes 的集群,同时你必须配置 kubectl 命令行工具与你的集群通信。 建议在至少有两个不作为控制平面主机的节点的集群上运行本教程。 如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面的 Kubernetes 练习环境之一:
要获知版本信息,请输入kubectl version
.你需要有一个带有默认 StorageClass的 动态 PersistentVolume 供应程序, 或者自己静态的提供 PersistentVolume 来满足这里使用的 PersistentVolumeClaim。
部署 MySQL
你可以通过创建一个 Kubernetes Deployment 并使用 PersistentVolumeClaim 将其连接到 某已有的 PersistentVolume 来运行一个有状态的应用。 例如,这里的 YAML 描述的是一个运行 MySQL 的 Deployment,其中引用了 PersistentVolumeClaim。 文件为 /var/lib/mysql 定义了卷挂载,并创建了一个 PersistentVolumeClaim,寻找一个 20G 大小的卷。 该申领可以通过现有的满足需求的卷来满足,也可以通过动态供应卷的机制来满足。
注意:在配置的 YAML 文件中定义密码的做法是不安全的。具体安全解决方案请参考 Kubernetes Secrets。
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
clusterIP: None
---
apiVersion: apps/v1
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:
# 在实际中使用 secret
- 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
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
部署 YAML 文件中定义的 PV 和 PVC:
kubectl apply -f https://k8s.io/examples/application/mysql/mysql-pv.yaml
部署 YAML 文件中定义的 Deployment:
kubectl apply -f https://k8s.io/examples/application/mysql/mysql-deployment.yaml
展示 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
列举出 Deployment 创建的 Pod:
kubectl get pods -l app=mysql
输出类似于:
NAME READY STATUS RESTARTS AGE mysql-63082529-2z3ki 1/1 Running 0 3m
查看 PersistentVolumeClaim:
kubectl describe pvc mysql-pv-claim
输出类似于:
Name: mysql-pv-claim Namespace: default StorageClass: Status: Bound Volume: mysql-pv-volume Labels: <none> Annotations: pv.kubernetes.io/bind-completed=yes pv.kubernetes.io/bound-by-controller=yes Capacity: 20Gi Access Modes: RWO Events: <none>
访问 MySQL 实例
前面 YAML 文件中创建了一个允许集群内其他 Pod 访问的数据库 Service。该 Service 中选项
clusterIP: None
让 Service 的 DNS 名称直接解析为 Pod 的 IP 地址。
当在一个 Service 下只有一个 Pod 并且不打算增加 Pod 的数量这是最好的。
运行 MySQL 客户端以连接到服务器:
kubectl run -it --rm --image=mysql:5.6 --restart=Never mysql-client -- mysql -h mysql -ppassword
此命令在集群内创建一个新的 Pod 并运行 MySQL 客户端,并通过 Service 连接到服务器。 如果连接成功,你就知道有状态的 MySQL 数据库正处于运行状态。
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 文档。
- 在 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-volume
如果通过手动的方式供应 PersistentVolume,那么也需要手动删除它以释放下层资源。 如果是用动态供应方式创建的 PersistentVolume,在删除 PersistentVolumeClaim 后 PersistentVolume 将被自动删除。 一些存储服务(比如 EBS 和 PD)也会在 PersistentVolume 被删除时自动回收下层资源。
接下来
欲进一步了解 Deployment 对象,请参考 Deployment 对象
进一步了解部署应用