Cuando una aplicación con estado en Container Service for Kubernetes (ACK) utiliza varios discos, tomar instantáneas de volumen individuales de cada disco por separado puede generar puntos de recuperación inconsistentes, ya que cada instantánea captura un momento ligeramente distinto. Las instantáneas de grupo resuelven este problema al activar todas las instantáneas simultáneamente, de modo que cada disco del grupo se captura en el mismo instante. Esto reduce el riesgo de inconsistencia de datos cuando necesita restaurar una aplicación en varios volúmenes.
Funcionamiento
Las instantáneas de grupo se basan en los grupos consistentes de instantáneas de ECS. ACK proporciona las siguientes definiciones de recursos personalizados (CRD) que puede utilizar para gestionar las instantáneas de grupo:
|
CRD |
Análogo a |
Propósito |
|
VolumeGroupSnapshotClass |
StorageClass |
Define el controlador y la política de eliminación para las instantáneas de grupo |
|
VolumeGroupSnapshot |
PersistentVolumeClaim (PVC) |
Una solicitud para crear una instantánea de un conjunto de discos, identificados mediante un selector de etiquetas |
|
VolumeGroupSnapshotContent |
PersistentVolume (PV) |
Registra el grupo consistente de instantáneas de ECS creado para la solicitud |
|
VolumeSnapshot |
— |
Una solicitud de instantánea de volumen; se crea automáticamente para cada disco después de crear un VolumeGroupSnapshot |
|
VolumeSnapshotContent |
— |
Registra información sobre una instantánea de ECS |
Al crear un VolumeGroupSnapshot, el plugin de Container Storage Interface (CSI) crea un grupo consistente de instantáneas de ECS y genera automáticamente un VolumeSnapshot y un VolumeSnapshotContent para cada disco seleccionado. Si un disco falla, restáurelo desde el VolumeSnapshot correspondiente.
Facturación
Los grupos consistentes de instantáneas son gratuitos. Las instantáneas dentro del grupo se facturan según el almacenamiento consumido. Para más detalles, consulte Snapshot billing.
Límites
Las instantáneas de grupo están sujetas a los mismos límites que las instantáneas de ECS. Consulte Limits.
Los tiempos de caducidad no son compatibles con los grupos consistentes de instantáneas de ECS. Elimine las instantáneas de grupo manualmente cuando ya no las necesite.
Requisitos previos
Antes de empezar, asegúrese de contar con lo siguiente:
Un clúster administrado de ACK que ejecute Kubernetes 1.28 o posterior. Consulte Create an ACK managed cluster.
El plugin de CSI instalado en la versión 1.31.4 o posterior. Para actualizar csi-plugin y csi-provisioner, consulte Update csi-plugin and csi-provisioner.
El servicio de instantáneas de Elastic Compute Service (ECS) activado (la activación es gratuita). Consulte Activate ECS Snapshot.
Si el clúster utiliza FlexVolume (obsoleto en ACK), actualice a CSI antes de crear instantáneas de grupo. Consulte Upgrade from FlexVolume to CSI. Para comprobar qué plugin de volumen está instalado, vaya a la página de detalles del clúster en la consola de ACK, seleccione Operations > Add-ons en el panel de navegación izquierdo y haga clic en la pestaña Storage.
Paso 1: Habilitar la compuerta de función
Habilite la compuerta de función EnableVolumeGroupSnapshots en csi-provisioner antes de crear instantáneas de grupo.
Inicie sesión en la consola de ACK. En el panel de navegación izquierdo, haga clic en Clusters.
En la página Clusters, haga clic en el nombre del clúster. En el panel de navegación izquierdo, seleccione Operations > Add-ons.
En la página Add-ons, busque la tarjeta de csi-provisioner y haga clic en Configuration en la esquina inferior derecha.
En el cuadro de diálogo csi-provisioner Parameters, establezca el campo FeatureGate en
EnableVolumeGroupSnapshots=truey haga clic en OK. Si ya hay otras compuertas de función habilitadas, agregue la nueva al final:xxxxxx=true,yyyyyy=false,EnableVolumeGroupSnapshots=true.
Paso 2: Desplegar un StatefulSet de MySQL
Este ejemplo utiliza un StatefulSet de MySQL con dos réplicas. Cada réplica monta un disco ESSD de 20 GiB como PVC, lo que le proporciona dos discos para crear una instantánea de grupo.
-
Cree el archivo
mysql.yamlcon el siguiente contenido: <details><summary>mysql.yaml</summary>apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql spec: selector: matchLabels: app: mysql serviceName: "mysql" replicas: 2 template: metadata: labels: app: mysql spec: containers: - name: mysql image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/mysql:8.0.30-8.6 env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-pass key: password imagePullPolicy: IfNotPresent volumeMounts: - name: data mountPath: /var/lib/mysql # MySQL data directory subPath: mysql volumeClaimTemplates: - metadata: name: data spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "alicloud-disk-essd" resources: requests: storage: 20Gi --- apiVersion: v1 kind: Secret metadata: name: mysql-pass type: Opaque data: password: MTIzNDU2 # Base64-encoded value of "123456" username: cm9vdA== # Base64-encoded value of "root"</details>
-
Despliegue el StatefulSet:
kubectl apply -f mysql.yaml -
Escriba datos de prueba en ambas réplicas de pod. Inicie sesión en el pod
mysql-0e inserte una fila:kubectl exec -it mysql-0 -- bash # Open a shell in the pod mysql -uroot -p123456 # Connect to MySQLCREATE DATABASE test; USE test; CREATE TABLE scores ( name VARCHAR(50) NOT NULL, score INT AUTO_INCREMENT PRIMARY KEY ); INSERT INTO scores(name, score) VALUES ("Amy", 95); SELECT * FROM scores;Salida esperada:
+------+-------+ | name | score | +------+-------+ | Amy | 95 | +------+-------+Repita los mismos pasos para el pod
mysql-1.
Paso 3: Crear instantáneas de grupo
Crear un VolumeGroupSnapshotClass
Ya existe en el clúster un VolumeGroupSnapshotClass predeterminado llamado alibabacloud-disk-group-snapshot. Para usar una clase personalizada, cree el archivo group-snapshot-class-demo.yaml:
apiVersion: groupsnapshot.storage.k8s.io/v1alpha1
kind: VolumeGroupSnapshotClass
metadata:
name: group-snapshot-class-demo
deletionPolicy: Delete
driver: diskplugin.csi.alibabacloud.com
El campo deletionPolicy controla qué sucede con el grupo consistente de instantáneas de ECS subyacente cuando elimina el VolumeGroupSnapshot:
|
Valor |
Comportamiento |
|
|
Elimina el VolumeGroupSnapshotContent y el grupo consistente de instantáneas de ECS |
|
|
Conserva el VolumeGroupSnapshotContent y el grupo consistente de instantáneas de ECS |
Aplique la clase:
kubectl apply -f group-snapshot-class-demo.yaml
Crear un VolumeGroupSnapshot
Cree el archivo group-snapshot-demo.yaml para crear una instantánea de ambos PVC montados en la aplicación MySQL:
apiVersion: groupsnapshot.storage.k8s.io/v1alpha1
kind: VolumeGroupSnapshot
metadata:
name: group-snapshot-demo
namespace: default
spec:
source:
selector:
matchLabels:
app: mysql # Selects all PVCs with this label
volumeGroupSnapshotClassName: group-snapshot-class-demo
El campo source.selector utiliza un selector de etiquetas para identificar los PVC que se van a respaldar. Los PVC creados a partir de las plantillas volumeClaimTemplates de un StatefulSet se etiquetan automáticamente con las etiquetas de pod del StatefulSet. Si creó sus PVC manualmente, agregue las etiquetas correspondientes antes de ejecutar este paso.
Aplique el VolumeGroupSnapshot:
kubectl apply -f group-snapshot-demo.yaml
Paso 4: Verificar las instantáneas de grupo
-
Monitoree el VolumeGroupSnapshot hasta que
READYTOUSEcambie defalseatrue:kubectl get vgs group-snapshot-demo -w -
Inspeccione los detalles de la instantánea para ver qué PVC corresponde a cada VolumeSnapshot:
Campo
Descripción
Bound Volume Group Snapshot Content NameEl VolumeGroupSnapshotContent vinculado a este VolumeGroupSnapshot
Persistent Volume Claim RefEl nombre del PVC respaldado
Volume Snapshot RefEl VolumeSnapshot creado para ese PVC
kubectl describe vgs group-snapshot-demoSalida esperada (abreviada):
Status: Bound Volume Group Snapshot Content Name: groupsnapcontent-adcef6ef-811a-4e9d-ba51-3927caxxxxxx Creation Time: 2024-11-27T06:02:56Z Pvc Volume Snapshot Ref List: Persistent Volume Claim Ref: Name: disk-mysql-0 Volume Snapshot Ref: Name: snapshot-1c2c5bcaf47ee2bffcc5b2f52dff65a4aacaaea38032c05d75acd536f7xxxxxx-2024-11-27-6.4.7 Persistent Volume Claim Ref: Name: disk-mysql-1 Volume Snapshot Ref: Name: snapshot-37a2fbf634d68cd2103f261313c2ed781fbd2bd52b5a0d0e0c0ef7c339xxxxxx-2024-11-27-6.4.9 -
Confirme que ambos VolumeSnapshot estén listos:
kubectl get volumesnapshotAmbas instantáneas deben mostrar
READYTOUSE: true. -
Obtenga el ID del grupo consistente de instantáneas de ECS:
kubectl describe vgsc groupsnapcontent-adcef6ef-811a-4e9d-ba51-3927caxxxxxxSalida esperada (abreviada):
Volume Group Snapshot Handle: ssg-2zeg72d1qym6vnxxxxxxPara ver el grupo consistente de instantáneas en la consola de ECS, vaya a la consola de ECS, seleccione Storage & Snapshots > Snapshots en el panel de navegación izquierdo, haga clic en la pestaña Snapshot-consistent Groups y busque
ssg-2zeg72d1qym6vnxxxxxx.
Paso 5: Restaurar volúmenes de disco desde instantáneas
Hay dos opciones de restauración disponibles: restaurar un solo volumen manualmente o restaurar todos los volúmenes en un solo lote mediante un script.
Opción 1: Restaurar un solo volumen
El siguiente ejemplo restaura el volumen de disco conectado al pod disk-mysql-0.
Cree el archivo disk-mysql-0-copy.yaml. El campo dataSource indica a CSI que aprovisione un nuevo disco a partir del VolumeSnapshot especificado:
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: disk-mysql-0-copy
spec:
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
storageClassName: "alicloud-disk-essd"
dataSource:
name: snapshot-1c2c5bcaf47ee2bffcc5b2f52dff65a4aacaaea38032c05d75acd536f7xxxxxx-2024-11-27-6.4.7 # [1]
kind: VolumeSnapshot # [2]
apiGroup: snapshot.storage.k8s.io # [3]
[1] El nombre del VolumeSnapshot que respalda a
disk-mysql-0(tomado de la salida dekubectl describe vgsanterior).[2] El tipo de recurso: siempre debe ser
VolumeSnapshotal restaurar desde una instantánea.[3] El grupo de API para los recursos de instantáneas de CSI.
Aplique el PVC:
kubectl apply -f disk-mysql-0-copy.yaml
Verifique que el PVC esté vinculado:
kubectl get pvc disk-mysql-0-copy
Salida esperada:
disk-mysql-0-copy Bound d-2ze0iwwqg0s6b0xxxxxx 20Gi RWO alicloud-disk-essd <unset> 69s
Para confirmar que el disco se creó a partir de la instantánea, vaya a la consola de ECS, seleccione Storage & Snapshots > Block Storage en el panel de navegación izquierdo, haga clic en la pestaña Cloud Disk y busque d-2ze0iwwqg0s6b0xxxxxx. Abra la página de detalles del disco para verificar que se creó a partir de una instantánea.
Opción 2: Restaurar todos los volúmenes en un solo lote
Utilice el script generate_pvc.sh para generar automáticamente manifiestos de PVC a partir de un VolumeGroupSnapshot y aplicarlos todos a la vez.
-
Instale la herramienta de línea de comandos
jq:CentOS:
yum install jqUbuntu:
apt-get install jq
-
Escale el StatefulSet de MySQL a cero réplicas para detener todas las escrituras antes de restaurar:
kubectl scale sts mysql --replicas=0 -
Elimine los PVC existentes:
kubectl delete pvc data-mysql-0 data-mysql-1 -
Cree el archivo
generate_pvc.shcon el siguiente contenido: <details><summary>generate_pvc.sh</summary>Parámetro
Descripción
Ejemplo
1
Namespace del VolumeGroupSnapshot
default2
Nombre del VolumeGroupSnapshot
group-snapshot-demo3
Nombre de StorageClass para los PVC restaurados
alicloud-disk-essd4
Capacidad del disco
20Gi5
Ruta al archivo kubeconfig
.kube/config6
Ruta de salida para el YAML de PVC generado
./output.yaml#!/bin/bash # Input parameters NAMESPACE=$1 # Namespace of the VolumeGroupSnapshot VGS_NAME=$2 # Name of the VolumeGroupSnapshot STORAGE_CLASS_NAME=$3 # StorageClass for the restored PVCs CAPACITY=$4 # Disk capacity (e.g., 20Gi) KUBECONFIG_PATH=$5 # Path to the kubeconfig file OUTPUT_FILE=$6 # Output path for the generated YAML # Get VolumeGroupSnapshot details VGS_INFO=$(kubectl --kubeconfig=${KUBECONFIG_PATH} -n ${NAMESPACE} get vgs ${VGS_NAME} -o json) # Validate that the PVC-snapshot mapping exists if ! echo ${VGS_INFO} | jq -e '.status.pvcVolumeSnapshotRefList' &>/dev/null; then echo "Error: .status.pvcVolumeSnapshotRefList not found in VolumeGroupSnapshot." exit 1 fi # Extract PVC names and their corresponding snapshot names PVCS=($(echo ${VGS_INFO} | jq -r '.status.pvcVolumeSnapshotRefList[].persistentVolumeClaimRef.name')) SNAPSHOTS=($(echo ${VGS_INFO} | jq -r '.status.pvcVolumeSnapshotRefList[].volumeSnapshotRef.name')) # Clear the output file > ${OUTPUT_FILE} # Generate one PVC manifest per disk for i in "${!PVCS[@]}"; do PVC_NAME=${PVCS[$i]} SNAPSHOT_NAME=${SNAPSHOTS[$i]} cat <<EOF >> ${OUTPUT_FILE} --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: ${PVC_NAME} spec: volumeMode: Filesystem accessModes: - ReadWriteOnce resources: requests: storage: ${CAPACITY} storageClassName: "${STORAGE_CLASS_NAME}" dataSource: name: ${SNAPSHOT_NAME} kind: VolumeSnapshot apiGroup: snapshot.storage.k8s.io EOF done echo "PVC YAML files have been written to ${OUTPUT_FILE}"</details> El script acepta seis parámetros posicionales:
-
Ejecute el script para generar los manifiestos de PVC:
bash generate_pvc.sh default group-snapshot-demo alicloud-disk-essd 20Gi .kube/config ./output.yamlEl archivo
output.yamlgenerado tendrá un aspecto similar al siguiente:--- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: disk-mysql-0 spec: volumeMode: Filesystem accessModes: - ReadWriteOnce resources: requests: storage: 20Gi storageClassName: "alicloud-disk-essd" dataSource: name: snapshot-1c2c5bcaf47ee2bffcc5b2f52dff65a4aacaaea38032c05d75acd536f7adb850-2024-11-27-6.4.7 kind: VolumeSnapshot apiGroup: snapshot.storage.k8s.io --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: disk-mysql-1 spec: volumeMode: Filesystem accessModes: - ReadWriteOnce resources: requests: storage: 20Gi storageClassName: "alicloud-disk-essd" dataSource: name: snapshot-37a2fbf634d68cd2103f261313c2ed781fbd2bd52b5a0d0e0c0ef7c3396fea1c-2024-11-27-6.4.9 kind: VolumeSnapshot apiGroup: snapshot.storage.k8s.ioEdite
output.yamlsi es necesario y luego aplíquelo:kubectl apply -f output.yaml -
Escale el StatefulSet nuevamente a dos réplicas:
kubectl scale sts mysql --replicas=2 -
Después de que se reinicien los pods, verifique que los datos se hayan restaurado:
kubectl exec -it mysql-0 -- bash # Open a shell in the pod mysql -uroot -p123456 # Connect to MySQL use test; select * from scores;Salida esperada:
+------+-------+ | name | score | +------+-------+ | Amy | 95 | +------+-------+