2.16. 使用卷快照的持久性存储

重要

OpenShift Container Platform 4.2 中已弃用卷快照。

本文介绍了如何使用 VolumeSnapshot 来防止 OpenShift Container Platform 中发生数据丢失。建议先熟悉持久性卷

重要

卷快照只是技术预览功能。技术预览功能不被红帽产品服务等级协议 (SLA) 支持,且可能在功能方面有缺陷。红帽不推荐在生产环境中使用它们。这些技术预览功能可以使用户提早试用新的功能,并有机会在开发阶段提供反馈意见。

有关红帽技术预览功能支持范围的详情,请参阅 https://access.redhat.com/support/offerings/techpreview/

2.16.1. 关于快照

卷快照是集群中的一个存储卷的快照。外部快照控制器和置备程序支持使用 OpenShift Container Platform 集群中的功能,并通过 OpenShift Container Platform API 处理卷快照。

使用卷快照时,集群管理员能够:

  • 为绑定到 PersistentVolumeClaim 的 PersistentVolume 创建快照。
  • 列出现有的 VolumeSnapshot。
  • 删除现有的 VolumeSnapshot。
  • 从现有 VolumeSnapshot 创建新的 PersistentVolume。

支持的 PersistentVolume 类型

  • AWS Elastic Block Store (EBS)
  • Google Compute Engine (GCE) Persistent Disk (PD)

2.16.2. 外部控制器和置备程序

控制器和置备程序提供卷快照功能。这些外部组件在集群中运行。

提供卷快照的两个外部组件:

外部控制器
创建、删除和报告有关卷快照的事件。
外部置备程序
从 VolumeSnapshot 创建新的 PersistentVolume。

外部控制器和置备程序服务以容器镜像形式分发,并可像平常一样在 OpenShift Container Platform 集群中运行。

2.16.2.1. 运行外部控制器和置备程序

集群管理员必须配置访问权限,以运行外部控制器和置备程序。

流程

允许容器管理 API 对象:

  1. 创建 ServiceAccount 和 ClusterRole:

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: snapshot-controller-runner
    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: snapshot-controller-role
    rules:
      - apiGroups: [""]
        resources: ["persistentvolumes"]
        verbs: ["get", "list", "watch", "create", "delete"]
      - apiGroups: [""]
        resources: ["persistentvolumeclaims"]
        verbs: ["get", "list", "watch", "update"]
      - apiGroups: ["storage.k8s.io"]
        resources: ["storageclasses"]
        verbs: ["get", "list", "watch"]
      - apiGroups: [""]
        resources: ["events"]
        verbs: ["list", "watch", "create", "update", "patch"]
      - apiGroups: ["apiextensions.k8s.io"]
        resources: ["customresourcedefinitions"]
        verbs: ["create", "list", "watch", "delete"]
      - apiGroups: ["volumesnapshot.external-storage.k8s.io"]
        resources: ["volumesnapshots"]
        verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
      - apiGroups: ["volumesnapshot.external-storage.k8s.io"]
        resources: ["volumesnapshotdatas"]
        verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  2. 作为集群管理员,提供 hostNetwork安全 上下文约束 (SCC):

    # oc adm policy add-scc-to-user hostnetwork -z snapshot-controller-runner

    此 SCC 控制对 Pod 正在使用的 snapshot-controller-runner 服务帐户的访问。

  3. 通过 ClusterRoleBinding 绑定规则:

    apiVersion: rbac.authorization.k8s.io/v1beta1
    kind: ClusterRoleBinding
    metadata:
      name: snapshot-controller
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: snapshot-controller-role
    subjects:
    - kind: ServiceAccount
      name: snapshot-controller-runner
      namespace: default 1
    1
    指定 snapshot-controller 所在的项目名称。

2.16.2.2. AWS 和 GCE 身份验证

为进行外部控制器和置备程序身份验证,云供应商可能需要管理员提供 Secret。

2.16.2.2.1. AWS 身份验证

如果外部控制器和置备程序部署在 Amazon Web Services (AWS) 中,AWS 必须能够使用访问密钥进行身份验证。

为向 Pod 提供凭证,集群管理员要创建一个新的 Secret:

apiVersion: v1
kind: Secret
metadata:
  name: awskeys
type: Opaque
data:
  access-key-id: <base64 encoded AWS_ACCESS_KEY_ID>
  secret-access-key: <base64 encoded AWS_SECRET_ACCESS_KEY>
重要

在为 awskeys secret 生成 base64 值时,请删除结尾的换行符:

$ echo -n "<aws_access_key_id>" | base64
$ echo -n "<aws_secret_access_key>" | base64

下例展示了外部控制器和置备程序容器的 AWS 部署。两个 Pod 容器都使用 Secret 访问 AWS API。

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: snapshot-controller
spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: snapshot-controller
    spec:
      serviceAccountName: snapshot-controller-runner
      hostNetwork: true
      containers:
        - name: snapshot-controller
          image: "registry.redhat.io/openshift3/snapshot-controller:latest"
          imagePullPolicy: "IfNotPresent"
          args: ["-cloudprovider", "aws"]
          env:
            - name: AWS_ACCESS_KEY_ID
              valueFrom:
                secretKeyRef:
                  name: awskeys
                  key: access-key-id
            - name: AWS_SECRET_ACCESS_KEY
              valueFrom:
                secretKeyRef:
                  name: awskeys
                  key: secret-access-key
        - name: snapshot-provisioner
          image: "registry.redhat.io/openshift3/snapshot-provisioner:latest"
          imagePullPolicy: "IfNotPresent"
          args: ["-cloudprovider", "aws"]
          env:
            - name: AWS_ACCESS_KEY_ID
              valueFrom:
                secretKeyRef:
                  name: awskeys
                  key: access-key-id
            - name: AWS_SECRET_ACCESS_KEY
              valueFrom:
                secretKeyRef:
                  name: awskeys
                  key: secret-access-key
2.16.2.2.2. GCE 身份验证

对于 Google Compute Engine (GCE),无需使用 Secret 来访问 GCE API。

管理员可以按照下例所示进行部署:

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: snapshot-controller
spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: snapshot-controller
    spec:
      serviceAccountName: snapshot-controller-runner
      containers:
        - name: snapshot-controller
          image: "registry.redhat.io/openshift3/snapshot-controller:latest"
          imagePullPolicy: "IfNotPresent"
          args: ["-cloudprovider", "gce"]
        - name: snapshot-provisioner
          image: "registry.redhat.io/openshift3/snapshot-provisioner:latest"
          imagePullPolicy: "IfNotPresent"
          args: ["-cloudprovider", "gce"]

2.16.2.3. 管理快照用户

根据集群配置,可能需要允许非管理员用户操作 API 服务器上的 VolumeSnapshot 对象。这可以通过创建一个绑定到特定用户或组的 ClusterRole 来完成。

例如,假设用户“alice”需要使用集群中的快照。集群管理员完成下列步骤:

  1. 定义一个新的 ClusterRole:

    apiVersion: v1
    kind: ClusterRole
    metadata:
      name: volumesnapshot-admin
    rules:
    - apiGroups:
      - "volumesnapshot.external-storage.k8s.io"
      attributeRestrictions: null
      resources:
      - volumesnapshots
      verbs:
      - create
      - delete
      - deletecollection
      - get
      - list
      - patch
      - update
      - watch
  2. 通过创建一个 ClusterRoleBinding 绑定对象,将集群角色绑定到用户“alice”:

    apiVersion: rbac.authorization.k8s.io/v1beta1
    kind: ClusterRoleBinding
    metadata:
      name: volumesnapshot-admin
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: volumesnapshot-admin
    subjects:
    - kind: User
      name: alice
注意

这只是 API 访问配置的一个示例。VolumeSnapshot 对象的行为与其他 OpenShift Container Platform API 对象类似。有关管理 API RBAC 的详情,请参阅 API 访问控制文档

2.16.3. 创建和删除快照

与持久性卷声明 (PVC) 绑定到持久性卷 (PV) 来置备卷的方式类似,VolumeSnapshotData 和 VolumeSnapshot 用于创建卷快照。

卷快照必须使用受支持的 PersistentVolume 类型。

2.16.3.1. 创建快照

要获取 PV 快照,请基于 VolumeSnapshot 创建一个新的 VolumeSnapshotData 对象,如下例所示:

apiVersion: volumesnapshot.external-storage.k8s.io/v1
kind: VolumeSnapshot 1
metadata:
  name: snapshot-demo
spec:
  persistentVolumeClaimName: ebs-pvc 2
1
基于 VolumeSnapshot 自动创建 VolumeSnapshotData 对象。
2
persistentVolumeClaimName 是绑定到 PersistentVolume 的 PersistentVolumeClaim 的名称。已为此特定 PV 创建了快照。

根据 PV 类型,创建快照操作可能会经历若干阶段,由不同的 VolumeSnapshot 状态来体现:

  1. 创建新的 VolumeSnapshot 对象。
  2. 启动控制器。可能需要冻结快照的 PersistentVolume,并且暂停应用程序。
  3. 创建(“截取”)快照。快照的 PersistentVolume 可能会恢复正常运作,但快照本身还没有就绪(status=True,type=Pending)。
  4. 创建新的 VolumeSnapshotData 对象,该对象代表实际快照。
  5. 快照已完成,且已可用(status=True,type=Ready)。
重要

用户负责确保数据一致性(停止 Pod 或应用程序,清除缓存,以及冻结文件系统等)。

注意

如果出现错误,VolumeSnapshot 状态中会带有出错信息。

显示 VolumeSnapshot 状态:

$ oc get volumesnapshot -o yaml

此时会显示这个状态,如下例所示:

apiVersion: volumesnapshot.external-storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  clusterName: ""
  creationTimestamp: 2017-09-19T13:58:28Z
  generation: 0
  labels:
    Timestamp: "1505829508178510973"
  name: snapshot-demo
  namespace: default 1
  resourceVersion: "780"
  selfLink: /apis/volumesnapshot.external-storage.k8s.io/v1/namespaces/default/volumesnapshots/snapshot-demo
  uid: 9cc5da57-9d42-11e7-9b25-90b11c132b3f
spec:
  persistentVolumeClaimName: ebs-pvc
  snapshotDataName: k8s-volume-snapshot-9cc8813e-9d42-11e7-8bed-90b11c132b3f
status:
  conditions:
  - lastTransitionTime: null
    message: Snapshot created successfully
    reason: ""
    status: "True"
    type: Ready
  creationTimestamp: null
1
指定 snapshot-controller 所在的项目名称。

2.16.3.2. 恢复快照

PVC 用于恢复快照。但是,管理员必须先创建一个 StorageClass,以便从现有 VolumeSnapshot 恢复 PersistentVolume。

  1. 创建 StorageClass:

    kind: StorageClass
    apiVersion: storage.k8s.io/v1
    metadata:
      name: snapshot-promoter
    provisioner: volumesnapshot.external-storage.k8s.io/snapshot-promoter
    parameters: 1
      encrypted: "true"
      type: gp2
    1
    如果您使用配置了 gp2 encryption 加密的 AWS EBS 存储,您必须设置 encryptedtype 参数。
  2. 创建 PVC:

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: snapshot-pv-provisioning-demo
      annotations:
        snapshot.alpha.kubernetes.io/snapshot: snapshot-demo 1
    spec:
      storageClassName: snapshot-promoter 2
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi 3
    1
    要恢复的 VolumeSnapshot 的名称。
    2
    由管理员创建,用于恢复 VolumeSnapshot。
    3
    恢复快照的存储大小必须足够大,以便适应原始 PV 的大小。

    创建一个新的 PersistentVolume 并绑定到 PersistentVolumeClaim。此过程可能需要几分钟,具体视 PV 类型而异。

2.16.3.3. 删除快照

删除 VolumeSnapshot:

$ oc delete volumesnapshot/<snapshot-name>

系统将自动删除绑定到 VolumeSnapshot 的 VolumeSnapshotData。