CDI是Kubevirt提供的磁盘镜像管理工具,它基于PVC为Kubernetes上运行的Kubevirt虚拟机提供镜像、磁盘等抽象概念。

Containerized-Data-Importer (CDI) 是 Kubernetes 的持久存储管理插件。

它的主要目标是在PVC的基础上构建 Kubevirt VM 的虚拟机磁盘资源,并提供一种将不同数据源的数据填充到指定PVC的能力。

DataVolume

CDI 自定义了CRD DataVolume 作为K8S标准PVC之上的抽象,当用户创建 DataVolume 资源时控制器会自动为其创建PVC,并填充数据。

目前支持以下数据源:

  • URL
  • Container Registry
  • 其他PVC
  • 从客户端上传
  • 创建空白磁盘
  • 从oVirt/VMWare的API

支持一下两种数据类型:

  • kubevirt:这种类型的数据,被认为是磁盘镜像!cdi会自动为其转换数据格式(如 QCOW2 -> Raw),并调整其虚拟空间的大小。
  • archive:tar包格式的数据,cdi会将其中的内容自动解压缩到指定的卷中。

注意,特定数据源只能处理特定格式的数据,关系如下:

  • http → kubevirt, archive
  • registry → kubevirt
  • pvc → Not applicable - content is cloned
  • upload → kubevirt
  • imageio → kubevirt
  • vddk → kubevirt

数据源

1.HTTP Source

创建HTTP Source 类型的源时,CDI 基于qemu-img 工具工作,支持的镜像格式主要包括以下几种:

  • VMDK:VMWare 镜像的格式
  • VDI:VirtualBox 镜像格式
  • VHD:Hyper-V 镜像的格式
  • QCOW2/QCOW
  • RAW

2.Upload Source

Upload Source数据源可以提供API接口,用户可以将数据直接推送到该接口,具体操作如下:

用户需要将cdi-uploadproxy服务的svc暴露到Kuberentes集群之外:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: cdi-uploadproxy-nodeport
  namespace: cdi
  labels:
    cdi.kubevirt.io: "cdi-uploadproxy"
spec:
  type: NodePort
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 31001
      protocol: TCP
  selector:
    cdi.kubevirt.io: cdi-uploadproxy
EOF

手工创建DV,并将source指定为upload

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
apiVersion: cdi.kubevirt.io/v1beta1
kind: DataVolume
metadata:
  name: upload-datavolume
spec:
  source:
      upload: {}
  pvc:
    accessModes:
      - ReadWriteOnce
    resources:
      requests:
        storage: 500Mi

创建Upload Token,集群创建以下ServiceAccount,并绑定相关权限

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
apiVersion: v1
kind: ServiceAccount
metadata:
  name: cdi-uploadtokenrequests
  namespace: cdi
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cdi-uploadtokenrequests
rules:
  - apiGroups:
      - "upload.cdi.kubevirt.io"
    resources:
      - 'uploadtokenrequests'
    verbs:
      - '*'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: ruijie:openplatform:openplatform-controller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cdi-uploadtokenrequests
subjects:
  - kind: ServiceAccount
    name: cdi-uploadtokenrequests
    namespace: cdi

创建的cdi-uploadtokenrequests后,在cdi的命名空间下会自动创建secret,名称格式为:cdi-uploadtokenrequests-token-xxx ,describe该secret中的token字段,可以获取用于上传的UploadToken:

POST:/apis/upload.cdi.kubevirt.io/v1beta1/namespaces/{namespace}/uploadtokenrequests

BODY 信息如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{
  "apiVersion": "upload.cdi.kubevirt.io/v1beta1",
  "kind": "UploadTokenRequest",
  "metadata": {
    "name": "DV名称",
    "namespace": "default",
    "spec": {
      "pvcName": "DV名称"
    }
  }
}

返回信息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{
  "kind": "UploadTokenRequest",
  "apiVersion": "upload.cdi.kubevirt.io/v1beta1",
  "metadata": {
    "name": "upload-datavolume",
    "namespace": "default",
    "creationTimestamp": null
  },
  "spec": {
    "pvcName": ""
  },
  "status": {
    "token": "UPLOADTOKEN"
  }
}

通过curl上传数据到datavolume,

1
2
3
4
5
# 同步上传
curl -v --insecure -H "Authorization: Bearer $UPLOADTOKEN" --data-binary @tests/images/cirros-qcow2.img https://$(minikube ip):31001/v1alpha1/upload

# 异步上传
curl -v --insecure -H "Authorization: Bearer $UPLOADTOKEN" --data-binary @tests/images/cirros-qcow2.img https://$(minikube ip):31001/v1alpha1/upload-async

3.Registry Source

创建一个可以作为DV源的docker 镜像(参考:Storing VMI Disks in the Container Registry

参考一下Dockerfile制作即可:

1
2
3
4
cat << END > Dockerfile
FROM kubevirt/container-disk-v1alpha
ADD fedora28.qcow2 /disk
END

可以使用 Buildah 替代 DinD在容器中构建镜像。

4. VDDK Source

CDI 支持已VDDK镜像作为DV的源数据

参考

kubevirt/containerized-data-importer

DataVolume介绍