Kubernetes1.5新特性:支援windows容器
一、Windows容器概述
1、Windows 容器型別
Windows 容器包括兩個不同的容器型別或執行時。
WindowsServer 容器 - 通過程序和名稱空間隔離技術提供應用程式隔離。 Windows Server 容器與容器主機和該主機上執行的所有容器共享核心。
Hyper-V容器 - 通過在高度優化的虛擬機器中執行每個容器,在由 Windows Server 容器提供的隔離上擴充套件。在此配置中,容器主機的核心不與 Hyper-V 容器共享。
2、Windows容器基礎知識
容器主機:使用 Windows 容器功能配置的物理或虛擬計算機系統。 容器主機將執行一個或多個 Windows 容器。
容器映像:在對容器檔案系統或登錄檔進行修改時(如軟體安裝),將在沙盒中捕獲它們。 在許多情況下,你可能希望捕獲此狀態,以便可以建立繼承這些更改的新容器。這就是映像的本質:一旦容器停止,你便可以放棄該沙盒,或者可以將其轉換為新的容器映像。 例如,讓我們想象你已從 WindowsServer Core 作業系統映像部署一個容器。 然後你將 MySQL 安裝到此容器中。 從此容器建立新映像將充當該容器的可部署版本。此映像將只包含所做的更改 (MySQL),但是將充當容器作業系統映像之上的一個層。
沙盒:容器啟動後,將在此“沙盒”層中捕獲所有的寫入操作,如檔案系統修改、登錄檔修改或軟體安裝。
容器作業系統映像:從映像部署容器。 容器作業系統映像是可能組成容器的許多映像層中的第一層。此映像提供作業系統環境。 容器作業系統映像不可變,並且無法修改。
容器儲存庫:每次建立容器映像時,容器映像及其依賴關係都會儲存在本地儲存庫中。這些映像可以在容器主機上重複使用多次。 容器映像還可以儲存在公共或私有登錄檔(如 DockerHub)中,以便可以在許多不同的容器主機上使用它們。二、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主機
ip route add 192.168.1.0/24 via <IP of Win01 host>
ip route add 192.168.2.0/24 via <IP of Win02 host>
6.1.2、配置Win01主機
docker network create -d transparent --gateway192.168.1.1 --subnet 192.168.1.0/24 <network name>
# A bridge is created with Adapter name "vEthernet(HNSTransparent)". Set its IP address to transparent network gateway
netsh interface ipv4 set address "vEthernet(HNSTransparent)" addr=192.168.1.1
route add 192.168.0.0 mask 255.255.255.0 192.168.0.1 if<Interface Id of the Routable Ethernet Adapter> -p
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主機
docker network create -d transparent --gateway192.168.2.1 --subnet 192.168.2.0/24 <network name>
# A bridge is created with Adapter name "vEthernet(HNSTransparent)". Set its IP address to transparent network gateway
netsh interface ipv4 set address "vEthernet(HNSTransparent)" addr=192.168.2.1
route add 192.168.0.0 mask 255.255.255.0 192.168.0.1 if<Interface Id of the Routable Ethernet Adapter> -p
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容器。
{
"apiVersion":"v1",
"kind":"Pod",
"metadata":{
"name":"iis",
"labels":{
"name":"iis"
}
},
"spec":{
"containers":[
{
"name":"iis",
"image":"microsoft/iis",
"ports":[
{
"containerPort":80
}
]
}
],
"nodeSelector":{
"beta.kubernetes.io/os": "windows"
}
}
}
七、已知的限制
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目錄下面建立一個文字檔案
echo "Symlink Test" > test.txt
b、建立一個檔案符號連結指向這個文字檔案
cmd /c mklink symtmp.txt test.txt
c、將目錄temp/work掛載到Windows容器中
docker run --rm -v c:\wd\test:c:\wd\test -itmicrosoft/windowsservercore cmd
開啟PowerShell視窗,在容器內部執行如下命令:
C:\> type C:\wd\test\symtmp.txt
實際輸出結果如下:
type : Could not find a part of the path'C:\wd\test\symtmp.txt'.
At line:1 char:1
+ type C:\wd\test\symtmp.txt
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+CategoryInfo : ObjectNotFound:(C:\wd\test\symtmp.txt:String) [Get-Content], DirectoryNotFoundException
+ FullyQualifiedErrorId :GetContentReaderDirectoryNotFoundError,Microsoft.PowerShell.Commands.GetContentCommand
如果執行正常的話,輸出結果應該如下:
C:\> type C:\wd\test\symtmp.txt
Symlink Test
3、在Windows節點上還不支援ConfigMap這種物件型別。 4、在Windows節點上執行kube-proxy命令時,實際上是通過netsh命令中的portproxy引數來實現的,當前只支援tcp協議,所以目前配置DNS時只能通過TCP協議來配置。