1. 背景与本文目标

每当看向 CNCF Landscape 的时候,我都会有种感叹,云原生富饶的生态环境,已经制造了一场云原生世界的寒武纪生命大爆发。这些云原生应用都在不同的领域做着应有的贡献,由于他们都遵循着云原生的开发标准,他们的结合又是那样的契合。云原生应用正在向着轻量、灵活、易交付的方向前进着,并借助 Kubernetes 云原生框架轻松与多种外部软硬件系统集成,形成多种企业级解决方案。相信在今后无论是个人用户还是企业级用户都会在云原生的环境中得到收益。

虽然应用架构的发展正在转向容器化Serverless ,但企业也为虚拟机上运行的应用程序进行了大量投资,而且这其中有许多正在承担着企业的重要服务。在 Kubernetes 环境中运行虚拟机已经不是什么新鲜的事,目前 Redhat 开源的 kubevirtMirantis 开源的 virtlet 都提供了以容器方式运行虚拟机的方案。这将允许开发人员在一个平台上,将虚拟机 (VM) 引入容器化工作与管理流程,这样他们就可以在统一的容器化平台中并行开发、管理和部署虚拟机以及容器和 Serverless 。

本篇文章将探讨如何利用 Kasten K10 保护青云云原生虚拟化平台 KSV (KubeSphere Virtualization)。KubeSphere 虚拟化(KSV)是由 KubeSphere 衍生的轻量化虚拟机管理平台,可满足企业级虚拟化业务需求。而利用 Kasten 将其以云原生的方式进行数据保护是我们本次讨论的重点,以下是本期同步视频。

本期同步视频

2. Kasten K10 与 青云 KubeSphere 虚拟化平台 KSV

Kasten K10

Kasten K10 是 Veeam 在 Kubernetes 平台的数据管理解决方案,通过部署 Kasten K10 企业可以安全地备份和还原、执行灾难恢复以及迁移云原生的应用。Kubernetes 集群资源和持久卷等存储资源。解决用户备份、灾难恢复、迁移过程中的数据管理问题,提高云原生环境数据管理的便捷性,帮助用户降低灾备成本,提高生产执行效率。

57febade8f28e2e641315cd73ff67e47.png
20220302121303

KubeSphere 虚拟化 KSV

KubeSphere 虚拟化(KSV)是由 KubeSphere 衍生的轻量化虚拟机管理平台,支持单节点部署和多节点部署,便捷易用,满足企业级虚拟化业务需求。KubeSphere 虚拟化采用了前后端分离的架构,实现了面向云原生的设计,各个模块松耦合设计。KubeSphere 虚拟化无底层的基础设施依赖,可以运行支持虚拟化的主机之上。

3949ee442b685994c3f67e8f5c905300.png
20220302135252

从 KSV 的官方文档我们了解到,KSV 基于 Kubernetes 容器平台,集成了多个云原生组件。前端提供图形化的 Web 控制台,支持资源概览、节点管理、IP 池管理、虚拟机管理、镜像管理、磁盘管理、项目管理、告警管理、日志管理、用户管理和 KSV助手等功能。通过 KSV API 服务和 KSV 控制器与后端交互,后端集成了 KubeVirt、MinIO、Multus、Calico 等多个云原生组件,底层基础设施集群可包含多个服务器节点以实现生产环境虚拟机业务的高可用性。

3. 验证目标

在本次验证场景中,我们将利用 Kasten K10 以保护云原生应用的方式,保护青云虚拟化管理平台 KSV。

  • 登录 KSV 虚拟化管理平台,查看与管理节点与资源池

  • 在 KSV 中创建项目与虚拟机,写入数据

  • 安装 Kasten K10 到 KSV 所在的 K3S Cluster

  • 用 Kasten 保护 KSV 中创建的项目与虚拟机

  • 还原 KSV 虚拟机及数据

利用 K10 对 Ceph rdb CSI 存储 API 进行调用生成快照,达成最快速的 RPO 与 RTO的备份与恢复 利用青云对象存储,将快照数据导出到对象存储桶上,实现了异地容灾与数据长期保留

达成效果:

利用 Ceph RBD CSI 快照,在本地 Kubenetes 环境,实现云原生应用的快速备份与恢复,利用青云 QingCloud 对象存储,在本地形成长期保留的同时,利用 Kasten K10 直接将数据容灾到远端,或利用对象存储实现存储桶的复制,实现 3-2-1-1-0 的数据保护。

4. 利用 KubeSphere 虚拟化 KSV 创建项目与虚拟机

4.1. 登录 KubeSphere 虚拟化平台

打开 Web 浏览器,在地址栏中输入 KSV Web 控制台的 IP 地址和端口号。

2416d8e37798424b92e814f96e3d37e7.png
20220302140532

登录后可以看到 KSV 的仪表板,在这里您可以查看:集群资源与节点、虚拟资源与用量、IOPS 和物理吞吐量等

06df7c120fa55dd28607678e69a07282.png
20220302140652

我们的目的是为验证 Kasten 对 KSV 的数据保护能力。在这里我们简化操作,直接进入正题,创建项目与虚拟机。

4.2. 创建项目与虚拟机

4.2.1 创建项目

点击 项目 然后点击 创建 我们将创建一个虚拟机的生态环境,包括用户虚拟化资源,而 K8S中我们将看到一个新的 Namespace ksv4 与项目名称一致。注意,我们要保护的项目是 ksv2 ,还原到 ksv3,ksv4是项目创建方法举例。

b0ce1d0046d5254c33d15b0bc839cc22.png
20220302141236

输入项目创建所需要的信息,包括名称,别名,与描述。

5875f40abb49a3b0a1e56c35c5304a07.png
20220302142315

在命令行进行查看,新建的项目在 k8s 中是一个新的 Namespace

$ kubectl get ns
NAME                               STATUS   AGE
cdi                                Active   4d19h
default                            Active   4d21h
kasten-io                          Active   45h
ksv2                               Active   4h50m
ksv3                               Active   4h33m
kube-node-lease                    Active   4d21h
kube-public                        Active   4d21h
kube-system                        Active   4d21h
kubekey-system                     Active   4d21h
kubesphere-controls-system         Active   4d21h
kubesphere-monitoring-federated    Active   4d21h
kubesphere-monitoring-system       Active   4d21h
kubesphere-system                  Active   4d21h
kubesphere-virtualization-system   Active   4d19h
kubevirt                           Active   4d19h
kvs4                               Active   24s
rook-ceph                          Active   4d21h

4.2.2 创建虚拟机

点击 VM 让我们来创建虚拟机

37f6037c18d2d3c428748dd420fc99c2.png
20220302142654

首先我们要有 System Iamge,如果没有上传与从其它地方 Copy 都是可以的,在这里我们以 Ubuntu 为例, 然后将系统资源,网络参数,鉴权方式设置好,指定主机名与数量即可完成虚拟机的创建。

0aaf541b4249d0496aafcea2f47e1a2b.png
20220302143025

在虚拟机创建好之后,我们可以用命令行查询主机的状态

#查看正在运行的VM
$ kubectl get vmi -n ksv3
NAME         AGE     PHASE     IP    NODENAME
i-cyh3xmet   4h26m   Running         ksvnode1

#查看有定义的VM
$ kubectl get vm -n ksv3
NAME         AGE     VOLUME
i-cyh3xmet   4h42m   

#查看运行的 Pod, 一个虚拟机就是一个 Pod
$ kubectl get po -n ksv3
NAME                             READY   STATUS    RESTARTS   AGE
virt-launcher-i-cyh3xmet-xtvtv   1/1     Running   0          4h27m

#查看PVC, 用 PVC 的名称,可以界面上找到对应的主机
$ kubectl get pvc -n ksv3
NAME               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGE
img-2yndvxw0       Bound    pvc-6ae3bbac-5b74-4559-a863-19cebfa884ca   24Gi       RWO            rook-ceph-block   4h46m
tpl-vol-z6tlpkzl   Bound    pvc-6e35ad24-1251-44ee-ae17-8bec73945a56   32Gi       RWO            rook-ceph-block   4h46m

用 PVC 的名称可以在界面上找到主机与磁盘的对应关系

408500b2dc765334df1a29dd72e172ff.png
20220302144215

4.2.3 模拟虚拟机中存储数据

打开 VNC 或是 Terminal 对话框

9f0353b4ff2833af9bd36d12ebfc19bc.png
20220302144500

模拟写入数据

root@ubuntu1:~# touch mars
root@ubuntu1:~# echo "mars 9:40" > mars
root@ubuntu1:~# cat mars
mars 9:40

5. 安装 Kasten K10 到 KSV Cluster

5.1 确认 K8S 与 容器运行时版本

在这里我们可以看到 KSV Cluster 是 K3S v1.21.6+ 版本,采用的是 containerd 容器运行时 1.4.11-k3s1,是 Kasten 所支持的,Kasten 支持列表见附录。

$ kubectl get node -o wide
NAME       STATUS   ROLES                         AGE     VERSION        INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
ksvnode1   Ready    control-plane,master,worker   4d22h   v1.21.6+k3s1   172.16.10.2   <none>        Ubuntu 20.04.3 LTS   5.4.0-91-generic   containerd://1.4.11-k3s1

5.2 确认存储类与快照类

# ceph rbd 存储类
$ kubectl get sc
NAME                        PROVISIONER                  RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
rook-ceph-block (default)   rook-ceph.rbd.csi.ceph.com   Delete          Immediate           true                   4d22h

# cpeh rbd 快照类
$ kubectl get volumesnapshotclass
NAME                                DRIVER                       DELETIONPOLICY   AGE
csi-rbdplugin-snapclass             rook-ceph.rbd.csi.ceph.com   Delete           4d22h

# 将 K10 与 CSI 联动的机制进行注释
kubectl annotate volumesnapshotclass csi-rbdplugin-snapclass \
    k10.kasten.io/is-snapshot-class=true
# yaml 效果
$ kubectl get volumesnapshotclass csi-rbdplugin-snapclass -o yaml
apiVersion: snapshot.storage.k8s.io/v1
deletionPolicy: Delete
driver: rook-ceph.rbd.csi.ceph.com
kind: VolumeSnapshotClass
metadata:
  annotations:
    k10.kasten.io/is-snapshot-class: "true"
    meta.helm.sh/release-name: ceph-cluster
    meta.helm.sh/release-namespace: rook-ceph
    snapshot.storage.kubernetes.io/is-default-class: "true"
  creationTimestamp: "2022-02-25T08:26:14Z"
  generation: 1
  labels:
    app.kubernetes.io/managed-by: Helm
  name: csi-rbdplugin-snapclass
  resourceVersion: "1959791"
  uid: bba92398-9daa-4f47-bb9d-4a3f03e26f19
parameters:
  clusterID: rook-ceph
  csi.storage.k8s.io/snapshotter-secret-name: rook-csi-rbd-provisioner
  csi.storage.k8s.io/snapshotter-secret-namespace: rook-ceph

# 联动状态,将会创建 k10关联的快照类
$ kubectl get volumesnapshotclass
NAME                                DRIVER                       DELETIONPOLICY   AGE
csi-rbdplugin-snapclass             rook-ceph.rbd.csi.ceph.com   Delete           4d22h
k10-clone-csi-rbdplugin-snapclass   rook-ceph.rbd.csi.ceph.com   Retain           43h

5.3 安装 Kasten K10

  1. 获取 Helm Chart 供本地使用

添加 Kasten Helm charts 存储库
$ helm repo add kasten https://charts.kasten.io/

$ helm repo list   
NAME            URL   ls
kasten          https://charts.kasten.io/         

$ helm repo update
# 以下这条命令会把 k10-4.0.x.tgz 包下载下来,如果不加任何参数,则会下载最新的版本
# 在Air Gapped 的环境中安装时,可以先行下载再使用。
$ helm fetch kasten/k10 --version=4.5.4
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "kasten" chart repository
Update Complete. ⎈Happy Helming!⎈
  1. 建立命名空间

$ kubectl create ns kasten-io   
namespace/kasten-io created

$ helm fetch kasten/k10 --version=4.5.4
  1. 安装 Kasten K10

$ helm install k10 k10-4.5.4.tgz --namespace kasten-io --set global.airgapped.repository=ccr.ccs.tencentyun.com/kasten-k10 \
  --set auth.tokenAuth.enabled=true \
  --set metering.mode=airgap \
  --set global.persistence.storageClass=rook-ceph-block
  1. 检查 Kasten K10 安装情况

$ kubectl get po -n kasten-io
NAME                                  READY   STATUS    RESTARTS   AGE
aggregatedapis-svc-57d7c44b9d-gwmtq   1/1     Running   3          46h
auth-svc-58999fb4f8-vft7m             1/1     Running   3          46h
catalog-svc-85f8cc5c4d-cs5vq          2/2     Running   6          46h
config-svc-688c5477bf-fr29c           1/1     Running   3          46h
crypto-svc-5b8b448bb5-hg7nd           2/2     Running   6          46h
dashboardbff-svc-6c756544c8-5nmrq     1/1     Running   3          46h
executor-svc-95b4464df-c6v4q          2/2     Running   6          46h
executor-svc-95b4464df-cc7vh          2/2     Running   6          46h
executor-svc-95b4464df-dvwbw          2/2     Running   6          46h
frontend-svc-588f856d48-t99sd         1/1     Running   3          46h
gateway-6b7bfd947d-926hs              1/1     Running   6          45h
jobs-svc-b9db684cd-tlx57              1/1     Running   3          46h
k10-grafana-54b5d8ffcc-jwhqc          1/1     Running   3          46h
kanister-svc-7497d4ffc9-pcdm5         1/1     Running   3          46h
logging-svc-6bd9c48b9c-8bz74          1/1     Running   3          46h
metering-svc-6d74f5f96d-7c5xn         1/1     Running   3          46h
prometheus-server-7f78865fb7-brd5x    2/2     Running   6          46h
state-svc-86ccd97996-5w774            1/1     Running   3          46h

5.4 查看 Kasten 的服务

$ kubectl get svc -n kasten-io
NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                        AGE
aggregatedapis-svc      ClusterIP   10.233.37.192   <none>        443/TCP                        46h
auth-svc                ClusterIP   10.233.33.4     <none>        8000/TCP                       46h
catalog-svc             ClusterIP   10.233.35.51    <none>        8000/TCP                       46h
config-svc              ClusterIP   10.233.38.179   <none>        8000/TCP,443/TCP               46h
crypto-svc              ClusterIP   10.233.58.201   <none>        8000/TCP,8001/TCP              46h
dashboardbff-svc        ClusterIP   10.233.26.109   <none>        8000/TCP                       46h
executor-svc            ClusterIP   10.233.20.225   <none>        8000/TCP                       46h
frontend-svc            ClusterIP   10.233.34.9     <none>        8000/TCP                       46h
gateway                 ClusterIP   10.233.29.195   <none>        8000/TCP                       46h
gateway-admin           ClusterIP   10.233.18.39    <none>        8877/TCP                       46h
jobs-svc                ClusterIP   10.233.12.31    <none>        8000/TCP                       46h
k10-grafana             ClusterIP   10.233.40.213   <none>        80/TCP                         46h
kanister-svc            ClusterIP   10.233.6.29     <none>        8000/TCP                       46h
logging-svc             ClusterIP   10.233.55.250   <none>        8000/TCP,24224/TCP,24225/TCP   46h
metering-svc            ClusterIP   10.233.13.14    <none>        8000/TCP                       46h
prometheus-server       ClusterIP   10.233.43.32    <none>        80/TCP                         46h
prometheus-server-exp   ClusterIP   10.233.35.124   <none>        80/TCP                         46h
state-svc               ClusterIP   10.233.44.178   <none>        8000/TCP                       46h

5.5 登录 Kasten UI

  1. 暴露 NodePort 类型的 Service,使 Kasten 具备 Web UI 访问接口

$ kubectl expose service gateway -n kasten-io --type=NodePort --name=gateway-nodeport
service/gatewaylb exposed
  1. 查看登录中服务的 IP 地址及端口

$ kubectl get svc -n kasten-io
NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                        AGE
<truncated...>
gateway-nodeport        NodePort    10.233.26.247   <none>        8000:32387/TCP                 44h
<truncated...>

$ kubectl get node -o wide
NAME       STATUS   ROLES                         AGE     VERSION        INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
ksvnode1   Ready    control-plane,master,worker   4d22h   v1.21.6+k3s1   172.16.10.2   <none>        Ubuntu 20.04.3 LTS   5.4.0-91-generic   containerd://1.4.11-k3s1

$ curl cip.cc
IP      : 139.198.157.224
地址    : 中国  上海
运营商  : qingcloud.com
数据二  : 上海市 | 青云数据中心
数据三  : 中国上海上海 | 电信
URL     : http://www.cip.cc/139.198.157.224
  1. 浏览器访问如下地址,填入 Token

http://139.198.157.224:32387/k10/#/

b34c8805c45278c593a97fb34edf6e34.png
20220302152551

在终端输入如下命令获取 Token

$ sa_secret=$(kubectl get serviceaccount k10-k10 -o jsonpath="{.secrets[0].name}" --namespace kasten-io) && \
  kubectl get secret $sa_secret --namespace kasten-io -ojsonpath="{.data.token}{'\n'}" | base64 --decode

登录 Kasten K10 的管理界面如下所示

35ebf8a29e5633840f3726140063eced.png
20220302162512

6. 配置青云 QingStor 对象存储作为备份库

我们可以通过过设置 S3 Compatible 存储库的方式,将青云 QingStor 对象存储设置成为备份存储库,满足 3-2-1-1-0 的备份黄金法则,当然 KSV Cluster 中集成了 MinIO 的对象存储,我们可以利用它进行本地备份库。

点击 Settings -> Locations -> New Profile 新建云存储库

e42dd2acc916c0f65a22e9fb918faae0.png
20220302153931

云存储库配置之后,显示列表如下

fcdd656270bc81f39ee36458cd776a86.png
20220302154305

7. KSV 云原生虚拟化平台的备份与还原

7.1 云原生应用的发现

Kasten 会自动发现 K8S Cluster 中的应用,并在 Application 中呈现列表, 没有被保护的应用上将出现 Create Policy 按钮

3289c53e81675221e5b88d5efd4325ec.png
20220302162740

7.2 云原生虚拟化的备份

点击 Create Policy, 让我们创建一个数据备份策略,在这个数据保护策略中 Kasten 不仅创建本地的快照对应用进行保护,还会将应用数据备份到青云 QingStor 对象存储,以实现数据的长期保留

ded04b6183765dcbefdd8b8205f5e5b5.png
20220302154523

注意,如果有不需要备份的元素,如虚拟机的镜像,可以在备份任务中灵活地进行元素排除

410541abe04e1cdb787b18299ff16deb.png
20220302154758

点击 Run Once 执行备份任务

847ba02fd506feb69760d50a946ae3c8.png
20220302155011

观察 Dashboard 可以看到应用已经备份完成

5f573ade17b2d03aa04e975a4ec8d077.png
20220302160645

7.3 云原生虚拟化的还原

在 Dashboard 中找到 Applications 点击 Restore

b3abcd674a862d50b9a21457600e4ba1.png
20220302161057

选择还原的时间点

6989232d309ebffc67aaad2dfcd52d01.png
20220302161117

新建一个 Namespace 进行还原,这里我们命名为 kvs3,点击 Restore 进行还原

1fe2cebc0f41c8685582b882f479eb5f.png
20220302160911

在控制台观察还原操作已经顺利完成

effc03c8b95c9ba4d7c4e5ba142abc8c.png
20220302161149

在青云 KubeSphere 虚拟化平台中我们已经看到还原的虚拟机已经可以正常的启动

f0529a16257d446c5db0ab9e21f7224c.png
20220302161219

并且数据已经完美地还原了

136ed955bab77a897c2c51638b240515.png
20220302161431

8. 总结

随着云原生生态的越发成熟,KubeSphere 容器平台已完成从单一产品到多核云原生生态家族的演进,青云的云原生虚拟化产品 KSV (KubeSphere Virtualization),利用成熟的虚拟化管理技术和 Kubernetes 容器编排的优势,满足了客户在云原生平台上虚拟化场景的需要。而 Kasten K10 by Veeam 解决方案 ,利用青云的 KubeSphere 生态环境中的多项目云服务,如 KSV 与 QingStor 对象存储,打造了可靠的云原生数据管理平台,可助力企业达成云原生虚拟化灾备、迁移和 DevOps 等目标,从而保证了企业云原生应用的弹性和可靠性。

9. 参考资料

KubeSphere 虚拟化介绍

https://kubesphere.cloud/docs/ksv/management/web-console-introduction/

Kasten 支持列表

https://docs.kasten.io/latest/install/requirements.html#prerequisites

OpenShift Virtualization

https://cloud.redhat.com/learn/topics/virtualization/

kubevirt Github

https://github.com/kubevirt

mirantis - virtlet run vms as kubernetes pods

https://www.mirantis.com/blog/virtlet-run-vms-as-kubernetes-pods/

virtlet Github

https://github.com/Mirantis/virtlet

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐