اجرای سرور VS Code در AWS

من عاشق کدنویسی هستم! من عاشق نوشتن هستم! من عاشق یادگیری، تلاش و بازی با خدمات جدید AWS هستم. مشکل این است که من همیشه به لپ تاپم برای کدنویسی دسترسی ندارم. من GitHub CodeSpaces را امتحان کردم اما واقعاً از این تجربه خوشم نیامد. من به چیزی مشابه اما متفاوت نیاز داشتم.
هدف
هدف ایجاد تنظیماتی بود که به من امکان میدهد با استفاده از VS Code از تبلت اندرویدی خود کدنویسی کنم. من نیاز به دسترسی به یک ترمینال کامل با SSH، AWS CLI، Git و موارد دیگر داشتم. بنابراین اجرای آن به صورت محلی روی تبلت گزینه ای نیست، حتی اگر نصب و اجرا شدن آن امکان پذیر باشد.
کد VS
VS Code از ابتدا به عنوان بخش مشتری و سرور ساخته شده است. هر دو بخش کلاینت و سرور می توانند روی یک کامپیوتر یا ماشین های مجازی مختلف اجرا شوند. این امکان اتصال به یک بخش سرور را اساساً از هر جایی، در صورتی که یک وب کلاینت یا مستقل باشد، می دهد.
این امکان توسعه از راه دور را از طریق ابزارهای مختلف مانند SSH یا حالت تونل ویژه فراهم می کند.
راه حل
با درک نحوه ساختار VS Code، اجرای بخش سرور در یک نمونه EC2 و اتصال به آن از طریق vscode.dev، با استفاده از حالت تونل ویژه، باید کاملاً امکان پذیر باشد. باید این امکان را داشته باشد که از تبلت اندرویدی من اجرا شود. برای اجرای VS Code در نمونه EC2 از VS Code CLI استفاده می کنیم
VPC و LaunchTemplate ایجاد کنید
اول از همه ما به یک نمونه EC2 در حال اجرا نیاز داریم، و برای داشتن آن، اجازه دهید با ایجاد یک VPC اولیه با استفاده از یک الگوی اولیه Cloudformation شروع کنیم.
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: setup basic VPC
Parameters:
ApplicationName:
Type: String
IPSuperSet:
Type: String
Description: The IP Superset to use for the VPC CIDR range, e.g 10.0
Default: "10.0"
Resources:
##########################################################################
# VPC Base Infrastructure #
##########################################################################
VPC:
Type: AWS::EC2::VPC
Properties:
EnableDnsSupport: true
EnableDnsHostnames: true
CidrBlock: !Sub "${IPSuperSet}.0.0/16"
Tags:
- Key: Name
Value: !Ref ApplicationName
PublicSubnetOne:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone:
Fn::Select:
- 0
- Fn::GetAZs: { Ref: "AWS::Region" }
VpcId: !Ref VPC
CidrBlock: !Sub ${IPSuperSet}.0.0/24
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub ${ApplicationName}-public-one
PublicSubnetTwo:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone:
Fn::Select:
- 1
- Fn::GetAZs: { Ref: "AWS::Region" }
VpcId: !Ref VPC
CidrBlock: !Sub ${IPSuperSet}.1.0/24
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub ${ApplicationName}-public-two
##########################################################################
# Gateways #
##########################################################################
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Ref ApplicationName
GatewayAttachement:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
##########################################################################
# Route Tables & Routes #
##########################################################################
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${ApplicationName}-public-rt
PublicRoute:
Type: AWS::EC2::Route
DependsOn: GatewayAttachement
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnetOneRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnetOne
RouteTableId: !Ref PublicRouteTable
PublicSubnetTwoRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnetTwo
RouteTableId: !Ref PublicRouteTable
بعد باید یک نمونه EC2 و یک حجم EBS ایجاد کنیم. ولوم EBS برای ذخیره همه کدها استفاده می شود، به این ترتیب می توانیم نمونه EC2 را از بین ببریم و تمام تنظیمات و کدها را روی ولوم EBS نگه داریم. ولوم EBS در هنگام راهاندازی اولیه نصب میشود و همچنین به fstab اضافه میشود، بنابراین اگر نمونه را راهاندازی مجدد کنیم دوباره نصب میشود. برای آسان کردن ایجاد نمونه های جدید با همان پیکربندی، از LaunchTemplate استفاده می کنیم.
ما همچنین تمام اجزای مورد نیاز را در طول بوت اولیه با استفاده از UserScript نصب خواهیم کرد. ما همه چیز را در لینوکس آمازون 2023 اجرا خواهیم کرد.
ما از Instance Connect استفاده خواهیم کرد تا بتوانیم به نمونه متصل شویم. بنابراین ما باید محدوده IP برای Instance Connect را به گروه امنیتی خود اضافه کنیم. برای یافتن محدوده IP می توانیم ip-ranges.json را دانلود کنیم.
AWSTemplateFormatVersion: "2010-09-09"
Description: Base setup for VS Code EC2 resources
Parameters:
AmiId:
Type: String
Default: ami-04b1c88a6bbd48f8e # AMI for Amazon Linux 2023 in eu-west-1
InstanceType:
Type: String
Description: Type of instance to use for EC2 runners.
Default: t3.large
AvailabilityZone:
Type: String
Description: The availability zone to run in
Default: eu-west-1a
InfrastructureStackName:
Type: String
Description: The name of the stack with the Infrastructure resources
ServerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: EC2 Security Group
VpcId:
Fn::ImportValue: !Sub ${InfrastructureStackName}:VpcId
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 18.202.216.48/29 # Instance Connect in eu-west-1
SecurityGroupInboundAllowSelf:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref ServerSecurityGroup
IpProtocol: tcp
FromPort: "0"
ToPort: "65535"
SourceSecurityGroupId: !Ref ServerSecurityGroup
InstanceRole:
Type: AWS::IAM::Role
Properties:
Policies:
- PolicyName: AllwoEC2Actions
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- ec2:*
Resource: "*"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action: sts:AssumeRole
EC2InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Roles:
- !Ref InstanceRole
CodeEbsVolume:
Type: AWS::EC2::Volume
Properties:
AvailabilityZone: !Ref AvailabilityZone
Encrypted: false
Size: 32
VolumeType: gp3
LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateData:
EbsOptimized: True
IamInstanceProfile:
Arn: !GetAtt EC2InstanceProfile.Arn
ImageId: !Ref AmiId
InstanceType: !Ref InstanceType
SecurityGroupIds:
- !GetAtt ServerSecurityGroup.GroupId
UserData:
Fn::Base64:
Fn::Sub: |
#!/bin/bash -xe
sudo -s
yum update -y
yum install -y jq
yum install git -y
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
VOLUME_ID=${CodeEbsVolume}
INSTANCE_ID=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/instance-id)
REGION=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r .region)
aws ec2 attach-volume --volume-id $VOLUME_ID --device /dev/xvdf --instance-id $INSTANCE_ID --region $REGION
mkdir vscode-data
chown -R ec2-user:ec2-user /vscode-data
mount /dev/xvdf /vscode-data
echo -e "/dev/xvdf /vscode-data xfs defaults,nofail 0 2" >> /etc/fstab
curl -Lk 'https://code.visualstudio.com/sha/download?build=stable&os=cli-alpine-x64' --output vscode_cli.tar.gz
tar -xf vscode_cli.tar.gz
نمونه EC2 را راه اندازی کنید
حالا بیایید از آن LaunchTemplate برای شروع یک نمونه EC2 استفاده کنیم. این بار اجازه دهید به سراغ کنسول AWS برویم تا آن را راه اندازی کنیم.
به بخش EC2 بروید و از منوی کشویی Launch Instance from template را انتخاب کنید.
با انتخاب LaunchTemplate که به تازگی ایجاد کردیم و نسخه مورد استفاده در صورت وجود بیشتر از یک شروع کنید. در مورد من من 6 نسخه دارم و دوست دارم از جدیدترین آنها استفاده کنم.
اکنون به پایین بروید و مطمئن شوید که AMI صحیح انتخاب شده است، باید آمازون Linux 2023 AMI باشد.
در نهایت یک زیرشبکه را در VPC که به تازگی ایجاد کرده ایم انتخاب کنید، باید منطقه در دسترس بودن حجم EBS که ایجاد کرده ایم باشد. در مورد من، حجم EBS را در eu-west-1a ایجاد کردهام، بنابراین نمونه باید در یک زیرشبکه در آن AZ باشد.
بقیه موارد را به عنوان پیش فرض بگذارید و روی گزینه Launch Instance کلیک کنید
VSCode را در نمونه شروع کنید
با اجرای نمونه، اکنون باید VSCode را راه اندازی کنیم. ما قبلاً CLI را در اسکریپت کاربر دانلود کرده ایم. بیایید با اتصال به نمونه با استفاده از Instance Connect شروع کنیم.
به نمونه بروید و Connect را انتخاب کنید.
اگر اتصال موفقیت آمیز باشد، باید ترمینالی مانند این را ببینید.
اکنون باید سرور VSCode را با استفاده از CLI راه اندازی کنیم، این کار را با این دستور انجام می دهیم.
~/code tunnel --accept-server-license-terms --name vscode-demo-tunnel
افزودن –accept-server-license-terms به دستور به طور خودکار شرایط مجوز را می پذیرد. همچنین باید به تونل خود یک نام بدهیم که با پارامتر –name انجام می شود. در دستور بالا نام vscode-demo-tunnel را به تونل می دهیم.
اکنون باید نتیجه ای مانند این به ما بدهد.
کاری که اکنون باید انجام دهیم این است که به سرور دسترسی داشته باشیم، که با پیمایش به URL هایلایت شده انجام می شود. این باید ما را به این صفحه ببرد.
در این صفحه باید کدی را که هنگام راهاندازی سرور VSCode دادهایم ارائه کنیم.
پس از یک فعال سازی، اکنون باید GitHub را برای سرور مجاز کنیم.
اگر همه چیز کار کند، باید در صفحه موفقیت قرار بگیریم.
با بازگشت به صفحه اتصال نمونه، اکنون باید ببینیم که سرور در حال اجرا است و یک URL برای اتصال به آن.
اکنون میتوانیم به URL برجستهشده، که در اصل «https://vscode.dev/tunnel/tunnel-name» است، برویم. VSCode باید در پنجره مرورگر بارگیری شود و به ما امکان دسترسی به یک ویرایشگر VSCode کامل با دسترسی ترمینال و همه چیز را بدهد.
در گوشه پایین سمت چپ وضعیت اتصال به طور کامل قابل مشاهده است.
این همان کاری است که ما باید انجام دهیم تا سرور VS Code روی یک نمونه EC2 اجرا شود و به ما اجازه دهد از هر مرورگری به آن متصل شویم. اساسا ما نسخه میزبانی شده خود از GitHub CodeSpaces را ایجاد کرده ایم.
اما، هنوز پیشرفت هایی وجود دارد که می توانیم انجام دهیم.
اضافه کردن مقداری اتوماسیون اضافی
اتصال به نمونه هر بار با استفاده از Instance Connect برای راه اندازی سرور چندان عملی نیست. انجام این کار از طریق تبلت اندرویدی کارساز است، اما من ترجیح میدهم این مرحله را کمی بیشتر به صورت خودکار انجام دهم.
چیزی که عالی خواهد بود این است که بتوانیم سرور VS Code را به عنوان سرویسی راه اندازی کنیم که می تواند در پس زمینه اجرا شود. بنابراین اول از همه اجازه دهید یک اسکریپت پوسته به نام vscodestart.sh ایجاد کنیم که سرور را راه اندازی می کند.
#!/bin/sh
~/code tunnel --accept-server-license-terms --name vscode-demo-tunnel
این همان دستوری است که در هنگام راهاندازی دستی از آن استفاده کردیم. در مرحله بعد یک سرویس لینوکس ایجاد می کنیم که می توانیم از systemd استفاده کنیم، بنابراین بیایید فایل سرویس را با نام vscode.service ایجاد کنیم.
[Unit]
After=network.target
[Service]
User=ec2-user
Group=ec2-user
ExecStart=/usr/local/bin/vscodestart.sh
[Install]
WantedBy=default.target
حالا بیایید فایل vscode.service را در /etc/systemd/system/ و vscodestart.sh را در /usr/local/bin/ کپی کنیم.
اکنون می توانیم سرور را با استفاده از دستور راه اندازی کنیم:
systemctl start vscode.service
به این ترتیب سرور VS Code اکنون می تواند در پس زمینه اجرا شود. خوب این اولین قدم در اتوماسیون بود. برای مرحله دوم، یک سند مدیریت سیستم های AWS ایجاد می کنیم که می توانیم آن را از AWS CLI یا کنسول اجرا کنیم. سپس سند SSM دستور start را در نمونه EC2 اجرا می کند که سرویس سرور VS Code را شروع می کند. بنابراین ما آن را به قالب CloudFormation خود اضافه می کنیم.
StartVCodeServerDocument:
Type: AWS::SSM::Document
Properties:
DocumentType: Command
Content:
schemaVersion: "2.2"
description: Command Document for VS Code start server service
mainSteps:
- action: "aws:runShellScript"
name: "startserver"
inputs:
runCommand:
- sudo systemctl start vscode.service
با قرار دادن سند SSM میتوانیم به کنسول بپریم و سند را روی نمونه خود اجرا کنیم. حتی اگر این یک راه حل کاملاً خودکار نباشد، گامی در مسیر درست است. من اکنون می توانم سرور VS Code را به راحتی در یک نمونه EC2 راه اندازی کنم و تا زمانی که به مرورگر دسترسی داشته باشم از هر دستگاهی کد بنویسم.
گوچاس
در طول پروژه چند اشتباه و چیزهایی وجود داشت که باید در نظر بگیریم. اول از همه، اولین باری که یک سرور در یک نمونه EC2 راه اندازی می شود، باید آن را با استفاده از کد تولید شده توسط سرور VS Code فعال کنیم. این یک راهحل کاملاً خودکار را کمی سختتر میکند، زیرا باید در اولین بار به نمونه متصل شویم.
همچنین باید در نظر داشته باشیم که برای هر حساب GitHub محدودیت 5 تونل وجود دارد. این بدان معناست که اگر ششمین تونل را شروع کنیم، اولین تونل بازیافت خواهد شد.
شرایط سرویس همچنین فقط استفاده از سرور VS Code را برای استفاده شخصی یا درون یک شرکت مجاز میکند. شما مجاز به میزبانی و اجرای آن به عنوان راه حل SaaS نیستید.
نتیجه گیری و مرحله بعدی
با اجرای سرور VS Code بر روی نمونه EC2 که مالک آن هستم، اکنون کنترل کامل هزینه آن، دسترسی آن را در دست دارم، و این امکان را به من می دهد که اگر بخواهم تمام مخازن خود را شبیه سازی کنم. من اکنون می توانم اساساً برای هر پروژه ام با تلاش و هزینه بسیار کم از هر دستگاهی کد بنویسم تا زمانی که بتوانم یک مرورگر را اجرا کنم و به اینترنت دسترسی داشته باشم. این اکنون به من این امکان را می دهد که وقتی در اتوبوس هستم یا هر جایی که به لپ تاپم دسترسی ندارم از رایانه لوحی اندروید خود کدنویسی یا وبلاگ نویسی کنم.
پس مراحل بعدی چیست؟
من قصد دارم یک راهاندازی کاملاً خودکار ایجاد کنم که بتوانم نمونههای سرور را از یک صفحه وب شروع و متوقف کنم. البته این راهحل بدون سرور در تمام قسمتهایی است که برای نمونه EC2 خود انتظار میرود.
همانطور که دیدید من نمونه EC2 را در یک زیر شبکه عمومی اجرا می کنم، این به این دلیل است که اولین باری که سرور را راه اندازی می کنم باید به آن متصل شوم. با Instance Connect Endpoint جدید میتوانم به نمونه متصل شوم حتی اگر در یک زیرشبکه خصوصی باشد.
کلمات پایانی
این یک پروژه واقعا سرگرم کننده بود. این واقعا عالی است که ببینید چقدر می توانید با کد و تلاش بسیار کم انجام دهید. در ادامه با ما همراه باشید.
فراموش نکنید که من را در لینکدین دنبال کنید و توییتر برای مطالب بیشتر، و بقیه وبلاگ های من را بخوانید