天天看點

采用 NGINX Ingress Controller 支援 OpenTracing?

原文作者:Raúl Marrero Rodríguez of F5

原文連結:​​采用 NGINX Ingress Controller for Kubernetes 支援 OpenTracing? - NGINX​​

轉載來源:NGINX 官方網站

摘要

近年來,許多企業紛紛在生産環境中采用該平台與微服務架構。然而,采用分布式服務也帶來了新的挑戰。想要識别故障或性能問題,我們需要分布式的追蹤工具。

OpenTracing 是一個用于分布式跟蹤的規範和api集。為了在使用 NGINX 和 NGINX Plus Ingress Controllers for Kubernetes 時對叢集中的流量執行負載均衡,我們在 Kubernetes 叢集中添加了對 HTTP 和 gRPC 請求 OpenTracing 的原生支援。

使用Open Tracing現有多種用例,本文将重點讨論如何使用請求上下文傳播跟蹤伺服器端點。

近年來,Kubernetes 的關注度穩健增長日益獲得業内青睐,許多企業紛紛在生産環境中采用該平台與微服務架構。然而,采用分布式服務也帶來了新的挑戰。充分了解和調試微服務應用程式的運作并非易事,尤其在服務數量多的情況下。想要識别故障或性能問題,我們需要​​分布式的追蹤​​工具 —— 當資料在構成應用的微服務之間傳輸時,這個工具能夠端到端地追蹤請求。

​​OpenTracing​​​ 是一個用于分布式跟蹤的規範和api集。在​​此前發表的一篇博文​​​中,我們展示了如何使用OpenTracing社群建立的開源子產品(​​nginx-opentracing​​​ 為 NGINX Open Source 和 NGINX Plus 代理和負載平衡的應用程式啟用分布式跟蹤。在撰寫本文時,OpenTracing 提供 ​​9 種程式設計語言​​的類庫。

現在,為了在使用 NGINX 和 NGINX Plus Ingress Controllers for Kubernetes 時對叢集中的流量執行負載均衡,我們還在 Kubernetes 叢集中添加了對 HTTP 和 gRPC 請求 OpenTracing 的原生支援。

使用 OpenTracing 現有多種用例,此處我們将重點讨論如何使用請求上下文傳播​​跟蹤伺服器端點​​。在分布式環境中,叢集内的每個應用均被視為不同的伺服器。設想一下,兩個應用或服務都參與處理來自用戶端的請求。例如,在下圖所示拓撲結構中,應用 1 是一台 既可處理 HTTP 請求并将其重定向至應用 2 的 Web 伺服器。這兩個應用均在 NGINX Ingress Controller 所執行負載均衡的 Kubernetes 叢集中運作,并啟用了 OpenTracing。是以我們可在來自 Ingress Controller 的請求通過應用 1 并到達應用 2 時對其進行跟蹤。

采用 NGINX Ingress Controller 支援 OpenTracing?

有關系統元件執行的任何操作(例如服務)的資訊将會被 OpenTracing 所謂的 span 捕獲。将這些 ​​span​​ 連結在一起,我們即可在資訊穿過叢集微服務的整個過程中對其進行識别和跟蹤。

注:在撰寫本文時,OpenTracing 僅在 NGINX Ingress Controller 的 ​​edge​​ 版本中可用。

将 OpenTracing 建構到 NGINX Ingress Controller 鏡像中

搭配使用 OpenTracing 和我們的 Ingress Controller 需要将 OpenTracing 子產品結合到 NGINX 或 NGINX Plus Ingress Controller 的 Docker 鏡像中,并指定所用跟蹤器。

在 Ingress Controller 的 ​​GitHub 存儲庫​​中,我們為 NGINX 和 NGINX Plus 提供了單獨的 Dockerfile。雖然二者均将開源 OpenTracing 子產品整合到 Docker 鏡像中,但處理的方式不同:

  • 在 NGINX 系統中,​​DockerfileWithOpentracing​​ 從 GitHub 下載下傳 OpenTracing 子產品,并在 Docker 的第一階段建構中對其進行手動彙集。
  • 在 NGINX Plus 系統中,​​DockerfileWithOpentracingForPlus​​​ 使用軟體保管系統擷取 NGINX 使用開源和 OpenTracing 子產品所建構并維護的​​動态子產品​​。

執行以下步驟:

  1. (可選)指定一個 Jaeger 預設以外的​​跟蹤器​​​。插件也适用于 ​​Datadog、LightStep 和 Zipkin​​​。使用不同的跟蹤器需根據 ​​OpenTracing 啟用說明​​中前提條件部分修改 Dockerfile。
  2. 遵照 Ingress Controller 存儲庫中的​​說明​​​建構 Docker 鏡像。在第 3 步中,需指定相應的 Dockerfile。

    NGINX:

$ make clean
$ make DOCKERFILE=DockerfileWithOpentracing PREFIX=YOUR-PRIVATE-REGISTRY/nginx-ingress      

     NGINX Plus:

$ make clean
$ make DOCKERFILE=DockerfileWithOpentracingForPlus PREFIX=YOUR-PRIVATE-REGISTRY/nginx-plus-ingress      

3. 按照 Ingress Controller 存儲庫中的​​說明​​安裝鏡像。

在運作說明第 3 節中的 kubectlapply 指令前,切記更新 YAML 檔案,以指定已引入 OpenTracing 的建立鏡像:

containers: 
 - image: IMAGE_WITH_OPENTRACING      

部署 Jaeger 跟蹤器

本博文所使用的是 Jaeger 預設跟蹤器。為簡單起見,我們将其部署在叢集内部,但也您也可以将其部署在叢集外部。Ingress Controller Pod 和任何使用 OpenTracing 的 Pod 必須有通路跟蹤器的權限。

同樣為簡單起見,我們将使用 Jaeger 提供的​​一體化模版​​在叢集中設立非生産 Jaeger 執行個體。最終适合開發環境的部署将建立一個 Jaeger Pod 及通路該 Pod 所需的服務,并在預設命名空間中設立最新 Jaeger 版本,其具有記憶體存儲容量和有限功能。

$ kubectl create -f https://raw.githubusercontent.com/jaegertracing/jaeger-kubernetes/master/all-in-one/jaeger-all-in-one-template.yml      

在生産環境中,我們推薦使用 ​​Jaeger Operator ​​​進行安裝。擷取更多有關 Jaeger 的資訊,請通路 ​​Jaeger 網站​​。

啟用 OpenTracing

以下針對 NGINX Ingress Controller 的 ConfigMap (nginx-config.yaml) 全局啟用 OpenTracing,并在 data部分中添加了三個新的 ConfigMap 鍵名:

  1. opentracing 鍵為所有在叢集中建立的 Ingress 資源啟用 OpenTracing。
  2. opentracing-tracer 鍵指定前往跟蹤器庫路徑,并在您建構它時将跟蹤器庫下載下傳并複制到 Ingress 控制器鏡像中。
  3. opentracing-tracer-config 鍵嵌入了跟蹤器配置。service_name 字段定義與實際 span 相關的服務;reporter 字段指定跟蹤器位址和端口(在此示例中是上一部分 Jaeger 服務一體式模闆部署的的位址和端口)。sampler字段指定​​用戶端采樣​​配置;為簡單起見,我們将配置可供所有 trace 進行采樣的“常量”采樣器(常項)。
kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-config
  namespace: nginx-ingress
data:
  opentracing: "True"
  opentracing-tracer: "/usr/local/lib/libjaegertracing_plugin.so"
  opentracing-tracer-config: | 
   {
      "service_name": "nginx-ingress",
      "sampler": {
        "type": "const",
        "param": 1
      },
      "reporter": {
        "localAgentHostPort": "jaeger-agent.default.svc.cluster.local:6831"
      }
    }      

應用,隻需運作:

$kubectl apply –fnginx-config.yam      

部署示例應用

為簡單起見,我們将使用NGINX執行個體作為我們的後端應用,其中有兩個不同應用——應用 1 配置将所有 HTTP 流量重定向到應用 2。

以下為第一個應用的 YAML 清單(​​s 和資料卷​​配置在 Pod 内運作的 NGINX 執行個體。其中一個 ConfigMap 采用 NGINX 配置,另一個則用于為每個 NGINX 執行個體指定跟蹤器配置(我們在每個應用中采用該配置,因為如前所述,應用 Pod 發送有關請求的資訊需通路跟蹤器)。

部署應用 1

以下為第一個應用的YAML 清單 (app1.yaml):

apiVersion: v1
kind: ConfigMap
metadata:
  name: app1-config
data:
  nginx.conf: |-
    user nginx;
    worker_processes  1;
    load_module modules/ngx_http_opentracing_module.so;
    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;
    events {
        worker_connections  1024;
    }
    http {
        opentracing_load_tracer /usr/local/lib/libjaegertracing_plugin.so
                                /etc/jaeger-config.json;
        opentracing on;
        server {
            listen 80;
            server_name example.com;
            location / {
                opentracing_propagate_context;
                proxy_set_header Host $host;
                proxy_pass http://app2-svc:80;
            }
        }
    }
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: jaeger-config-app1
data:
  jaeger-config.json: |-
    {
      "service_name": "app1",
      "sampler": {
        "type": "const",
        "param": 1
      },
      "reporter": {
        "localAgentHostPort": "jaeger-agent.default.svc.cluster.local:6831"
      }
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app1
  template:
    metadata:
      labels:
        app: app1
    spec:
      containers:
      - name: app1
        image: opentracing/nginx-opentracing
        ports:
        - containerPort: 80
        volumeMounts:
          - name: config-app1
            mountPath: /etc/nginx/nginx.conf
            subPath: nginx.conf
            readOnly: true
          - name: config-jaeger
            mountPath: /etc/jaeger-config.json
            subPath: jaeger-config.json
            readOnly: true
      volumes:
      - name: config-app1
        configMap:
          name: app1-config
      - name: config-jaeger
        configMap:
          name: jaeger-config-app1
---
apiVersion: v1
kind: Service
metadata:
  name: app1-svc
spec:
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: app1      

運作以下指令部署第一個應用:

$kubectl apply –fapp1.yaml      

部署應用 2

以下為第二個應用的 YAML 清單 (app2.yaml):

apiVersion: v1
kind: ConfigMap
metadata:
  name: app2-config
data:
  nginx.conf: |-
    user nginx;
    worker_processes  1;
    load_module modules/ngx_http_opentracing_module.so;
    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;
    events {
        worker_connections  1024;
    }
    http {
        opentracing_load_tracer /usr/local/lib/libjaegertracing_plugin.so
                                /etc/jaeger-config.json;
        opentracing on;
        server {
            listen 80;
            server_name example.com;
            location / {
                opentracing_propagate_context;
                opentracing_tag app app2;
                return 200 "Success!\n";
            }
        }
    }
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: jaeger-config-app2
data:
  jaeger-config.json: |-
    {
      "service_name": "app2",
      "sampler": {
          "type": "const",
          "param": 1
      },
      "reporter": {
          "localAgentHostPort": "jaeger-agent.default.svc.cluster.local:6831"
      }
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app2
  template:
    metadata:
      labels:
        app: app2
    spec:
      containers:
      - name: app2
        image: opentracing/nginx-opentracing
        ports:
        - containerPort: 80
        volumeMounts:
          - name: config-app2
            mountPath: /etc/nginx/nginx.conf
            subPath: nginx.conf
            readOnly: true
          - name: config-jaeger
            mountPath: /etc/jaeger-config.json
            subPath: jaeger-config.json
            readOnly: true
      volumes:
      - name: config-app2
        configMap:
          name: app2-config
      - name: config-jaeger
        configMap:
          name: jaeger-config-app2
---
apiVersion: v1
kind: Service
metadata:
  name: app2-svc
spec:
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: app2      

運作以下指令部署第二個應用:

$kubectl apply -fapp2.yaml      

部署 Ingress 資源

為了支援叢集外部對應用 1 的通路,我們将建立以下 Ingress 資源 (opentracing-ingress.yaml):

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: opentracing-ingress
  annotations:
    nginx.org/location-snippets: |
      opentracing_propagate_context;
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: app1-svc
          servicePort: 80      

在這裡,我們在 Ingress Controller 使用了 nginx.org/location-snippets 注釋啟用​​跟蹤上下文傳播​​​。​​代碼段注釋​​是将自定義代碼添加到 Ingress Controller 中最終 NGINX 配置的一種有效方法。

最後,我們通過運作以下指令來應用 Ingress 資源:

$kubectl apply -fopentracing-ingress.yaml      

驗證應用 1 和應用 2 是否均正常運作:

$ kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
app1-68fd9db45c-szqpr     1/1     Running   0          53m
app2-67c7788789-lvbgw     1/1     Running   0          53m      

跟蹤請求

現在,我們隻需通過 Ingress Controller 向應用 1 送出請求,其中:

  1. IC_HTTP_PORT 是 Ingress 控制器 Pod 中的 HTTP 端口(預設為 80)
  2. IC_IP_ADDRESS是 Ingress 控制器 Pod 的 IP 位址。如果使用​​minikube​​,則采用 minikube IP 位址。
$curl --resolveexample.com:IC_HTTP_PORT:IC_IP_ADDRESShttp://example.com:IC_HTTP_PORT/--insecure
Success!      

檢視trace

我們運作以下指令來通路 Jaeger 使用者界面,其中 JAEGER_POD 是我們通過​​部署 Jaeger 跟蹤器​​​一體式模闆所建立的Pod中的“​​類型/名稱​​”值:

$kubectl port-forwardJAEGER_POD 16686:16686      

每個請求都會建立一個新的 trace。您可在浏覽器中在 ​​http://localhost:16686​​ 打開 Jaeger 使用者界面去檢視剛剛送出請求的 trace,在左欄 Service 字段中鍵入 nginx-egress,然後點選欄底部的 FindTraces 按鈕。

采用 NGINX Ingress Controller 支援 OpenTracing?

點選搜尋視窗右欄中的 nginx-ingress,選擇 trace。在打開的視窗(下圖)中,我們看到我們請求的三種 span:棕色代表 Ingress Controller,藍色代表應用 1,黃色代表應用 2。

采用 NGINX Ingress Controller 支援 OpenTracing?

擷取更多相關各個 span 的詳細資訊,包括 HTTP 狀态代碼、主機名、IP 位址和 Jaeger 版本,請點選其 span 的按鈕。

采用 NGINX Ingress Controller 支援 OpenTracing?

結語

在 Kubernetes 中為您的服務啟用 OpenTracing 可支援您和您的團隊及時了解應用運作的情況并快速排除故障。

更多資源

  • 官網:​​nginx.org.cn​​
  • 微信公衆号:​​https://mp.weixin.qq.com/s/XVE5yvDbmJtpV2alsIFwJg​​
  • 微信群:​​https://www.nginx.org.cn/static/pc/images/homePage/QR-code.png?v=1621313354​​
  • B 站:​​https://space.bilibili.com/628384319​​

繼續閱讀