Calico 是一種容器之間互通的網絡方案。在虛擬化平台中,比如 OpenStack、Docker 等都需要實現 workloads 之間互連,但同時也需要對容器做隔離控制,就像在 Internet 中的服務僅開放80端口、公有雲的多租戶一樣,提供隔離和管控機制。
而在多數的虛擬化平台實現中,通常都使用二層隔離技術來實現容器的網絡,這些二層的技術有一些弊端,比如需要依賴 VLAN、bridge 和隧道等技術,
其中 bridge 帶來了復雜性,vlan 隔離和 tunnel 隧道則消耗更多的資源並對物理環境有要求,隨着網絡規模的增大,整體會變得越加復雜。
我們嘗試把 Host 當作 Internet 中的路由器,同樣使用 BGP 同步路由,並使用 iptables 來做安全訪問策略,最終設計出了 Calico 方案。
適用場景:k8s環境中的pod之間需要隔離
設計思想:Calico 不使用隧道或 NAT 來實現轉發,而是巧妙的把所有二三層流量轉換成三層流量,並通過 host 上路由配置完成跨 Host 轉發。
設計優勢:
1.更優的資源利用
二層網絡通訊需要依賴廣播消息機制,廣播消息的開銷與 host 的數量呈指數級增長,Calico 使用的三層路由方法,則完全抑制了二層廣播,減少了資源開銷。
另外,二層網絡使用 VLAN 隔離技術,天生有 4096 個規格限制,即便可以使用 vxlan 解決,但 vxlan 又帶來了隧道開銷的新問題。而 Calico 不使用 vlan 或 vxlan 技術,使資源利用率更高。
2.可擴展性
Calico 使用與 Internet 類似的方案,Internet 的網絡比任何數據中心都大,Calico 同樣天然具有可擴展性。
3.簡單而更容易 debug
因為沒有隧道,意味着 workloads 之間路徑更短更簡單,配置更少,在 host 上更容易進行 debug 調試。
4.更少的依賴
Calico 僅依賴三層路由可達。
5.可適配性
Calico 較少的依賴性使它能適配所有 VM、Container、白盒或者混合環境場景。
Calico 是一個三層的數據中心網絡方案,而且方便集成 OpenStack 這種 IaaS 雲架構,能夠提供高效可控的 VM、容器、裸機之間的通信。
Calico不使用重疊網絡比如flannel和libnetwork重疊網絡驅動,它是一個純三層的方法,使用虛擬路由代替虛擬交換,每一台虛擬路由通過BGP協議傳播可達信息(路由)到剩余數據中心;Calico在每一個計算節點利用Linux Kernel實現了一個高效的vRouter來負責數據轉發,
而每個vRouter通過BGP協議負責把自己上運行的workload的路由信息像整個Calico網絡內傳播——小規模部署可以直接互聯,大規模下可通過指定的BGP route reflector來完成。
缺陷:
從上面的通信過程來看,跨主機通信時,整個通信路徑完全沒有使用NAT或者UDP封裝,性能上的損耗確實比較低。但正式由於calico的通信機制是完全基於三層的,這種機制也帶來了一些缺陷,例如:
- calico目前只支持TCP、UDP、ICMP、ICMPv6協議,如果使用其他四層協議(例如NetBIOS協議),建議使用weave、原生overlay等其他overlay網絡實現。
- 基於三層實現通信,在二層上沒有任何加密包裝,因此只能在私有的可靠網絡上使用。
- 流量隔離基於iptables實現,並且從etcd中獲取需要生成的隔離規則,有一些性能上的隱患
結合上面這張圖,我們來過一遍 Calico 的核心組件:
Felix:主要的Calico代理agent Calico agent,跑在每台需要運行 workload 的節點上,主要負責配置路由及 ACLs 等信息來確保 endpoint 的連通狀態;
Felix是一個守護程序,它在每個提供endpoints資源的計算機上運行。在大多數情況下,這意味着它需要在托管容器或VM的宿主機節點上運行。 Felix 負責編制路由和ACL規則以及在該主機上所需的任何其他內容,以便為該主機上的endpoints資源正常運行提供所需的網絡連接。
根據特定的編排環境,Felix負責以下任務:
管理網絡接口,Felix將有關接口的一些信息編程到內核中,以使內核能夠正確處理該endpoint發出的流量。 特別是,它將確保主機正確響應來自每個工作負載的ARP請求,並將為其管理的接口啟用IP轉發支持。它還監視網絡接口的出現和消失,以便確保針對這些接口的編程得到了正確的應用。
編寫路由,Felix負責將到其主機上endpoints的路由編寫到Linux內核FIB(轉發信息庫)中。 這可以確保那些發往目標主機的endpoints的數據包被正確地轉發。
編寫ACLs,Felix還負責將ACLs編程到Linux內核中。 這些ACLs用於確保只能在endpoints之間發送有效的網絡流量,並確保endpoints無法繞過Calico的安全措施。
報告狀態,Felix負責提供有關網絡健康狀況的數據。 特別是,它將報告配置其主機時發生的錯誤和問題。 該數據會被寫入etcd,以使其對網絡中的其他組件和操作才可見。
Orchestrator Plugin
每個主要的雲編排平台都有單獨的Calico網絡插件(例如OpenStack,Kubernetes)。 這些插件的目的是將Calico更緊密地綁定到編排工具中,允許用戶管理Calico網絡,就像他們管理編排工具中內置的網絡工具一樣。
一個好的Orchestrator插件示例是Calico Neutron ML2 驅動程序。 該插件與Neutron的ML2插件集成,允許用戶通過Neutron API調用來配置Calico網絡,實現了與Neutron的無縫集成。
Orchestrator插件負責以下任務:
API Translation,每個雲編排工具都不可避免地擁有自己的一套用於管理網絡的API接口規范, Orchestrator插件的主要工作就是將這些API轉換為Calico的數據模型,然后將其存儲在Calico的數據存儲區中。這種轉換中的一些工作將非常簡單,其他一部分可能更復雜,以便將單個復雜操作(例如,實時遷移)轉換為Calico網絡期望的一系列更簡單的操作。
Feedback,如有需要,orchestrator插件將從Calico網絡向編排器提供管理命令的反饋信息。 包括提供有關Felix存活的信息,以及如果網絡配置失敗則將某些endpoints標記為失敗。
ETCD: 分布式鍵值存儲,主要負責網絡元數據一致性,確保 Calico 網絡狀態的准確性
etcd是一個分布式鍵值存儲數據庫,專注於實現數據存儲一致性。 Calico使用etcd提供組件之間的數據通信,並作為可以保證一致性的數據存儲,以確保Calico始終可以構建出一個准確的網絡。
根據orchestrator插件的不同,etcd既可以是作為主數據存儲使用,也可以是一個單獨數據存儲的輕量級鏡像。例如,在OpenStack部署中,OpenStack數據庫被認為是“真實配置信息的來源”,而etcd用於鏡像其中有關網絡配置的信息,並用於服務其他Calico組件。
etcd組件穿插在整個部署中。它可以被分為兩組主機節點:核心集群和代理。
對於小型部署,核心集群可以是一個節點的etcd集群(通常與orchestrator插件組件位於同一節點上)。這種部署模型很簡單但沒有為etcd提供冗余。在etcd失敗的情況下,orchstrator插件必須重建數據庫,例如OpenStack,它需要插件從OpenStack數據庫重新同步狀態到etcd。
在較大的部署中,核心群集可以根據etcd管理指南進行擴展。
此外,在運行Felix或orchstrator插件的每台計算機上,會運行一個etcd代理服務。這減少了etcd核心集群上的負載,並為主機節點屏蔽了etcd服務集群的細節。在etcd集群與orchstrator插件在同一台機器上都有成員的情況下,可以放棄在該機器上使用etcd代理。
etcd負責執行以下任務:
Data Storage,etcd以分布式、一致和容錯的方式存儲Calico網絡的數據(對於至少三個etcd節點的cluster大小)。 這確保Calico網絡始終處於已知良好狀態,同時允許運行etcd的個別機器節點失敗或無法訪問。Calico網絡數據的這種分布式存儲提高了Calico組件從數據庫讀取的能力。
Communication,etcd也用作組件之間的通信服務。 我們通過讓非etcd組件監視鍵值空間中的某些點來確保他們看到已經做出的任何更改,從而允許他們及時響應這些更改。 該功能允許將狀態信息提交到數據庫,然后觸發基於該狀態數據的進一步網絡配置管理。
BIRD是什么
BIRD是布拉格查理大學數學與物理學院的一個學校項目,項目名是BIRD Internet Routing Daemon的縮寫。 目前,它由CZ.NIC實驗室開發和支持。
BIRD項目旨在開發一個功能齊全的動態IP路由守護進程,主要針對(但不限於)Linux,FreeBSD和其他類UNIX系統,並在GNU通用公共許可證下分發。詳細信息參照官網https://bird.network.cz/。
作為一個開源的網絡路由守護進程項目,BRID設計並支持了以下功能:
both IPv4 and IPv6 protocols
multiple routing tables
the Border Gateway Protocol (BGPv4)
the Routing Information Protocol (RIPv2, RIPng)
the Open Shortest Path First protocol (OSPFv2, OSPFv3)
the Babel Routing Protocol
the Router Advertisements for IPv6 hosts
a virtual protocol for exchange of routes between different routing tables on a single host
a command-line interface allowing on-line control and inspection of status of the daemon
soft reconfiguration (no need to use complex online commands to change the configuration, just edit the configuration file and notify BIRD to re-read it and it will smoothly switch itself to the new configuration, not disturbing routing protocols unless they are affected by the configuration changes)
a powerful language for route filtering
BGP Client (BIRD): 主要負責把 Felix 寫入 kernel 的路由信息分發到當前 Calico 網絡,確保 workload 間的通信的有效性;
Calico在每個運行Felix服務的節點上都部署一個BGP客戶端。 BGP客戶端的作用是讀取Felix程序編寫到內核中並在數據中心內分發的路由信息。
BGP客戶端負責執行以下任務:
路由信息分發,當Felix將路由插入Linux內核FIB時,BGP客戶端將接收它們並將它們分發到集群中的其他工作節點。
BGP Route Reflector (BIRD) : 大規模部署時使用,摒棄所有節點互聯的 mesh 模式,通過一個或者多個BGP Route Reflector來完成集中式的路由分發
對於較大規模的部署,簡單的BGP可能成為限制因素,因為它要求每個BGP客戶端連接到網狀拓撲中的每一個其他BGP客戶端。這需要越來越多的連接,迅速變得難以維護,甚至會讓一些設備的路由表撐滿。
因此,在較大規模的部署中,Calico建議部署BGP Route Reflector。通常是在Internet中使用這樣的組件充當BGP客戶端連接的中心點,從而防止它們需要與群集中的每個BGP客戶端進行通信。為了實現冗余,也可以同時部署多個BGP Route Reflector服務。Route Reflector僅僅是協助管理BGP網絡,並沒有endpoint數據會通過它們。
在Calico中,此BGP組件也是使用的最常見的BIRD,配置為Route Reflector運行,而不是標准BGP客戶端。
BGP Route Reflector負責以下任務:
集中式的路由信息分發,當Calico BGP客戶端將路由從其FIB通告到Route Reflector時,Route Reflector會將這些路由通告給部署集群中的其他節點。
總結:
利用了Linux內核原生的路由和iptables防火牆功能。 進出各個容器、虛擬機和物理主機的所有流量都會在路由到目標之前遍歷這些內核規則。
- Felix:主要的Calico代理agent,運行每台計算機上管理endpoints資源。
- calicoctl:允許從命令行界面配置實現高級策略和網絡。
- orchestrator plugins:提供與各種流行的雲計算編排工具的緊密集成和同步支持。
- key/value store:存儲Calico的策略配置和網絡狀態信息,目前主要使用etcdv3或k8s api。
- calico/node:在每個主機上運行,從key/value存儲中讀取相關的策略和網絡配置信息,並在Linux內核中實現它。
- Dikastes/Envoy:可選的Kubernetes sidecars,可以通過相互TLS身份驗證保護工作負載到工作負載的通信,並增加應用層控制策略。
通過將整個互聯網的可擴展 IP 網絡原則壓縮到數據中心級別,Calico 在每一個計算節點利用Linux kernel實現了一個高效的vRouter來負責數據轉發而每個vRouter通過BGP
協議負責把自己上運行的 workload 的路由信息像整個 Calico 網絡內傳播 - 小規模部署可以直接互聯,大規模下可通過指定的BGP route reflector 來完成。這樣保證最終所有的 workload 之間的數據流量都是通過 IP 包的方式完成互聯的
Calico原理
Calico把每個操作系統的協議棧認為是一個路由器,然后把所有的容器認為是連在這個路由器上的網絡終端,在路由器之間跑標准的路由協議——BGP的協議,然后讓它們自己去學習這個網絡拓撲該如何轉發。
所以Calico方案其實是一個純三層的方案,也就是說讓每台機器的協議棧的三層去確保兩個容器,跨主機容器之間的三層連通性。
對於控制平面,它每個節點上會運行兩個主要的程序,一個是Felix,它會監聽ECTD中心的存儲,從它獲取事件,比如說用戶在這台機器上加了一個IP,或者是分配了一個容器等。接着會在這台機器上創建出一個容器,並將其網卡、IP、MAC都設置好,然后在內核的路由表里面寫一條,注明這個IP應該到這張網卡。
綠色部分是一個標准的路由程序,
它會從內核里面獲取哪一些IP的路由發生了變化,然后通過標准BGP的路由協議擴散到整個其他的宿主機上,讓外界都知道這個IP在這里,你們路由的時候得到這里來。
由於Calico是一種純三層的實現,因此可以避免與二層方案相關的數據包封裝的操作,中間沒有任何的NAT,沒有任何的overlay,所以它的轉發效率可能是所有方案中最高的,因為它的包直接走原生TCP/IP的協議棧,它的隔離也因為這個棧而變得好做
因為TCP/IP的協議棧提供了一整套的防火牆的規則,所以它可以通過IPTABLES的規則達到比較復雜的隔離邏輯。
Calico 節點組網可以直接利用數據中心的網絡結構(支持 L2 或者 L3),不需要額外的 NAT,隧道或者 VXLAN overlay network。
如上圖所示,這樣保證這個方案的簡單可控,而且沒有封包解包,節約 CPU 計算資源的同時,提高了整個網絡的性能。
此外,Calico 基於 iptables 還提供了豐富而靈活的網絡 policy, 保證通過各個節點上的 ACLs 來提供 workload 的多租戶隔離、安全組以及其他可達性限制等功能。
在主機網絡拓撲的組織上,calico的理念與weave類似,都是在主機上啟動虛擬機路由器,將每個主機作為路由器使用,組成互聯互通的網絡拓撲。當安裝了calico的主機組成集群后
其拓撲如下圖所示
每個主機上都部署了calico/node作為虛擬路由器,並且可以通過calico將宿主機組織成任意的拓撲集群。當集群中的容器需要與外界通信時,就可以通過BGP協議將網關物理路由器加入到集群中,使外界可以直接訪問容器IP,而不需要做任何NAT之類的復雜操作。
當容器通過calico進行跨主機通信時,其網絡通信模型如下圖所示:
從上圖可以看出,當容器創建時,calico為容器生成veth pair,一端作為容器網卡加入到容器的網絡命名空間,並設置IP和掩碼,一端直接暴露在宿主機上,並通過設置路由規則,將容器IP暴露到宿主機的通信路由上。
於此同時,calico為每個主機分配了一段子網作為容器可分配的IP范圍,這樣就可以根據子網的CIDR為每個主機生成比較固定的路由規則。
當容器需要跨主機通信時,主要經過下面的簡單步驟:
- 容器流量通過veth pair到達宿主機的網絡命名空間上。
- 根據容器要訪問的IP所在的子網CIDR和主機上的路由規則,找到下一跳要到達的宿主機IP。
- 流量到達下一跳的宿主機后,根據當前宿主機上的路由規則,直接到達對端容器的veth pair插在宿主機的一端,最終進入容器。
Calico網絡方式(兩種)
路由表中Flags標志的含義:
U up表示當前為啟動狀態
H host表示該路由為一個主機,多為達到數據包的路由
G Gateway 表示該路由是一個網關,如果沒有說明目的地是直連的
D Dynamicaly 表示該路由是重定向報文修改
M 表示該路由已被重定向報文修改
1)IPIP
從字面來理解,就是把一個IP數據包又套在一個IP包里,即把 IP 層封裝到 IP 層的一個 tunnel,看起來似乎是浪費,實則不然。它的作用其實基本上就相當於一個基於IP層的網橋!一般來說,普通的網橋是基於mac層的,根本不需 IP,而這個 ipip 則是通過兩端的路由做一個 tunnel,把兩個本來不通的網絡通過點對點連接起來。ipip 的源代碼在內核 net/ipv4/ipip.c 中可以找到。
- IPIP是一種將各Node的路由之間做一個tunnel,再把兩個網絡連接起來的模式。啟用IPIP模式時,Calico將在各Node上創建一個名為”tunl0″的虛擬網絡接口。如下圖所示。
使用IPIP模式后的路由如下:
2)BGP
邊界網關協議(Border Gateway Protocol, BGP)是互聯網上一個核心的去中心化自治路由協議。它通過維護IP路由表或‘前綴’表來實現自治系統(AS)之間的可達性,屬於矢量路由協議。BGP不使用傳統的內部網關協議(IGP)的指標,而使用基於路徑、網絡策略或規則集來決定路由。因此,它更適合被稱為矢量性協議,而不是路由協議。BGP,通俗的講就是講接入到機房的多條線路(如電信、聯通、移動等)融合為一體,實現多線單IP,BGP 機房的優點:服務器只需要設置一個IP地址,最佳訪問路由是由網絡上的骨干路由器根據路由跳數與其它技術指標來確定的,不會占用服務器的任何系統。
前面介紹過IPIP網絡pod之間的流量發送tunl0,然后tunl0發送對端設備。BGP網絡中,pod之間的流量直接從網卡發送目的地,減少了tunl0這個環節。
IPIP網絡:
流量:tunlo設備封裝數據,形成隧道,承載流量。
適用網絡類型:適用於互相訪問的pod不在同一個網段中,跨網段訪問的場景。外層封裝的ip能夠解決跨網段的路由問題。
效率:流量需要tunl0設備封裝,效率略低
BGP網絡:
流量:使用路由信息導向流量
適用網絡類型:適用於互相訪問的pod在同一個網段,適用於大型網絡。
效率:原生hostGW,效率高
部署calico提供網絡策略功能
官方提供的安裝方式
https://docs.projectcalico.org/getting-started/kubernetes/installation/config-options
這兩說一下ETCD 的安裝流程,不推薦這種方式
規模小於50 的節點可以考慮
etcd 適合混合部署的環境
大概安裝流程:
curl https://docs.projectcalico.org/manifests/calico-etcd.yaml -O
修改kubelet配置:
設置各node上Kubelet服務的啟動參數: --network-plugin=cni, 可能還要加上這兩個參數:
--cni-conf-dir CNI插件的配置文件目錄,默認為/etc/cni/net.d 該目錄下的配置文件內容需要符合CNI規范
--cni-bin-dir: CNI插件的可執行文件目錄,默認為/opt/cni/bin
設置好后,重新啟動kubelet。
這樣通過calico就完成了Node間容器網絡的設置 ,在后續的pod創建過程中,Kubelet將通過CNI接口調用 calico進行Pod的網絡設置包括IP地址,路由規則,Iptables規則
Secret 配置修改
data:
etcd-key: (cat /opt/kubernetes/ssl/server-key.pem | base64 -w 0) # 將輸出結果填寫在這里
etcd-cert: (cat /opt/kubernetes/ssl/server.pem | base64 -w 0) # 將輸出結果填寫在這里
etcd-ca: (cat /opt/kubernetes/ssl/ca.pem | base64 -w 0) # 將輸出結果填寫在這里
ConfigMap 配置修改
data:
etcd_endpoints: "https://192.168.0.216:2379"
etcd_ca: "/calico-secrets/etcd-ca"
etcd_cert: "/calico-secrets/etcd-cert"
etcd_key: "/calico-secrets/etcd-key"
關於ConfigMap部分主要參數如下:
etcd_endpoints:Calico使用etcd來保存網絡拓撲和狀態,該參數指定etcd的地址,可以使用K8S Master所用的etcd,也可以另外搭建。
calico_backend:Calico的后端,默認為bird。
cni_network_config:符合CNI規范的網絡配置,其中type=calico表示,Kubelet 從 CNI_PATH (默認為/opt/cni/bin)目錄找calico的可執行文件,用於容器IP地址的分配。
etcd 如果配置TLS安全認證,則還需要指定相應的ca、cert、key等文件
修改 Pods 使用的 IP 網段,默認使用 192.168.0.0/16 網段
Calico 模式設置
Calico 有兩種網絡模式:BGP
和 IPIP
- 使用
IPIP
模式時,設置CALICO_IPV4POOL_IPIP="always"
- 使用
BGP
模式時,設置CALICO_IPV4POOL_IPIP="off"
kubectl apply -f calico-etcd.yaml
二進制安裝calicoctl,部署到一台主master節點即可
官網安裝方式:
https://docs.projectcalico.org/getting-started/clis/calicoctl/install
https://github.com/projectcalico/calicoctl/releases
wget https://github.com/projectcalico/calicoctl/releases/download/v3.14.2/calicoctl-linux-amd64 -O /usr/bin/calicoctl
chmod +x /usr/bin/calicoctl
calicoctl通過讀寫calico的數據存儲系統(datastore)進行查看或者其他各類管理操作,通常,它需要提供認證信息經由相應的數據存儲完成認證。
在使用Kubernetes API數據存儲時,需要使用類似kubectl的認證信息完成認證。它可以通過環境變量聲明的DATASTORE_TYPE和KUBECONFIG接入集群,
例如以下命令格式運行calicoctl
calicoctl create:根據配置文件創建資源,配置文件可以是yaml或者json格式,資源類型node、bgpPeer、hostEndpoint、workloadEndpoint、ipPool、policy、profile。-f 指定資源文件位置,-c 默認是/etc/calico/calicoctl.cfg
calicoctl replace:根據配置文件替換一個已經存在的資源,參數和create一樣
calicoctl apply:根據配置文件創建一個資源或者替換一個已有的資源,參數和create一樣
calicoctl delete:根據資源文件刪除資源,或者根據類型、標識符刪除資源
calicoctl get:根據文件顯示設置資源,或者根據類型、標識符顯示資源。顯示格式有多種ps、wide、yaml、json....
calicoctl config:允許用戶查看或者修改Felix和BGP的低級組件配置。calicoctl config set/unset/get <NAME> <VALUE>
calicoctl ipam release:從calico ip 地址管理中釋放一個ip。這個不會刪除endpoint上的ip,只是會清除已經釋放的美歐干凈移除的ip
calicoctl ipam show:顯示已經已經分配的ip
官網配置和使用說明
https://docs.projectcalico.org/getting-started/clis/calicoctl/configure/kdd
[root@k8s-master ~]# DATASTORE_TYPE=kubernetes KUBECONFIG=~/.kube/config calicoctl get nodes
NAME
k8s-master
k8s-node1
k8s-node2
也可以直接將認證信息等保存於配置文件中,calicoctl默認加載 /etc/calico/calicoctl.cfg 配置文件讀取配置信息,如下所示:
[root@k8s-master ~]# cat /etc/calico/calicoctl.cfg
apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:
datastoreType: "kubernetes"
kubeconfig: "/root/.kube/config"
[root@k8s-master ~]# calicoctl get nodes
NAME
k8s-master
k8s-node1
k8s-node2
[root@k8s-master ~]# calicoctl node status
Calico process is running.
IPv4 BGP status
+---------------+-------------------+-------+----------+-------------+
| PEER ADDRESS | PEER TYPE | STATE | SINCE | INFO |
+---------------+-------------------+-------+----------+-------------+
| 138.138.82.15 | node-to-node mesh | up | 09:03:56 | Established |
| 138.138.82.16 | node-to-node mesh | up | 09:04:08 | Established |
+---------------+-------------------+-------+----------+-------------+
IPv6 BGP status
No IPv6 peers found.
[root@k8s-master ~]# calicoctl get ipPool -o yaml
#查看工作中的負載節點
[root@k8s-master ~]# calicoctl get workloadendpoints
如果遇到問題可以使用calicoctl命令行工具收集診斷信息。這應該以超級用戶權限運行,例如:
# calicoctl node diags
需要注意的問題:如果服務器的網卡名稱不一樣,需要固定指定的網卡,或者IP 網絡
- name: IP_AUTODETECTION_METHOD
value: "interface=eno2.*"
#value: "can-reach=192.168.1.1"
經過測試calico 會按照ifconfig 倒序的方式查找第一個可以通的網卡地址,正好和flannel相反
詳細的文檔參考
https://www.dazhuanlan.com/2019/11/28/5ddf4e436e79f/
https://zhuanlan.zhihu.com/p/81120952
本文參考文檔:
https://www.cnblogs.com/centos-python/articles/10876083.html
https://www.kubernetes.org.cn/4960.html
https://cloud.tencent.com/developer/article/1482739