1. 程式人生 > >Istio可觀測性

Istio可觀測性

# Istio可觀測性 Istio的可觀測性包括metrics,日誌,分散式鏈路跟蹤以及視覺化展示。下面主要介紹如何在istio中部署基於Prometheus的metrics監控,基於jaeger的鏈路跟蹤和基於kiali的視覺化介面。 [TOC] ## Prometheus ### 配置說明 在istio網格中,每個元件都會暴露一個提供metrics的endpoint。Prometheus可以從這些endpoints上抓取metrics(通過[Prometheus配置檔案](https://prometheus.io/docs/prometheus/latest/configuration/configuration/)來設定scraping,埠以及TLS等)。 為了採集整個網格的metrics,需要配置Prometheus scraping元件: 1. 控制面(`istiod` deployment) 2. ingress和egress閘道器 3. Envoy sidecar 4. 使用者應用(如果該應用也可以暴露Prometheus metrics的話) 為了簡化metrics的配置,istio提供瞭如下兩種操作模式: #### Option 1:合併metrics 為了簡化配置,istio可以通過`prometheus.io` annotations來控制所有scraping。這使Istio的scraping可以使用標準配置(例如[Helm `stable/prometheus`](https://github.com/helm/charts/tree/master/stable/prometheus) charts提供的配置)來做到開箱即用。 該選項預設是啟用的,但可以在安裝期間通過傳入`--set meshConfig.enablePrometheusMerge=false`來禁用該功能。當啟用時,會在所有的控制面pod上新增`prometheus.io` annotations來配置scraping。如果已經存在這些annotations,則會被覆蓋。通過該選項,Envoy sidecar會將istio的metrics和應用的metrics進行合併,合併後的metrics暴露地址為:`/stats/prometheus:15020`. > 通過kubect describe pod命令可以檢視pod的annotation,需要注意的是控制面和資料暴露的埠是不同的。資料面暴露的埠為15020,如下: > > ```yaml > prometheus.io/path: /stats/prometheus > prometheus.io/port: 15020 > prometheus.io/scrape: true > ``` > > 但istiod的埠為15014,ingress-gateway和egress-gateway的埠為15090。總體來說與官方[埠描述](https://istio.io/latest/docs/ops/deployment/requirements/#ports-used-by-istio)一致。 該選項會以明文方式暴露所有的metrics。 下面特性可能並不適用於所有場景: - 在抓取metrcis時啟用TLS - 應用暴露的metrics與istio的metrics的名稱相同。例如,應用暴露了一個名為`istio_requests_total`的metric,可能是因為應用本身也運行了Envoy - 部署的Prometheus沒有基於標準的`prometheus.io` annotation抓取metrics。 如果有必要,則可以在pod上新增`prometheus.istio.io/merge-metrics: "false"` annotation來禁用metrics合併功能。 #### Option 2:自定義抓取metrics配置 內建的demo profile會安裝Prometheus,幷包含了所有必要的scraping配置。可以在使用istioctl部署istio時傳入引數`--set values.prometheus.enabled=true`來部署Prometheus。 但內建的Prometheus缺少高階自定義配置功能,如認證的持久化等,導致其不大合適在生產環境中使用。為了使用已經存在的Prometheus,需要在Prometheus配置中新增scraping配置[`prometheus/configmap.yaml`](https://raw.githubusercontent.com/istio/istio/release-1.7/manifests/charts/istio-telemetry/prometheus/templates/configmap.yaml)。 該配置會新增抓取控制面以及所有Envoy sidecar的metrcis的功能。此外,還配置了一個job,用來抓取添加了`prometheus.io` annotation的所有資料面pod的應用metrics。 ##### TLS設定 控制面,閘道器和Envoy sidecar的metrics都以明文方式暴露。然而,應用metrics會遵循istio對負載的配置。例如如果啟用了[Strict mTLS](https://istio.io/latest/docs/tasks/security/authentication/authn-policy/#globally-enabling-istio-mutual-tls-in-strict-mode),那麼Prometheus需要使用istio證書來配置scrape 對於自建的Prometheus,參考[為沒有sidecar的應用程式提供證書和金鑰](https://istio.io/latest/blog/2020/proxy-cert/)一文來為Prometheus提供證書,並新增TLS scraping配置。 ### 總結 istio的metrics分為兩類:istio自身的metrics和應用產生的metrics,前者以明文方式暴露,後者遵循對應負載的配置,即,如果負載啟用了TLS,則Prometheus也需要配置TLS才能獲取應用的metrics。 istio的metrics主要通過[kubernetes_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config)服務發現進行採集。其中`prometheus.io/path`和`prometheus.io/port` annotation分別對應metrics `meta_kubernetes_pod_annotation_prometheus_io_scrape`和`meta_kubernetes_pod_annotation_prometheus_io_path` 。簡單配置如下: ```yaml - job_name: 'kubernetes-pods' kubernetes_sd_configs: - role: pod relabel_configs: - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] action: keep regex: true - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] action: replace target_label: __metrics_path__ regex: (.+) - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] action: replace regex: ([^:]+)(?::\d+)?;(\d+) replacement: $1:$2 target_label: __address__ - action: labelmap regex: __meta_kubernetes_pod_label_(.+) - source_labels: [__meta_kubernetes_namespace] action: replace target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_pod_name] action: replace target_label: kubernetes_pod_name ``` 更多配置可以參見官方提供的[配置](https://raw.githubusercontent.com/istio/istio/release-1.7/manifests/charts/istio-telemetry/prometheus/templates/configmap.yaml)。 ## Jaeger ### 概述 分散式跟蹤使使用者可以通過分佈在多個服務中的網格跟蹤請求。通過這種方式可以瞭解請求延遲,並通過視覺化實現序列化和並行。 Istio利用[Envoy的分散式跟蹤](https://www.envoyproxy.io/docs/envoy/v1.12.0/intro/arch_overview/observability/tracing)特性提供開箱即用的跟蹤整合。特別地,istio提供了選項來安裝不同的跟蹤後端,以及配置代理來發送這些後端自動傳送跟蹤span。檢視[Zipkin](https://istio.io/latest/docs/tasks/observability/distributed-tracing/zipkin/), [Jaeger](https://istio.io/latest/docs/tasks/observability/distributed-tracing/jaeger/)和[Lightstep](https://istio.io/latest/docs/tasks/observability/distributed-tracing/lightstep/)來了解istio如何與這些跟蹤系統共同工作。 ### 跟蹤上下文的傳遞 雖然istio代理可以自動傳送span,但它們需要一些提示來將整個跟蹤聯絡在一起。應用需要傳遞合適的HTTP首部,這樣當代理髮送span資訊時,這些span可以正確地關聯到單個跟蹤中。 為了實現上述目的,應用需要在傳入請求中收集並傳遞如下首部到任何傳出請求中: - `x-request-id` - `x-b3-traceid` - `x-b3-spanid` - `x-b3-parentspanid` - `x-b3-sampled` - `x-b3-flags` - `x-ot-span-context` 此外,基於[OpenCensus](https://opencensus.io/) (如Stackdriver)的跟蹤整合需要傳遞下面首部: - `x-cloud-trace-context` - `traceparent` - `grpc-trace-bin` 如果檢視istio的`productpage`例子的Python原始碼,可以看到應用會使用[OpenTracing](https://opentracing.io/)庫從HTTP請求中抽取需要的首部: ```python def getForwardHeaders(request): headers = {} # x-b3-*** headers can be populated using the opentracing span span = get_current_span() carrier = {} tracer.inject( span_context=span.context, format=Format.HTTP_HEADERS, carrier=carrier) headers.update(carrier) # ... incoming_headers = ['x-request-id', 'x-datadog-trace-id', 'x-datadog-parent-id', 'x-datadog-sampled'] # ... for ihdr in incoming_headers: val = request.headers.get(ihdr) if val is not None: headers[ihdr] = val return headers ``` `reviews`應用會使用`requestHeaders`做類似的事情: ```java @GET @Path("/reviews/{productId}") public Response bookReviewsById(@PathParam("productId") int productId, @Context HttpHeaders requestHeaders) { // ... if (ratings_enabled) { JsonObject ratingsResponse = getRatings(Integer.toString(productId), requestHeaders); ``` 當在應用程式中執行下游呼叫時,需要包含這些首部。 ### 使用Jaeger 本例將使用[Bookinfo](https://istio.io/latest/docs/examples/bookinfo/)。 ### 部署 1. 使用如下方式快速部署一個用於演示的Jaeger。當然也可以參考[Jaeger](https://www.jaegertracing.io/)官方檔案進行自定義部署。 ```shell $ kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.7/samples/addons/jaeger.yaml ``` 2. 可以參考[此處](https://istio.io/latest/docs/tasks/observability/distributed-tracing/configurability/#customizing-trace-sampling)修改取樣率 ### 訪問Jaeger 上面部署的Jaeger對應的k8s service名為`tracing`,檢視該service,可以看到容器和service暴露的埠均為16686。 ```shell # oc describe svc tracing Name: tracing Namespace: istio-system Labels: app=jaeger Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"jaeger"},"name":"tracing","namespace":"istio-system"},"s... Selector: app=jaeger Type: ClusterIP IP: 10.84.179.208 Port: http-query 80/TCP TargetPort: 16686/TCP Endpoints: 10.80.2.226:16686 Session Affinity: None Events: