通常,当 DevOps 工程师在 vSphere with Tanzu 环境中置备虚拟机时,OVF 模板会包含硬编码的详细信息,例如基本网络配置。但是,在创建虚拟机 CR 之前,您可能不知道也通常无法为虚拟机的 OVF 属性分配某些值,例如,IPAM 提供的网络数据。借助模板字符串支持,您无需提前了解网络信息。可以使用基于 Golang 的模板填充 OVF 属性值并配置虚拟机的网络堆栈。

过程

  1. 对于要配置的所有属性,确保 OVF 文件包含 ovf:userConfigurable="true" 条目。
    通过此条目,系统可用在收集数据后将网络值占位符(如名称服务器和管理 IP)替换为实际数据。
    使用以下示例。
    ovf
    <Property ovf:key="hostname" ovf:type="string" ovf:userConfigurable="true" ovf:value="ubuntuguest">
          <Description>Specifies the hostname for the appliance</Description>
    </Property>
    <Property ovf:key="nameservers" ovf:type="string" ovf:userConfigurable="true" ovf:value="1.1.1.1, 1.0.0.1">
          <Label>2.2. DNS</Label>
          <Description>A comma-separated list of IP addresses for up to three DNS servers</Description>
    </Property>
    <Property ovf:key="management_ip" ovf:type="string" ovf:userConfigurable="true">
          <Label>2.3. Management IP</Label>
          <Description>The static IP address for the appliance on the Management Port Group in CIDR format (Eg. ip/subnet mask bits). This cannot be DHCP.</Description>
    </Property>
  2. 创建包含模板字符串的虚拟机 YAML 文件。
    引导资源的模板字符串将收集填充 OVF 属性值所需的数据。
    您可以使用以下方法之一来构建模板字符串。
    • 使用 vm-operator-api。

      有关详细信息,请参见 GitHub 中的以下页面:https://github.com/vmware-tanzu/vm-operator-api/blob/master/api/v1alpha1/virtualmachinetempl_types.go

      以下是示例 YAML 文件:
      apiVersion: vmoperator.vmware.com/v1alpha1
      kind: VirtualMachine
      metadata:
        name: template-vm
        namespace: test-ns
        annotations:
          vmoperator.vmware.com/image-supported-check: disable
      spec:
        className: best-effort-xsmall
        imageName: haproxy-v0.2.0
        powerState: poweredOn
        storageClass: wcpglobal-storage-profile
        vmMetadata:
          configMapName: template-vm-1
          transport: vAppConfig
        
      ---
      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: template-vm-1
        namespace: test-ns
      data:
        nameservers: "{{ (index .V1alpha1.Net.Nameservers 0) }}"
        hostname: "{{ .V1alpha1.VM.Name }} "                  
        management_ip: "{{ (index (index .V1alpha1.Net.Devices 0).IPAddresses 0) }}"
        management_gateway: "{{ (index .V1alpha1.Net.Devices 0).Gateway4 }}"
    • 使用以下功能。
      函数名称 特征码 描述
      V1alpha1_FirstIP func () string 从第一个网卡获取第一个非环回 IP。
      V1alpha1_FirstIPFromNIC func (index int) string 从第 i 个网卡获取非环回 IP 地址。如果索引超出范围,则不会解析模板字符串。
      V1alpha1_FormatIP func (IP string, netmask string) string 使用网络长度设置 IP 地址的格式。网络掩码可以是长度(例如 /24),也可以是十进制表示法(例如 255.255.255.0)。

      如果输入的网络掩码无效或与默认掩码不同,则不会对其进行解析。

      V1alpha1_FormatNameservers operatorc (count int, delimiter string) string 使用特定分隔符设置首次出现的名称服务器计数的格式。计数为负数表示所有名称服务器。
      V1alpha1_IP func(IP string) string 使用默认网络掩码 CIDR 设置 IP 地址的格式。

      如果 IP 无效,将不会解析模板字符串。

      V1alpha1_IPsFromNIC func (index int) []string 列出第 i 个网卡的所有 IP。

      如果索引超出范围,则不会解析模板字符串。

      如果使用 函数,则 YAML 文件如下所示:
      apiVersion: vmoperator.vmware.com/v1alpha1
      kind: VirtualMachine
      metadata:
        name: template-vm
        namespace: test-ns
        annotations:
          vmoperator.vmware.com/image-supported-check: disable
      spec:
        className: best-effort-xsmall
        imageName: haproxy-v0.2.0
        powerState: poweredOn
        storageClass: wcpglobal-storage-profile
        vmMetadata:
          configMapName: template-vm-2
          transport: vAppConfig
        
      ---
      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: template-vm-2
        namespace: test-ns
      data:
        nameservers: "{{ V1alpha1_FormatNameservers 2 \",\" }}"
        hostname: "{{ .V1alpha1.VM.Name }} "                  
        management_ip: "{{ V1alpha1_FormatIP \"192.168.1.10\" \"255.255.255.0\" }}"
        management_gateway: "{{ (index .V1alpha1.Net.Devices 0).Gateway4 }}"
  3. 部署虚拟机。
    kubectl apply -f file_name.yaml

下一步做什么

如果自定义失败且虚拟机未获得 IP 地址,请使用 vSphere 虚拟机 Web 控制台检查虚拟机。请参见使用 vSphere 虚拟机 Web 控制台对虚拟机进行故障排除