關于容器方面的知識大全
容器和虛擬機的區別:
1、虛擬化級別:
容器是一種操作系統級的虛擬化,它共享主機操作系統的內核,是在用戶空間中提供隔離,每個容器都運行在一個獨立的用戶空間實例中,但與主機系統共享內核,這使得容器相對輕量,啟動速度快
虛擬機是一種硬件級的虛擬化,它在主機上運行完整的操作系統,包括獨立的內核,每個虛擬機都有自己的虛擬硬件,通過虛擬機監視程序(Hypervisor)與主機通信,虛擬機啟動較慢,因為需要加載完整的操作系統
2、資源消耗:
由于容器共享主機系統的內核,所以它們通常占用更少的資源
虛擬機需要獨立的操作系統和內核,因此通常比容器占用更多的資源
3、隔離性:
容器之間是共享主機內核的所以在安全性和隔離性上不如虛擬機
虛擬機都有獨立的內核和用戶空間,所以它的隔離性更加強大
4、啟動時間:
容器只需要啟動應用程序及其運行環境,不需要加載整個操作系統,所以啟動更快
虛擬機需要加載整個的操作系統,所以啟動時間較長
docker總結:
docker是什么
docker是一種輕量級的容器化技術,其主要原理是利用linux操作系統的cgroups、namespace和AUFS等特性來虛擬化系統資源,使得應用程序可以被封裝成一個可移植的、可靠的、可復制的容器,在不同的環境中運行且無需擔心環境差異導致的兼容性問題
解釋Cgroups和AUFS
Cgroups是linux內核的一個功能,用來限制、控制與分離一個進程組的資源(如:CPU、內存、磁盤輸入輸出等)
AUFS是用于為linux文件系統實現聯合掛載
overlayFS:
docker的核心:
1、image(鏡像):可以理解為一個靜態的只讀文件,除了提供容器運行時所需的程序,庫,資源,配置文件,還包含了一些為運行時準備的配置參數
2、containers(容器):容器是鏡像創建的應用運行實例,可以將其啟動,開始,停止,刪除,所有的容器都是相互隔離的,鏡像是只讀的,容器從鏡像啟動的時候,在鏡像的最上層創建了一個可寫層,鏡像本身保持不變
3、reposity(倉庫):類似與代碼庫,用于存儲和分發鏡像
docker的四種網絡模式:
1、bridge:默認網絡,此網絡和物理交換機類似,從docker0上分配一個IP給容器使用,并設置docker0的地址為默認網關。
2、Host:使用這個模式,容器不會獲得一個獨立的network namespace,而是和宿主機共享一個network namespace,容器不會虛擬出自己的網卡和IP,但是容器的其他方面,如文件系統,進程列表等還是和宿主機隔離的。
3、None:使用這個模式,容器沒有網卡,IP路由等信息,需要我們自己為容器添加這些信息,但是None模式有助于容器的安全
4、Container:這種模式適合其他容器共用network namespace,和指定的容器共享IP、端口范圍等,當然,除了這幾方面之外,兩個容器的文件系統,進程列表等還是相互隔離的,他們是通過容器的lo網卡(回環接口)設備通信
docker的bridge(橋接模式)的網絡實現:
同一臺服務器上的容器進行通信
在bridge模式下,Docker Deamon在啟動時會創建一個虛擬網橋docker0,會給這個網橋分配一個子網,針對docker創建的每一個容器都會創建一個虛擬的以太網設備(veth設備對),這個設備是成對出現的,其中一端連接到docker0網橋上,另一端使用linux網絡命名空間技術,映射到容器內的eth0上,然后從docker0網橋的地址段上給eth0分配一個IP地址,同時容器內也會根據IP地址生成一個MAC地址,確保不會有ARP沖突,這樣可以確保同一臺服務器上的容器間可以相互通信
不同服務器之間容器進行通信
為了跨節點互相通信,就必須在主機上分配端口,這樣可以通過端口路由到容器上
docker的存儲:
1、默認存儲:運行在容器中,隨著容器的刪除而刪除
2、bind mount:綁定掛載,使用docker run 參數進行綁定到本地的
3、volume數據卷:先創建一個數據卷,再綁到容器中
4、tmpfs mount:使用tmpfs掛載創建容器
dockerfile的指令:
FROM:非注釋行的首行,標注以哪個鏡像為基礎鏡像
LABEL:標簽
WORKDIR:工作目錄
RUN:docker build時所運行的命令,有三種格式:
1、RUN <command> 2、RUN "/bin/sh -c command" 3、RUN ["/bin/sh -c command"]
CMD:此指令和RUN大致一樣,不同之處在于CMD是當docker run時運行的命令,CMD的參數可以提供給ENTRYPOINT docker run 添加參數時會覆蓋
COPY:根據上下文,拷貝文件到鏡像中具體路徑下
ADD:根據上下文,拷貝文件到鏡像中具體的路徑,此指令和COPY大致一樣,但是ADD能根據URL地址進行添加,同時如果是壓縮文件,拷貝到鏡像中時,具有解壓功能。當是RUL下載時沒有解壓功能
EXPOSE:容器暴露的端口
VOLUME:容器的掛載的邏輯卷,docker run 可以覆蓋掉
ENV:環境變量 docker run 可以覆蓋
USER:用戶
ONBUILD:依靠上一個鏡像為基礎鏡像,運行時所走的指令
ENTRYPOINT:配置容器啟動后執行的命令,不可被docker run 提供的參數覆蓋
CMD和ENTRYPOINT的區別和聯系:
1、CMD在docker run的時候是可以被覆蓋掉的,而ENTRYPOINT則不會,只有使用--entrypoint時才會覆蓋掉ENTRYPOINT的
2、CMD也可以作為ENTRYPOINT的參數,同時在執行docker run 時添加參數也會能覆蓋掉CMD的
RUN和CMD的區別:
RUN和CMD都是用于執行命令,區別在與這兩個指令的運行時機不同,RUN是在docker build是運行的,CMD是在docker run時運行的,同時CMD在docker run時是可以被覆蓋的
docker的兩種登錄方式:
docker exec 此命令有兩個重要的參數-i和-t,不會像attach退出時會導致容器停止,和正常console窗口操作一樣
docker attach 退出容器時,會導致容器停止,同時登錄到同一個容器上,如果一個窗口出現阻塞,其它窗口也會出現阻塞
dockerfile構建多鏡像
要在單個dockerfile中構建多個鏡像,可以使用dockerfile的多階段構建特性,多階段構建允許在同一個Dockerfile中定義多個構建階段,每個階段生成一個鏡像,然后可以選擇性的從一個階段復制文件到下一個階段
階段1、使用FROM指令聲明一個基礎鏡像,并使用AS定義一個階段名稱,在這個階段中你可以執行一些編譯和構建操作
如果有多個階段,除最終階段之外,基本上何階段1的操作一樣
最終階段,在這個階段中,可以從之前的構建階段中復制生成的結構到該階段指令為COPY --from=“之前階段的名稱”,最終鏡像通常只包含應用程序的可以執行文件和運行環境
k8s的總結:
k8s的安裝方式:使用的是kubeadm
什么是k8s
k8s是一個可移植,可擴展的用于管理容器化的工作負載和服務,可促進聲明式配置和自動化,且擁有龐大且快速的生態系統
k8s集群有什么優點
k8s集群的注意事項:
每個node節點的pod數量不超過110,可以使用--max-pods設置pod的最大數量
node節點數不超過5千
pod總數不超過15萬
容器總數不超過30萬
k8s集群的優化:
etcd優化:
快照調優:
使用 V2 后端創建快照可能會很昂貴,因此只有在對 etcd 進行給定數量的更改后才會創建快照。默認情況下,每 10,000 次更改后將創建快照。如果etcd的內存使用率和磁盤使用率過高,請嘗試通過在命令行中設置以下內容來降低快照閾值:
etcd --snapshot-count=5000
ETCD_SNAPSHOT_COUNT=5000 etcd
以上兩種方式都可以
心跳間隔和選舉超時時間調優:
heartbeat-interval:心跳間隔時間
election-timeout:選舉超時時間
etcd --heartbeat-interval=100 --election-timeout=500
ETCD_HEARTBEAT_INTERVAL=100 ETCD_ELECTION_TIMEOUT=500 etcd
以上兩種方法都可以修改
磁盤IO調優:
一個ETCD群集對磁盤潛伏期非常敏感。由于ETCD必須堅持其日志提案,因此來自其他過程的磁盤活動可能會導致較長的FSONC潛伏期。結果是,等等可能會錯過心跳,導致要求超時和臨時領導者損失。當給出高磁盤優先級時,ETCD服務器有時可以穩定地與這些過程一起運行。
提高存儲限制,默認是2G
kube-apiserver的優化參數:
--enable-priority-and-fairness :如果為 true,則使用增強的處理程序替換 max-in-flight 處理程序, 以便根據優先級和公平性完成排隊和調度。
--max-mutating-requests-inflight :默認值為200,如果 --enable-priority-and-fairness 為 true,那么此值和 --max-requests-inflight 的和將確定服務器的總并發限制(必須是正數)。 否則,該值限制同時運行的變更類型的請求的個數上限。0 表示無限制。
--max-requests-inflight:默認值為400,如果 --enable-priority-and-fairness 為 true,那么此值和 --max-mutating-requests-inflight 的和將確定服務器的總并發限制(必須是正數)。 否則,該值限制進行中非變更類型請求的最大個數,0表示無限制。
kube-controller-manager的優化參數:
--kube-api-qps:默認值是20,與API服務通信時每秒請求數(QPS)的限制
--kube-api-burst:默認值30,與 Kubernetes API 服務器通信時突發峰值請求個數上限
調整controller-manager同步資源的周期,避免過多的資源同步導致集群資源的消耗,所有帶--concurrent前綴的參數
kube-scheduler參數:
--kube-api-qps:默認值50,與 kubernetes apiserver 通信時要使用的 QPS 如果 --config 指定了一個配置文件,那么這個參數將被忽略
根據現有的調度策略進行調度
1、對apiserver進行高可用搭建,結合keepalived和haproxy
2、對資源管理和調度策略進行優化,設置合理的資源限制和資源請求,結合調度策略:如node親和性,pod親和性、污點和容忍度等,對資源進行調度
3、網絡優化,使用合適的網絡插件,啟用IPVS來代替iptables來提高大規模集群下的網絡性能
4、設置合理的更新策略,實現平滑升級盡量不影響業務的正常運行
5、持久化存儲,根據不同的業務使用不同持久化存儲方案
6、使用網絡安全策略,提高集群內部的安全隔離性
7、一些監控設置,自動擴容機制的設置,健康檢查的設置等一些舉措,來提高集群的穩定性
k8s集群的架構:
一個k8s集群至少包含一個控制平面(control plane),以及一個或多個工作節點(work node),控制平面(control plane)負責管理工作節點和維護集群狀態,所有任務的分配都來自于控制平面,工作節點(work node)負責執行由控制平面分配的請求任務,運行實際的應用和負載,控制平面(control plane)又包含了apiserver、scheduler、controller manager和etcd四個核心組件,而controller manager 又包含了節點控制器,任務控制器,端點分片控制器和服務賬號控制器等,工作節點(node work)節點上運行著kubelet、kube-proxy和container runtime三個核心組件
k8s的核心組件:
- Etcd:存儲了整個集群的數據和信息狀態
- kube-apiServer:操作集群的唯一入口,并提供認證、授權、訪問控制、API注冊和發現等機制,集群的各組件間都是通過api server進行通信的
- kube-scheduler:資源調度,按照預定的調度策略進行資源調度
- kube-controller Manager:負責維護集群的狀態,比如故障檢測、自動擴容,自動更新等
controller manager又包含了:
節點控制器(node controller):負責在節點出現故障時,進行通知和響應
任務控制器(Job Controller):監測代表一次性任務的Job對象,然后創建Pods來運行這些任務直到完成
端點分片控制器(EndpointSlice Controoler):填充端點分片對象(以提供Service和Pod間的連接)
服務帳號控制器(ServiceAccount Contoller):為新的命名空間創建默認的服務賬號(Service Account)
- Kubelet:負責維護容器的生命周期,同時也負責Volume和網絡的管理
- Container Runtime:負責鏡像管理以及Pod和容器的真正運行
- Kube-proxy:負責為Service提供集群內部的服務發現和負載均衡(根據linux內核的iptables轉發實現的)
- CoreDNS:負責k8s集群內部的服務發現和域名解析功能
解析過程:當一個pod或其它服務訪問k8s集群中的另一個service時,它會使用目標service的名稱作為域名解析傳遞給CoreDNS,CoreDNS收到DNS請求后,k8s插件會根據請求中的域名查找對應的service,并將其解析為對應的podIP地址,然后CoreDNS將解析結果返回給發起請求的pod或service
- cloud-controller-manager:
k8s集群的存儲掛載方式:
configmap、secrets、hostpath、emptydir(空目錄,用于臨時存儲數據),pv、pvc、storageclass(動態存儲類)
k8s的高可用集群(使用二進制安裝)
使用keepalived+haproxy+kube-apiserver 6443端口
自建etcd存儲集群,自建容器引擎(docker或containerd),使用kubeadm進行安裝
k8s的資源清單:
pod、node、daemonset、deployment、ReplicationController、replicaset、statefulset、ConfigMap、ingress、service、pv、pvc、storage class、Secret
deployment更新策略
recreate:重新創建策略,在創建新的pod之前,所有現有的pod會被殺死
rollingupdate:滾動更新策略,
maxunavailable:最大不可用,用來指定在更新過程中不可用的pod的個數上限,該值是絕對數和百分比,此值不能為0,如:設置30%,當更新開始時會立即縮容到期望pod個數的70%,新pod準備就緒之后,繼續縮容就有的replicaset,然后對新的replicaset擴容,確保更新期間pod的數在任何時候都至少保持在70%
maxsurge:最大峰值,用來指定可以創建的超出期望pod個數的pod數量,此值是絕對數或百分比,此值不能為0,如,設置30%,代表會對replicaset擴容,同時保證pod的總數不超過pod總數的130%,一旦舊pod被殺死,新的replicaset可以進一步擴容,同時確保更新期間的任何時候運行中的pod總數量最多為所需pod總數的130%
pod的訪問過程或者是客戶端怎么訪問到后端的pod上
這會產生兩個資源對象:service和endpoints
pod是應用的載體,我們通過pod的ip訪問應用是不現實的,因為pod的IP地址是不固定的,每次重啟或重建pod,IP地址都會改變,所以k8s引用了service資源,service會把同一個服務的多個pod進行聚合,并且提供了一個統一的入口地址,通過訪問Service的入口地址就能訪問后面的pod服務,同時Service資源是通過selecter的標簽選擇器和pod的selecter進行關聯。
Endpoints是k8s的一個資源對象,存儲在etcd中,用來記錄一個service對應的所有pod的訪問地址,它是根據service配置文件中的selecter標簽選擇器產生的,一個service由一組pod組成,這些pod通過Endpoints暴露出來,實際上它也是實現service服務端點的集合,換句話就是service和pod之間的聯系是通過endpoints實現的
k8s的service資源的會話粘連性
sessionAffinity:確保來自特定客戶端的連接每次都傳遞給同一個pod,默認為none
sessionAffinityConfig.clientIP.timeoutSeconds:會話粘連性超時,默認是3個小時,10800分鐘
k8s的kube-proxy支持的三種工作模式:1、userspace(用戶空間)2、Iptables,3、Ipvs
kube-proxy是基于linux內核的iptables進行工作的
簡述kube-proxy的作用:
kube-proxy運行在所有的節點上,它是通過apiserver接口監控Service和endpoint的變化,創建路由規則以提供服務IP和負載功能,簡單理解就是此進程是Service的透明代理兼負載均衡器,其核心功能是將到某個Service的訪問請求轉發到后端的多個Pod資源上
簡述kube-proxy的iptables的原理:
從1.2版本開始,iptables作為kube-proxy的默認模式,iptables模式下的kube-proxy不再起到proxy作用,其核心功能,通過API Service的Watch接口實時跟蹤Service和endpoint的變更信息,并更新對應的iptables規則,Client的請求流量則通過iptables的NAT機制直接路由到目標Pod上
簡述kube-proxy的ipvs的原理:(需要安裝ipvadm、ipset)
ipvs在k8s的1.11版本中升級為GA穩定版,IPVS則專門用于高性能負載均衡,并使用更高效的數據結構(hash表),允許幾乎無限的規模擴張,因此被kube-proxy采納為最新模式
在IPVS模式下,使用iptables的擴展ipset,而不是直接調用iptables來生成規則鏈,iptables規則鏈是一個線性的數據結構,ipset則引入了帶索引的數據結構,因此當規則很多時,也可以很高效地查找和匹配
可以將ipset簡單理解為一個IP(段)的集合,這個集合的內容可以是IP地址,IP網段,端口等,iptables可以直接添加規則對這個"可變的集合"進行操作,這樣的好處就是可以大大減少iptables的規則數量
簡述Iptables和IPVS的異同點:
iptables和IPVS都是基于linux的Netfilter實現的,但定位不同,二者有著本質上的區別,iptables是為防火墻而設計的,ipvs則是專門用于高性能負載均衡,并使用高效的數據結構(Hash表),允許幾乎無限的規模擴張
與iptables相比,ipvs的優勢:
1、為大型集群提供了更好的可擴展性和性能
2、支持比iptables更復雜的負載均衡算法
3、支持服務器健康檢查和連接重試等功能
4、可以動態的修改ipset集合,即使iptables的規則正在使用這個集合
k8s中負載均衡的策略:
輪詢、最少連接、iphash等
k8s的service中的四種服務類型:
1、ClusterIP:在集群內部通訊
2、NodePort:可以和集群外部通訊
3、ExternalName:表示把集群外部的服務引入到進群內部來,實現集群內部pod和集群外部進行通訊
4、LoadBalancer:這個表示我可以把k8s部署在虛擬機上,自動在外部創建負載均衡,比如在阿里云上,底層是LBAAS
Pod的生命周期:
簡述一下Pod的生命周期
pod的生命周期是指,pod資源從創建到終止運行的這段時間范圍,包含了pod的創建、運行初始化容器過程、運行主容器過程和pod的終止過程,而在這段時間中又分為了兩個階段,一是初始化階段,二是主容器運行階段,初始化階段可以理解為是對pod的運行環境進行初始化,當初始化結束之后才開始進入到主容器運行階段,當運行主容器時會產生容器啟動后鉤子,當容器終止時,會有容器結束前鉤子,而在主容器運行階段,又會有兩種健康檢查,就緒性檢查和存活性檢查,在整個pod的生命周期內會產生五種狀態:
Pending(掛起):Pod已經被k8s接受,但有一個或多個容器尚未創建亦未運行,此階段包括等待Pod被調度和鏡像下載的時間
Running(運行):Pod已經綁定到了某個節點,Pod中的容器已經被創建,至少有一個容器在運行,或正處于啟動或重啟狀態
Succeeded(成功):Pod中的容器都已成功終止,并且不會被重啟
failed(失敗):Pod中所有的容器已被終止,并且至少有一個容器是因為失敗終止,也就是說,容器以非0狀態退出或者被系統終止
unkown(未知):因為某些原因無法獲得Pod的狀態,這種情況通常是因為與Pod所在的主機通信失敗
同時還有兩個過渡狀態:ContainerdCreating和terminating
pod的創建過程:
1、客戶端將創建Pod的請求發送給Api Server
2、apiserver將Pod信息寫入到Etcd中,etcd將結果響應給apiserver,apiserver將創建結果響應給客戶端(此時pod處于pending狀態)
3、scheduler通過apiserver的watch接口,獲取到有未調度的Pod的通知,根據調度策略選擇一個node節點,告訴apiserver這個Pod應該運行于哪個node節點
4、Apiserver將這個Pod和node的綁定信息更新到etcd中,etcd將寫入結果響應給Apiserver
5、kubelet通過apiserver的watch接口,獲取到當前節點有創建pod的通知,kubelet調用docker創建容器,kubelet將pod運行狀態發送給apiserver
6、apiserver將pod狀態信息更新到etcd
pod的初始化過程:
1、初始化容器階段,會初始化Pod中每個容器,容器是串行執行的
2、啟動main container,在main container剛剛啟動后就可執行postStart指令(容器啟動后鉤子)
3、在整個main container運行周期中做了兩類健康探測:liveness probe(存活探測)和readiness probe(就緒性探測)
4、在main container結束前可以執行preStop命令(容器結束前鉤子)
pod的終止過程:
1、用戶向apiserver發送刪除pod對象的命令
2、apiserver中的pod對象信息會隨著時間的推移而更新,在寬限期內(默認30s),pod被視為dead
3、將pod標記為terminating狀態
4、kubelet在監控到pod對象轉為terminating狀態的同時啟動pod關閉進程
5、(entpoint)端點控制器監控到pod對象的關閉行為時將其從所有匹配到此端點的service資源的endpoints列表中移除
6、如果當前pod對象定義了prestop鉤子處理器,則在其標記為terminating后即會以同步的方式啟動執行
7、pod對象中的容器進程收到停止信號
8、寬限期結束后,若pod中還存在仍在運行的進程,那么pod對象會收到立即終止的信號
9、kubelet請求apiserver將此pod資源的寬限期設置為0從而完成刪除操作,此時pod對于用戶已不可見
當apiserver接受到用戶刪除指令,默認有30s等待優雅退出,超過30s就會被標記為死亡狀態,此時pod的狀態為terminating,kubelet看到pod標記為terminating狀態之后就開始了關閉pod的工作
1、pod從service的endpoint列表中被移除
2、如果該pod定義了一個停止前的鉤子,其會在pod內部被調用,停止鉤子一般定義了如何優雅的結束進程
3、進程被發送TERM信號(kill -14)
4、當超過優雅退出的時間后,pod中的所有進程都會被發送sigkill信號(kill -9)
Pod生命周期中常見的五種狀態:
1、掛起(pending):Pod已被k8s系統接受,但是有一個或多個容器尚未創建亦未運行,此階段包括等待Pod被調度或鏡像正被下載的時間
2、運行中(running):Pod已經綁定到某個節點上,Pod中的容器都已被創建,至少有一個容器仍在運行,或正處于啟動或重啟狀態
3、成功(succeeded):Pod中的所有容器都被成功終止,并且不會再重啟
4、失敗(failed):Pod中的所有容器都已終止,并且至少有一個容器是因為失敗終止,容器以非0狀態退出或被系統終止
5、未知(unknown):因為某些原因無法獲取pod的狀態,通常是因為與pod所在主機通信失敗
6、complete的狀態:通常表示該pod的主要容器已經成功完成其工作并正常退出,這通常用于運行一次性任務或作業(CronJob)
Deployment創建流程:
客戶端將創建deployment的請求發送給Apiserver組件
1、Apiserver組件將Deployment信息寫入etcd中,etcd將寫入結果響應給api server,api server將結果響應給客戶端
2、controller manager組件通過api server的watch接口,獲取到新增的deployment資源,deployment contoller向api server發送創建replica set的請求,api server 將replica set 信息寫入etcd中
3、controller manager 通過api server的watch接口獲取到新增的replica set資源,replica set向api server發送創建pod的請求,api server將pod的信息寫入etcd
4、scheduler 通過api server 的watch接口獲取到未調度的pod通知,根據調度算法選擇一個node節點,告訴api server這個pod應該運行在那個node節點上
5、api server將這個pod和node的綁定信息更新到etcd中,etcd將寫入結果響應給api server
6、kubelet 通過api server的watch接口獲取到當前node節點有創建pod的通知,kubelet調用docker創建容器,kubelet將pod的運行狀態發送給api server
7、api server將pod的信息更新到etcd中
k8s容器探針:
livenessProbe(存活性探針):用于判斷容器是否正在運行,如果不滿足健康條件,那么kubelet將根據pod中設置的重啟策略來判斷pod是否需要重啟,livenessProbe按照配置進行探測來判斷容器是不是正常,如果探測不到,代表容器不健康,則kubelet會殺掉容器(不是pod資源)并根據容器的重啟策略進行相應的處理,如果沒有配置探針,則默認容器啟動為Success狀態,即探針返回的值永遠是Success,即Success后pod的狀態是RUNNING
readinessProbe(就緒行探針):用于指示容器是否準備好為請求提供服務,只有程序正常,容器開始對外提供網絡訪問,當程序沒有問題時,容器的狀態是Success,pod的READY狀態為true,從0/1變為1/1,如果不正常一直是0/1,狀態為false,如果readinessProbe正常,則此pod關聯的Service資源。EndPoint的列表也將基于pod的ready狀態進行設置,如果運行中ready狀態變為false,則系統自動把pod從service資源關聯的EndPoint列表中移除,此時kube-proxy將不再把流量引入到這個pod上,kube-proxy通過這種機制能夠防止將流量轉發到不可用的pod上,如果pod恢復為ready狀態,將會被加回到EndPoint列表中,kube-proxy也將通過負載機制引入流量到此pod上
startupProbe(啟動性探針):用于容器中的應用是否已經啟動,在復雜的程序中readinessProbe和livenessProbe不能更好的判斷程序是否啟動和存活,這時就可以使用startupProbe,當三種探針都存在時,先執行startupProbe,其它兩個探針將會被暫時禁用,直到pod滿足startupProbe配置的條件,其它兩個探針才運行
startupProbe(啟動性探針)只是在容器啟動后按照配置滿足一次后,不再后續進行探測,而其它兩種探針則會一直存在,直到容器消亡才停止探測
探針的四種方式:
tcpSocket:通過TCP連接檢測容器內的端口是否通,如果遠程系統(容器)在打開連接后立即將其關閉,算作健康
httpGet:通過應用程序暴漏的API地址檢查程序是否正常,返回狀態碼大于等于200且小于400,則診斷成功
exec:在容器中執行一條命令
grpc:使用grpc執行一個遠程過程調用,目標應該實現grpc健康檢查,如果響應的狀態是'SERVING',則認為診斷成功
探測結果顯示的三種狀態:
Success:表示檢測通過
Failure:表示檢測未通過
Unknow:表示檢測沒有正常進行
探針參數:
initialDelaySeconds:
periodSeconds:
timeoutSeconds:
successThreshold:
failureThreshold:
terminationGracePeriodSeconds:
k8s的存儲卷(PV、PVC、StorageClass)
PV:持久化存儲卷,是實際的存儲資源,由管理員創建,定義了存儲容量、訪問模式、存儲類別等,一旦綁定到PVC,就不能再被其它PVC使用
PVC:存儲卷聲明,是Pod請求使用PV的抽象,定義了Pod所需存儲資源的屬性,如:大小,訪問模式,存儲類別
StorageClass:動態存儲,k8s使用StorageClass創建PVC,并根據StorageClass的規則動態分配PV,滿足PVC的需求
PV與PVC的關系:
PVC是PV的請求,定義了Pod需要的存儲資源的屬性,PVC可以綁定到PV,前提是PV滿足PVC的請求需求,PV是實際的存儲資源,一旦綁定,K8S會自動將PVC映射到相應的PV上
k8s的資源限制:
limits:約束,分為內存、CPU和hugepages
spec.containers[].resources.limits.cpu
spec.containers[].resources.limits.memory
spec.containers[].resources.limits.hugepages-<size>
requesets:請求,分為內存、CPU和hugepages
spec.containers[].resources.requests.cpu
spec.containers[].resources.requests.memory
spec.containers[].resources.requests.hugepages-<size>
資源限制和請求設置的好處
當出現資源搶占的時候,按照優先級的不同,對pod進行驅逐,
驅逐策略為:
優先驅逐沒有設置資源請求和限制的,其次驅逐的是limit和request不相等的pod,最后驅逐的是limit和request設置相等值的pod
QoS(服務質量等級)
1、高優先級(Guaranteed):Pod中的每個容器同時設置了CPU和內存的requests和limits,而且值必須相等
注意:如果container指定了自己內存限制,但沒有指定內存請求,k8s會自動為它指定與內存限制相等的內存請求,同樣,如果容器指定了自己的CPU限制,但沒有指定CPU請求,k8s會自動為它指定與CPU限制相等的CPU請求
2、中優先級(Burstable):Pod中至少有一個容器設置了cpu或內存的requests和limits,但不滿足Guaranteed等級的要求
3、低優先級(BestEffort):沒有一個容器設置CPU和內存的requests和limits值
k8s的有狀態服務和無狀態服務
無狀態服務:運行的pod不需要持久化存儲數據,并且多個pod對于同一個請求是相同的,多個實例可以共享相同的持久化數據,相關的資源:deployment replicaset 等
有狀態服務:每個pod都具有唯一的標識,該標識包括順序標識,穩定的網絡標識和穩定的存儲,該標識和pod是綁定的,每個pod都有自己獨立的持久化存儲,并且在k8s中是通過申明模板來進行定義的。相關資源為:statefulset
無頭服務屬于有狀態服務的一種,可以根據DNS名稱訪問pod,DNS名稱組成,pod名稱+service名稱+命名空間名稱+svc.cluster.local
deployment、daemonset、statefulset的區別
在k8s中,deployment、daemonset、statefulset是三種不同類型的控制器,用于管理容器化應用程序的部署和運行,他們之間的只要區別在于它們管理pod的方式以及它們適用場景不同,總的來說,deployment使用于無狀態服務,statefulset適用于有狀態服務,daemonset則用于在集群每個節點上運行特定的后臺服務
1、deployment是k8s中常見的控制器之一,用于管理無狀態應用程序,負責創建和管理pod的副本,確保定義的副本數與期望的副本數一致,支持滾動更新,主要用于web服務,api服務等不需要持久化的應用程序
2、statefulset用于管理有狀態的服務,這些服務需要穩定的唯一的網絡標識和持久化存儲,與deployment的不同在于statefulset創建的pod具有固定的身份,即使重啟和遷移它們的標識也不會改變,還支持有序部署和擴展,常用于數據庫、緩存系統等需要持久化存儲和唯一網絡標識的應用
3、daemonset用于確保集群中的每個節點都運行一個或多個副本,通常用于部署在每個節點上運行的后天服務、日志收集等,與deployment和statefulset不同之處在于daemonset不會自動擴縮容,它會在每個節點上創建一個副本,并在節點加入或移除集群時,自動調整pod的數
k8s集群的configmap和secrets的區別:
configmap:用來將非機密性數據保存到鍵值對中,可以用于環境變量、命令行參數和管理配置文件
secret:用于保存包含敏感信息的數據,是加密性的
k8s的ingress和ingress controller
Ingress:
ingress:是反向代理規則,一種管理進入集群的HTTP/HTTPS流量的資源對象,用來規定HTTP/S請求應該被轉發到哪個service上,比如根據請求中的不同host和url路徑請求落到不同的service,
ingress controller:是一個反向代理程序,它負責解析ingress的反向規則,如果有增刪改的變動,所有的ingress controller都會及時更新自己相應的轉發規則,當ingress controller收到請求后就會根據這些規則將請求代理到對應的service
ingress的工作原理:
1)Ingress controller通過與Kubernetes api進行交互,動態的感知集群中Ingress規則的變化;
2)然后讀取它,按照自定義的規則,規則就是寫明了哪個域名對應哪個service,生成一段nginx配置;
3)再寫到nginx-ingress-controller的pod里,這個Ingress controller的pod里運行著一個Nginx服務,控制器會把生成的nginx配置寫入/etc/nginx.conf文件中;
4)然后reload一下使配置生效。以此達到域名分別配置和動態更新的問題;
ingress解決的問題:
1、減少不必要的端口映射
2、動態配置服務
kuebernetes更新證書:
備份原來的證書和etcd數據目錄
修改kubeadm的原代碼中關于證書時長的信息,進行build代碼,得到新的kubeadm命令,替換原來集群中的kubeadm命令,使用kubeadm certs 命令進行更換證書,如果是高可用集群,則每個master節點都需要執行kubeadm certs renew all
Pod的重啟策略:
Never:當容器終止退出,從不重啟容器
OnFailure:當容器異常退出(退出狀態碼非0)時,重啟容器
Always:當容器終止退出后,總是重啟容器,默認策略
Pod中鏡像的更新策略
Always:總是去鏡像倉庫拉去鏡像
Never:從不拉去鏡像,只用本地鏡像
IfNotPresent:如果本地有需要的鏡像就不會進行拉去,如果沒有就去倉庫拉去鏡像
Pod中的pause容器:
Pause容器又叫infra容器(基礎設施容器)是一種特殊類型的容器,是k8s自動生成并且注入到每個pod中,主要是為其它容器提供一個可靠的、隔離的運行環境,本身不包含任何業務邏輯,可以在創建其它容器之前將其加載到pod中,以確保Pod中的其它容器在Pause容器的基礎上運行;
Pause容器的主要作用:
網絡命名空間隔離
容器間通信
共享存儲卷
生命周期管理
1、為其它容器提供生命周期的隔離和協調,它可以幫助管理員確保pod中各個容器的啟動順序和依賴關系,避免容器間的相互干擾和沖突;
2、為Pod中的容器提供一個穩定的網絡環境,確保容器網絡的連接可靠性
Pod資源中針對容器提供網絡命名空間等共享機制的是底層基礎容器pause,它就是為了管理pod容器的共享操作,也能管理容器的生命周期,這個pause的容器有兩個核心功能:1、它提供了整個pod的linux命名空間的基礎,2、啟動PID命名空間,它在每個pod中都作為PID為1的進程(init進程),并收回僵尸進程
pause容器的工作原理:
1、與k8s其它組件進行交互:
Pause容器作為Pod中的一個組件,與k8s的其他組件進行交互,當pod被創建時,API服務將Pause容器的配置信息存儲在etcd中,并通知Contoller manager對Pod進行處理,Contoller manager將Pause容器與Pod中的其它容器一起調度到節點上運行
2、管理容器的生命周期:
Pause容器通過使用名為cri-pause的進程來管理其它容器的生命周期,當pod中的其它容器啟動時,cri-pause進程會將這些容器的啟動信息記錄在特定的文件中,當pod被刪除時,cri-pause進程會檢測到該文件并停止記錄,以確保Pod中的容器在Pause容器的基礎上一致地執行生命周期操作
3、實現容器間的協調合作
Pause容器通過使用cni網絡插件來實現容器間的協調合作,當Pod中的其它容器啟動時,cni網絡插件將為這些容器分配IP地址,并設置網絡連接,確保Pod中的各個容器可以相互通信,實現協調合作
Pod中的init containers:
init容器與其它普通容器非常像,但是有兩點是不一樣的,1、它必須在應用容器啟動前運行完成,2、一個init容器必須在下一個init容器運行前完成運行,是有執行順序的,同時init容器不支持lifecyle、livenessProbe、readinessProbe和startupProbe,因為它們必須在pod就緒前運行完成。
k8s的網絡模型:
k8s的網絡模型的目標是:每個一個pod都擁有一個扁平化共享網絡命名空間的IP,稱為podIP,通過podIP,pod能夠跨網絡與其他物理機和pod進行通信,一個pod一個IP的(IP-per-IP)模型創建一個干凈、反向兼容的模型,在該模型中,從端口、網絡、域名解析、服務發現、負載均衡、應用配置和遷移等角度,pod都能被看成虛擬機或物理機,這樣就能夠平滑的從一個非容器環境遷移到同一個pod內的容器環境
為了實現這個模型,在k8s中需要解決:容器間的通信,pod間的通信(同一個node上pod間和不同node上的pod間的通信),pod和service間的通信
Pod間的通信:
1、容器之間的通信
同一個Pod中的容器,共享同一個網絡命令空間,共享同一個linux協議棧,容器間的通信是可以通過localhot進行相互通信的
2、同一個node節點上的Pod間的通信
主要依賴兩個主要設備,一個是虛擬網絡設備(veth pair),veth pair每次都是生成一對,一端連接的是pod,一端連接的宿主機上的網絡命名空間上,然后在宿主機這邊又接入到了一個網橋設備(cni0),通過網橋設備把報文等發送到相對應pod的虛擬網絡設備(veth pair)上,再通過虛擬網絡設備連接到相連的pod上
3、不同node節點上的Pod間的通信
這需要通過網絡組件進行實現,如flannel,calico
4、Pod和Service間的通信
通過iptables的路由過濾轉發
flannel網絡:
Flannel是一種覆蓋網絡,它能夠給每一個node節點上的容器分配一個互不沖突的IP地址,在這些IP地址之間建立一個覆蓋網絡,也就是將TCP數據包封裝在另一種網絡包里面進行路由轉發和通信,網絡信息都會存儲在etcd中
flannel的網絡模式:
UDP:
host-gw:
VXLAN:
calico網絡:
calico是基于BGP的純三層網絡,calico在每個節點上利用Linux Kernel實現了一個高效的虛擬路由器vRouter來負責數據轉發的,每個vRouter都是通過BGP協議把本節點上運行的容器的路由信息向整個calico網絡廣播,并自動設置到達其他節點的路由轉發規則,calico保證所有的容器之間的數據流量都是通過IP路由的方式完成互聯互通,calico節點組網是直接利用數據中心的網絡結構,不需要額外的NAT、隧道或覆蓋網絡(overlay network),沒有額外的解包封包
calico的網絡模式:
IPIP:
BGP:
flanel和calico網絡插件的區別:
網絡拓撲:
Flannel:通過創建虛擬網絡層來實現容器之間的通信,通常使用Overlay網絡技術(VXLAN或UDP封裝)將容器的IP地址映射到節點的物理IP地址,然后路由數據包以實現容器之間的通信
Calico:使用BGP路由協議來實現容器間的通信,每個節點在Calico網絡中有唯一的IP地址,并使用BGP來交換路由信息,從而實現容器間的直接路由
性能和效率:
Flannel:使用Overlay網絡技術,引入了一些額外的封裝和解封裝,可能會對性能產生一些微弱的負擔
Calico:直接路由方法更高效,減少了一些封裝和解分裝的操作,減少了額外的網絡開銷
網絡策略:
Fannel:本身不提供網絡策略,但是可以和k8s的網絡策略相結合
Calico:允許定義復雜的網絡策略,如,允許\拒絕流量
部署復雜性:
Flannel:部署簡單,用于小型的集群
Calico:用于大中規模的集群,提供更多的配置和管理
k8s集群的RBAC授權
RBAC是k8s集群基于Role(角色)的訪問控制,是一種基于組織中用戶的角色來調節控制計算機或網絡資源的訪問方法
Role:
ClusterRole:
RoleBinding:
ClusterRoleBinding:
Kubernetes集群外部如何訪問集群內的服務:
對于kubernetes,集群外部的客戶端默認是無法通過pod的IP和Service的虛擬IP,虛擬端口號訪問的,通常需要使用四種方式進行訪問
1、映射pod到宿主機
2、映射Service到宿主機
3、映射Service到LoadBalancer
4、通過ingress進行訪問
k8s的pod調度策略:
默認的調度策略
定向調度(強制調度)
nodeName:根據node節點的名稱選擇調度到哪個節點上,創建pod時,指定nodeName的名稱
nodeSelector:根據node節點的lable進行選擇調度到那個節點上
實現方式:1、給node節點打標簽,kubectl lable nodes node01 disktype=ssd
2、創建pod時,指定nodeselector
親和性調度
nodeAffinity:以node為目標,根據node的標簽來解決pod可以調度到哪些node上的問題
podAffinity:以pod為目標,根據pod的標簽來解決pod可以和哪些已存在的pod部署到同一個拓撲域中的問題
podAntiAffinity:以pod為目標,根據pod的標簽來解決pod不能和哪些已存在的pod部署到同一個拓撲域中的問題
親和性和反親和性的使用場景說明:
親和性:如果兩個應用頻繁交互,那就有必要利用親和性讓兩個應用盡可能的靠近,這樣就可以減少網絡通信帶來的性能耗損
反親和性:當應用采用副本部署時,有必要采用反親和性讓各個應用實例打散分布在各個node上,這樣可以提高服務的高可用性
親和性調度的調度策略又分為:preferredDuringSchedulingIgnoredDuringExecution、requiredDuringSchedulingIgnoredDuringExecution
軟親和性:盡量調度到滿足親和性策略的節點上,如果策略得不到滿足時,也可以調度到其它節點上
硬親和性:只能調度到符合親和性策略的節點上
污點和容忍度
污點:node通過污點拒絕pod調度到上面
NoSchedule:k8s不會把pod調度到具有該污點的node上,但不會影響當前node上已經存在的pod
PreferNoSchedule:k8s將盡量避免把pod調度到具有該污點的node上,除非沒有其它節點可以調度
NoExecute:k8s將不會把pod調度到具有該污點的node上,同時也會把該node上已存在的pod驅離
容忍度:pod通過設置容忍度忽略node上的污點,把pod調度到node上
tolerations:
- key: "key"
operator: "Equal"|"Exists"
effect: "effect"
value: "value"
tolerationSeconds: 3600 #延遲驅逐時間(當容忍度不符合節點定義時,pod在該節點運行超過該時間,會被驅逐)
Equal:與污點信息完全匹配的等之關系,key、value和effect與節點的taint完全一致,才能調度到node上
Exists:存在性匹配方式,會忽略value,只要有key和effect就行,同時,如果不指定key、effect值時,能匹配容忍所有的污點,當不指定effect值時,能匹配污點key與對應的所有effect值
k8s的網絡隔離(NetworkPolicy)
三種規則兩種匹配
三種規則:
1、對同一個namespace下的pod進行網絡隔離
podSelector
2、對不同的namespace下的pod進行網絡隔離
namespaceSelector
3、根據CIDR進行隔離
兩種匹配:
1、ingress:流入,在該字段下編寫的入站策略,也就是被選中的pod允許哪些資源訪問
2、egress:流出,在該字段下編寫的出站策略,也就是被選中的pod可以訪問哪些資源
示例:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: networkpol-01
namespace: default
spec:
podSelector: #pod選擇器
matchLabels:
app: canary-nginx #使用標簽選中pod,限制被選中的pod的訪問
policyTypes:
- "Ingress"
- "Egress"
ingress: #入站白名單(當前被選中的pod允許哪些資源訪問)
- from:
- podSelector: #通過pod選擇器同命名空間下的運行訪問pod
matchLabels:
name: busybox ## busybox 可以得到 canary-nginx 的內容
- namespaceSelector: #通過命名空間選擇器選中允許訪問的資源有哪些
matchLabels:
kubernetes.io/metadata.name: hello ## 這個hello名稱空間的可以訪問 canary-nginx 的內容
- ipBlock: #CIDR方式指定允許訪問的資源有哪些
cidr: "192.168.0.0/16" ## 默認 從 192.168.0.0 - 192.168.255.255 都能訪問這個Pod
except: ## 排除指定范圍
- "192.168.1.0/24" ## 192.168.1.0-192.168.1.255 不能訪問
### 兩個 - ,代表并集(或者)
### 一個 - ,代表交集(且)
ports:
- port: 80 #監聽端口
egress: ## 出站白名單,也就是當前通過"canary-nginx"選中的pod能給訪問哪些資源
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: hello ## app: canary-nginx 能訪問hello名稱空間的所有
ports:
- port: 80 #監聽端口
ETCD數據的備份和恢復
數據備份:
使用etcdctl進行備份,指定數據庫的地址端口,指定ETCD的密鑰地址,指定備份方式和數據的備份名稱,如:
etcdctl snapshot save etcd.db(數據備份名稱) --endpoints=https://127.0.0.1:2379 --cacert=(指定etcd根證書) --cert=(指定etcd客戶端數字證書) --key=(指定key)
數據恢復:
需要停止api-server和etcd服務,備份k8s集群的數據和配置,備份etcd的原來數據
etcdctl snapshot restore etcd.db --data-dir=(數據恢復的地址)
api接口的限流:
kong:
sentinel:
維護k8s集群node節點的過程
1、先使用命令使node節點不可調度
kubectl cordon node01
2、使用 drain標記node節點為維護階段,驅逐該節點上pod
kubectl drain node node01
k8s的污點設置
kubectl taint node k8s-node01 key=value:NoSchedule
pod中出現oom之后怎么dump文件下來
可以使用掛載卷的方式,
或者可以使用kubectl cp把dump文件拷貝出來
當發布的時候還能訪問舊有的pod上,該怎么辦?
service資源下的sessionAffinity設置為ClusterIP
可以設置會話超時時間
sessionAffinityConfig.clientIP.timeoutSeconds:默認為10800(3小時)
k8s集群的RBAC授權
role(角色)
rolebinding(角色綁定)
clusterrole(集群角色)
clusterrolebinding(集群角色綁定)
k8s的邊車容器(cidecar)
邊車容器是與主容器在同一個pod中運行的輔助容器,這些容器通過提供額外的服務或功能(如日志,監控、數據同步)來增強或擴展主應用容器的功能,而不需要修改主應用代碼

浙公網安備 33010602011771號