برنامه نویسی

یک معماری بر روی AWS بسازید که خود را تخریب کند

آیا می توانید تصور کنید که چقدر باورنکردنی است که بتوانید برنامه ای بسازید که به محض توقف استفاده از آن، بتواند خود را نابود کند؟! 🤯

صحنه ای عالی از The Mandalorian

اگر ترجیح می دهید این مقاله را به زبان انگلیسی بخوانید، اینجا را کلیک کنید!


در این مقاله قصد دارم موارد استفاده، نمودار معماری و توضیح هر سرویسی که در این زیرساخت AWS استفاده می شود را به اشتراک بگذارم. نکته مهم در مورد این راه حل این است که می توانید هر سرویس دیگری را که نیاز دارید ادغام کنید!

انگیزه

اغلب اتفاق می افتد که توسعه دهندگان منابع زیادی را برای آزمایش برنامه های خود جمع آوری می کنند و سپس فراموش می کنند آنها را حذف کنند و باعث هزینه های غیر ضروری می شود.

در حال کار بر روی یک ابتکار داخلی با یکی از همکاران بزرگم، از من خواسته شد که راه حلی خلاقانه برای این نوع مشکلات پیدا کنم. در آن زمان بود که شریک من روی ایجاد یک پیکربندی خودکار برنامه در یک نمونه EC2 تمرکز کرد، در حالی که من مسئول ساختن زیرساختی بودم که می‌توانست به طور خودکار حذف شود.

در چه نوع سناریوهایی به این معماری نیاز دارم؟

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

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

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

چگونه کار می کند؟

این معماری با AWS CloudFormation ساخته شده است، یک سرویس تامین کننده که از زیرساخت به عنوان کد استفاده می کند. مزیت این ابزار این است که تمام منابع و وابستگی ها در آن تعریف شده اند قالب ها و در آن آشکار شود باتری ها، که پاک کردن همه چیز را به عنوان یک درایو آسان می کند.

نمودار معماری

بیایید روی آن تمرکز کنیم اجزای اصلی معماری: نمونه EC2، هشدار CloudWatch، قانون EventBridge، تابع Lambda و نقش IAM مربوطه آن، خط مشی و مجوز. منابع بی اهمیت دیگری مانند یک گروه امنیتی، نقش نمونه و نمایه نمونه مورد نیاز هستند. اینها را حذف خواهیم کرد.

این به صف شدن از CloudFormation معماری زیر را ایجاد می کند:

معماری خود ویرانگر

این معماری در عمل است:

پس از استفاده نشدن از برنامه، معماری خود ویرانگر


حالا بله، ما به طور کامل وارد هر یک از این عناصر می شویم! 🤓

نمونه وب سرور

اول از همه، ما به یک برنامه نیاز داریم. این در یک نمونه EC2 مستقر می شود و می توانید آن را هر طور که می خواهید پیکربندی کنید. در این مورد، من آن را در داخل بخش پیکربندی کردم UserData.

این تعریف منبع است:

"WebServerInstance": {
      "Type" : "AWS::EC2::Instance",
      "Properties": {
        "ImageId"            : "ami-0ab4d1e9cf9a1215a",
        "InstanceType"       : "t3.small",
        "KeyName"            : "PAR_DE_LLAVES",
        "IamInstanceProfile" : "PERFIL_DE_INSTANCIA",
        "BlockDeviceMappings" : [
          {
            "DeviceName" : "/dev/xvda",
            "Ebs" : {
              "VolumeType"           : "gp2",
              "VolumeSize"           : "25",
              "Encrypted"            : "true",
              "KmsKeyId"             : "LLAVE_KMS",
              "DeleteOnTermination"  : "true"
            }
          }],

        "NetworkInterfaces" : [{
            "AssociatePublicIpAddress"  : "true",
            "DeleteOnTermination"       : "true",
            "SubnetId"                  : "ID_DE_SUBRED",
            "GroupSet"                  :  ["GRUPO_DE_SEGURIDAD"],
            "DeviceIndex"               : 0
          }],

         "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
            "#!/bin/bash\n",
            "CONFIGURACION_DE_APLICACION"
            ]]}}
      }
    }
وارد حالت تمام صفحه شوید

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

زنگ بیکار

بر اساس متریک استفاده از CPU، می توانیم بدانیم که آیا برنامه هنوز در حال استفاده است یا خیر.

زنگ هشدار برای موارد زیر برنامه ریزی شده است: هنگامی که حداکثر استفاده از CPU به مدت 1 ساعت به زیر 12٪ کاهش می یابد، آلارم نمونه را متوقف می کند.

✏️استفاده از: محدودیت تعیین شده برای استفاده از CPU باید با توجه به درخواست شما تعریف شود. در مورد من، برنامه یک داشبورد Splunk بود، بنابراین آن محدودیت مناسب ترین بود.

این تعریف زنگ هشدار است:

"MyEC2Alarm": {
        "Type": "AWS::CloudWatch::Alarm",
        "Properties": {
          "AlarmDescription": "Alarm to stop Instance",
          "AlarmName": "Inactivity Alarm",
          "AlarmActions": 
            [ "arn:aws:automate:us-east-1:ec2:stop" ],
          "MetricName": "CPUUtilization",
          "Namespace": "AWS/EC2",
          "Statistic": "Maximum",
          "Period": "1800",
          "Threshold": "3",
          "ComparisonOperator": "LessThanOrEqualToThreshold",
          "EvaluationPeriods": "2",
          "Dimensions": [
            {
              "Name": "InstanceId",
              "Value": {  "Ref" :  "WebServerInstance" }
            }
          ]
        }
    }
وارد حالت تمام صفحه شوید

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

Regla de EventBridge

قانون EventBridge منتظر می ماند تا برنامه در حالت باشد دستگیر شدپس می توانید اقدام کنید. این عمل فراخوانی تابع Lambda است که حاوی کدی است که *پشته* CloudFormation را حذف می کند.

"EventRule": {
      "DependsOn": ["ADLambda", "WebServerInstance"],
      "Type": "AWS::Events::Rule",
      "Properties": {
        "Description": "EventRule for EC2 Stopping",
        "EventPattern": {
          "source": [
            "aws.ec2"
          ],
          "detail-type": [
            "EC2 Instance State-change Notification"
          ],
          "detail": {
            "state": [
              "stopped"
            ],
            "instance-id": [{
              "Ref": "WebServerInstance"
            }]
          }
        },
        "State": "ENABLED",
        "Targets": [{
          "Arn": {"Fn::GetAtt": ["ADLambda", "Arn"] },
          "Id": "ADLambda"
        }]
      }
    }
وارد حالت تمام صفحه شوید

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

تابع لامبدا

هنگامی که تابع توسط قانون فراخوانی شد، کد پایتون را اجرا می کند که پشته CloudFormation را حذف می کند… باور نکردنی است، اینطور نیست؟ 🤯

در اینجا تعریف لامبدا:

"ADLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Handler": "index.handler",
        "Role": {
          "Fn::GetAtt": [
              "LambdaExecutionRole",
              "Arn"
          ]
        },
        "Code": {
          "ZipFile": "import boto3 \nimport os \nimport json \nstack_name = os.environ['stackName'] \n\ndef delete_cfn(stack_name):\n  try:\n   cfn = boto3.resource('cloudformation')\n   stack = cfn.Stack(stack_name)\n   stack.delete()\n   return \"SUCCESS\"\n  except:\n   return \"ERROR\" \ndef handler(event, context):\n  print(\"Received event:\")\n  print(json.dumps(event))\n  return delete_cfn(stack_name)"
        },
        "Environment": {
          "Variables": {
            "stackName": {
              "Ref" : "AWS::StackName"
            }
          }
        },
        "Runtime": "python3.9"
      }
}
وارد حالت تمام صفحه شوید

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

کد پایتون

این کدی است که در خط “ZipFile” در بخش قبل یافت می شود.

import boto3 
import os 
import json 
stack_name = os.environ['stackName']
def delete_cfn(stack_name):
 try:
 cfn = boto3.resource('cloudformation')
 stack = cfn.Stack(stack_name)
 stack.delete()
 return "SUCCESS"
 except:
 return "ERROR" 
def handler(event, context):
 print("Received event:")
 print(json.dumps(event))
 return delete_cfn(stack_name)
وارد حالت تمام صفحه شوید

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

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

نقش لامبدا

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

"LambdaExecutionRole": {
"Type": "AWS::IAM::Role",
"DeletionPolicy": "Retain",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": ["lambda.amazonaws.com"]
},
"Action": ["sts:AssumeRole"]
}
]
},
"Path": "https://dev.to/"
}
}
وارد حالت تمام صفحه شوید

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

سیاست لامبدا

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

✏️استفاده از: فراموش نکنید که منابع اضافی را که به آن مستقر می کنید اضافه کنید.

"LambdaExecutionPolicy": {
"Type": "AWS::IAM::Policy",
"DeletionPolicy": "Retain",
"Properties": {
"PolicyName": "autodestruction-policy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["logs:"],
"Resource": "arn:aws:logs:
::"
},
{
"Effect": "Allow",
"Action": [ "cloudformation:DeleteStack" ],
"Resource": {
"Ref": "AWS::StackId"
}},
{
"Effect": "Allow",
"Action": [ "lambda:DeleteFunction" ],
"Resource": ""
},
{
"Effect": "Allow",
"Action": [ "events:RemoveTargets" ],
"Resource": "
"
},
{
"Effect": "Allow",
"Action": [ "events:DeleteRule" ],
"Resource": ""
},
{
"Effect": "Allow",
"Action": [ "lambda:RemovePermission" ],
"Resource": "
"
},
{
"Effect": "Allow",
"Action": ["iam:DeleteRolePolicy","iam:DeleteRole"],
"Resource": ""
},
{
"Effect": "Allow",
"Action": [ "ec2:TerminateInstances" ],
"Resource": [{ "Fn::Join": ["", [
"arn:aws:ec2:",{"Ref": "AWS::Region"},":",
{"Ref": "AWS::AccountId"}, ":instance/",
{"Ref": "WebServerInstance"}]]}]
},
{
"Effect": "Allow",
"Action": [ "iam:DeleteRolePolicy" ],
"Resource": "
"
},
{
"Effect": "Allow",
"Action": [ "cloudwatch:DeleteAlarms" ],
"Resource": [{"Fn::GetAtt" : ["MyEC2Alarm","Arn"]}]
}
]
},
"Roles": [{
"Ref" : "LambdaExecutionRole"
}]
}
}
وارد حالت تمام صفحه شوید

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

اجازه برای لامبدا

این منبعی است که به قانون EventBridge اجازه می دهد تا تابع را فراخوانی کند.

"PermissionForADLambda": {
"Type": "AWS::Lambda::Permission",
"Properties": {
"FunctionName": {
"Ref": "ADLambda"
},
"Action": "lambda:InvokeFunction",
"Principal": "events.amazonaws.com",
"SourceArn": {
"Fn::GetAtt": [
"EventRule",
"Arn"
]
}
}
}
وارد حالت تمام صفحه شوید

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

حالا قسمت جالب اینجاست…

تابع لامبدا نمی تواند کل پشته را حذف کند زیرا باعث حذف آن می شود سیاست لامبدا (کسی که مجوز حذف را دارد) و رول لامبدا (کسی که آن سیاست ها را اجرا می کند). اگر آنها را حذف کنیم، چگونه می توان کار را تمام کرد؟ شما نمی توانید خودتان را حذف کنید و به آنچه خواسته اید ادامه دهید.

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

میدونم به چی فکر میکنی… “آنا، این دیگر معماری نیست که به طور کامل خود ویران شود”. خوب این نزدیک است که من می توانم! و مزیت این است که آن نقش و آن سیاست هزینه ایجاد نکنید، بنابراین هنوز در حال صرفه جویی هستید!

💡واقعیت جالب: من چندین هفته را صرف یافتن راهی برای کارکرد این معماری کردم، تا اینکه به AWS Summit مکزیکو سیتی رفتم و این را برای یک معمار AWS توضیح دادم (در اتاق “از کارشناسان بپرسید”). او کسی بود که مرا به ایده حفظ منابع آگاه کرد!

پس از ایجاد همه چیز، CloudFormation باید به این صورت باشد:

ایجاد منابع در CloudFormation

اکنون تنها چیزی که باقی می ماند این است که استفاده از آن برنامه را متوقف کنید و منتظر بمانید…⏰

حذف منابع در CloudFormation

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

نتیجه

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

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

👩‍💻به ساختن ادامه دهیم!

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

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

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

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