برنامه نویسی

ساخت پسوند AWS Lambda Telemetry API برای ورود مستقیم به Grafana Loki

در معماری های ترکیبی، توابع بدون سرور با راه حل های کانتینری کار می کنند. وقتی گزارش‌های CloudWatch را انتخاب نمی‌کنید، لاگ‌های Lambda باید ترجمه شوند. روش قدیمی انجام این کار از طریق فیلترهای اشتراک با استفاده از توابع اضافی Lambda برای تبدیل گزارش است. با Lambda Telemetry API روشی زیباتر، کارآمدتر و مقرون به صرفه تر وجود دارد. من از Grafana Loki به عنوان یک نمونه کار استفاده می کنم و به شما نشان می دهم که چگونه یک پسوند Lambda-Loki Telemetry APi فعال بسازید.

استفاده از راه حل متمرکز Logging در محیط های هیبریدی

به عنوان مثال از Grafana Loki به عنوان راه حل متمرکز ورود به سیستم خود استفاده کنید، جایی که ظرف و توابع لامبدا باید سیاهههای مربوط به آنجا ارسال شود بسیار رایج است.

اشتراک، ابونمان

همانطور که در مستندات Lambda-Promtail توضیح داده شده است، برای خواندن گزارش های Lamba باید از فیلتر اشتراک Logs CloudWatch استفاده کنید. همانطور که قهرمان بدون سرور Yan Cui در این مقاله بیان کرد، Transform Lambda همزمانی Lambda شما را می خورد و هزینه های اضافی اضافه می کند. می‌توانید با استفاده از جریان‌های Kinesis اضافی از آن استفاده کنید یا از آن استفاده کنید Lambda Telemetry API به عنوان یک پسوند لامبدا.

که این معماری سبک تر را ممکن می کند:

چراغ اشتراک

معرفی Lambda Telemetry API

با Lambda Telemetry API، برنامه های افزودنی Lambda می توانند مستقیماً داده های تله متری را از Lambda دریافت کنند.

برنامه های افزودنی لامبدا

با Lambda Extension API می توانید از لایه Lambda استفاده کنید که به عنوان یک فرآیند مستقل در محیط اجرا نامیده می شود و می تواند ادامه دهد پس از پردازش کامل فراخوانی تابع اجرا شود.

افزونه

Lambda Telemetry API

Telemetry API رویدادها را از این جریان‌های تله‌متری دریافت می‌کند:

  • سکو تله متری – گزارش ها، متریک ها و ردیابی ها که رویدادها و خطاهای مربوط به چرخه عمر زمان اجرا محیط اجرا، چرخه عمر برنامه افزودنی و فراخوانی عملکرد را توصیف می کنند.

  • تابع گزارش‌ها – گزارش‌های سفارشی که کد تابع Lambda ایجاد می‌کند.

  • افزونه گزارش‌ها – گزارش‌های سفارشی که کد برنامه افزودنی Lambda ایجاد می‌کند.

یک برنامه افزودنی می‌تواند با عضویت در آن، تمام خروجی‌های گزارش را از یک تابع Lambda دریافت کند Function مناسبت ها. انواع رویداد در راهنمای توسعه دهنده تعریف شده است.

توسط نه با عضویت در رویدادهای پلتفرم، رویدادهایی مانند آن را دریافت نخواهید کرد platform.start رویداد، که ایجاد می کند START ورودی های گزارش شما فقط خروجی را از خود تابع Lambda دریافت خواهید کرد. به این ترتیب لاگ ها بهتر قابل تجزیه خواهند بود.

گرافانا لبز لوکی

ابزار Grafana اغلب در محیط کانتینری استفاده می شود. بنابراین من پسوند را برای Grafana Loki، که راه حل ورود به سیستم است، خواهم ساخت.

واقعیت جالب: اولین رویکرد من استفاده از قابل تجزیه بود. اما مشخص شد که تجزیه پذیر در حال حاضر قادر به کار با نقش های IAM نیست.

از رویداد Lambda Telemetry API تا promtail

می‌توانید رویدادها را با api promtail یا api جدیدتر Loki وارد Loki کنید. api در مستندات توضیح داده شده است. من استفاده خواهم کرد /api/prom/push زنگ زدن.

کد پسوند

همانطور که AWS در ایجاد برنامه های افزودنی با استفاده از Telemetry API بیان می کند
که توصیه می شود از یک زبان کامپایل شده مانند Golang یا Rust استفاده کنید. بنابراین، البته، من از GO استفاده می کنم.

چند نمونه برنامه افزودنی github وجود دارد. من با استفاده از go-example-telemetry-api-extension به عنوان نقطه شروع می توانید کد را در مخزن Lambda-Telemetry-API-Loki من مشاهده کنید.

کی به کی زنگ میزنه

برنامه افزودنی در این مراحل اصلی کار می کند:

1) پسوند را با Extensions API ثبت کنید
2) برای دریافت رویدادها یک شنونده HTTP راه اندازی کنید
3) در هر یک از انواع پلتفرم، عملکرد، برنامه افزودنی مشترک شوید
4) رویدادها را دریافت کنید و آنها را به هدف، در اینجا Loki ارسال کنید

1) ثبت نام کنید

این کار از طریق ثبت نام فراخوانی برنامه افزودنی api.

دیدن extensionApi/client.go:

`

baseUrl := fmt.Sprintf("http://%s/2020-01-01/extension", os.Getenv("AWS_LAMBDA_RUNTIME_API"))
//...
const action = "/register"
url := e.baseUrl + action
///
httpRes, err := e.httpClient.Do(httpReq)
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

2) شنونده

ساختار از یک سرور HTTP و یک صف تشکیل شده است. به دلایل عملکرد، رویدادها مستقیماً به لوکی منتقل نمی شوند، بلکه در صف قرار می گیرند DISPATCH_MIN_BATCH_SIZE متغیر محیطی.

پسوند Lambda محیط خود را از تابع Lambda دریافت می کند، بنابراین شما مقادیر را در Lambda Function API تنظیم می کنید.

type TelemetryApiListener struct {
    httpServer *http.Server
    // LogEventsQueue is a synchronous queue and is used to put the received log events to be dispatched later
    LogEventsQueue *queue.Queue
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

3) مشترک شوید

که در telemetryApi/client.go کارکرد Subscribe تماس می گیرد baseUrl از تله متری افزونه:

baseUrl := fmt.Sprintf("http://%s/2022-07-01/telemetry", os.Getenv("AWS_LAMBDA_RUNTIME_API"))
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

پارامترهای ممکن در مرجع Lambda Telemetry API توضیح داده شده است.
برای مثال، اگر انتظار داده‌ای با حجم بالا دارید، باید اندازه دسته و پارامتر بافر تماس مشترک را تنظیم کنید.

اکنون که یک افزونه داریم، باید آن را بسازیم و در توابع Lambda نصب کنیم.

ساخت و نصب لایه تله متری

در مخزن با کمک فایل وظیفه بزرگ لایه های باینری را می سازم:

cd loki_extension
task build
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

که صدا می زند:

GOOS=linux GOARCH=amd64 go build -o dist/extensions/grafana-loki-extension main.go
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

که یک باینری اجرایی برای معماری amd64 ایجاد می کند. اگر از معماری بازو استفاده می کنید، باید متغیر GOARCH را تغییر دهید. باینری ایجاد شده فشرده شده و به صورت لایه Lambda منتشر می شود.
برای تنظیم لایه ARN در تابع لامبدا، ARN را ذخیره می کنم.
با افزونه، زمان اجراهای سازگار را تعریف می کنید --compatible-runtimes برای لایه لامبدا

کل تماس:

ARN=`aws lambda publish-layer-version --layer-name "grafana-loki-extension" --region eu-central-1 --compatible-runtimes nodejs16.x go1.x python3.9 --zip-file  "fileb://extension.zip" --query "LayerVersionArn" --output text` && echo $ARN
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

خروجی:

arn:aws:lambda:eu-central-1:012345679812:layer:grafana-loki-extension:1
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون لایه در حساب فعلی AWS نصب شده است. می‌توانیم بدون تغییر یک خط از کد تابع، از لایه در توابع لامبدا استفاده کنیم.

راه اندازی تست معماری

برپایی

راه اندازی دارای سه جزء است:

1) لایه تله متری با پسوند Loki
2) ظروف Grafana Loki و سایر ابزارهای تله متری به عنوان راه اندازی docker-compose
3) تست توابع Lambda برای Telemetry API نوشته شده در TypeScript، Python و Go

1) لایه تله متری

این همان لایه ای است که من نصب کردم. برای تابع لامبدا به ARN ارجاع می دهید:

arn:aws:lambda:eu-central-1:012345679812:layer:grafana-loki-extension:1.

2) ابزار Grafana

من از تنظیمی از کتاب Cloud-Native Observability with OpenTelemetry استفاده می کنم

این هست نه برای تولید. برای تنظیمات بهتر، مقالات دیگر این مجموعه را ببینید.

راه اندازی شامل:

  • کلکسیونر Opentelemetry
  • پرومتئوس
  • لوکی
  • Promtail
  • گرافانا

برای یک محیط آزمایشی، کانتینرها را در یک سرور Cloud9 در یک شبکه عمومی راه اندازی می کنیم.

2.1. یک محیط Cloud 9 ایجاد کنید

2.2. قوانینی را به گروه امنیتی نمونه باز شده به IP خود اضافه کنید و api Loki/Promtail را برای آدرس‌های IP Lambda مانند:

sg

برای تولید، شما باید یک راه‌اندازی احراز هویت یا/و Lambda در VPC در یک زیرشبکه خصوصی داشته باشید تا IPهای ثابتی دریافت کنید.

2.3. نصب Docker Compose در Cloud9:

sudo curl -L "https://github.com/docker/compose/releases/download/1.23.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

خروجی:

AWSReservedSSO_AWSAdministratorAccess_b58ba5bc1d953bb1:~/environment $ docker-compose --version
docker-compose version 1.23.1, build b02f1306
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

2.4. کلون کردن مخزن:

git clone https://github.com/megaproaktiv/Lambda-Telemetry-API-Loki.git
cd Lambda-Telemetry-API-Loki/grafana-container/
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

2.5. محیط Grafana را راه اندازی کنید:

docker-compose up
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

خروجی:

Creating network "grafana-container_observability" with the default driver
...
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

2.6. گرافانا را باز کنید

اکنون ابزارهای Grafana باید در حال اجرا باشند، بنابراین IP عمومی نمونه Cloud9 خود را در پورت باز کنید 3000.

مثال: http://3.67.195.192:3000/?orgId=1

شما باید چیزی شبیه به:

گرافانا

3) توابع لامبدا

در دایرکتوری lambda_telementry_api منابع Lambda با CDK تعریف شده اند.

اگر از نسخه لایه دیگری استفاده می کنید، باید url را در آن تطبیق دهید lib/lambda_telementry_api-stack.ts:

const extensionName = "grafana-loki-extension"
const layerVersion="1"
const loki_ip="3.67.195.192"
const distpatch_min_batch_size = "10"

const lambdatelematryApiLayerArn = "arn:aws:lambda:"+region+":"+account+":layer:"+extensionName+":"+layerVersion
const ltaLayer = lambda.LayerVersion.fromLayerVersionArn(this, "ltalayer", lambdatelematryApiLayerArn)
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

همچنین IP Loki را از مرحله آخر تنظیم کنید.

مطمئن شوید که داکر را در حال اجرا کرده اید و پشته CDK را با استفاده از:

task deploy
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این همه توابع لامبدا را ساخته و آنها را مستقر می کند.

اکنون ما یک راه‌اندازی ورود ساده‌تر ایجاد کرده‌ایم:

افزونه

تنظیمات را تست کنید

توابع Lambda تمام رویدادهای PutObject را از یک سطل S3 می گیرند و کلید شی را در DynamoDB می نویسند.

یک اسکریپت تست در داخل وجود دارد lambda_telementry_api دایرکتوری که شی را در سطل ایجاد شده قرار می دهد:

/test/traffic.sh
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اسکریپت را بعد از تقریباً متوقف کنید. 20 کپی تماس.

خروجی به نظر می رسد:

So 12 Feb 2023 14:42:17 CET
upload: ./readme.md to s3://lambdatelementryapistack-incoming0b397865-hjxvhc2842jy//test-4-0-0-
So 12 Feb 2023 14:42:18 CET
upload: ./readme.md to s3://lambdatelementryapistack-incoming0b397865-hjxvhc2842jy//test-4-0-1-
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

گزارش‌های CloudWatch تابع Lambda اکنون خروجی برنامه افزودنی را نیز نشان می‌دهند. سطح گزارش روی پرمخاطب تنظیم شده است، بنابراین می توانید بسیاری از رویدادها را ببینید:

رویدادها را از برنامه افزودنی ثبت کنید

time="2023-02-12T13:42:18Z" level=info msg="[main] Starting the Telemetry API extension" pkg=main
time="2023-02-12T13:42:18Z" level=info msg="[main] Registering extension" pkg=main
time="2023-02-12T13:42:18Z" level=info msg="[client:Register] Registering using baseURLhttp://127.0.0.1:9001/2020-01-01/extension" pkg=extensionApi
time="2023-02-12T13:42:18Z" level=info msg="[client:Register] Registration success with extensionId 5b43e095-292c-4d3c-94d0-be9cea43c78d" pkg=extensionApi
time="2023-02-12T13:42:18Z" level=info msg="[main] Registation success with extensionId5b43e095-292c-4d3c-94d0-be9cea43c78d" pkg=main
time="2023-02-12T13:42:18Z" level=info msg="[main] Starting the Telemetry listener" pkg=main
time="2023-02-12T13:42:18Z" level=info msg="[listener:Start] Starting on addresssandbox:4323" pkg=telemetryApi
time="2023-02-12T13:42:18Z" level=info msg="[main] Subscribing to the Telemetry API" pkg=main
time="2023-02-12T13:42:18Z" level=info msg="[client:Subscribe] Subscribing using baseUrl:http://127.0.0.1:9001/2022-07-01/telemetry" pkg=telemetryApi
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

صف منتظر خاموش شدن یا اگر distpatch_min_batch_sizeرسیده است:

time="2023-02-12T13:58:16Z" level=info msg="[listener:http_handler] logEvents received:1 LogEventsQueue length:2" pkg=telemetryApi
time="2023-02-12T14:02:18Z" level=info msg="[listener:http_handler] logEvents received:2 LogEventsQueue length:11" pkg=telemetryApi
time="2023-02-12T14:02:18Z" level=info msg="[dispatcher:Dispatch] Dispatching :11 log events" pkg=telemetryApi
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ثبت رویدادها از پلتفرم

INIT_START Runtime Version: python:3.9.v16  Runtime Version ARN: arn:aws:lambda:eu-central-1::runtime:07a48df201798d627f2b950f03bb227aab4a655a1d019c3296406f95937e2525
END RequestId: 1af7f8ab-94e7-4a7a-b3c8-db06eedf874b
REPORT RequestId: 1af7f8ab-94e7-4a7a-b3c8-db06eedf874b  Duration: 132.32 ms Billed Duration: 133 ms Memory Size: 1024 MB    Max Memory Used: 83 MB  Init Duration: 783.94 ms    
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

رویدادها را از تابع ثبت کنید

پایتون لامبدا lambda_telementry_api/lambda/py/app.py پاسخ DynamoDb را ثبت می کند:

    for record in message['Records']:
        itemKey = record['s3']['object']['key']
        response = putDynamoItem(environment['Table'], itemKey)
        print(response)
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در گزارش های cloudwatch می بینیم:

{'ConsumedCapacity': {'TableName': 'items', 'CapacityUnits': 1.0}, 'ResponseMetadata': {'RequestId': 'DPKG7GR6V8G0SA2ATEPR2M4UB3VV4KQNSO5AEMVJF66Q9ASUAAJG', 'HTTPStatusCode': 200, 'HTTPHeaders': {'server': 'Server', 'date': 'Sun, 12 Feb 2023 13:42:19 GMT', 'content-type': 'application/x-amz-json-1.0', 'content-length': '62', 'connection': 'keep-alive', 'x-amzn-requestid': 'DPKG7GR6V8G0SA2ATEPR2M4UB3VV4KQNSO5AEMVJF66Q9ASUAAJG', 'x-amz-crc32': '2296128304'}, 'RetryAttempts': 0}}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

حالا باید همین اتفاق را در گرافانا ببینیم.

گزارش های تابع را در Grafana Loki / Grafana جستجو کنید

لوکی با برچسب ها کار می کند. برای یافتن توابع Lambda، کلاینت promtail با نام تابع به عنوان برچسب در مقداردهی اولیه می شود. loki/promtail.go:

    function_name = os.Getenv("AWS_LAMBDA_FUNCTION_NAME")
    labels := "{source=\""+source_name+"\",function=\""+function_name+"\"}"
    lokiIp := os.Getenv("LOKI_IP")
    if len(lokiIp) == 0 {
        panic("LOKI Ip undefined")
    }
    conf = promtail.ClientConfig{
        PushURL:            "http://"+lokiIp+":3100/api/prom/push",
        Labels:             labels,
        BatchWait:          5 * time.Second,
        BatchEntriesNumber: 10000,
        SendLevel:          promtail.INFO,
        PrintLevel:         promtail.ERROR,
    }
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

همه رویدادهای عملکرد لامبدا با عنوان برچسب گذاری شده اند Source=Lambda

در مرورگر Grafana Loki (2) را با نماد کاوش (1) شروع کنید:

لوکی را کاوش کنید

بنابراین پس از ورود اولین رویدادها به لوکی، این برچسب ها را مشاهده می کنید:

برچسب های لامبدا

برچسب source نشان می دهد که ما داریم Lambdaوقایع و سه متفاوت function برچسب‌ها به ما اجازه می‌دهند هر یک از توابع را پرس و جو کنیم.

وقتی این برچسب ها را پرس و جو می کنید، دریافت می کنید فقط گزارش‌های عملکرد، نه گزارش‌های پلتفرم یا برنامه‌های افزودنی مانند CloudWatch:

پرس و جو

بنابراین پسوند کار می کند و همه چیز گزارش عملکرد به لوکی ارسال می شوند!

خلاصه

برنامه افزودنی API و برنامه های افزودنی تله متری Lambda امکان اتصال داده های تله متری به اهداف AWS و غیر AWS را فراهم می کند.

اگر برنامه افزودنی راه‌اندازی و اجرا شود، انعطاف‌پذیری بسیار بیشتری نسبت به CloudWatch به تنهایی دارید. از سوی دیگر، Lambda به شدت با گزارش‌های CloudWatch یکپارچه شده است و برای دریافت آن، باید لایه‌های اضافی را پیکربندی نکنید.

بنابراین برای برنامه استاندارد بدون سرور، پسوندها نباید ضروری باشند. اما برای پروژه های با حجم بالا یا ترکیبی، عملکرد بیشتری را فراهم می کند و در هزینه ها صرفه جویی می کند زیرا به منابع اضافی در قالب Log Function نیاز ندارید.

مزیت اصلی این است که توابع لامبدا ثبت نام همزمانی لامبدا را مصرف نمی کند. همچنین، می‌توانید تصمیم بگیرید که کدام رویدادهای گزارش را می‌خواهید ببینید.

این مقاله مجموعه ای در مورد مشاهده پذیری بدون سرور را به پایان می رساند.

اگر برای پروژه بدون سرور خود نیاز به مشاوره دارید، در تماس با اسپانسر این وبلاگ یعنی tecRacer تردید نکنید.

برای اطلاعات بیشتر در مورد توسعه AWS، من را در برنامه توسعه https://dev.to/megaproaktiv دنبال کنید.

همچنین ببینید

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا