在使用微服務會面臨最大的一個問題也就是在服務數量增加帶來的排查成本和監控成本,大家為了解決這些成本也衍生出了很多工作,當然在Istio中也很好的融合了這些組件,默認安裝下就已經帶上了這些組件(zipkin + jaeger , prometheus + grafana),本節就來看看怎么來使用這些組件
附上:
喵了個咪的博客:w-blog.cn
Istio官方地址:https://preliminary.istio.io/zh
Istio中文文檔:https://preliminary.istio.io/zh/docs/
PS : 此處基于當前最新istio版本1.0.3版本進行搭建和演示
一. 清理bookinfo重新創建
先重置官方示例bookinfo回到最初的狀態:
運行清理bookinfo腳本,并且重新創建
> ./istio-1.0.3/samples/bookinfo/platform/kube/cleanup.sh
namespace ? [default] istio-test
using NAMESPACE=istio-test
Deleted config: destinationrules details
...
Application cleanup successful
# 重新初始化
> kubectl apply -n istio-test -f istio-1.0.3/samples/bookinfo/platform/kube/bookinfo.yaml
> kubectl apply -n istio-test -f istio-1.0.3/samples/bookinfo/networking/bookinfo-gateway.yaml
> kubectl apply -n istio-test -f istio-1.0.3/samples/bookinfo/networking/destination-rule-all.yaml
二. 鏈路監控
在微服務中往往一次請求會盡力N多服務,那么每個服務的響應狀態這個業務經過哪些服務對開發或問題排查就顯得額外重要,鏈路監控是其中的一種解決方案,把微服務中的調用鏈進行記錄并且通過可視化的方式進行展示,行業中相對成熟的解決方案就是zipkin,但是因為zipkin的界面并不是那么友好一般我們配合著jaeger進行使用,istio也對它進行了整合.
2.1 訪問使用jaeger
通過內部映射的方式映射到本機的
> kubectl port-forward -n istio-system $(kubectl get pod -n istio-system -l app=jaeger -o jsonpath='{.items[0].metadata.name}') 16686:16686
或者也可修改成nodeport端口:
> kubectl edit svc jaeger-query -n istio-system
ports:
- name: query-http
port: 16686
protocol: TCP
targetPort: 16686
nodePort: 30686
selector:
app: jaeger
sessionAffinity: None
type: NodePort
在 Jaeger dashboard里從Service下選擇productpage,點擊Find Traces 按鈕,可以看到跟蹤信息:
進到下一層可以看到每個服務的調用層次以及總體消耗時間的分布:
在展開可以看到更多的相關內容
2.2 鏈路監控的必要條件 Headers 傳遞
為什么使用服務網格之后還需要傳遞指定的Headers呢? 這里就要從鏈路監控的機制來說了,在服務網格之前需要鏈路監控每個程序都需要向鏈路監控服務器發送消息,由第一個程序找鏈接監控發起ID獲取,接下來的每個程序被調用的時候都需要告知鏈路監控系統我是在這個鏈路ID之中,此時才能關聯整個鏈路.
雖然 Istio 代理能夠自動發送 Span 信息,但還是需要一些輔助手段來把整個跟蹤過程統一起來。應用程序應該自行傳播跟蹤相關的 HTTP Header,這樣在代理發送 Span 信息的時候,才能正確的把同一個跟蹤過程統一起來。
為了完成跟蹤的傳播過程,應用應該從請求源頭中收集下列的 HTTP Header,并傳播給外發請求:
- x-request-id
- x-b3-traceid
- x-b3-spanid
- x-b3-parentspanid
- x-b3-sampled
- x-b3-flags
- x-ot-span-context
如果查看示例服務,可以看到productpage服務(Python)從HTTP請求中提取所需的標頭:
def getForwardHeaders(request):
headers = {}
if 'user' in session:
headers['end-user'] = session['user']
incoming_headers = [ 'x-request-id',
'x-b3-traceid',
'x-b3-spanid',
'x-b3-parentspanid',
'x-b3-sampled',
'x-b3-flags',
'x-ot-span-context'
]
for ihdr in incoming_headers:
val = request.headers.get(ihdr)
if val is not None:
headers[ihdr] = val
#print "incoming: "+ihdr+":"+val
return headers
2.3 采集控制
Istio 默認捕獲所有請求的跟蹤。例如,何時每次訪問時都使用上面的 Bookinfo 示例應用程序 / productpage你在 Jaeger 看到了相應的痕跡儀表板。鏈路監控每次和鏈路服務器通訊也是有性能消耗的,在一個每天千萬pv的業務下把所有鏈路全部采集下來是不合適的,無論從CPU還是磁盤空間都很容易出現瓶頸,并且鏈路監控并不是日志是一種排查手段,所以我們需要在生產環境下進行采集頻率的限制:
找到pilot中PILOT_TRACE_SAMPLING環境變量從100%修改成10%的采集率:
> kubectl -n istio-system edit deploy istio-pilot
...
- name: PILOT_TRACE_SAMPLING
value: "10"
...
> :wq
再去刷新頁面10次在JaegerUI只會看到一次調用,這邊最小精度是0.01%有效值是0.0~100.0(不需要此功能可以完全不開啟)
三, 數據采集
Istio集成的另外一個利器就是prometheus + grafana了, prometheus作為基礎數據采集和存儲方式grafana進行了可定制化報表展示以及報警等機制,先使用樣的方式開啟外部端口或映射端口到本地:
> kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=prometheus -o jsonpath='{.items[0].metadata.name}') 9090:9090
> kubectl edit svc prometheus -n istio-system
ports:
- name: http-prometheus
port: 9090
protocol: TCP
targetPort: 9090
nodePort: 30090
selector:
app: prometheus
sessionAffinity: None
type: NodePort
就可以查詢各種指標了
例子一 :
# productpage服務的所有請求總數
> istio_requests_total{destination_service="productpage.istio-test.svc.cluster.local"}
例子二 :
# reviews 服務的 v3版本的所有請求總數
> istio_requests_total{destination_service="reviews.istio-test.svc.cluster.local", destination_version="v3"}
例子三 :
# 過去 5 分鐘對所有 productpage 服務的請求比例
> rate(istio_requests_total{destination_service=~"productpage.*", response_code="200"}[5m])
四, 監控可視化
當然直接使用prometheus并不是很方便對于用戶并不是特別友好,也不能做很多的預設,一般會配合grafana一起使用
> kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=grafana -o jsonpath='{.items[0].metadata.name}') 3000:3000
> kubectl edit svc grafana -n istio-system
ports:
- name: http
port: 3000
protocol: TCP
targetPort: 3000
nodePort: 33000
selector:
app: grafana
sessionAffinity: None
type: NodePort
讓后就可以指定各種各樣的指標了