aws(学习笔记第十五课)
- 如何从灾难中恢复
学习内容:
- 使用
CloudWatch
对服务器进行监视与恢复 - 区域(
region
),可用区(available zone
)和子网(subnet
) - 使用自动扩展(
AutoScalingGroup
)
1. 使用CloudWatch
对服务器进行监视与恢复
- 整体架构
这里模拟Jenkins Server
在灾难时候,可以由AWS Cloudwatch Alarm
监视到,之后将其recover
。
在这里,elastic ip
定义了,并且将其指向了Jenkins Server
。为什么平时没有使用elastic ip
,这里特意使用它呢。
因为默认如果让AWS
自动配置给ec2
的internet ip
,都是临时的ip
,每次ec2
实例重启了之后,都会重新分配ip
。但是作为Jenkins Server
来使用,并且一旦从灾难中recover
之后,ip address
变化的话,运用起来将会特别不方便。
- 代码解析
-
代码
json{ "AWSTemplateFormatVersion": "2010-09-09", "Description": " (Jenkins (CI server) running on EC2 with AWS CloudWatch recovery)", "Parameters": { "KeyName": { "Description": "Key Pair name", "Type": "AWS::EC2::KeyPair::KeyName", "Default": "my-cli-key" }, "JenkinsAdminPassword": { "Description": "Password for Jenkins admin user", "Type": "String", "AllowedPattern" : "[a-zA-Z0-9]*", "MinLength" : "8", "MaxLength" : "42" } }, "Mappings": { "EC2RegionMap": { "ap-northeast-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-cbf90ecb"}, "ap-southeast-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-68d8e93a"}, "ap-southeast-2": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-fd9cecc7"}, "eu-central-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-a8221fb5"}, "eu-west-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-a10897d6"}, "sa-east-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-b52890a8"}, "us-east-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-1ecae776"}, "us-west-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-d114f295"}, "us-west-2": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-e7527ed7"} } }, "Resources": { "VPC": { "Type": "AWS::EC2::VPC", "Properties": { "EnableDnsSupport": "true", "EnableDnsHostnames": "true", "CidrBlock": "10.0.0.0/16", "Tags": [ { "Key": "Name", "Value": "jenkins-recovery" } ] } }, "Subnet": { "Type": "AWS::EC2::Subnet", "Properties": { "VpcId": { "Ref": "VPC" }, "AvailabilityZone": {"Fn::Select": ["0", {"Fn::GetAZs": ""}]}, "CidrBlock": "10.0.0.0/24", "Tags": [ { "Key": "Name", "Value": "jenkins-recovery" } ] } }, "InternetGateway": { "Type": "AWS::EC2::InternetGateway", "Properties": { "Tags": [ { "Key": "Name", "Value": "jenkins-recovery" } ] } }, "GatewayToInternet": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { "VpcId": { "Ref": "VPC" }, "InternetGatewayId": { "Ref": "InternetGateway" } } }, "RouteTable": { "Type": "AWS::EC2::RouteTable", "Properties": { "VpcId": { "Ref": "VPC" }, "Tags": [ { "Key": "Name", "Value": "jenkins-recovery" } ] } }, "InternetRoute": { "Type": "AWS::EC2::Route", "Properties": { "RouteTableId": { "Ref": "RouteTable" }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "InternetGateway" } }, "DependsOn": "GatewayToInternet" }, "RouteTableAssociation": { "Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": { "SubnetId": { "Ref": "Subnet" }, "RouteTableId": { "Ref": "RouteTable" } } }, "NetworkAcl": { "Type": "AWS::EC2::NetworkAcl", "Properties": { "VpcId": { "Ref": "VPC" }, "Tags": [ { "Key": "Name", "Value": "jenkins-recovery" } ] } }, "NetworkAceSSH": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "10", "Protocol": "6", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "22", "To": "22" } } }, "NetworkAceJenkinsHTTP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "11", "Protocol": "6", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "8080", "To": "8080" } } }, "NetworkAceNTP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "20", "Protocol": "17", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "123", "To": "123" } } }, "NetworkAceICMP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "30", "Protocol": "1", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "Icmp": { "Code": "-1", "Type": "-1" } } }, "NetworkAceHighPortsTCP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "40", "Protocol": "6", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "1024", "To": "65535" } } }, "NetworkAceHighPortsUDP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "41", "Protocol": "17", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "1024", "To": "65535" } } }, "NetworkAceEgress": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "10", "Protocol": "-1", "RuleAction": "allow", "Egress": "true", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "0", "To": "65535" } } }, "NetworkAclAssociation": { "Type": "AWS::EC2::SubnetNetworkAclAssociation", "Properties": { "SubnetId": { "Ref": "Subnet" }, "NetworkAclId": { "Ref": "NetworkAcl" } } }, "SecurityGroup": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "SecurityGroupforjenkins", "VpcId": { "Ref": "VPC" }, "Tags": [ { "Key": "Name", "Value": "jenkins-recovery" } ], "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "CidrIp": "0.0.0.0/0" }, { "IpProtocol": "tcp", "FromPort": "8080", "ToPort": "8080", "CidrIp": "0.0.0.0/0" }, { "IpProtocol": "icmp", "FromPort": "-1", "ToPort": "-1", "CidrIp": "0.0.0.0/0" } ] } }, "ElasticIP": { "Type": "AWS::EC2::EIP", "Properties": { "InstanceId": {"Ref": "Server"}, "Domain": "vpc" }, "DependsOn": "GatewayToInternet" }, "Server": { "Type": "AWS::EC2::Instance", "Properties": { "ImageId": {"Fn::FindInMap": ["EC2RegionMap", {"Ref": "AWS::Region"}, "AmazonLinuxAMIHVMEBSBacked64bit"]}, "InstanceType": "t2.micro", "KeyName": {"Ref": "KeyName"}, "SecurityGroupIds": [{"Ref": "SecurityGroup"}], "SubnetId": {"Ref": "Subnet"}, "UserData": {"Fn::Base64": {"Fn::Join": ["", [ "#!/bin/bash -ex\n", "wget http://pkg.jenkins-ci.org/redhat/jenkins-1.616-1.1.noarch.rpm\n", "rpm --install jenkins-1.616-1.1.noarch.rpm\n", "sed -i -e 's/JENKINS_ARGS=\\\"\\\"/JENKINS_ARGS=\\\"--argumentsRealm.passwd.admin=", {"Ref": "JenkinsAdminPassword"}, " --argumentsRealm.roles.admin=admin\\\"/g' /etc/sysconfig/jenkins\n", "echo \"<?xml version='1.0' encoding='UTF-8'?><hudson><version>1.0</version><useSecurity>true</useSecurity><authorizationStrategy class=\\\"hudson.security.FullControlOnceLoggedInAuthorizationStrategy\\\"/><securityRealm class=\\\"hudson.security.LegacySecurityRealm\\\"/></hudson>\" > /var/lib/jenkins/config.xml\n", "service jenkins start\n" ]]}}, "Tags": [ { "Key": "Name", "Value": "jenkins-recovery" } ] }, "DependsOn": "GatewayToInternet" }, "RecoveryAlarm": { "Type": "AWS::CloudWatch::Alarm", "Properties": { "AlarmDescription": "Recover server when underlying hardware fails.", "Namespace": "AWS/EC2" , "MetricName": "StatusCheckFailed_System", "Statistic": "Minimum", "Period": "60", "EvaluationPeriods": "5", "ComparisonOperator": "GreaterThanThreshold", "Threshold": "0", "AlarmActions": [{"Fn::Join": ["", ["arn:aws:automate:", { "Ref": "AWS::Region"}, ":ec2:recover"]]}], "Dimensions": [{"Name": "InstanceId", "Value": {"Ref": "Server"}}] } } }, "Outputs": { "JenkinsURL": { "Description": "URL to access web interface of Jenkins server.", "Value": {"Fn::Join": ["", ["http://", {"Ref": "ElasticIP"}, ":8080"]]} }, "User": { "Description": "Administrator user for Jenkins.", "Value": "admin" }, "Password": { "Description": "Password for Jenkins administrator user.", "Value": {"Ref": "JenkinsAdminPassword"} } } }
-
分析
-
这里使用了
AWS:CloudWatch:Alarm
,如下所示。json"RecoveryAlarm": { "Type": "AWS::CloudWatch::Alarm", "Properties": { "AlarmDescription": "Recover server when underlying hardware fails.", "Namespace": "AWS/EC2" , "MetricName": "StatusCheckFailed_System", "Statistic": "Minimum", "Period": "60", "EvaluationPeriods": "5", "ComparisonOperator": "GreaterThanThreshold", "Threshold": "0", "AlarmActions": [{"Fn::Join": ["", ["arn:aws:automate:", { "Ref": "AWS::Region"}, ":ec2:recover"]]}], "Dimensions": [{"Name": "InstanceId", "Value": {"Ref": "Server"}}] } }
这里,设置了
AWS::CloudWatch::Alarm
,每隔60秒检查下ec2
的状态,如有ec2
有问题,那么使用arn:aws:automate:
进行在其他的Available Zone
恢复,但是这里无法让ec2 server
模拟出问题的场合,所以这里不能实际上让arn:aws:automate:ec2:recover
发生。
-
2. 区域(region
),可用区(available zone
)和子网(subnet
)
- 区域(
region
),可用区(available zone
)- 一个区域(
region
)里面,包含多个可用区(available zone
),每个可用区(available zone
)有多个数据中心(DataCenter
)。 - 不同区域(
region
)的之间通过低延时的链路链接。可以想象,在同一个region
的服务之前的网络延时会非常小。
- 一个区域(
- 全球性的服务跨多个区域
- 各种服务的不同区域
- 各种服务的不同区域
VPC
,区域(region
)以及子网(subnet
)VPC
一定会属于一个区域(region
)- 子网(
subnet
)一定属于一个可用区(Availibility Zone
)
3. 使用自动扩展(AutoScalingGroup
)
-
使用自动扩展(
AutoScalingGroup
),可以保证执行数量的虚拟服务器一直运行。-
代码
json{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "(Jenkins (CI server) running with Auto Scaling Group over multiple AZs)", "Parameters": { "KeyName": { "Description": "Key Pair name", "Type": "AWS::EC2::KeyPair::KeyName", "Default": "my-cli-key" }, "JenkinsAdminPassword": { "Description": "Password for Jenkins admin user", "Type": "String", "AllowedPattern" : "[a-zA-Z0-9]*", "MinLength" : "8", "MaxLength" : "42" } }, "Mappings": { "EC2RegionMap": { "ap-northeast-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-cbf90ecb"}, "ap-southeast-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-68d8e93a"}, "ap-southeast-2": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-fd9cecc7"}, "eu-central-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-a8221fb5"}, "eu-west-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-a10897d6"}, "sa-east-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-b52890a8"}, "us-east-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-1ecae776"}, "us-west-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-d114f295"}, "us-west-2": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-e7527ed7"} } }, "Resources": { "VPC": { "Type": "AWS::EC2::VPC", "Properties": { "EnableDnsSupport": "true", "EnableDnsHostnames": "true", "CidrBlock": "10.0.0.0/16", "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "SubnetA": { "Type": "AWS::EC2::Subnet", "Properties": { "VpcId": { "Ref": "VPC" }, "AvailabilityZone": {"Fn::Select": ["0", {"Fn::GetAZs": ""}]}, "CidrBlock": "10.0.0.0/24", "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "SubnetB": { "Type": "AWS::EC2::Subnet", "Properties": { "VpcId": { "Ref": "VPC" }, "AvailabilityZone": {"Fn::Select": ["1", {"Fn::GetAZs": ""}]}, "CidrBlock": "10.0.1.0/24", "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "InternetGateway": { "Type": "AWS::EC2::InternetGateway", "Properties": { "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "GatewayToInternet": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { "VpcId": { "Ref": "VPC" }, "InternetGatewayId": { "Ref": "InternetGateway" } } }, "RouteTable": { "Type": "AWS::EC2::RouteTable", "Properties": { "VpcId": { "Ref": "VPC" }, "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "InternetRoute": { "Type": "AWS::EC2::Route", "Properties": { "RouteTableId": { "Ref": "RouteTable" }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "InternetGateway" } }, "DependsOn": "GatewayToInternet" }, "RouteTableAssociationA": { "Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": { "SubnetId": { "Ref": "SubnetA" }, "RouteTableId": { "Ref": "RouteTable" } } }, "RouteTableAssociationB": { "Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": { "SubnetId": { "Ref": "SubnetB" }, "RouteTableId": { "Ref": "RouteTable" } } }, "NetworkAcl": { "Type": "AWS::EC2::NetworkAcl", "Properties": { "VpcId": { "Ref": "VPC" }, "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "NetworkAceSSH": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "10", "Protocol": "6", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "22", "To": "22" } } }, "NetworkAceJenkinsHTTP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "11", "Protocol": "6", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "8080", "To": "8080" } } }, "NetworkAceNTP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "20", "Protocol": "17", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "123", "To": "123" } } }, "NetworkAceICMP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "30", "Protocol": "1", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "Icmp": { "Code": "-1", "Type": "-1" } } }, "NetworkAceHighPortsTCP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "40", "Protocol": "6", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "1024", "To": "65535" } } }, "NetworkAceHighPortsUDP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "41", "Protocol": "17", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "1024", "To": "65535" } } }, "NetworkAceEgress": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "10", "Protocol": "-1", "RuleAction": "allow", "Egress": "true", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "0", "To": "65535" } } }, "NetworkAclAssociationA": { "Type": "AWS::EC2::SubnetNetworkAclAssociation", "Properties": { "SubnetId": { "Ref": "SubnetA" }, "NetworkAclId": { "Ref": "NetworkAcl" } } }, "NetworkAclAssociationB": { "Type": "AWS::EC2::SubnetNetworkAclAssociation", "Properties": { "SubnetId": { "Ref": "SubnetB" }, "NetworkAclId": { "Ref": "NetworkAcl" } } }, "SecurityGroupJenkins": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "SecurityGroupforjenkins", "VpcId": { "Ref": "VPC" }, "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ], "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "CidrIp": "0.0.0.0/0" }, { "IpProtocol": "tcp", "FromPort": "8080", "ToPort": "8080", "CidrIp": "0.0.0.0/0" }, { "IpProtocol": "icmp", "FromPort": "-1", "ToPort": "-1", "CidrIp": "0.0.0.0/0" } ] } }, "LaunchTemplate": { "Type": "AWS::EC2::LaunchTemplate", "Properties": { "LaunchTemplateName": "LaunchTemplate", "LaunchTemplateData":{ "ImageId": {"Fn::FindInMap": ["EC2RegionMap", {"Ref": "AWS::Region"}, "AmazonLinuxAMIHVMEBSBacked64bit"]}, "KeyName": {"Ref": "KeyName"}, "NetworkInterfaces":[ { "DeviceIndex":0, "AssociatePublicIpAddress":true, "Groups":[ {"Ref": "SecurityGroupJenkins"} ], "DeleteOnTermination":true } ], "InstanceType": "t2.micro", "UserData": { "Fn::Base64": { "Fn::Join": [ "", [ "#!/bin/bash -ex\n", "wget http://pkg.jenkins-ci.org/redhat/jenkins-1.616-1.1.noarch.rpm\n", "rpm --install jenkins-1.616-1.1.noarch.rpm\n", "sed -i -e 's/JENKINS_ARGS=\\\"\\\"/JENKINS_ARGS=\\\"--argumentsRealm.passwd.admin=", {"Ref": "JenkinsAdminPassword"}, " --argumentsRealm.roles.admin=admin\\\"/g' /etc/sysconfig/jenkins\n", "echo \"<?xml version='1.0' encoding='UTF-8'?><hudson><version>1.0</version><useSecurity>true</useSecurity><authorizationStrategy class=\\\"hudson.security.FullControlOnceLoggedInAuthorizationStrategy\\\"/><securityRealm class=\\\"hudson.security.LegacySecurityRealm\\\"/></hudson>\" > /var/lib/jenkins/config.xml\n", "service jenkins start\n" ] ] } } } } }, "AutoScalingGroup": { "Type": "AWS::AutoScaling::AutoScalingGroup", "Properties": { "LaunchTemplate" : {"LaunchTemplateId" : {"Ref" : "LaunchTemplate"},"Version" : {"Fn::GetAtt" : ["LaunchTemplate","LatestVersionNumber"]}}, "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz", "PropagateAtLaunch": true } ], "DesiredCapacity": 1, "MinSize": 1, "MaxSize": 1, "VPCZoneIdentifier": [{"Ref": "SubnetA"}, {"Ref": "SubnetB"}], "HealthCheckGracePeriod": 600, "HealthCheckType": "EC2" }, "DependsOn": "GatewayToInternet" } } }
-
代码解析
AutoScalingGroup
设定了两个subnet
,可以在一个subnet
的EC2 server
出现问题的时候,在另一个subnet
启动另一个EC2 server
。
subnet A
和subnet B
每个subnet
都在不同的Availability Zone
。
-
创建一个
jenkins task
-
删除
jenkins
实例
-
检测
Auto Scaling Group
的动作
可以看到Auto Scaling Group
会马上启动另一个EC2 server
来支持jenkins
服务。
注意,这里,IP
地址和建立的jenkins task
都已经没有了,接下来解决两个问题。 -
-
使用
AMI
进行恢复。-
在现在的
jenkins server
上建立task
-
对当前的
jenkins server
保存镜像shellDell@DESKTOP-DHMQMJG MINGW64 ~/.ssh $ aws ec2 create-image --instance-id i-05593a7ba7b94e566 --name jenkins-multiaz { "ImageId": "ami-01ed9b718c5a467c4" }
-
对
cloudformation
进行更新
*在参数中增加AMISnapshot
,稍后更新CloudFormation
的时候会选择上面建立的AMI
。
-
对
cloudformation
进行更新,LaunchTemplate
里面设定AMI
参数- 在参数中增加
AMISnapshot
,稍后更新CloudFormation
的时候会选择上面建立的AMI
。
- 对
cloudformation
进行更新
- 在参数中增加
-
Cloudformation
更新成功
-
删除当前的
Jenkins server
-
重启之后的
jenkins server
确认可以看到上面建立的
jenkins task
已经保留过来了,原因是使用了AMI
,对当前的EBS
进行了保存。
-
-
cloudformation
代码json{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "AWS in Action: chapter 11 (Jenkins (CI server) running with Auto Scaling Group over multiple AZs)", "Parameters": { "KeyName": { "Description": "Key Pair name", "Type": "AWS::EC2::KeyPair::KeyName", "Default": "my-cli-key" }, "JenkinsAdminPassword": { "Description": "Password for Jenkins admin user", "Type": "String", "AllowedPattern" : "[a-zA-Z0-9]*", "MinLength" : "8", "MaxLength" : "42" }, "AMISnapshot": { "Description": "AMI ID to start virtual server from.", "Type": "String", "AllowedPattern" : "[\u0020-\uD7FF\uE000-\uFFFD\uD800\uDC00-\uDBFF\uDFFF\r\n\t]*", "MinLength" : "1", "MaxLength" : "255" } }, "Resources": { "VPC": { "Type": "AWS::EC2::VPC", "Properties": { "EnableDnsSupport": "true", "EnableDnsHostnames": "true", "CidrBlock": "10.0.0.0/16", "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "SubnetA": { "Type": "AWS::EC2::Subnet", "Properties": { "VpcId": { "Ref": "VPC" }, "AvailabilityZone": {"Fn::Select": ["0", {"Fn::GetAZs": ""}]}, "CidrBlock": "10.0.0.0/24", "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "SubnetB": { "Type": "AWS::EC2::Subnet", "Properties": { "VpcId": { "Ref": "VPC" }, "AvailabilityZone": {"Fn::Select": ["1", {"Fn::GetAZs": ""}]}, "CidrBlock": "10.0.1.0/24", "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "InternetGateway": { "Type": "AWS::EC2::InternetGateway", "Properties": { "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "GatewayToInternet": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { "VpcId": { "Ref": "VPC" }, "InternetGatewayId": { "Ref": "InternetGateway" } } }, "RouteTable": { "Type": "AWS::EC2::RouteTable", "Properties": { "VpcId": { "Ref": "VPC" }, "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "InternetRoute": { "Type": "AWS::EC2::Route", "Properties": { "RouteTableId": { "Ref": "RouteTable" }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "InternetGateway" } }, "DependsOn": "GatewayToInternet" }, "RouteTableAssociationA": { "Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": { "SubnetId": { "Ref": "SubnetA" }, "RouteTableId": { "Ref": "RouteTable" } } }, "RouteTableAssociationB": { "Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": { "SubnetId": { "Ref": "SubnetB" }, "RouteTableId": { "Ref": "RouteTable" } } }, "NetworkAcl": { "Type": "AWS::EC2::NetworkAcl", "Properties": { "VpcId": { "Ref": "VPC" }, "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "NetworkAceSSH": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "10", "Protocol": "6", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "22", "To": "22" } } }, "NetworkAceJenkinsHTTP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "11", "Protocol": "6", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "8080", "To": "8080" } } }, "NetworkAceNTP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "20", "Protocol": "17", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "123", "To": "123" } } }, "NetworkAceICMP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "30", "Protocol": "1", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "Icmp": { "Code": "-1", "Type": "-1" } } }, "NetworkAceHighPortsTCP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "40", "Protocol": "6", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "1024", "To": "65535" } } }, "NetworkAceHighPortsUDP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "41", "Protocol": "17", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "1024", "To": "65535" } } }, "NetworkAceEgress": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "10", "Protocol": "-1", "RuleAction": "allow", "Egress": "true", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "0", "To": "65535" } } }, "NetworkAclAssociationA": { "Type": "AWS::EC2::SubnetNetworkAclAssociation", "Properties": { "SubnetId": { "Ref": "SubnetA" }, "NetworkAclId": { "Ref": "NetworkAcl" } } }, "NetworkAclAssociationB": { "Type": "AWS::EC2::SubnetNetworkAclAssociation", "Properties": { "SubnetId": { "Ref": "SubnetB" }, "NetworkAclId": { "Ref": "NetworkAcl" } } }, "SecurityGroupJenkins": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "SecurityGroupforjenkins", "VpcId": { "Ref": "VPC" }, "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ], "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "CidrIp": "0.0.0.0/0" }, { "IpProtocol": "tcp", "FromPort": "8080", "ToPort": "8080", "CidrIp": "0.0.0.0/0" }, { "IpProtocol": "icmp", "FromPort": "-1", "ToPort": "-1", "CidrIp": "0.0.0.0/0" } ] } }, "LaunchTemplate": { "Type": "AWS::EC2::LaunchTemplate", "Properties": { "LaunchTemplateName": "LaunchTemplate", "LaunchTemplateData":{ "ImageId": {"Ref": "AMISnapshot"}, "KeyName": {"Ref": "KeyName"}, "NetworkInterfaces":[ { "DeviceIndex":0, "AssociatePublicIpAddress":true, "Groups":[ {"Ref": "SecurityGroupJenkins"} ], "DeleteOnTermination":true } ], "InstanceType": "t2.micro", "UserData": { "Fn::Base64": { "Fn::Join": [ "", [ "#!/bin/bash -ex\n", "wget http://pkg.jenkins-ci.org/redhat/jenkins-1.616-1.1.noarch.rpm\n", "rpm --install jenkins-1.616-1.1.noarch.rpm\n", "sed -i -e 's/JENKINS_ARGS=\\\"\\\"/JENKINS_ARGS=\\\"--argumentsRealm.passwd.admin=", {"Ref": "JenkinsAdminPassword"}, " --argumentsRealm.roles.admin=admin\\\"/g' /etc/sysconfig/jenkins\n", "echo \"<?xml version='1.0' encoding='UTF-8'?><hudson><version>1.0</version><useSecurity>true</useSecurity><authorizationStrategy class=\\\"hudson.security.FullControlOnceLoggedInAuthorizationStrategy\\\"/><securityRealm class=\\\"hudson.security.LegacySecurityRealm\\\"/></hudson>\" > /var/lib/jenkins/config.xml\n", "service jenkins start\n" ] ] } } } } }, "AutoScalingGroup": { "Type": "AWS::AutoScaling::AutoScalingGroup", "Properties": { "LaunchTemplate" : {"LaunchTemplateId" : {"Ref" : "LaunchTemplate"},"Version" : {"Fn::GetAtt" : ["LaunchTemplate","LatestVersionNumber"]}}, "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz", "PropagateAtLaunch": true } ], "DesiredCapacity": 1, "MinSize": 1, "MaxSize": 1, "VPCZoneIdentifier": [{"Ref": "SubnetA"}, {"Ref": "SubnetB"}], "HealthCheckGracePeriod": 600, "HealthCheckType": "EC2" }, "DependsOn": "GatewayToInternet" } } }
-
-
使用
elastic IP
进行对网络接口进行固定。IP
地址每次都要发生变化,还是不理想。- 利用
elastic IP
进行网络接口的固定 - 修改的代码
-
设定
IamRole
json"IamRole": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": {"Service": ["ec2.amazonaws.com"] }, "Action": ["sts:AssumeRole"] } ] }, "Path": "/", "Policies": [ { "PolicyName": "root", "PolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Action": ["ec2:AssociateAddress"], "Resource": ["*"], "Effect": "Allow" } ] } } ] } }, "IamInstanceProfile": { "Type": "AWS::IAM::InstanceProfile", "Properties": { "Path": "/", "Roles": [{"Ref": "IamRole"}] } },
-
为
LaunchTemplate
设定IamRole
参数
这里主要是为了给EC2 server
实例设定IamRole
,以便EC2 server
能够执行aws ec2 associate-address
命令,在灾难恢复的时候设定固定的Elastic IP
。
-
更新
cloudformation
堆栈
-
Elastic IP
整体代码json{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "AWS in Action: chapter 11 (Jenkins (CI server) running with Auto Scaling Group over multiple AZs)", "Parameters": { "KeyName": { "Description": "Key Pair name", "Type": "AWS::EC2::KeyPair::KeyName", "Default": "my-cli-key" }, "JenkinsAdminPassword": { "Description": "Password for Jenkins admin user", "Type": "String", "AllowedPattern" : "[a-zA-Z0-9]*", "MinLength" : "8", "MaxLength" : "42" }, "AMISnapshot": { "Description": "AMI ID to start virtual server from.", "Type": "String", "AllowedPattern" : "[\u0020-\uD7FF\uE000-\uFFFD\uD800\uDC00-\uDBFF\uDFFF\r\n\t]*", "MinLength" : "1", "MaxLength" : "255" } }, "Mappings": { "EC2RegionMap": { "ap-northeast-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-cbf90ecb"}, "ap-southeast-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-68d8e93a"}, "ap-southeast-2": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-fd9cecc7"}, "eu-central-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-a8221fb5"}, "eu-west-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-a10897d6"}, "sa-east-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-b52890a8"}, "us-east-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-1ecae776"}, "us-west-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-d114f295"}, "us-west-2": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-e7527ed7"} } }, "Resources": { "VPC": { "Type": "AWS::EC2::VPC", "Properties": { "EnableDnsSupport": "true", "EnableDnsHostnames": "true", "CidrBlock": "10.0.0.0/16", "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "SubnetA": { "Type": "AWS::EC2::Subnet", "Properties": { "VpcId": { "Ref": "VPC" }, "AvailabilityZone": {"Fn::Select": ["0", {"Fn::GetAZs": ""}]}, "CidrBlock": "10.0.0.0/24", "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "SubnetB": { "Type": "AWS::EC2::Subnet", "Properties": { "VpcId": { "Ref": "VPC" }, "AvailabilityZone": {"Fn::Select": ["1", {"Fn::GetAZs": ""}]}, "CidrBlock": "10.0.1.0/24", "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "InternetGateway": { "Type": "AWS::EC2::InternetGateway", "Properties": { "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "GatewayToInternet": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { "VpcId": { "Ref": "VPC" }, "InternetGatewayId": { "Ref": "InternetGateway" } } }, "RouteTable": { "Type": "AWS::EC2::RouteTable", "Properties": { "VpcId": { "Ref": "VPC" }, "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "InternetRoute": { "Type": "AWS::EC2::Route", "Properties": { "RouteTableId": { "Ref": "RouteTable" }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { "Ref": "InternetGateway" } }, "DependsOn": "GatewayToInternet" }, "RouteTableAssociationA": { "Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": { "SubnetId": { "Ref": "SubnetA" }, "RouteTableId": { "Ref": "RouteTable" } } }, "RouteTableAssociationB": { "Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": { "SubnetId": { "Ref": "SubnetB" }, "RouteTableId": { "Ref": "RouteTable" } } }, "NetworkAcl": { "Type": "AWS::EC2::NetworkAcl", "Properties": { "VpcId": { "Ref": "VPC" }, "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ] } }, "NetworkAceSSH": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "10", "Protocol": "6", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "22", "To": "22" } } }, "NetworkAceJenkinsHTTP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "11", "Protocol": "6", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "8080", "To": "8080" } } }, "NetworkAceNTP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "20", "Protocol": "17", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "123", "To": "123" } } }, "NetworkAceICMP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "30", "Protocol": "1", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "Icmp": { "Code": "-1", "Type": "-1" } } }, "NetworkAceHighPortsTCP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "40", "Protocol": "6", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "1024", "To": "65535" } } }, "NetworkAceHighPortsUDP": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "41", "Protocol": "17", "RuleAction": "allow", "Egress": "false", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "1024", "To": "65535" } } }, "NetworkAceEgress": { "Type": "AWS::EC2::NetworkAclEntry", "Properties": { "NetworkAclId": { "Ref": "NetworkAcl" }, "RuleNumber": "10", "Protocol": "-1", "RuleAction": "allow", "Egress": "true", "CidrBlock": "0.0.0.0/0", "PortRange": { "From": "0", "To": "65535" } } }, "NetworkAclAssociationA": { "Type": "AWS::EC2::SubnetNetworkAclAssociation", "Properties": { "SubnetId": { "Ref": "SubnetA" }, "NetworkAclId": { "Ref": "NetworkAcl" } } }, "NetworkAclAssociationB": { "Type": "AWS::EC2::SubnetNetworkAclAssociation", "Properties": { "SubnetId": { "Ref": "SubnetB" }, "NetworkAclId": { "Ref": "NetworkAcl" } } }, "SecurityGroupJenkins": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "SecurityGroupforjenkins", "VpcId": { "Ref": "VPC" }, "Tags": [ { "Key": "Name", "Value": "jenkins-multiaz" } ], "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "CidrIp": "0.0.0.0/0" }, { "IpProtocol": "tcp", "FromPort": "8080", "ToPort": "8080", "CidrIp": "0.0.0.0/0" }, { "IpProtocol": "icmp", "FromPort": "-1", "ToPort": "-1", "CidrIp": "0.0.0.0/0" } ] } }, "IamRole": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": {"Service": ["ec2.amazonaws.com"] }, "Action": ["sts:AssumeRole"] } ] }, "Path": "/", "Policies": [ { "PolicyName": "AttachIP", "PolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Action": ["ec2:AssociateAddress"], "Resource": ["*"], "Effect": "Allow" } ] } } ] } }, "IamInstanceProfile": { "Type": "AWS::IAM::InstanceProfile", "Properties": { "Path": "/", "Roles": [{"Ref": "IamRole"}] } }, "ElasticIP": { "Type": "AWS::EC2::EIP", "Properties": { "Domain": "vpc" }, "DependsOn": "GatewayToInternet" }, "LaunchTemplate": { "Type": "AWS::EC2::LaunchTemplate", "Properties": { "LaunchTemplateName": "LaunchTemplate", "LaunchTemplateData":{ "ImageId": {"Ref": "AMISnapshot"}, "KeyName": {"Ref": "KeyName"}, "IamInstanceProfile": { "Arn": {"Fn::GetAtt": ["IamInstanceProfile","Arn"]}}, "NetworkInterfaces":[ { "DeviceIndex":0, "AssociatePublicIpAddress":true, "Groups":[ {"Ref": "SecurityGroupJenkins"} ], "DeleteOnTermination":true } ], "InstanceType": "t2.micro", "UserData": { "Fn::Base64": { "Fn::Join": [ "", [ "#!/bin/bash -ex\n", "aws configure set default.region ", {"Ref": "AWS::Region"},"\n", "INSTANCE_ID=`curl -s http://169.254.169.254/latest/meta-data/instance-id`\n", "aws ec2 associate-address --instance-id $INSTANCE_ID --allocation-id ", {"Fn::GetAtt": ["ElasticIP", "AllocationId"]}, "\n", "wget http://pkg.jenkins-ci.org/redhat/jenkins-1.616-1.1.noarch.rpm\n", "rpm --install jenkins-1.616-1.1.noarch.rpm\n", "sed -i -e 's/JENKINS_ARGS=\\\"\\\"/JENKINS_ARGS=\\\"--argumentsRealm.passwd.admin=", {"Ref": "JenkinsAdminPassword"}, " --argumentsRealm.roles.admin=admin\\\"/g' /etc/sysconfig/jenkins\n", "echo \"<?xml version='1.0' encoding='UTF-8'?><hudson><version>1.0</version><useSecurity>true</useSecurity><authorizationStrategy class=\\\"hudson.security.FullControlOnceLoggedInAuthorizationStrategy\\\"/><securityRealm class=\\\"hudson.security.LegacySecurityRealm\\\"/></hudson>\" > /var/lib/jenkins/config.xml\n", "service jenkins start\n" ] ] } } } } }, "AutoScalingGroup": { "Type": "AWS::AutoScaling::AutoScalingGroup", "Properties": { "LaunchTemplate" : {"LaunchTemplateId" : {"Ref" : "LaunchTemplate"},"Version" : {"Fn::GetAtt" : ["LaunchTemplate","LatestVersionNumber"]}}, "Tags": [ { "Key": "Name", "Value": "jenkins-elasticip", "PropagateAtLaunch": true } ], "DesiredCapacity": 1, "MinSize": 1, "MaxSize": 1, "VPCZoneIdentifier": [{"Ref": "SubnetA"}, {"Ref": "SubnetB"}], "HealthCheckGracePeriod": 600, "HealthCheckType": "EC2" }, "DependsOn": "GatewayToInternet" } }, "Outputs": { "JenkinsURL": { "Description": "URL to access web interface of Jenkins server.", "Value": {"Fn::Join": ["", ["http://", {"Ref": "ElasticIP"}, ":8080"]]} }, "User": { "Description": "Administrator user for Jenkins.", "Value": "admin" }, "Password": { "Description": "Password for Jenkins administrator user.", "Value": {"Ref": "JenkinsAdminPassword"} } } }
-
Jenkins Server
的IP
地址是Elastic IP
可以看到IP
地址是54.92.85.184
,和Elastic IP
相同的。
- 删除了
Jenkins Server
之后,重新启动的的IP
地址还是Elastic IP
-
-