Kubernetes-Host網絡模式,指定Pod 物理機IP

在實際生產環境中,有些容器內應用(比如編碼器)需要用到物理層面的網絡資源(比如組播流)。這就要求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默認網絡模式啓動。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章