【作者】中国农业银行研发中心张少波一、引言容器化技术是当今科技时代支持微服务和DevOps的重要推动力海浪。虽然Docker容器技术源自Linux内核相关技术,但微软、Docker和Kubernetes社区也在不断完善Windows操作系统对容器化的支持。从v1.14版本开始,Kubernetes对Windows容器的支持进入稳定阶段。本文试图从Windows容器化技术的相关概念出发,探讨Windows.NET应用在上云之路上的相关问题。2.Windows容器化技术(1)Windows容器类型与传统的硬件虚拟化技术相比,容器技术更轻量级。代价是应用程序在容器中的运行在一定程度上仍然依赖于宿主操作系统内核提供的能力。多个容器共享宿主机的操作系统内核。也正是因为这个原因,Windows容器无法在Linux上运行,Linux容器也无法在Windows上运行。为了提供容器化能力,Windows从Server2016开始逐渐加入内核命名空间、控制组、分层文件系统等内核功能,以提供类似于Linux的容器化能力。实际上,Windows支持两种类型的容器运行时:进程隔离和Hyper-V隔离。运行容器时可以指定两种隔离模式作为参数。进程隔离,也称为WindowsServer容器,是WindowsServer上的默认隔离模式。该模式下宿主机上的多个容器共享宿主机的操作系统内核,存在一定的安全隐患,仅适用于私有云环境。同时,由于共享内核,容器的内核版本要与宿主机保持一致,即只有WindowsServer2019容器才能运行在WindowsServer2019宿主机上。Hyper-V隔离是上述模式的扩展,是Windows10上默认的隔离模式。在这种模式下,每个容器独立运行在高度优化的虚拟机上,不共享主机内核,因此可以运行其他版本的内核甚至Linux内核。但是需要注意的是,只能运行相同或旧版本的内核。例如,WindowsServer2019主机除了可以运行WindowsServer2019容器外,还可以运行WindowsServer2016容器,但不能运行1903或1909容器。(2)Linux容器vsWindows容器与Linux容器相比,Windows容器有以下主要特点:1.如上所述,Windows容器内核版本与宿主机内核版本之间存在强绑定,即使Hyper-V使用模式,它只会增加对运行旧内核版本的容器的支持。在Linux上,只要内核版本高于3.10,任何版本内核的容器都可以运行。2.基础镜像较大。完整的WindowsServerimageservercore大小约为1.5G,最小的基础imagenanoserver约为100M,对应的alpineLinux只有5M左右。3、Hyper-V隔离理论上可以支持Linux容器。LCOW(Windows上的Linux容器)使用Hyper-V隔离来支持Linux容器,可以在最新的DockerforWindows中作为一项实验性功能启用。由于使用了Hyper-V,即将推出的WSL2(WindowsSubsystemforLinux2)也可以实现对Linux容器的支持。(3)Windows上的Kubernetes的局限性Windows上的Kubernetes的支持还在成熟过程中,目前已知有以下局限性:1.最低要求是WindowsServer2019和DockerEE1809。2.Kubeadm支持管理Windows节点目前还处于测试阶段,目前管理Windows的方式比较繁琐。3、目前仅支持进程隔离模式,该模式无法限制容器内存上限。4.Windows支持的CNI插件非常少,异构集群也需要插件同时支持Linux和Windows节点,所以Flannel成为了最常用的选择。目前Flannel对host-gw后端的支持是Stable,对vxlan后端的支持还在Alpha。5、不支持NFS存储。3.现有.NET应用上云(1)测试环境搭建目前Kubernetes支持Windows节点作为工作节点。本次测试环境为Kubernetesv1.17,Windows节点为WindowsServer2019和DockerEE18.09,网络方案选择为Flannel的vxlan模式。Windows节点上的Flanneld和Kube-Proxy支持作为Windows服务或DaemonSet运行。这一次,我们选择了更加稳定的Windows服务方式。经验证,节点重启后可以自动加入集群。(2)基础镜像选择微软针对不同类型的应用程序提供了四种基础镜像选择,见下表:其中,NanoServer和WindowsServerCore是最常用的选择。NanoServer的优势在于它只为.NETCore构建,镜像大小比ServerCore小很多。ServerCore除了提供.NETFramework支持外,还内置了PowerShell和WMI等功能。如果我行现有的.NETFramwork应用上云,如果不考虑改造为.NETCore应用,应该选择WindowsServerCore作为基础镜像。微软基于WindowsServerCore,提供如下镜像供选择:根据应用类型和场景选择基础镜像,然后根据内核版本确定镜像标签,即可完成基础镜像的选择。需要注意的是,微软官方仓库中的镜像每个月都会更新一次。为了保持一致性,最好在下载图片时在标签中明确指定更新哪个月份。(3)镜像制作本节我们以IIS为基础镜像制作最简单的网站镜像。Dockerfile如下:index.html的内容为:使用如下命令打包:dockerbuild-tiis-site。(4)本地运行在本地使用如下命令在浏览器访问localhost:5000中dockerrun--rm-d--nameiis-p5000:80iis-site,出现如下页面证明运行成功。可以使用命令dockerexec-itiispowershell登录正在运行的容器,查看.NETFramework版本是否为4.8,如下图。上图中很多功能没有启用,可以在制作镜像的时候使用Add-WindowsFeature添加Windows功能。与只能看到一个进程的Linux容器不同,Windows容器可以看到应用程序以外的多个进程。(5)在k8s上部署镜像创建完成后,可以尝试在Kubernetes上部署。service和deployment的使用方法和linux容器一样,这里不再赘述。由于是Linux和Windows节点共存的异构集群,所以需要通过类似“kubernetes.io/os”的nodeSelector来指定要调度到Windows节点上的Windows容器:windows。参考:SrikanthMachiraju的《Learning Windows Server Containers》https://v1-16.docs.kubernetes.io/docs/setup/production-environment/windows/user-guide-windows-nodes/https://docs.microsoft.com/zh-cn/virtualization/windowscontainers/https://kubernetes.io/docs/setup/production-environment/windows/intro-windows-in-kubernetes/
