#c# #amazon-web-services #windows-services
#c# #amazon-веб-сервисы #windows-службы
Вопрос:
У меня есть C#.NET приложение-служба Windows, работающее на Windows EC2 в AWS. Каков наилучший шаблон для обеспечения высокой доступности с использованием Multi-AZ (например, если зона доступности выйдет из строя, как 2-я служба Windows узнает о запуске?)
Ответ №1:
Если служба Windows работает <15 минут, преобразуйте ее в лямбда-выражение — таким образом, она будет масштабироваться в миллисекундах, платите только за используемое время выполнения (не 24×7), забудьте об исправлениях. Если нет, вы можете рассмотреть пакетную службу или, наконец, использовать EC2s.
Вы захотите автоматизировать развертывание всего в AWS с помощью AWS SDK, AWS CLI, AWS CDK или Cloud Formation.
CloudFormation проще всего настроить, в приведенном здесь примере создается один EC2 в ASG с минимальным и максимальным значением, равным 1. Это означает, что если экземпляр EC2 выйдет из строя, ASG обнаружит это (это называется событием масштаба), и поскольку минимальное значение равно 1, он запустит другой экземпляр.
Я включил в UserData пример загрузки скрипта powershell, который может установить вашу службу, это занимает слишком много времени, я бы порекомендовал вам создать AMI и использовать его в шаблоне CloudFormation (CFN). Я бы рекомендовал вам загрузить этот шаблон CFN и попробовать завершить экземпляр ad, через минуту ASG запустит новый. Единственный способ — удалить ASG, чтобы удалить этот единственный экземпляр!
Замените «YourWindowsService» именем вашей службы и укажите VPC:
AWSTemplateFormatVersion: 2010-09-09
Description: YourWindowsService deployment script
Parameters:
Environment:
Description: The environment we deploy to
Type: String
Default: 'nonprod'
AllowedValues: ['nonprod','prod']
KeyPairName:
Description: >-
Mandatory. Enter a Public/private key pair. If you do not have one in this region,
please create it before continuing
Type: 'AWS::EC2::KeyPair::KeyName'
Default: YourKeyPairName
Subnet1ID:
Description: 'ID of the subnet 1 for auto scaling group'
Type: 'AWS::EC2::Subnet::Id'
Subnet2ID:
Description: 'ID of the subnet 2 for auto scaling group'
Type: 'AWS::EC2::Subnet::Id'
RemoteAccessCIDR:
AllowedPattern: >-
^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(/([0-9]|[1-2][0-9]|3[0-2]))$
ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/x
Description: Allowed CIDR block for external SSH access to YourWindowsServices IIS WS
Type: String
Default: 0.0.0.0/0
AppName:
Type: String
Description: Application Name
Default: "YourWindowsService"
InstanceProfile:
Type: String
Default: YourIAMProvisioningProfileOrEc2FullAccess
AMI:
Type: 'AWS::EC2::Image::Id'
Mappings:
EnvironmentToInstanceType:
nonprod:
instanceType: t3.medium
prod:
instanceType: t3.large
EnvironmentToVPC:
nonprod:
VPC: vpc-................
prod:
VPC: something.cant.be.null
DisableTerminate:
prod:
YesorNo: 'false'
nonprod:
YesorNo: 'false'
Conditions:
CreateNonProdResources: !Equals [ !Ref Environment, prod ]
CreateProdResources: !Equals [ !Ref Environment, nonprod ]
Resources:
YourWindowsServiceMainLogGroup:
Type: 'AWS::Logs::LogGroup'
SSHMetricFilter:
Type: 'AWS::Logs::MetricFilter'
Properties:
LogGroupName: !Ref YourWindowsServiceMainLogGroup
FilterPattern: ON FROM USER PWD
MetricTransformations:
- MetricName: SSHCommandCount
MetricValue: 1
MetricNamespace: !Join
- /
- - AWSQuickStart
- !Ref 'AWS::StackName'
YourWindowsServiceAutoScalingGroup:
Type: 'AWS::AutoScaling::AutoScalingGroup'
Properties:
LaunchConfigurationName: !Ref YourWindowsServiceLaunchConfiguration
AutoScalingGroupName: !Join
- '.'
- - !Ref 'AWS::StackName'
- 'ASG'
VPCZoneIdentifier:
- !Ref Subnet1ID
- !Ref Subnet2ID
MinSize: 1
MaxSize: 1
Cooldown: '300'
DesiredCapacity: 1
Tags:
- Key: Name
Value: YourWindowsPCName
PropagateAtLaunch: 'true'
YourWindowsServiceLaunchConfiguration:
Type: 'AWS::AutoScaling::LaunchConfiguration'
Properties:
AssociatePublicIpAddress: 'false'
PlacementTenancy: default
KeyName: !Ref KeyPairName
ImageId: !Ref AMI
SecurityGroups:
- Fn::If: [CreateNonProdResources, !Ref YourWindowsServiceNonProdSecurityGroup, !Ref "AWS::NoValue"]
- Fn::If: [CreateProdResources, !Ref YourWindowsServiceProdSecurityGroup, !Ref "AWS::NoValue"]
IamInstanceProfile: !Ref InstanceProfile
InstanceType: !FindInMap [EnvironmentToInstanceType, !Ref 'Environment', instanceType]
UserData:
!Base64 |
<powershell>
#setup an install folder
$path = "C:temp"
If(!(test-path $path))
{
New-Item -ItemType Directory -Force -Path $path
}
cd $path
#using S3 (ie the AWS API) fetch the powershell install script and execute it
$S3BucketName = "a-unique-bucket"
$bootstrap = "install-env.ps1"
$script = ($path $bootstrap)
Set-DefaultAWSRegion -Region ap-southeast-2
Copy-S3Object -BucketName $S3BucketName -key $bootstrap -LocalFile ($path $bootstrap)
amp; $script
</powershell>
<persist>true</persist>
<runAsLocalSystem>true</runAsLocalSystem>
YourWindowsServiceNonProdSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Condition: CreateNonProdResources
Properties:
GroupDescription: Enables access to YourWindowsService
GroupName: !Join
- '.'
- - !Ref 'AWS::StackName'
- 'SG'
VpcId: !FindInMap [EnvironmentToVPC, !Ref 'Environment', VPC]
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: !Ref RemoteAccessCIDR
- IpProtocol: icmp
FromPort: '-1'
ToPort: '-1'
CidrIp: !Ref RemoteAccessCIDR
- IpProtocol: tcp
FromPort: '80'
ToPort: '80'
CidrIp: !Ref RemoteAccessCIDR
- IpProtocol: tcp
FromPort: '3389'
ToPort: '3389'
CidrIp: !Ref RemoteAccessCIDR
- IpProtocol: udp
FromPort: '3389'
ToPort: '3389'
CidrIp: !Ref RemoteAccessCIDR
YourWindowsServiceProdSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Condition: CreateProdResources
Properties:
GroupDescription: Enables access to YourWindowsService
GroupName: !Join
- '.'
- - !Ref 'AWS::StackName'
- 'SG'
VpcId: !FindInMap [EnvironmentToVPC, !Ref 'Environment', VPC]
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: !Ref RemoteAccessCIDR
- IpProtocol: icmp
FromPort: '-1'
ToPort: '-1'
CidrIp: !Ref RemoteAccessCIDR
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '80'
ToPort: '80'
CidrIp: !Ref RemoteAccessCIDR
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '3389'
ToPort: '3389'
CidrIp: !Ref RemoteAccessCIDR
- IpProtocol: udp
FromPort: '3389'
ToPort: '3389'
CidrIp: !Ref RemoteAccessCIDR
Комментарии:
1. Я бы дважды проверил, нужно ли мне использовать Lambda для замены моей службы Windows. Экземпляр EC2 может быть более дешевым вариантом, если мой код выполняется как рабочая служба. Например, если я использую выделенный лямбда-код объемом 2 ГБ памяти 24×7 при циклическом выполнении, это обойдется мне примерно в 86 долларов в месяц, в то время как EC2 t3a.small будет стоить 13,5 долларов в месяц. Однако Lambda отлично подходит для выполнения на основе событий.
Ответ №2:
Вы можете использовать механизм блокировки, чтобы предотвратить одновременную работу обоих экземпляров. Redis может быть хорошим вариантом, используя https://github.com/samcook/RedLock.net
Ответ №3:
Зона доступности в AWS — это группа центров обработки данных, необычно, что все центры обработки данных в AZ могут отключаться одновременно. Если вы согласны с тем, чтобы ваш экземпляр EC2 Windows оставался в single AZ, вы можете настроить автоматическое восстановление на вашем экземпляре EC2. Это восстановит ваш экземпляр EC2 на работоспособном хосте в случае повреждения существующего экземпляра EC2 или сервера.
На случай, если вы действительно хотите перейти через AZS в случае маловероятного отключения уровня AZ. Вы можете настроить автоматическое масштабирование EC2 с несколькими выбранными AZs. Вы можете сохранить минимальное и максимальное количество экземпляров равным 1. Таким образом, вы настраиваете автоматическое масштабирование для управления экземплярами EC2 в AZs, указывая при этом, чтобы он не создавал более 1 экземпляра одновременно. Если ваш экземпляр в существующей AZ становится недоступным и если вся AZ, в которой запущен ваш экземпляр, становится недоступной, служба автоматического масштабирования запустит ваш единственный экземпляр в одном из других AZ. Однако для службы Windows это перебор. Этот шаблон имеет смысл для нескольких веб-серверов, стоящих за средством балансировки нагрузки приложений. Как я уже сказал, AWS AZ — это группа из нескольких центров обработки данных, поэтому автоматического восстановления более чем достаточно для одного экземпляра EC2.