k8s伸縮與親和

[toc]

一、HPA與彈性伸縮

1.1 scale

  • scale命令可以使用命令行通過控制器調(diào)整副本數(shù)
kubectl scale --replicas=3 deployment/mysql -n default

1.2 HPA

1.2.1 HPA簡介

HPA(Horizontal Pod Autoscaler)控制器,通過autoscale自動控制在k8s集群中運行的pod數(shù)量(水平自動伸縮),需要提前設(shè)置pod范圍及觸發(fā)條件;k8從1.1版本開始增加了HPA控制器,用于實現(xiàn)基于pod中資源(CPU)利用率進行對pod的自動擴縮容功能的實現(xiàn),開始版本只能基于Heapster組件實現(xiàn)對CPU利用率作為觸發(fā)條件,但是在k8s 1.11版本開始使用Metric Server完成數(shù)據(jù)采集,然后將采集到的數(shù)據(jù)通過API(Aggregated API,匯總API),例如metrics.k8s.io、custom.Metrics.k8s.io、external.metric.k8s.io,然后再把數(shù)據(jù)提供給HPA控制器進行查詢,實現(xiàn)基于某個資源利用率對pod進行擴縮容的目的。

控制管理器默認每隔15s(可以通過 horizontal-pod-autoscaler-sync-period修改)

kube-controller-manager --help | grep horizontal-pod-autoscaler-sync-period 進行查看

HPA控制器訪問metrics-server查到的;kubelet將pod的資源利用率數(shù)據(jù)收集后,匯報給api-server,api-server將數(shù)據(jù)寫入etcd中,然后metrics-server通過api-server拿到數(shù)據(jù)

1.2.2 計算公式

從最基本的角度來看,Pod 水平自動擴縮控制器根據(jù)當(dāng)前指標和期望指標來計算擴縮比例。

期望副本數(shù) = ceil[當(dāng)前副本數(shù) * (當(dāng)前指標/期望指標)]

例如,當(dāng)前度量值為 200m,目標設(shè)定值為 100m,那么由于 200.0/100.0 == 2.0, 副本數(shù)量將會翻倍。 如果當(dāng)前指標為 50m,副本數(shù)量將會減半,因為50.0/100.0 == 0.5。 如果計算出的擴縮比例接近 1.0 (根據(jù)--horizontal-pod-autoscaler-tolerance 參數(shù)全局配置的容忍值,默認為 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分鐘,開始伸縮;可以設(shè)置冷卻期,防止pod剛擴縮容后,又馬上恢復(fù)

二、CI/CD

2.1 CI

CI(Continuous Integration)持續(xù)集成

2.1.1 gitlab簡介

https://about.gitlab.com/

GitLab是一個用于倉庫管理系統(tǒng)的開源項目,使用Git作為代碼管理工具,并在此基礎(chǔ)上搭建起來的web服務(wù)

GitLab和GitHub一樣屬于第三方基于Git開發(fā)的產(chǎn)品,免費且開源(基于MIT協(xié)議),與GitHub類似,可以注冊用戶,任意提交你的代碼,添加SSHKey等;不同的是,GitLab是可以部署到自己的服務(wù)器上,數(shù)據(jù)庫等一切信息都掌握在自己手上,適合團隊內(nèi)部寫作開發(fā)

簡單來說可以把GitLab看作個人版的GitHub

2.1.2 安裝gitlab

  • 安裝相關(guān)依賴
yum install -y policycoreutils openssh-server opssh-clients postfix
  • 關(guān)閉防火墻并設(shè)置開機不啟動
systemctl disable firewalld
systemctl stop firewalld
  • 啟動ssh服務(wù)并設(shè)置為開機自啟動
systemctl enable sshd
systemctl start sshd
  • 啟動postfix服務(wù)并設(shè)置為開機自動
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 組、項目和用戶

  • 創(chuàng)建組

使用管理員root創(chuàng)建組,一個組里面可以有多個項目分支,可以將開發(fā)添加到組里面進行權(quán)限設(shè)置,不通的組就是公司里不通的開發(fā)項目或者服務(wù)模塊,不通的組添加不通的角色即可實現(xiàn)對開發(fā)成員權(quán)限的管理

1646185133776.png

私有組,只有組里的用戶才可以訪問;公開的組所有人都可以訪問;通常設(shè)置為私有

  • 創(chuàng)建項目
1646185342798.png

在上步創(chuàng)建的組中創(chuàng)建項目,圖中標紅方框位置,選擇剛才創(chuàng)建的組,創(chuàng)建私有項目

  • 創(chuàng)建用戶

點擊導(dǎo)航欄扳手圖標(Admin Area),點擊Users

1646185877988.png

點擊New user

1646186020335.png

密碼會在用戶第一次登陸時重置

1646186095509.png

項目限制,默認是十萬個,可以自己修改;訪問級別默認是Regular,可以訪問歸屬組和項目,Admin可以訪問所有組、項目和用戶

創(chuàng)建用戶后點擊Edit設(shè)置用戶密碼

1646186348591.png
1646186389583.png
  • 添加用戶到組

點擊導(dǎo)航欄Groups,Explore groups

1646186508814.png

點擊進去要管理的項目,點擊Members

1646186615114.png

選擇用戶和相應(yīng)的權(quán)限添加到組

1646186796939.png

GitLab用戶在組里面有五種不同權(quán)限:

Guest:可以創(chuàng)建issue、發(fā)表評論、不能讀寫版本庫

Reporter:可以克隆代碼,不能提交;QA、PM可以賦予這個權(quán)限

Developer:可以克隆代碼、開發(fā)、提交、push;普通開發(fā)可以賦予這個權(quán)限

Maintainer:可以創(chuàng)建項目、添加tag、保護分支、添加項目成員、編輯項目;核心開發(fā)可以賦予這個權(quán)限

Owner:可以設(shè)置訪問權(quán)限(Visibility Level)、刪除項目、遷移項目、管理組成員;開發(fā)組組長可以賦予這個權(quán)限

2.2 CD

CD(Continuous Delivery)持續(xù)交付

2.2.1 jenkins簡介

Jenkins是一個開源軟件項目,是基于java開發(fā)的一種持續(xù)集成工具,用于監(jiān)控持續(xù)重復(fù)的工作,旨在提供一個開發(fā)易用的軟件平臺,是軟件項目可以進行持續(xù)集成。

功能包括:

持續(xù)的軟件版本發(fā)布/測試項目

監(jiān)控外部調(diào)用執(zhí)行的工作

2.2.2 安裝jenkins

  • 安裝jdk依賴
yum install -y java-1.8.0-openjdk*

安裝后目錄為/usr/lib/jvm

  • 關(guān)閉防火墻并設(shè)置開機不啟動
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用戶,需要創(chuàng)建一個jenkins用戶,用root也可以

JENKINS_PORT="PORT"

  • 啟動jenkins并設(shè)置為開機自啟動
systemctl start jenkins
systemctl enable jenkins

2.2.3 創(chuàng)建憑證

創(chuàng)建向gitlab拉取代碼時的憑證

1646188588490.png

可以選擇用戶名密碼,就是gitlab的用戶名密碼,需要用戶有對項目管理的權(quán)限,填寫的描述是在選擇認證方式時的提示

2.2.4 創(chuàng)建任務(wù)

  • 點擊新建任務(wù),創(chuàng)建一個任務(wù)
1646188951167.png
1646189008169.png

新建任務(wù)一般是自由風(fēng)格(freestyle)、maven、流水線(pipeline)較多,每種類型的構(gòu)建其實都可以完成一樣的構(gòu)建過程與結(jié)果,只是在操作方式、靈活度等方面有所區(qū)別,在實際開發(fā)中可以根據(jù)自己的需求和習(xí)慣來選擇(流水線類型靈活度較高)

點擊新創(chuàng)建的項目

1646189183179.png

點擊配置,源碼管理選擇Git

1646189652044.png

填寫git代碼url,選擇相應(yīng)認證方式;http選擇用戶名密碼認證,ssh選擇密鑰認證;選擇分支

選擇構(gòu)建方式

1646190125783.png

點擊立即構(gòu)建

1646189833246.png

點擊控制臺輸出,查看構(gòu)建日志

1646189922207.png

2.2.5 免密登陸

  • 在任意一臺服務(wù)器生成密鑰對
ssh-keygen -t rsa

在/root/.ssh目錄下,找到公私鑰對,.pub結(jié)尾的是公鑰

  • 在gitlab配置公鑰
1646190494474.png

點擊SSH Keys,填寫公鑰,點擊Add key

1646190873978.png
  • 在jenkins添加私鑰
1646191159269.png

在添加憑據(jù)的位置,類型選擇SSH Username with private key,填寫的描述是選擇憑據(jù)時的提示,用戶名是生成公私鑰的用戶,點擊Add,將私鑰粘貼進去

2.2.6 配置mvn

  • 在系統(tǒng)配置,全局配置中配置環(huán)境變量
1646191651546.png
1646191730308.png

添加這幾個環(huán)境變量;注意添加主機PATH環(huán)境變量,不然在編譯的時候會報錯不能執(zhí)行命令;"PATH+EXTRA"是固定名字

2.2.7 pipeline

pipeline是一套運行在jenkins上的工作流框架,將原來獨立運行與單個或者多個節(jié)點的任務(wù)連接起來,實現(xiàn)單個任務(wù)難以完成的復(fù)雜流程編排和可視化的工作

pipeline優(yōu)點:

代碼:pipeline以代碼的形式實現(xiàn),通常被檢入源代碼控制,使團隊能夠編輯,審查和迭代其傳送流程

持久:無論是計劃內(nèi)的還是計劃外的服務(wù)器重啟,pipeline都是可恢復(fù)的

可停止:pipeline可接收交互式輸入,以確定是否繼續(xù)執(zhí)行pipeline

多功能:pipeline支持實現(xiàn)世界中復(fù)雜的持續(xù)交付要求,支持fork/join、循環(huán)執(zhí)行,并行執(zhí)行任務(wù)的功能

可擴展:pipeline插件支持其DSL的自定義擴展,以及與其他插件集成的多個選項

特點:

pipeline腳本是由Groovy語言實現(xiàn)的,支持兩種語法,Declaration(聲明式)和Scripted Pipeline(腳本式)語法

pipeline有兩種創(chuàng)建方法:可在jenkins的Web UI界面中輸入腳本,也可以通過一個jenkinsfile腳本文件放入項目源碼庫中(推薦在jenkins中直接從源代碼控制(SCM)中直接載入jenkinsfile pipeline的方法)

2.3 鏡像升級與回滾

2.3.1 deployment控制器

deployment控制器支持兩種更新策略,默認為滾動更新

  • 滾動更新

滾動更新(rollingUpdate)是默認的更新策略,基于新版本鏡像創(chuàng)建新版本pod,然后刪除一部分舊版本pod,然后再創(chuàng)建新版本pod,再刪除一部分舊版本pod,知道舊版本pod刪除完成;滾動更新優(yōu)勢在于升級過程中不會導(dǎo)致服務(wù)不可用,缺點是升級過程中會導(dǎo)致兩個版本在短時間內(nèi)并存

升級過程是在執(zhí)行更新操作后k8s會再創(chuàng)建一個新版本的ReplicaSet控制器,在刪除舊版本的ReplicaSet控制器下的pod時,也會在新版本的ReplicaSet控制器下創(chuàng)建新的pod,知道舊版本的pod更新完,再把舊版本的ReplicaSet控制器也回收

在執(zhí)行滾動更新的同時,為了保證服務(wù)的可用性(pod拉取鏡像進行創(chuàng)建并且執(zhí)行探針探測期間是不可用的),當(dāng)前控制器內(nèi)不可用的pod不能超出一定范圍,需要保留一定數(shù)量的pod以保證服務(wù)可以被客戶端正常訪問

pod可用比例可以通過命令設(shè)置

kubectl explain deployment.spec.strategy

deployment.spec.strategy.rollingUpdate.maxSurge:指定在升級期間pod總數(shù)可以超出期望的pod數(shù)量或者百分比,默認為25%,如果設(shè)置10%,就是當(dāng)前有100個pod,那么升級時最多可以共存110個pod,也就是額外有10%的pod臨時超出ReplicaSet指定的副本數(shù)

deployment.spec.strategy.rollingUpdate.maxUnavailable:指定在升級期間最大不可用的pod數(shù)量,可以是數(shù)值或者百分比,默認是25%,就是當(dāng)前有100個pod,那么升級時最多可以有25個(25%)pod不可用,即還有75個(75%)pod是可用的

注意:以上兩個值不能同時為0,如果maxUnavailable最大不可用pod為0,maxSurage超出pod數(shù)也為0,那么將會導(dǎo)致pod無法進行滾動更新

  • 重建更新

重建(recreate)更新是先刪除現(xiàn)有的pod,然后基于新版本的鏡像重建,優(yōu)勢是同時只有一個版本提供服務(wù),不會產(chǎn)生多版本在線問題,缺點是pod刪除后到pod重建成功之間的時間,服務(wù)無法訪問,因此使用較少

  • 版本升級

更新鏡像

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

回滾到上一個版本;再次執(zhí)行命令的時候,是回滾到當(dāng)前版本

比如deployment現(xiàn)在三個版本,nging的1.19、1.20、1.21;當(dāng)前版本是nginx:1.21,上一個版本是nginx:1.20,執(zhí)行回滾命令會回滾到nginx:1.20,現(xiàn)在對于更新后的版本來說,nginx:1.20是當(dāng)前版本,上一個版本是nginx:1.21,所以再次執(zhí)行回滾命令是回滾到nginx:1.21,而不會回滾到nginx:1.19

每次執(zhí)行回滾命令,當(dāng)前版本號為現(xiàn)有最大版本號(REVISION)加一,也就是最新版本號

回滾到指定版本

kubectl -n NAMESPACE rollout undo deployment DEPLOYMENT --to-revision=1

回滾到版本號為1的版本,現(xiàn)有最新版本號加1,成為最新的版本(回滾指定的歷史版本號會消失,變成最新版本號)

2.3.2 自動化

gitlab,jenkins,和set images命令,可以實現(xiàn)業(yè)務(wù)的自動化更新功能(結(jié)合shell腳本),如果需要業(yè)務(wù)回滾,可以使用rollout undo命令

三、親和與污點

3.1 pod創(chuàng)建流程

  1. 用戶通過kubectl命令行或者dashboard創(chuàng)建pod請求,發(fā)給kube-apiserver,kube-apiserver負責(zé)鑒權(quán)和準入,然后把請求寫入etcd
  2. 一直監(jiān)聽kube-apiserver的kube-scheduler按照策略進行調(diào)度(nodeSelector、nodeAffinity等),如果沒有聲明策略,會執(zhí)行默認策略
  3. kube-scheduler給pod選定node,第一步先過濾掉不符合條件的node(例如node資源不足,不符合pod需求),第二步在可用的多個節(jié)點之間進行打分,選擇其中得分最高的節(jié)點進行綁定
  4. kube-scheduler將綁定關(guān)系返回給kube-apiserver,由kube-apiserver再把數(shù)據(jù)寫入etcd
  5. node節(jié)點上一直監(jiān)聽kube-apiserver的kubelet,如果發(fā)現(xiàn)有本機需要創(chuàng)建pod的事件,kubelet會將事件獲取過來,然后在本機調(diào)用容器運行時,創(chuàng)建pod

3.2 nodeSelector

基于標簽選擇器,將pod調(diào)度到目的節(jié)點上

  • 打標簽
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調(diào)度不成功

3.3 nodeName

選定node名字創(chuàng)建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間調(diào)度的約束,目前支持兩種形式:

  • requiredDuringSchedulingIgnoredDuringExecution

必須滿足pod調(diào)度匹配條件,如果不滿足則不進行調(diào)度

  • preferredDuringSchedulingIgnoredDuringExecution

傾向滿足pod調(diào)度匹配條件,不滿足的情況下會調(diào)度到不符合條件的node上

IgnoredDuringExecution表示如果在pod運行期間node的標簽發(fā)生變化,導(dǎo)致親和性策略不能滿足,也會繼續(xù)運行當(dāng)前pod

  • 操作符支持And、In、NotIn、Exists、DoesNotExist、Gt、Lt
  • 可以設(shè)置軟匹配和硬匹配,在軟匹配下,如果調(diào)度器無法匹配節(jié)點,仍然將pod調(diào)度調(diào)度到其他不符合條件的節(jié)點
  • 可以對pod定義親和性策略,例如,允許一些pod可以或者不可以調(diào)度到同一臺node

In:標簽的值存在匹配列表中(匹配成功就調(diào)度到目的node,實現(xiàn)node親和)

NotIn:標簽的值不存在指定的匹配列表中(不會調(diào)度到目的node,實現(xiàn)反親和)

Gt:標簽的值大于某個值(字符串)

Lt:標簽的值小于某個值(字符串)

Exists:指定的標簽存在

注:如果定義一個nodeSelectorTerms(條件)中通過一個matchExpressions(匹配表達式)基于列表指定了多個條件,則只要滿足其中一個條件,就會被調(diào)度到相應(yīng)的節(jié)點上。

   如果定義一個nodeSelectorTerms中都通過一個matchExpressions(匹配表達式)指定key匹配多個條件,則所有的條件都必須滿足才會調(diào)度到相應(yīng)節(jié)點,即and關(guān)系。

3.4.2 親和性硬策略

requiredDuringSchedulingIgnoredDuringExecution即硬策略

  • depolyment的yaml文件中聲明Affinity選擇器硬策略,多個matchExpressions
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions: #匹配條件1,多個values可以調(diào)度
              - key: KEY1
                operator: In
                values:
                - VALUE1 # 只有一個value匹配成功也可以調(diào)度
                - VALUE2
            - matchExpressions: #匹配條件2,多個matchExpressions,任意一個matchExpressions的values中有一個value匹配成功就可以調(diào)度
              - key: KEY2
                operator: In
                values:
                - VALUE3  #即使這兩個條件都匹配不上也可以調(diào)度
                - 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必須同時滿足,否則不調(diào)度
                operator: In
                values:
                - VALUE3

層級:deployment.spec.template.spec.affinity

多個key,都滿足條件才可以

如果調(diào)度失敗會報錯:

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

軟策略中可以設(shè)置weight(權(quán)重),優(yōu)先匹配權(quán)重高的key

軟策略即使所有的key匹配都不成功,也會可以成功調(diào)度到node上

3.4.4 親和性結(jié)合使用

硬策略和軟策略結(jié)合使用

  • depolyment的yaml文件中聲明Affinity選擇器硬策略和軟策略結(jié)合使用
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution: #硬限制
            nodeSelectorTerms:
            - matchExpressions: #硬匹配條件1
              - key: "kubernetes.io/role"
                operator: NotIn
                values:
                - "master" #硬性匹配key 的值kubernetes.io/role不包含master的節(jié)點,即絕對不會調(diào)度到master節(jié)點(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

首先匹配硬策略,然后根據(jù)權(quán)重匹配軟策略

3.4.5 反親和性

operator為NotIn,即為反親和性

  • depolyment的yaml文件中聲明Affinity選擇器反親和性
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions: #匹配條件1
              - key: disktype
                operator: NotIn
                values:
                - hdd #絕對不會調(diào)度到hdd的節(jié)點

層級:deployment.spec.template.spec.affinity

不會調(diào)度到NotIn聲明的鍵值對的node上

3.5 podAffinity

3.5.1 podAffinity簡介

pod親和性與反親和性可以基于已經(jīng)在節(jié)點上運行的pod標簽,約束新創(chuàng)建的pod調(diào)度的目的節(jié)點,注意不是node標簽,是pod的標簽;pod親和性與反親和性可以通過LabelSelector選擇namespace,是應(yīng)為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標簽,優(yōu)先調(diào)度到匹配成功的pod所在的節(jié)點上

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標簽,必須調(diào)度到匹配成功的pod所在的節(jié)點上

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

關(guān)鍵字為podAntiAffinity,node親和沒有這個選項

鍵為KEY,值為VALUE的pod標簽,不會調(diào)度到匹配成功的pod所在的節(jié)點上

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標簽,優(yōu)先不調(diào)度到匹配成功的pod所在的節(jié)點上

3.6 Taints和Tolerations

3.6.1 taints簡介

  1. 污點(taints)用于node節(jié)點排斥pod調(diào)度,與親和和作用是完全相反的,即taint的node和pod是排斥調(diào)度關(guān)系
  2. 容忍(toleration)用于pod容忍node節(jié)點的污點信息,即node有污點信息也會將新的pod調(diào)度到該node

https://kubernetes.io/zh/docs/concepts/scheduling-eviction/taint-and-toleration/

3.6.2 污點設(shè)置與取消

  • 給nodes設(shè)置污點
kubectl taint node NODE_IP key1=value1:NoSchedule

污點類型:

NoSchedule:表示k8s不會把pod調(diào)度到具有污點的node上

PreferNoSchedule:表示k8s優(yōu)先不調(diào)度到具有污點的node上

NoExecute:表示k8s不會把pod調(diào)度到具有污點的node上,同時會把node上已經(jīng)存在的pod強制驅(qū)逐出去

  • 取消污點
kubectl taint node NODE_IP key1:NoSchedule-

3.6.3 tolerations簡介

  1. tolerations(容忍)定義pod的容忍度,可以調(diào)度至含有污點的node。
  2. 容忍基于operator的匹配污點

operator有兩種

Exists:容忍度不需要value二十直接匹配污點類型

Equal:需要指定value并且value值等于tolerations的key

3.6.4 容忍設(shè)置

  • 設(shè)置容忍
      tolerations:
      - key: "key1"
        operator: "Equal"
        value: "value1"
        effect: "NoSchedule"

層級:deployment.spec.template.spec.tolerations

匹配key、value、effect的值,匹配成功,可以容忍污點(優(yōu)先調(diào)度到?jīng)]有污點的節(jié)點)

3.6 驅(qū)逐

3.6.1 驅(qū)逐簡介

驅(qū)逐(eviction,節(jié)點驅(qū)逐),用于當(dāng)node節(jié)點資源不足的時候自動將pod進行強制驅(qū)逐,以保證當(dāng)期node節(jié)點的正常運行。k8s基于QoS(服務(wù)質(zhì)量等級)驅(qū)逐pod,QoS等級包括:

  1. Guaranteed:limits和requests相等(最后驅(qū)逐)
  2. Burstable:limits高于requests(次之)
  3. BestEffort:沒有限制,即resources為空(最先驅(qū)逐)

當(dāng)宿主機資源不足時,pod還在向宿主機申請資源,宿主機內(nèi)核為了保證正常運行,會把占用資源較多的進程殺掉,以保證主機能正常運行,殺掉進程之后,就會觸發(fā)驅(qū)逐(pod狀態(tài)eviction),pod掛了之后,kube-controller-manager會在別的主機重建

kubelet有默認值,即使沒配置,也會驅(qū)逐;如果resources配置不合理,pod有可能會被反復(fù)驅(qū)逐

  • kube-controller-manager實現(xiàn)eviction:node宕機后驅(qū)逐
  • kubelet實現(xiàn)eviction:基于node負載、資源利用率等

3.6.2 驅(qū)逐條件

  • 軟驅(qū)逐

軟驅(qū)逐不會立即驅(qū)逐pod,可以自定義寬限期,在條件持續(xù)到寬限期限還沒有恢復(fù),kubelet再強制殺死pod并觸發(fā)驅(qū)逐

eviction-signal:kubelet捕獲node節(jié)點信號,進行判斷是否驅(qū)逐,比如通過cgoupfs獲取memory.available的值

operator:基于預(yù)算符比對條件是否匹配資源使用情況

quantity:獲取node節(jié)點資源使用率進行驅(qū)逐,可以使用百分比或者單位指定,如內(nèi)存1Gi等

eviction-soft:軟驅(qū)逐條件,如memory.available<1.5Gi,如果驅(qū)逐條件持續(xù)時長超過指定的寬限期,會觸發(fā)pod驅(qū)逐

eviction-soft-grace-period:驅(qū)逐寬限期,如memory.available=1m30s,定義軟驅(qū)逐條件在觸發(fā)pod驅(qū)逐之前時長

eviction-max-pod-grace-period:在滿足軟驅(qū)逐條件而終止pod時的最大允許寬限期(以秒為單位)

  • 硬驅(qū)逐

硬驅(qū)逐條件沒有寬限期,當(dāng)達到硬驅(qū)逐條件時,kubelet會強制立即殺死pod并驅(qū)逐

kubelet具有以下默認硬驅(qū)逐條件(可以自行跳轉(zhuǎn)):

imagefs.available<15%
memory.available<100Mi
nodefs.available<10%
nodefs.inodesFree<5%

查看kubelet配置中硬驅(qū)逐配置:

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%(宿主機節(jié)點)

四、Prometheus

4.1 監(jiān)控簡介

監(jiān)控的重要性:通過業(yè)務(wù)監(jiān)控系統(tǒng),全面掌握業(yè)務(wù)環(huán)境的運行狀態(tài),通過白盒監(jiān)控能夠提前預(yù)知業(yè)務(wù)瓶頸,通過黑盒監(jiān)控能夠第一時間發(fā)現(xiàn)業(yè)務(wù)故障并通過告警通告運維人員進行緊急恢復(fù),從而將業(yè)務(wù)影響降到最低。

黑盒監(jiān)控:關(guān)注實時的狀態(tài),一般都是正在發(fā)生的事件,比如nginx web界面打開報錯503等,即黑盒監(jiān)控重點在于能對正在發(fā)生的故障進行通知告警

白盒監(jiān)控:關(guān)注的是原因,也就是系統(tǒng)內(nèi)部暴露的一些指標數(shù)據(jù),比如nginx后端服務(wù)器響應(yīng)時間長等

監(jiān)控系統(tǒng)需要能夠有效的支持白盒監(jiān)控和黑盒監(jiān)控,通過白盒監(jiān)控能夠了解內(nèi)部的運行狀態(tài),以及對監(jiān)控指標的觀察,能夠預(yù)判可能出現(xiàn)的潛在問題,從而對潛在的不確定因素進行提前優(yōu)化并避免問題的發(fā)生;通過黑盒監(jiān)控(如HTTP探針、TCP探針)可以在系統(tǒng)或服務(wù)發(fā)生故障時快速通知相關(guān)人員進行處理

通過完善的監(jiān)控體系,達到以下目的:

長期趨勢分析:通過對監(jiān)控樣本數(shù)據(jù)的持續(xù)收集和統(tǒng)計,對監(jiān)控指標進行長期趨勢分析。例如,通過對磁盤空間增長率的判斷,我們可以提前預(yù)測在未來什么時間點需要對資源進行擴容

對照分析:兩個版本的系統(tǒng)運行資源使用情況的差異性,在不同容量情況下系統(tǒng)的并發(fā)和負載對比

告警:當(dāng)系統(tǒng)出現(xiàn)或者即將出現(xiàn)故障時,監(jiān)控系統(tǒng)迅速通知管理員,從而針對告警內(nèi)容進行快速的處理

故障分析與定位:當(dāng)問題發(fā)生后,需要對問題進行調(diào)查和處理;通過對監(jiān)控和歷史數(shù)據(jù)的分析,找到并解決根源問題

數(shù)據(jù)可視化:通過可視化儀表盤能夠直接獲取系統(tǒng)的運行狀態(tài)、資源使用情況、以及服務(wù)運行狀態(tài)等直觀的信息

4.2 常用監(jiān)控軟件

開源軟件監(jiān)控:cacti、nagios、zabbix、smokeping、open-falcon、nightingale、prometheus等

  • Cacti

https://www.cacti.net/

https://github.com/Cacti/cacti

cacti是基于LAMP平臺展現(xiàn)的網(wǎng)絡(luò)流量監(jiān)測及分析工具,通過SNMP技術(shù)或自定義腳本從目標設(shè)備、主機獲取監(jiān)控指標信息;其次進行數(shù)據(jù)存儲,調(diào)用模板將數(shù)據(jù)存到數(shù)據(jù)庫,使用rrdtool存儲和更新數(shù)據(jù),通過rrdtool繪制結(jié)果圖形;最后進行數(shù)據(jù)展現(xiàn),通過web方式將監(jiān)控結(jié)果呈現(xiàn)出來,常用于在數(shù)據(jù)中心監(jiān)控網(wǎng)絡(luò)設(shè)備。

  • Nagios

https://www.nagios.org/

Nagios是用來監(jiān)視系統(tǒng)和網(wǎng)絡(luò)的開源應(yīng)用軟件,利用其眾多的插件實現(xiàn)對本機和遠端服務(wù)的監(jiān)控,當(dāng)被監(jiān)控對象發(fā)生異常時,會及時向管理員告警,提供一批預(yù)設(shè)好的監(jiān)控插件,用戶可以調(diào)用,也可以自定義shell腳本來監(jiān)控服務(wù),適合各企業(yè)的業(yè)務(wù)監(jiān)控,可通過web頁面顯示監(jiān)控對象狀態(tài)、日志、告警信息,分層告警機制及自定義監(jiān)控相對薄弱。

  • SmokePing

https://www.oetiker.ch/home/oss-2/projekte/smokeping/

Somkeping是一款用于網(wǎng)絡(luò)性能檢測的開源監(jiān)控軟件,主要用于對IDC的網(wǎng)絡(luò)狀況、網(wǎng)絡(luò)質(zhì)量、穩(wěn)定性等做檢測,通過rrdtool制圖,展示網(wǎng)絡(luò)的時延情況。

  • open-falcon

http://open-falcon.org/

https://github.com/XiaoMi/open-falcon

小米公司開源的監(jiān)控軟件,open-falcon(獵鷹),監(jiān)控能力和性能較強

  • Nightingale

https://n9e.didiyun.com/

https://n9e.gitee.io/

夜鶯( Nightingale )是一款經(jīng)過大規(guī)模生產(chǎn)環(huán)境驗證的、分布式高性能的運維監(jiān)控系統(tǒng),由滴滴基于open-falcon二次開發(fā)后開源出來的分布式監(jiān)控系統(tǒng)

  • Zabbix

https://www.zabbix.com/

目前使用較多的開源監(jiān)控軟件,可橫向擴展,自定義監(jiān)控項,支持多種監(jiān)控方式,可監(jiān)控網(wǎng)絡(luò)與服務(wù)等

zabbix 6.0支持監(jiān)控kubernetes(centos系統(tǒng)只有8以上支持)

  • prometheus

https://prometheus.io/

https://github.com/prometheus/prometheus

針對容器環(huán)境的開源監(jiān)控軟件

商業(yè)監(jiān)控解決方案

  • 監(jiān)控寶

https://www.jiankongbao.com/

  • 聽云

https://www.tingyun.com/

4.3 Prometheus簡介

prometheus是基于go語言開發(fā)的一套開源的監(jiān)控、報警和時間序列數(shù)據(jù)庫的組合,是有SoundCloud公司開發(fā)的開源監(jiān)控系統(tǒng),prometheus于2016年加入CNCF(Cloud Native Computing Foundation,云原生計算基金會),于2018年8月9日成為繼kubernetes之后畢業(yè)的第二個項目,prometheus在容器和微服務(wù)領(lǐng)域得到了廣泛的應(yīng)用。

特點如下:

使用key-value的多維度(多個角度、層面)格式保存數(shù)據(jù)

使用時序數(shù)據(jù)庫

支持第三方Dashboard實現(xiàn)更好的圖形界面,如grafana(grafana 2.5.0版本及以上)

組件模塊化

不需要依賴存儲,數(shù)據(jù)可以本地保存,也可以遠程保存

平均每個采樣點僅占3.5bytes,且一個Prometheus Server可以處理數(shù)百萬級別的metrics指標數(shù)據(jù)

支持服務(wù)自動化發(fā)現(xiàn)(基于consul等方式動態(tài)發(fā)現(xiàn)被監(jiān)控的目標服務(wù))

強大的數(shù)據(jù)查詢語句(PoemQL,Prometheus Query Language)

數(shù)據(jù)可以直接進行算術(shù)運算

易于橫向伸縮

眾多官方和第三方的exporter實現(xiàn)不通的指標數(shù)據(jù)收集

容器監(jiān)控的實現(xiàn)方式對比虛擬機或物理機來說,有較大的區(qū)別,比如容器在k8s環(huán)境中可以任意橫向擴容與縮容,那么就需要監(jiān)控服務(wù)能夠自動對新創(chuàng)建的容器進行監(jiān)控,當(dāng)容器刪除后,有能夠及時的從監(jiān)控服務(wù)總刪除,而傳統(tǒng)的zabbix的監(jiān)控方式需要在每個容器中安裝啟動agent,并且在容器自動發(fā)現(xiàn)注冊及模板關(guān)聯(lián)方面并沒有比較好的實現(xiàn)方式。

Prometheus包含以下組件:

prometheus server:主服務(wù),接受外部http請求,收集、存儲與查詢數(shù)據(jù)等

prometheus targets:靜態(tài)收集的目標服務(wù)數(shù)據(jù)

service discovery:動態(tài)發(fā)現(xiàn)服務(wù)

prometheus alerting:報警通知

push gateway:數(shù)據(jù)收集代理服務(wù)器(類似于zabbix proxy)

data visualization and exporter:數(shù)據(jù)可視化與數(shù)據(jù)導(dǎo)出(訪問客戶端)

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目錄下執(zhí)行
kubectl apply -f .
  • 然后后退一層目錄,到kube-prometheus/manifests目錄下執(zhí)行
 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類型,重新執(zhí)行
kubectl apply -f prometheus-service.yaml
  • 修改grafana-service.yaml文件,端口類型改成NodePort類型,重新執(zhí)行
kubectl apply -f grafana-service.yaml
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容