一、Windows容器概述

1、Windows 容器类型

    Windows 容器包括两个不同的容器类型或运行时。

    WindowsServer 容器

    Hyper-V容器

2、Windows容器基础知识

    容器主机:使用 Windows 容器功能配置的物理或虚拟计算机系统。 容器主机将运行一个或多个 Windows 容器。

    容器映像:在对容器文件系统或注册表进行修改时(如软件安装),将在沙盒中捕获它们。 在许多情况下,你可能希望捕获此状态,以便可以创建继承这些更改的新容器。这就是映像的本质:一旦容器停止,你便可以放弃该沙盒,或者可以将其转换为新的容器映像。 例如,让我们想象你已从 WindowsServer Core 操作系统映像部署一个容器。 然后你将 MySQL 安装到此容器中。 从此容器创建新映像将充当该容器的可部署版本。此映像将只包含所做的更改 (MySQL),但是将充当容器操作系统映像之上的一个层。

    沙盒:容器启动后,将在此“沙盒”层中捕获所有的写入操作,如文件系统修改、注册表修改或软件安装。

    容器操作系统映像:从映像部署容器。 容器操作系统映像是可能组成容器的许多映像层中的第一层。此映像提供操作系统环境。 容器操作系统映像不可变,并且无法修改。

    容器存储库: 每次创建容器映像时,容器映像及其依赖关系都会存储在本地存储库中。这些映像可以在容器主机上重复使用多次。 容器映像还可以存储在公共或私有注册表(如 DockerHub)中,以便可以在许多不同的容器主机上使用它们。

Kubernetes1.5新特性:支持windows容器_javascript

二、K8S 1.5 新特性介绍

在Kubernetes1.5中增加了对windows容器的支持,kubelet和kube-proxy已经可以部署在windows操作系统上,但是API Server, Scheduler, Controller Manager等控制功能组件还是需要部署在linux操作系统上。

这是一个α特性,也就是说只能在测试环境中使用的特性,将来整体设计还有可能发生变化,而且目前只能够支持windows server 2016操作系统,但是无论如何,Kubenetes已经开始支持windows容器了,大家可以在POC环境中展现这个能力了。

下面是使用这个新特性前应该具备的先决条件:

1、 部署Kubernetes1.5控制功能组件到Linux操作系统上

2、 在Linux上配置kubernetes网络插件

3、 准备windows操作系统:Windows Server 2016 (RTM version 10.0.14393 or later)

4、 准备Docker容器环境:Docker Version 1.12.2-cs2-ws-beta or later

三、配置windows网络

    网络配置成三层路由可达。像flannel、calico等第三方网络插件在windows环境中不能正常工作,在三层路由可达的环境中,集群节点使用B类地址中的IP,工作节点使用C类地址中的IP,所有工作节点上的POD都接入这个C类地址组成的子网中,这样不但相同节点上的POD可以相互通讯,而且不同节点上的POD也可以可以通讯, windows操作系统和Linux操作系统中的POD也可以通讯。

    1、配置Linux操作系统网络:在Linux节点上面创建一个brige私有网络,然后通过一个公有网络来实现上面说的三层路由可达。

    2、配置windows操作系统网络:

        2.1、每个windows节点都需要两块虚拟网络适配器,通过Hyper-V虚拟交换机采用透明方式和二层网桥方式来配置这两块虚拟网络适配器

        2.2、创建容器透明网络(在下面“配置路由”章节中会详细介绍)

        2.3、启用windows操作系统的路由和远程访问服务(Routing and Remote Access Service)。路由和远程访问服务(Routing and Remote Access Service)是Windows  server中绑定的一个软件组件,除了分组过滤,按需拨号路由选择和支持开放最短路径优先(OSPF)之外, 还结合有RAShe多协议路由选择,允许在虚拟网络适配器之间进行路由。启动服务后几句可以在不同虚拟网络适配器之间进行路由,并且可以将网络包发送给在这个节点上运行的POD中。

        2.4、路由规则明确访都通过公有网络来访问其他POD。把这些路由规则都添加到路由表中。下图描述了kubernetes下windows网络环境配置,在Hyper-V虚拟机中配置了两块网卡,一块可以访问共有网络(10.5.6.216和10.5.6.218),一块可以访问私有网络(192.168.1.1和192.168.2.1),在每台Hyper-V虚拟机中都配置路由规则,通过路由规则来确保不同Hyper-V虚拟机中的容器可以通过IP相互访问。


四、配置windows容器

    为了在Kubernetes上运行windows容器,我们需要配置windows操作系统,并且还需要配置Kubernetes在节点上安装的组件,为了保证不同Kubernetes节点之间的POD可以相互访问,还需要配置路由规则。

1、配置windows操作系统

    1.1、上面已经介绍了,需要准备Windows Server 2016 (RTMversion 10.0.14393 or later)和Docker Version1.12.2-cs2-ws-beta。

    1.2、因为docker发布的GA版本中不具备支持windows版本DNS功能,但是这个功能已经合入docker master版本中了,所以需要在docker master中下载支持windows版本DNS功能的版本。

    1.3、从docker hub(https://hub.docker.com/r/apprenda/pause)上拉拽镜像apprenda/pause。

    1.4、启用windows操作系统的路由和远程访问服务(Routing and Remote Access Service)。

2、配置Linux主机

    2.1、安装Linux操作系统。

    2.2、安装CNI网络插件。

3、配置Kubernetes组件

    3.1、安装Git(用来从Git上面获取Kubernetes源代码)

    3.2、安装Go1.7.1以及以上版本(用来提供Kubernetes所需的Go语言运行环境)

    3.3、安装make(用来编译Kubernetes源代码)

4、编译kubelet组件

    4.1、cd $GOPATH/src/k8s.io/kubernetes

    4.2、在Linux操作系统上或者MacOS操作系统上:KUBE_BUILD_PLATFORMS=windows/amd64make WHAT=cmd/kubelet

    4.3、在windows操作系统上:go build cmd/kubelet/kubelet.go

5、编译kube-proxy组件

    5.1、cd $GOPATH/src/k8s.io/kubernetes

    5.2、在Linux操作系统上或者MacOS操作系统上:KUBE_BUILD_PLATFORMS=windows/amd64make WHAT=cmd/kube-proxy

    5.3、在windows操作系统上:go build cmd/kube-proxy/proxy.go

6、配置路由策略

下面环境由一个Linux操作系统节点和两个windows操作系统节点组成,Kubernetes集群中CIDR配置为192.168.0.0/16。

主机名

路由IP地址

POD CIDR

Lin01

<IP of Lin01 host>

192.168.0.0/24

Win01

<IP of Win01 host>

192.168.1.0/24

Win02

<IP of Win02 host>

192.168.2.0/24

    6.1、配置路由

        6.1.1、配置Lin01主机

[javascript] 
​​view plain​​​
​​​copy​​



1. ip route add 192.168.1.0/24 via <IP of Win01 host>
2. ip route add 192.168.2.0/24 via <IP of Win02 host>
6.1.2、配置Win01主机

[javascript]
​​view plain​​​
​​​copy​​



1. docker network create -d transparent --gateway192.168.1.1 --subnet 192.168.1.0/24 <network name>
2. # A bridge is created with Adapter name "vEthernet(HNSTransparent)". Set its IP address to transparent network gateway
3. netsh interface ipv4 set address "vEthernet(HNSTransparent)" addr=192.168.1.1
4. route add 192.168.0.0 mask 255.255.255.0 192.168.0.1 if<Interface Id of the Routable Ethernet Adapter> -p
5. route add 192.168.2.0 mask 255.255.255.0 192.168.2.1 if<Interface Id of the Routable Ethernet Adapter> -p
6.1.3、配置Win02主机

[javascript]
​​view plain​​​
​​​copy​​



1. docker network create -d transparent --gateway192.168.2.1 --subnet 192.168.2.0/24 <network name>
2. # A bridge is created with Adapter name "vEthernet(HNSTransparent)". Set its IP address to transparent network gateway
3. netsh interface ipv4 set address "vEthernet(HNSTransparent)" addr=192.168.2.1
4. route add 192.168.0.0 mask 255.255.255.0 192.168.0.1 if<Interface Id of the Routable Ethernet Adapter> -p
5. route add 192.168.1.0 mask 255.255.255.0 192.168.1.1if <Interface Id of the Routable Ethernet Adapter> -p

五、启动Kubernetes集群

1、在Linux节点上启动Kubernetes控制组件,在windows节点上启动kubelet组件。

2、在windows节点上运行PowerShell脚本。(需要注意的是,如果重启节点或者进程退出了,需要重启启动kubelet组件)

3、设置环境变量CONTAINER_NETWORK,env:CONTAINER_NETWORK="<dockernetwork>"

4、在windows操作系统上运行kubelet。在PowerShell窗口中运行命令D:\>kubelete.exe --hostname-override=<ip address/hostname ofthe windoes node> --pod-infra-ontainer-image="apprenda/pause"--resolv-conf="" --api_servers=<api server location>

5、在windows操作系统上运行kube-proxy。在PowerShell窗口中使用管理员权限运行命令,如果节点重新启动或者进程终止了,需要在PowerShell窗口中重新启动kube-proxy命令。

    5.1、在节点设置环境变量$env:INTERFACE_TO_ADD_SERVICE_IP= "vEthernet (HNS Internal NIC)",这样在安装完docker后就可以直接使用。

    5.2、在PowerShell窗口中运行kube-proxy命令。D:\>proxy.exe --v=3--proxy-mode=userspace --hostname-override=<ip address/hostname of thewindows node> --master=<api server location> --bind-address=<ipaddress of the windows node>

六、Windows节点上POD调度

    如上所述,我们已经搭建了Linux和Windows两种类型操作系统的Kubernetes集群环境,我们还需要配置Kubernetes,这样才能够在windows节点上调度对应的windows容器,可以通过设置kubernetes.io/os参数来实现。

    下面的例子中配置了iis(internet信息服务)容器,这种容器只能在windows操作系统上运行,通过配置nodeSelector来让Kubernetes在windows操作系统上调度iis容器。

[java]  ​​view plain​​​  ​​​copy​

1. {
2. "apiVersion":"v1",
3. "kind":"Pod",
4. "metadata":{
5. "name":"iis",
6. "labels":{
7. "name":"iis"
8. }
9. },
10. "spec":{
11. "containers":[
12. {
13. "name":"iis",
14. "image":"microsoft/iis",
15. "ports":[
16. {
17. "containerPort":80
18. }
19. ]
20. }
21. ],
22. "nodeSelector":{
23. "beta.kubernetes.io/os": "windows"
24. }
25. }
26. }

七、已知的限制

1、由于在Windows操作系统上没有网络命名空间,所以在Windows节点上一个POD中只能运行一个容器。

2、因为Windows容器上的bug,在Windows节点上Secrets这种对象类型无法正常工作。Secrets这种对象类型主要是在容器中的数据卷里以文件的形式被使用的,但是这种使用方式在Windows容器上使用时会出错。

下面是这个问题的详细描述:

    在Windows Server 2016主机上创建一个指向文本文件的符号链接,将这个符号链接所在工作目录作为一个数据卷挂载到Windows容器中。在Windows Server 2016操作系统上可以正常访问这个符号链接,但是在Windows容器中访问这个符号链接失败。

    如果用过 Linux ,那想必也看到过符号链接(这是一种特殊的文件),也用过 “ ln ” 这个链接命令,mklink 和 ln 的功能几乎一样。mklink 便是用来创建符号链接的,自从 Vista 以后,微软便在 widows中 偷偷地用起了这个工具 。在用户目录下,可以看到很多很像快捷方式的文件,当然这是隐藏的,但却不能打开,其实这便是符号链接。

通过下面步骤可以重现这个问题:

a、打开PowerShell窗口,在temp/work目录下面创建一个文本文件

[javascript]
​​view plain​​​
​​​copy​​



1. echo "Symlink Test" > test.txt
b、创建一个文件符号链接指向这个文本文件

[javascript]
​​view plain​​​
​​​copy​​



1. cmd /c mklink symtmp.txt test.txt
c、将目录temp/work挂载到Windows容器中

[javascript]
​​view plain​​​
​​​copy​​



1. docker run --rm -v c:\wd\test:c:\wd\test -itmicrosoft/windowsservercore cmd
打开PowerShell窗口,在容器内部运行如下命令:

[javascript]
​​view plain​​​
​​​copy​​



1. C:\> type C:\wd\test\symtmp.txt

实际输出结果如下:

[javascript]  ​​view plain​​​  ​​​copy​

1. type : Could not find a part of the path'C:\wd\test\symtmp.txt'.
2. At line:1 char:1
3. + type C:\wd\test\symtmp.txt
4. + ~~~~~~~~~~~~~~~~~~~~~~~~~~
5. +CategoryInfo : ObjectNotFound:(C:\wd\test\symtmp.txt:String) [Get-Content], DirectoryNotFoundException
6. + FullyQualifiedErrorId :GetContentReaderDirectoryNotFoundError,Microsoft.PowerShell.Commands.GetContentCommand

如果运行正常的话,输出结果应该如下:

[javascript]  ​​view plain​​​  ​​​copy​

  1. C:\> type C:\wd\test\symtmp.txt
  2. Symlink Test


3、在Windows节点上还不支持ConfigMap这种对象类型。 4、在Windows节点上执行kube-proxy命令时,实际上是通过netsh命令中的portproxy参数来实现的,当前只支持tcp协议,所以目前配置DNS时只能通过TCP协议来配置。