Contour 學習筆記(一):使用 Contour 接管 Kubernetes 的南北流量
> 原文連結:Contour 學習筆記(一):使用 Contour 接管 Kubernetes 的南北流量
在 Kubernetes 中執行大規模以 Web 為中心的工作負載,最關鍵的需求之一就是在 L7
層實現高效流暢的入口流量管理。自從第一批 Kubernetes Ingress Controller
開發完成以來,Envoy
(由 Matt Klein 和 Lyft 團隊開發)已經成為雲原生生態系統中的新生力量。Envoy 之所以受到支援,因為它是一個 CNCF 託管的專案,與整個容器圈和雲原生架構有著天然的支援。
容器公司 Heptio 開源的專案 Contour 使用 Envoy
據官方部落格介紹,Heptio Contour
可以為使用者提供以下好處:
- 一種簡單的安裝機制來快速部署和整合 Envoy。
- 與 Kubernetes 物件模型的整合。
Ingress
配置的動態更新,而無需重啟底層負載均衡器。- 專案成熟後,將允許使用 Envoy 一些強大的功能,如熔斷器、外掛式的處理器鏈,以及可觀測性和可除錯性,可以非常方便地對接監控系統。
- IngressRoute 之間可以級聯,用來做藍綠部署非常方便。
下面我們就來試用一下。
1. 安裝步驟
Contour Ingress controller 由兩個元件組成:
Envoy
: 提供高效能反向代理。Contour
: 充當 Envoy 的控制平面,為 Envoy 的路由配置提供統一的來源。
官方文件提供了三種部署方法:
- 通過
DaemonSet
來部署,每個節點上跑一個 Contour 例項(Contour 與 Envoy 在同一個 Pod 中)。 - 通過
Deployment
來部署,總共跑兩個 Contour 例項(Contour 與 Envoy 在同一個 Pod 中)。 - 通過 Deployment 來部署 Contour,總共跑兩個 Contour 例項;通過 DaemonSet 來部署 Envoy,每個節點上跑一個 Envoy 例項。
經過老夫目測,第三種方案比較妙,這樣可以讓 Contour 和 Envoy 這兩個元件解耦,可以分別按需對不同的元件進行擴充套件,具體的優勢如下:
- Envoy 以 Daemonset 的形式執行,具有很強的擴充套件性,後續可通過
ipvs
和keepalived
等工具來實現其負載均衡和高可用。 - Envoy 執行的網路模式是
hostNetwork
,減少了額外的網路效能損耗。 - Contour 與 Envoy 之間通過雙向認證的自簽名證書進行通訊,大大增強了安全性。
- 升級 Contour 不需要重啟 Envoy。
聽起來好像不錯的樣子。
我們就採用第三種方案來部署,首先克隆官方倉庫,進入 manifest 清單目錄:
$ git clone https://github.com/heptio/contour
$ cd contour/examples/ds-hostnet-split
為了便於檢視 envoy 的配置,修改 03-envoy.yaml
,將 envoy 的 admin-adress
設定為 0.0.0.0,並暴露 9001 埠:
...省略...
initContainers:
- args:
- bootstrap
- --admin-address=0.0.0.0
- /config/contour.json
...省略...
將 Envoy Service 的型別改為 ClusterIP
:
$ cat 02-service-envoy.yaml
apiVersion: v1
kind: Service
metadata:
name: envoy
namespace: heptio-contour
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: nlb
spec:
externalTrafficPolicy: Local
ports:
- port: 80
name: http
protocol: TCP
- port: 443
name: https
protocol: TCP
selector:
app: envoy
type: ClusterIP
部署:
$ kubectl apply ./
檢視狀態:
$ kubectl -n heptio-contour get pod
NAME READY STATUS RESTARTS AGE
contour-767fd99989-27qjw 0/1 Running 0 21s
contour-767fd99989-kcjxz 0/1 Running 0 21s
contour-certgen-29nqs 0/1 Completed 0 21s
envoy-cnzvm 0/1 Running 0 21s
envoy-lb8mm 0/1 Running 0 21s
envoy-qzmt4 0/1 Running 0 21s
$ kubectl -n heptio-contour get job
NAME COMPLETIONS DURATION AGE
contour-certgen 1/1 2s 4m42s
contour-certgen
是一個 Job,它會生成有效期為一年的 mTLS(雙向認證)證書,並將其掛載到 Contour 和 Envoy 的容器中。如果你想自定義證書,可以參考官方文件。
> 如果你還沒有部署 Kubernetes 叢集怎麼辦?廢話,當然是用 sealos 啊!分分鐘搞起一個高可用叢集。
2. Ingress 測試
安裝結束後,我們就可以來測試 Ingress 了。在 examples/example-workload
目錄下包含一個示例應用,可以直接使用:
$ kubectl apply -f examples/example-workload/kuard-ingressroute.yaml
檢視建立好的資源:
$ kubectl get po,svc,ingressroute -l app=kuard
NAME READY STATUS RESTARTS AGE
pod/kuard-67789b8754-5c4w7 1/1 Running 0 63s
pod/kuard-67789b8754-fpdfb 1/1 Running 0 63s
pod/kuard-67789b8754-fx9bn 1/1 Running 0 63s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kuard ClusterIP 10.97.46.79 <none> 80/TCP 63s
NAME FQDN TLS SECRET FIRST ROUTE STATUS STATUS DESCRIPTION
ingressroute.contour.heptio.com/kuard kuard.local / valid valid IngressRoute
將域名加入本地電腦的 hosts:
$ echo "$INGRESS_HOST kuard.local" >> /etc/hosts
其中 $INGRESS_HOST
是任意執行 Envoy 節點的 IP。
現在我們就可以在瀏覽器中輸入域名 kuard.local
訪問應用了:
3. Contour 工作原理
Contour 同時支援 Ingress
資源物件和 IngressRoute
資源物件(通過 CRD 建立),這些物件都是為進入叢集的請求提供路由規則的集合。這兩個物件的結構和實現方式有所不同,但它們的核心意圖是相同的,都是為進入叢集的請求提供路由規則。如不作特殊說明,後面當我們描述 “Ingress” 時,它將同時適用於 Ingress
和 IngressRoute
物件。
通常情況下,當 Envoy 配置了 CDS
的 endpoint 時,它會定期輪詢端點,然後將返回的 JSON 片段合併到其執行配置中。如果返回到 Envoy 的叢集配置代表當前的 Ingress 物件的集合,則可以將 Contour 視為從 Ingress
物件到 Envoy
叢集配置的轉換器。隨著 Ingress 物件的新增和刪除,Envoy 會動態新增並刪除相關配置,而無需不斷重新載入配置。
在實踐中,將 Ingress 物件轉換為 Envoy 配置更加微妙,需要將 Envoy 中的 xDS 配置(包括 CDS
,EDS
和 RDS
)對映到 Kubernetes 中。Contour 至少需要觀察 Ingress
、Service
和 Endpoint
這幾個資源物件以構建這些服務的響應,它通過 client-go
的 cache/informer 機制免費獲得這些 watchers
。這些 watchers 提供新增,更新和刪除物件的邊緣觸發通知,也可以通過 watch API
在本地快取快取物件,以便後續查詢。
Contour 將收集到的這些物件處理為虛擬主機及其路由規則的有向非迴圈圖(DAG),這表明 Contour 將有權構建路由規則的頂級檢視,並將群集中的相應服務和TLS祕鑰連線在一起。一旦構建了這個新的資料結構,我們就可以輕鬆實現 IngressRoute
物件的驗證,授權和分發。改資料結構匯出的 png
圖片如下圖所示:
<center>![](https://oscimg.oschina.net/oscnet/5f97e86a7acfb149548de8a86779eb4f648.jpg)</center>
Envoy API 呼叫和 Kubernetes API 資源之間的對映關係如下:
-
CDS : 叢集發現服務。對映為 Kubernetes 中的
Service
以及一部分 Ingress 物件的TLS
配置。 -
EDS : 服務發現服務。對映為 Kubernetes 中的
Endpoint
。Envoy 使用 EDS 自動獲取Cluster
成員,這與 Endpoint 物件中包含的資訊非常匹配。Envoy 使用 Contour 在EDS
響應中返回的名稱查詢EDS
。 -
RDS : 路由發現服務。對映為 Kubernetes 中的
Ingress
。提供了虛擬主機名和字首路由資訊的 RDS 與 Ingress 匹配得更好。
4. 對映關係詳情
CDS
CDS
更像是 Kubernetes 中的 Service
資源,因為 Service 是具體 Endpoint
(Pods)的抽象,Envoy Cluster 是指 Envoy 連線到的一組邏輯上相似的上游主機(參考下文的 RDS)。其中 TLS
配置也是 CDS 的一部分,而 Kubernetes 中的 TLS 資訊由 Ingress 提供,所以這部分之間的對映關係會有些複雜。
EDS
EDS
更像是 Kubernetes 中的 Endpoint
資源,這部分對映關係的實現最簡單。Contour 將 Endpoint 的響應物件轉換為 EDS 的 { address: [] }
json 配置塊。
RDS
RDS
更像是 Kubernetes 中的 Ingress
資源。RDS 將字首,路徑或正則表示式之一路由到 Envoy 群集。Envoy 叢集的名稱可以從 Ingress 的 IngressSpec
的配置項中獲取(比如:namespace/serviceName_servicePort
),因為這是一個選擇器,它會匹配 Service 物件被轉換後返回的 CDS 物件。
5. Contour 架構分析
Contour Ingress controller 由兩個元件組成:
Envoy
: 提供高效能反向代理。Contour
: 充當 Envoy 的控制平面,為 Envoy 的路由配置提供統一的來源。
以本文的部署方式為例,在 Envoy 的 Pod 初始化期間,Contour 作為 Init
容器執行,並將 bootstrap(初始化)配置寫入一個 temporary volume。該 Volume
被傳遞給 Envoy 容器並告訴 Envoy 將另一個 Deployment 中的 Contour 容器視為控制平面。
初始化完成後,Envoy 容器啟動,檢索 Contour 寫入的 bootstrap 配置,並開始輪詢 Contour 以熱更新配置。如果控制平面無法訪問,Envoy 將會進行優雅重試。
Contour 相當於 Kubernetes API 的客戶端。它監視 Ingress
,Service
和 Endpoint
物件,並通過將其物件快取轉換為相關的 JSON
欄位來充當其 Envoy 的控制平面。
從 Kubernetes 到 Contour 的資訊轉換是通過 SharedInformer
框架 watching API 來完成的;而從 Contour 到 Envoy 的資訊轉換是通過 Envoy 定期輪詢來實現的。
6. IngressRoute 介紹
Ingress 物件從 Kubernetes 1.1 版本開始被引進,用來描述進入叢集的請求的 HTTP 路由規則。但迄今為止 Ingress 物件還停留在 beta
階段,不同的 Ingress Controller 外掛為了新增 HTTP 路由的額外屬性,只能通過新增大量的 annotation
來實現,而且每個外掛的 annotation 都不一樣,非常混亂。
IngressRoute
CRD 的目標就是擴充套件 Ingress API 的功能,以便提供更豐富的使用者體驗以及解決原始設計中的缺點。
**目前 Contour 是唯一支援 IngressRoute CRD 的 Kubernetes Ingress Controller。**下面就來看看它與 Ingress 相比的優點:
- 安全地支援多團隊 Kubernetes 叢集,能夠限制哪些名稱空間可以配置虛擬主機和 TLS 憑據。
- 允許將路徑或域名的路由配置分發給另一個名稱空間。
- 接受單個路由中的多個服務,並對它們之間的流量進行負載均衡。
- 無需通過新增
annotation
就可以定義服務權重和負載均衡策略。 - 在建立時驗證 IngressRoute 物件,並在建立後報告驗證是否有效。
從 Ingress 到 IngressRoute
一個基本的 Ingress
物件如下所示:
# ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: basic
spec:
rules:
- host: foo-basic.bar.com
http:
paths:
- backend:
serviceName: s1
servicePort: 80
這個 Ingress 物件名為 basic
,它將傳入的 HTTP 流量路由到標頭檔案中 Host:
欄位值為 foo-basic.bar.com
且埠為 80 的 s1
服務。該路由規則通過 IngressRoute
來實現如下:
# ingressroute.yaml
apiVersion: contour.heptio.com/v1beta1
kind: IngressRoute
metadata:
name: basic
spec:
virtualhost:
fqdn: foo-basic.bar.com
routes:
- match: /
services:
- name: s1
port: 80
對應關係很簡單,我就不再詳細介紹了,更多功能配置可以參考官方倉庫的文件:IngressRoute。
7. Envoy 初始配置檔案
Contour 會根據啟動引數和 K8S API Server 中的配置資訊生成 Envoy 的初始配置檔案,可以使用下面的命令將 Envoy Pod 中的配置檔案匯出來檢視其中的內容:
$ kubectl -n heptio-contour exec envoy-lb8mm -- cat /config/envoy.json > envoy.json
開啟網站 https://www.bejson.com/jsonviewernew/,將配置檔案內容複製貼上進去,可以看到配置檔案的結構如圖所示:
其中各個配置節點的內容如下:
Dynamic_resources
配置動態資源,這裡配置了 LDS 和 RDS 伺服器。
"dynamic_resources": {
"lds_config": {
"api_config_source": {
"api_type": "GRPC",
"grpc_services": [
{
"envoy_grpc": {
"cluster_name": "contour"
}
}
]
}
},
"cds_config": {
"api_config_source": {
"api_type": "GRPC",
"grpc_services": [
{
"envoy_grpc": {
"cluster_name": "contour"
}
}
]
}
}
}
Static_resources
配置靜態資源,包括了 contour
和 service-stats
兩個 cluster,其中 contour cluster 對應前面 dynamic_resources 中的 LDS 和 RDS 配置,指明瞭 Envoy 用於獲取動態資源的伺服器地址。
"static_resources": {
"clusters": [
{
"name": "contour",
"alt_stat_name": "heptio-contour_contour_8001",
"type": "STRICT_DNS",
"connect_timeout": "5s",
"load_assignment": {
"cluster_name": "contour",
"endpoints": [
{
"lb_endpoints": [
{
"endpoint": {
"address": {
"socket_address": {
"address": "contour",
"port_value": 8001
}
}
}
}
]
}
]
},
"circuit_breakers": {
"thresholds": [
{
"priority": "HIGH",
"max_connections": 100000,
"max_pending_requests": 100000,
"max_requests": 60000000,
"max_retries": 50
},
{
"max_connections": 100000,
"max_pending_requests": 100000,
"max_requests": 60000000,
"max_retries": 50
}
]
},
"tls_context": {
"common_tls_context": {
"tls_certificates": [
{
"certificate_chain": {
"filename": "/certs/tls.crt"
},
"private_key": {
"filename": "/certs/tls.key"
}
}
],
"validation_context": {
"trusted_ca": {
"filename": "/ca/cacert.pem"
},
"verify_subject_alt_name": [
"contour"
]
}
}
},
"http2_protocol_options": {}
},
{
"name": "service-stats",
"alt_stat_name": "heptio-contour_service-stats_9001",
"type": "LOGICAL_DNS",
"connect_timeout": "0.250s",
"load_assignment": {
"cluster_name": "service-stats",
"endpoints": [
{
"lb_endpoints": [
{
"endpoint": {
"address": {
"socket_address": {
"address": "0.0.0.0",
"port_value": 9001
}
}
}
}
]
}
]
}
}
]
}
Admin
配置 Envoy 的日誌路徑以及管理埠。
"admin": {
"access_log_path": "/dev/null",
"address": {
"socket_address": {
"address": "0.0.0.0",
"port_value": 9001
}
}
}
結合 Envoy 的初始化配置檔案和第 5 節的分析,我們可以大致看到 Contour 通過 Envoy 來實現南北流量管理的基本原理。即控制平面將 xDS server 資訊通過 static resource
的方式配置到 Envoy 的初始化配置檔案中,Envoy 啟動後通過 xDS server 獲取到 dynamic resource
,包括叢集中的 service 資訊及路由規則。
Envoy 配置初始化流程:
- Envoy initContainer 根據啟動引數和 K8S API Server 中的配置資訊生成 Envoy 的初始配置檔案
envoy.json
,該檔案告訴 Envoy 從xDS server
中獲取動態配置資訊,並配置了 xDS server 的地址資訊,即控制平面的Contour
。 - Envoy 使用配置檔案
envoy.json
啟動。 - Envoy 根據獲取到的動態配置啟動 Listener,並根據 Listener 的配置,結合 Route 和 Cluster 對進入的流量進行處理。
8. IngressRoute 配置對映
通過上節的分析我們知道,Envoy 中實際生效的配置是由初始化配置檔案中的靜態配置和從 Contour 獲取的動態配置一起組成的,我們可以通過 Envoy 的管理介面來獲取 Envoy 的完整配置,先開啟 Envoy 的管理介面:
然後點選 config_dump
,就能看到 Envoy 的完整配置:
我們在第二節建立了一個 ingressroute,現在來看看它是怎麼對映到 Envoy 的配置檔案中的。你可以到 config_dump
中查詢相關配置,但還有更好的辦法,我們可以通過 Contour 的命令列工具直接呼叫 Contour 的 xDS gRPC 介面來分別檢視 Envoy 的 Listener、Route、Cluster 和 Endpoint 配置。
Contour 總共有兩個例項,通過選舉來實現高可用,被選中的例項作為 leader
來對外提供服務。
$ kubectl -n heptio-contour get pod -l app=contour
NAME READY STATUS RESTARTS AGE
contour-767fd99989-27qjw 1/1 Running 0 14h
contour-767fd99989-kcjxz 0/1 Running 0 14h
看看哪個是 leader:
可以看到該例項不是 leader,我們到另一個例項中去檢視 Envoy xDS 配置。
Listener
Envoy 採用 listener 來接收並處理 downstream
發過來的請求,listener 的處理邏輯是外掛式的,可以通過配置不同的 filter 來插入不同的處理邏輯。Listener 可以繫結到 IP Socket
或者 Unix Domain Socket
上,也可以不繫結到一個具體的埠上,而是接收從其他 listener 轉發來的資料。
Listener 的配置可以通過下面的命令檢視:
$ kubectl -n heptio-contour exec -it contour-767fd99989-27qjw -- contour cli --cafile=/ca/cacert.pem --cert-file=/certs/tls.crt --key-file=/certs/tls.key lds
可以看到 Listener 被繫結到了 80 埠上,同時通過 RDS 配置了一個路由規則 ingress_http
,在路由規則中再根據不同的請求目的地對請求進行處理。
Route
Route 用來配置 Envoy 的路由規則,根據 host 來對請求進行路由分發。
Route 的配置可以通過下面的命令檢視:
$ kubectl -n heptio-contour exec -it contour-767fd99989-27qjw -- contour cli --cafile=/ca/cacert.pem --cert-file=/certs/tls.crt --key-file=/certs/tls.key rds
上面是 ingress_http
的路由配置,對應了兩個 virtual host
,其中一個是預設路由(圖中省略),上面展示的是 kuard 的路由,對應到 Cluster default/kuard/80/da39a3ee5e
。其中 domains: "kuard.local:*"
表示允許訪問的域名為 kuard.local,埠可以是任意值。
Cluster
Cluster 是一個服務叢集,Cluster 中包含一個到多個 endpoint,每個 endpoint 都可以提供服務,Envoy 根據負載均衡演算法將請求傳送到這些 endpoint 中。
Cluster 的配置可以通過下面的命令檢視:
$ kubectl -n heptio-contour exec -it contour-767fd99989-27qjw -- contour cli --cafile=/ca/cacert.pem --cert-file=/certs/tls.crt --key-file=/certs/tls.key cds
cluster_name: "contour"
表示通過 xDS 介面從 contour 控制平面動態獲取 Endpoint 資訊。獲取到的 Endpoint 是 default/kuard
。
Endpoint
Endpoint 就對應到 Kubernetes 中的 Endpoint
資源,對應的即是 Pod 的 IP+Port
。
Cluster 的配置可以通過下面的命令檢視:
$ kubectl -n heptio-contour exec -it contour-767fd99989-27qjw -- contour cli --cafile=/ca/cacert.pem --cert-file=/certs/tls.crt --key-file=/certs/tls.key eds|grep "default/kuard" -A 34 -B 2
驗證一下:
$ kubectl get ep -l app=kuard
NAME ENDPOINTS AGE
kuard 100.118.117.18:8080,100.119.55.150:8080,100.91.147.204:8080 17h
9. 對接監控
Contour 和 Envoy 都暴露一些監控指標可以被 Prometheus
抓取,官方也提供了 Prometheus 和 Grafana 的部署模板,但一般情況下我們都會有自己的監控系統,比如 prometheus-operator,只需要將官方的 Grafana 模板匯入自己的 Grafana 中就可以了,後續會探討詳細步驟。
Envoy Metrics
Envoy 預設通過 admin 介面暴露監控指標,為了避免暴露 admin 介面,Contour 建立了一個靜態 Listener,只將訪問路徑為 /stats
的流量轉發到 service-stats
Cluster,即 admin 介面,其他所有請求一律拒絕訪問。
> 本文只是為了方便檢視,才將 admin 介面的 IP 改為 0.0.0.0,生產環境建議不要改,預設值為 127.0.0.1
。
所以 Envoy 在 8002
埠暴露監控指標,路徑為 /stats/prometheus
。
Contour Metrics
Contour 在 8000
埠上暴露監控指標,路徑為 /metrics
。包含以下監控指標:
- contour_ingressroute_total (gauge) : IngressRoute 的總數量,包括狀態為
Valid / Invalid / Orphaned
的 IngressRoute。 - contour_ingressroute_orphaned_total (gauge) : 狀態為
Orphaned
的 IngressRoute 數量。 - contour_ingressroute_root_total (gauge) :
Root
IngressRoute 的數量(每個 vhost 只有一個 Root IngressRoute)。 - contour_ingressroute_valid_total (gauge) : 狀態為
Valid
的 IngressRoute 數量。 - contour_ingressroute_invalid_total (gauge) : 狀態為
Invalid
的 IngressRoute 數量。 contour_ingressroute_dagrebuild_timestamp (gauge)
: 最近一次重建 DAG 的時間戳。
下面就來教大家怎麼將 Contour 接入 Prometheus-Operator,對 Prometheus-Operator 不熟的同學,推薦看一下張館長的這篇文章:全手動部署prometheus-operator監控Kubernetes叢集遇到的坑。
RBAC 授權
為了讓 Prometheus 能夠 list
其他 namespace 中的 pod,我們需要賦予它相應的許可權,首先進入 kube-prometheus
專案的 manifests 目錄:
$ cd kube-prometheus/manifests
$ ll *SpecificNamespace*
4 -rw-r--r-- 1 root root 988 8月 27 05:22 prometheus-roleBindingSpecificNamespaces.yaml
4 -rw-r--r-- 1 root root 1078 8月 27 05:15 prometheus-roleSpecificNamespaces.yaml
修改 prometheus-roleSpecificNamespaces.yaml
,向其中新增如下的 Role:
- apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: prometheus-k8s
namespace: heptio-contour
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- pods
verbs:
- get
- list
- watch
修改 prometheus-roleBindingSpecificNamespaces.yaml
,向其中新增如下的 RoleBinding:
- apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: prometheus-k8s
namespace: heptio-contour
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: prometheus-k8s
subjects:
- kind: ServiceAccount
name: prometheus-k8s
namespace: monitoring
然後建立相應的 Role
和 RoleBinding
:
$ kubectl apply -f prometheus-roleSpecificNamespaces.yaml
$ kubectl apply -f prometheus-roleBindingSpecificNamespaces.yaml
修改 Contour manifest 檔案
Prometheus 監控的物件被叫做 Target
,Target 通過 Cluster 中的 Endpoint
資源來定義,每個監控物件都有一個對應的 Endpoint。而 ServiceMonitor
是 Target 的抽象,ServiceMonitor 通過標籤來找到對應的 Endpoint,然後將相應的 Target 新增到 Prometheus 的監控列表中。
預設情況下 Contour 的 Service 是沒有打標籤的,所以我們需要修改 yaml 檔案,加上相應的標籤。首先修改 Contour Deployment 的 yaml 檔案:
# 03-contour.yaml
ports:
- containerPort: 8001
name: xds
protocol: TCP
- containerPort: 8000
name: http-metrics # 將 name 改為 http-metrics
protocol: TCP
再修改 Contour Service 的 yaml 檔案:
# 02-service-envoy.yaml
ports:
- port: 80
name: http
protocol: TCP
- port: 443
name: https
protocol: TCP
# 新增新埠
- port: 8002
name: http-metrics
protocol: TCP
Envoy 類似,先修改 Envoy Deployment 的 yaml 檔案:
# 03-envoy.yaml
ports:
- containerPort: 80
hostPort: 80
name: http
protocol: TCP
- containerPort: 443
hostPort: 443
name: https
protocol: TCP
# 新增新埠
- containerPort: 8002
hostPort: 8002
name: http-metrics
protocol: TCP
再修改 Envoy Service 的 yaml 檔案:
# 02-service-envoy.yaml
ports:
- port: 80
name: http
protocol: TCP
- port: 443
name: https
protocol: TCP
# 新增新埠
- port: 8002
name: http-metrics
protocol: TCP
最後重新 apply 一下:
# 在 contour/examples/ds-hostnet-split 目錄下
$ kubectl apply -f ./
建立 ServiceMonitor
接下來就是建立相應的 ServiceMonitor
來抓取指標資料,沒什麼好說的,自己看 yaml 檔案:
$ cat prometheus-serviceMonitorContour.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
labels:
app: contour
name: contour
namespace: monitoring
spec:
endpoints:
- interval: 30s
port: http-metrics
jobLabel: app
namespaceSelector:
matchNames:
- heptio-contour
selector:
matchLabels:
app: contour
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
labels:
app: envoy
name: envoy
namespace: monitoring
spec:
endpoints:
- interval: 30s
path: /stats/prometheus
port: http-metrics
namespaceSelector:
matchNames:
- heptio-contour
selector:
matchLabels:
app: envoy
建立 IngressRoute
為了檢視 Prometheus
和 Grafana
的 Dashboard,我們需要為它們建立相應的 IngressRoute,yaml 檔案內容如下:
# ingressroute-prometheus.yaml
apiVersion: contour.heptio.com/v1beta1
kind: IngressRoute
metadata:
labels:
app: grafana
name: grafana
namespace: monitoring
spec:
virtualhost:
fqdn: grafana.sealos.io
routes:
- match: /
services:
- name: grafana
port: 3000
---
apiVersion: contour.heptio.com/v1beta1
kind: IngressRoute
metadata:
labels:
app: prometheus
name: prometheus
namespace: monitoring
spec:
virtualhost:
fqdn: prometheus.sealos.io
routes:
- match: /
services:
- name: prometheus-k8s
port: 9090
直接 apply:
$ kubectl apply -f ingressroute-prometheus.yaml
將域名寫入本地電腦的 hosts 中:
$ echo "$INGRESS_HOST grafana.sealos.io" >> /etc/hosts
$ echo "$INGRESS_HOST prometheus.sealos.io" >> /etc/hosts
其中 $INGRESS_HOST
是任意執行 Envoy 節點的 IP。
現在我們可以在瀏覽器中輸入域名 prometheus.sealos.io
來檢視 Prometheus Target 狀態。
可以看到這兩個 Target 已經被抓取到了。
匯入 Grafana 模板
前面提到 Contour 官方倉庫中提供了 Grafana Dashboard 模板,現在我們要做的事就是把這個模板匯入到自己的 Grafana 中。官方的 Grafana Dashboard 模板定義在 contour/examples/grafana
目錄下的 ConfigMap 檔案中,可以先把它匯出來:
# 假設 contour 專案在你的 $HOME 目錄
$ sed '/---/,$d' ~/contour/examples/grafana/02-grafana-configmap.yaml \
sed 's/grafana-dashs/grafana-dashboard-contour/' \
sed 's/contour-monitoring/monitoring/' \
sed 's/kubernetes_pod_name/pod/g' \
sed 's/ingress_http_update/update/g' \
kubectl apply -f -
configmap/grafana-dashboard-contour created
建立了 ConfigMap
後,還要再掛載到 Grafana 的 Dashboard 中,所以需要修改 Grafana Deployment 的 yaml 檔案:
# ~/kube-prometheus/manifests/grafana-deployment.yaml
volumeMounts:
- mountPath: /var/lib/grafana
name: grafana-storage
readOnly: false
...省略...
# 新增掛載
- mountPath: /grafana-dashboard-definitions/0/contour
name: grafana-dashboard-contour
readOnly: false
...省略...
volumes:
- emptyDir: {}
name: grafana-storage
...省略...
# 新增 ConfigMap
- configMap:
name: grafana-dashboard-contour
name: grafana-dashboard-contour
重新 apply 一下:
$ kubectl apply -f grafana-deployment.yaml
現在在瀏覽器中輸入域名 grafana.sealos.io
,就可以看到 Contour 和 Envoy 的 Dashboard 了。
對接監控到這裡就結束了,剩下的大家可以自己去探索,總體來說難度還是稍微有點大,希望我的細心講解能夠幫助到你。
微信公眾號
掃一掃下面的二維碼關注微信公眾號,在公眾號中回覆◉加群◉即可加入我們的雲原生交流群,和孫巨集亮、張館長、陽明等大佬一起探討雲原生技術