前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【k8s】run VMs on Kubernetes

【k8s】run VMs on Kubernetes

原创
作者头像
williamji
修改2022-08-25 18:43:08
1.7K0
修改2022-08-25 18:43:08
举报
文章被收录于专栏:腾讯云产品腾讯云产品

概述

本文简单介绍并实践基于k8s平台运行虚机。

本文比较适合自建集群,阿里云,腾讯云,华为云等云厂商的普通云服务器不支持二次虚拟化,无法实现vm on vm。如果只是业务需要虚机,可以直接在云厂商购买虚机使用。

本文测试使用腾讯云的容器服务,节点使用裸金属云服务器。

应用场景

  • 统一的k8s平台,k8s上可以运行容器,也可以运行虚机
  • 有些重型应用需要部署在虚机上
  • 虚机拥有更好的隔离性
  • etc

开源项目

开源的基于k8s的虚机解决方案有kubevirt和virtlet,其中kubevirt使用CRD扩展k8s API,virtlet则实现了CRI接口。

kubevirt

kubevirt使用CRD扩展k8s api,控制面以add-on的形式部署到k8s集群。

项目:https://github.com/kubevirt/kubevirt

文档:https://kubevirt.io/

架构:

virtlet

virtlet是较早开源的基于k8s平台的虚机解决方案,实现了CRI接口,组件部署需要先给节点部署cri-proxy,cri-proxy会根据配置选择dockershim或者virtlet,然后再部署daemonset

项目:https://github.com/Mirantis/virtlet

文档:https://docs.virtlet.cloud/

架构:

kubevirt/virtlet

kubevirt

virtlet

公司

redhat

Mirantis

开源项目

现状

持续更新

3年未更新

版本

v0.56.0

v1.5.1

star

3.5K

686

同时运行虚机/容器

支持

支持

实现方式

CRD add-on

CRI

组件部署

简单(add-on)

复杂(worker节点配置+add-on)

使用方法

CR,扩展性强

pod annotation(原生workload)

虚机方案

libvirt API

libvirt API

cloudInit

支持

支持

多网卡

支持(依赖网络插件)

支持(依赖网络插件)

......

kubevirt实践

注意腾讯云只有裸金属云服务器的标准集群可以用于kubevirt/virtlet使用测试。

  • 标准集群普通云服务器不支持二次虚拟化,无法测试。
  • serverless集群由于节点都是虚拟的超级节点不支持Daemonset原生资源,并且创建的pod也是先申请虚机然后在虚机里起容器(不支持二次虚拟化)
  • 边缘集群用于管理边缘节点,无法部署kubevirt/virtlet控制面板组件

创建tke集群

参考文档:https://cloud.tencent.com/document/product/457/32189

  • 腾讯云上创建tke集群(这里工作节点选择黑石服务器,普通云服务器不支持二次虚拟化)
  • 以托管标准集群为例【注意:托管集群区别于独立集群,master组件由腾讯云托管。标准集群区别于serverless集群和边缘集群,支持原生节点注册和超级节点管理】,在"容器服务"->"集群",点击"新建"
  • 选择"标准节点",然后点击"创建"
  • 配置好集群名(以williamji-baremetal为例),集群版本,运行时,私有网络以及容器网络之后点击下一步
  • 配置集群规模,以及worker节点配置,机型这里测试选择裸金属服务器。配置好之后点击下一步
  • 配置好worker节点登录方式以及对应秘钥/密码之后点击下一步
  • 配置集群组件之后点击下一步,组件在集群创建后也可以添加,这里使用默认组件,然后下一步
  • 勾选"我已经阅读并同意"后点击完成
  • 等集群创建好之后可以在"容器服务"->"集群"中搜索并查看对应集群
  • 点击集群,进入集群查看集群相关菜单以及相应的资源

kubevirt组件部署

参考kubevirt文档:https://kubevirt.io/quickstart_cloud/

  • 部署kubevirt组件的CRD和kubevirt-operator。
代码语言:javascript
复制

export VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases | grep tag_name | grep -v -- '-rc' | sort -r | head -1 | awk -F': ' '{print $2}' | sed 's/,//' | xargs)
echo $VERSION
kubectl create -f https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-operator.yaml
  • 部署好之后会多个kubevirts.kubevirt.io的CRD和virt-operator的deployment,其中kubevirt这个CRD和operator是用来部署kubevirt组件的。
  • 部署kubevirt组件,也就是创建一个kubevirt实例(CR),如下命令。
代码语言:javascript
复制
export VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases | grep tag_name | grep -v -- '-rc' | sort -r | head -1 | awk -F': ' '{print $2}' | sed 's/,//' | xargs)
echo $VERSION
kubectl create -f https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/kubevirt-cr.yaml

  • 部署好kubevirt组件之后,会多一个kubevirt资源。然后virt-operator会创建对应的kubevirt组件,包含deployment:kubevirt/virt-api,deployment:kubevirt/virt-controller以及daemonset:kubevirt/virt-handler以及kubevirt的vm对应CRD资源
  • 等待kubevirt所有组件pod运行正常之后,查看节点信息,注意节点里有可分配的kvm和tun等设备插件,如果是可分配的kvm设备是0表示节点不支持虚拟化,需要开启虚拟化。可以通过virt-hander日志查看设备插件信息
  • 安装kubevirt命令行工具virtctl,该命令用于管理以及访问虚机。实际上virtctl下载地址就在github的release界面上。
代码语言:javascript
复制
VERSION=$(kubectl get kubevirt.kubevirt.io/kubevirt -n kubevirt -o=jsonpath="{.status.observedKubeVirtVersion}")
ARCH=$(uname -s | tr A-Z a-z)-$(uname -m | sed 's/x86_64/amd64/') || windows-amd64.exe
echo ${ARCH}
curl -L -o virtctl https://github.com/kubevirt/kubevirt/releases/download/${VERSION}/virtctl-${VERSION}-${ARCH}
chmod +x virtctl
sudo install virtctl /usr/local/bin

  • 安装好virtctl命令之后,可以查看virtctl的help信息

准备container-disk镜像

kubevirt提供了测试的container-disk镜像可以直接用于vm创建。参考https://github.com/kubevirt/kubevirt/blob/main/containerimages/container-disk-images.md

  • iso引导文件可以直接用于kubevirt的vm创建,创建好vm之后需要vnc登录虚机完成引导(以下windows测试直接使用的iso文件)
  • qcow2云镜像可以用来挂载启动虚机,网上一般都会有发行版的cloudimage,如果有iso镜像想转换成qcow2镜像,比较麻烦,依赖libvirt相关工具。参考文档:https://www.ibm.com/docs/en/cic/1.1.2?topic=images-creating-from-iso-kvm
  • 把qcow2镜像构建到容器镜像,测试dockerfile以及构建方式如下
代码语言:javascript
复制

cat > Dockerfile <<EOF
FROM kubevirt/container-disk-v1alpha
ADD fedora32.qcow2 /disk/
EOF

docker build -t kubevirt/fedora-sriov-testing:latest .

CDI组件部署

CDI使用CRD扩展api,用于将虚拟机映像或其他数据填充PVC来挂载虚机。数据可以来自不同的来源:URL、容器镜像仓库、或来自客户端的上传。

代码语言:javascript
复制
export VERSION=$(curl -s https://github.com/kubevirt/containerized-data-importer/releases/latest | grep -o "v[0-9]\.[0-9]*\.[0-9]*")
kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/$VERSION/cdi-operator.yaml
kubectl create -f https://github.com/kubevirt/containerized-data-importer/releases/download/$VERSION/cdi-cr.yaml

  • CDI组件部署好之后,先创建CRD,然后创建CR(cdi),operator会创建cdi相关组件。

使用container-disk镜像直接运行虚机(cirros镜像)

参考文档:https://kubevirt.io/labs/kubernetes/lab1.html

  • 使用测试yaml如下。该vm资源使用了quay.io/kubevirt/cirros-container-disk-demo这个container-disk镜像。
代码语言:javascript
复制

cat > cirros.yaml <<EOF
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: testvm
spec:
  running: true
  template:
    metadata:
      labels:
        kubevirt.io/size: small
        kubevirt.io/domain: testvm
    spec:
      domain:
        devices:
          disks:
            - name: containerdisk
              disk:
                bus: virtio
            - name: cloudinitdisk
              disk:
                bus: virtio
          interfaces:
          - name: default
            masquerade: {}
        resources:
          requests:
            memory: 64M
      networks:
      - name: default
        pod: {}
      volumes:
        - name: containerdisk
          containerDisk:
            image: quay.io/kubevirt/cirros-container-disk-demo
        - name: cloudinitdisk
          cloudInitNoCloud:
            userDataBase64: SGkuXG4=
EOF

  • 使用kubectl部署该yaml
代码语言:javascript
复制
kubectl create -f cirros.yaml

  • 注意yaml中的Running为true表示创建vm之后启动虚机。如果Running为false的话,则只会创建vm资源,不会启动,需要使用如下命令启动虚机才会创建vm pod并在pod里启动虚机
代码语言:javascript
复制
virtctl start <vm-name>

  • 查看testvm以及对应pod是否Running
  • 然后等vmi变成Running并且对应pod变成Running之后,可以使用如下命令连接虚机
代码语言:javascript
复制
 virtctl console <vm-name>
  • cirros镜像登录的账号为cirros,密码是gocubsgo。
  • 当然,也可以使用如下命令登录虚机
代码语言:javascript
复制
virtctl ssh --local-ssh=true cirros@testvmi

运行测试虚机(Windows虚机+ISO镜像为例)

kubevirt windows参考文档:https://kubevirt.io/2020/KubeVirt-installing_Microsoft_Windows_from_an_iso.html

注意:该测试受客户端环境影响,vm启动成功但是挂载的iso操作系统没有安装好。

  • 下载ISO镜像。注意镜像比较大,下载比较慢。
代码语言:javascript
复制
ISO镜像下载网址:https://info.microsoft.com/ww-landing-windows-server-2012-R2.html
Note: 需要输入个人信息可以免费试用180天
cloudimage镜像下载网址:https://cloudbase.it/windows-cloud-images/

  • 通过virtctl工具上传iso镜像到pvc中,其中image-path表示本地ISO镜像文件,--uploadproxy-url表示service: cdi/

uploadproxy的集群服务

代码语言:javascript
复制
virtctl image-upload \
--image-path=./9600.17050.WINBLUE_REFRESH.140317-1640_X64FRE_SERVER_EVAL_EN-US-IR3_SSS_X64FREE_EN-US_DV9.ISO \
--pvc-name=iso-win2k12 \
--access-mode=ReadOnlyMany \
--pvc-size=5G \
--uploadproxy-url=https://10.96.164.35:443 \
--insecure \
--wait-secs=240

  • virtctl image-upload是将客户端的ios文件上传到pvc绑定的pv上,该上传操作会经过apiserver,大镜像比较慢。测试时直接将下载好的iso文件存放到节点上,并将对应目录创建为hostpath类型的pv,然后创建pvc绑定pv
代码语言:javascript
复制
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-windows-iso
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/windows"
    type: DirectoryOrCreate
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: "pvc-windows-iso"
  labels:
    app: containerized-data-importer
spec:
  storageClassName: manual
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

  • 创建pvc和pv用于虚机操作系统的安装,这里也使用hostpath类型的pv
代码语言:javascript
复制
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-windows-hd
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/windows-hd"
    type: DirectoryOrCreate
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: "pvc-windows-hd"
  labels:
    app: containerized-data-importer
spec:
  storageClassName: manual
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi

  • 创建vm(cr)资源,vm会使用存储iso文件的pvc,以及用于操作系统安装的pvc。这里字段running为true表示vm创建好后会自动启动,vm创建好后,controller会listwatch并创建vm pod。
代码语言:javascript
复制
apiVersion: kubevirt.io/v1alpha3
kind: VirtualMachine
metadata:
  name: win2k12-iso
spec:
  running: true
  template:
    metadata:
      labels:
        kubevirt.io/domain: win2k12-iso
    spec:
      domain:
        cpu:
          cores: 4
        devices:
          disks:
          - bootOrder: 1
            cdrom:
              bus: sata
            name: cdromiso
          - disk:
              bus: virtio
            name: harddrive
          - cdrom:
              bus: sata
            name: virtiocontainerdisk
        machine:
          type: q35
        resources:
          requests:
            memory: 8G
      volumes:
      - name: cdromiso
        persistentVolumeClaim:
          claimName: pv-windows-iso
      - name: harddrive
        persistentVolumeClaim:
          claimName: pv-windows-hd
      - containerDisk:
          image: kubevirt/virtio-container-disk
        name: virtiocontainerdisk

  • vm创建好之后,查看vm以及对应的pod是否正常
  • 测试console能正常连接
  • 测试vnc,正常情况下会弹出windows的安装窗口,测试环境受限制弹不出来,无法继续安装。
  • 因为windows iso镜像还没安装,所以虚机也没起来,只是qemu-kvm进程运行正常。
  • 所以对应的windows虚机IP无法ping通。

运行测试虚机(fedora虚机+initcloud)

参考文档:https://kubevirt.io/labs/kubernetes/lab2.html

  • 创建fedora的pvc,使用annotation配置fedora的cloudimage镜像url,利用了cdi从url中获取镜像
代码语言:javascript
复制
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: "fedora"
  labels:
    app: containerized-data-importer
  annotations:
    cdi.kubevirt.io/storage.import.endpoint: "https://download.fedoraproject.org/pub/fedora/linux/releases/33/Cloud/x86_64/images/Fedora-Cloud-Base-33-1.2.x86_64.raw.xz"
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  • 这里pvc绑定使用的hostpath类型的pv,当然有sc提供的pv(cbs,cfs,cos)也可以,最终会在pv的目录下创建下载的cloudimage
代码语言:javascript
复制
apiVersion: v1
kind: PersistentVolume
metadata:
  name: task-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"
    type: DirectoryOrCreate

  • 可以看到pvc启动后有importer-<pvcname>对应的pod已经运行,该pod会下载pvc中annotation的云镜像到pv挂载中。
  • 查看importer-<pvcname>的pod日志,等待pod处理完成,处理快慢依赖网速。pod日志里会有Prometheus打印的处理进度,处理完成后会有相关日志,然后pod会被删除。【注意:这里只是测试cdi的能力,建议还是直接拿下载好的cloudimage打成containerdisk镜像使用】
  • 然后创建vm挂载该pvc。该vm资源以virtio的形式挂载cloudimage,并且把cloudinit也挂载到虚机中。其中cloudinit里有公钥,虚机启动成功后可以用私钥登录。(ssh公钥秘钥的生成可以使用:ssh-keygen命令)
代码语言:javascript
复制
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  generation: 1
  labels:
    kubevirt.io/os: linux
  name: vm1
spec:
  running: true
  template:
    metadata:
      creationTimestamp: null
      labels:
        kubevirt.io/domain: vm1
    spec:
      domain:
        cpu:
          cores: 2
        devices:
          disks:
          - disk:
              bus: virtio
            name: disk0
          - cdrom:
              bus: sata
              readonly: true
            name: cloudinitdisk
        machine:
          type: q35
        resources:
          requests:
            memory: 1024M
      volumes:
      - name: disk0
        persistentVolumeClaim:
          claimName: fedora
      - cloudInitNoCloud:
          userData: |
            #cloud-config
            hostname: vm1
            ssh_pwauth: True
            disable_root: false
            ssh_authorized_keys:
            - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzJrjWS+X39RGxRiyQkUFFzcHiw5zPg2ASHRHN+wF7418yd+XqZ4PWK8oM2z0Fy4pX+MRMgH36qUhcx0qO6N1UMTsYQr0vbEJ1+6NGrgR4E3Mj3852H3dncVRjcrQL0+JdSFAzpBi/xQnqLS2BpTE0q4rh6kOGPhJ/YhhBAUwxj633o37eiBNZybmkb2XkxqG+kN0513QzPyaIfMwQ1OMe2xTiTeDJIWk1TZ8EJtp6PGxDy+CHCZCtKsE9jzohM4oZF2bBGW9A+gkwxoKAsHAZ0xD3xQFU2xRAKEgl16VNfjgeBZnpbRVIPlhlpQXWyFlJLLqMiLbt0wHhBLB9HCNZ williamji@VM-46-151-centos
        name: cloudinitdisk

  • vm资源创建成功后,可以查看vm状态是否Running,对应的virt-launcher pod是否Running
  • 等launcher pod和vm状态Running,表示虚机运行正常。
  • 使用virtctl命令连接到虚机
代码语言:javascript
复制
virtctl console vm1

  • 使用virtctl ssh命令ssh到虚机中。命令如下
代码语言:javascript
复制
virtctl ssh fedora@vm1 -i <秘钥文件>

  • 登录到虚机后,在虚拟上ping其他podIP可以ping通

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 应用场景
  • 开源项目
    • kubevirt
      • virtlet
        • kubevirt/virtlet
        • kubevirt实践
          • 创建tke集群
            • kubevirt组件部署
              • 准备container-disk镜像
                • CDI组件部署
                  • 使用container-disk镜像直接运行虚机(cirros镜像)
                    • 运行测试虚机(Windows虚机+ISO镜像为例)
                      • 运行测试虚机(fedora虚机+initcloud)
                      相关产品与服务
                      云服务器
                      云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档