12.1 对Windows容器的支持

Kubernetes从1.5版本开始就引入了管理基于Windows Server 2016操作系统的Windows容器的功能。随着Windows Server version 1709版本的发布,Kubernetes 1.9版本对Windows容器的支持提升为Beta版本。在Windows Server 2019版本发布之后,Kubernetes 1.14版本对Windows容器的支持提升为GA稳定版本,使得Linux应用和Windows应用在Kubernetes中统一混合编排成为可能,进一步屏蔽了操作系统的差异,提高了应用管理效率。

随着Windows Server版本的快速更新,目前Kubernetes唯一支持的版本是Windows Server 2019,可参考官方文档完成操作系统的安装和配置。本节对如何在Windows Server 2019上安装Docker、部署Kubernetes Node、部署服务等操作步骤和发展趋势进行详细说明。

将一台Windows Server服务器部署为Kubernetes Node,需要的组件包括Docker、Node组件(kubelet和kube-proxy)和CNI网络插件。本例以Flannel CNI插件部署容器Overlay网络,要求在Linux Kubernetes集群中已经部署好Flannel组件。注意:Windows Server仅能作为Node加入Kubernetes集群中,集群的Master仍需在Linux环境中运行。

12.1.1 在Windows Server上安装Docker

这里推荐使用Docker EE 18.09及以上版本,通过如下Powershell脚本完成安装:

12.1.2 在Windows Server上部署Kubernetes Node组件

在Windows Server上部署的Kubernetes Node组件包括kubelet和kube-proxy,本节对其安装部署、配置修改、CNI插件部署进行说明。

1)下载和安装Kubernetes Node所需的服务

从Kubernetes的版本发布页面下载Windows Node相关文件kubernetes-node-windows-amd64.tar.gz(在压缩包内包含kubelet.exe、kube-proxy.exe、kubectl.exe和kubeadm.exe),如图12.1所示。

图12.1 Kubernetes Windows Node二进制文件下载页面

将kubernetes-node-windows-amd64.tar.gz的内容解压缩到 c:\k目录下,主要需要kubelet.exe、kube-proxy.exe、kubectl.exe,即可完成Node组件的安装。

2)下载pause镜像

从Kubernetes 1.14 版本开始,微软提供了运行Pod所需的pause镜像mcr.microsoft.com/k8s/core/pause:1.2.0,我们通过docker pull命令将其下载到Windows Server上:

3)从Linux Node上复制kubeconfig配置文件和客户端CA证书

将kubeconfig文件从已存在的Linux Node复制到Windows Node的C:\k目录下,并将文件名改为config。将客户端CA证书client.crt、client.key、ca.crt复制到相应的目录下,例如C:/k/ssl_keys/。

config的内容示例如下:

使用kubectl.exe config命令验证能否正常访问Master,例如:

4)下载Windows Node所需的脚本和配置文件

从官方GitHub代码库下载Windows Node所需的脚本和配置文件,如图12.2所示。

图12.2 Windows Node所需的脚本和配置文件下载页面

下载后,将全部文件都复制到C:\k目录下。

5)下载CNI相关的脚本和配置文件

这里以Flannel为例进行CNI网络配置,从GitHub下载相关文件,如图12.3所示。

图12.3 Flannel脚本和配置文件下载页面

下载后,将全部文件都复制到C:\k目录下,覆盖同名的其他文件。

6)修改Powershell脚本中的配置参数

下面对Powershell脚本中需要修改的关键参数进行说明。

(1)start.ps1脚本。修改以下启动参数的值,也可以在运行start.ps1时通过命令行参数指定:

参数说明如下。

◎ clusterCIDR:Flannel容器网络的IP地址范围设置,与Master设置保持一致。

◎ KubeDnsServiceIP:使用Kubernetes集群DNS服务的ClusterIP地址,例如169.169.0.100。

◎ serviceCIDR:使用Master设置的集群Service的ClusterIP地址范围,例如169.169.0.0/16。

◎ InterfaceName:Windows主机的网卡名,例如Ethernet。

◎ LogDir:日志目录,例如C:\k\logs。

◎ KubeletFeatureGates:kubelet的feature gates可选参数设置。

(2)通过环境变量设置Node名称。在脚本中会将环境变量NODE_NAME的值作为Node名称,建议将其设置为Windows Server的IP地址:

(3)helper.psm1脚本。helper.psm1脚本为start-kubelet.ps1(启动kubelet的脚本)使用的辅助脚本,其中通过许多函数进行了系统设置,关键的修改点如下。

◎ 将--hostname-override的值设置为Windows Server的IP地址,例如:

◎ 在Update-CNIConfig函数内设置Nameservers(DNS服务器)的IP地址,例如169.169.0.100:

◎ 在Update-NetConfig函数内设置Flannel容器网络IP地址池,例如10.244.0.0/16:

(4)register-svc.ps1脚本。register-svc.ps1脚本通过nssm.exe将flanneld.exe、kubelet.exe和kube-proxy.exe注册为Windows Server的系统服务,关键的修改点如下:

参数说明如下。

◎ clusterCIDR:Flannel容器网络IP地址范围设置,与Master设置保持一致。

◎ KubeDnsServiceIP:使用Kubernetes集群DNS服务的ClusterIP地址,例如169.169.0.100。

◎ LogDir:日志目录,例如C:\k\logs。

◎ Hostname:Node名称,建议将其设置为Windows Server的IP地址。

(5)start-kubeproxy.ps1脚本。将--hostname-override的值设置为Windows Server的IP地址,例如:

7)启动Node

在配置修改完毕后运行start.ps1脚本,启动Windows Node(加入Kubernetes集群):

将启动参数-ManagementIP的值设置为Windows Node的主机IP地址。

该脚本的启动过程如下。

(1)启动flanneld,设置CNI网络,如图12.4所示。

图12.4 启动flanneld,设置CNI网络

(2)打开一个新的powershell窗口来启动kubelet,如图12.5所示。

图12.5 kubelet的启动日志

(3)打开一个新的powershell窗口来启动kube-proxy,如图12.6所示。

图12.6 kube-proxy的启动日志

(4)在服务启动成功之后,在Master上查看新加入的Windows Node:

查看这个Node的Label,可以看到其包含“kubernetes.io/os=windows”的标签,与Linux Node进行区分(Linux Node的标签为“kubernetes.io/os=linux”):

12.1.3 在Windows Server上部署容器应用和服务

在Windows Node启动成功且状态为Ready之后,就可以像在Linux Node上部署容器应用一样,在Windows Node上部署Windows容器应用了。

1)部署win-server容器应用和服务

以下为win-server服务示例,包括一个Deployment和一个Service的定义。

其中容器镜像的版本需要与Windows Server 2019的版本匹配,例如mcr.microsoft.com/windows/servercore:1809-amd64,版本信息详见Docker Hub官网的说明。

在Deployment的配置中需要设置nodeSelector为“kubernetes.io/os:windows”,以将Windows容器调度到Windows Node上。另外设置Service为NodePort类型,验证能否通过Windows Server主机IP地址和NodePort端口号访问服务。

win-server.yaml配置文件的内容如下:

通过kubectl create命令完成部署:

在Pod创建成功后,查看Pod的状态:

查看Service的信息:

2)在Linux环境中访问Windows容器服务

(1)在Linux容器内访问Windows容器服务,通过Windows Pod IP访问成功:

(2)在Linux容器内访问Windows容器服务,通过Windows容器Service IP访问成功:

(3)在Linux容器内访问Windows容器服务,通过Windows Server的IP和NodePort访问成功:

3)在Windows Server主机上访问Windows容器服务

(1)在Windows Server主机上访问Windows容器服务,通过Windows Pod IP访问成功:

(2)在Windows Server主机上访问Windows容器服务,通过Windows容器Service IP访问成功:

(3)在Windows Server主机上访问Windows容器服务,通过Windows Server的IP和NodePort无法访问(这是Windows网络模型的一个限制):

4)在Windows容器内访问Linux容器服务(示例中Web服务已部署)

(1)在Windows容器内访问Linux容器服务,通过Linux Pod IP访问成功:

(2)在Windows容器内访问Linux容器服务,通过Linux服务IP访问成功:

(3)在Windows容器内访问Linux容器服务,通过Linux服务名称访问成功:

12.1.4 Kubernetes支持的Windows容器特性、限制和发展趋势

本节从Kubernetes管理功能、容器运行时、持久化存储、网络、已知的功能限制和计划增强的功能几个方面,对Kubernetes支持的Windows容器特性、限制和发展趋势进行说明。

1)Kubernetes管理功能

(1)Pod:

◎ 支持一个Pod内的多个容器设置进程隔离和Volume共享;

◎ 支持显示Pod详细状态信息;

◎ 支持Liveness和Readiness健康检查机制;

◎ 支持postStart和preStop命令设置;

◎ 支持ConfigMap、Secret以环境变量或Volume设置到容器内;

◎ 支持EmptyDir类型的Volume存储卷;

◎ 支持挂载主机上的命名管道(named pipe);

◎ 支持资源限制的设置;

◎ 支持在Pod或容器级别配置GMSA(基于组管理的AD服务帐户),支持基于AD的身份验证,从Kubernetes 1.14版本开始引入,在1.18版本时达到Stable阶段。需要预先配置CRD“GMSACredentialSpec”、配置GMSA Webhook、将Windows Node配置到AD中、创建GMSA凭据规约、为GMSA账户设置正确的RBAC策略等,然后在Pod或Container级别设置securityContext.windowsOptions.gmsaCredentialSpecName为GMSACredentialSpec名称,这样就可以为Pod或容器设置正确的AD身份了。

(2)支持的控制器类型包括ReplicaSet、ReplicationController、Deployments、StatefulSets、DaemonSet、Job和CronJob。

(3)服务:

◎ 支持ClusterIP、NodePort、LoadBalancer等服务类型;

◎ 支持Headless服务;

◎ 支持服务外部名称ExternalName。

(4)其他:

◎ 支持Pod和容器级别的性能指标;

◎ 支持自动水平扩缩容HPA;

◎ 支持kubectl exec登录容器;

◎ 支持Resource Quota资源配额设置;

◎ 支持Preemption调度策略。

2)容器运行时

(1)Docker EE版本:从Kubernetes 1.14版本开始支持Docker EE 18.09及以上版本。

(2)CRI-ContainerD:从Kubernetes 1.18开始增加在Windows上运行ContainerD的支持,目前为Alpha阶段。

3)持久化存储

(1)内置支持的持久化存储类型包括awsElasticBlockStore、azureDisk、azureFile、gcePersistentDisk、vsphereVolume。

(2)FlexVolume插件:FlexVolume插件以二进制可执行文件提供,需要将其部署在Windows主机上,支持的插件类型包括SMB和iSCSI。

(3)CSI插件:CSI插件需要以特权模式运行,在Windows上通过csi-proxy进行代理,需要预先将csi-proxy二进制文件部署在Windows主机上。

4)网络

Windows容器通过CNI插件设置网络。在Windows上,容器网络与虚拟机网络相似,每个容器都将被设置一个虚拟网卡(Virtual Network Adapter,vNIC),并连接至一个Hyper-V虚拟交换机(vSwitch)。Windows通过HNS(Host Networking Service)服务和HCS(Host Compute Service)服务完成容器的虚拟网卡vNIC设置和网络连通性设置。

目前Windows支持5种网络驱动或网络模式:L2bridge、L2tunnel、Overlay、Transparent和NAT,对各种模式的详细说明参见官方文档。

另外,Flannel CNI插件的VXLAN模式支持目前为Alpha阶段。

目前支持的Pod、Service、Node之间的网络访问方式如下:

◎ Pod→Pod (IP)

◎ Pod→Pod (Name)

◎ Pod→Service (ClusterIP)

◎ Pod→Service (PQDN,不包含"."的相对域名)

◎ Pod→Service (FQDN)

◎ Pod→External (IP)

◎ Pod→External (DNS)

◎ Node→Pod

◎ Pod→Node

目前支持的IPAM选项包括Host-local、HNS IPAM、Azure-vnet-ipam。

5)已知的功能限制

(1)控制平面:Windows Server仅能作为Node加入Kubernetes集群中,集群的Master仍需在Linux环境中运行。

(2)计算资源管理:

◎ Windows没有类似于Linux cgroups的管理功能;

◎ Windows容器镜像的版本需要与宿主机的操作系统版本匹配,未来计划基于Hyper-V隔离机制实现向后版本兼容。

(3)暂不支持的特性:

◎ TerminationGracePeriod;

◎ 单文件映射,将在CRI-ContainerD中实现;

◎ Termination message,将在CRI-ContainerD中实现;

◎ 特权模式;

◎ 巨页(HugePage);

◎ 节点问题检测器(node problem detector);

◎ 部分共享命名空间的特性。

(4)存储资源管理:

◎ 存储卷仅支持以目录形式挂载到容器中,不支持以文件形式挂载;

◎ 不支持只读文件系统;

◎ 不支持user-mask、permissions等Linux文件系统设置;

◎ 不支持subpath挂载;

◎ 不支持块设备;

◎ 不支持挂载内存为存储介质;

◎ 不支持基于NFS的存储卷。

(5)网络资源管理:Windows网络与Linux网络在许多方面都不同,关于Windows容器网络的概念,可以参考官网的说明。由于Windows网络技术的特点,以下Kubernetes容器网络特性暂不支持:

◎ hostnetwork模式;

◎ 从Windows Server宿主机通过NodePort访问服务;

◎ 未来的版本支持从Windows Server宿主机访问服务的虚拟ClusterIP地址;

◎ kube-proxy对overlay网络的支持目前为Alpha阶段,要求在Windows Server 2019上安装KB4482887;

◎ 本地流量策略和DSR模式;

◎ l2bridge、l2tunnel和overlay几种网络模式不支持IPv6;

◎ win-overlay、win-bridge和Azure-CNI几种网络插件不支持ICMP协议出站Outbound访问。

Kubernetes从1.15版本开始,支持通过kubectl port-forward命令实现服务端口转发功能。

Flannel CNI插件的限制包括:

◎ 无法实现Node到Pod网络通信;

◎ 限制使用VNI端口号4096和UDP端口号4789,将在未来的版本中解决。

DNS域名解析的限制包括:

◎ ClusterFirstWithHostNet设置;

◎ 可用查询DNS后缀仅有一个,即namespace.svc.cluster.local;

◎ 在Windows上有多个DNS域名解析器,推荐使用Resolve-DNSName。

安全相关的限制包括:

◎ 不支持RunAsUser,未来考虑增加RunAsUsername设置;

◎ 不支持Linux上的SELinux、AppArmor、Seccomp、Capabilities等设置。

另外,还包括一些API的限制。

6)计划增强的功能

◎ 通过kubeadm完成Windows Node的部署,目前为持续更新阶段。

◎ 支持基于Hyper-V虚拟化技术在1个Pod中包含多个容器(目前在1个Pod中只能包含1个容器)。

◎ 支持Service Accounts中的组管理,目前为Beta阶段。

◎ 支持更多的CNI插件。

◎ 支持更多的存储插件。