在K8s中定義Pod中運行容器有兩個維度的限制:
1. 資源需求:即運行Pod的節點必須知足運行Pod的最基本需求才能運行Pod。
如: Pod運行至少須要2G內存,1核CPU
2. 資源限額:即運行Pod期間,可能內存使用量會增長,那最多能使用多少內存,這就是資源限額。前端
# kubectl describe node node1.zcf.com ....................... Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) Resource Requests Limits #這裏顯示的就是 資源的需求 和 限額 -------- -------- ------ cpu 250m (12%) 0 (0%) memory 0 (0%) 0 (0%) ephemeral-storage 0 (0%) 0 (0%) Requests: 就是需求限制,也叫軟限制 Limits:最大限制,也叫硬限制 一般來講:Limits >= Requests 而且requests 和 limits 一般要一塊兒配置,若只配置了requests,而不配置limits,則極可能致使Pod會吃掉全部資源。
須要注意:
目前k8s在對資源限制方面還有欠缺,特別是Java應用,由於Pod運行起來後,它看到的資源是Node上所有的資源,雖然可經過requests和limits限制,但咱們都知道JVM啓動後,它要計算本身的堆內存中不一樣區域的大小,而這些大小一般是按比例劃分的,倘若JVM啓動後,根據Node上實際的內存大小來計算堆內存中老年代,Eden,倖存區那確定會出問題,由於,咱們給它分片的內存確定不夠,因此這個要特別注意,而解決辦法,只能是在啓動Java應用前,配置JVM能使用的最大內存量。
在K8s的資源:
CPU:
咱們知道2核2線程的CPU,可被系統識別爲4個邏輯CPU,在K8s中對CPU的分配限制是對邏輯CPU作分片限制的。
也就是說分配給容器一個CPU,實際是分配一個邏輯CPU。
並且1個邏輯CPU還可被單獨劃分子單位,即 1個邏輯CPU,還可被劃分爲1000個millicore(毫核), 簡單說就是1個邏輯CPU,繼續邏輯分割爲1000個豪核心。
豪核:可簡單理解爲將CPU的時間片作邏輯分割,每一段時間片就是一個豪核心。
因此:500m 就是500豪核心,即0.5個邏輯CPU.
內存:
K,M,G,T,P,E #一般這些單位是以1000爲換算標準的。
Ki, Mi, Gi, Ti, Pi, Ei #這些一般是以1024爲換算標準的。
K8s中資源限制對調度Pod的影響:node
cpu.limits: 是咱們設置Pod運行時,最大可以使用500m個CPU,但要保障Pod能在Node上成功啓動起來,就必需能提供cpu.requests個CPU.
當預選策略在選擇備選Node時,會首先考慮當前Pod運行, 其所需資源是否足夠, 來作爲首要判斷條件,假如某Node上已經運行了一些Pod,預選策略會獲取當前全部Pod的cpu.requests ,ram.requests等,這裏以cpu.requests來講明,好比說某Node上是2核2線程的CPU,全部容器的cpu.requests所有加起來假如已經3.9個CPU了,那麼此Node在預選階段就會被篩選掉。git
資源限制配置:
kubectl explain pods.spec.containers.resorces
limits:<map[string]string>
requests:<map[string]string>程序員
#如下壓測時,若壓測內存,可能致使登陸容器都成問題,所以改成僅測試CPU。 apiVersion: v1 kind: Pod metadata: name: pod-cpu-limits labels: app: test tier: frontend spec: containers: - name: myapp image: ikubernetes/stress-ng command: ["/usr/bin/stress-ng","-c 1","--metrics-brief"] resources: requests: cpu: "500m" memory: "512Mi" limits: cpu: "500m" memory: "512Mi"
QoS類型:
Guranteed:
每一個容器的CPU,RAM資源都設置了相同值的requests 和 limits屬性。
簡單說: cpu.limits = cpu.requests
memory.limits = memory.requests
這類Pod的運行優先級最高,但凡這樣配置了cpu和內存的limits和requests,它會自動被歸爲此類。
Burstable:
每一個容器至少定義了CPU,RAM的requests屬性,這裏說每一個容器是指:一個Pod中能夠運行多個容器。
那麼這類容器就會被自動歸爲burstable,而此類就屬於中等優先級。
BestEffort:
沒有一個容器設置了requests 或 limits,則會歸爲此類,而此類別是最低優先級。
QoS類型的做用:
Node上會運行不少Pod,當運行一段時間後,發現Node上的資源緊張了,這時K8s就會根據QoS類別來選擇Kill掉一部分Pod,那些會先被Kill掉?
固然就是優先級最低的,也就是BestEffort,若BestEffort被Kill完了,仍是緊張,接下來就是Kill中等優先級的,即Burstable,依次類推。
這裏有個問題,BestEffort由於沒有設置requests和limits,可根據誰佔用資源最多,就kill誰,但Burstable設置了requests和limits,它的kill標準是什麼?
若按照誰佔資源多kill誰,那遇到這樣的問題,怎麼選擇?
PodA: 啓動時設置了memory.request=512M , memory.limits=1G
PodB: 設置爲: memory.requests=1G, memory.limits=2G
PodA: 運行了一段時間後,佔用了500M了,它可能還有繼續申請內存。
PodB: 它則佔用了512M內存了,但它可能也還須要申請內存。
想一想,如今Node資源緊張了,會先kill誰?
其實,會優先kill PodA , 爲啥?
由於它啓動時,說本身須要512M內存就夠了,但你如今這麼積極的申請內存,都快把你需求的內存吃完了,只能說明你太激進了,所以會先kill。
而PodB,啓動時須要1G,但目前才用了1半,說明它比較溫和,所以不會先kill它。github
K8s中Pod監控的指標有如下幾類:
1. Kubernetes系統指標
2. 容器指標,即:容器使用的CPU,內存,存儲等資源的統計用量的
3. 應用指標,即業務應用的指標,如:接收了多少用戶請求,正在處理的用戶請求等等。docker
K8s中獲取Node資源用量,Pod資源用量要如何實現?
其實早期K8s中kubelet內封裝了一個組件叫cAdvisor,它啓動後,會監聽在14041端口上,來對外提供單節點上Node和Pod的資源統計用量,可是因爲安全性問題,後期就將kubelet上的cAdvisor改成不監聽,而是會經過配置HeapSter Pod的訪問cAdvisor的地址,將本身的統計數據發送給它,由它來負責存儲這些統計數據,但HeapSter它默認是將數據存儲在緩存中,不能持久存儲,所以它須要藉助InfluxDB來實現數據的持久化,這些資源統計用量被髮給HeapSter後,若經過命令行工具來獲取指定Node上的資源使用統計,以及Pod的資源使用統計時,能夠用kubectl top [node |pod] 來查看,但若想查看歷史數據,就不能實現了,由於命令行工具只能從HeapSter來獲取實時數據,而沒法獲取歷史數據,若要獲取歷史數據,就必須藉助另外一個組件叫Grafana,它能夠從InfluxDB中讀取時序存儲的數據,並經過圖形界面來展現給用戶。數據庫
HeapSter 因爲從Kubernetes1.11.1之後將被廢棄,從11.2後將被完全廢棄。
它被廢棄的緣由是,由於它自身的設計架構上,會去整合不少第三方開發的後端存儲組件,其中InfluxDB就是其中之一,因爲是第三方組織研發的,因此這就致使了一個問題,若那天第三方對此不感興趣了,就會放棄對這些後端存儲組件的維護,致使沒法繼續支持K8s後期版本的。另外一個緣由是在HeapSter中這些第三方存儲組件也是做爲其核心代碼的一部分存在的,所以它帶來的問題是,HeapSter的代碼會愈來愈臃腫,並且配置也會愈來愈複雜,於是K8s才決定放棄HeapSter。
apache
HeapSter-amd64:v1.5.4 + heapster-influxdb-amd64:v1.5 + heapster-grafana-amd64:v5.0.4
#測試發現,不能正常工做,查看日誌一切正常,可是沒法正常獲取監控指標數據。
使用下面這個舊版本的組合,是能夠正常工做的,這個須要注意:
HeapSter-amd64:v1.5.1 + heapster-influxdb-amd64:v1.3.3 + heapster-grafana-amd64:v4.4.3
#這個組合中,grafana配置NodePort後,從外部訪問,Grafana沒有Web圖像接口,但從日誌上能夠看到外部訪問記錄,也沒有報錯,懷疑其可能沒有圖像界面。
#因此這個grafana組件能夠不安裝。另外,我測試將5.0.4的Grafana部署上,它能夠鏈接到InfluxDB,應該是能獲取數據,但由於沒有默認面板,因此若想測試,須要自行到grafana官網去找一些模板測試。vim
構建上面三個組件的順序:
後端
1. 先部署InfluxDB,由於它被HeapSter所依賴
wget -c https://raw.githubusercontent.com/kubernetes-retired/heapster/master/deploy/kube-config/influxdb/influxdb.yaml
2. 接着就能夠直接應用此清單
kubectl apply -f influxdb.yaml
若鏡像下載失敗,可嘗試阿里雲鏡像的谷歌鏡像倉庫下載:
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/heapster-influxdb-amd64:v1.5.2
3. 驗證
# kubectl get pod -n kube-system
#kubectl describe pod -n kube-system monitoring-influxdb-xxxxx
#從輸出的信息中能夠看到默認influxdb使用HTTP協議來對對外提供服務,你能夠經過它的一些專用客戶端工具來登入它,查看它所提供的服務。
4. 接下來建立HeapSter,但建立HeapSter前須要先建立它全部依賴的RBAC配置,由於默認使用kubeasz部署的K8s集羣是啓用了RBAC的,所以須要先建立HeapSter所需的RBAC配置.
wget -c https://raw.githubusercontent.com/kubernetes-retired/heapster/master/deploy/kube-config/rbac/heapster-rbac.yaml
kubectl apply heapster-rbac.yaml
#建立完RBAC後,就能夠建立heapster Pod了。
wget https://raw.githubusercontent.com/kubernetes-retired/heapster/master/deploy/kube-config/influxdb/heapster.yaml
#須要注意: apiVersion: v1 kind: ServiceAccount #heapSter須要使用一個服務賬戶,由於它須要能從全部Node上獲取Pod的資源統計信息,所以它必須被受權. metadata: name: heapster namespace: kube-system #在HeapSter容器定義部分能夠看到它引用了上面建立的SA賬戶 spec: serviceAccountName: heapster containers: - name: heapster image: k8s.gcr.io/heapster-amd64:v1.5.4 imagePullPolicy: IfNotPresent command: - /heapster - --source=kubernetes:https://kubernetes.default #這裏是定義HeapSter從K8s內部訪問APIServer的地址. - --sink=influxdb:http://monitoring-influxdb.kube-system.svc:8086 #這是指明HeapSter訪問InfluxDB的地址,由於InfluxDB是Pod,不能直接訪問Pod的IP,所以這裏訪問的是InfluxDB前端的SerivseIP。 #另外還有注意,HeapSter也須要Serivce apiVersion: v1 kind: Service ..... name: heapster namespace: kube-system spec: ports: - port: 80 #這裏能夠看到它在Node上暴露的端口是80 targetPort: 8082 #HeapSter在Pod內部啓動的端口爲8082 type: NodePort #若須要K8s外部訪問HeapSter,可修改端口類型爲NodePort selector: k8s-app: heapster
#接着執行應用此清單
kubectl apply -f heapster.yaml
#查看heapster的日誌:
kubectl logs -n kube-system heapster-xxxxx
5. 最後來部署Grafana
wget https://raw.githubusercontent.com/kubernetes-retired/heapster/master/deploy/kube-config/influxdb/grafana.yaml
#另外還有須要注意: volumeMounts: - mountPath: /etc/ssl/certs #它會自動掛載Node上的/etc/ssl/certs目錄到容器中,並自動生成證書,由於它使用的HTTPS. name: ca-certificates readOnly: true #Grafana啓動時,會去鏈接數據源,默認是InfluxDB,這個配置是經過環境變量來傳入的 env: - name: INFLUXDB_HOST value: monitoring-influxdb #這裏可看到,它將InfluxDB的Service名傳遞給Grafana了。 - name: GF_SERVER_HTTP_PORT value: "3000" #默認Grafara在Pod內啓動時,監聽的端口也是經過環境變量傳入的,默認是3000端口. #在一個是,咱們須要配置Grafana能夠被外部直接訪問 ports: - port: 80 targetPort: 3000 selector: k8s-app: grafana type: NodePort
部署完成後,可登陸Dashboard查看資源狀態統計信息
自定義資源:
在K8s中支持用戶根據本身業務的特殊需求去自定義服務組件,來擴展K8s原始的Service,headless等,這種被稱爲 自制資源定義(CRD)。
另外在K8s中也可本身開發一個新的APIServer,它裏面可提供本身所須要的API接口,而後在經過K8s 中的所謂的API聚合器將本身開發的APIServer和K8s本身的APIServer聚合在一塊兒來使用它;在否則就是本身修改K8s源碼,來新增須要的功能定義。
K8s從1.8開始引入資源指標API,它將資源的內容也看成API接口中的數據直接進行獲取,而不像早期HeapSter,須要先部署HeapSter,而後從HeapSter中獲取資源指標數據,這樣帶來的不即是,咱們獲取數據就須要經過兩個地方獲取,當獲取API資源(Pod, Service,...)是經過APIServer獲取,而獲取監控資源指標時,就必須從HeapSter中獲取,而在新版的K8s中,引入資源指標API就是想避免這種麻煩,讓用戶再來獲取數據時,所有從APIServer來獲取,而要實現這個功能,它引入了一個API聚合器,由於資源監控指標API是容許用戶自定義開發的,而開發出來的資源指標API經過一個相似代理層的API聚合器 將這些用戶開發的資源指標API 和 原始的APIServer聯合起來,用戶經過訪問API聚合器,來獲取本身須要的數據,而API聚合器會根據用戶的請求,自動將請求轉發給APIServer或資源指標API。
須要說明的是 資源指標API 分爲兩類,一類是核心指標,另外一類是非核心指標,核心指標是metrics-server提供的,它也是一個Pod。
HPA:它是水平Pod自動伸縮器,它也是須要獲取資源指標來判斷,並做出一些預約義動做,如:判斷CPU使用率已經80%了,則會自動增長一個Pod,若發現某個Pod的資源使用率很低,一直維持在好比說5%,它能夠自動關閉幾個該Pod,以便騰出資源供其它Pod使用等。
kubectl top .... 這個命令 和 HPA功能在早期都是須要依賴HeapSter來工做的,可是HeapSter有個不少的缺陷,它只能統計CPU,內存,磁盤等的資源用量,但沒法獲取其它更多資源指標,這就限制了咱們想獲取更多信息的途徑,另外也使得HPA的功能受到了限制,例若有時候,Pod的CPU,內存等佔有率不高,但其訪問量卻很是高,這時咱們也但願能自動建立Pod來分擔併發壓力,但HeapSter就沒法幫咱們作的,所以才致使新的資源指標API的出現,以及後來又引入了自定義資源指標的模型。
Prometheus:它能夠收集基本指標,同時還能夠收集網絡報文的收發速率,網絡鏈接的數量,內存,包括進程的新建和回收的速率等等,而這些K8s早期是不支持的,它讓咱們可使用這些功能來加強咱們的HPA能力。它即做爲監控組件使用,也做爲一些特殊指標的資源提供者來提供,但這些不是內建的標準核心指標,這些咱們統稱爲自定義指標。
須要注意Prometheus要想將它監控採集到的數據,轉化爲指標格式,須要一個特殊的組件,它叫 k8s-prometheus-adapter
K8s新一代監控指標架構由兩部分組成:
metrics-server:
它主要用於提供監控指標API,但它一般是由用戶提供的API服務,它自己不是k8s的核心組件,它僅是K8s上的一個Pod,所以爲了能讓用戶無縫的使用metrics-server上提供的API,所以就必須使用kube-aggregator。固然kube-aggregator不只僅能夠聚合傳統APIServer和metrics-server,它還能夠聚合不少用戶自定義的API服務。
/apps/metrics.k8s.io/v1beta1:
這個羣組默認是不包含在建立API Server中的,所以你經過 kubectl api-versions 查看,是沒有這個羣組的,這個羣組實際是由 metrics-server 來提供的,而咱們須要作的是使用kube-aggregator將這個API羣組合併到API Server中去,這樣用戶再去訪問API Server時,就能夠訪問到此API羣組了。
#須要修改兩個文件: #第一個文件: metrics-server-deployment.yaml #此清單文件定義了metrics-server鏡像和metrics-server-nanny容器啓動的參數,這些參數有些須要修改 #metrics-server容器: command: - /metrics-server - --metric-resolution=30s #- --kubelet-insecure-tls #網上不少文章都說必須加上此參數, 此參數含義: #若不能作TLS加密認證,使用不安全的通訊也能夠.但我測試時,不加也能正常工做,僅作借鑑 # These are needed for GKE, which doesn't support secure communication yet. # Remove these lines for non-GKE clusters, and when GKE supports token-based auth. - --kubelet-port=10255 - --deprecated-kubelet-completely-insecure=true - --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP #metrics-server-nanny容器: command: - /pod_nanny - --config-dir=/etc/config #下面這些{{....}} 這些若不替換,啓動metrics-server-nanny容器時會報錯,但從報錯日誌中能夠到它們的簡單說明 - --cpu={{ base_metrics_server_cpu }} #設置metrics-server基本運行可用CPU豪核數量,測試設置100m - --extra-cpu=0.5m - --memory={{ base_metrics_server_memory }} #分配給metrics-server基本運行的內存大小, 測試設置 150Mi - --extra-memory={{ metrics_server_memory_per_node }}Mi #每一個節點上的metrics-server額外分配內存大小,測試50Mi - --threshold=5 - --deployment=metrics-server-v0.3.3 - --container=metrics-server - --poll-period=300000 - --estimator=exponential # Specifies the smallest cluster (defined in number of nodes) # resources will be scaled to. #- --minClusterSize={{ metrics_server_min_cluster_size }} #這裏字面意思彷佛是 設置啓動幾組Metrics-server,選項說明提示默認是16組. 但這我註釋掉了。 #第二個文件:resource-reader.yaml rules: - apiGroups: - "" resources: - pods - nodes - nodes/stats #這裏須要注意:默認是沒有添加的,若只添加nodes,它是獲取不到nodes/stats的狀態信息的, # 由於nodes/stats和nodes是兩個不一樣的資源. nodes/stats是獲取節點監控數據的專用資源. - namespaces #以上兩個文件修改好後,就可執行應用了 kubectl apply -f ./ #在應用使用,可查看kube-system名稱空間中 metrics-server pod的建立 kubectl get pod -n kube-system -w #會發現metrics-server先建立一組,等第二組啓動爲running後,第一組就會自動終止。目前尚未弄明白是什麼邏輯。 #上面修改好後,測試發現仍是會報錯,但已經不報參數無效的錯誤了 # kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE ................ metrics-server-v0.3.3-7d598d5c9d-qngp7 2/2 Running 0 49s # kubectl logs -n kube-system metrics-server-v0.3.3-7d598d5c9d-qngp7 -c metrics-server-nanny ERROR: logging before flag.Parse: I0729 13:06:42.923342 1 pod_nanny.go:65] Invoked by [/pod_nanny --config-dir=/etc/config --cpu=100m --extra-cpu=0.5m --memory=300Mi --extra-memory=50Mi --threshold=5 --deployment=metrics-server-v0.3.3 --container=metrics-server --poll-period=300000 --estimator=exponential] ERROR: logging before flag.Parse: I0729 13:06:42.923611 1 pod_nanny.go:81] Watching namespace: kube-system, pod: metrics-server-v0.3.3-7d598d5c9d-qngp7, container: metrics-server. ERROR: logging before flag.Parse: I0729 13:06:42.923642 1 pod_nanny.go:82] storage: MISSING, extra_storage: 0Gi ERROR: logging before flag.Parse: I0729 13:06:42.927214 1 pod_nanny.go:109] cpu: 100m, extra_cpu: 0.5m, memory: 300Mi, extra_memory: 50Mi ERROR: logging before flag.Parse: I0729 13:06:42.927362 1 pod_nanny.go:138] Resources: [{Base:{i:{value:100 scale:-3} d:{Dec:<nil>} s:100m Format:DecimalSI} ExtraPerNode:{i:{value:5 scale:-4} d:{Dec:<nil>} s: Format:DecimalSI} Name:cpu} {Base:{i:{value:314572800 scale:0} d:{Dec:<nil>} s:300Mi Format:BinarySI} ExtraPerNode:{i:{value:52428800 scale:0} d:{Dec:<nil>} s:50Mi Format:BinarySI} Name:memory}] #上面準備就緒後,就可作如下測試 1. 查看api-versions是否多出了一個 metrics.k8s.io/v1beta1 # kubectl api-versions ............. metrics.k8s.io/v1beta1 2. 若以上驗證都經過了,則可作如下測試 kubectl proxy --ports=8080 3. 在另外一個終端訪問8080 curl http://localhost:8080/apis/metrics.k8s.io/v1beta1 { "kind": "APIResourceList", "apiVersion": "v1", "groupVersion": "metrics.k8s.io/v1beta1", "resources": [ { "name": "nodes", "singularName": "", "namespaced": false, "kind": "NodeMetrics", "verbs": [ "get", "list" ........................ } #查看收集到的Pods 和 node監控數據 curl http://localhost:8080/apis/metrics.k8s.io/v1beta1/node
#查看是否能獲取Node 和 Pod的資源使用狀況:
經過上面部署metrics-server,咱們能夠獲取到核心資源信息了,可是若想獲取更多監控資源數據,就必須藉助另外一個Addons組件來獲取,而這個Addons就是prometheus
它自己就是一個監控系統,它相似於Zabbix,它也須要在Node上安裝Agent,而prometheus將本身的Agent稱爲node_exporter, 但這個node_exporter它僅是用於給Prometheus提供Node的系統級監控指標數據的,所以,若你想採集MySQL的監控數據,你還須要本身部署一個MySQL_exporter,才能採集mySQL的監控數據,並且Prometheus還有不少其它重量級的應用exporter,可在用到時自行學習。
咱們須要知道,若你能獲取一個node上的監控指標數據,那麼去獲取該node上運行的Pod的指標數據就很是容易了。所以Prometheus,就是經過metrics URL來獲取node上的監控指標數據的,固然咱們還能夠經過在Pod上定義一些監控指標數據,而後,定義annotations中定義容許 Prometheus來抓取監控指標數據,它就能夠直接獲取Pod上的監控指標數據了。
PromQL:
這是Prometheus提供的一個RESTful風格的,強大的查詢接口,這也是它對外提供的訪問本身採集數據的接口。
可是Prometheus採集的數據接口與k8s API Server資源指標數據格式不兼容,所以API Server是不能直接使用Prometheus採集的數據的,須要藉助一個第三方開發的k8s-prometheus-adapter來解析prometheus採集到的數據, 這個第三方插件就是經過PromQL接口,獲取Prometheus採集的監控數據,而後,將其轉化爲API Server能識別的監控指標數據格式,可是咱們要想經過kubectl來查看這些轉化後的Prometheus監控數據,還須要將k8s-prometheus-adpater聚合到API Server中,才能實現直接經過kubectl獲取數據 。
#接下來部署Prometheus的步驟大體爲:
1. 部署Prometheus
2. 配置Prometheus可以獲取Pod的監控指標數據
3. 在K8s上部署一個k8s-prometheus-adpater Pod
4. 此Pod部署成功後,還須要將其聚合到APIServer中
說明:
Prometheus它自己就是一個時序數據庫,由於它內建了一個存儲 全部eporter 或 主動上報監控指標數據給Prometheus的Push Gateway的數據 存儲到本身的內建時序數據庫中,所以它不須要想InfluxDB這種外部數據庫來存數據。
Prometheus在K8s中經過Service Discovery來找到須要監控的目標主機,而後經過想Grafana來展現本身收集到的全部監控指標數據,另外它還能夠經過Web UI 或 APIClients(PromQL)來獲取其中的數據。
Prometheus自身沒有提供報警功能,它會將本身的報警需求專給另外一個組件Alertmanger來實現報警功能。
#在K8s上部署Prometheus須要注意,由於Prometheus自己是一個有狀態數據集,所以建議使用statefulSet來部署並控制它,可是若你只打算部署一個副本,那麼使用deployment和statefulSet就不重要了。可是你若須要後期進行縱向或橫向擴展它,那你就只能使用StatefulSet來部署了。
部署K8s Prometheus
須要注意,這是馬哥本身作的簡版Prometheus,他沒有使用PVC,若須要部署使用PVC的Prometheus,可以使用kubernetes官方的Addons中的清單來建立。
官方地址:https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/prometheus
馬哥版的地址:https://github.com/iKubernetes/k8s-prom
下面以馬哥版原本作說明: 1. 先部署名稱空間: kubectl apply -f namespace.yaml --- apiVersion: v1 kind: Namespace metadata: name: prom #這裏須要注意: 他是先建立了一個prom的名稱空間,而後,將全部Prometheus的應用都放到這個名稱空間了。 2. 先建立node_exporter: cd node_exporter #須要注意: apiVersion: apps/v1 kind: DaemonSet metadata: name: prometheus-node-exporter namespace: prom ....... spec: tolerations: #這裏須要注意:你要保障此Pod運行起來後,它能容忍Master上的污點.這裏僅容忍了默認Master的污點.這裏須要根據實際狀況作確認。 - effect: NoSchedule key: node-role.kubernetes.io/master containers: - image: prom/node-exporter:v0.15.2 #這裏使用的node-exporter的鏡像版本。 name: prometheus-node-exporter #應用這些清單 kubectl apply -f ./
#應用完成後,查看Pod
#接着進入Prometheus的清單目錄 cd prometheus #prometheus-deploy.yaml 它須要的鏡像文件可從hub.docker.com中下載,若網速慢的話。 #prometheus-rbac.yaml apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: name: prometheus rules: - apiGroups: [""] resources: - nodes - nodes/proxy - services - endpoints - pods verbs: ["get", "list", "watch"] - apiGroups: - extensions resources: - ingresses verbs: ["get", "list", "watch"] - nonResourceURLs: ["/metrics"] verbs: ["get"] #prometheus-deploy.yaml resources: #這裏作了一個資源使用限制,須要確認你每一個節點上要能知足2G的可用內存的需求,若你的Node上不能知足這個limits,就將這部分刪除,而後作測試。 limits: memory: 2Gi #接着開始應用這些清單: kubectl apply -f ./
#應用完成後查看:
kubectl get all -n prom
#如今來部署,讓K8s能獲取Prometheus的監控數據 cd kube-state-metrics #此清單中的鏡像若不能從google倉庫中獲取,可到hub.docker.com中搜索鏡像名,下載其餘人作的測試 #K8s須要經過kube-state-metrics這個組件來進行格式轉化,實現將Prometheus的監控數據轉換爲K8s API Server能識別的格式。 #可是kube-state-metrics轉化後,仍是不能直接被K8s所使用,它還須要藉助k8s-prometheus-adpater來將kube-state-metrics聚合到k8s的API Server裏面,這樣才能經過K8s API Server來訪問這些資源數據。
#應用kube-state-metrics的清單文件 kubectl apply -f ./
#應用完成後,再次驗證
#以上建立好之後,可先到k8s-prometheus-adapter的開發者github上下載最新的k8s-prometheus-adapter的清單文件 https://github.com/DirectXMan12/k8s-prometheus-adapter/tree/master/deploy/manifests #注意:
# !!!!!!!!!
# 使用上面新版本的k8s-prometheus-adapter的話,而且是和馬哥版的metrics-server結合使用,須要修改清單文件中的名稱空間爲prom
# !!!!!!!!!!!!!!! # 但下面這個文件要特別注意: custom-metrics-apiserver-auth-reader-role-binding.yaml piVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: custom-metrics-auth-reader namespace: kube-system #這個custom-metrics-auth-reader必須建立在kube-system名稱空間中,由於它要綁到這個名稱空間中的Role上 roleRef: apiGroup: rbac.authorization.k8s.io kind: Role #此角色是用於外部APIServer認證讀的角色 name: extension-apiserver-authentication-reader subjects: - kind: ServiceAccount name: custom-metrics-apiserver #這是咱們本身建立的SA帳號 namespace: prom #這些須要注意:要修改成prom #以上清單文件下載完成後,須要先修改這些清單文件中的namespace爲prom,由於咱們要部署的Prometheus都在prom這個名稱空間中. 以後就能夠正常直接應用了 kubectl apply -f ./
# 應用完成後,須要檢查
kubectl get all -n prom #查看全部Pod都已經正常運行後。。
# 查看api-versions中是否已經包含了 custom.metrics.k8s.io/v1beta1, 若包含,則說明部署成功
kubectl api-versions
# 測試獲取custom.metrics.k8s.io/v1beta1的監控數據
curl http://localhost:8080/custom.metrics.k8s.io/v1beta1/
下面測試將Grafana部署起來,而且讓Grafana從Prometheus中獲取數據 #部署Grafana,這裏部署方法和上面部署HeapSter同樣,只是這裏僅部署Grafana wget https://raw.githubusercontent.com/kubernetes-retired/heapster/master/deploy/kube-config/influxdb/grafana.yaml #此清單若須要修改apiVersion,也要向上面修改同樣,配置其seletor。 #另外還有須要注意: volumeMounts: - mountPath: /etc/ssl/certs #它會自動掛載Node上的/etc/ssl/certs目錄到容器中,並自動生成證書,由於它使用的HTTPS. name: ca-certificates readOnly: true #Grafana啓動時,會去鏈接數據源,默認是InfluxDB,這個配置是經過環境變量來傳入的 env: #- name: INFLUXDB_HOST # value: monitoring-influxdb #這裏可看到,它將InfluxDB的Service名傳遞給Grafana了。 #須要特別注意:由於這裏要將Grafana的數據源指定爲Prometheus,因此這裏須要將InfluxDB作爲數據源給關閉,若你知道如何定義prometheus的配置, #也可直接修改,不修改也能夠,那就直接註釋掉,而後部署完成後,登陸Grafana後,在修改它的數據源獲取地址。 - name: GF_SERVER_HTTP_PORT value: "3000" #默認Grafara在Pod內啓動時,監聽的端口也是經過環境變量傳入的,默認是3000端口. #在一個是,咱們須要配置Grafana能夠被外部直接訪問 ports: - port: 80 targetPort: 3000 selector: k8s-app: grafana type: NodePort #配置完成後,進行apply kubectl apply -f grafana.yaml #而後查看service對集羣外暴露的訪問端口 kubectl get svc -n prom
#隨後打開瀏覽器,作如下修改
#接着,你能夠查找一個,如何導入第三方作好的模板,而後,從grafana官網下載一個模板,導入就能夠獲取一個漂亮的監控界面了。
#獲取Prometheus的模板文件,可從這個網站獲取
https://grafana.com/grafana/dashboards?search=kubernetes
HPA功能:
正如前面所說,它可根據咱們所設定的規則,監控當前Pod總體使用率是否超過咱們設置的規則,若超過則設置的根據比例動態增長Pod數量。
舉個簡單的例子:
假若有3個Pod,咱們規定其最大使用率不能高於60%,但如今三個Pod每一個CPU使用率都到達90%了,那該增長几個Pod的?
HPA的計算方式是:
90% × 3 = 270% , 那在除以60,就是須要增長的Pod數量, 270 / 60 = 4.5 ,也就是5個Pod
#HPA示例:
kubectl run myapp --image=harbor.zcf.com/k8s/myapp:v1 --replicas=1 \
--requests='cpu=50m,memory=256Mi' --limits='cpu=50m,memory=256Mi' \
--labels='app=myapp' --expose --port=50
#修改myapp的svcPort類型爲NodePort,讓K8s集羣外部能夠訪問myapp,這樣方便壓力測試,讓Pod的CPU使用率上升,而後,查看HPA自動建立Pod.
kubectl patch svc myapp -p '{"spec":{"type":"NodePort"}}'
# kubectl get pods
#這裏目前只有一個Pod!!
kubectl describe pod myapp-xxxx #可查看到它當前的QoS類別爲: Guranteed
#建立HPA,根據CPU利用率來自動伸縮Pod
kubectl autoscale deployment myapp --min=1 --max=8 --cpu-percent=40
#查看當前Pod是Service: # kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE .................. myapp NodePort 172.30.162.48 <none> 80:50113/TCP 103m #建立成功後,就能夠經過ab等壓測工具來測試自動伸縮 #apt-get install apache2-utils # # ab -c 1000 -n 3000 http://192.168.111.84:50113 #查看HPA自動伸縮狀況 # kubectl describe hpa Name: myapp Namespace: default ............................ resource cpu on pods (as a percentage of request): 76% (38m) / 40% Min replicas: 1 Max replicas: 8 Deployment pods: 6 current / 8 desired #這裏可看到如今已經啓動6個Pod #建立一個HPA v2版本的自動伸縮其 #完整配置清單: vim hpa-pod-demo-v2.yaml apiVersion: v1 kind: Service metadata: labels: app: myapp name: myapp-v2 spec: clusterIP: 172.30.10.98 ports: - port: 80 protocol: TCP targetPort: 80 type: NodePort selector: app: myapp --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: myapp name: myapp-v2 spec: replicas: 1 selector: matchLabels: app: myapp strategy: {} template: metadata: labels: app: myapp spec: containers: - image: harbor.zcf.com/k8s/myapp:v1 name: myapp-v2 ports: - containerPort: 80 resources: limits: cpu: 50m memory: 256Mi requests: cpu: 50m memory: 256Mi --- apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler metadata: name: myapp-v2 spec: maxReplicas: 8 minReplicas: 1 scaleTargetRef: apiVersion: extensions/v1beta1 kind: Deployment name: myapp metrics: - type: Resource resource: name: cpu targetAverageUtilization: 55 - type: Resource resource: name: memory targetAverageValue: 50Mi
#壓測方便和上面同樣。這個配置清單中定義了CPU和內存的資源監控指標,V2是支持內存監控指標的,但V1是不支持的。
#若之後本身程序員開發的Pod,能經過Prometheus導出Pod的資源指標,好比:HTTP的訪問量,鏈接數,咱們就能夠根據HTTP的訪問量或者鏈接數來作自動伸縮。
在那個Pod上的那些指標可用,是取決於你的Prometheus可以從你的Pod的應用程序中獲取到什麼樣的指標的,可是Prometheus能獲取的指標是由必定語法要求的,開發要依據 Prometheus支持的RESTful風格的接口,去輸出一些指標數據,這指標記錄當前系統上Web應用程序所承載的最大訪問數等一些指標數據,那咱們就可基於這些輸出的指標數據,來完成HPA自動伸縮的擴展。
#自定義資源指標來建立HPA,實現根據Pod中輸出的最大鏈接數來自動擴縮容Pod
#下面是一個HPA的定義,你還須要建立一個能輸出http_requests這個自定義資源指標的Pod,而後才能使用下面的HPA的清單。
下面清單是使用自定義資源監控指標 http_requests 來實現自動擴縮容:
docker pull ikubernetes/metrics-app #可從這裏獲取metrics-app鏡像
vim hpa-http-requests.yaml apiVersion: v1 kind: Service metadata: labels: app: myapp name: myapp-hpa-http-requests spec: clusterIP: 172.30.10.99 #要根據實際狀況修改成其集羣IP ports: - port: 80 protocol: TCP targetPort: 80 type: NodePort #若須要集羣外訪問,可添加 selector: app: myapp --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: myapp name: myapp-hpa-http-requests spec: replicas: 1 #這裏指定Pod副本數量爲1 selector: matchLabels: app: myapp strategy: {} template: metadata: labels: app: myapp annotations: #annotations必定要,而且要定義在容器中!! prometheus.io/scrape: "true" #這是容許Prometheus到容器中抓取監控指標數據 prometheus.io/port: "80" prometheus.io/path: "/metrics" #這是指定從那個URL路徑中獲取監控指標數據 spec: containers: - image: harbor.zcf.com/k8s/metrics-app #此鏡像中包含了作好的,能輸出符合Prometheus監控指標格式的數據定義。 name: myapp-metrics ports: - containerPort: 80 resources: limits: cpu: 50m memory: 256Mi requests: cpu: 50m memory: 256Mi --- apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler metadata: name: myapp-hpa-http-requests spec: maxReplicas: 8 minReplicas: 1 scaleTargetRef: #這指定要伸縮那些類型的Pod。 apiVersion: extensions/v1beta1 kind: Deployment #這裏指定對名爲 myapp-hpa-http-requests這個 Deployment控制器 下的全部Pod作自動伸縮. name: myapp-hpa-http-requests metrics: - type: Pods #設置監控指標是從那種類型的資源上獲取:它支持Resource,Object,Pods ; #resource:核心指標如:cpu,內存可指定此類型,若監控的資源指標是從Pod中獲取,那類型就是Pods pods: metricName: http_requests #http_requests就是自定義的監控指標,它是Prometheus中Pod中獲取的。 targetAverageValue: 800m #800m:是800個併發請求,由於一個併發請求,就須要一個CPU核心來處理,因此是800個豪核,就是800個併發請求。 # curl http://192.168.111.84:55066/metrics #注意:Prometheus抓取數據時,它要求獲取資源指標的數據格式以下: # HELP http_requests_total The amount of requests in total #HELP:告訴Prometheus這個數據的描述信息 # TYPE http_requests_total counter #TYPE: 告訴Prometheus這個數據的類型 http_requests_total 1078 #告訴Prometheus這個數據的值是多少。 # HELP http_requests_per_second The amount of requests per second the latest ten seconds # TYPE http_requests_per_second gauge http_requests_per_second 0.1 # 測試方法: 1. 先在一個終端上執行: for i in `seq 10000`; do curl http://K8S_CLUSTER_NODE_IP:SERVER_NODE_PORT/ ; done 2. 查看hpa的狀態 # kubectl describe hpa Name: myapp-hpa-http-requests Namespace: default ......... Reference: Deployment/myapp-hpa-http-requests Metrics: ( current / target ) "http_requests" on pods: 4366m / 800m Min replicas: 1 Max replicas: 8 Deployment pods: 8 current / 8 desired ........................ Events: Type Reason Age From Message ---- ------ ---- ---- ------- ..................... Normal SuccessfulRescale 51s horizontal-pod-autoscaler New size: 4; reason: pods metric http_requests above target Normal SuccessfulRescale 36s horizontal-pod-autoscaler New size: 8; reason: pods metric http_requests above target 3. 查看Pod # kubectl get pod NAME READY STATUS RESTARTS AGE myapp-hpa-http-requests-69c9968cdf-844lb 1/1 Running 0 24s myapp-hpa-http-requests-69c9968cdf-8hcjl 1/1 Running 0 24s myapp-hpa-http-requests-69c9968cdf-8lx9t 1/1 Running 0 39s myapp-hpa-http-requests-69c9968cdf-d4xdr 1/1 Running 0 24s myapp-hpa-http-requests-69c9968cdf-k4v6h 1/1 Running 0 114s myapp-hpa-http-requests-69c9968cdf-px2rl 1/1 Running 0 39s myapp-hpa-http-requests-69c9968cdf-t52xr 1/1 Running 0 39s myapp-hpa-http-requests-69c9968cdf-whjl6 1/1 Running 0 24s