برنامه نویسی

یاد بگیرید که برنامه پایتون خود را مانند یک PRO نظارت کنید! 🧙‍♂️🪄

Summarize this content to 400 words in Persian Lang

TL; DR

در این آموزش آسان برای پیگیری، نحوه نظارت بر برنامه پایتون خود را با استفاده از آن کشف خواهید کرد ردیابی توزیع شده.

آنچه خواهید آموخت: ✨

نحوه ساخت میکروسرویس در پایتون 🐍.
راه اندازی کانتینرهای Docker 📦 برای میکروسرویس ها.
پیکربندی Kubernetes برای مدیریت میکروسرویس ها.
یکپارچه سازی باطن ردیابی برای تجسم ردیابی ها 🕵️‍♂️.

آیا آماده‌اید تا مهارت‌های نظارت بر برنامه پایتون خود را روشن کنید؟ 🔥

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

🚨 در این بخش از وبلاگ، ما یک اپلیکیشن میکروسرویس ساختگی پایتون خواهیم ساخت. اگر قبلاً یکی را دارید و دنبال می‌کنید، از این قسمت صرفنظر کنید.

ساختار پوشه اولیه برنامه خود را مطابق شکل زیر ایجاد کنید. 👇

mkdir python-microservices && cd python-microservices
mkdir src && cd src
mkdir microservice1 microservice2

راه اندازی سرور 🖥️

برای اهداف نمایشی، من دو میکروسرویس ایجاد خواهم کرد که با یکدیگر ارتباط برقرار می کنند و در نهایت، می توانیم از آن برای تجسم ردیابی توزیع شده استفاده کنیم.

Microservice ساخت و Dockerizing 1

داخل /microservice1 دایرکتوری، یک محیط مجازی پایتون جدید ایجاد کنید، وابستگی های لازم را نصب کنید و یک برنامه Flask را مقداردهی اولیه کنید.

🚨 من فرض می‌کنم که شما با یک ماشین مبتنی بر یونیکس دنبال می‌کنید. اگر در دستگاه ویندوزی هستید، برخی از دستورات متفاوت خواهند بود.

cd microservice1
python -m venv .venv
source .venv/bin/activate

💡 اگر روی پوسته ماهی هستید، دستور زیر را اجرا کنید تا محیط مجازی فعال شود.

source .venv/bin/activate.fish

وابستگی های مورد نیاز را نصب کنید:

pip install Flask requests

دریافت لیست وابستگی های نصب شده در requirements.txt تا بعداً بتوانیم از آن در کانتینر خود برای نصب وابستگی ها استفاده کنیم.

pip freeze > requirements.txt

یک فایل جدید به نام ایجاد کنید app.py و خطوط کد زیر را اضافه کنید:

# 👇 src/microservice1/app.py
import socket
import requests
from flask import Flask, jsonify, render_template

app = Flask(__name__)

def user_os_details():
hostname = socket.gethostname()
hostip = socket.gethostbyname(hostname)
return hostname, hostip

@app.route(“/”)
def index():
return “<p>Welcome to Flask microservice 1</p>”

@app.route(“/health”)
def health():
return jsonify(status=”Microservice 1 Running…”)

@app.route(“/get-users”)
def get_users():
response = requests.get(“http://microservice2:5001/get-gh-users”)
return render_template(“index.html”, users=response.json())

@app.route(“/os-details”)
def details():
host_name, host_ip = user_os_details()
return jsonify(hostname=host_name, hostip=host_ip)

if __name__ == “__main__”:
app.run(“0.0.0.0”, 5000)

💡 اگر متوجه شده اید، ما در حال درخواست داده از http://microservice2:5001/get-gh-users. شاید بپرسید این میکروسرویس2 چیست؟ خوب، ما می توانیم از نام سرویس به عنوان نام میزبان در همان شبکه در docker استفاده کنیم. ما بعداً پس از اتمام نوشتن و داکر کردن این میکروسرویس، این سرویس را ایجاد خواهیم کرد.

همانطور که می بینید، این یک برنامه بسیار ساده Flask با چند نقطه پایانی است. را user_os_details() تابع را دریافت می کند نام میزبان و آدرس IP از دستگاه

را @app.route(“/”) و @app.route(“/health”) دکوراتورها ریشه و نقطه پایانی “/health” برنامه Flask را تعریف می کنند. نقطه پایانی “/health” بعداً برای بررسی سلامت کانتینر استفاده خواهد شد ❤️‍🩹 در Dockerfile.

را @app.route(“/get-users”) و @app.route(“/os-details”) دکوراتورها نقاط پایانی “/get-users” و “/os-details” را تعریف می کنند. نقطه پایانی “/get-users” کاربران GitHub را از آن واکشی می کند میکروسرویس 2 و آنها را به عنوان تکیه گاه به index.html فایل برای رندر در همین حال، نقطه پایانی “/os-details” جزئیات سیستم را نمایش می دهد. در نهایت برنامه روی پورت 5000 اجرا می شود.

حال، بیایید ایجاد کنیم index.html فایلی که در آن کاربران دریافتی را از microservice2 رندر می کنیم.

یک پوشه جدید ایجاد کنید /templates و یک را اضافه کنید index.html فایل با محتوای زیر:

<!– 👇 src/microservice1/templates/index.html –>

<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
<title>Microservice 1</title>
</head>
<body>
<h1>Microservice 1</h1>
<h2>This is the data received from microservice2:</h2>
<p>{{ users }}</p>
</body>
</html>

اولین میکروسرویس ما آماده است. بیایید آن را docker کنیم. ایجاد یک Dockerfile داخل /microservice1 دایرکتوری و خطوط کد زیر را اضافه کنید:

🚨 حتما اسمش را دقیقا بنویسید Dockerfile بدون پسوند

# 👇 src/microservice1/Dockerfile
# Use Python alpine as the base image.
FROM python:3.12.1-alpine3.18
# Optional: Upgrade pip to the latest version.
RUN pip install –upgrade pip
# Create a new user with fewer permissions.
RUN adduser -D lowkey
# Switch to user lowkey
USER lowkey
# Change the working directory to ~/app
WORKDIR /home/lowkey/app
# Copy the requirements.txt file required to install the dependencies.
COPY –chown=lowkey:lowkey requirements.txt requirements.txt
# Install the dependencies
RUN pip install -r requirements.txt
# Copy the rest of the files to the current directory in the docker container.
COPY –chown=lowkey:lowkey . .
# Expose port 5000
EXPOSE 5000
# Switch to the root user just for installing curl. It is required.
USER root
# Install curl. Alpine uses apk as its package manager.
RUN apk –no-cache add curl
# Switch back to user lowkey
USER lowkey
# Check the health of the container. The “/health” endpoint is used
# to verify the container is up and running.
HEALTHCHECK –interval=30s –timeout=30s –start-period=30s –retries=5 \
CMD curl -f http://localhost:5000/health || exit 1
# Finally, start the application.
ENTRYPOINT [ “python”, “app.py” ]

ایجاد یک .dockerignore فایلی با نام فایل‌هایی که نمی‌خواهیم به کانتینر منتقل کنیم.

__pycache__
.venv
README.md
Dockerfile
.dockerignore

اکنون، این کل تنظیمات اولین میکروسرویس ما است. ✨

Microservice ساخت و Dockerizing 2

ما یک راه اندازی مشابه خواهیم داشت میکروسرویس 1، فقط با چند تغییر اینجا و آنجا.

تنظیمات اولیه را دقیقاً همانطور که برای آن انجام دادیم انجام دهید میکروسرویس 1. پس از آن، در /microservice2 پوشه، ایجاد کنید app.py فایل و خطوط کد زیر را اضافه کنید:

# 👇 src/microservice2/app.py
import random
import requests
from flask import Flask, jsonify, render_template

app = Flask(__name__)

def get_gh_users():
url = “https://api.github.com/users?per_page=5”

# Choose a random timeout between 1 and 5 seconds
timeout = random.randint(3, 6)

try:
response = requests.get(url, timeout=timeout)
return response.json()
except requests.exceptions.Timeout:
return {“error”: “Request timed out after {} seconds”.format(timeout)}
except requests.exceptions.RequestException as e:
return {“error”: “Request failed: {}”.format(e)}

@app.route(“/”)
def index():
return “<p>Welcome to Flask microservice 2</p>”

@app.route(“/get-gh-users”)
def get_users():
results = []

# Loop through the number of requests and append the results to the list
for _ in range(3):
result = get_gh_users()
results.append(result)

# Return the list of results as a JSON response
return jsonify(results)

@app.route(“/health”)
def health():
return jsonify(status=”Microservice 2 Running…”)

@app.route(“/os-details”)
def details():
try:
response = requests.get(“http://microservice1:5000/os-details”).json()
host_name = response[“hostname”] host_ip = response[“hostip”] return render_template(“index.html”, hostname=host_name, hostip=host_ip)
except requests.exceptions.Timeout as errt:
return {“error”: “Request timed out after {} seconds”.format(errt)}
except requests.exceptions.RequestException as e:
return {“error”: “Request failed: {}”.format(e)}

if __name__ == “__main__”:
app.run(“0.0.0.0”, 5001)

را @app.route(“/”) دکوراتور نقطه پایانی اصلی برنامه Flask را تعریف می کند و یک پیام خوشامدگویی را برمی گرداند. را @app.route(“/health”) decorator نقطه پایانی “/health” را تعریف می کند که می تواند برای بررسی وضعیت سلامت ظرف مورد استفاده قرار گیرد.

را @app.route(“/get-gh-users”) decorator نقطه پایانی “/get-gh-users” را تعریف می کند که از عبارت استفاده می کند get_gh_users() عملکردی برای واکشی کاربران GitHub و برگرداندن آنها به عنوان یک پاسخ JSON. در نهایت، @app.route(“/os-details”) decorator نقطه پایانی “/os-details” را تعریف می کند که جزئیات سیستم عامل را از آن بازیابی می کند میکروسرویس 1 و آنها را در index.html فایل در نهایت برنامه روی پورت 5001 اجرا می شود.

حال، بیایید ایجاد کنیم index.html فایلی که ما کاربران دریافتی را از آن رندر می کنیم میکروسرویس 2.

یک پوشه جدید ایجاد کنید /templates و یک را اضافه کنید index.html فایل با محتوای زیر:

<!– 👇 src/microservice2/templates/index.html –>

<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
<title>Microservice 2</title>
</head>
<body>
<h1>Microservice 2</h1>
<h2>This is the hostname and IP address received from the microservice1:</h2>
<p>{{ hostname }} – {{ hostip }}</p>
</body>
</html>

اکنون زمان آن رسیده است که این میکروسرویس را نیز داکر کنیم. کل را کپی و پیست کنید Dockerfile محتوا برای میکروسرویس 1 و فقط پورت را از 5000 به 5001 تغییر دهید.

همچنین، یک را اضافه کنید .dockerignore فایل و همان فایل هایی را که در هنگام ایجاد اضافه کردیم را شامل شود میکروسرویس 1.

اکنون، این کل تنظیمات میکروسرویس دوم ما نیز هست. ✨

ساخت Dockerfiles با Docker Compose

ما بهترین شیوه های ساخت تصویر را با استفاده از Docker Compose به جای ساخت هر تصویر به صورت دستی دنبال خواهیم کرد. در اینجا ما فقط دو تصویر داریم، اما تصور کنید که صدها یا هزاران Dockerfiles داشته باشیم. ساخت هر کدام به صورت دستی کار خسته کننده ای خواهد بود. 😴

در ریشه پروژه، یک فایل جدید با نام ایجاد کنید docker-compose.yaml و کد زیر را اضافه کنید:

services:
microservice1:
build:
context: ./src/microservice1
dockerfile: Dockerfile
image: microservice1-image:1.0
ports:
– “5000:5000”
restart: always

microservice2:
build:
context: ./src/microservice2
dockerfile: Dockerfile
image: microservice2-image:1.0
ports:
– “5001:5001”
restart: always

این فایل Docker Compose دو سرویس را تعریف می کند، میکروسرویس 1 و میکروسرویس 2. هر سرویس با استفاده از سرویس مربوطه خود ساخته می شود Dockerfile واقع در /src دایرکتوری، با میکروسرویس 1 نگاشت به پورت 5000 و میکروسرویس 2 به پورت 5001

تصاویر به دست آمده برچسب گذاری می شوند microservice1-image:1.0 و microservice2-image:1.0به ترتیب. هر دو سرویس تنظیم شده‌اند که همیشه راه‌اندازی مجدد شوند، مطمئن شوید که اگر کانتینر با مشکل مواجه شود، دوباره راه‌اندازی می‌شود.

حال با استفاده از دستور زیر تصاویر را بسازید:

docker compose build

استقرار در Kubernetes 🧑‍🚀

مطمئن شوید مینی کوب نصب شده است، یا دنبال کنید این لینک راهنمای نصب 👀

با اجرای دستور زیر یک کلاستر محلی Kubernetes ایجاد کنید. هنگام راه اندازی Odigos و Jaeger به آن نیاز خواهیم داشت.

Minikube را شروع کنید: 🚀

minikube start

از آنجایی که ما در محیط محلی Kubernetes در حال اجرا هستیم، باید پوسته خود را برای استفاده از داکر-دمون minikube نشان دهیم.

برای نشان دادن پوسته خود به داکر-دمون minikube، اجرا کنید:

minikube -p minikube docker-env | source

و اکنون، هنگام اجرای هر دستور Docker مانند docker images یا docker ps، آنچه را که در Minikube وجود دارد به جای آنچه که به صورت محلی در سیستم خود دارید، خواهید دید.

اکنون که هر دو میکروسرویس خود را آماده و داکر شده‌ایم، زمان آن رسیده است که Kubernetes را برای مدیریت این سرویس‌ها راه‌اندازی کنیم.

در ریشه پروژه، یک پوشه جدید ایجاد کنید /k8s/manifests. در داخل این پوشه، پیکربندی‌های استقرار و سرویس را برای هر دو میکروسرویس خود اضافه می‌کنیم.

پیکربندی استقرار 📜: برای استقرار کانتینرها در خوشه Kubernetes.

پیکربندی سرویس 📄: برای نمایش غلاف ها در داخل خوشه و خارج از خوشه.

ابتدا اجازه دهید مانیفست را برای آن ایجاد کنیم microservice1. یک فایل جدید ایجاد کنید microservice1-deployment-service.yaml و مطالب زیر را اضافه کنید:

// 👇 k8s/manifests/microservice1-deployment-service.yaml
version: apps/v1
kind: Deployment
metadata:
name: microservice1
spec:
selector:
matchLabels:
app: microservice1
template:
metadata:
labels:
app: microservice1
spec:
containers:
– name: microservice1
image: microservice1-image:1.0
imagePullPolicy: Never
resources:
limits:
memory: “200Mi”
cpu: “500m”
ports:
– containerPort: 5000

apiVersion: v1
kind: Service
metadata:
name: microservice1
labels:
app: microservice1
spec:
type: NodePort
selector:
app: microservice1
ports:
– port: 8080
targetPort: 5000
nodePort: 30001

این پیکربندی یک میکروسرویس به نام را مستقر می کند میکروسرویس 1 با محدودیت منابع از 200 مگابایت حافظه 🗃️ و 0.5 هسته CPU. این میکروسرویس را به صورت داخلی در پورت 5000 از طریق Deployment و به صورت خارجی در معرض دید قرار می دهد NodePort 30001 از طریق یک سرویس.

🤔 به یاد داشته باشید docker-compose build دستوری که ما هنگام ساختن Dockerfiles خود به خصوص نام تصاویر استفاده کردیم؟ ما از همان تصاویر برای ایجاد کانتینرها استفاده می کنیم.

در پورت 8080 در کلاستر قابل دسترسی است. فرض می کنیم microservice1-image:1.0 به صورت محلی در دسترس است با imagePullPolicy: Never. اگر این در جای خود نباشد، سعی می کند تصویر را از داکر هاب 🐋 بیرون بکشد و شکست بخورد.

حال، بیایید مانیفست را برای میکروسرویس 2. یک فایل جدید با نام ایجاد کنید microservice2-deployment-service.yaml و مطالب زیر را اضافه کنید:

// 👇 k8s/manifests/microservice2-deployment-service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: microservice2
spec:
selector:
matchLabels:
app: microservice2
template:
metadata:
labels:
app: microservice2
spec:
containers:
– name: microservice2
image: microservice2-image:1.0
imagePullPolicy: Never
resources:
limits:
memory: “200Mi”
cpu: “500m”
ports:
– containerPort: 5001

apiVersion: v1
kind: Service
metadata:
name: microservice2
labels:
app: microservice2
spec:
type: NodePort
selector:
app: microservice2
ports:
– port: 8081
targetPort: 5001
nodePort: 30002

شبیه مانیفست برای است microservice1، تنها با چند تغییر.

این پیکربندی یک میکروسرویس به نام را مستقر می کند میکروسرویس 2 و آن را به صورت داخلی در پورت 5001 از طریق Deployment و به صورت خارجی در معرض دید قرار می دهد NodePort 30002 از طریق یک سرویس.

قابل دسترسی در پورت 8081 در داخل خوشه، با فرض microservice2-image:1.0 به صورت محلی در دسترس است با imagePullPolicy: Never.

وقتی همه این کارها انجام شد، مطمئن شوید که این تنظیمات را اعمال کرده اید و خوشه Kubernetes را با این سرویس ها راه اندازی کنید. دایرکتوری را به /manifests و دستورات زیر را اجرا کنید:

kubectl apply -f microservice1-deployment-service.yaml
kubectl apply -f microservice2-deployment-service.yaml

بررسی کنید که هر دو استقرار ما هستند در حال دویدن با اجرای دستور زیر:

kubectl get pods

در نهایت، برنامه ما آماده است و در Kubernetes با تنظیمات استقرار لازم مستقر شده است. 🎊

در حال نصب Odigos 🧑‍💻

💡 اودیگوها یک صفحه کنترل مشاهده پذیری منبع باز است که سازمان ها را قادر می سازد خط لوله مشاهده پذیری خود را ایجاد و حفظ کنند. به طور خلاصه، ما از Odigos برای ابزارسازی خودکار برنامه پایتون خود استفاده خواهیم کرد.

ℹ️ اگر روی مک در حال اجرا هستید، دستور زیر را برای نصب Odigos به صورت محلی اجرا کنید.

brew install keyval-dev/homebrew-odigos-cli/odigos

ℹ️ اگر از یک ماشین لینوکس استفاده می کنید، با اجرای دستورات زیر آن را از نسخه های GitHub نصب کنید. مطمئن شوید که فایل را با توجه به توزیع لینوکس خود تغییر دهید.

ℹ️ اگر باینری Odigos قابل اجرا نیست، این دستور را اجرا کنید chmod +x odigos تا قبل از اجرای دستور install آن را قابل اجرا کنید.

curl -LJO https://github.com/keyval-dev/odigos/releases/download/v1.0.15/cli_1.0.15_linux_amd64.tar.gz
tar -xvzf cli_1.0.15_linux_amd64.tar.gz
./odigos install

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

اکنون، Odigos آماده اجرا است 🚀. می‌توانیم رابط کاربری آن را اجرا کنیم، باطن ردیابی را پیکربندی کنیم و ردیابی‌ها را بر اساس آن ارسال کنیم.

اتصال Odigos به Backend Tracing ✨

💡 جیگر یک سیستم ردیابی توزیع شده سرتاسر منبع باز است.

راه اندازی Jaeger ✨

برای این آموزش استفاده خواهیم کرد جیگر 🕵️‍♂️، یک پلت فرم منبع باز محبوب برای مشاهده ردیابی های توزیع شده در یک برنامه میکروسرویس. ما از آن برای مشاهده ردیابی های تولید شده توسط Odigos استفاده خواهیم کرد.

برای دستورالعمل های نصب Jaeger، این را دنبال کنید پیوند. 👀

برای استقرار Jaeger در یک خوشه Kubernetes، دستورات زیر را اجرا کنید:

kubectl create ns tracing
kubectl apply -f https://raw.githubusercontent.com/keyval-dev/opentelemetry-go-instrumentation/master/docs/getting-started/jaeger.yaml -n tracing

در اینجا، ما در حال ایجاد یک tracing فضای نام و اعمال پیکربندی استقرار 📃 برای Jaeger در آن فضای نام.

این دستور نمونه Jaeger خود میزبان و سرویس آن را تنظیم می کند.

برای دریافت وضعیت پادهای در حال اجرا دستور زیر را اجرا کنید:

kubectl get pods -A -w

صبر کنید تا هر سه غلاف درست شود در حال دویدن قبل از ادامه بیشتر

اکنون، برای مشاهده رابط Jaeger به صورت محلی، باید به جلو منتقل کنیم. ترافیک را از پورت 16686 در ماشین محلی به پورت 16686 در غلاف انتخابی در خوشه Kubernetes هدایت کنید.

kubectl port-forward -n tracing svc/jaeger 16686:16686

این دستور یک تونل بین ماشین محلی و Jaeger pod ایجاد می کند و رابط کاربری Jaeger را نشان می دهد تا بتوانید با آن تعامل داشته باشید.

در حال حاضر، در http://localhost:16686، باید بتوانید نمونه Jaeger را در حال اجرا ببینید.

پیکربندی Odigos برای کار با Jaeger 🌟

ℹ️ برای کاربران لینوکس، به پوشه ای که باینری های Odigos را از نسخه های GitHub دانلود کرده اید بروید و دستور زیر را برای راه اندازی Odigos UI اجرا کنید.

./odigos ui

ℹ️ برای کاربران مک، فقط اجرا کنید:

odigos ui

بازدید کنید http://localhost:3000 و با رابط Odigos روبرو خواهید شد که در آن هر دو استقرار را در آن مشاهده خواهید کرد default فضای نام

هر دو مورد را انتخاب کنید و روی Next کلیک کنید. در صفحه بعد، Jaeger را به عنوان باطن انتخاب کنید و وقتی از شما خواسته شد جزئیات زیر را اضافه کنید:

نام مقصد: هر اسمی میخوای بذار، بگیم ردیابی پایتون.

نقطه پایان 🎯: اضافه کردن jaeger.tracing:4317 برای نقطه پایانی

و تمام – Odigos آماده است تا آثاری را به باطن Jaeger ما ارسال کند. به همین سادگی است.

مشاهده ردیابی توزیع شده 🧐

به محض اینکه Odigos را برای کار با Jaeger به عنوان باطن ردیابی خود راه اندازی کردیم، Odigos از قبل شروع به ارسال آثار برنامه ما به Jaeger کرده است.

بازدید کنید http://localhost:16686 و هر دو میکروسرویس ما را در منوی کشویی انتخاب کنید.

چند درخواست به نقاط پایانی ما ارائه دهید، و در نهایت، Jaeger شروع به پر شدن با ردیابی خواهد کرد.

روی هر یک از درخواست ها کلیک کنید و ردیابی ها را بررسی کنید.

این همه بدون تغییر یک خط کد انجام شد. 🔥

جمع بندی! ⚡

تا کنون، شما یاد گرفته اید که برنامه پایتون خود را با ردیابی توزیع شده، با استفاده از نظارت دقیق 👀 اودیگوها به عنوان میان افزار بین برنامه شما و باطن ردیابی جیگر.

کد منبع این آموزش در اینجا موجود است:

https://github.com/shricodev/blogs/tree/main/odgs-monitor-PY-like-a-pro

خیلی ممنون که خواندید! 🎉 🫡

نظرات خود را در بخش نظرات زیر بیاندازید. 👇

من را در شبکه های اجتماعی دنبال کنید 🐥

شریج آچاریا فالو کنید

Full Stack SDE • مشارکت کننده منبع باز • همکار @Oppia • ایمیل برای همکاری

TL; DR

در این آموزش آسان برای پیگیری، نحوه نظارت بر برنامه پایتون خود را با استفاده از آن کشف خواهید کرد ردیابی توزیع شده.

آنچه خواهید آموخت: ✨

  • نحوه ساخت میکروسرویس در پایتون 🐍.
  • راه اندازی کانتینرهای Docker 📦 برای میکروسرویس ها.
  • پیکربندی Kubernetes برای مدیریت میکروسرویس ها.
  • یکپارچه سازی باطن ردیابی برای تجسم ردیابی ها 🕵️‍♂️.

آیا آماده‌اید تا مهارت‌های نظارت بر برنامه پایتون خود را روشن کنید؟ 🔥

گیف آتش بزنید

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

🚨 در این بخش از وبلاگ، ما یک اپلیکیشن میکروسرویس ساختگی پایتون خواهیم ساخت. اگر قبلاً یکی را دارید و دنبال می‌کنید، از این قسمت صرفنظر کنید.

ساختار پوشه اولیه برنامه خود را مطابق شکل زیر ایجاد کنید. 👇

mkdir python-microservices && cd python-microservices
mkdir src && cd src
mkdir microservice1 microservice2

راه اندازی سرور 🖥️

برای اهداف نمایشی، من دو میکروسرویس ایجاد خواهم کرد که با یکدیگر ارتباط برقرار می کنند و در نهایت، می توانیم از آن برای تجسم ردیابی توزیع شده استفاده کنیم.

Microservice ساخت و Dockerizing 1

داخل /microservice1 دایرکتوری، یک محیط مجازی پایتون جدید ایجاد کنید، وابستگی های لازم را نصب کنید و یک برنامه Flask را مقداردهی اولیه کنید.

🚨 من فرض می‌کنم که شما با یک ماشین مبتنی بر یونیکس دنبال می‌کنید. اگر در دستگاه ویندوزی هستید، برخی از دستورات متفاوت خواهند بود.

cd microservice1
python -m venv .venv
source .venv/bin/activate

💡 اگر روی پوسته ماهی هستید، دستور زیر را اجرا کنید تا محیط مجازی فعال شود.

source .venv/bin/activate.fish

وابستگی های مورد نیاز را نصب کنید:

pip install Flask requests

دریافت لیست وابستگی های نصب شده در requirements.txt تا بعداً بتوانیم از آن در کانتینر خود برای نصب وابستگی ها استفاده کنیم.

pip freeze > requirements.txt

یک فایل جدید به نام ایجاد کنید app.py و خطوط کد زیر را اضافه کنید:

# 👇 src/microservice1/app.py
import socket
import requests
from flask import Flask, jsonify, render_template

app = Flask(__name__)

def user_os_details():
    hostname = socket.gethostname()
    hostip = socket.gethostbyname(hostname)
    return hostname, hostip

@app.route("/")
def index():
    return "<p>Welcome to Flask microservice 1</p>"

@app.route("/health")
def health():
    return jsonify(status="Microservice 1 Running...")

@app.route("/get-users")
def get_users():
    response = requests.get("http://microservice2:5001/get-gh-users")
    return render_template("index.html", users=response.json())

@app.route("/os-details")
def details():
    host_name, host_ip = user_os_details()
    return jsonify(hostname=host_name, hostip=host_ip)

if __name__ == "__main__":
    app.run("0.0.0.0", 5000)

💡 اگر متوجه شده اید، ما در حال درخواست داده از http://microservice2:5001/get-gh-users. شاید بپرسید این میکروسرویس2 چیست؟ خوب، ما می توانیم از نام سرویس به عنوان نام میزبان در همان شبکه در docker استفاده کنیم. ما بعداً پس از اتمام نوشتن و داکر کردن این میکروسرویس، این سرویس را ایجاد خواهیم کرد.

همانطور که می بینید، این یک برنامه بسیار ساده Flask با چند نقطه پایانی است. را user_os_details() تابع را دریافت می کند نام میزبان و آدرس IP از دستگاه

را @app.route("/") و @app.route("/health") دکوراتورها ریشه و نقطه پایانی “/health” برنامه Flask را تعریف می کنند. نقطه پایانی “/health” بعداً برای بررسی سلامت کانتینر استفاده خواهد شد ❤️‍🩹 در Dockerfile.

را @app.route("/get-users") و @app.route("/os-details") دکوراتورها نقاط پایانی “/get-users” و “/os-details” را تعریف می کنند. نقطه پایانی “/get-users” کاربران GitHub را از آن واکشی می کند میکروسرویس 2 و آنها را به عنوان تکیه گاه به index.html فایل برای رندر در همین حال، نقطه پایانی “/os-details” جزئیات سیستم را نمایش می دهد. در نهایت برنامه روی پورت 5000 اجرا می شود.

حال، بیایید ایجاد کنیم index.html فایلی که در آن کاربران دریافتی را از microservice2 رندر می کنیم.

یک پوشه جدید ایجاد کنید /templates و یک را اضافه کنید index.html فایل با محتوای زیر:

<!-- 👇 src/microservice1/templates/index.html -->

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Microservice 1</title>
</head>
<body>
  <h1>Microservice 1</h1>
  <h2>This is the data received from microservice2:</h2>
  <p>{{ users }}</p>
</body>
</html>

اولین میکروسرویس ما آماده است. بیایید آن را docker کنیم. ایجاد یک Dockerfile داخل /microservice1 دایرکتوری و خطوط کد زیر را اضافه کنید:

🚨 حتما اسمش را دقیقا بنویسید Dockerfile بدون پسوند

# 👇 src/microservice1/Dockerfile
# Use Python alpine as the base image.
FROM python:3.12.1-alpine3.18
# Optional: Upgrade pip to the latest version.
RUN pip install --upgrade pip
# Create a new user with fewer permissions.
RUN adduser -D lowkey
# Switch to user lowkey
USER lowkey
# Change the working directory to ~/app
WORKDIR /home/lowkey/app
# Copy the requirements.txt file required to install the dependencies.
COPY --chown=lowkey:lowkey requirements.txt requirements.txt
# Install the dependencies
RUN pip install -r requirements.txt
# Copy the rest of the files to the current directory in the docker container.
COPY --chown=lowkey:lowkey . .
# Expose port 5000
EXPOSE 5000
# Switch to the root user just for installing curl. It is required.
USER root
# Install curl. Alpine uses apk as its package manager.
RUN apk --no-cache add curl
# Switch back to user lowkey
USER lowkey
# Check the health of the container. The "/health" endpoint is used 
# to verify the container is up and running.
HEALTHCHECK --interval=30s --timeout=30s --start-period=30s --retries=5 \ 
            CMD curl -f http://localhost:5000/health || exit 1
# Finally, start the application.
ENTRYPOINT [ "python", "app.py" ]

ایجاد یک .dockerignore فایلی با نام فایل‌هایی که نمی‌خواهیم به کانتینر منتقل کنیم.

__pycache__
.venv
README.md
Dockerfile
.dockerignore

اکنون، این کل تنظیمات اولین میکروسرویس ما است. ✨

Microservice ساخت و Dockerizing 2

ما یک راه اندازی مشابه خواهیم داشت میکروسرویس 1، فقط با چند تغییر اینجا و آنجا.

تنظیمات اولیه را دقیقاً همانطور که برای آن انجام دادیم انجام دهید میکروسرویس 1. پس از آن، در /microservice2 پوشه، ایجاد کنید app.py فایل و خطوط کد زیر را اضافه کنید:

# 👇 src/microservice2/app.py
import random
import requests
from flask import Flask, jsonify, render_template

app = Flask(__name__)

def get_gh_users():
    url = "https://api.github.com/users?per_page=5"

    # Choose a random timeout between 1 and 5 seconds
    timeout = random.randint(3, 6)

    try:
        response = requests.get(url, timeout=timeout)
        return response.json()
    except requests.exceptions.Timeout:
        return {"error": "Request timed out after {} seconds".format(timeout)}
    except requests.exceptions.RequestException as e:
        return {"error": "Request failed: {}".format(e)}

@app.route("/")
def index():
    return "<p>Welcome to Flask microservice 2</p>"

@app.route("/get-gh-users")
def get_users():
    results = []

    # Loop through the number of requests and append the results to the list
    for _ in range(3):
        result = get_gh_users()
        results.append(result)

    # Return the list of results as a JSON response
    return jsonify(results)

@app.route("/health")
def health():
    return jsonify(status="Microservice 2 Running...")

@app.route("/os-details")
def details():
    try:
        response = requests.get("http://microservice1:5000/os-details").json()
        host_name = response["hostname"]
        host_ip = response["hostip"]
        return render_template("index.html", hostname=host_name, hostip=host_ip)
    except requests.exceptions.Timeout as errt:
        return {"error": "Request timed out after {} seconds".format(errt)}
    except requests.exceptions.RequestException as e:
        return {"error": "Request failed: {}".format(e)}

if __name__ == "__main__":
    app.run("0.0.0.0", 5001)

را @app.route("/") دکوراتور نقطه پایانی اصلی برنامه Flask را تعریف می کند و یک پیام خوشامدگویی را برمی گرداند. را @app.route("/health") decorator نقطه پایانی “/health” را تعریف می کند که می تواند برای بررسی وضعیت سلامت ظرف مورد استفاده قرار گیرد.

را @app.route("/get-gh-users") decorator نقطه پایانی “/get-gh-users” را تعریف می کند که از عبارت استفاده می کند get_gh_users() عملکردی برای واکشی کاربران GitHub و برگرداندن آنها به عنوان یک پاسخ JSON. در نهایت، @app.route("/os-details") decorator نقطه پایانی “/os-details” را تعریف می کند که جزئیات سیستم عامل را از آن بازیابی می کند میکروسرویس 1 و آنها را در index.html فایل در نهایت برنامه روی پورت 5001 اجرا می شود.

حال، بیایید ایجاد کنیم index.html فایلی که ما کاربران دریافتی را از آن رندر می کنیم میکروسرویس 2.

یک پوشه جدید ایجاد کنید /templates و یک را اضافه کنید index.html فایل با محتوای زیر:

<!-- 👇 src/microservice2/templates/index.html -->

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Microservice 2</title>
</head>
<body>
  <h1>Microservice 2</h1>
  <h2>This is the hostname and IP address received from the microservice1:</h2>
  <p>{{ hostname }} - {{ hostip }}</p>
</body>
</html>

اکنون زمان آن رسیده است که این میکروسرویس را نیز داکر کنیم. کل را کپی و پیست کنید Dockerfile محتوا برای میکروسرویس 1 و فقط پورت را از 5000 به 5001 تغییر دهید.

همچنین، یک را اضافه کنید .dockerignore فایل و همان فایل هایی را که در هنگام ایجاد اضافه کردیم را شامل شود میکروسرویس 1.

اکنون، این کل تنظیمات میکروسرویس دوم ما نیز هست. ✨

ساخت Dockerfiles با Docker Compose

ما بهترین شیوه های ساخت تصویر را با استفاده از Docker Compose به جای ساخت هر تصویر به صورت دستی دنبال خواهیم کرد. در اینجا ما فقط دو تصویر داریم، اما تصور کنید که صدها یا هزاران Dockerfiles داشته باشیم. ساخت هر کدام به صورت دستی کار خسته کننده ای خواهد بود. 😴

در ریشه پروژه، یک فایل جدید با نام ایجاد کنید docker-compose.yaml و کد زیر را اضافه کنید:

services:
  microservice1:
    build:
      context: ./src/microservice1
      dockerfile: Dockerfile
    image: microservice1-image:1.0
    ports:
      - "5000:5000"
    restart: always

  microservice2:
    build:
      context: ./src/microservice2
      dockerfile: Dockerfile
    image: microservice2-image:1.0
    ports:
      - "5001:5001"
    restart: always

این فایل Docker Compose دو سرویس را تعریف می کند، میکروسرویس 1 و میکروسرویس 2. هر سرویس با استفاده از سرویس مربوطه خود ساخته می شود Dockerfile واقع در /src دایرکتوری، با میکروسرویس 1 نگاشت به پورت 5000 و میکروسرویس 2 به پورت 5001

تصاویر به دست آمده برچسب گذاری می شوند microservice1-image:1.0 و microservice2-image:1.0به ترتیب. هر دو سرویس تنظیم شده‌اند که همیشه راه‌اندازی مجدد شوند، مطمئن شوید که اگر کانتینر با مشکل مواجه شود، دوباره راه‌اندازی می‌شود.

حال با استفاده از دستور زیر تصاویر را بسازید:

docker compose build

خروجی ساخت Docker Compose

استقرار در Kubernetes 🧑‍🚀

مطمئن شوید مینی کوب نصب شده است، یا دنبال کنید این لینک راهنمای نصب 👀

با اجرای دستور زیر یک کلاستر محلی Kubernetes ایجاد کنید. هنگام راه اندازی Odigos و Jaeger به آن نیاز خواهیم داشت.

Minikube را شروع کنید: 🚀

minikube start

شروع Minikube

از آنجایی که ما در محیط محلی Kubernetes در حال اجرا هستیم، باید پوسته خود را برای استفاده از داکر-دمون minikube نشان دهیم.

برای نشان دادن پوسته خود به داکر-دمون minikube، اجرا کنید:

minikube -p minikube docker-env | source

و اکنون، هنگام اجرای هر دستور Docker مانند docker images یا docker ps، آنچه را که در Minikube وجود دارد به جای آنچه که به صورت محلی در سیستم خود دارید، خواهید دید.

اکنون که هر دو میکروسرویس خود را آماده و داکر شده‌ایم، زمان آن رسیده است که Kubernetes را برای مدیریت این سرویس‌ها راه‌اندازی کنیم.

در ریشه پروژه، یک پوشه جدید ایجاد کنید /k8s/manifests. در داخل این پوشه، پیکربندی‌های استقرار و سرویس را برای هر دو میکروسرویس خود اضافه می‌کنیم.

  • پیکربندی استقرار 📜: برای استقرار کانتینرها در خوشه Kubernetes.
  • پیکربندی سرویس 📄: برای نمایش غلاف ها در داخل خوشه و خارج از خوشه.

ابتدا اجازه دهید مانیفست را برای آن ایجاد کنیم microservice1. یک فایل جدید ایجاد کنید microservice1-deployment-service.yaml و مطالب زیر را اضافه کنید:

// 👇 k8s/manifests/microservice1-deployment-service.yaml
version: apps/v1
kind: Deployment
metadata:
  name: microservice1
spec:
  selector:
    matchLabels:
      app: microservice1
  template:
    metadata:
      labels:
        app: microservice1
    spec:
      containers:
        - name: microservice1
          image: microservice1-image:1.0
          imagePullPolicy: Never
          resources:
            limits:
              memory: "200Mi"
              cpu: "500m"
          ports:
            - containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
  name: microservice1
  labels:
    app: microservice1
spec:
  type: NodePort
  selector:
    app: microservice1
  ports:
    - port: 8080
      targetPort: 5000
      nodePort: 30001

این پیکربندی یک میکروسرویس به نام را مستقر می کند میکروسرویس 1 با محدودیت منابع از 200 مگابایت حافظه 🗃️ و 0.5 هسته CPU. این میکروسرویس را به صورت داخلی در پورت 5000 از طریق Deployment و به صورت خارجی در معرض دید قرار می دهد NodePort 30001 از طریق یک سرویس.

🤔 به یاد داشته باشید docker-compose build دستوری که ما هنگام ساختن Dockerfiles خود به خصوص نام تصاویر استفاده کردیم؟ ما از همان تصاویر برای ایجاد کانتینرها استفاده می کنیم.

در پورت 8080 در کلاستر قابل دسترسی است. فرض می کنیم microservice1-image:1.0 به صورت محلی در دسترس است با imagePullPolicy: Never. اگر این در جای خود نباشد، سعی می کند تصویر را از داکر هاب 🐋 بیرون بکشد و شکست بخورد.

حال، بیایید مانیفست را برای میکروسرویس 2. یک فایل جدید با نام ایجاد کنید microservice2-deployment-service.yaml و مطالب زیر را اضافه کنید:

// 👇 k8s/manifests/microservice2-deployment-service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: microservice2
spec:
  selector:
    matchLabels:
      app: microservice2
  template:
    metadata:
      labels:
        app: microservice2
    spec:
      containers:
        - name: microservice2
          image: microservice2-image:1.0
          imagePullPolicy: Never
          resources:
            limits:
              memory: "200Mi"
              cpu: "500m"
          ports:
            - containerPort: 5001
---
apiVersion: v1
kind: Service
metadata:
  name: microservice2
  labels:
    app: microservice2
spec:
  type: NodePort
  selector:
    app: microservice2
  ports:
    - port: 8081
      targetPort: 5001
      nodePort: 30002

شبیه مانیفست برای است microservice1، تنها با چند تغییر.

این پیکربندی یک میکروسرویس به نام را مستقر می کند میکروسرویس 2 و آن را به صورت داخلی در پورت 5001 از طریق Deployment و به صورت خارجی در معرض دید قرار می دهد NodePort 30002 از طریق یک سرویس.

قابل دسترسی در پورت 8081 در داخل خوشه، با فرض microservice2-image:1.0 به صورت محلی در دسترس است با imagePullPolicy: Never.

وقتی همه این کارها انجام شد، مطمئن شوید که این تنظیمات را اعمال کرده اید و خوشه Kubernetes را با این سرویس ها راه اندازی کنید. دایرکتوری را به /manifests و دستورات زیر را اجرا کنید:

kubectl apply -f microservice1-deployment-service.yaml
kubectl apply -f microservice2-deployment-service.yaml

بررسی کنید که هر دو استقرار ما هستند در حال دویدن با اجرای دستور زیر:

kubectl get pods

Kubernetes Pods

در نهایت، برنامه ما آماده است و در Kubernetes با تنظیمات استقرار لازم مستقر شده است. 🎊

در حال نصب Odigos 🧑‍💻

💡 اودیگوها یک صفحه کنترل مشاهده پذیری منبع باز است که سازمان ها را قادر می سازد خط لوله مشاهده پذیری خود را ایجاد و حفظ کنند. به طور خلاصه، ما از Odigos برای ابزارسازی خودکار برنامه پایتون خود استفاده خواهیم کرد.

Odigos - ابزار نظارت

ℹ️ اگر روی مک در حال اجرا هستید، دستور زیر را برای نصب Odigos به صورت محلی اجرا کنید.

brew install keyval-dev/homebrew-odigos-cli/odigos

ℹ️ اگر از یک ماشین لینوکس استفاده می کنید، با اجرای دستورات زیر آن را از نسخه های GitHub نصب کنید. مطمئن شوید که فایل را با توجه به توزیع لینوکس خود تغییر دهید.

ℹ️ اگر باینری Odigos قابل اجرا نیست، این دستور را اجرا کنید chmod +x odigos تا قبل از اجرای دستور install آن را قابل اجرا کنید.

curl -LJO https://github.com/keyval-dev/odigos/releases/download/v1.0.15/cli_1.0.15_linux_amd64.tar.gz
tar -xvzf cli_1.0.15_linux_amd64.tar.gz
./odigos install

نصب Odigos

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

اکنون، Odigos آماده اجرا است 🚀. می‌توانیم رابط کاربری آن را اجرا کنیم، باطن ردیابی را پیکربندی کنیم و ردیابی‌ها را بر اساس آن ارسال کنیم.

اتصال Odigos به Backend Tracing ✨

💡 جیگر یک سیستم ردیابی توزیع شده سرتاسر منبع باز است.

Jaeger - پلت فرم ردیابی توزیع شده

راه اندازی Jaeger ✨

برای این آموزش استفاده خواهیم کرد جیگر 🕵️‍♂️، یک پلت فرم منبع باز محبوب برای مشاهده ردیابی های توزیع شده در یک برنامه میکروسرویس. ما از آن برای مشاهده ردیابی های تولید شده توسط Odigos استفاده خواهیم کرد.

برای دستورالعمل های نصب Jaeger، این را دنبال کنید پیوند. 👀

برای استقرار Jaeger در یک خوشه Kubernetes، دستورات زیر را اجرا کنید:

kubectl create ns tracing
kubectl apply -f https://raw.githubusercontent.com/keyval-dev/opentelemetry-go-instrumentation/master/docs/getting-started/jaeger.yaml -n tracing

در اینجا، ما در حال ایجاد یک tracing فضای نام و اعمال پیکربندی استقرار 📃 برای Jaeger در آن فضای نام.

این دستور نمونه Jaeger خود میزبان و سرویس آن را تنظیم می کند.

برای دریافت وضعیت پادهای در حال اجرا دستور زیر را اجرا کنید:

kubectl get pods -A -w

صبر کنید تا هر سه غلاف درست شود در حال دویدن قبل از ادامه بیشتر

Kubernetes Pods

اکنون، برای مشاهده رابط Jaeger به صورت محلی، باید به جلو منتقل کنیم. ترافیک را از پورت 16686 در ماشین محلی به پورت 16686 در غلاف انتخابی در خوشه Kubernetes هدایت کنید.

kubectl port-forward -n tracing svc/jaeger 16686:16686

این دستور یک تونل بین ماشین محلی و Jaeger pod ایجاد می کند و رابط کاربری Jaeger را نشان می دهد تا بتوانید با آن تعامل داشته باشید.

حمل و نقل بندر Jaeger

در حال حاضر، در http://localhost:16686، باید بتوانید نمونه Jaeger را در حال اجرا ببینید.

پیکربندی Odigos برای کار با Jaeger 🌟

ℹ️ برای کاربران لینوکس، به پوشه ای که باینری های Odigos را از نسخه های GitHub دانلود کرده اید بروید و دستور زیر را برای راه اندازی Odigos UI اجرا کنید.

./odigos ui

ℹ️ برای کاربران مک، فقط اجرا کنید:

odigos ui

بازدید کنید http://localhost:3000 و با رابط Odigos روبرو خواهید شد که در آن هر دو استقرار را در آن مشاهده خواهید کرد default فضای نام

رابط کاربری اولیه Odigos

هر دو مورد را انتخاب کنید و روی Next کلیک کنید. در صفحه بعد، Jaeger را به عنوان باطن انتخاب کنید و وقتی از شما خواسته شد جزئیات زیر را اضافه کنید:

  • نام مقصد: هر اسمی میخوای بذار، بگیم ردیابی پایتون.
  • نقطه پایان 🎯: اضافه کردن jaeger.tracing:4317 برای نقطه پایانی

و تمام – Odigos آماده است تا آثاری را به باطن Jaeger ما ارسال کند. به همین سادگی است.

راه اندازی ابزار Odigos برای ارسال ردیابی به Jaeger Tracing

مشاهده ردیابی توزیع شده 🧐

به محض اینکه Odigos را برای کار با Jaeger به عنوان باطن ردیابی خود راه اندازی کردیم، Odigos از قبل شروع به ارسال آثار برنامه ما به Jaeger کرده است.

بازدید کنید http://localhost:16686 و هر دو میکروسرویس ما را در منوی کشویی انتخاب کنید.

Jaeger UI برای انتخاب میکروسرویس ها

چند درخواست به نقاط پایانی ما ارائه دهید، و در نهایت، Jaeger شروع به پر شدن با ردیابی خواهد کرد.

روی هر یک از درخواست ها کلیک کنید و ردیابی ها را بررسی کنید.

Jaeger درخواست ردیابی

این همه بدون تغییر یک خط کد انجام شد. 🔥

عجب گیف

جمع بندی! ⚡

تا کنون، شما یاد گرفته اید که برنامه پایتون خود را با ردیابی توزیع شده، با استفاده از نظارت دقیق 👀 اودیگوها به عنوان میان افزار بین برنامه شما و باطن ردیابی جیگر.

کد منبع این آموزش در اینجا موجود است:

https://github.com/shricodev/blogs/tree/main/odgs-monitor-PY-like-a-pro

خیلی ممنون که خواندید! 🎉 🫡

نظرات خود را در بخش نظرات زیر بیاندازید. 👇

من را در شبکه های اجتماعی دنبال کنید 🐥

تصویر شریکودف

شریج آچاریا فالو کنید

Full Stack SDE • مشارکت کننده منبع باز • همکار @Oppia • ایمیل برای همکاری

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

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

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

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