目錄貼:Kubernetes學習系列
在實際生產環境中,有些容器內應用(比如編碼器)需要用到物理層面的網絡資源(比如組播流)。這就要求Kubernetes中的該Pod以HOST模式來啟動。以下實驗了Kubernetes-HOST網絡模式,並給出了一些運維建議。
1、Pod的網絡
每個Pod都會默認啟動一個pod-infrastructure(或pause)的容器,作為共享網絡的基准容器。其他業務容器在啟動之后,會將自己的網絡模式指定為“"NetworkMode": "container:pause_containerID”。這樣就能做到Pod中的所有容器網絡都是共享的,一個Pod中的所有容器中的網絡是一致的,它們能夠通過本地地址(localhost)訪問其他用戶容器的端口。在Kubernetes的網絡模型中,每一個Pod都擁有一個扁平化共享網絡命名空間的IP,稱為PodIP。通過PodIP,Pod就能夠跨網絡與其他物理機和容器進行通信。
也可以設置Pod為Host網絡模式,即直接使用宿主機的網絡,不進行網絡虛擬化隔離。這樣一來,Pod中的所有容器就直接暴露在宿主機的網絡環境中,這時候,Pod的PodIP就是其所在Node的IP。從原理上來說,當設定Pod的網絡為Host時,是設定了Pod中pod-infrastructure(或pause)容器的網絡為Host,Pod內部其他容器的網絡指向該容器。如下所示(65070affecfc61為業務容器,f60a2ee415e3為pod-infrastructure容器):
[root@k8s-node-3 ~]# docker inspect 65070affecfc6131b2385e5c40d4f21f73c343cc15e7983cdce8594e38ed020f | grep NetworkMode "NetworkMode": "container:f60a2ee415e301491f30ffc12855880273da6eded2526a5319eed72a92caef7f", [root@k8s-node-3 ~]# docker inspect f60a2ee415e301491f30ffc12855880273da6eded2526a5319eed72a92caef7f | grep NetworkMode "NetworkMode": "host", [root@k8s-node-3 ~]#
2、啟動示例
[root@k8s-master yaml]# cat test-host.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: test-host spec: replicas: 4 template: metadata: labels: name: test-host spec: containers: - name: test-host image: registry:5000/back_demon:1.0 command: - /jboss/jboss-eap-6.1/bin/standalone.sh ports: - containerPort: 8080 hostNetwork: true
3、運維經驗
3.1 副本數量
對於同Deployment下的Host模式啟動的Pod,每個node上只能啟動一個。也就是說,Host模式的Pod啟動副本數不可以多於“目標node”的數量,“目標node”指的是在啟動Pod時選定的node,若未選定(沒有指定nodeSelector),“目標node”的數量就是集群中全部的可用的node的數量。當副本數大於“目標node”的數量時,多出來的Pod會一直處於Pending狀態,因為schedule已經找不到可以調度的node了。
以下示例中,集群只有4個node,當設置副本數量為5時,最后一個Pod狀態會一直處於Pending狀態。
[root@k8s-master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE test-host-1108333573-11wbl 1/1 Running 0 17s 10.0.251.153 k8s-node-1 test-host-1108333573-2k35s 1/1 Running 0 17s 10.0.251.146 k8s-node-3 test-host-1108333573-lnlpy 1/1 Running 0 17s 10.0.251.222 k8s-node-4 test-host-1108333573-t6izr 1/1 Running 0 17s 10.0.251.155 k8s-node-2 test-host-1108333573-tf4mc 0/1 Pending 0 17s <none>
3.2 PodIP
Pod的PodIP就是其所在Node的IP,具體如下:
[root@k8s-master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE test-host-1108333573-11wbl 1/1 Running 0 2h 10.0.251.153 k8s-node-1 test-host-1108333573-2k35s 1/1 Running 0 2h 10.0.251.146 k8s-node-3 test-host-1108333573-lnlpy 1/1 Running 0 2h 10.0.251.222 k8s-node-4 test-host-1108333573-t6izr 1/1 Running 0 2h 10.0.251.155 k8s-node-2
雖然PodIP是NodeIP,但也可以通過service的方式加到Kubernetes的虛擬化網絡中被使用。具體如下:
[root@k8s-master yaml]# cat demon1/frontend-service.yaml apiVersion: v1 kind: Service metadata: name: frontend-service labels: name: frontend-service spec: type: NodePort ports: - port: 8080 nodePort: 30002 selector: name: frontend-service [root@k8s-master yaml]# kubectl create -f test-host-svc.yaml service "test-host" created [root@k8s-master yaml]# kubectl describe svc test-host Name: test-host Namespace: default Labels: name=test-host Selector: name=test-host Type: NodePort IP: 10.254.127.198 Port: <unset> 8080/TCP NodePort: <unset> 30003/TCP Endpoints: 10.0.251.146:8080,10.0.251.153:8080,10.0.251.155:8080 + 1 more... Session Affinity: None No events.
創建成功之后,集群內部的應用可通過虛擬網絡中的clusterIP:10.254.127.198:8080來訪問后端服務,集群外部的應用(如瀏覽器)可以通過nodeIP+NodePort來訪問后端服務。
3.3 端口占用
3.3.1 其他Pod端口占用
若同集群中,用host模式啟動的deployment(或RC)有多個,若這些 deployment中定義的containerPort有相同的值,那么,Kubernetes會校驗出端口資源的沖突。示例如下:
[root@k8s-master yaml]# cat test-host.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: test-host spec: replicas: 3 template: metadata: labels: name: test-host spec: containers: - name: test-host image: registry:5000/back_demon:1.0 command: - /jboss/jboss-eap-6.1/bin/standalone.sh ports: - containerPort: 8080 hostNetwork: true [root@k8s-master yaml]# cat test-host1.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: test-host1 spec: replicas: 2 template: metadata: labels: name: test-host1 spec: containers: - name: test-host1 image: registry:5000/back_demon:1.0 command: - /jboss/jboss-eap-6.1/bin/standalone.sh ports: - containerPort: 8080 hostNetwork: true [root@k8s-master yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE test-host-1108333573-9oo55 1/1 Running 0 19m 10.0.251.155 k8s-node-2 test-host-1108333573-uc2v2 1/1 Running 0 19m 10.0.251.146 k8s-node-3 test-host-1108333573-vxezq 1/1 Running 0 19m 10.0.251.153 k8s-node-1 test-host1-6476903-q8e6o 0/1 Pending 0 19m <none> test-host1-6476903-zmk5l 1/1 Running 0 19m 10.0.251.222 k8s-node-4
實驗集群下,可用的node數量只有4個,而兩個deployment——test-host、test-host1對外暴露額端口是相同的——8080。兩個deployment一共要啟動的副本數量為5,這時,最后啟動的那個Pod就會一直處於Pending狀態。
3.3.2 宿主機端口占用
當Host模式的Deployment(或RC)聲明一個端口時,比如8080,若宿主機上有非Kubernetes控制的程序占用了8080這個端口,這時Kubernetes是無法校驗到的。也就是說,schedule僅僅會記錄Kubernetes集群中的端口占用信息,並在調度時做相關的校驗工作。但schedule不會校驗宿主機上真正的端口占用信息。這其實是非常合理的,集群中的node通常成千上萬,被當做一台台單純的提供計算能力的資源,計算什么由中心節點來決定。沒有必要,也沒有場景需要在node上額外的跑其他程序。
在使用Host模式網絡時,需注意的是,每個應用(部署成一個deployment)都要有自己固定的、和其他應用不同的端口,比如編碼器永遠固定成9525、源服務器永遠固定成9537等。且宿主機在做了Kubernetes集群中的node之后,盡量不對非本集群應用提供服務。
3.4 鏡像制作要求
必須用Host模式啟動的Pod,在鏡像制作時要求端口唯一、且單一。
一般Pod中只會存在一個業務主鏡像,該業務鏡像在制作時,應該只放一種應用,這個應用只對外開放一個接口。例如,編碼器主控節點這個應用,主要有兩方面的功能:1)接收組播流,並控制處理節點,占用端口9525;2)可視化操控界面,占用端口8080。其中接收組播流這塊,需要使用Host模式的網絡。拆分建議為兩個業務鏡像,部署時部署兩個deployment。即接收組播流拆成一個鏡像,固定端口9525,使用Host模式啟動;可視化界面拆成一個鏡像,用Kubernetes默認網絡模式啟動。