[toc]
一、HPA與彈性伸縮
1.1 scale
- scale命令可以使用命令行通過控制器調整副本數
kubectl scale --replicas=3 deployment/mysql -n default
1.2 HPA
1.2.1 HPA簡介
HPA(Horizontal Pod Autoscaler)控制器,通過autoscale自動控制在k8s集群中運行的pod數量(水平自動伸縮),需要提前設置pod范圍及觸發條件;k8從1.1版本開始增加了HPA控制器,用于實現基于pod中資源(CPU)利用率進行對pod的自動擴縮容功能的實現,開始版本只能基于Heapster組件實現對CPU利用率作為觸發條件,但是在k8s 1.11版本開始使用Metric Server完成數據采集,然后將采集到的數據通過API(Aggregated API,匯總API),例如metrics.k8s.io、custom.Metrics.k8s.io、external.metric.k8s.io,然后再把數據提供給HPA控制器進行查詢,實現基于某個資源利用率對pod進行擴縮容的目的。
控制管理器默認每隔15s(可以通過 horizontal-pod-autoscaler-sync-period修改)
kube-controller-manager --help | grep horizontal-pod-autoscaler-sync-period 進行查看
HPA控制器訪問metrics-server查到的;kubelet將pod的資源利用率數據收集后,匯報給api-server,api-server將數據寫入etcd中,然后metrics-server通過api-server拿到數據
1.2.2 計算公式
從最基本的角度來看,Pod 水平自動擴縮控制器根據當前指標和期望指標來計算擴縮比例。
期望副本數 = ceil[當前副本數 * (當前指標/期望指標)]
例如,當前度量值為
200m
,目標設定值為100m
,那么由于200.0/100.0 == 2.0
, 副本數量將會翻倍。 如果當前指標為50m
,副本數量將會減半,因為50.0/100.0 == 0.5
。 如果計算出的擴縮比例接近 1.0 (根據--horizontal-pod-autoscaler-tolerance
參數全局配置的容忍值,默認為 0.1), 將會放棄本次擴縮。
1.2.3 伸縮命令
- 命令行
kubectl autoscale rc foo --max=5 --cpu-percent=80
- yaml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
namespace: linux
name: tomcat-app1-podautoscaler
labels:
app: tomcat-app1
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: tomcat-app1-deployment
minReplicas: 2
maxReplicas: 5
targetCPUUtilizationPercentage: 50
1.2.4 部署hpa
- 通過yaml部署
kubectl apply -f hpa.yaml
首次啟動,默認是等5分鐘,開始伸縮;可以設置冷卻期,防止pod剛擴縮容后,又馬上恢復
二、CI/CD
2.1 CI
CI(Continuous Integration)持續集成
2.1.1 gitlab簡介
GitLab是一個用于倉庫管理系統的開源項目,使用Git作為代碼管理工具,并在此基礎上搭建起來的web服務
GitLab和GitHub一樣屬于第三方基于Git開發的產品,免費且開源(基于MIT協議),與GitHub類似,可以注冊用戶,任意提交你的代碼,添加SSHKey等;不同的是,GitLab是可以部署到自己的服務器上,數據庫等一切信息都掌握在自己手上,適合團隊內部寫作開發
簡單來說可以把GitLab看作個人版的GitHub
2.1.2 安裝gitlab
- 安裝相關依賴
yum install -y policycoreutils openssh-server opssh-clients postfix
- 關閉防火墻并設置開機不啟動
systemctl disable firewalld
systemctl stop firewalld
- 啟動ssh服務并設置為開機自啟動
systemctl enable sshd
systemctl start sshd
- 啟動postfix服務并設置為開機自動
systemctl enable postfix
systemctl start postfix
- 下載gitlab包,并安裝
wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-12.4.2-ce.0.el7.x86_64.rpm
rpm -ivh gitlab-ce-12.4.2-ce.0.el7.x86_64.rpm
- 修改gitlab配置
vim /etc/gitlab/gitlab.rb
修改gitlab訪問地址和端口,默認為80
external_url 'http://IP:PORT'
nginx['listen_port'] = PORT
- 重載配置及啟動gitlab
gitlab-ctl reconfigure
gitlab-ctl restart
2.1.3 組、項目和用戶
- 創建組
使用管理員root創建組,一個組里面可以有多個項目分支,可以將開發添加到組里面進行權限設置,不通的組就是公司里不通的開發項目或者服務模塊,不通的組添加不通的角色即可實現對開發成員權限的管理
私有組,只有組里的用戶才可以訪問;公開的組所有人都可以訪問;通常設置為私有
- 創建項目
在上步創建的組中創建項目,圖中標紅方框位置,選擇剛才創建的組,創建私有項目
- 創建用戶
點擊導航欄扳手圖標(Admin Area),點擊Users
點擊New user
密碼會在用戶第一次登陸時重置
項目限制,默認是十萬個,可以自己修改;訪問級別默認是Regular,可以訪問歸屬組和項目,Admin可以訪問所有組、項目和用戶
創建用戶后點擊Edit設置用戶密碼
- 添加用戶到組
點擊導航欄Groups,Explore groups
點擊進去要管理的項目,點擊Members
選擇用戶和相應的權限添加到組
GitLab用戶在組里面有五種不同權限:
Guest:可以創建issue、發表評論、不能讀寫版本庫
Reporter:可以克隆代碼,不能提交;QA、PM可以賦予這個權限
Developer:可以克隆代碼、開發、提交、push;普通開發可以賦予這個權限
Maintainer:可以創建項目、添加tag、保護分支、添加項目成員、編輯項目;核心開發可以賦予這個權限
Owner:可以設置訪問權限(Visibility Level)、刪除項目、遷移項目、管理組成員;開發組組長可以賦予這個權限
2.2 CD
CD(Continuous Delivery)持續交付
2.2.1 jenkins簡介
Jenkins是一個開源軟件項目,是基于java開發的一種持續集成工具,用于監控持續重復的工作,旨在提供一個開發易用的軟件平臺,是軟件項目可以進行持續集成。
功能包括:
持續的軟件版本發布/測試項目
監控外部調用執行的工作
2.2.2 安裝jenkins
- 安裝jdk依賴
yum install -y java-1.8.0-openjdk*
安裝后目錄為/usr/lib/jvm
- 關閉防火墻并設置開機不啟動
systemctl disable firewalld
systemctl stop firewalld
- 安裝jenkins
wget https://mirrors.tuna.tsinghua.edu.cn/jenkins/redhat/jenkins-2.300-1.1.noarch.rpm
rmp -ivh jenkins-2.300-1.1.noarch.rpm
- 修改jenkins配置
vim /etc/sysconfig/jenkins
JENKINS_USER="root"
默認是jenkins用戶,需要創建一個jenkins用戶,用root也可以
JENKINS_PORT="PORT"
- 啟動jenkins并設置為開機自啟動
systemctl start jenkins
systemctl enable jenkins
2.2.3 創建憑證
創建向gitlab拉取代碼時的憑證
可以選擇用戶名密碼,就是gitlab的用戶名密碼,需要用戶有對項目管理的權限,填寫的描述是在選擇認證方式時的提示
2.2.4 創建任務
- 點擊新建任務,創建一個任務
新建任務一般是自由風格(freestyle)、maven、流水線(pipeline)較多,每種類型的構建其實都可以完成一樣的構建過程與結果,只是在操作方式、靈活度等方面有所區別,在實際開發中可以根據自己的需求和習慣來選擇(流水線類型靈活度較高)
點擊新創建的項目
點擊配置,源碼管理選擇Git
填寫git代碼url,選擇相應認證方式;http選擇用戶名密碼認證,ssh選擇密鑰認證;選擇分支
選擇構建方式
點擊立即構建
點擊控制臺輸出,查看構建日志
2.2.5 免密登陸
- 在任意一臺服務器生成密鑰對
ssh-keygen -t rsa
在/root/.ssh目錄下,找到公私鑰對,.pub結尾的是公鑰
- 在gitlab配置公鑰
點擊SSH Keys,填寫公鑰,點擊Add key
- 在jenkins添加私鑰
在添加憑據的位置,類型選擇SSH Username with private key,填寫的描述是選擇憑據時的提示,用戶名是生成公私鑰的用戶,點擊Add,將私鑰粘貼進去
2.2.6 配置mvn
- 在系統配置,全局配置中配置環境變量
添加這幾個環境變量;注意添加主機PATH環境變量,不然在編譯的時候會報錯不能執行命令;"PATH+EXTRA"是固定名字
2.2.7 pipeline
pipeline是一套運行在jenkins上的工作流框架,將原來獨立運行與單個或者多個節點的任務連接起來,實現單個任務難以完成的復雜流程編排和可視化的工作
pipeline優點:
代碼:pipeline以代碼的形式實現,通常被檢入源代碼控制,使團隊能夠編輯,審查和迭代其傳送流程
持久:無論是計劃內的還是計劃外的服務器重啟,pipeline都是可恢復的
可停止:pipeline可接收交互式輸入,以確定是否繼續執行pipeline
多功能:pipeline支持實現世界中復雜的持續交付要求,支持fork/join、循環執行,并行執行任務的功能
可擴展:pipeline插件支持其DSL的自定義擴展,以及與其他插件集成的多個選項
特點:
pipeline腳本是由Groovy語言實現的,支持兩種語法,Declaration(聲明式)和Scripted Pipeline(腳本式)語法
pipeline有兩種創建方法:可在jenkins的Web UI界面中輸入腳本,也可以通過一個jenkinsfile腳本文件放入項目源碼庫中(推薦在jenkins中直接從源代碼控制(SCM)中直接載入jenkinsfile pipeline的方法)
2.3 鏡像升級與回滾
2.3.1 deployment控制器
deployment控制器支持兩種更新策略,默認為滾動更新
- 滾動更新
滾動更新(rollingUpdate)是默認的更新策略,基于新版本鏡像創建新版本pod,然后刪除一部分舊版本pod,然后再創建新版本pod,再刪除一部分舊版本pod,知道舊版本pod刪除完成;滾動更新優勢在于升級過程中不會導致服務不可用,缺點是升級過程中會導致兩個版本在短時間內并存
升級過程是在執行更新操作后k8s會再創建一個新版本的ReplicaSet控制器,在刪除舊版本的ReplicaSet控制器下的pod時,也會在新版本的ReplicaSet控制器下創建新的pod,知道舊版本的pod更新完,再把舊版本的ReplicaSet控制器也回收
在執行滾動更新的同時,為了保證服務的可用性(pod拉取鏡像進行創建并且執行探針探測期間是不可用的),當前控制器內不可用的pod不能超出一定范圍,需要保留一定數量的pod以保證服務可以被客戶端正常訪問
pod可用比例可以通過命令設置
kubectl explain deployment.spec.strategy
deployment.spec.strategy.rollingUpdate.maxSurge:指定在升級期間pod總數可以超出期望的pod數量或者百分比,默認為25%,如果設置10%,就是當前有100個pod,那么升級時最多可以共存110個pod,也就是額外有10%的pod臨時超出ReplicaSet指定的副本數
deployment.spec.strategy.rollingUpdate.maxUnavailable:指定在升級期間最大不可用的pod數量,可以是數值或者百分比,默認是25%,就是當前有100個pod,那么升級時最多可以有25個(25%)pod不可用,即還有75個(75%)pod是可用的
注意:以上兩個值不能同時為0,如果maxUnavailable最大不可用pod為0,maxSurage超出pod數也為0,那么將會導致pod無法進行滾動更新
- 重建更新
重建(recreate)更新是先刪除現有的pod,然后基于新版本的鏡像重建,優勢是同時只有一個版本提供服務,不會產生多版本在線問題,缺點是pod刪除后到pod重建成功之間的時間,服務無法訪問,因此使用較少
- 版本升級
更新鏡像
kubectl -n NAMESPACE set image deployment/DEPLOYMENT CONTAINER_NAME=IMAGE:VERSION --record=true
--record=true可以記錄變更命令,在查看歷史信息命令的CHANGE-CAUSE里顯示
查看歷史信息
kubectl -n NAMESPACE rollout history deployment DEPLOYMENT
rollout有效資源種類包括:deployments、daemonsets、statefulsets
回滾版本
kubectl -n NAMESPACE rollout undo deployment DEPLOYMENT
回滾到上一個版本;再次執行命令的時候,是回滾到當前版本
比如deployment現在三個版本,nging的1.19、1.20、1.21;當前版本是nginx:1.21,上一個版本是nginx:1.20,執行回滾命令會回滾到nginx:1.20,現在對于更新后的版本來說,nginx:1.20是當前版本,上一個版本是nginx:1.21,所以再次執行回滾命令是回滾到nginx:1.21,而不會回滾到nginx:1.19
每次執行回滾命令,當前版本號為現有最大版本號(REVISION)加一,也就是最新版本號
回滾到指定版本
kubectl -n NAMESPACE rollout undo deployment DEPLOYMENT --to-revision=1
回滾到版本號為1的版本,現有最新版本號加1,成為最新的版本(回滾指定的歷史版本號會消失,變成最新版本號)
2.3.2 自動化
gitlab,jenkins,和set images命令,可以實現業務的自動化更新功能(結合shell腳本),如果需要業務回滾,可以使用rollout undo命令
三、親和與污點
3.1 pod創建流程
- 用戶通過kubectl命令行或者dashboard創建pod請求,發給kube-apiserver,kube-apiserver負責鑒權和準入,然后把請求寫入etcd
- 一直監聽kube-apiserver的kube-scheduler按照策略進行調度(nodeSelector、nodeAffinity等),如果沒有聲明策略,會執行默認策略
- kube-scheduler給pod選定node,第一步先過濾掉不符合條件的node(例如node資源不足,不符合pod需求),第二步在可用的多個節點之間進行打分,選擇其中得分最高的節點進行綁定
- kube-scheduler將綁定關系返回給kube-apiserver,由kube-apiserver再把數據寫入etcd
- node節點上一直監聽kube-apiserver的kubelet,如果發現有本機需要創建pod的事件,kubelet會將事件獲取過來,然后在本機調用容器運行時,創建pod
3.2 nodeSelector
基于標簽選擇器,將pod調度到目的節點上
- 打標簽
kubectl label node NODE_IP KEY=VALUE
- 刪除標簽
kubectl label node NODE_IP KEY-
刪除標簽是key后邊加上減號
- depolyment的yaml文件中聲明nodeSelector選擇器
nodeSelector:
KEY: VALUE
層級:deployment.spec.template.spec.nodeSelector
如果有多個標簽時,必須同時滿足,不然pod調度不成功
3.3 nodeName
選定node名字創建pod
- depolyment的yaml文件中聲明nodeName選擇器
spec:
nodeName: 192.168.204.102
層級:deploy.spec.template.spec.nodeName
使用較少
3.4 nodeaAffinity
3.4.1 nodeaAffinity簡介
affinity是kubernetes 1.2版本后引入的新特性,類似于nodeSelector,允許使用者指定一些pod在Node間調度的約束,目前支持兩種形式:
- requiredDuringSchedulingIgnoredDuringExecution
必須滿足pod調度匹配條件,如果不滿足則不進行調度
- preferredDuringSchedulingIgnoredDuringExecution
傾向滿足pod調度匹配條件,不滿足的情況下會調度到不符合條件的node上
IgnoredDuringExecution表示如果在pod運行期間node的標簽發生變化,導致親和性策略不能滿足,也會繼續運行當前pod
- 操作符支持And、In、NotIn、Exists、DoesNotExist、Gt、Lt
- 可以設置軟匹配和硬匹配,在軟匹配下,如果調度器無法匹配節點,仍然將pod調度調度到其他不符合條件的節點
- 可以對pod定義親和性策略,例如,允許一些pod可以或者不可以調度到同一臺node
In:標簽的值存在匹配列表中(匹配成功就調度到目的node,實現node親和)
NotIn:標簽的值不存在指定的匹配列表中(不會調度到目的node,實現反親和)
Gt:標簽的值大于某個值(字符串)
Lt:標簽的值小于某個值(字符串)
Exists:指定的標簽存在
注:如果定義一個nodeSelectorTerms(條件)中通過一個matchExpressions(匹配表達式)基于列表指定了多個條件,則只要滿足其中一個條件,就會被調度到相應的節點上。
如果定義一個nodeSelectorTerms中都通過一個matchExpressions(匹配表達式)指定key匹配多個條件,則所有的條件都必須滿足才會調度到相應節點,即and關系。
3.4.2 親和性硬策略
requiredDuringSchedulingIgnoredDuringExecution即硬策略
- depolyment的yaml文件中聲明Affinity選擇器硬策略,多個matchExpressions
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions: #匹配條件1,多個values可以調度
- key: KEY1
operator: In
values:
- VALUE1 # 只有一個value匹配成功也可以調度
- VALUE2
- matchExpressions: #匹配條件2,多個matchExpressions,任意一個matchExpressions的values中有一個value匹配成功就可以調度
- key: KEY2
operator: In
values:
- VALUE3 #即使這兩個條件都匹配不上也可以調度
- VALUE4
層級:deployment.spec.template.spec.affinity
多個matchExpressions,任意一個標簽的任意一個值匹配成功就可以
- depolyment的yaml文件中聲明Affinity選擇器硬策略,多個key
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions: #匹配條件1
- key: KEY1
operator: In
values:
- VALUE1
- VALUE2 #同個key的多個value只有有一個匹配成功就行
- key: KEY2 #條件1和條件2必須同時滿足,否則不調度
operator: In
values:
- VALUE3
層級:deployment.spec.template.spec.affinity
多個key,都滿足條件才可以
如果調度失敗會報錯:
Warning FailedScheduling 45s default-scheduler 0/3 nodes are available: 3 node(s) didn't match Pod's node affinity/selector
3.4.3 親和性軟策略
preferredDuringSchedulingIgnoredDuringExecution即軟策略
- depolyment的yaml文件中聲明Affinity選擇器軟策略
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: KEY1
operator: In
values:
- VALUE1
- weight: 60
preference:
matchExpressions:
- key: KEY2
operator: In
values:
- VALUE2
層級:deployment.spec.template.spec.affinity
軟策略中可以設置weight(權重),優先匹配權重高的key
軟策略即使所有的key匹配都不成功,也會可以成功調度到node上
3.4.4 親和性結合使用
硬策略和軟策略結合使用
- depolyment的yaml文件中聲明Affinity選擇器硬策略和軟策略結合使用
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: #硬限制
nodeSelectorTerms:
- matchExpressions: #硬匹配條件1
- key: "kubernetes.io/role"
operator: NotIn
values:
- "master" #硬性匹配key 的值kubernetes.io/role不包含master的節點,即絕對不會調度到master節點(node反親和)
preferredDuringSchedulingIgnoredDuringExecution: #軟限制
- weight: 80
preference:
matchExpressions:
- key: project
operator: In
values:
- magedu
- weight: 100
preference:
matchExpressions:
- key: disktype
operator: In
values:
- ssd
層級:deployment.spec.template.spec.affinity
首先匹配硬策略,然后根據權重匹配軟策略
3.4.5 反親和性
operator為NotIn,即為反親和性
- depolyment的yaml文件中聲明Affinity選擇器反親和性
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions: #匹配條件1
- key: disktype
operator: NotIn
values:
- hdd #絕對不會調度到hdd的節點
層級:deployment.spec.template.spec.affinity
不會調度到NotIn聲明的鍵值對的node上
3.5 podAffinity
3.5.1 podAffinity簡介
pod親和性與反親和性可以基于已經在節點上運行的pod標簽,約束新創建的pod調度的目的節點,注意不是node標簽,是pod的標簽;pod親和性與反親和性可以通過LabelSelector選擇namespace,是應為pod是命名空間限定的,而node不屬于任何namespace
目前支持兩種形式:
- requiredDuringSchedulingIgnoredDuringExecution
硬策略
- preferredDuringSchedulingIgnoredDuringExecution
軟策略
Pod親和性與反親和性操作符:In、NotIn、Exists、DoesNotExists
對于pod親和性和反親和性而言,硬策略和軟策略中的topoloygKey不允許為空
對于硬策略要求的pod反親和性,準入控制器LimitPodHardAntiAffinityTopology被引入以確保topologyKey只能是kubernetes.io/hostname;如果希望topologyKey可以用于其他定制拓撲邏輯,可以更改準入控制器或者禁用。
3.5.2 親和性軟策略
- depolyment的yaml文件中聲明Affinity選擇器軟策略pod親和性
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: KEY
operator: In
values:
- VALUE
topologyKey: kubernetes.io/hostname
namespaces:
- linux
層級:deployment.spec.template.spec.affinity
匹配鍵為KEY,值為VALUE的pod標簽,優先調度到匹配成功的pod所在的節點上
3.5.3 親和性硬策略
- depolyment的yaml文件中聲明Affinity選擇器硬策略pod親和性
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: KEY
operator: In
values:
- VALUE
topologyKey: "kubernetes.io/hostname"
namespaces:
- linux
層級:deployment.spec.template.spec.affinity
匹配鍵為KEY,值為VALUE的pod標簽,必須調度到匹配成功的pod所在的節點上
3.5.4 反親和硬策略
- depolyment的yaml文件中聲明Affinity選擇器硬策略pod反親和性
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: KEY
operator: In
values:
- VALUE
topologyKey: "kubernetes.io/hostname"
namespaces:
- linux
層級:deployment.spec.template.spec.affinity
關鍵字為podAntiAffinity,node親和沒有這個選項
鍵為KEY,值為VALUE的pod標簽,不會調度到匹配成功的pod所在的節點上
3.5.5 反親和軟策略
- depolyment的yaml文件中聲明Affinity選擇器軟策略pod反親和性
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: LINUX
operator: In
values:
- VALUE
topologyKey: kubernetes.io/hostname
namespaces:
- linux
層級:deployment.spec.template.spec.affinity
鍵為KEY,值為VALUE的pod標簽,優先不調度到匹配成功的pod所在的節點上
3.6 Taints和Tolerations
3.6.1 taints簡介
- 污點(taints)用于node節點排斥pod調度,與親和和作用是完全相反的,即taint的node和pod是排斥調度關系
- 容忍(toleration)用于pod容忍node節點的污點信息,即node有污點信息也會將新的pod調度到該node
https://kubernetes.io/zh/docs/concepts/scheduling-eviction/taint-and-toleration/
3.6.2 污點設置與取消
- 給nodes設置污點
kubectl taint node NODE_IP key1=value1:NoSchedule
污點類型:
NoSchedule:表示k8s不會把pod調度到具有污點的node上
PreferNoSchedule:表示k8s優先不調度到具有污點的node上
NoExecute:表示k8s不會把pod調度到具有污點的node上,同時會把node上已經存在的pod強制驅逐出去
- 取消污點
kubectl taint node NODE_IP key1:NoSchedule-
3.6.3 tolerations簡介
- tolerations(容忍)定義pod的容忍度,可以調度至含有污點的node。
- 容忍基于operator的匹配污點
operator有兩種
Exists:容忍度不需要value二十直接匹配污點類型
Equal:需要指定value并且value值等于tolerations的key
3.6.4 容忍設置
- 設置容忍
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
層級:deployment.spec.template.spec.tolerations
匹配key、value、effect的值,匹配成功,可以容忍污點(優先調度到沒有污點的節點)
3.6 驅逐
3.6.1 驅逐簡介
驅逐(eviction,節點驅逐),用于當node節點資源不足的時候自動將pod進行強制驅逐,以保證當期node節點的正常運行。k8s基于QoS(服務質量等級)驅逐pod,QoS等級包括:
- Guaranteed:limits和requests相等(最后驅逐)
- Burstable:limits高于requests(次之)
- BestEffort:沒有限制,即resources為空(最先驅逐)
當宿主機資源不足時,pod還在向宿主機申請資源,宿主機內核為了保證正常運行,會把占用資源較多的進程殺掉,以保證主機能正常運行,殺掉進程之后,就會觸發驅逐(pod狀態eviction),pod掛了之后,kube-controller-manager會在別的主機重建
kubelet有默認值,即使沒配置,也會驅逐;如果resources配置不合理,pod有可能會被反復驅逐
- kube-controller-manager實現eviction:node宕機后驅逐
- kubelet實現eviction:基于node負載、資源利用率等
3.6.2 驅逐條件
- 軟驅逐
軟驅逐不會立即驅逐pod,可以自定義寬限期,在條件持續到寬限期限還沒有恢復,kubelet再強制殺死pod并觸發驅逐
eviction-signal:kubelet捕獲node節點信號,進行判斷是否驅逐,比如通過cgoupfs獲取memory.available的值
operator:基于預算符比對條件是否匹配資源使用情況
quantity:獲取node節點資源使用率進行驅逐,可以使用百分比或者單位指定,如內存1Gi等
eviction-soft:軟驅逐條件,如memory.available<1.5Gi,如果驅逐條件持續時長超過指定的寬限期,會觸發pod驅逐
eviction-soft-grace-period:驅逐寬限期,如memory.available=1m30s,定義軟驅逐條件在觸發pod驅逐之前時長
eviction-max-pod-grace-period:在滿足軟驅逐條件而終止pod時的最大允許寬限期(以秒為單位)
- 硬驅逐
硬驅逐條件沒有寬限期,當達到硬驅逐條件時,kubelet會強制立即殺死pod并驅逐
kubelet具有以下默認硬驅逐條件(可以自行跳轉):
imagefs.available<15%
memory.available<100Mi
nodefs.available<10%
nodefs.inodesFree<5%查看kubelet配置中硬驅逐配置:
cat /etc/systemd/system/kubelet.service cat /var/lib/kubelet/config.yaml
配置如下:
eventBurst: 10
eventRecordQPS: 5
evictionHard:
imagefs.available: 15%
memory.available: 300Mi
nodefs.available: 10%
nodefs.inodesFree: 5%(宿主機節點)
四、Prometheus
4.1 監控簡介
監控的重要性:通過業務監控系統,全面掌握業務環境的運行狀態,通過白盒監控能夠提前預知業務瓶頸,通過黑盒監控能夠第一時間發現業務故障并通過告警通告運維人員進行緊急恢復,從而將業務影響降到最低。
黑盒監控:關注實時的狀態,一般都是正在發生的事件,比如nginx web界面打開報錯503等,即黑盒監控重點在于能對正在發生的故障進行通知告警
白盒監控:關注的是原因,也就是系統內部暴露的一些指標數據,比如nginx后端服務器響應時間長等
監控系統需要能夠有效的支持白盒監控和黑盒監控,通過白盒監控能夠了解內部的運行狀態,以及對監控指標的觀察,能夠預判可能出現的潛在問題,從而對潛在的不確定因素進行提前優化并避免問題的發生;通過黑盒監控(如HTTP探針、TCP探針)可以在系統或服務發生故障時快速通知相關人員進行處理
通過完善的監控體系,達到以下目的:
長期趨勢分析:通過對監控樣本數據的持續收集和統計,對監控指標進行長期趨勢分析。例如,通過對磁盤空間增長率的判斷,我們可以提前預測在未來什么時間點需要對資源進行擴容
對照分析:兩個版本的系統運行資源使用情況的差異性,在不同容量情況下系統的并發和負載對比
告警:當系統出現或者即將出現故障時,監控系統迅速通知管理員,從而針對告警內容進行快速的處理
故障分析與定位:當問題發生后,需要對問題進行調查和處理;通過對監控和歷史數據的分析,找到并解決根源問題
數據可視化:通過可視化儀表盤能夠直接獲取系統的運行狀態、資源使用情況、以及服務運行狀態等直觀的信息
4.2 常用監控軟件
開源軟件監控:cacti、nagios、zabbix、smokeping、open-falcon、nightingale、prometheus等
- Cacti
https://github.com/Cacti/cacti
cacti是基于LAMP平臺展現的網絡流量監測及分析工具,通過SNMP技術或自定義腳本從目標設備、主機獲取監控指標信息;其次進行數據存儲,調用模板將數據存到數據庫,使用rrdtool存儲和更新數據,通過rrdtool繪制結果圖形;最后進行數據展現,通過web方式將監控結果呈現出來,常用于在數據中心監控網絡設備。
- Nagios
Nagios是用來監視系統和網絡的開源應用軟件,利用其眾多的插件實現對本機和遠端服務的監控,當被監控對象發生異常時,會及時向管理員告警,提供一批預設好的監控插件,用戶可以調用,也可以自定義shell腳本來監控服務,適合各企業的業務監控,可通過web頁面顯示監控對象狀態、日志、告警信息,分層告警機制及自定義監控相對薄弱。
- SmokePing
https://www.oetiker.ch/home/oss-2/projekte/smokeping/
Somkeping是一款用于網絡性能檢測的開源監控軟件,主要用于對IDC的網絡狀況、網絡質量、穩定性等做檢測,通過rrdtool制圖,展示網絡的時延情況。
- open-falcon
https://github.com/XiaoMi/open-falcon
小米公司開源的監控軟件,open-falcon(獵鷹),監控能力和性能較強
- Nightingale
夜鶯( Nightingale )是一款經過大規模生產環境驗證的、分布式高性能的運維監控系統,由滴滴基于open-falcon二次開發后開源出來的分布式監控系統
- Zabbix
目前使用較多的開源監控軟件,可橫向擴展,自定義監控項,支持多種監控方式,可監控網絡與服務等
zabbix 6.0支持監控kubernetes(centos系統只有8以上支持)
- prometheus
https://github.com/prometheus/prometheus
針對容器環境的開源監控軟件
商業監控解決方案
- 監控寶
- 聽云
4.3 Prometheus簡介
prometheus是基于go語言開發的一套開源的監控、報警和時間序列數據庫的組合,是有SoundCloud公司開發的開源監控系統,prometheus于2016年加入CNCF(Cloud Native Computing Foundation,云原生計算基金會),于2018年8月9日成為繼kubernetes之后畢業的第二個項目,prometheus在容器和微服務領域得到了廣泛的應用。
特點如下:
使用key-value的多維度(多個角度、層面)格式保存數據
使用時序數據庫
支持第三方Dashboard實現更好的圖形界面,如grafana(grafana 2.5.0版本及以上)
組件模塊化
不需要依賴存儲,數據可以本地保存,也可以遠程保存
平均每個采樣點僅占3.5bytes,且一個Prometheus Server可以處理數百萬級別的metrics指標數據
支持服務自動化發現(基于consul等方式動態發現被監控的目標服務)
強大的數據查詢語句(PoemQL,Prometheus Query Language)
數據可以直接進行算術運算
易于橫向伸縮
眾多官方和第三方的exporter實現不通的指標數據收集
容器監控的實現方式對比虛擬機或物理機來說,有較大的區別,比如容器在k8s環境中可以任意橫向擴容與縮容,那么就需要監控服務能夠自動對新創建的容器進行監控,當容器刪除后,有能夠及時的從監控服務總刪除,而傳統的zabbix的監控方式需要在每個容器中安裝啟動agent,并且在容器自動發現注冊及模板關聯方面并沒有比較好的實現方式。
Prometheus包含以下組件:
prometheus server:主服務,接受外部http請求,收集、存儲與查詢數據等
prometheus targets:靜態收集的目標服務數據
service discovery:動態發現服務
prometheus alerting:報警通知
push gateway:數據收集代理服務器(類似于zabbix proxy)
data visualization and exporter:數據可視化與數據導出(訪問客戶端)
4.4 安裝
4.4.1 docker安裝
docker run -p 9090:9090 prom/prometheus
官方示例需要指定配置文件掛載路徑,也可以不掛載,直接跑起來
4.4.2 operator安裝
github上對比k8s版本,找到合適的版本,這里以k8s v1.22.2為例,operator版本為0.9
git clone -b release-0.9 https://github.com/prometheus-operator/kube-prometheus.git
- 首先到kube-prometheus/manifests/setup目錄下執行
kubectl apply -f .
- 然后后退一層目錄,到kube-prometheus/manifests目錄下執行
kubectl apply -f .
下載后需要修改k8s.gcr.io/kube-state-metrics/kube-state-metrics:v2.1.1和k8s.gcr.io/prometheus-adapter/prometheus-adapter:v0.9.0的鏡像,這google官方的倉庫,訪問不了,可以去docker官方鏡像倉庫找到替換下
- 修改prometheus-service.yaml文件,端口類型改成NodePort類型,重新執行
kubectl apply -f prometheus-service.yaml
- 修改grafana-service.yaml文件,端口類型改成NodePort類型,重新執行
kubectl apply -f grafana-service.yaml