亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Kubernetes上如何使用Jaeger分布式追蹤

發布時間:2023-03-07 17:30:22 來源:億速云 閱讀:124 作者:iii 欄目:開發技術

今天小編給大家分享一下Kubernetes上如何使用Jaeger分布式追蹤的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

    正文

    作為分布式系統(或任何系統)的一個組成部分,監測基礎設施的重要性怎么強調都不過分。監控不僅要跟蹤二進制的 "上升 "和 "下降 "模式,還要參與到復雜的系統行為中。監測基礎設施的設置可以讓人們深入了解性能、系統健康和長期的行為模式。

    微服務架構中的可觀察性

    Kubernetes已經成為微服務基礎設施和部署的事實上的協調器。這個生態系統非常豐富,是開源社區中發展最快的系統之一。帶有Prometheus、ElasticSearch、Grafana、Envoy/Consul、Jaeger/Zipkin的監控基礎設施構成了一個堅實的基礎,以實現整個堆棧的指標、日志、儀表盤、服務發現和分布式跟蹤。

    分布式追蹤

    分布式跟蹤能夠捕獲請求,并建立一個從用戶請求到數百個服務之間互動的整個調用鏈的視圖。它還能對應用程序的延遲(每個請求花了多長時間)進行檢測,跟蹤網絡調用的生命周期(HTTP、RPC等),并通過獲得瓶頸的可見性來確定性能問題。

    下面的章節將介紹在Kubernetes設置中使用Jaeger對gRPC服務進行分布式跟蹤。Jaeger Github Org有專門的Repo,用于Kubernetes中Jaeger的各種部署配置。這些都是很好的例子,我將嘗試分解每個Jaeger組件和它的Kubernetes部署。

    Jaeger組件

    Jaeger是一個開源的分布式跟蹤系統,實現了OpenTracing規范。Jaeger包括存儲、可視化和過濾跟蹤的組件。

    架構圖

    Kubernetes上如何使用Jaeger分布式追蹤

    Jaeger客戶端

    應用程序跟蹤儀表從Jaeger客戶端開始。下面的例子使用Jaeger Go庫從環境變量初始化追 蹤 器配置,并啟用客戶端指標。

    package tracer
    import (
        "io"
        "github.com/uber/jaeger-client-go/config"
        jprom "github.com/uber/jaeger-lib/metrics/prometheus"
    )
    func NewTracer() (opentracing.Tracer, io.Closer, error) {
        // load config from environment variables
        cfg, _ := jaegercfg.FromEnv()
    	// 博客原來:janrs.com
        // create tracer from config
        return cfg.NewTracer(
            config.Metrics(jprom.New()),
        )
    }

    Go客戶端使通過環境變量初始化Jaeger配置變得簡單。一些需要設置的重要環境變量包括JAEGER_SERVICE_NAME、JAEGER_AGENT_HOST和JAEGER_AGENT_PORT。Jaeger Go客戶端支持的環境變量的完整列表列在這里。

    為了給你的gRPC微服務添加追蹤功能,我們將使用gRPC中間件來啟用gRPC服務器和客戶端的追蹤功能。 grpc-ecosystem/go-grpc-middleware有一個很棒的攔截器集合,包括支持OpenTracing提供者的服務器端和客戶端的攔截器。

    grpc_opentracing包暴露了opentracing攔截器,可以用任何opentracing.Tracer實現來初始化。在這里,我們用連鎖的單項和流攔截器初始化了一個gRPC服務器。啟用它將創建一個根serverSpan,對于每個服務器端的gRPC請求,追 蹤 器將為服務中定義的每個RPC調用附加一個Span。

    package grpc_server
    import (
    	"github.com/opentracing/opentracing-go"
    	"github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
    	"github.com/grpc-ecosystem/go-grpc-middleware"
    	"google.golang.org/grpc"
      	"github.com/masroorhasan/myapp/tracer"		
    )
    func NewServer() (*grpc.Server, error) {
     	// initialize tracer
    	tracer, closer, err := tracer.NewTracer()
    	defer closer.Close()
    	if err != nil {
    		return &grpc.Server{}, err
    	}
    	opentracing.SetGlobalTracer(tracer)
    	// initialize grpc server with chained interceptors # janrs.com
    	s := grpc.NewServer(
    		grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
    			// add opentracing stream interceptor to chain
    			grpc_opentracing.StreamServerInterceptor(grpc_opentracing.WithTracer(tracer)),
      		)),
    	  	grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
    			// add opentracing unary interceptor to chain
    			grpc_opentracing.UnaryServerInterceptor(grpc_opentracing.WithTracer(tracer)),
    		)),
    	)
    	return s, nil
    }

    為了實現對gRPC服務的上游和下游請求的追蹤,gRPC客戶端也必須用客戶端開放追蹤攔截器進行初始化,如下例所示。

    package grpc_client
    import (
        "github.com/opentracing/opentracing-go"
        "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
        "github.com/grpc-ecosystem/go-grpc-middleware"
        "google.golang.org/grpc"
        "github.com/masroorhasan/myapp/tracer"
    )
    func NewClientConn(address string) (*grpc.ClientConn, error) {
        // initialize tracer #博文來源:janrs.com
        tracer, closer, err := tracer.NewTracer()
        defer closer.Close()
        if err != nil {
            return &grpc.ClientConn{}, err
        }
        // initialize client with tracing interceptor [#博文來源:janrs.com#] using grpc client side chaining
        return grpc.Dial(
            address,
            grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
                grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(tracer)),
            )),
            grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
                grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(tracer)),
            )),
         )
    }

    由gRPC中間件創建的父跨度被注入到go上下文中,從而實現強大的跟蹤支持。opentracing go客戶端可以用來將子跨度附加到父跨度上,以實現更精細的追蹤,以及控制每個跨度的壽命,為追蹤添加自定義標簽等。

    Jaeger代理

    Jaeger代理是一個守護進程,它通過UDP接收來自Jaeger客戶端的跨度,并將它們分批轉發給收集器。該代理作為一個緩沖器,從客戶那里抽象出批處理和路由。

    盡管代理是作為一個守護程序建立的,但在Kubernetes設置中,代理可以被配置為在應用Pod中作為一個sidecar容器運行,或作為一個獨立的DaemonSet。

    下文討論了每種部署策略的優點和缺點。

    Jaeger SideCar 代理

    Jaeger Sidecar 代理是一個容器,與你的應用容器放在同一個艙中。表示為Jaeger服務的應用程序myapp將通過localhost向代理發送Jaeger跨度到6381端口。[#博文來源:janrs.com#]如前所述,這些配置是通過客戶端的環境變量JAEGER_SERVICE_NAME、JAEGER_AGENT_HOST和JAEGER_AGENT_PORT設置的。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp-deployment
      namespace: default
      labels:
        app: myapp
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: myapp
      template:
        metadata:
          labels:
            app: myapp
        spec:
          containers:
          - name: myapp
            image: masroorhasan/myapp
            ports:
            - containerPort: 80
            env:
            - name: JAEGER_SERVICE_NAME
              value: myapp
            - name: JAEGER_AGENT_HOST
              value: localhost  # default
            - name: JAEGER_AGENT_PORT
              value: "6831"
            resources:
              limits:
                memory: 500M
                cpu: 250m
              requests:
                memory: 500M
                cpu: 250m
          # sidecar agent
          - name: jaeger-agent
            image: jaegertracing/jaeger-agent:1.6.0
            ports:
            - containerPort: 5775
              protocol: UDP
            - containerPort: 5778
              protocol: TCP
            - containerPort: 6831
              protocol: UDP
            - containerPort: 6832
              protocol: UDP
            command:
              - "/go/bin/agent-linux"
              - "--collector.host-port=jaeger-collector.monitoring:14267"
            resources:
              limits:
                memory: 50M
                cpu: 100m
              requests:
                memory: 50M
                cpu: 100m

    通過這種方法,每個代理(也就是每個應用)都可以被配置為向不同的收集器(也就是不同的后端存儲)發送痕跡。

    然而,這種方法最大的缺點之一是將代理的生命周期和應用程序緊密結合在一起。追蹤的目的是在應用程序的生命周期內提供對其的洞察力。更有可能的是,代理側車容器在主應用容器之前被殺死,在應用服務關閉期間,任何/所有重要的追蹤都會丟失。這些痕跡的丟失對于理解復雜服務交互的應用生命周期行為可能是非常重要的。這個GitHub問題驗證了在關機期間正確處理SIGTERM的必要性。

    Jaeger Daemonset 代理

    另一種方法是通過Kubernetes中的DaemonSet工作負載,將代理作為集群中每個節點的守護程序運行。DaemonSet工作負載可以確保當節點被擴展時,DaemonSet Pod的副本也隨之擴展。

    在這種情況下,每個代理守護程序負責從其節點中安排的所有運行中的應用程序(配置了Jaeger客戶端)中獲取追蹤信息。這是通過在客戶端設置JAEGER_AGENT_HOST指向節點中代理的IP來配置的。代理DaemonSet被配置為hostNetwork: true和適當的DNS策略,以便Pod使用與主機相同的IP。由于代理的6831端口是通過UDP接受jaeger.thrift消息的,所以守護的Pod配置端口也與hostPort: 6831綁定。

    # Auth : janrs.com
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp-deployment
      namespace: default
      labels:
        app: myapp
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: myapp
      template:
        metadata:
          labels:
            app: myapp
        spec:
          containers:
          - name: myapp
            image: masroorhasan/myapp
            ports:
            - containerPort: 80
            env:
            - name: JAEGER_SERVICE_NAME
              value: myapp
            - name: JAEGER_AGENT_HOST   # NOTE: Point to the Agent daemon on the Node
              valueFrom:
                fieldRef:
                  fieldPath: status.hostIP
            - name: JAEGER_AGENT_PORT
              value: "6831"
            resources:
              limits:
                memory: 500M
                cpu: 250m
              requests:
                memory: 500M
                cpu: 250m
    ---
    apiVersion: extensions/v1beta1
    kind: DaemonSet
    metadata:
      name: jaeger-agent
      namespace: monitoring
      labels:
        app: jaeger
        jaeger-infra: agent-daemonset
    spec:
      template:
        metadata:
          labels:
            app: jaeger
            jaeger-infra: agent-instance
        spec:
          hostNetwork: true     # NOTE: Agent is configured to have same IP as the host/node
          dnsPolicy: ClusterFirstWithHostNet
          containers:
          - name: agent-instance
            image: jaegertracing/jaeger-agent:1.6.0
            command:
              - "/go/bin/agent-linux"
              - "--collector.host-port=jaeger-collector.monitoring:14267"
              - "--processor.jaeger-binary.server-queue-size=2000"
              - "--discovery.conn-check-timeout=500ms"
            ports:
            - containerPort: 5775
              protocol: UDP
            - containerPort: 6831
              protocol: UDP
              hostPort: 6831
            - containerPort: 6832
              protocol: UDP
            - containerPort: 5778
              protocol: TCP
            resources:
              requests:
                memory: 200M
                cpu: 200m
              limits:
                memory: 200M
                cpu: 200m

    人們可能會被誘 惑(就像我一樣),用Kubernetes服務來引導DaemonSet。這背后的想法是,不要把應用程序的痕跡綁定到當前節點的單一代理上。使用服務可以將工作負載(跨度)分散到集群中的所有代理。這在理論上減少了在受影響節點的單個代理莢發生故障的情況下,應用實例丟失跨度的機會。

    然而,當你的應用程序擴展時,這將不起作用,高負載會在需要處理的痕跡數量上產生巨大的峰值。使用Kubernetes服務意味著通過網絡從客戶端向代理發送追蹤信息。很快,我就開始注意到大量的掉線現象。客戶端通過UDP thrift協議向代理發送跨度,大量的峰值導致超過UDP最大數據包大小,從而導致丟包。

    解決辦法是適當地分配資源,使Kubernetes在整個集群中更均勻地調度pod。[#博文來源:janrs.com#]我們可以增加客戶端的隊列大小(設置JAEGER_REPORTER_MAX_QUEUE_SIZE環境變量),以便在代理失效時有足夠的緩沖空間。增加代理的內部隊列大小也是有益的(設置處理器.jaeger-binary.server-queue-size值),這樣他們就不太可能開始丟棄跨度。

    Jaeger Collector 服務

    Jaeger收集器負責從Jaeger代理那里接收成批的跨度,通過處理管道運行它們,并將它們存儲在指定的存儲后端。跨度以jaeger.thrift格式從Jaeger代理處通過TChannel(TCP)協議發送,端口為14267。

    Jaeger收集器是無狀態的,可以根據需要擴展到任何數量的實例。因此,收集器可以由Kubernetes內部服務(ClusterIP)前置,可以從代理到不同收集器實例的內部流量進行負載平衡。

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: jaeger-collector
      namespace: monitoring
      labels:
        app: jaeger
        jaeger-infra: collector-deployment
    spec:
      replicas: 1
      strategy:
        type: Recreate
      template:
        metadata:
          labels:
            app: jaeger
            jaeger-infra: collector-pod
        spec:
          containers:
          - image: jaegertracing/jaeger-collector:1.6.0
            name: jaeger-collector
            args: ["--config-file=/conf/collector.yaml"]
            ports:
            - containerPort: 14267
              protocol: TCP
            - containerPort: 14268
              protocol: TCP
            - containerPort: 9411
              protocol: TCP
            readinessProbe:
              httpGet:
                path: "/"
                port: 14269
            volumeMounts:
            - name: jaeger-configuration-volume
              mountPath: /conf
            env:
            - name: SPAN_STORAGE_TYPE
              valueFrom:
                configMapKeyRef:
                  name: jaeger-configuration
                  key: span-storage-type
          volumes:
            - configMap:
                name: jaeger-configuration
                items:
                  - key: collector
                    path: collector.yaml
              name: jaeger-configuration-volume
          resources:
            requests:
              memory: 300M
              cpu: 250m
            limits:
              memory: 300M
              cpu: 250m
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: jaeger-collector
      namespace: monitoring
      labels:
        app: jaeger
        jaeger-infra: collector-service
    spec:
      ports:
      - name: jaeger-collector-tchannel
        port: 14267
        protocol: TCP
        targetPort: 14267
      selector:
        jaeger-infra: collector-pod
      type: ClusterIP
    view raw

    Jaeger Query 查詢服務

    查詢服務是支持用戶界面的Jaeger服務器。它負責從存儲器中檢索痕跡,并將其格式化以顯示在用戶界面上。根據查詢服務的使用情況,它的資源占用率非常小。

    設置一個內部Jaeger用戶界面的入口,指向后端查詢服務。

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: jaeger-query
      namespace: monitoring
      labels:
        app: jaeger
        jaeger-infra: query-deployment
    spec:
      replicas: 1
      strategy:
        type: Recreate
      template:
        metadata:
          labels:
            app: jaeger
            jaeger-infra: query-pod
        spec:
          containers:
          - image: jaegertracing/jaeger-query:1.6.0
            name: jaeger-query
            args: ["--config-file=/conf/query.yaml"]
            ports:
            - containerPort: 16686
              protocol: TCP
            readinessProbe:
              httpGet:
                path: "/"
                port: 16687
            volumeMounts:
            - name: jaeger-configuration-volume
              mountPath: /conf
            env:
            - name: SPAN_STORAGE_TYPE
              valueFrom:
                configMapKeyRef:
                  name: jaeger-configuration
                  key: span-storage-type
            resources:
              requests:
                memory: 100M
                cpu: 100m
              limits:
                memory: 100M
                cpu: 100m
          volumes:
            - configMap:
                name: jaeger-configuration
                items:
                  - key: query
                    path: query.yaml
              name: jaeger-configuration-volume
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: jaeger-query
      namespace: monitoring
      labels:
        app: jaeger
        jaeger-infra: query-service
    spec:
      ports:
      - name: jaeger-query
        port: 16686
        targetPort: 16686
      selector:
        jaeger-infra: query-pod
      type: ClusterIP
    ---
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
     name: jaeger-ui
     namespace: monitoring
     annotations:
       kubernetes.io/ingress.class: traefik # or nginx or whatever ingress controller
    spec:
     rules:
     - host: jaeger.internal-host # your jaeger internal endpoint
       http:
         paths:
         - backend:
             serviceName: jaeger-query
             servicePort: 16686

    Storage Configuration 存儲配置

    Jaeger同時支持ElasticSearch和Cassandra作為存儲后端。使用ElasticSearch作為存儲,可以擁有一個強大的監控基礎設施,將跟蹤和日志記錄聯系在一起。采集器處理管道的一部分是為其存儲后端索引跟蹤--這將使跟蹤顯示在你的日志UI(例如Kibana)中,也將跟蹤ID與你的結構化日志標簽綁定。你可以通過SPAN_STORAGE_TYPE的環境變量將存儲類型設置為ElasticSearch,并通過配置配置存儲端點。

    Kubernetes ConfigMap用于設置一些Jaeger組件的存儲配置。例如,Jaeger收集器和查詢服務的存儲后端類型和端點。

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: jaeger-configuration
      namespace: monitoring
      labels:
        app: jaeger
        jaeger-infra: configuration
    data:
      span-storage-type: elasticsearch
      collector: |
        es:
          server-urls: http://elasticsearch:9200
        collector:
          zipkin:
            http-port: 9411
      query: |
        es:
          server-urls: http://elasticsearch:9200

    監控

    如前所述,追蹤是監控基礎設施的一個重要組成部分。這意味著,甚至你的追蹤基礎設施的組件也需要被監控。

    Jaeger在每個組件的特定端口上以Prometheus格式暴露指標。如果有正在運行的Prometheus節點導出器(它絕對應該是)在特定的端口上刮取指標 - 然后將你的Jaeger組件的指標端口映射到節點導出器正在刮取指標的端口。

    這可以通過更新Jaeger服務(代理、收集器、查詢)來完成,將它們的指標端口(5778、14628或16686)映射到節點出口商期望搜刮指標的端口(例如8888/8080)。

    一些需要跟蹤的重要指標。

    Health of each component — memory usage: sum(rate(container_memory_usage_bytes{container_name=~”^jaeger-.+”}[1m])) by (pod_name)

    Health of each component — CPU usage: sum(rate(container_cpu_usage_seconds_total{container_name=~"^jaeger-.+"}[1m])) by (pod_name)

    Batch failures by Jaeger Agent: sum(rate(jaeger_agent_tc_reporter_jaeger_batches_failures[1m])) by (pod)

    Spans dropped by Collector: sum(rate(jaeger_collector_spans_dropped[1m])) by (pod)

    Queue latency (p95) of Collector: histogram_quantile(0.95, sum(rate(jaeger_collector_in_queue_latency_bucket[1m])) by (le, pod))

    這些指標為了解每個組件的性能提供了重要的見解,歷史數據應被用來進行最佳設置。

    以上就是“Kubernetes上如何使用Jaeger分布式追蹤”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    黄骅市| 句容市| 黔西县| 介休市| 北辰区| 南郑县| 寿宁县| 铜山县| 图木舒克市| 庆城县| 肥乡县| 衡阳县| 武定县| 永济市| 乾安县| 阳江市| 泽普县| 棋牌| 娱乐| 巍山| 望都县| 清徐县| 海安县| 弥渡县| 射洪县| 霍山县| 饶阳县| 武鸣县| 雷波县| 遂平县| 阿拉善右旗| 奉贤区| 腾冲县| 嵊泗县| 和静县| 株洲市| 宝坻区| 永春县| 敦煌市| 牡丹江市| 汕头市|