添加镜像实例

镜像实例是已导入集群、可作为启动卷使用的操作系统镜像。虚拟机从该镜像克隆其系统磁盘,而不是再次下载镜像,因此从一个镜像创建大量虚拟机的速度很快,也不会给镜像服务器带来负载。

在 Kubernetes 术语中,镜像实例是一个指向 PersistentVolumeClaim 的 DataSource(cdi.kubevirt.io/v1beta1)。CDI 通过导入 DataVolume 填充该声明——从镜像地址导入,或克隆现有磁盘或卷快照。在 API 侧,可启动卷中介绍了相同的对象。

在管理员下添加的镜像实例位于集群的共享 kube-public 命名空间中,可供每个命名空间中的虚拟机使用。若要添加仅供一个命名空间使用的镜像实例,包括位于 S3 上的镜像以及需要凭证的镜像,请参阅命名空间中的镜像实例。

前提条件

  • 集群中已安装 Virtualization。
  • 用于镜像卷的存储类。建议使用其 StorageProfile 提供读写多次和块设备的存储类(例如 Ceph RBD 块存储);请参阅存储设置。
  • 若要从镜像源添加,必须已添加该镜像源;请参阅添加镜像源。

来源

来源导入内容DataVolume 源
镜像源平台管理员添加的镜像源地址(registry 或 HTTP)。需要凭证的镜像源和 S3 镜像源会列出,但无法在此处选择,因为 kube-public 不包含 Secret;请从命名空间中添加。名称会根据镜像源预先填充,其默认实例类型和首选项也会一并继承(请参阅默认规格)。registry 或 http
网络直接输入的镜像地址:Registry(registry.example.com/images/centos:7;系统会为你添加 docker://)或 HTTP(http:// 或 https:// URL,指向 qcow2 / raw 文件)。此页面无法使用凭证,且此处不提供对象存储(S3)——S3 始终需要凭证 Secret,因此请从命名空间中添加 S3 镜像。registry 或 http
磁盘克隆任意命名空间中的现有磁盘:DataVolume,或不包含该对象的 PersistentVolumeClaim。正在运行的虚拟机的磁盘会列出,但无法选择(由正在运行的虚拟机使用……;请先将其停止)。架构默认为磁盘所属虚拟机的架构。pvc
卷快照克隆一个已准备就绪、可供使用的 VolumeSnapshot。虚拟机快照创建的快照会标记为来自虚拟机快照……。snapshot

对于磁盘或卷快照,实例大小默认为来源的大小,且不能小于来源大小。之后删除来源不会影响镜像实例:镜像实例拥有自己的副本。

操作步骤

  1. 进入管理员。

  2. 在左侧导航栏中,点击虚拟化 > 镜像 > 镜像实例,然后选择集群。

  3. 点击添加镜像实例。

  4. 配置参数。

    参数说明
    来源镜像源、网络、磁盘或卷快照;请参阅来源。
    操作系统 / CPU 架构创建虚拟机时,用于查找镜像实例。带有两种架构标签的镜像源可按任一架构添加。
    镜像源 / 来源类型和镜像 URL / 磁盘 / 卷快照根据来源指定要导入的内容。
    名称最多 53 个字符。镜像源会预填充此字段;磁盘或卷快照来源时此字段为空。
    显示名称可选。
    实例大小镜像卷的大小,至少与镜像的虚拟大小相同。默认值为 30 Gi(最小值为 1 Gi);对于磁盘或卷快照来源,默认值为来源的大小。
    StorageClass / 卷模式 / 访问模式请参阅存储设置。
    CA 证书、请求标头、校验和、拉取方式根据镜像地址的类型显示;请参阅导入设置。磁盘或卷快照来源不使用这些设置。
  5. 点击添加。

控制台会先对每个对象执行试运行检查,然后创建 DataSource、CA 证书 ConfigMap(如果有)和导入 DataVolume。如果其中任何一个对象被拒绝,已创建的对象都会被删除,因此添加失败后不会留下任何对象。CDI 填充卷之前,新镜像实例的状态会显示为正在导入,之后变为可用;请参阅状态。

存储设置

存储字段按以下顺序排列,因为每个字段都会缩小下一个字段的范围:实例大小、StorageClass、卷模式、访问模式。

提供的卷模式和访问模式是 CDI 在其 StorageProfile 中为该存储类报告的模式。选择存储类后,控制台会选择推荐的组合:

  1. 如果有可用选项,则选择带有 ReadWriteMany 的 Block Device — 卷可以同时挂载到多个节点上,这是实时迁移所需的;
  2. 否则选择任何带有 ReadWriteMany 的组合(例如 CephFS 上的 File System);
  3. 否则选择配置文件中的第一个组合。

提供的访问模式取决于你选择的卷模式。如果在存储类支持 ReadWriteMany 的情况下选择了其他访问模式,表单会对此进行提示。如果无法读取存储类的 StorageProfile,则模式改为遵循平台的存储类规则。

检查存储类支持的内容:

kubectl get storageprofile sc-ceph-cluster-block -o jsonpath='{.status.claimPropertySets}{"\n"}'
# [{"accessModes":["ReadWriteMany"],"volumeMode":"Block"},
#  {"accessModes":["ReadWriteOnce"],"volumeMode":"Block"},
#  {"accessModes":["ReadWriteOnce"],"volumeMode":"Filesystem"}]

导入设置

地址类型设置
HTTP / HTTPSCA 证书、请求标头、校验和
RegistryCA 证书、拉取方式
S3(仅命名空间)CA 证书、凭证 Secret — 请参阅命名空间中的镜像实例

这些设置会写入导入 DataVolume,并与镜像实例一同保留,因此重新导入时会再次使用这些设置。

CA 证书

对于证书为自签名证书或由私有 CA 签发的镜像服务器,请将 CA 证书粘贴为 PEM 文本,或点击加载文件以加载 PEM 或 DER 文件(DER 文件会显示为 PEM)。可以连续粘贴多个证书,例如中间 CA 和根 CA。只接受证书 — 私钥和其他文本会被拒绝。

证书会存储在镜像实例所拥有的 ConfigMap <image instance name>-img-ca 中,使用键 tls.crt,并在删除镜像实例时一同删除;DataVolume 会以 certConfigMap 的形式引用该证书。没有 CA 证书时,不会创建 ConfigMap。镜像地址中的主机必须位于证书的 Subject Alternative Names 中;CDI 不会跳过主机名验证。有关背景信息和故障排除,请参阅从带有自签名证书的 HTTPS 服务器导入虚拟机镜像。

证书仅在你的浏览器中进行检查。表单会列出每个证书 — 角色(根证书、中间证书或叶证书)、主题、颁发者、有效期(临近到期时显示 expires in N days)、Subject Alternative Names 和 SHA-256 指纹(与 openssl x509 -noout -fingerprint -sha256 相同)。不会访问镜像地址以及证书中的任何 OCSP、CA 颁发者或 CRL 地址;只有在点击添加时,证书才会发送到集群。

由于导入会失败,以下问题会阻止添加镜像实例:

  • 证书文本大于 64 KiB;
  • 无法读取证书;
  • 证书的序列号为负数;
  • 证书的 RSA 密钥短于 1024 位;
  • 所有证书均已过期或尚未生效。

以下属于警告;你仍然可以添加镜像实例:

  • 仅包含服务器证书 — 请添加签发该证书的 CA,否则服务器证书续期后导入会失败;
  • 某个证书将在 30 天内到期;
  • 某些证书已过期或尚未生效;
  • 某个证书使用 SHA-1 或 MD5 签名;
  • 某个证书签发了另一个证书,但未标记为 CA;
  • 镜像地址使用 http://,因此不会使用 CA 证书;
  • 叶证书对镜像地址的主机无效(IP 地址必须是 IP SAN;通配符只能匹配一个标签)。

请求标头

仅适用于 HTTP 地址。每行输入一个标头,格式为 Name: value;这些标头会随下载一起发送(extraHeaders)。标头以纯文本形式存储在 DataVolume 中 — 请勿在其中放置机密信息;请改用命名空间中的凭证 Secret。

校验和

仅适用于 HTTP 地址。以 md5:、sha1:、sha256: 或 sha512: 后跟十六进制摘要的格式输入预期摘要,例如 sha256:c199c9b6…875a。CDI 会据此验证下载的镜像;不匹配会导致导入永久失败,镜像实例会显示为失败,原因是校验和不匹配。

拉取方式

仅适用于 Registry 地址。

  • Pod(默认):导入器 Pod 会拉取镜像,并通过临时空间将其复制到卷中。
  • Node:节点会将镜像作为容器镜像拉取,因此该镜像必须是节点能够拉取的容器磁盘(包括通过节点的 Registry 凭证拉取);不会使用临时空间。

凭证 Secret 只能由命名空间中的镜像实例使用,并且仅用于 Pod;选择凭证后,Node 将不可用。请参阅凭证。

平台随附的镜像源默认为 Node。

使用 API

对于从带有私有 CA 的 HTTPS 地址导入、名为 centos-7 的镜像实例,控制台会在 kube-public 中创建以下对象。使用 kubectl 应用相同的对象,即可在不使用控制台的情况下添加镜像实例。

apiVersion: cdi.kubevirt.io/v1beta1
kind: DataSource
metadata:
  name: centos-7
  namespace: kube-public
  labels:
    virtualization.cpaas.io/image-instance: "true"
    virtualization.cpaas.io/image-os-type: centos        # the operating system
    virtualization.cpaas.io/image-os-arch: amd64         # amd64 | arm64
    virtualization.cpaas.io/source-type: address         # image-source | address | disk | volume-snapshot
    virtualization.cpaas.io/size: 30Gi
    virtualization.cpaas.io/storage-class: sc-ceph-cluster-block
    virtualization.cpaas.io/volume-mode: Block
    virtualization.cpaas.io/access-mode: ReadWriteMany
  annotations:
    cpaas.io/display-name: CentOS 7.9
spec:
  source:
    pvc:
      name: centos-7-img-a1b2c          # the import DataVolume below
      namespace: kube-public
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: centos-7-img-ca
  namespace: kube-public
data:
  tls.crt: |
    -----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----
---
apiVersion: cdi.kubevirt.io/v1beta1
kind: DataVolume
metadata:
  name: centos-7-img-a1b2c              # <image instance>-img-<5 random characters>
  namespace: kube-public
  labels:
    virtualization.cpaas.io/image-instance-name: centos-7
  annotations:
    cdi.kubevirt.io/storage.bind.immediate.requested: "true"
spec:
  source:
    http:
      url: https://images.example.internal/centos-7.qcow2
      certConfigMap: centos-7-img-ca
      extraHeaders:
        - "X-Request-Source: platform"
      checksum: sha256:<hex digest>
  storage:
    storageClassName: sc-ceph-cluster-block
    volumeMode: Block
    accessModes:
      - ReadWriteMany
    resources:
      requests:
        storage: 30Gi

控制台还会将镜像实例设为 DataVolume 和 ConfigMap 的控制器所有者,因此删除 DataSource 时也会删除这些对象;手动应用但不包含 ownerReference 的对象必须逐个删除。

对于其他地址类型,请将 DataVolume 的 spec.source 替换为以下选项之一。

Registry,由节点拉取:

source:
  registry:
    url: docker://registry.example.com/images/centos:7
    pullMethod: node
    # certConfigMap: centos-7-img-ca    # a registry behind a private CA

另一个命名空间中的磁盘(克隆):

source:
  pvc:
    name: web-01-rootfs
    namespace: demo

卷快照(克隆):

source:
  snapshot:
    name: web-01-snapshot
    namespace: demo

查看导入状态:

kubectl get dv,datasource -n kube-public
# NAME                                            PHASE       PROGRESS
# datavolume.cdi.kubevirt.io/centos-7-img-a1b2c   Succeeded   100.0%