运行单实例有状态应用程序

此页面展示了如何使用持久卷和部署在 Kubernetes 中运行单实例有状态应用程序。该应用程序是 MySQL。

目标

  • 创建一个引用您环境中磁盘的持久卷。
  • 创建一个 MySQL 部署。
  • 将 MySQL 暴露给集群中的其他 Pod,使其在已知 DNS 名称下可访问。

开始之前

  • 您需要拥有一个 Kubernetes 集群,并且 kubectl 命令行工具必须配置为与您的集群通信。建议在至少有两个节点的集群上运行本教程,这些节点不充当控制平面主机。如果您还没有集群,可以使用 minikube 创建一个,或者可以使用以下 Kubernetes 游乐场之一

    要检查版本,请输入 kubectl version

  • 您需要拥有一个 动态持久卷供应器,该供应器具有默认的 存储类,或者 静态供应持久卷 以满足此处使用的 持久卷声明

部署 MySQL

您可以通过创建 Kubernetes 部署并使用持久卷声明将其连接到现有持久卷来运行有状态应用程序。例如,此 YAML 文件描述了一个运行 MySQL 并引用持久卷声明的部署。该文件为 /var/lib/mysql 定义了一个卷挂载,然后创建一个持久卷声明,该声明查找 20G 卷。此声明将由满足要求的任何现有卷或动态供应器满足。

注意:密码在配置文件 YAML 中定义,这是不安全的。有关安全解决方案,请参阅 Kubernetes 秘密

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:
          # 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
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 文件的内容

    kubectl apply -f https://k8s.io/examples/application/mysql/mysql-deployment.yaml
    
  3. 显示有关部署的信息

    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. 列出部署创建的 Pod

    kubectl get pods -l app=mysql
    

    输出类似于以下内容

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

    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 访问数据库。服务选项 clusterIP: None 使服务 DNS 名称直接解析到 Pod 的 IP 地址。当您只有一个 Pod 在服务后面并且您不打算增加 Pod 数量时,这是最佳选择。

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

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

此命令在集群中创建一个运行 MySQL 客户端的新 Pod,并通过服务将其连接到服务器。如果它连接成功,则表示您的有状态 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>

更新

可以使用 kubectl apply 命令像往常一样更新部署的镜像或任何其他部分。以下是一些特定于有状态应用程序的注意事项

  • 不要扩展应用程序。此设置仅适用于单实例应用程序。底层持久卷只能挂载到一个 Pod。对于集群有状态应用程序,请参阅 StatefulSet 文档
  • 在部署配置 YAML 文件中使用 strategy: type: Recreate。这指示 Kubernetes 不要 使用滚动更新。滚动更新将不起作用,因为您一次只能运行一个 Pod。Recreate 策略将在创建具有更新配置的新 Pod 之前停止第一个 Pod。

删除部署

按名称删除已部署的对象

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

如果您手动供应了持久卷,则还需要手动删除它,以及释放底层资源。如果您使用了动态供应器,它会在看到您删除了持久卷声明时自动删除持久卷。一些动态供应器(例如 EBS 和 PD 的供应器)也会在删除持久卷时释放底层资源。

下一步

上次修改时间:2023 年 8 月 24 日下午 6:38 PST:使用 code_sample shortcode 代替 code shortcode (e8b136c3b3)