استقرار لامبدا با IP استاتیک هرگز به این سادگی نبوده است 🍰

TL; DR
🧠 نحوه استقرار a را بیاموزید لامبدا با IP استاتیک (برای نگرانی در لیست سفید)
⚡ اجرا کنید عملیات NodeJS SFTP با استفاده از این لامبدا
ممکن است برنامه بدون سرور شما نیاز به اتصال به سرور شریکی داشته باشد که نیاز به لیست سفید IP دارد.
ما از چارچوب بدون سرور برای استقرار تابع Lambda خود استفاده خواهیم کرد تایپ اسکریپت AWS CDK برای ایجاد زیرساخت مورد نیاز برای دادن IP ثابت به لامبدا 🔒.
اگر با این کتابخانه ها آشنایی ندارید، توصیه می کنم این پست وبلاگ Ultimate Serverless DevX: Serverless Framework x CDK را بررسی کنید تا یاد بگیرید که چگونه این دو را با هم هماهنگ کنید. 🤝
علاوه بر این، از بسته NodeJS ssh2-promise برای انجام عملیات SFTP در تابع Lambda خود استفاده خواهیم کرد. 💽
این چیزی است که ما خواهیم ساخت 👷:
بریم سر کار 💪🔨!
☁️ VPC، NAT Gateway و Elastic IP
ابتدا باید یک VPC با یک زیرشبکه عمومی و یک زیرشبکه خصوصی ایجاد کنیم. زیرشبکه خصوصی میزبان تابع Lambda ما خواهد بود و زیرشبکه عمومی میزبان NAT Gateway ما خواهد بود.
const vpc = new Vpc(stack, 'Vpc', {
vpcName: 'vpc',
natGateways: 1, // 👈 Automatically creates an Elastic IP
maxAzs: 1, // 👈 Use more if you need high availability
subnetConfiguration: [
{
name: 'private-subnet-1',
subnetType: SubnetType.PRIVATE_WITH_NAT,
cidrMask: 24,
},
{
name: 'public-subnet-1',
subnetType: SubnetType.PUBLIC,
cidrMask: 24,
},
],
});
💸 سلب مسئولیت قیمت
این معماری هزینه خواهد داشت مقداری پول. NAT Gateway بر روی نمونه EC2 اجرا می شود که برای شما هزینه دارد حدود 30 دلار در ماه. این قیمت در تعداد AZ هایی که استفاده می کنید ضرب می شود.
همچنین توصیه میکنم از CloudFormation Outputs برای ذخیره شناسههای منابعی که بعداً به آنها نیاز خواهید داشت استفاده کنید. ما می خواهیم به آن سیلی بزنیم ✨کد IaC را پاک کنید✨ در روابط عمومی ما 🖐️ .
export const vpcSecurityGroupOutputId = 'SgOutputId';
export const vpcPrivateSubnetOutputId = 'VpcPvSubOutputId';
...
const privateSubnets = vpc.selectSubnets(
{ subnetType: SubnetType.PRIVATE_WITH_NAT }
);
export const [privateSubnetId1] = privateSubnets.subnetIds;
// 👇 Outputing the IDs of the resources in case another stack needs them
new CfnOutput(stack, vpcSecurityGroupOutputId, {
value: vpc.vpcDefaultSecurityGroup,
});
new CfnOutput(stack, vpcPrivateSubnet1OutputId, {
value: privateSubnetId1,
});
⚡ تابع Lambda را اجرا کنید
اکنون که VPC خود را داریم، میتوانیم تابع Lambda خود را با استفاده از چارچوب بدون سرور اجرا کنیم.
export const staticIpLambda = {
timeout: 15,
handler: getHandlerPath(__dirname),
vpc: {
securityGroupIds: [ stack.resolve(vpc.vpcDefaultSecurityGroup) ],
subnetIds: [ stack.resolve(privateSubnetId1) ],
},
};
همچنین میتوانید این مقاله Framework بدون سرور x CDK را بررسی کنید تا نحوه استفاده از آن را بیاموزید stack.resolve()
روش 🧑🚀.
و بام! 🎉 تابع Lambda ما در زیر شبکه خصوصی ما مستقر است.
تمام ترافیک خروجی از تابع Lambda ما اکنون از طریق دروازه NAT عبور می کند، که از IP Elastic که قبلا ایجاد کردیم استفاده می کند. 🚀
می توانید IP Elastic دروازه NAT خود را با استفاده از کنسول AWS بازیابی کنید.
به سرویس VPC بروید و Elastic IPs را کلیک کنید. باید IP Elastic ایجاد شده توسط CDK را ببینید.
اکنون فقط به شریک خود پیام دهید و از او بخواهید این IP را در لیست سفید قرار دهد. 📩
❓ این قسمت در واقع اختیاری است.
ما یک مورد استفاده بسیار خاص از SFTP و مشکلی که در حین استفاده از آن با آن مواجه شدم را پوشش خواهیم دادssh2-promise
وserverless-esbuild
افزونه
حالا بیایید در مورد یک مورد استفاده بسیار خاص صحبت کنیم: انجام عملیات SFTP در تابع Lambda شما.
من می خواستم این مورد استفاده را با شما به اشتراک بگذارم زیرا با مشکلات عجیب و غریبی روبرو شدم ssh2-promise
بسته به درستی در لامبدا من قرار نمی گیرد .zip code
. 🤯
🔒 کلید SSH
اگر شریک SFTP شما به یک کلید SSH نیاز دارد، توصیه میکنم کلید را در AWS Secrets Manager ذخیره کنید. سپس می توانید با استفاده از میان افزار Middy Secrets Manager آن را در تابع Lambda خود بازیابی کنید. این کلید را به عنوان یک رشته در شما ارائه می دهد زمینه تابع لامبدا. 🤓
💽 فایلی را که می خواهید ارسال کنید در Lambda خود ذخیره کنید /tmp
پوشه
این ssh2-promise
بسته برای ارسال فایل شما نیاز به دسترسی به سیستم فایل دارد. یک راه برای دستیابی به آن در زمینه تابع لامبدا، استفاده از اهرم است /tmp
پوشه
این پوشه قابل نوشتن است و زمانی که عملکرد Lambda شما خاتمه یابد حذف خواهد شد.
🚧 هشدار
این/tmp
پوشه ماندگار نیست اگر می خواهید فایل هایی را که ارسال کرده اید پیگیری کنید، باید از S3 نیز استفاده کنید. 📦
همچنین توجه داشته باشید که/tmp
پوشه بین فراخوانی های متوالی لامبدا در یک محیط اجرا به اشتراک گذاشته می شود. از یک نام فایل منحصر به فرد برای جلوگیری از هر گونه اشکال استفاده کنید 🐛.
این همان چیزی است که کد نهایی با آن به نظر می رسد ssh2-promise
بسته:
fs.writeFileSync('/tmp/myFile.txt', 'Hello World!');
const sshPrivateKey = context["SSH_PRIVATE_KEY"]
const ssh = new SSH2Promise({
host: 'sftpIpAddress',
username: 'sftpUsername',
privateKey: sshPrivateKey,
port: "SFTP_PORT",
});
await ssh.connect();
const sftp = ssh.sftp();
await sftp.fastPut('/tmp/myFile.txt', "distant_name.txt");
await ssh.close();
صید 🎣
اگر مثل من از serverless-esbuild
افزونه برای بستهبندی عملکرد Lambda شما، ممکن است با مشکلات عجیبی روبرو شوید.
این ssh2-promise
بسته به درستی در تابع Lambda شما قرار داده نشده است. 🤯
برای حل این مشکل ابتدا پچ کردم serverless-esbuild
افزونه اجازه می دهد تا ماژول yarn3 حذف شود. من می خواهم ssh2-promise
بسته بندی نه توسط esbuild همراه شود.
این وصله در اینجا به عنوان یک اصل github در دسترس است
سپس، من مجبور به اضافه کردن ssh2-promise
بسته به externals
بخش من esbuild
پیکربندی
// serverless.ts
const serverlessConfiguration = {
..., // 👈 Your other serverless config
custom: {
esbuild: { ...esbuildConfig, external: ['ssh2-promise'] },
},
};
تابع Lambda شما اکنون باید بتواند عملیات SFTP را انجام دهد. 🚀
با تشکر برای خواندن! 🙏
اگر سوال یا بازخوردی دارید، در صورت تمایل با من تماس بگیرید توییتر یا در نظرات زیر سوال بپرسید. 🥸
همچنین برای مقالات بیشتر در مورد AWS، سرور بدون سرور و توسعه ابری، Dev.to من را بررسی کنید. 📝