一篇從應(yīng)用部署/服務(wù)管治/集群配置三個(gè)方便來(lái)check你的K8S使用姿勢(shì)是否正確,包含單不限于服務(wù)監(jiān)控檢查/資源使用/標(biāo)簽/HPA,VPA/安全策略/RBAC/日志/監(jiān)控是否為最佳實(shí)踐的check list。
一 應(yīng)用部署
1.1 健康檢查
readiness probe確定容器何時(shí)可以接收流量。
Kubelet執(zhí)行檢查并確定應(yīng)用程序是否可以接收流量。
liveness probe確定何時(shí)應(yīng)重新啟動(dòng)容器。
kubelet執(zhí)行檢查并確定是否應(yīng)重新啟動(dòng)容器。
1.1.1 容器就緒性探針
就緒性和存活性探針沒有默認(rèn)值,如果您未設(shè)置就緒探針,則kubelet會(huì)假定該應(yīng)用程序已準(zhǔn)備就緒,可以在容器啟動(dòng)后立即接收流量。
1.1.2 發(fā)生致命錯(cuò)誤時(shí)容器崩潰
如果應(yīng)用程序遇到不可恢復(fù)的錯(cuò)誤,則應(yīng)使其崩潰,例如:
未捕獲的異常
代碼中的錯(cuò)字(用于動(dòng)態(tài)語(yǔ)言)
無(wú)法加載標(biāo)頭或依賴項(xiàng)
請(qǐng)注意,您不應(yīng)發(fā)信號(hào)通知Liveness探針失敗,相反,您應(yīng)該立即退出該過程,并讓kubelet重新啟動(dòng)容器。
1.1.3 配置被動(dòng)的存活性探針
Liveness探針旨在在卡住容器時(shí)重新啟動(dòng)容器,例如:
如果您的應(yīng)用程序正在處理無(wú)限循環(huán),則無(wú)法退出或?qū)で髱椭?/p>
當(dāng)該進(jìn)程消耗100%的CPU時(shí),將沒有時(shí)間回復(fù)(其他)Readiness探針檢查,并且最終將其從服務(wù)中刪除。但是,該P(yáng)od仍被注冊(cè)為當(dāng)前Deployment的活動(dòng)副本。如果沒有Liveness探針,它將保持運(yùn)行狀態(tài),但與服務(wù)分離。換句話說,該過程不僅不處理任何請(qǐng)求,而且還消耗資源。
此時(shí)應(yīng)該怎么辦:
從您的應(yīng)用程序公開端點(diǎn)
端點(diǎn)總是回復(fù)成功響應(yīng)
使用“活力”探針獲取端點(diǎn)
請(qǐng)注意,您不應(yīng)該使用Liveness探針來(lái)處理應(yīng)用程序中的致命錯(cuò)誤,并要求Kubernetes重新啟動(dòng)應(yīng)用程序。相反,您應(yīng)該讓應(yīng)用程序崩潰。
僅在過程無(wú)響應(yīng)的情況下,才應(yīng)將“活動(dòng)性”探針用作恢復(fù)機(jī)制。
1.1.4 存活性探針與就緒性探針的區(qū)別
當(dāng)“活力”和“就緒”探針指向相同的端點(diǎn)時(shí),探針的作用會(huì)合并在一起。
當(dāng)應(yīng)用程序發(fā)出信號(hào)表明尚未準(zhǔn)備就緒或尚待運(yùn)行時(shí),kubelet會(huì)將容器與服務(wù)分離并同時(shí)將其刪除。
您可能會(huì)注意到連接斷開,因?yàn)槿萜鳑]有足夠的時(shí)間耗盡當(dāng)前連接或處理傳入的連接。
可以參考:article that discussed graceful shutdown.
1.2 應(yīng)用的獨(dú)立性
如果應(yīng)用程序連接到數(shù)據(jù)庫(kù),也許你認(rèn)為如果數(shù)據(jù)庫(kù)為就緒就返回一個(gè)失敗的就緒就ok了,但是事實(shí)并非如此,例如您有一個(gè)依賴于后端API的前端應(yīng)用程序。如果該API不穩(wěn)定(例如由于錯(cuò)誤而有時(shí)不可用),則就緒探測(cè)器將失敗,并且前端應(yīng)用程序中的相關(guān)就緒也將失敗。這就會(huì)導(dǎo)致停機(jī)時(shí)間。更一般而言,下游依賴項(xiàng)的故障可能會(huì)傳播到上游的所有應(yīng)用程序,并最終也降低前端面層
1.2.1 就緒性探針應(yīng)該獨(dú)立
就緒性探針不應(yīng)該依以下服務(wù):
數(shù)據(jù)庫(kù)
數(shù)據(jù)庫(kù)遷移
APIs
第三方服務(wù)
詳細(xì)可參考:explore what happens when there’re dependencies in the readiness probes in this essay.
1.2.2 應(yīng)用程序重連到依賴服務(wù)
應(yīng)用啟動(dòng)時(shí),它不應(yīng)該因?yàn)閿?shù)據(jù)庫(kù)等依賴項(xiàng)尚未就緒就崩潰,而是,應(yīng)用程序應(yīng)繼續(xù)嘗試重新連接數(shù)據(jù)庫(kù),直到成功為止。
Kubernetes希望可以以任何順序啟動(dòng)應(yīng)用程序組件。當(dāng)您確保您的應(yīng)用程序可以重新連接到諸如數(shù)據(jù)庫(kù)之類的依賴項(xiàng)時(shí),這樣可以大大提升服務(wù)的健壯性。
1.3 優(yōu)雅的關(guān)機(jī)
您應(yīng)該等待現(xiàn)有連接耗盡并停止處理新連接。請(qǐng)注意,當(dāng)Pod終止時(shí),該P(yáng)od的端點(diǎn)將從服務(wù)中刪除。
但是,可能需要一些時(shí)間才能將諸如kube-proxy或Ingress控制器之類的組件通知更改。
詳細(xì)可參考:handling client requests correctly with Kubernetes.
正確的優(yōu)雅停止順序
在收到SIGTERM后
服務(wù)器停止接受新的鏈接
完成現(xiàn)有所有的請(qǐng)求
然后殺死所有的keepalive鏈接
進(jìn)程退出
可以利用工具測(cè)試:test that your app gracefully shuts down with this tool: kube-sigterm-test.
1.3.1 應(yīng)用程序未通過SIGTERM信號(hào)關(guān)閉,但它已經(jīng)終止了鏈接
可能需要一些時(shí)間才能將諸如kube-proxy或Ingress控制器之類的組件通知端點(diǎn)更改。
因此,盡管標(biāo)記為已終止,但流量仍可能流向Pod。
該應(yīng)用程序應(yīng)停止接受所有剩余連接上的新請(qǐng)求,并在耗盡傳出隊(duì)列后將其關(guān)閉。
1.3.2 應(yīng)用程序仍在寬限期處理請(qǐng)求
您可能要考慮使用容器生命周期事件,例如the preStop handler自定義pod刪除之前的動(dòng)作
1.3.3 Dockerfile中的CMD將SIGTERM轉(zhuǎn)發(fā)到進(jìn)程
通過在應(yīng)用中捕獲SIGTERM信號(hào),可以在Pod即將終止時(shí)收到通知。
你應(yīng)該注意:forwarding the signal to the right process in your container.
1.3.4 關(guān)閉所有空閑的保持活動(dòng)套接字
如果調(diào)用方應(yīng)用未關(guān)閉TCP連接(例如使用TCP保持活動(dòng)狀態(tài)或連接池),它將連接到一個(gè)Pod,而不使用該服務(wù)中的其他Pod。
當(dāng)時(shí)當(dāng)pod刪除的時(shí)候會(huì)發(fā)生什么呢,理想狀態(tài)請(qǐng)求應(yīng)該使用其他POD,但是,調(diào)用方應(yīng)用程序與即將終止的Pod的連接壽命很長(zhǎng),它將繼續(xù)使用它。
另一方面,你不應(yīng)該突然終止一個(gè)長(zhǎng)鏈接,相反,您應(yīng)該先關(guān)閉它們,然后再關(guān)閉應(yīng)用程序。
您可以在有關(guān)以下內(nèi)容的文章中閱讀有關(guān)保持活動(dòng)連接的信息:gracefully shutting down a Nodejs HTTP server.
1.4 容錯(cuò)能力
物理機(jī)硬件故障
云供應(yīng)商或管理程序
kernel恐慌
pod部署在這些節(jié)點(diǎn)上也將丟失
在以下情況下可以刪除pod
直接刪除一個(gè)pod
draining一個(gè)node
從節(jié)點(diǎn)上刪除Pod,以允許另一個(gè)Pod適合該節(jié)點(diǎn)
以上任何情況都可能影響您的應(yīng)用程序的可用性,并可能導(dǎo)致停機(jī)。
您應(yīng)該避免所有Pod都無(wú)法使用并且無(wú)法提供實(shí)時(shí)流量的情況。
1.4.1 部署運(yùn)行多個(gè)副本
永遠(yuǎn)不要僅運(yùn)行一個(gè)pod
利用控制器Deployment, DaemonSet, ReplicaSet or StatefulSet.來(lái)運(yùn)行pod,不應(yīng)該將應(yīng)用運(yùn)行為自主式pod
可以參考:Running more than one instance your of your Pods guarantees that deleting a single Pod won’t cause downtime.
1.4.2 避免將Pod放置在單個(gè)節(jié)點(diǎn)中
即使您運(yùn)行Pod的多個(gè)副本,也無(wú)法保證丟失節(jié)點(diǎn)不會(huì)破壞您的服務(wù)。
如果你在單一node上運(yùn)行一個(gè)11個(gè)副本集的pod,如果這個(gè)node故障,這個(gè)服務(wù)也一樣會(huì)停機(jī)
運(yùn)行反親和性在集群中:You should apply anti-affinity rules to your Deployments so that Pods are spread in all the nodes of your cluster.
詳細(xì)可以參考:inter-pod affinity and anti-affinity
1.4.3 設(shè)置Pod中斷預(yù)算
當(dāng)一個(gè)node被打上污點(diǎn),pod是要被刪除并且重新調(diào)度
但是如果你的系統(tǒng)壓力很大,不能接受丟失50%的pod這時(shí)候改怎么辦呢,驅(qū)逐pod可能會(huì)影響你的服務(wù)
為了保護(hù)部署免受可能同時(shí)摧毀多個(gè)Pod的意外事件的影響,可以定義Pod中斷預(yù)算。
想象一下:“ Kubernetes,請(qǐng)確保我的應(yīng)用始終至少有5個(gè)Pod在運(yùn)行”。
如果最終狀態(tài)導(dǎo)致該部署的Pod少于5個(gè),Kubernetes將阻止耗盡事件。
官網(wǎng)參考文檔:Pod Disruption Budgets.
1.5 資源使用
為了最大化調(diào)度程序的效率,您應(yīng)該與Kubernetes共享詳細(xì)信息,例如資源利用,工作負(fù)載優(yōu)先級(jí)和開銷。
1.5.1 設(shè)置所有容器的內(nèi)存限制和請(qǐng)求
資源限制用于限制容器可以使用多少CPU和內(nèi)存,并使用containerSpec的resources屬性設(shè)置。調(diào)度程序?qū)⑦@些用作度量標(biāo)準(zhǔn)之一,以確定哪個(gè)節(jié)點(diǎn)最適合當(dāng)前Pod。根據(jù)調(diào)度程序,沒有內(nèi)存限制的容器的內(nèi)存利用率為零。如果可調(diào)度在任何節(jié)點(diǎn)上的Pod數(shù)量不受限制,則會(huì)導(dǎo)致資源超額使用,并可能導(dǎo)致節(jié)點(diǎn)(和kubelet)崩潰。
同用的可以適用于CPU限制
但是,您是否應(yīng)該始終設(shè)置內(nèi)存和CPU的限制和要求?
如果您的進(jìn)程超出內(nèi)存限制,則該進(jìn)程將終止。由于CPU是可壓縮的資源,因此如果您的容器超出限制,則將限制該過程。
如果您想更深入地研究CPU和內(nèi)存限制,則應(yīng)查看以下文章:
Understanding resource limits in kubernetes: memory
Understanding resource limits in kubernetes: cpu time
請(qǐng)注意,如果不確定什么是正確的CPU或內(nèi)存限制,則可以在建議模式打開的情況下使用Kubernetes中的Vertical Pod Autoscaler。自動(dòng)縮放器會(huì)分析您的應(yīng)用并建議限制。
1.5.2 將CPU請(qǐng)求設(shè)置為1個(gè)CPU或以下
除非你有計(jì)算類型的實(shí)例類型job
it is recommended to set the request to 1 CPU or below.
1.5.3 禁用CPU限制—除非您有很好的用例
CPU以每個(gè)時(shí)間單位的CPU時(shí)間單位來(lái)度量。
cpu:1表示每秒1個(gè)CPU秒。
如果您有1個(gè)線程,則每秒消耗的CPU時(shí)間不能超過1秒。
如果您有2個(gè)線程,則可以在0.5秒內(nèi)消耗1個(gè)CPU秒。
8個(gè)線程可以在0.125秒內(nèi)消耗1個(gè)CPU秒。之后,您的過程將受到限制。
如果不確定您的應(yīng)用程序的最佳設(shè)置是什么,最好不要設(shè)置CPU限制。
深入研究可參考:this article digs deeper in CPU requests and limits.
1.5.4 命名空間具有LimitRange
如果您認(rèn)為可能忘記設(shè)置內(nèi)存和CPU限制,則應(yīng)考慮使用LimitRange對(duì)象為當(dāng)前名稱空間中部署的容器定義標(biāo)準(zhǔn)大小。
可參考:The official documentation about LimitRange
1.5.5 為Pod設(shè)置適當(dāng)?shù)姆?wù)質(zhì)量(QoS)
當(dāng)一個(gè)節(jié)點(diǎn)進(jìn)入過量使用狀態(tài)(即使用過多資源)時(shí),Kubernetes試圖驅(qū)逐該節(jié)點(diǎn)中的某些Pod。Kubernetes根據(jù)定義明確的邏輯對(duì)Pod進(jìn)行排名和逐出。
參考:configuring the quality of service for your Pods
1.6 標(biāo)記資源
1.6.1 資源已定義技術(shù)標(biāo)簽
你能通過以下tag標(biāo)記pod
名稱,應(yīng)用程序的名稱,例如“用戶API”
實(shí)例,標(biāo)識(shí)應(yīng)用程序?qū)嵗奈ㄒ幻Q(您可以使用容器圖像標(biāo)簽)
版本,應(yīng)用程序的當(dāng)前版本(增量計(jì)數(shù)器)
組件,架構(gòu)中的組件,例如“ API”或“數(shù)據(jù)庫(kù)”
部分,該應(yīng)用程序所屬的更高級(jí)別應(yīng)用程序的名稱,例如“支付網(wǎng)關(guān)”由…
管理,用于管理應(yīng)用程序(例如“ kubectl”或“ Helm”)的操作的工具
標(biāo)簽可參考:recommended by the official documentation.
建議不要標(biāo)記所有資源。
1.6.2 資源已定義業(yè)務(wù)標(biāo)簽
您可以使用以下標(biāo)簽標(biāo)記Pod:
owner:標(biāo)示改資源的負(fù)責(zé)人
project:聲明資源所屬的項(xiàng)目
business-unit:用于標(biāo)識(shí)與資源關(guān)聯(lián)的成本中心或業(yè)務(wù)部門;通常用于成本分配和跟蹤
1.6.3 資源定義安全等級(jí)標(biāo)簽
tag pod通過以下label
confidentiality:資源支持的特定數(shù)據(jù)保密級(jí)別的標(biāo)識(shí)符
compliance:an identifier for workloads designed to adhere to specific compliance requirements
1.7 日志
日志對(duì)于調(diào)試問題和監(jiān)視應(yīng)用程序活動(dòng)特別有用。
1.7.1 應(yīng)用程序記錄到stdout和stderr
有兩種日志策略,主動(dòng)方式與被動(dòng)方式
使用被動(dòng)方式日志記錄的應(yīng)用程序不需要了解了解日志記錄基礎(chǔ)結(jié)構(gòu),而是將消息記錄到標(biāo)準(zhǔn)輸出中。
主動(dòng)方式,該應(yīng)用程序與中間聚合器建立了網(wǎng)絡(luò)連接,將數(shù)據(jù)發(fā)送到第三方日志記錄服務(wù),或直接寫入數(shù)據(jù)庫(kù)或索引。
最佳實(shí)踐:the twelve-factor app.
1.7.2 避免日志使用sidecars模式
如果希望將日志轉(zhuǎn)換應(yīng)用于具有非標(biāo)準(zhǔn)日志事件模型的應(yīng)用程序,則可能需要使用sidecar容器。
使用Sidecar容器,您可以在將日志條目運(yùn)送到其他地方之前對(duì)其進(jìn)行規(guī)范化。
例如,您可能需要先將Apache日志轉(zhuǎn)換為L(zhǎng)ogstash JSON格式,然后再將其發(fā)送到日志基礎(chǔ)結(jié)構(gòu)。
但是,如果您可以控制應(yīng)用程序,則可以從一開始就輸出正確的格式。
sidecares啟動(dòng)需要時(shí)間,您可以節(jié)省為群集中的每個(gè)Pod運(yùn)行額外的容器的時(shí)間。
1.8 伸縮
容器具有本地文件系統(tǒng),您可能會(huì)想使用它來(lái)持久化數(shù)據(jù)。
但是,將持久性數(shù)據(jù)存儲(chǔ)在容器的本地文件系統(tǒng)中會(huì)阻止包圍的Pod進(jìn)行水平縮放(即通過添加或刪除Pod的副本)。
這是因?yàn)?,通過使用本地文件系統(tǒng),每個(gè)容器都維護(hù)自己的“狀態(tài)”,這意味著Pod副本的狀態(tài)可能會(huì)隨時(shí)間而變化。從用戶的角度來(lái)看,這會(huì)導(dǎo)致行為不一致(例如,當(dāng)請(qǐng)求命中一個(gè)Pod時(shí),特定的用戶信息可用,但當(dāng)請(qǐng)求命中另一個(gè)Pod時(shí),則不可用)。
相反,任何持久性信息都應(yīng)保存在Pod外部的中央位置。例如,在集群中的PersistentVolume中,或者在集群外部的某些存儲(chǔ)服務(wù)中甚至更好。
1.8.1 容器在其本地文件系統(tǒng)中不存儲(chǔ)任何狀態(tài)
容器具有本地文件系統(tǒng),您可能會(huì)想使用它來(lái)持久化數(shù)據(jù)。
但是,將持久性數(shù)據(jù)存儲(chǔ)在容器的本地文件系統(tǒng)中會(huì)阻止包圍的Pod進(jìn)行水平縮放(即通過添加或刪除Pod的副本)。
這是因?yàn)?,通過使用本地文件系統(tǒng),每個(gè)容器都維護(hù)自己的“狀態(tài)”,這意味著Pod副本的狀態(tài)可能會(huì)隨時(shí)間而變化。從用戶的角度來(lái)看,這會(huì)導(dǎo)致行為不一致(例如,當(dāng)請(qǐng)求命中一個(gè)Pod時(shí),特定的用戶信息可用,但當(dāng)請(qǐng)求命中另一個(gè)Pod時(shí),則不可用)。
相反,任何持久性信息都應(yīng)保存在Pod外部的中央位置。例如,在集群中的PersistentVolume中,或者在集群外部的某些存儲(chǔ)服務(wù)中甚至更好。
1.8.2 對(duì)于可變使用模式的應(yīng)用應(yīng)該使用HPA
HPA是kubernetes內(nèi)置的一個(gè)特性它能夠監(jiān)控當(dāng)前的應(yīng)用和根據(jù)當(dāng)前的使用率自動(dòng)添加及刪除POD副本
通過配置HPA來(lái)保障你的應(yīng)用在任何情況下包括(異常流量峰值)能夠保存可用及正常響應(yīng)
配置HPA自動(dòng)伸縮你的應(yīng)用,需要去創(chuàng)建一個(gè)HPA的資源對(duì)象,該對(duì)象定義了監(jiān)控你應(yīng)用的什么指標(biāo)
HPA也能夠健康k8s內(nèi)置的資源指標(biāo)(POD的CPU/MEM資源使用率)或者自定義指標(biāo),對(duì)于自定義指標(biāo),你需要去收集和暴露這些指標(biāo),例如你可用使用Prometheus/Prometheus Adapter
1.8.3 不要使用VPA,因?yàn)楦奶匦赃€在測(cè)試中
當(dāng)POD需要更多資源時(shí),VPA能夠通過自動(dòng)的調(diào)整你的POD的資源請(qǐng)求和限制,
VPA非常適用于單體應(yīng)用無(wú)法進(jìn)行橫向副本數(shù)的擴(kuò)張
但是目前VPA仍然處于測(cè)試階段,垂直方向調(diào)整POD資源需要重啟POD
考慮到這些限制,更多的應(yīng)用在k8s中可用橫行擴(kuò)張,因此不要在生產(chǎn)環(huán)境中使用VPA
1.8.4 如果有很高的工作負(fù)載,可以使用集群自動(dòng)伸縮
集群伸縮是區(qū)別于(HPA/VPA)的另一種伸縮類型
集群自動(dòng)伸縮能夠通過增加或移除node節(jié)點(diǎn)來(lái)自動(dòng)縮放集群的大小
當(dāng)由于現(xiàn)有一個(gè)node節(jié)點(diǎn)的資源不足導(dǎo)致pod調(diào)度失敗時(shí),此刻集群會(huì)進(jìn)行擴(kuò)增操作,集群會(huì)增加一個(gè)work node來(lái)保證pod能夠正常調(diào)度,相似的,如果一個(gè)worker node資源使用率低,那么集群自動(dòng)伸縮會(huì)先驅(qū)逐這個(gè)worker node上面的pod,最終去移除此node
對(duì)于集群工作負(fù)載很高的應(yīng)用場(chǎng)景下,就去自動(dòng)伸縮非常有用,集群自動(dòng)縮分可以讓你滿足需求高峰,而不會(huì)通過過度陪你走工作節(jié)點(diǎn)來(lái)浪費(fèi)資源。
對(duì)于工作負(fù)載不大的應(yīng)用場(chǎng)景,可以不用去設(shè)置集群自動(dòng)伸縮,因?yàn)榭赡苡肋h(yuǎn)都使用不到改規(guī)則,如果你的集群工作負(fù)載緩慢增長(zhǎng),可以通過監(jiān)控系統(tǒng)來(lái)手動(dòng)添加worker node
1.9 配置和密鑰
1.9.1 外部化所有配置
配置應(yīng)該在應(yīng)用之外的代碼維護(hù),這有一些好處
更改配置不用重新編譯代碼
當(dāng)應(yīng)用程序正在運(yùn)行,配置文件可以單獨(dú)被更新
相同的代碼能夠被用于不同的環(huán)境
在Kubernetes中,可以將配置保存在ConfigMaps中,然后可以在將卷作為環(huán)境變量傳入時(shí)將其安裝到容器中。
在ConfigMap中僅保存非敏感配置。對(duì)于敏感信息(例如憑據(jù)),請(qǐng)使用Secret資源。
1.9.2 將Secrets作為卷而不是環(huán)境變量
Secret資源的內(nèi)容應(yīng)作為卷掛載到容器中,而不是作為環(huán)境變量傳遞。
這是為了防止秘密值出現(xiàn)在用于啟動(dòng)容器的命令中,該命令可能由不應(yīng)該訪問秘密值的人員檢查
二 管治
2.1 名稱空間限制
您不應(yīng)允許用戶使用比您事先同意的資源更多的資源。
群集管理員可以設(shè)置約束,以使用配額和限制范圍限制項(xiàng)目中使用的對(duì)象數(shù)量或計(jì)算資源數(shù)量。
詳細(xì)可參考;limit ranges
2.1.1 名稱空間限制范圍
如果為設(shè)置容器資源消耗限制,那么會(huì)出現(xiàn)容器資源爭(zhēng)搶導(dǎo)致其他容器異常狀況發(fā)生,
k8s有兩個(gè)特性來(lái)約束資源使用:ResourceQuota 和 LimitRange.
使用LimitRange對(duì)象,您可以定義資源請(qǐng)求的默認(rèn)值和名稱空間內(nèi)單個(gè)容器的限制。
在該命名空間內(nèi)創(chuàng)建的任何容器(未明確指定請(qǐng)求和限制值)都將分配默認(rèn)值。
2.1.2 名稱控制資源配額
你能夠在名稱空間中通過資源配額限制所有容器資源的總消耗量
定義名稱空間的資源配額會(huì)限制屬于該名稱空間的所有容器可以消耗的CPU,內(nèi)存或存儲(chǔ)資源的總量。
您還可以為其他Kubernetes對(duì)象設(shè)置配額,例如當(dāng)前名稱空間中的Pod數(shù)量。
如果您認(rèn)為有人可以利用您的集群并創(chuàng)建20000 ConfigMap,則可以使用LimitRange來(lái)防止這種情況。
2.2 POD安全策略
遭到破壞的容器
容器使用節(jié)點(diǎn)上不允許的資源,例如進(jìn)程,網(wǎng)絡(luò)或文件系統(tǒng)
一般來(lái)說,應(yīng)該將Pod的功能限制在最低限度。
2.2.1 啟用POD安全策略
例如,您可以使用Kubernetes Pod安全策略來(lái)限制:
訪問主機(jī)進(jìn)程或者網(wǎng)絡(luò)名稱空間
運(yùn)行授權(quán)的容器
容器運(yùn)行時(shí)的用戶
訪問主機(jī)的文件系統(tǒng)
linux能力,Seccomp or SELinux profiles
選擇正確的策略依賴于集群原生的特性,可以參考:Kubernetes Pod Security Policy best practices
2.2.2 禁用特權(quán)容器
在一個(gè)POD中,容器能夠作為特權(quán)模式容器運(yùn)行來(lái)不受限制訪問主機(jī)系統(tǒng)的資源
通常這樣是危險(xiǎn)的,你應(yīng)該給有必要的制定容器可以訪問的等級(jí),
特權(quán)Pod的有效使用案例包括在節(jié)點(diǎn)上使用硬件,例如GPU。
可以參考:learn more about security contexts and privileges containers from this article.
2.2.3 容器使用只讀文件系統(tǒng)
容器中使用只讀文件系統(tǒng)來(lái)強(qiáng)制保障容器的無(wú)狀態(tài)話
這種方式不僅能減輕風(fēng)險(xiǎn)例如熱補(bǔ)丁,而且可以避免避免惡意程序在容器內(nèi)存儲(chǔ)或者操作數(shù)據(jù)的風(fēng)險(xiǎn)。
使用只讀文件系統(tǒng)聽起來(lái)很簡(jiǎn)單,但是實(shí)際還是有一些復(fù)雜
如果你需要寫日志或者存儲(chǔ)一些臨時(shí)文件在一個(gè)臨時(shí)目錄該怎么辦呢,可以參考:running containers securely in production.
2.2.4 避免利用root用戶啟動(dòng)容器
在容器中運(yùn)行一個(gè)進(jìn)程與主機(jī)上運(yùn)行一個(gè)進(jìn)程沒有太大區(qū)別,只不過一些很小的元數(shù)據(jù)在容器中聲明
因此容器中的uid為0的用戶與主機(jī)上的root用戶相同
如果用戶設(shè)法脫離了以root用戶身份在容器中運(yùn)行的應(yīng)用程序,則他們可以使用同一root用戶獲得對(duì)主機(jī)的訪問權(quán)限。
配置容器以使用非特權(quán)用戶是防止特權(quán)升級(jí)攻擊的最佳方法。
詳細(xì)可以參考:article offers some detailed explanation examples of what happens when you run your containers as root.
2.2.5 限制能力
Linux功能使進(jìn)程能夠執(zhí)行許多特權(quán)操作,其中只有root用戶默認(rèn)可以執(zhí)行。
例如,CAP_CHOWN允許進(jìn)程“對(duì)文件UID和GID進(jìn)行任意更改”。
即使您的進(jìn)程不是以root身份運(yùn)行,進(jìn)程也有可能通過提升特權(quán)來(lái)使用那些類似root的功能。
最佳實(shí)踐:
Linux Capabilities: Why They Exist and How They Work
Linux Capabilities In Practice
2.2.6 防止特權(quán)升級(jí)
您應(yīng)該在關(guān)閉特權(quán)升級(jí)的情況下運(yùn)行容器,以防止使用setuid或setgid二進(jìn)制文件提升特權(quán)。
2.3 網(wǎng)絡(luò)策略
容器可以在與其他容器進(jìn)行網(wǎng)絡(luò)通訊,不需要進(jìn)行地址轉(zhuǎn)換
集群中的node節(jié)點(diǎn)可以與其他節(jié)點(diǎn)進(jìn)行網(wǎng)絡(luò)通訊
一個(gè)容器的IP地址始終是相同的,從另一個(gè)容器或其本身看時(shí)是獨(dú)立的。
如果您打算將群集分成較小的塊并在名稱空間之間進(jìn)行隔離,則第一條規(guī)則無(wú)濟(jì)于事。
想象一下您的集群中的用戶是否能夠使用集群中的任何其他服務(wù)。
現(xiàn)在,想象一下如果集群中的惡意用戶要獲得對(duì)集群的訪問權(quán)限,他們可以向整個(gè)集群發(fā)出請(qǐng)求。
要解決此問題,您可以定義如何使用網(wǎng)絡(luò)策略允許Pods在當(dāng)前名稱空間和跨名稱空間中進(jìn)行通信。
2.3.1 啟用網(wǎng)絡(luò)策略
Kubernetes網(wǎng)絡(luò)策略指定Pod組的訪問權(quán)限,就像云中的安全組用于控制對(duì)VM實(shí)例的訪問一樣。
換句話說,它在Kubernetes集群上運(yùn)行的Pod之間創(chuàng)建了防火墻。
可參考:Securing Kubernetes Cluster Networking.
2.3.2 每個(gè)命名空間中都有一個(gè)保守的NetworkPolicy
該存儲(chǔ)庫(kù)包含Kubernetes網(wǎng)絡(luò)策略的各種用例和示例YAML文件,以在您的設(shè)置中利用。如果你想知道
how to drop/restrict traffic to applications running on Kubernetes
2.4 基于角色的訪問控制RBAC
放棄所需的最小權(quán)限是一種常見的做法,但是實(shí)際操作又如何量化最小權(quán)限?
細(xì)粒度的策略提供了更高的安全性,但是需要更多的精力來(lái)進(jìn)行管理。
更大范圍的授權(quán)可以使不必要的API訪問服務(wù)帳戶,但更易于控制。
2.4.1 禁用默認(rèn)服務(wù)帳戶的自動(dòng)掛載
請(qǐng)注意,默認(rèn)的ServiceAccount將自動(dòng)安裝到所有Pod的文件系統(tǒng)中。您可能要禁用它并提供更詳細(xì)的策略。
可以參考:the default ServiceAccount is automatically mounted into the file system of all Pods.
2.4.2 RBAC策略設(shè)置為所需的最少特權(quán)
尋找有關(guān)如何設(shè)置RBAC規(guī)則的好的建議是一項(xiàng)挑戰(zhàn)。在Kubernetes RBAC的3種現(xiàn)實(shí)方法中,您可以找到三種實(shí)用場(chǎng)景和有關(guān)如何入門的實(shí)用建議。
參考;3 realistic approaches to Kubernetes RBAC
2.4.3 RBAC策略是精細(xì)的,不能共享
需求:
允許用戶可以部署,但是不允許去讀secrets
admin應(yīng)該可以訪問所有資源
默認(rèn)情況下,應(yīng)用程序不應(yīng)獲得對(duì)Kubernetes API的寫訪問權(quán)限
對(duì)于某些用途,應(yīng)該可以寫入Kubernetes API。
四個(gè)要求轉(zhuǎn)化為五個(gè)單獨(dú)的角色:
ReadOnly
PowerUser
Operator
Controller
Admin
2.5 自定義策略
例如,您可能要避免從公共互聯(lián)網(wǎng)下載容器,而希望首先批準(zhǔn)這些容器。
也許您有一個(gè)內(nèi)部注冊(cè)表,并且只有此注冊(cè)表中的映像可以部署在您的群集中。
您如何強(qiáng)制只能在群集中部署受信任的容器?沒有針對(duì)此的RBAC政策。
2.5.1 僅允許從已知注冊(cè)表部署容器
您可能要考慮的最常見的自定義策略之一是限制可以在群集中部署的映像。
The following tutorial explains how you can use the Open Policy Agent to restrict not approved images.
2.5.2 強(qiáng)制Ingress主機(jī)名唯一
用戶創(chuàng)建Ingress清單時(shí),可以使用其中的任何主機(jī)名。
但是,您可能希望阻止用戶多次使用相同的主機(jī)名并互相覆蓋。Open Policy Agent的官方文檔包含有關(guān)如何在驗(yàn)證Webhook中檢查Ingress資源的教程。
a tutorial on how to check Ingress resources as part of the validation webhook.
2.5.3 僅在Ingress主機(jī)名中使用批準(zhǔn)的域名
用戶創(chuàng)建Ingress清單時(shí),可以使用其中的任何主機(jī)名。一種
但是,您可能希望阻止用戶使用無(wú)效的主機(jī)名。Open Policy Agent的官方文檔包含有關(guān)如何在驗(yàn)證Webhook中檢查Ingress資源的教程。
三 集群配置
最好的選擇是將群集與標(biāo)準(zhǔn)參考進(jìn)行比較。
對(duì)于Kubernetes,參考是Internet安全中心(CIS)基準(zhǔn)。
3.1 批準(zhǔn)的Kubernetes配置
3.1.1 集群通過CIS基準(zhǔn)測(cè)試
Internet安全中心提供了一些準(zhǔn)則和基準(zhǔn)測(cè)試,以確保代碼安全的最佳實(shí)踐。
他們還維護(hù)了Kubernetes的基準(zhǔn),您可以download from the official website.
kube-bench是一種工具,用于自動(dòng)執(zhí)行CIS Kubernetes基準(zhǔn)測(cè)試并報(bào)告集群中的錯(cuò)誤配置。
[INFO] 1 Master Node Security Configuration [INFO] 1.1 API Server [WARN] 1.1.1 Ensure that the --anonymous-auth argument is set to false (Not Scored) [PASS] 1.1.2 Ensure that the --basic-auth-file argument is not set (Scored) [PASS] 1.1.3 Ensure that the --insecure-allow-any-token argument is not set (Not Scored) [PASS] 1.1.4 Ensure that the --kubelet-https argument is set to true (Scored) [PASS] 1.1.5 Ensure that the --insecure-bind-address argument is not set (Scored) [PASS] 1.1.6 Ensure that the --insecure-port argument is set to 0 (Scored) [PASS] 1.1.7 Ensure that the --secure-port argument is not set to 0 (Scored) [FAIL] 1.1.8 Ensure that the --profiling argument is set to false (Scored)
請(qǐng)注意,無(wú)法使用kube-bench檢查托管集群(例如GKE,EKS和AKS)的主節(jié)點(diǎn)。主節(jié)點(diǎn)由云提供商控制。
3.1.2 禁用元數(shù)據(jù)云提供程序元數(shù)據(jù)API
云平臺(tái)(AWS,Azure,GCE等)通常將本地元數(shù)據(jù)服務(wù)公開給實(shí)例。
默認(rèn)情況下,實(shí)例上運(yùn)行的Pod可以訪問這些API,并且可以包含該節(jié)點(diǎn)的云憑據(jù)或諸如kubelet憑據(jù)之類的置備數(shù)據(jù)。
這些憑據(jù)可用于在群集內(nèi)升級(jí)或升級(jí)到同一帳戶下的其他云服務(wù)。
3.1.3 限制對(duì)Alpha或Beta功能的訪問
Alpha和Beta Kubernetes功能正在積極開發(fā)中,并且可能會(huì)存在限制或錯(cuò)誤,從而導(dǎo)致安全漏洞。
始終評(píng)估Alpha或Beta功能可能提供的價(jià)值,以防對(duì)您的安全狀況造成潛在風(fēng)險(xiǎn)。
如有疑問,請(qǐng)禁用不使用的功能。
3.2 認(rèn)證
kubernetes提供了不同的認(rèn)證策略
Static Tokens:很難使之無(wú)效,應(yīng)避免
Bootstrap Tokens:與上面的靜態(tài)令牌相同
Basic Authentication:通過網(wǎng)絡(luò)以明文形式傳輸憑據(jù)
X509 client certs:需要定期更新和重新分發(fā)客戶端證書
Service Account Tokens:是集群中運(yùn)行的應(yīng)用程序和工作負(fù)載的首選身份驗(yàn)證策略
OpenID Connect (OIDC) Tokens:OIDC與您的身份提供商(例如AD,AWS IAM,GCP IAM等)集成后,為最終用戶提供了最佳的身份驗(yàn)證策略。
更多詳細(xì)策略可參考:in the official documentation.
3.2.1 使用OpenID(OIDC)令牌作為用戶身份驗(yàn)證策略
Kubernetes支持各種身份驗(yàn)證方法,包括OpenID Connect(OIDC)。
OpenID Connect允許單點(diǎn)登錄(SSO)(例如您的Google身份)連接到Kubernetes集群和其他開發(fā)工具。
你不用分別取記憶和管理認(rèn)證,您可能有多個(gè)群集連接到同一OpenID提供程序。
詳細(xì)可以參考:learn more about the OpenID connect in Kubernetes
3.3 RBAC
3.3.1 ServiceAccount令牌僅適用于應(yīng)用程序和控制器
服務(wù)帳戶令牌不應(yīng)該用于嘗試與Kubernetes群集進(jìn)行交互的最終用戶,但對(duì)于在Kubernetes上運(yùn)行的應(yīng)用程序和工作負(fù)載,它們是首選的身份驗(yàn)證策略。
3.4 日志設(shè)定
3.4.1 有一個(gè)日志保留和歸檔策略
您應(yīng)該保留30-45天的歷史日志。
3.4.2 從節(jié)點(diǎn),控制平面,審核中收集日志
從那收集日志?
Nodes(kubelet,container runtime)
控制平面(API server,scheduler,controller manager)
k8s 審計(jì)(對(duì)API服務(wù)器的所有請(qǐng)求)
應(yīng)該收集什么?
應(yīng)用名稱
應(yīng)用實(shí)例
應(yīng)用版本
集群ID
容器名稱
容器運(yùn)行在集群的那個(gè)node節(jié)點(diǎn)上
容器運(yùn)行在那個(gè)pod內(nèi)
名稱空間
3.4.3 在每個(gè)節(jié)點(diǎn)上最好使用守護(hù)程序來(lái)收集日志,而不是在每個(gè)中運(yùn)行sidecars
應(yīng)用程序應(yīng)該登錄到標(biāo)準(zhǔn)輸出,而不是文件。
每個(gè)節(jié)點(diǎn)上的守護(hù)程序可以從容器運(yùn)行時(shí)收集日志(如果記錄到文件,則可能需要每個(gè)pod的sidecar容器)。
3.4.4 提供日志聚合工具
使用日志聚合工具,例如EFK堆棧(Elasticsearch,F(xiàn)luentd,Kibana),DataDog,Sumo Logic,Sysdig,GCP Stackdriver,Azure Monitor,AWS CloudWatch。
審核編輯:黃飛
-
數(shù)據(jù)庫(kù)
+關(guān)注
關(guān)注
7文章
3852瀏覽量
64727 -
容器
+關(guān)注
關(guān)注
0文章
499瀏覽量
22130
原文標(biāo)題:三 集群配置
文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
OpenStack與K8s結(jié)合的兩種方案的詳細(xì)介紹和比較
如何使用kubernetes client-go實(shí)踐一個(gè)簡(jiǎn)單的與K8s交互過程
![如何使用kubernetes client-go<b class='flag-5'>實(shí)踐</b>一個(gè)簡(jiǎn)單的與<b class='flag-5'>K8s</b>交互過程](https://file.elecfans.com/web1/M00/DE/5F/pIYBAGAYxO6AH-XxAAB0jY76Iww004.jpg)
Docker不香嗎為什么還要用K8s
簡(jiǎn)單說明k8s和Docker之間的關(guān)系
K8S集群服務(wù)訪問失敗怎么辦 K8S故障處理集錦
![<b class='flag-5'>K8S</b>集群服務(wù)訪問失敗怎么辦 <b class='flag-5'>K8S</b>故障處理集錦](https://file.elecfans.com/web2/M00/12/E9/poYBAGEu8TeASCueAAAT1AA4nh0921.png)
mysql部署在k8s上的實(shí)現(xiàn)方案
k8s是什么意思?kubeadm部署k8s集群(k8s部署)|PetaExpres
什么是K3s和K8s?K3s和K8s有什么區(qū)別?
k8s生態(tài)鏈包含哪些技術(shù)
![<b class='flag-5'>k8s</b>生態(tài)鏈包含哪些技術(shù)](https://file1.elecfans.com/web2/M00/8F/8C/wKgZomTQXVCAEPtNAAANqN42JQk707.jpg)
K8S落地實(shí)踐經(jīng)驗(yàn)分享
![<b class='flag-5'>K8S</b>落地<b class='flag-5'>實(shí)踐</b>經(jīng)驗(yàn)分享](https://file1.elecfans.com/web2/M00/BA/4F/wKgZomWTh0CAE9H-AAAEuq6Qww8107.jpg)
k8s云原生開發(fā)要求
![<b class='flag-5'>k8s</b>云原生開發(fā)要求](https://file1.elecfans.com/web2/M00/0B/06/wKgaomcZ5XOAO7bVAAGe1drYtZc769.png)
評(píng)論