基於 EKS Fargate 搭建微服務效能分析系統

亞馬遜雲開發者發表於2023-05-11

背景

近期 Amazon Fargate 在中國區正式落地,因 Fargate 使用 Serverless 架構,更加適合對效能要求不敏感的服務使用,Pyroscope 是一款基於 Golang 開發的應用程式效能分析工具,Pyroscope 的服務端為無狀態服務且效能要求不敏感,使用 EKS Fargate 搭建 Pyroscope,Pyroscope 的客戶端使用 DNS 地址連線到服務端。將為單次效能測試和持續效能最佳化提供保障,並且每當應用服務上線或更新後,流量增加或者功能故障都會造成終端使用者的體驗變差,如何定位效能瓶頸便成為了重點,在 EKS Fargate上 搭建 Pyroscope 既能減少開發者的維護成本又能給開發者開箱即用的效能瓶頸快速定位到程式碼的平臺,而且 Pyroscope 支援 Python,Rust,NodeJS,Rube,Java,DotNet,Golang 等多語言環境

亞馬遜雲科技開發者社群為開發者們提供全球的開發技術資源。這裡有技術文件、開發案例、技術專欄、培訓影片、活動與競賽等。幫助中國開發者對接世界最前沿技術,觀點,和專案,並將中國優秀開發者或技術推薦給全球雲社群。如果你還沒有關注/收藏,看到這裡請一定不要匆匆劃過,點這裡讓它成為你的技術寶庫!

使用場景

  • 快速發現原始碼中的存在的效能問題
  • 根據指標監控發現高 CPU 利用率的問題
  • 快速定位記憶體洩漏和修復輔助提供有效支撐
  • 深入理解應用程式的呼叫耗時和依賴樹
  • 跟蹤指標和時間軸以便於定位效能異常點
  • 整合到 CI 定位每次變更的效能情況

介紹下 Pyroscope

這是一款開源的實時效能監控平臺,使用 Agent/SDK – Server 架構,讓開發者可以輕鬆監控服務效能,因 Pyroscope 監控的級別足夠深入。不管是最近5秒的資料還是長期儲存的效能資料,都可以快速透過 Grafana Plugin 或者 Pyroscope UI 進行定位。且因為使用分塊取樣的能力。使得使用 Pyrosocpe 的 Agent 對應用程式的 CPU 佔用較低。

Pyroscope Server 採用 BadgerDB 作為 Key-value 資料儲存(未來將會支援 S3 相容儲存),具有高壓縮比,低磁碟空間佔用和低成本。支援多種語言和 Docker,k8s,EC2 等多種平臺注入,Python,Rube,Java,DotNet 都是透過 pyrosocope 的命令啟動相關 Agent 來執行監控,針對 metric-export 和 eBPF 有也有相關支援

Pyrosocpe UI 使用的方式和 Grafana 相似,可以使用 Grafana Plugin 也可以使用 Pyroscope UI 使用,名詞使用:inuse_object,alloc_objects,inuse_space,alloc_space, 分別對應已分配或者尚未分配的物件在記憶體中的佔用

Pyroscope UI

Pyroscope + Grafana Logs: 根據當前 Logs volume 找到存在效能問題的程式碼行,快速定位問題

Pyroscope + Tracing(Jaeger) : 根據 Pyroscope_id 在 jaeger 中找到對應的請求用於故障排除

效能告警

Pyrosocpe 支援將應用服務效能指標匯出到 Prometheus,聯動 Prometheus 全家桶進行服務耗時跟蹤和效能的異常告警,只需要將 Pyroscope 配置到Prometheus配置檔案中。使得 Prometheus 可以使用 Kubernetes_sd 主動發現資料並採集上報

部署指南

  • 將樣例程式碼的遠端倉庫克隆到本地
git clone [github.com/Hoverhuang-er/eks-fargate-ppf](http://github.com/Hoverhuang-er/eks-fargate-ppf) && mv eks-fargate-ppf ppf
  • 使用 Terraform 建立 AWS EKS Cluster 和 Fargate profile
cd ppf/eks && terraform init && terraform apply -auto-approve
  • 使用 kubectl 部署 Pyroscope
---
apiVersion: v1
kind: Namespace
metadata:
  name: fg1
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  namespace: fg1
  name: pyroscope-server
spec:
  volumeClaimTemplates:
    - metadata:
        name: pyroscope-server-storage
      spec:
        accessModes: [ "ReadWriteOnce" ]
        storageClassName: "gp2"
        resources:
          requests:
            storage: 8Gi
  minReadySeconds: 10
  selector:
    matchLabels:
      app.kubernetes.io/name: pyroscope-server
  replicas: 1
  template:
    metadata:
      labels:
        app.kubernetes.io/name: pyroscope-server
    spec:
      containers:
      - image: dockerhub.io/pyroscope/pyroscope:latest
        imagePullPolicy: Always
        name: pyroscope-server
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  namespace: fg1
  name: pyroscope-server-services
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: NodePort
  selector:
    app.kubernetes.io/name: pyroscope-server
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  namespace: fg1
  name: pyroscope-server-ingress
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  ingressClassName: alb
  rules:
    - http:
        paths:
        - path: /*
          pathType: Prefix
          backend:
            service:
              name: pyroscope-server
              port:
                number: 80

使用 Skooner 或者 Potainer.io 對EKS 叢集進行簡單管理
kubectl apply -f ppf/dashboard.yaml

如何使用 Pyroscope 進行效能最佳化

Pyroscope 具有程式碼侵入性,如需進一步使用,請謹慎考慮

樣例程式碼:Ruby

require "pyroscope"

Pyroscope.configure do |config|
  config.app_name = "test.ruby.app"
  config.server_address = ENV["PYROSCOPE_SERVER_ADDRESS"]
  config.tags = {
    :region => "ap-southeast-1",
    :hostname => ENV["HOSTNAME"]
  }
end

def work(n)
  i = 0
  while i < n
    i += 1
  end
end

def fast_function
  Pyroscope.tag_wrapper({ "function" => "fast" }) do
    work(20000)
  end
end

def slow_function
  Pyroscope.tag({ "function" => "slow" })
    work(80000)
  Pyroscope.remove_tags("function")
end

while true
  fast_function
  slow_function
end

用於部署的 Dockerfile:

FROM ruby:3.0.1

WORKDIR /usr/src/app

RUN adduser --disabled-password --gecos --quiet pyroscope
USER pyroscope

COPY --from=pyroscope/pyroscope:latest /usr/bin/pyroscope /usr/bin/pyroscope
COPY main.rb ./main.rb
COPY Gemfile ./Gemfile
COPY Gemfile.lock ./Gemfile.lock

ENV PYROSCOPE_APPLICATION_NAME=simple.ruby.app
ENV PYROSCOPE_SERVER_ADDRESS=http://172.31.0.233:4040/
ENV PYROSCOPE_LOG_LEVEL=debug

RUN bundle install

CMD ["ruby", "main.rb"]

執行 App 即可發現效能問題

根據下圖中的耗時高的問題進行分析是否可以最佳化

綜述

使用 Pyroscope 有助於開發人員持續提高應用程式的效能。減少耗時爆點的存在和影響,並可以將資料輸出到 Grafana,協助開發人員持續最佳化服務並有效降低成本,使用 Amazon EKS Fargate 搭建 Pyroscope 在幫助開發人員和維護人員進行系統服務效能架構最佳化的同時,基於 Serveless contaienr 減少維護成本。

本篇作者

黃書昊
Amazon ProServe DevOps 顧問,致力於解決企業客戶 DevOps 諮詢和實施,在雲原生 /DevOps/ 微服務框架/效能最佳化和加速研發效能領域有深入研究的熱情

王帥
Amazon 專業服務團隊 Devops 顧問。提倡融合文化,實踐和工具的Devops 理念,致力於幫助客戶使組織能夠以更高的速度和可靠性交付產品並獲得業務價值。擅長平臺規劃,遷移和工具鏈設計。對新鮮事物充滿熱情

文章來源:https://dev.amazoncloud.cn/column/article/6309aed2e0f88a79bcf...

相關文章