小木猫

 找回密码
 立即注册

扫一扫,访问微社区

搜索
热搜: 活动 交友 discuz
查看: 753|回复: 0

智汇华云 | kata container virtiofs测试和技术分析

[复制链接]

2400

主题

2402

帖子

8253

积分

版主

Rank: 7Rank: 7Rank: 7

积分
8253

木猫可人突出贡献

发表于 2021-7-14 23:43:09 | 显示全部楼层 |阅读模式
  智汇华云|katacontainervirtiofs测试和技术分析

  

  云原生技术已经成为加快企业数字化转型的一个不折不扣的风向标。而以容器为代表的云原生技术正在成为释放云价值的最短路径。本期智汇华云,带大家一起了解和体验安全容器katacontainer的?些特性。

  前?

  当前云原?技术发展的如?如荼,容器化技术以及kubernetes容器化应?管理平台,带来了全新的?态系统.随着容器技术的发展,容器运?时规范OCI也逐渐脱离Docker被单独提了出来,kubernetes?期使?的容器运?时是runC,轻量,性能?,但因为共?linux内核以及namespace机制隔离的不彻底,存在?定的安全问题,业界涌现了好?个安全容器的解决?案,?如Google的gVisor,Amazon的Firecracker,vmware的CRX等,开源世界???较有名的解决?案是katacontainer,本?主要就关注在安全容器katacontainer的?些特性了解和体验。kataContainer

  katacontainer由?系列技术组成,来源于两个项?的合并,IntelClearContainers和HyperrunV,然后?加上redhat贡献的virtio-fs,?种在guest和宿主机之间共享?件系统的?案。涉及的技术有QEMU/KVM,Linuxkernel,?件系统,容器运?时,容器?络等,是?项?较复杂的组合产品,?且还保持着很?的新特性开发进度,本次主要体验和梳理virtiofs相关的内容,这些内容有部分是来源于kata的社区邮件列表以及slack,还有微信群,?常感慨,kata的社区真是?常的Nice,专业程度和热?都令?感动。

  virtiofs?件系统结构

  默认容器是使?cgroup和namespace做进程,?络,?件系统挂载点等隔离,是?常轻量级的。?katacontainer为了实现安全容器,使?了VM虚拟机作为强隔离?段,有独?的内核和虚拟机镜像,为了降低资源消耗,hypervisor使?了?常?的guestkernel和guestimage,?度优化了内核的启动时间,最?化了内存占?,只提供容器负载所需要的最基本的服务。virtio-fs?件系统,在资源消耗上也使?了多种优化特性。下?就来看?看具体是怎么使?的,以及特性理解katacontainer作为除了runC之外另?种runtime,需要先在kubernetes环境中做集成部署,以便做各种观察。当然直接使?他的CTR?具也是可以,只是缺少CNI的?持,?络??不能?动配置。katacontainerconfiguration.toml配置参数有两种共享?件系统类型可以选择,之前默认是virtio-9p,现在基本上都会选择virtio-fs,有若?优点。virtio-9p和virtio-fs?件系统对?

  1.virtio-9p基于现存的?络协议,并没有虚拟化场景提供优化

  2.virtio-fs利?了hypervisor和虚拟机处于相同节点的优势

  DAX特性,?件内容能够映射到宿主机的内存窗?,允许客户机直接访问宿主机的pagecache

  减少内存占?,因为客户机cache已经被绕过了

  不需要?络节点通信,提?了IO性能

  测试

  katacontainer与整合使?virtiofsd,把宿主机?录共享给微虚拟机使?。测试环境版本:Centos8

  qemu-kvm5.1

  kubernetes1.18

  containerd1.4.4

  katacontainer2.0.4

  使?kubernetes新版本的RuntimeClass对象,指定handler:kata

  创建pod

  1apiVersion:v1

  2kindod

  3metadata:

  4name:kata-alpine

  5spec:

  6runtimeClassName:kataclass

  7containers:

  8-name:alpine

  9image:alpine:latest

  10imagePullPolicy:IfNotPresent

  11command:

  12-/bin/sh

  13-"-c"

  14-"sleep60m"

  15restartPolicy:Always

  16nodeSelector:

  17kubernetes.io/hostname:

  k8s05k8s05节点宿主机进程查看

  1[root@k8s05~]#psaux|grepkata

  2root5000860.00.1141218447796?SlJun1814:00/usr/bin/conta

  3root5001170.00.01290644960?SlJun180:00/usr/libexec/k

  4root5001550.23.243675161059672?SlJun1841:47/usr/bin/qemu-

  5root5001580.00.85667064271696?SlJun180:03/usr/libexec/k

  可以看到katacontainerv2启动了新的与kubernetes对接的CRI进程containerd-shim-kata-v2,KVM虚拟机,还有2个virtiofsd进程。为什么会启动2个virtiofs呢?为了提?安全性,virtiofsd进程fork??,以便进?新的mount/pid/net命名空间,只有?进程内存映射,CPU使???处于活跃状态。

  可以看到qemu虚拟化了设备vhost-user-fs-pci,有?个tag为kataShared,这个就是虚拟机要mount的源。tag就是?个?定义?件系统需要接收的参数,定义路径?的。

  NotethatLinux4.19-basedvirtio-fskernelsrequiredadifferentmountsyntax.mount-tvirtio_fsnone/mnt-otag=myfs,rootmode=040000,user_id=0,group_id=0instead.mount_tag:AtagwhichactsasahinttotheguestOSandisusedtomountthisexportedpath.

  1-devicevhost-user-fs-pci,chardev=char-538bb1c14588b18e,tag=kataShared

  进?kata容器观察

  1[root@k8s01kata-container]#kubectlexec-itkata-alpine--sh

  2/#df-h

  3FilesystemSizeUsedAvailableUse%Mountedon

  4kataShared74.0G49.5G24.4G67%/

  5tmpfs64.0M064.0M0%/dev

  6tmpfs1.4G01.4G0%/sys/fs/cgroup

  7kataShared74.0G49.5G24.4G67%/etc/hosts

  8kataShared74.0G49.5G24.4G67%/dev/termination-log

  9kataShared74.0G49.5G24.4G67%/etc/hostname

  10kataShared74.0G49.5G24.4G67%/etc/resolv.conf

  11shm1.4G01.4G0%/dev/shm

  12kataShared15.7G12.0K15.7G0%/run/secrets/kubernetes.i

  13tmpfs64.0M064.0M0%/proc/keys

  14tmpfs64.0M064.0M0%/proc/timer_list

  可以看到容器已经挂载了tag定义的?件系统。tag名字可以是任意取的,只要能guest挂载时候指定相同的就可以。对于kata来说,已经整合好了,不需要??指定

  有时候如果处于调试?的或者是想看?下虚拟机的信息,可以配置kata开启debug模式,qemu暴露vsock接?,虚拟机通过agent开启shell

  1configuration.toml

  2

  3[agent.kata]

  4debug_console_enabled=true

  宿主机再?动启动kata-monitor进程,获取sandbox的vsock地址,??监听localhost:8090端?,就可以通过kata-runtimeexec$sandboxId接?虚拟机bash了

  1[root@k8s05kata]#/usr/bin/kata-monitor

  2INFO[0010]addsandboxtocachecontainer=7e4cef94733381a9d9c509aa2a0be87e0c0bd

  3INFO[0020]deletesandboxfromcachecontainer=5246e787b17eeab4ca83e9e73583a1b5

  进?虚拟机查看

  kata根据sandbox的ID,指定唯?的宿主机内存共享?录source,传递给virtiofsd.虚拟机挂载virtiofsd导出的共享的?录到/run/kata-containers/shared/containers,然后再以bindmount的?式挂载进容器。

  1[root@k8s05~]#kata-runtimeexec0965321e164975f01c85f997fbb0183773a9e97cb5767d9

  2bash-4.2#df-h

  3FilesystemSizeUsedAvailUse%Mountedon

  4rootfs1.4G350M1.1G25%/

  5dev1.4G01.4G0%/dev

  6tmpfs1.5G01.5G0%/dev/shm

  7tmpfs1.5G16K1.5G1%/run

  8tmpfs1.5G01.5G0%/sys/fs/cgroup

  9kataShared16G1.6G15G11%/run/kata-containers/shared/containers

  10shm1.5G01.5G0%/run/kata-containers/sandbox/shm

  kata根据sandbox的ID,指定唯?的宿主机内存共享?录source,传递给virtiofsd.虚拟机挂载virtiofsd导出的共享的?录到/run/kata-containers/shared/containers,然后再以bindmount的?式挂载进容器。

  持久卷挂载

  ?络持久卷?如iscsi也是能直接挂载进kata容器的,例如创建?个pod,直接指定pvc,pv使?某?个iscsilun,然后在容器中创建?个?件

  1[root@k8s01kata-container]#kubectlexec-itiscsipd--sh

  2/#cd/mnt/iscsipd

  3/mnt/iscsipd#ls

  4lost+found

  5/mnt/iscsipd#touchaaaa.txt

  在虚拟机??已经通过virtiofs挂载在了?个容器id?录之下

  1[root@k8s05~]#kata-runtimeexece96d0ce2249e9027f0e1102e66a0c0013473ac48a088240

  2bash-4.2#mount

  3rootfson/typerootfs(rw,size=1444588k,nr_inodes=361147)

  4kataSharedon/run/kata-containers/shared/containerstypevirtiofs(rw,relatime)

  5kataSharedon/run/kata-containers/e96d0ce2249e9027f0e1102e66a0c0013473ac48a08824

  6kataSharedon/run/kata-containers/839162f25b7907bf91ecb027305e64dd5ccf36f55b15b6

  7bash-4.2#find/-nameaaaa.txt

  8/run/kata-containers/shared/containers/839162f25b7907bf91ecb027305e64dd5ccf36f55b

  在宿主机上是识别为硬盘块设备/dev/sdd,被kubelet挂载在特定?录下?,?个是sandbox_id,?个是应?container_id

  1[root@k8s05~]#lsblk

  2NAMEMAJ:MINRMSIZEROTYPEMOUNTPOINT

  3sda8:0050G0disk

  4├─sda18:101G0part/boot

  5sdc8:3202G0disk

  6sdd8:4802G0disk/run/kata-containers/shared/sandboxes/e96d0ce2

  就如前?说的,所有数据都要经过virtiofs,不管是镜像数据还是?络存储卷。虚拟机要和宿主机数据交互,就必须要穿过qemu,virtiofs就是穿过qemu的桥梁,提供共享?件机制。数据相关的操作最终还是在宿主机上,?如镜像层的合并,仍然是containerd的存储层插件snapshotter完成,底层仍然是调?了overlayfs?件系统

  1/etc/containerd/config.toml

  2[plugins."io.containerd.grpc.v1.cri".containerd]

  3snapshotter="overlayfs"

  4default_runtime_name="runc"

  5no_pivot=false

  6disable_snapshot_annotations=true

  7discard_unpacked_layers=false

  8...

  9[plugins."io.containerd.service.v1.diff-service"]10default=["walking"]

  另外katacontainer整合使?virtiofs的?式,与独???操作virtiofs的?式,有些地?稍有不同,?如按virtiofs官?说明,可以指定host?件?录$TESTDIR作为源

  1./virtiofsd--socket-path=/tmp/vhostqemu-osource=$TESTDIR-ocache=alwa

  ?在kataruntime??是不允许的,?如在configuration.toml?配置

  1virtio_fs_extra_args=["-o","--thread-pool-size=1","-o","/opt/kata-instance"]

  kubelet会报错:

  WarningFailedCreatePodSandBox1s(x14over15s)kubelet,k8s05Failedtocreatepodsandbox:rpcerror:code=Unknowndesc=failedtocreatecontainerdtask:failedtolaunchqemu:exitstatus1,errormessagesfromqemulog:qemu-system-x86_64:cannotcreatePIDfifile:Cannotopenpidfifile:Nosuchfifileordirectory

  kata还会打开vhost-usersocket?件描述符,传递给virtiofsd。可能有?会有疑问,为什么每?个virtiofsd进程的fd参数都等于3,会不会有冲突。其实不会,因为?件描述符是进程独?的,STDIO占据了0,1和2,那么virtiofsd第?个可?的fdnum就是3了

  virtiofsdcacheguest

  guest?成是会指定内存??,virtiofsd会共享使?guest的内存。默认使?memory-backend-fifile内存对象

  virtiofsd共享使?VM内存,configuration.toml配置参数default_memory

  qemu命令?接受的参数

  1-objectmemory-backend-file,id=dimm1,size=3072M,mem-path=/dev/shm,share=on-numa

  guest和host数据传输都是通过virtio-fs,包括容器镜像和容器卷,读写权限取决于virtiofsd进程的权限

  DAX(直接访问)

  dax

  DAXwindows是?块虚拟内存区域,通过PCIBar把?件映射到guest??,并不真正的占?主机那么多内存,即使有100个虚拟机,设置的DAXcache是1G,也不会真的使?100G内存。只是?种page映射机制,所以也不需要任何的cache策略。

  要任何的cache策

  katacontainer官?下载的版本默认没有不?持,需要编译安装gitlab托管的virtio-fsqemu项?qemu5.0-virtiofs-dax分?

  configuration.toml设置virtio_fs_cache_sizedaxwindow??,qemu初始化vhost-user-fs-pci设备

  1-machineq35,accel=kvm,kernel_irqchip,nvdimm

  2-devicenvdimm,id=nv0,memdev=mem0-objectmemory-backend-file,id=mem0,mem-path=/o

  3-devicevhost-user-fs-pci,chardev=char-ea09ec33d071ac42,tag=kataShared,cache-size

  如果是rootfsimage可以看到模拟的nvdimm信息,??编译镜像的话,image_builder.sh构建脚本会在image?件头部写?daxmetadata信息。initrdimage看不到。image相当于是直接?rootfs引导,initramfs(initrd)是把cpio+gz打包压缩的rootfs解压到内存?,再?内存?的initramfs来引导。前者可以利?dax,让guestos认为这就是个dimm内存,不需要再加载到另?块内存?,后者就是需要解压到?块内存。

  DAX背后的想法是避免在guest中使?_second_缓冲区缓存。?般对于常规?件,guest会维护???件系统缓冲区。

  现在呢,对于与virtiofs共享的?件,由于它们驻留在主机上,您将在主机上拥有?份缓存副本,然后virtiofs会将其发送给guest,然后guest就也有了?份副本,成本就?较?。DAX就是为了解决这个问题的,它所做的就是将主机buffffermap到客户机中,guest使?与主机相同的物理内存,即使它使?不同的虚拟地址。如果没有DAX,内存使?量可能会?常?,因为每个guest都有??的?件缓冲区。例如,如果您启动?个Fedora容器并“dnfinstallsomething”,您将看到内存使?量增加了约300M,因为在该操作期间读取/写?了许多?件。如果没有DAX,那么guest也需要分配350M。使?DAX,它就会直接使?宿主机中已为这些?件缓冲分配的350M内存

  性能测试

  测测DAXwindow??对性能的影响(virtio_fs_cache_size=512)

  ??件测试

  1fio--name=small-file-multi-read--directory=/usr/share/nginx/html\

  2--rw=randread--file_service_type=sequential\

  3--bs=4k--filesize=10M--nrfiles=100\

  4--runtime=60--time_based--numjobs=1

  5...

  6small-file-multi-readgroupid=0,jobs=1):err=0:pid=190:MonJul507:05:18

  7read:IOPS=12.0k,BW=46.0MiB/s(49.2MB/s)(212MiB/4505msec)

  件测试

  1fio--name=5G-bigfile-rand-read--directory=/usr/share/nginx/html--rw=ra

  2...

  35G-bigfile-rand-readgroupid=0,jobs=1):err=0:pid=184:MonJul506:57:0824read:IOPS=1255,BW=5024KiB/s(5144kB/s)(294MiB/60002msec)

  从压测观察到当读写的?件超过daxwindow后,性能下降很多,原因和dax映射机制有关,dax窗?的回收是?较慢的,当活跃数据超过daxwindow,产?很多的回收?作会导致性能很差。另外daxwindow的映射单元是按每2MB内存??映射的,具体来说就是由512个structpage(onestructpageforeach4Krange)和?个structfuse_dax_mapping。每个单元映射范围?约需要消耗32K额外内存。?如1GBofdaxwindow:512*32K=16MBofmemoryusage.

  同时还观察到virtiofsd占?内存很?,?如本实例qemu-system-x86_64rss内存3.1G,virtiofsdrss1.6G,?产中对资源的控制需要细节控制。

  总结

  katacontainer还是?项?较复杂的技术组合,实践?档较少,有问题要不就是求教于社区,要不就得翻源码,源码牵涉到linuxkernel,qemu/kvm,fifilesystem,内存映射,容器等多种技术,?且还是?较新的技术。但云原?安全?是未来越来越受到重视的领域,极?影响业务容器化的决策。希望?业能更多的参与到安全容器上来,增加实践场景,畅快投?云原?的怀抱。



您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表