Kubernetes組件
Kubernetes Master:kube-apiserver、kube-controller-manager、kube-scheduler
Kubernetes Node:kube-proxy、kubelet
kube-apiserver: API-server 負載輸出RESTful風格的Kubernetes API, 它是集群的所有REST操作命令的
接入點,並負責接收、校驗並響應所有REST請求,結果狀態被持久存儲於etcd中。
因此API server 是整個集群網關
kube-scheduler: 負責調度
kube-controller-manager: 負責容器編排,集群內部的管理控制中心,負責集群內的Node、Pod副本、服務端點
(Endpoint)、命名空間(Namespace)、服務賬號(ServiceAccount)、資源定額(ResourceQuota)的管理。
kubelet:kubelet 是運行在node 上的守護進程,它從API server接收關於pod對象的配置信息並確保它們的
處於期望狀態(desired state目標狀態)。kubelet會在API server上注冊當前節點,定期向Master匯報節點
資源使用情況,並通過cAdvisor監控容器和節點資源占用情況
kube-proxy:一個網絡代理,每個node上都運行一個kube-proxy守護進程,它能夠按需為server資源對象生成
iptables或ipvs規則,從而捕獲訪問當前server和GlusterIP 的流量並將其轉發至后端正真pod對象
CNI (Container Network Interface):eg:flannel、calico
CRI (Container Runtime Interface):eg:docker
CSI (Container Storage Interface):eg:PV
OCI(Open Container Initiative, 開放容器標准):eg:runC
pod:解析
1.Pod是K8s進行創建、調度和管理的最小單位
2.Pod運行於Node節點上, 若干相關容器的組合
3.Pod內包含的容器運行在同一宿主機上,使用相同的網絡命名空間、IP地址和端口,能夠通過localhost進行通信
4.Pod可以指定一組共享存儲。Volumes Pod中的所有容器都可以訪問共享卷,從而使這些容器可以共享數據
5.Pod 就是 k8s 世界里的"應用",而一個應用可以由多個容器組成。
ps:Pod本身無法自我修復,K8s中使用kube-controller-manager管理Pod
pause容器:
1)每個Pod中都有一個pause容器,pause容器做為Pod的網絡接入點
2)屬於同一個Pod的所有容器共享網絡的namespace
3)一個Pod里的容器與另外主機上的Pod容器能夠直接通信(lo)
4)屬於同一個Pod的所有容器共享Volume掛載卷
一、K8s網絡設計
1.每個Pod都擁有一個獨立IP地址,Pod內所有容器共享一個網絡命名空間
2.集群內所有Pod都在一個直接連通的扁平網絡中,可通過IP直接訪問
(1) 所有容器之間無需NAT就可以直接互相訪問
(2) 所有Node和所有容器之間無需NAT就可以直接互相訪問
(3) 容器自己看到的IP跟其他容器看到的一樣
二、K8s網絡要求
K8s對網絡的要求總的來講主要有兩個最基本的要求,分別是:
1)要能夠為每一個Node上的Pod分配互相不沖突的IP地址
2)要所有Pod之間能夠互相訪問
三、K8s網絡規范
CNI是由CoreOS提出的一個容器網絡規范。已采納規范的包括Apache Mesos, Cloud Foundry, Kubernetes, Kurma 和 rkt。
另外 Contiv Networking, Project Calico 和 Weave這些項目也為CNI提供插件。
四、K8s網絡實現
隧道方案
隧道方案在IaaS層的網絡中應用也比較多,將pod分布在一個大二層的網絡規模下。網絡拓撲簡單,但隨着節點規模的增長復雜度會提升。
Weave:UDP廣播,本機建立新的BR,通過PCAP互通
Open vSwitch(OVS):基於VxLan和GRE協議,但是性能方面損失比較嚴重
Flannel:UDP廣播,VxLan
Racher:IPsec
路由方案
路由方案一般是從3層或者2層實現隔離和跨主機容器互通的,出了問題也很容易排查。
Calico:基於BGP協議的路由方案,支持很細致的ACL控制,對混合雲親和度比較高。
Macvlan:從邏輯和Kernel層來看隔離性和性能最優的方案,基於二層隔離,所以需要二層路由器支持,大多數雲服務商不支持,所以混合雲上比較難以實現。
五、K8s Pod的網絡創建流程
1.每個Pod除了創建時指定的容器外,都有一個kubelet啟動時指定的基礎容器
2.kubelet創建基礎容器,生成network namespace
3.kubelet調用網絡CNI driver,由它根據配置調用具體的CNI 插件(eg:calico,flannel)
4.CNI 插件給基礎容器配置網絡
5.Pod 中其他的容器共享使用基礎容器的網絡
k8s網絡
三種 IP 定義
1.Node IP:Node 節點的 IP 地址,即物理機(虛擬機)的 IP 地址。
2.Pod IP:Pod 的 IP 地址,即 docker 容器的 IP 地址,此為虛擬 IP 地址。
3.Cluster IP:Service 的 IP 地址,此為虛擬 IP 地址。
三種 IP 的理解
Node IP:是物理機的IP(或虛擬機IP)。每個Service都會在Node節點上開通一個端口,外部可以通過http://NodeIP:NodePort
即可訪問 Service 里的 Pod 提供的服務。
Pod IP:是每個Pod的IP地址,Docker Engine根據 docker 網橋的 IP 地址段進行分配的,通常是一個虛擬的二層網絡。
同Service下的pod可以直接根據PodIP相互通信
不同Service下的pod在集群間pod通信要借助於 cluster ip
pod和集群外通信,要借助於node ip
Cluster IP: 是Service的IP地址,此為虛擬 IP 地址,外部網絡無法 ping 通,只有k8s集群內部訪問使用。
Cluster IP僅僅作用於K8s Service這個對象,並由K8es管理和分配P地址 Cluster
IP無法被ping,他沒有一個“實體網絡對象”來響應 Cluster IP只能結合Service
Port組成一個具體的通信端口,單獨的Cluster IP不具備通信的基礎,並且他們屬於K8s集群這樣一個封閉的空間。
在不同Service下的pod節點在集群間相互訪問可以通過Cluster IP
K8s的網絡中pod的通信:
1. 同一Pod內的容器間通信:
因為pause容器提供pod內網絡共享,所以容器直接可以使用localhost(lo)訪問其他容器
2. 各Pod彼此之間的通信(兩個pod在一台主機上面, 兩個pod分布在不同主機之上)
1)兩個pod在一台主機上面: 通過docker默認的docker網橋互連容器(docker0), ifconfig 查了docker0
2)兩個pod分布在不同主機之上: 通過CNI插件實現,eg: flannel、calico
3. Pod與Service間的通信
Service分配的ip叫cluster ip是一個虛擬ip(相對固定,除非刪除service),這個ip只能在k8s集群內部使用,
如果service需要對外提供,只能使用Nodeport方式映射到主機上,使用主機的ip和端口對外提供服務。
節點上面有個kube-proxy進程,這個進程從master apiserver獲取信息,感知service和endpoint的創建,然后做兩個事:
1.為每個service 在集群中每個節點上面創建一個隨機端口,任何該端口上面的連接會代理到相應的pod
2.集群中每個節點安裝iptables/ipvs規則,用於clusterip + port路由到上一步定義的隨機端口上面,所以集群中每個node上面都有service的轉發規則:iptables -L -n -t filter
Pod Network
K8s的一個Pod中包含有多個容器,這些容器共享一個Network Namespace,即是共享一個Network Namespace中的一個IP。創建Pod時,首先會生成一個pause容器,然后其他容器會共享pause容器的網絡。
docker ps -a 可查看到/pause容器,和kubectl get pod -o wied 查到的容器名字是一樣的
pause的ip又是從哪里分配到的?如果還是用一個以docker0為網關的內網ip就會出現問題了。
docker默認的網絡是為同一台宿主機的docker容器通信設計的,K8s的Pod需要跨主機與其他Pod通信,
所以需要設計一套讓不同Node的Pod實現透明通信(without NAT)的機制。
docker0的默認ip是172.17.0.1,docker啟動的容器也默認被分配在172.17.0.1/16的網段里。跨主機的Pod
通信要保證Pod的ip不能相同,所以還需要設計一套為Pod統一分配IP的機制。
以上兩點,就是K8s在Pod network這一層需要解決的問題,可以利用插件解決如:flannel或者calico