برنامه نویسی

استقرار یک برنامه کاربردی در Amazon Elastic Kubernetes Service

Summarize this content to 400 words in Persian Lang
بنابراین یک روز صبح از خواب بیدار شدید و تصمیم گرفتید Kubernetes را یاد بگیرید. شما کمی جست‌وجو کردید و متوجه شدید که برای شروع به دانش نظری زیادی نیاز است، اما شما بیشتر اهل انجام کار هستید.

من در همان قایق تو هستم. و برخلاف سایر وبلاگ‌ها یا آموزش‌ها که در آن محصول نهایی را می‌بینید که به خوبی کار می‌کند، این وبلاگ‌ها برای مستندسازی سفر واقعی من در ساخت خدمات میکرو در EKS در نظر گرفته شده‌اند.

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

در مورد استفاده از AWS توجه داشته باشید

مطمئن شوید که MFA را در حساب خود فعال کرده اید و هشدارهای صورتحساب را در AWS تنظیم کنید. این یک ویدیوی یوتیوب خوب در مورد صورتحساب است.

یک خوشه Kubernetes ایجاد کنید

ما از eksctl برای مدیریت خوشه های EKS خود استفاده خواهیم کرد. این محبوب ترین رابط کاربری است که من پیدا کردم.

eksctl یک ابزار ساده CLI برای ایجاد و مدیریت خوشه ها در EKS – سرویس مدیریت Kubernetes آمازون برای EC2 است. این در Go نوشته شده است، از CloudFormation استفاده می کند، توسط Weaveworks ایجاد شده است و از مشارکت های جامعه استقبال می کند.

توجه داشته باشید که به دلیل eksctl از CloudFormation استفاده می کند، من به شدت توصیه می کنم از کنسول AWS برای اصلاح منابع استفاده نکنید. من قصد دارم از ChatGPT برای شناسایی دستورات مفید در حین انجام کارها استفاده کنم.

eksctl create cluster \
–name finansy \
–version 1.30 \
–nodes 1 \
–node-type t2.micro \
–region us-west-2

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

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

برای مقداردهی اولیه به 15 دقیقه نیاز است. توجه داشته باشید که t2.micro واجد شرایط لایه رایگان است. هدف من کاهش هزینه ها تا حد امکان است.

پیکربندی برای اتصال به EKS Cluster از ترمینال

اکنون که خوشه ایجاد شده است، می خواهیم از CLI به آن متصل شویم.

aws eks update-kubeconfig –region us-west-2 –name finansy

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

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

این ما را قادر می سازد تا از تعامل kubectl با صفحه کنترلی خوشه Kubernetes خود استفاده کنیم.

ممکن است از خود بپرسید که چرا در زمانی که داشتیم به CLI دیگری نیاز داریم eksctl در حال حاضر eksctl یک ابزار AWS برای مدیریت کلاستر EKS شما است، اما نمی توانید K8S را با استفاده از آن پیکربندی کنید. eksctl. ما نیاز داریم kubectl برای آن

توجه: دستورات برای دریافت جریان kubectl زمینه در صورتی که به صورت محلی به خوشه ها متصل هستید (متاسفم) و از راه دور (EX).

kubectl config current-context
kubectl config get-contexts
kubectl config use-context

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

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

یک سرویس جاوا ایجاد کنید

ما یک API مبتنی بر جاوا را در Spring Boot در EKS مستقر خواهیم کرد. در اینجا یک وبلاگ با جزئیات فرآیند است. مطمئن شوید که می توانید به یک API در پورت دسترسی داشته باشید 8080.

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

تولید یک JAR

و کپی کردن آن در دایرکتوری پروژه مربوط به زیرساخت

را اصلاح کنید build به خود تگ کنید pom.xml فایلی که از maven می خواهد که a را ایجاد کند jar فایل توجه داشته باشید که copy پیکربندی به قرار دادن کمک می کند jar در یک پوشه متفاوت برای مدیریت k8s infra، اما این کاملا اختیاری است.

org.springframework.boot
spring-boot-maven-plugin

repackage

org.apache.maven.plugins
maven-antrun-plugin
1.8

package

run

file=”${project.build.directory}/${project.artifactId}.jar”
tofile=”app/${project.artifactId}.jar”/>

${project.artifactId}

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

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

یک Dockerfile ایجاد کنید

نام فایل: Dockerfile

# Use an official OpenJDK 21 runtime as a parent image
FROM openjdk:21

# Set the working directory in the container
WORKDIR /app

# Copy the executable JAR file to the container
COPY app/portfolio-service.jar /app/portfolio-service.jar

CMD [“java”, “-jar”, “/app/portfolio-service.jar”]

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

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

توجه داشته باشید که ما به سادگی با استفاده از jar تولید شده توسط maven یک تصویر داکر تولید می کنیم. ممکن است بخواهید این کانتینر را اجرا کنید و مطمئن شوید که سرویس همانطور که انتظار می رود کار می کند.

docker build -t finansy/portfolio-service:1.1 .
docker run -d -p 8080:8080 –name portfolio-service finansy/portfolio-service:1.1

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

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

curl http://localhost:8080/ و اطمینان حاصل کنید که پاسخ مورد انتظار را دریافت می کنید.

تصویر را در آمازون ECR بارگذاری کنید

ثبت کانتینر الاستیک آمازون چیست؟

تصاویر کانتینر را بدون نصب یا تغییر زیرساخت به Amazon ECR فشار دهید و با استفاده از هر ابزار مدیریتی تصاویر را بکشید.

ما می خواهیم تصویر خود را به ECR فشار دهیم تا EKS بتواند به آن رجوع کند.

به کنسول آمازون ECR بروید
یک مخزن ایجاد کنید
روی دکمه View push commands در جزئیات مخزن کلیک کنید
دستورالعمل ها را برای احراز هویت Docker با رجیستری ECR دنبال کنید
تصویر داکر را فشار دهید
uri تصویر docker را کپی کنید و آن را به روز کنید image مسیر زیر در k8s.yaml.

مفاهیم Kubernetes به طور خلاصه

در اینجا مروری کوتاه بر مفاهیم Kubernetes است که برای بقیه پست مفید خواهد بود. این بخش از طریق ChatGPT ایجاد می شود 🙂

1. Kubernetes Pod

الف غلاف کوچکترین و ساده ترین شی کوبرنتس است. این یک نمونه واحد از یک فرآیند در حال اجرا در خوشه شما را نشان می دهد. یک Pod می‌تواند یک یا چند کانتینر (مثلاً کانتینرهای Docker) را که فضای نام شبکه، آدرس IP و حجم‌های ذخیره‌سازی یکسانی را به اشتراک می‌گذارند، کپسوله کند. کانتینرها در یک Pod معمولاً به طور محکم به هم متصل می شوند و نیاز به اشتراک منابع مانند ذخیره سازی یا شبکه دارند.

خصوصیات کلیدی:

آدرس IP واحد: هر Pod یک آدرس IP منحصر به فرد دارد.

فضای ذخیره سازی مشترک: ظروف در همان Pod حجم های ذخیره سازی را به اشتراک می گذارند.

چرخه زندگی: غلاف ها به گونه ای طراحی شده اند که زودگذر باشند. آنها را می توان بر اساس نیازهای برنامه به صورت پویا ایجاد و از بین برد.

2. استقرار Kubernetes

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

توابع کلیدی:

مقیاس بندی: به راحتی تعداد Pods را بالا یا پایین کنید.

به روز رسانی های چرخشی: برای به‌روزرسانی Pods بدون توقف، به‌روزرسانی‌های متحرک را انجام دهید.

بازگشت به عقب: در صورت عدم موفقیت به نسخه قبلی، به نسخه قبلی برگردید.

استفاده معمولی: از Deployments برای مدیریت برنامه های بدون حالت و اطمینان از حفظ وضعیت مطلوب برنامه استفاده می کنید.

3. سرویس Kubernetes

الف خدمات یک انتزاع است که مجموعه ای منطقی از Pods و خط مشی برای دسترسی به آنها را تعریف می کند. این یک نقطه پایانی پایدار (آدرس IP و نام DNS) برای Pods فراهم می کند که می تواند در طول زمان تغییر کند.

توابع کلیدی:

کشف خدمات: یک نام DNS پایدار برای مجموعه ای از Pods ارائه می دهد.

تعادل بار: ترافیک ورودی را بین پادهایی که بخشی از سرویس هستند توزیع می کند.

پورت فورواردینگ: یک پورت در سرویس را به یک پورت در Pods نگاشت می کند.

انواع:

ClusterIP: سرویس را در یک IP داخلی خوشه ای نمایش می دهد. فقط در داخل خوشه قابل دسترسی است.

NodePort: سرویس را در IP هر گره در یک پورت استاتیک نشان می دهد. اجازه دسترسی خارجی را می دهد.

LoadBalancer: ارائه شده توسط یک ارائه دهنده ابر برای افشای خارجی سرویس با استفاده از متعادل کننده بار مبتنی بر ابر.

سرویس بی سر: IP خوشه ای را اختصاص نمی دهد. برای برنامه های حالت دار مفید است.

4. Kubernetes Load Balancer

الف متعادل کننده بار خود یک منبع Kubernetes نیست، اما اغلب به همراه خدمات Kubernetes استفاده می شود. وقتی یک سرویس از نوع ایجاد می کنید LoadBalancer، Kubernetes یک متعادل کننده بار مبتنی بر ابر (اگر توسط ارائه دهنده ابر شما پشتیبانی می شود) برای مدیریت ترافیک خارجی ارائه می دهد.

توابع کلیدی:

دسترسی خارجی: یک نقطه دسترسی به خدمات را از خارج از خوشه Kubernetes فراهم می کند.

توزیع ترافیک: ترافیک ورودی را در چند پاد توزیع می کند تا بار را متعادل کند.

رابطه بین بار متعادل کننده و سرویس

متعادل کننده بار: منبعی است که توسط ارائه دهندگان ابر (به عنوان مثال، AWS ELB، GCP Load Balancer) ارائه می شود که ترافیک ورودی از خارج از خوشه را مدیریت می کند و آن را در نقاط پایانی مناسب توزیع می کند.

سرویس (نوع: LoadBalancer): وقتی یک سرویس Kubernetes از نوع ایجاد می کنید LoadBalancer، Kubernetes برای ایجاد و پیکربندی بار متعادل کننده با ارائه دهنده ابر تعامل دارد. سپس سرویس از این متعادل کننده بار برای هدایت ترافیک خارجی به پادهایی که بخشی از سرویس هستند استفاده می کند.

به طور خلاصه، در حالی که خدمات یک رابط داخلی پایدار ارائه می دهد و ممکن است ترافیک را در داخل خوشه مدیریت کند متعادل کننده بار (هنگامی که با a LoadBalancer نوع سرویس) یک رابط خارجی فراهم می کند و توزیع ترافیک را از خارج از خوشه به Pods مناسب مدیریت می کند.

پیکربندی K8S را ایجاد کنید

جدید ایجاد کنید k8s.yaml فایل

apiVersion: apps/v1
kind: Deployment
metadata:
name: portfolio-service-deployment
spec:
replicas: 3
selector:
matchLabels:
app: portfolio-service
template:
metadata:
labels:
app: portfolio-service
spec:
containers:
– name: portfolio-service
image: .dkr.ecr.us-west-2.amazonaws.com/finansy/portfolio-service:latest
ports:
– containerPort: 8080


apiVersion: v1
kind: Service
metadata:
name: portfolio-service
spec:
selector:
app: portfolio-service
ports:
– protocol: TCP
port: 80
targetPort: 8080
type: LoadBalancer

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

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

این زمان خوبی برای پیگیری انواع اجزای Deployment و LoadBalancer Kuberntes است.

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

➜ portfolio-service kubectl apply -f k8s.yaml
deployment.apps/portfolio-service-deployment created
service/portfolio-service created

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

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

دریافت نقطه پایانی خدمات

➜ portfolio-service kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.100.0.1 443/TCP 26m
portfolio-service LoadBalancer 10.100.177.55 a39b306d52a8b44fbbedcf670da443f6-1356185046.us-west-2.elb.amazonaws.com 80:31295/TCP 4m14s

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

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

وضعیت پاد را دریافت کنید

➜ portfolio-service kubectl get pods
NAME READY STATUS RESTARTS AGE
portfolio-service-deployment-6b6b4b6c4c-6dm8w 0/1 Pending 0 5m6s
portfolio-service-deployment-6b6b4b6c4c-jtpnq 0/1 Pending 0 5m6s
portfolio-service-deployment-6b6b4b6c4c-r9xps 0/1 Pending 0 5m6s

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

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

آنها باید در حالت Running باشند. بیایید به صفحه EKS خود در AWS نگاه کنیم.

چرا غلاف ها در وضعیت معلق هستند

به نظر می رسد که از حداکثر محدودیت IP در هر گره فراتر رفته ایم.

این اطلاعات جالب را در مورد Stack Overflow پیدا کردم.

The formula for defining the maximum number of Pods per EC2 Node instance is as follows:

N * (M-1) + 2

Where:

N is the number of Elastic Network Interfaces (ENI) of the instance type

M is the number of IP addresses per ENI

So for the instance you used which is t3.micro the number of pods that can be deployed are:

2 * (2-1) + 2 = 4 Pods, the 4 pods capacity is already used by pods in kube-system namespace

Here you can find the calculated max number of pods for each instance type
https://github.com/aws/amazon-vpc-cni-k8s/blob/master/misc/eni-max-pods.txt

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

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

شناسایی نوع نمونه مناسب برای مورد استفاده ما

ما احتمالاً می خواهیم بتوانیم 15-20 پاد را در هر نمونه اجرا کنیم.ما لیست بالا را به ChatGPT دادیم و در اینجا چیزی است که می گوید:

Given these options, c5.large and m5.large are suitable as they provide enough IPs to support 15-20 pods and are relatively affordable. Between these two, the c5.large instance is slightly cheaper.

Cheapest instance for 15-20 pods:

c5.large: 29 IPs, approximately $0.085 per hour.

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

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

ایجاد یک گروه گره جدید در خوشه

➜ portfolio-service eksctl create nodegroup \
–cluster finansy \
–name c5LargeNg \
–node-type c5.large \
–nodes 1 \
–nodes-min 1 \
–nodes-max 1

2024-09-02 12:02:22 [ℹ] will use version 1.30 for new nodegroup(s) based on control plane version
2024-09-02 12:02:24 [ℹ] nodegroup “c5LargeNg” will use “” [AmazonLinux2/1.30] 2024-09-02 12:02:24 [ℹ] 2 existing nodegroup(s) (new-node-group,ng-9e92b41d) will be excluded
2024-09-02 12:02:24 [ℹ] 1 nodegroup (c5LargeNg) was included (based on the include/exclude rules)
2024-09-02 12:02:24 [ℹ] will create a CloudFormation stack for each of 1 managed nodegroups in cluster “finansy”
2024-09-02 12:02:24 [ℹ] 2 sequential tasks: { fix cluster compatibility, 1 task: { 1 task: { create managed nodegroup “c5LargeNg” } }
}
2024-09-02 12:02:24 [ℹ] checking cluster stack for missing resources
2024-09-02 12:02:25 [ℹ] cluster stack has all required resources
2024-09-02 12:02:25 [ℹ] building managed nodegroup stack “eksctl-finansy-nodegroup-c5LargeNg”
2024-09-02 12:02:25 [ℹ] deploying stack “eksctl-finansy-nodegroup-c5LargeNg”
2024-09-02 12:02:25 [ℹ] waiting for CloudFormation stack “eksctl-finansy-nodegroup-c5LargeNg”
2024-09-02 12:02:55 [ℹ] waiting for CloudFormation stack “eksctl-finansy-nodegroup-c5LargeNg”
2024-09-02 12:03:52 [ℹ] waiting for CloudFormation stack “eksctl-finansy-nodegroup-c5LargeNg”
2024-09-02 12:05:17 [ℹ] waiting for CloudFormation stack “eksctl-finansy-nodegroup-c5LargeNg”
2024-09-02 12:05:17 [ℹ] no tasks
2024-09-02 12:05:17 [✔] created 0 nodegroup(s) in cluster “finansy”
2024-09-02 12:05:18 [ℹ] nodegroup “c5LargeNg” has 1 node(s)
2024-09-02 12:05:18 [ℹ] node “ip-192-168-3-155.us-west-2.compute.internal” is ready
2024-09-02 12:05:18 [ℹ] waiting for at least 1 node(s) to become ready in “c5LargeNg”
2024-09-02 12:05:18 [ℹ] nodegroup “c5LargeNg” has 1 node(s)
2024-09-02 12:05:18 [ℹ] node “ip-192-168-3-155.us-west-2.compute.internal” is ready
2024-09-02 12:05:18 [✔] created 1 managed nodegroup(s) in cluster “finansy”
2024-09-02 12:05:18 [ℹ] checking security group configuration for all nodegroups
2024-09-02 12:05:18 [ℹ] all nodegroups have up-to-date cloudformation templates

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

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

گروه گره قدیمی را حذف کنید

➜ ~ eksctl delete nodegroup –cluster finansy –name ng-9e92b41d
2024-09-02 12:06:03 [ℹ] 1 nodegroup (ng-9e92b41d) was included (based on the include/exclude rules)
2024-09-02 12:06:03 [ℹ] will drain 1 nodegroup(s) in cluster “finansy”
2024-09-02 12:06:03 [ℹ] starting parallel draining, max in-flight of 1
2024-09-02 12:06:03 [ℹ] cordon node “ip-192-168-88-252.us-west-2.compute.internal”
2024-09-02 12:06:30 [✔] drained all nodes: [ip-192-168-88-252.us-west-2.compute.internal] 2024-09-02 12:06:30 [✖] failed to acquire semaphore while waiting for all routines to finish: context canceled
2024-09-02 12:06:30 [ℹ] will delete 1 nodegroups from cluster “finansy”
2024-09-02 12:06:30 [ℹ] 1 task: { 1 task: { delete nodegroup “ng-9e92b41d” [async] } }
2024-09-02 12:06:31 [ℹ] will delete stack “eksctl-finansy-nodegroup-ng-9e92b41d”
2024-09-02 12:06:31 [✔] deleted 1 nodegroup(s) from cluster “finansy”

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

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

گزارش های Pod را بررسی کنید

➜ ~ kubectl logs portfolio-service-deployment-6b6b4b6c4c-cslnw

. ____ _ __ _ _
/\\ / ___’_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | ‘_ | ‘_| | ‘_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
‘ |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/

:: Spring Boot :: (v3.3.2)

2024-09-02T19:08:16.805Z INFO 1 — [Finansy Portfolio Service] [ main] f.p.s.FinansyPortfolioServiceApplication : Starting FinansyPortfolioServiceApplication using Java 21 with PID 1 (/app/portfolio-service.jar started by root in /app)
2024-09-02T19:08:16.828Z INFO 1 — [Finansy Portfolio Service] [ main] f.p.s.FinansyPortfolioServiceApplication : No active profile set, falling back to 1 default profile: “default”
2024-09-02T19:08:20.090Z INFO 1 — [Finansy Portfolio Service] [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data R2DBC repositories in DEFAULT mode.
2024-09-02T19:08:20.940Z INFO 1 — [Finansy Portfolio Service] [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 828 ms. Found 1 R2DBC repository interface.
2024-09-02T19:08:24.691Z DEBUG 1 — [Finansy Portfolio Service] [ main] s.w.r.r.m.a.RequestMappingHandlerMapping : 5 mappings in ‘requestMappingHandlerMapping’
2024-09-02T19:08:24.728Z DEBUG 1 — [Finansy Portfolio Service] [ main] o.s.w.r.handler.SimpleUrlHandlerMapping : Patterns [/webjars/**, /**] in ‘resourceHandlerMapping’
2024-09-02T19:08:24.824Z DEBUG 1 — [Finansy Portfolio Service] [ main] o.s.w.r.r.m.a.ControllerMethodResolver : ControllerAdvice beans: 0 @ModelAttribute, 0 @InitBinder, 1 @ExceptionHandler
2024-09-02T19:08:24.907Z DEBUG 1 — [Finansy Portfolio Service] [ main] o.s.w.s.adapter.HttpWebHandlerAdapter : enableLoggingRequestDetails=”false”: form data and headers will be masked to prevent unsafe logging of potentially sensitive data
2024-09-02T19:08:26.568Z INFO 1 — [Finansy Portfolio Service] [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port 8080 (http)
2024-09-02T19:08:26.615Z INFO 1 — [Finansy Portfolio Service] [ main] f.p.s.FinansyPortfolioServiceApplication : Started FinansyPortfolioServiceApplication in 11.949 seconds (process running for 13.818)

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

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

دوباره نقطه پایان سرویس را دریافت کنید

➜ ~ kubectl get svc

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.100.0.1 443/TCP 88m
portfolio-service LoadBalancer 10.100.177.55 a39b306d52a8b44fbbedcf670da443f6-1356185046.us-west-2.elb.amazonaws.com 80:31295/TCP 66m

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

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

نقطه پایانی را پرس و جو کنید

➜ ~ curl http://a39b306d52a8b44fbbedcf670da443f6-1356185046.us-west-2.elb.amazonaws.com/api/v1/user-assets
[]%

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

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

سرور راه اندازی شده است!

خوشه را حذف کنید

تا از تحمیل هرگونه هزینه اضافی جلوگیری شود.

eksctl delete cluster –name finansy

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

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

بنابراین یک روز صبح از خواب بیدار شدید و تصمیم گرفتید Kubernetes را یاد بگیرید. شما کمی جست‌وجو کردید و متوجه شدید که برای شروع به دانش نظری زیادی نیاز است، اما شما بیشتر اهل انجام کار هستید.

من در همان قایق تو هستم. و برخلاف سایر وبلاگ‌ها یا آموزش‌ها که در آن محصول نهایی را می‌بینید که به خوبی کار می‌کند، این وبلاگ‌ها برای مستندسازی سفر واقعی من در ساخت خدمات میکرو در EKS در نظر گرفته شده‌اند.

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

در مورد استفاده از AWS توجه داشته باشید

مطمئن شوید که MFA را در حساب خود فعال کرده اید و هشدارهای صورتحساب را در AWS تنظیم کنید. این یک ویدیوی یوتیوب خوب در مورد صورتحساب است.

یک خوشه Kubernetes ایجاد کنید

ما از eksctl برای مدیریت خوشه های EKS خود استفاده خواهیم کرد. این محبوب ترین رابط کاربری است که من پیدا کردم.

eksctl یک ابزار ساده CLI برای ایجاد و مدیریت خوشه ها در EKS – سرویس مدیریت Kubernetes آمازون برای EC2 است. این در Go نوشته شده است، از CloudFormation استفاده می کند، توسط Weaveworks ایجاد شده است و از مشارکت های جامعه استقبال می کند.

توجه داشته باشید که به دلیل eksctl از CloudFormation استفاده می کند، من به شدت توصیه می کنم از کنسول AWS برای اصلاح منابع استفاده نکنید. من قصد دارم از ChatGPT برای شناسایی دستورات مفید در حین انجام کارها استفاده کنم.

eksctl create cluster \
  --name finansy \
  --version 1.30 \
  --nodes 1 \
  --node-type t2.micro \
  --region us-west-2
وارد حالت تمام صفحه شوید

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

برای مقداردهی اولیه به 15 دقیقه نیاز است. توجه داشته باشید که t2.micro واجد شرایط لایه رایگان است. هدف من کاهش هزینه ها تا حد امکان است.

پیکربندی برای اتصال به EKS Cluster از ترمینال

اکنون که خوشه ایجاد شده است، می خواهیم از CLI به آن متصل شویم.

aws eks update-kubeconfig --region us-west-2 --name finansy
وارد حالت تمام صفحه شوید

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

این ما را قادر می سازد تا از تعامل kubectl با صفحه کنترلی خوشه Kubernetes خود استفاده کنیم.

ممکن است از خود بپرسید که چرا در زمانی که داشتیم به CLI دیگری نیاز داریم eksctl در حال حاضر eksctl یک ابزار AWS برای مدیریت کلاستر EKS شما است، اما نمی توانید K8S را با استفاده از آن پیکربندی کنید. eksctl. ما نیاز داریم kubectl برای آن

توجه: دستورات برای دریافت جریان kubectl زمینه در صورتی که به صورت محلی به خوشه ها متصل هستید (متاسفم) و از راه دور (EX).

kubectl config current-context
kubectl config get-contexts
kubectl config use-context 
وارد حالت تمام صفحه شوید

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

یک سرویس جاوا ایجاد کنید

ما یک API مبتنی بر جاوا را در Spring Boot در EKS مستقر خواهیم کرد. در اینجا یک وبلاگ با جزئیات فرآیند است. مطمئن شوید که می توانید به یک API در پورت دسترسی داشته باشید 8080.

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

تولید یک JAR

و کپی کردن آن در دایرکتوری پروژه مربوط به زیرساخت

را اصلاح کنید build به خود تگ کنید pom.xml فایلی که از maven می خواهد که a را ایجاد کند jar فایل توجه داشته باشید که copy پیکربندی به قرار دادن کمک می کند jar در یک پوشه متفاوت برای مدیریت k8s infra، اما این کاملا اختیاری است.

  
    
      
        org.springframework.boot
        spring-boot-maven-plugin
         
            
              
                  repackage
              
            
          
      
      
        org.apache.maven.plugins
        maven-antrun-plugin
        1.8
        
            
                package
                
                    run
                
                
                    
                         file="${project.build.directory}/${project.artifactId}.jar"
                              tofile="app/${project.artifactId}.jar"/>
                    
                
            
        
      
    

    ${project.artifactId}
  
وارد حالت تمام صفحه شوید

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

یک Dockerfile ایجاد کنید

نام فایل: Dockerfile

# Use an official OpenJDK 21 runtime as a parent image
FROM openjdk:21

# Set the working directory in the container
WORKDIR /app

# Copy the executable JAR file to the container
COPY app/portfolio-service.jar /app/portfolio-service.jar

CMD ["java", "-jar", "/app/portfolio-service.jar"]
وارد حالت تمام صفحه شوید

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

توجه داشته باشید که ما به سادگی با استفاده از jar تولید شده توسط maven یک تصویر داکر تولید می کنیم. ممکن است بخواهید این کانتینر را اجرا کنید و مطمئن شوید که سرویس همانطور که انتظار می رود کار می کند.

docker build -t finansy/portfolio-service:1.1 .
docker run -d -p 8080:8080 --name portfolio-service finansy/portfolio-service:1.1
وارد حالت تمام صفحه شوید

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

curl http://localhost:8080/ و اطمینان حاصل کنید که پاسخ مورد انتظار را دریافت می کنید.

تصویر را در آمازون ECR بارگذاری کنید

ثبت کانتینر الاستیک آمازون چیست؟

تصاویر کانتینر را بدون نصب یا تغییر زیرساخت به Amazon ECR فشار دهید و با استفاده از هر ابزار مدیریتی تصاویر را بکشید.

ما می خواهیم تصویر خود را به ECR فشار دهیم تا EKS بتواند به آن رجوع کند.

  • به کنسول آمازون ECR بروید
  • یک مخزن ایجاد کنید
  • روی دکمه View push commands در جزئیات مخزن کلیک کنید
  • دستورالعمل ها را برای احراز هویت Docker با رجیستری ECR دنبال کنید
  • تصویر داکر را فشار دهید
  • uri تصویر docker را کپی کنید و آن را به روز کنید image مسیر زیر در k8s.yaml.

مفاهیم Kubernetes به طور خلاصه

در اینجا مروری کوتاه بر مفاهیم Kubernetes است که برای بقیه پست مفید خواهد بود. این بخش از طریق ChatGPT ایجاد می شود 🙂

1. Kubernetes Pod

الف غلاف کوچکترین و ساده ترین شی کوبرنتس است. این یک نمونه واحد از یک فرآیند در حال اجرا در خوشه شما را نشان می دهد. یک Pod می‌تواند یک یا چند کانتینر (مثلاً کانتینرهای Docker) را که فضای نام شبکه، آدرس IP و حجم‌های ذخیره‌سازی یکسانی را به اشتراک می‌گذارند، کپسوله کند. کانتینرها در یک Pod معمولاً به طور محکم به هم متصل می شوند و نیاز به اشتراک منابع مانند ذخیره سازی یا شبکه دارند.

خصوصیات کلیدی:

  • آدرس IP واحد: هر Pod یک آدرس IP منحصر به فرد دارد.
  • فضای ذخیره سازی مشترک: ظروف در همان Pod حجم های ذخیره سازی را به اشتراک می گذارند.
  • چرخه زندگی: غلاف ها به گونه ای طراحی شده اند که زودگذر باشند. آنها را می توان بر اساس نیازهای برنامه به صورت پویا ایجاد و از بین برد.

2. استقرار Kubernetes

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

توابع کلیدی:

  • مقیاس بندی: به راحتی تعداد Pods را بالا یا پایین کنید.
  • به روز رسانی های چرخشی: برای به‌روزرسانی Pods بدون توقف، به‌روزرسانی‌های متحرک را انجام دهید.
  • بازگشت به عقب: در صورت عدم موفقیت به نسخه قبلی، به نسخه قبلی برگردید.

استفاده معمولی: از Deployments برای مدیریت برنامه های بدون حالت و اطمینان از حفظ وضعیت مطلوب برنامه استفاده می کنید.

3. سرویس Kubernetes

الف خدمات یک انتزاع است که مجموعه ای منطقی از Pods و خط مشی برای دسترسی به آنها را تعریف می کند. این یک نقطه پایانی پایدار (آدرس IP و نام DNS) برای Pods فراهم می کند که می تواند در طول زمان تغییر کند.

توابع کلیدی:

  • کشف خدمات: یک نام DNS پایدار برای مجموعه ای از Pods ارائه می دهد.
  • تعادل بار: ترافیک ورودی را بین پادهایی که بخشی از سرویس هستند توزیع می کند.
  • پورت فورواردینگ: یک پورت در سرویس را به یک پورت در Pods نگاشت می کند.

انواع:

  • ClusterIP: سرویس را در یک IP داخلی خوشه ای نمایش می دهد. فقط در داخل خوشه قابل دسترسی است.
  • NodePort: سرویس را در IP هر گره در یک پورت استاتیک نشان می دهد. اجازه دسترسی خارجی را می دهد.
  • LoadBalancer: ارائه شده توسط یک ارائه دهنده ابر برای افشای خارجی سرویس با استفاده از متعادل کننده بار مبتنی بر ابر.
  • سرویس بی سر: IP خوشه ای را اختصاص نمی دهد. برای برنامه های حالت دار مفید است.

4. Kubernetes Load Balancer

الف متعادل کننده بار خود یک منبع Kubernetes نیست، اما اغلب به همراه خدمات Kubernetes استفاده می شود. وقتی یک سرویس از نوع ایجاد می کنید LoadBalancer، Kubernetes یک متعادل کننده بار مبتنی بر ابر (اگر توسط ارائه دهنده ابر شما پشتیبانی می شود) برای مدیریت ترافیک خارجی ارائه می دهد.

توابع کلیدی:

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

رابطه بین بار متعادل کننده و سرویس

  • متعادل کننده بار: منبعی است که توسط ارائه دهندگان ابر (به عنوان مثال، AWS ELB، GCP Load Balancer) ارائه می شود که ترافیک ورودی از خارج از خوشه را مدیریت می کند و آن را در نقاط پایانی مناسب توزیع می کند.
  • سرویس (نوع: LoadBalancer): وقتی یک سرویس Kubernetes از نوع ایجاد می کنید LoadBalancer، Kubernetes برای ایجاد و پیکربندی بار متعادل کننده با ارائه دهنده ابر تعامل دارد. سپس سرویس از این متعادل کننده بار برای هدایت ترافیک خارجی به پادهایی که بخشی از سرویس هستند استفاده می کند.

به طور خلاصه، در حالی که خدمات یک رابط داخلی پایدار ارائه می دهد و ممکن است ترافیک را در داخل خوشه مدیریت کند متعادل کننده بار (هنگامی که با a LoadBalancer نوع سرویس) یک رابط خارجی فراهم می کند و توزیع ترافیک را از خارج از خوشه به Pods مناسب مدیریت می کند.

پیکربندی K8S را ایجاد کنید

جدید ایجاد کنید k8s.yaml فایل

apiVersion: apps/v1
kind: Deployment
metadata:
  name: portfolio-service-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: portfolio-service
  template:
    metadata:
      labels:
        app: portfolio-service
    spec:
      containers:
        - name: portfolio-service
          image: .dkr.ecr.us-west-2.amazonaws.com/finansy/portfolio-service:latest
          ports:
            - containerPort: 8080

---
apiVersion: v1
kind: Service
metadata:
  name: portfolio-service
spec:
  selector:
    app: portfolio-service
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: LoadBalancer
وارد حالت تمام صفحه شوید

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

این زمان خوبی برای پیگیری انواع اجزای Deployment و LoadBalancer Kuberntes است.

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

➜  portfolio-service kubectl apply -f k8s.yaml 
deployment.apps/portfolio-service-deployment created
service/portfolio-service created
وارد حالت تمام صفحه شوید

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

دریافت نقطه پایانی خدمات

➜  portfolio-service kubectl get svc
NAME                TYPE           CLUSTER-IP      EXTERNAL-IP                                                               PORT(S)        AGE
kubernetes          ClusterIP      10.100.0.1                                                                          443/TCP        26m
portfolio-service   LoadBalancer   10.100.177.55   a39b306d52a8b44fbbedcf670da443f6-1356185046.us-west-2.elb.amazonaws.com   80:31295/TCP   4m14s

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

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

وضعیت پاد را دریافت کنید

➜  portfolio-service kubectl get pods
NAME                                            READY   STATUS    RESTARTS   AGE
portfolio-service-deployment-6b6b4b6c4c-6dm8w   0/1     Pending   0          5m6s
portfolio-service-deployment-6b6b4b6c4c-jtpnq   0/1     Pending   0          5m6s
portfolio-service-deployment-6b6b4b6c4c-r9xps   0/1     Pending   0          5m6s
وارد حالت تمام صفحه شوید

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

آنها باید در حالت Running باشند. بیایید به صفحه EKS خود در AWS نگاه کنیم.

چرا غلاف ها در وضعیت معلق هستند

به نظر می رسد که از حداکثر محدودیت IP در هر گره فراتر رفته ایم.

این اطلاعات جالب را در مورد Stack Overflow پیدا کردم.

The formula for defining the maximum number of Pods per EC2 Node instance is as follows:

N * (M-1) + 2

Where:

N is the number of Elastic Network Interfaces (ENI) of the instance type

M is the number of IP addresses per ENI

So for the instance you used which is t3.micro the number of pods that can be deployed are:

2 * (2-1) + 2 = 4 Pods, the 4 pods capacity is already used by pods in kube-system namespace

Here you can find the calculated max number of pods for each instance type
https://github.com/aws/amazon-vpc-cni-k8s/blob/master/misc/eni-max-pods.txt
وارد حالت تمام صفحه شوید

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

شناسایی نوع نمونه مناسب برای مورد استفاده ما

ما احتمالاً می خواهیم بتوانیم 15-20 پاد را در هر نمونه اجرا کنیم.
ما لیست بالا را به ChatGPT دادیم و در اینجا چیزی است که می گوید:

Given these options, c5.large and m5.large are suitable as they provide enough IPs to support 15-20 pods and are relatively affordable. Between these two, the c5.large instance is slightly cheaper.

Cheapest instance for 15-20 pods:

c5.large: 29 IPs, approximately $0.085 per hour.
وارد حالت تمام صفحه شوید

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

ایجاد یک گروه گره جدید در خوشه

➜  portfolio-service eksctl create nodegroup \
  --cluster finansy \
  --name c5LargeNg \
  --node-type c5.large \
  --nodes 1 \
  --nodes-min 1 \
  --nodes-max 1


2024-09-02 12:02:22 [ℹ]  will use version 1.30 for new nodegroup(s) based on control plane version
2024-09-02 12:02:24 [ℹ]  nodegroup "c5LargeNg" will use "" [AmazonLinux2/1.30]
2024-09-02 12:02:24 [ℹ]  2 existing nodegroup(s) (new-node-group,ng-9e92b41d) will be excluded
2024-09-02 12:02:24 [ℹ]  1 nodegroup (c5LargeNg) was included (based on the include/exclude rules)
2024-09-02 12:02:24 [ℹ]  will create a CloudFormation stack for each of 1 managed nodegroups in cluster "finansy"
2024-09-02 12:02:24 [ℹ]
2 sequential tasks: { fix cluster compatibility, 1 task: { 1 task: { create managed nodegroup "c5LargeNg" } }
}
2024-09-02 12:02:24 [ℹ]  checking cluster stack for missing resources
2024-09-02 12:02:25 [ℹ]  cluster stack has all required resources
2024-09-02 12:02:25 [ℹ]  building managed nodegroup stack "eksctl-finansy-nodegroup-c5LargeNg"
2024-09-02 12:02:25 [ℹ]  deploying stack "eksctl-finansy-nodegroup-c5LargeNg"
2024-09-02 12:02:25 [ℹ]  waiting for CloudFormation stack "eksctl-finansy-nodegroup-c5LargeNg"
2024-09-02 12:02:55 [ℹ]  waiting for CloudFormation stack "eksctl-finansy-nodegroup-c5LargeNg"
2024-09-02 12:03:52 [ℹ]  waiting for CloudFormation stack "eksctl-finansy-nodegroup-c5LargeNg"
2024-09-02 12:05:17 [ℹ]  waiting for CloudFormation stack "eksctl-finansy-nodegroup-c5LargeNg"
2024-09-02 12:05:17 [ℹ]  no tasks
2024-09-02 12:05:17 [✔]  created 0 nodegroup(s) in cluster "finansy"
2024-09-02 12:05:18 [ℹ]  nodegroup "c5LargeNg" has 1 node(s)
2024-09-02 12:05:18 [ℹ]  node "ip-192-168-3-155.us-west-2.compute.internal" is ready
2024-09-02 12:05:18 [ℹ]  waiting for at least 1 node(s) to become ready in "c5LargeNg"
2024-09-02 12:05:18 [ℹ]  nodegroup "c5LargeNg" has 1 node(s)
2024-09-02 12:05:18 [ℹ]  node "ip-192-168-3-155.us-west-2.compute.internal" is ready
2024-09-02 12:05:18 [✔]  created 1 managed nodegroup(s) in cluster "finansy"
2024-09-02 12:05:18 [ℹ]  checking security group configuration for all nodegroups
2024-09-02 12:05:18 [ℹ]  all nodegroups have up-to-date cloudformation templates
وارد حالت تمام صفحه شوید

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

گروه گره قدیمی را حذف کنید

➜  ~ eksctl delete nodegroup --cluster finansy --name ng-9e92b41d
2024-09-02 12:06:03 [ℹ]  1 nodegroup (ng-9e92b41d) was included (based on the include/exclude rules)
2024-09-02 12:06:03 [ℹ]  will drain 1 nodegroup(s) in cluster "finansy"
2024-09-02 12:06:03 [ℹ]  starting parallel draining, max in-flight of 1
2024-09-02 12:06:03 [ℹ]  cordon node "ip-192-168-88-252.us-west-2.compute.internal"
2024-09-02 12:06:30 [✔]  drained all nodes: [ip-192-168-88-252.us-west-2.compute.internal]
2024-09-02 12:06:30 [✖]  failed to acquire semaphore while waiting for all routines to finish: context canceled
2024-09-02 12:06:30 [ℹ]  will delete 1 nodegroups from cluster "finansy"
2024-09-02 12:06:30 [ℹ]  1 task: { 1 task: { delete nodegroup "ng-9e92b41d" [async] } }
2024-09-02 12:06:31 [ℹ]  will delete stack "eksctl-finansy-nodegroup-ng-9e92b41d"
2024-09-02 12:06:31 [✔]  deleted 1 nodegroup(s) from cluster "finansy"
وارد حالت تمام صفحه شوید

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

گزارش های Pod را بررسی کنید

➜  ~ kubectl logs portfolio-service-deployment-6b6b4b6c4c-cslnw

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.3.2)

2024-09-02T19:08:16.805Z  INFO 1 --- [Finansy Portfolio Service] [           main] f.p.s.FinansyPortfolioServiceApplication : Starting FinansyPortfolioServiceApplication using Java 21 with PID 1 (/app/portfolio-service.jar started by root in /app)
2024-09-02T19:08:16.828Z  INFO 1 --- [Finansy Portfolio Service] [           main] f.p.s.FinansyPortfolioServiceApplication : No active profile set, falling back to 1 default profile: "default"
2024-09-02T19:08:20.090Z  INFO 1 --- [Finansy Portfolio Service] [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data R2DBC repositories in DEFAULT mode.
2024-09-02T19:08:20.940Z  INFO 1 --- [Finansy Portfolio Service] [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 828 ms. Found 1 R2DBC repository interface.
2024-09-02T19:08:24.691Z DEBUG 1 --- [Finansy Portfolio Service] [           main] s.w.r.r.m.a.RequestMappingHandlerMapping : 5 mappings in 'requestMappingHandlerMapping'
2024-09-02T19:08:24.728Z DEBUG 1 --- [Finansy Portfolio Service] [           main] o.s.w.r.handler.SimpleUrlHandlerMapping  : Patterns [/webjars/**, /**] in 'resourceHandlerMapping'
2024-09-02T19:08:24.824Z DEBUG 1 --- [Finansy Portfolio Service] [           main] o.s.w.r.r.m.a.ControllerMethodResolver   : ControllerAdvice beans: 0 @ModelAttribute, 0 @InitBinder, 1 @ExceptionHandler
2024-09-02T19:08:24.907Z DEBUG 1 --- [Finansy Portfolio Service] [           main] o.s.w.s.adapter.HttpWebHandlerAdapter    : enableLoggingRequestDetails="false": form data and headers will be masked to prevent unsafe logging of potentially sensitive data
2024-09-02T19:08:26.568Z  INFO 1 --- [Finansy Portfolio Service] [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port 8080 (http)
2024-09-02T19:08:26.615Z  INFO 1 --- [Finansy Portfolio Service] [           main] f.p.s.FinansyPortfolioServiceApplication : Started FinansyPortfolioServiceApplication in 11.949 seconds (process running for 13.818)
وارد حالت تمام صفحه شوید

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

دوباره نقطه پایان سرویس را دریافت کنید

➜  ~ kubectl get svc

NAME                TYPE           CLUSTER-IP      EXTERNAL-IP                                                               PORT(S)        AGE
kubernetes          ClusterIP      10.100.0.1                                                                          443/TCP        88m
portfolio-service   LoadBalancer   10.100.177.55   a39b306d52a8b44fbbedcf670da443f6-1356185046.us-west-2.elb.amazonaws.com   80:31295/TCP   66m
وارد حالت تمام صفحه شوید

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

نقطه پایانی را پرس و جو کنید

➜  ~  curl http://a39b306d52a8b44fbbedcf670da443f6-1356185046.us-west-2.elb.amazonaws.com/api/v1/user-assets
[]%
وارد حالت تمام صفحه شوید

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

سرور راه اندازی شده است!

خوشه را حذف کنید

تا از تحمیل هرگونه هزینه اضافی جلوگیری شود.

eksctl delete cluster --name finansy
وارد حالت تمام صفحه شوید

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

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

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

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

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