나 한테 알려줘! (3부: CDK를 사용한 Transit Gateway)
37964 단어 devopstypescriptawstutorial
개요
Transit Gateway (TGW) is a relatively new thing on AWS 그러나 특히 더 복잡한 토폴로지(예: 서로 다른 AWS 지역 및 계정에 걸쳐 있는 수십 또는 수백 개의 VPC)의 경우 네트워킹이 크게 단순화되었습니다.
간단히 말해서 acts as a highly scalable cloud router . A single TGW can support up to 5,000 attachments , 여기서 연결은 VPC, Direct Connect Gateway (DXGW) , VPN 연결 또는 다른 TGW에 대한 피어링 연결일 수 있습니다.
TGW와 VPC 간의 트래픽은 물론 리전 간 트래픽도 계속 유지됩니다the AWS backbone network.
TGW(메시 네트워크, 허브 앤 스포크 네트워크, 공유 서비스가 포함된 격리된 VPC 등)를 사용하기 위한 다양한 시나리오가 있으며 TGW를 사용하지 않고 구축하는 것은 사실상 불가능합니다enterprise-grade infrastructure on AWS.
비용 측면에서 두 가지 비용을 지불합니다: the number of attachments to a TGW (there's an hourly rate) and data transfer .
구현
이 시리즈의 공통 주제인 것처럼 두 개의 VPC를 함께 연결하여 두 VPC에 배치된 EC2 인스턴스 간에 성공적인 ping을 수행할 것입니다. 이번에는 TGW(Transit Gateway)가 접착제가 될 것입니다.
NET에서 생성한
VpcStack
및 InstanceStack
클래스를 다시 한 번 재사용합니다. 또한 두 개의 클래스를 생성합니다. 둘 다 하나의 파일에 존재합니다. 하나는 TGW용이고 다른 하나는 TGW로 연결되는 경로용입니다.➜ ping-me-cdk-example$ touch lib/tgw.ts
ping-me-cdk-example/lib/tgw.ts
import * as ec2 from '@aws-cdk/aws-ec2';
import * as cdk from '@aws-cdk/core';
interface TransitGatewayProps extends cdk.StackProps {
vpcs: [ec2.Vpc, ec2.Vpc, ...ec2.Vpc[]]; // <--- a list of VPC objects (at least two are required) to be attached to the Transit Gateway; NB only routes between the first two VPCs will be created
}
export class TransitGatewayStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props: TransitGatewayProps) {
super(scope, id, props);
// create a Transit Gateway
const tgw = new ec2.CfnTransitGateway(this, 'Tgw');
// For each supplied VPC, create a Transit Gateway attachment
props.vpcs.forEach((vpc, index) => {
new ec2.CfnTransitGatewayAttachment(this, `TgwVpcAttachment${index}`, {
subnetIds: vpc.privateSubnets.map(privateSubnet => privateSubnet.subnetId),
transitGatewayId: tgw.ref,
vpcId: vpc.vpcId,
});
});
// Output the Transit Gateway's ID
new cdk.CfnOutput(this, 'TransitGatewayId', {
value: tgw.ref,
exportName: 'TransitGatewayId',
});
}
}
export class RoutesToTransitGatewayStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props: TransitGatewayProps) {
super(scope, id, props);
// Add route from the private subnet of the first VPC to the second VPC over the Transit Gateway
// NB the below was taken from: https://stackoverflow.com/questions/62525195/adding-entry-to-route-table-with-cdk-typescript-when-its-private-subnet-alread
props.vpcs[0].privateSubnets.forEach(({ routeTable: { routeTableId } }, index) => {
new ec2.CfnRoute(this, 'RouteFromPrivateSubnetOfVpc1ToVpc2' + index, {
destinationCidrBlock: props.vpcs[1].vpcCidrBlock,
routeTableId,
transitGatewayId: cdk.Fn.importValue('TransitGatewayId'), // Transit Gateway must already exist
});
});
// Add route from the private subnet of the second VPC to the first VPC over the Transit Gateway
props.vpcs[1].privateSubnets.forEach(({ routeTable: { routeTableId } }, index) => {
new ec2.CfnRoute(this, 'RouteFromPrivateSubnetOfVpc2ToVpc1' + index, {
destinationCidrBlock: props.vpcs[0].vpcCidrBlock,
routeTableId,
transitGatewayId: cdk.Fn.importValue('TransitGatewayId'), // Transit Gateway must already exist
});
});
}
}
이 네 가지 클래스를 마음대로 사용할 수 있으므로 필요한 스택을 초기화할 수 있습니다.
ping-me-cdk-example/bin/ping-me-cdk-example.ts
import * as cdk from '@aws-cdk/core';
import { VpcStack } from '../lib/vpc';
import { InstanceStack } from '../lib/instance';
import { PeeringStack } from '../lib/peering';
import { CustomerGatewayDeviceStack } from '../lib/cgd';
import { TransitGatewayStack, RoutesToTransitGatewayStack } from '../lib/tgw';
const app = new cdk.App(); // <--- you can read more about the App construct here: https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_core.App.html
/**
* CODE FROM "Ping Me! (Part 1: VPC Peering Using CDK)" AND "Ping Me! (Part 2: Site-to-Site VPN Using CDK)" WAS REMOVED FOR VISIBILITY
*/
// Create two VPCs
const vpcsMetInTransit = new VpcStack(app, 'VpcsMetInTransitStack', {
vpcSetup: {
cidrs: ['10.0.4.0/24', '10.0.5.0/24'], // <--- two non-overlapping CIDR ranges for our two VPCs
maxAzs: 1, // <--- to keep the costs down, we'll stick to 1 availability zone per VPC (obviously, not something you'd want to do in production)
},
});
// Create two EC2 instances, one in each VPC
new InstanceStack(app, 'InstanceTransitStack', {
vpcs: vpcsMetInTransit.createdVpcs,
});
// Create a Transit Gateway and attach both VPCs to it
new TransitGatewayStack(app, 'TransitGatewayStack', {
vpcs: [vpcsMetInTransit.createdVpcs[0], vpcsMetInTransit.createdVpcs[1]],
});
// Create routes between both VPCs over the Transit Gateway
new RoutesToTransitGatewayStack(app, 'RoutesToTransitGatewayStack', {
vpcs: [vpcsMetInTransit.createdVpcs[0], vpcsMetInTransit.createdVpcs[1]],
});
배포는 다음 세 단계로 수행됩니다.
InstanceTransitStack
(암시적으로 VpcsMetInTransitStack
와 함께). (이 단계에서 원본 EC2 인스턴스의 ID와 대상 EC2 인스턴스의 프라이빗 IP를 가져올 수 있습니다.
둘 다 서로 ping을 시도할 때 조금 있으면 유용합니다.)
➜ ping-me-cdk-example$ cdk deploy InstanceTransitStack --require-approval never
Including dependency stacks: VpcsMetInTransitStack
VpcsMetInTransitStack
VpcsMetInTransitStack: deploying...
VpcsMetInTransitStack: creating CloudFormation changeset...
[██████████████████████████████████████████████████████████] (30/30)
✅ VpcsMetInTransitStack
Outputs:
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc07C831B30CidrBlockB8164F9E = 10.0.4.0/24
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc07C831B30DefaultSecurityGroup52C351BF = sg-0b97deeeacfd5627d
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc1C211860BCidrBlock933A5AA8 = 10.0.5.0/24
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc1C211860BDefaultSecurityGroup87C47BC2 = sg-0dfe3c25a0cd42e84
VpcsMetInTransitStack.ExportsOutputRefVpc07C831B304FE08623 = vpc-063e0aaa8aaf32b32
VpcsMetInTransitStack.ExportsOutputRefVpc0privateSubnet1RouteTableB5C6777D52F53FE8 = rtb-053b342d2f9950c58
VpcsMetInTransitStack.ExportsOutputRefVpc0privateSubnet1SubnetD6383522ACB05B9B = subnet-002286581738a15da
VpcsMetInTransitStack.ExportsOutputRefVpc1C211860B64169B74 = vpc-0020c0197873df61c
VpcsMetInTransitStack.ExportsOutputRefVpc1privateSubnet1RouteTable339A93B3DFC75FCA = rtb-0b3cac3abd02c16d6
VpcsMetInTransitStack.ExportsOutputRefVpc1privateSubnet1Subnet41967AFDFF883DAB = subnet-0c10da57ee874b680
Stack ARN:
arn:aws:cloudformation:eu-west-1:REDACTED:stack/VpcsMetInTransitStack/a54b7350-3560-11eb-ae91-0643678755c5
InstanceTransitStack
InstanceTransitStack: deploying...
InstanceTransitStack: creating CloudFormation changeset...
[██████████████████████████████████████████████████████████] (10/10)
✅ InstanceTransitStack
Outputs:
InstanceTransitStack.Instance0BastionHostId1959CA92 = i-03d7c391c35302d4a # <--- COPY THE ID OF YOUR SOURCE EC2 INSTANCE!
InstanceTransitStack.Instance0PrivateIp = 10.0.4.58
InstanceTransitStack.Instance1BastionHostIdEF2AA144 = i-0d315dbb89ed80f82
InstanceTransitStack.Instance1PrivateIp = 10.0.5.54 # <--- COPY THE PRIVATE IP OF YOUR DESTINATION EC2 INSTANCE!
Stack ARN:
arn:aws:cloudformation:eu-west-1:REDACTED:stack/InstanceTransitStack/11f0b6a0-3561-11eb-842c-0aa13688a741
TransitGatewayStack
➜ ping-me-cdk-example$ cdk deploy TransitGatewayStack --require-approval never
Including dependency stacks: VpcsMetInTransitStack
VpcsMetInTransitStack
VpcsMetInTransitStack: deploying...
✅ VpcsMetInTransitStack (no changes)
Outputs:
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc07C831B30CidrBlockB8164F9E = 10.0.4.0/24
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc07C831B30DefaultSecurityGroup52C351BF = sg-0b97deeeacfd5627d
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc1C211860BCidrBlock933A5AA8 = 10.0.5.0/24
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc1C211860BDefaultSecurityGroup87C47BC2 = sg-0dfe3c25a0cd42e84
VpcsMetInTransitStack.ExportsOutputRefVpc07C831B304FE08623 = vpc-063e0aaa8aaf32b32
VpcsMetInTransitStack.ExportsOutputRefVpc0privateSubnet1RouteTableB5C6777D52F53FE8 = rtb-053b342d2f9950c58
VpcsMetInTransitStack.ExportsOutputRefVpc0privateSubnet1SubnetD6383522ACB05B9B = subnet-002286581738a15da
VpcsMetInTransitStack.ExportsOutputRefVpc1C211860B64169B74 = vpc-0020c0197873df61c
VpcsMetInTransitStack.ExportsOutputRefVpc1privateSubnet1RouteTable339A93B3DFC75FCA = rtb-0b3cac3abd02c16d6
VpcsMetInTransitStack.ExportsOutputRefVpc1privateSubnet1Subnet41967AFDFF883DAB = subnet-0c10da57ee874b680
Stack ARN:
arn:aws:cloudformation:eu-west-1:REDACTED:stack/VpcsMetInTransitStack/a54b7350-3560-11eb-ae91-0643678755c5
TransitGatewayStack
TransitGatewayStack: deploying...
TransitGatewayStack: creating CloudFormation changeset...
[██████████████████████████████████████████████████████████] (5/5)
✅ TransitGatewayStack
Outputs:
TransitGatewayStack.TransitGatewayId = tgw-057de86d7c789626e
Stack ARN:
arn:aws:cloudformation:eu-west-1:REDACTED:stack/TransitGatewayStack/e86b7b70-3561-11eb-b82a-0ad12ebbcfd9
RoutesToTransitGatewayStack
➜ ping-me-cdk-example$ cdk deploy RoutesToTransitGatewayStack --require-approval never
Including dependency stacks: VpcsMetInTransitStack
VpcsMetInTransitStack
VpcsMetInTransitStack: deploying...
✅ VpcsMetInTransitStack (no changes)
Outputs:
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc07C831B30CidrBlockB8164F9E = 10.0.4.0/24
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc07C831B30DefaultSecurityGroup52C351BF = sg-0b97deeeacfd5627d
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc1C211860BCidrBlock933A5AA8 = 10.0.5.0/24
VpcsMetInTransitStack.ExportsOutputFnGetAttVpc1C211860BDefaultSecurityGroup87C47BC2 = sg-0dfe3c25a0cd42e84
VpcsMetInTransitStack.ExportsOutputRefVpc07C831B304FE08623 = vpc-063e0aaa8aaf32b32
VpcsMetInTransitStack.ExportsOutputRefVpc0privateSubnet1RouteTableB5C6777D52F53FE8 = rtb-053b342d2f9950c58
VpcsMetInTransitStack.ExportsOutputRefVpc0privateSubnet1SubnetD6383522ACB05B9B = subnet-002286581738a15da
VpcsMetInTransitStack.ExportsOutputRefVpc1C211860B64169B74 = vpc-0020c0197873df61c
VpcsMetInTransitStack.ExportsOutputRefVpc1privateSubnet1RouteTable339A93B3DFC75FCA = rtb-0b3cac3abd02c16d6
VpcsMetInTransitStack.ExportsOutputRefVpc1privateSubnet1Subnet41967AFDFF883DAB = subnet-0c10da57ee874b680
Stack ARN:
arn:aws:cloudformation:eu-west-1:REDACTED:stack/VpcsMetInTransitStack/a54b7350-3560-11eb-ae91-0643678755c5
RoutesToTransitGatewayStack
RoutesToTransitGatewayStack: deploying...
RoutesToTransitGatewayStack: creating CloudFormation changeset...
[██████████████████████████████████████████████████████████] (4/4)
✅ RoutesToTransitGatewayStack
Stack ARN:
arn:aws:cloudformation:eu-west-1:REDACTED:stack/RoutesToTransitGatewayStack/d803d8d0-3562-11eb-aaeb-02e586bc56f0
확인
이제 핑을 풀어볼 시간입니다!
따라하는 경우 아래를 실행하기 전에 원본 EC2 인스턴스(
i-03d7c391c35302d4a
)의 ID와 대상 EC2 인스턴스(10.0.5.54
)의 프라이빗 IP를 적절한 값으로 교체해야 합니다.aws ssm send-command \
--document-name "AWS-RunShellScript" \
--document-version "1" \
--targets '[{"Key":"InstanceIds","Values":["i-03d7c391c35302d4a"]}]' \
--parameters '{"workingDirectory":[""],"executionTimeout":["3600"],"commands":["ping 10.0.5.54 -c 3"]}' \
--timeout-seconds 600 \
--max-concurrency "50" \
--max-errors "0"
{
"Command": {
"CommandId": "f7ed8e0e-a313-405a-a811-7885b4d532e7",
"DocumentName": "AWS-RunShellScript",
"DocumentVersion": "1",
"Comment": "",
"ExpiresAfter": "2020-12-03T15:06:43.691000+01:00",
"Parameters": {
"commands": [
"ping 10.0.5.54 -c 3"
],
"executionTimeout": [
"3600"
],
"workingDirectory": [
""
]
},
"InstanceIds": [],
"Targets": [
{
"Key": "InstanceIds",
"Values": [
"i-03d7c391c35302d4a"
]
}
],
"RequestedDateTime": "2020-12-03T13:56:43.691000+01:00",
"Status": "Pending",
"StatusDetails": "Pending",
"OutputS3BucketName": "",
"OutputS3KeyPrefix": "",
"MaxConcurrency": "50",
"MaxErrors": "0",
"TargetCount": 0,
"CompletedCount": 0,
"ErrorCount": 0,
"DeliveryTimedOutCount": 0,
"ServiceRole": "",
"NotificationConfig": {
"NotificationArn": "",
"NotificationEvents": [],
"NotificationType": ""
},
"CloudWatchOutputConfig": {
"CloudWatchLogGroupName": "",
"CloudWatchOutputEnabled": false
},
"TimeoutSeconds": 600
}
}
이제 AWS CLI
aws ssm get-command-invocation
command를 사용하여 성공했는지 확인하겠습니다.다시 말하지만, 따라하는 경우 아래를 실행하기 전에 명령 ID(
f7ed8e0e-a313-405a-a811-7885b4d532e7
)와 소스 EC2 인스턴스의 ID( i-03d7c391c35302d4a
)를 적절한 값으로 바꿔야 합니다.➜ ping-me-cdk-example$ aws ssm get-command-invocation --command-id f7ed8e0e-a313-405a-a811-7885b4d532e7 --instance-id i-03d7c391c35302d4a
{
"CommandId": "f7ed8e0e-a313-405a-a811-7885b4d532e7",
"InstanceId": "i-03d7c391c35302d4a",
"Comment": "",
"DocumentName": "AWS-RunShellScript",
"DocumentVersion": "1",
"PluginName": "aws:runShellScript",
"ResponseCode": 0,
"ExecutionStartDateTime": "2020-12-03T12:56:44.343Z",
"ExecutionElapsedTime": "PT2.044S",
"ExecutionEndDateTime": "2020-12-03T12:56:46.343Z",
"Status": "Success",
"StatusDetails": "Success",
"StandardOutputContent": "PING 10.0.5.54 (10.0.5.54) 56(84) bytes of data.\n64 bytes from 10.0.5.54: icmp_seq=1 ttl=254 time=0.489 ms\n64 bytes from 10.0.5.54: icmp_seq=2 ttl=254 time=0.311 ms\n64 bytes from 10.0.5.54: icmp_seq=3 ttl=254 time=0.306 ms\n\n--- 10.0.5.54 ping statistics ---\n3 packets transmitted, 3 received, 0% packet loss, time 2027ms\nrtt min/avg/max/mdev = 0.306/0.368/0.489/0.087 ms\n",
"StandardOutputUrl": "",
"StandardErrorContent": "",
"StandardErrorUrl": "",
"CloudWatchOutputConfig": {
"CloudWatchLogGroupName": "",
"CloudWatchOutputEnabled": false
}
}
3 packets transmitted, 3 received, 0% packet loss
. 그것은 놀라운 성공입니다!대청소
지갑을 위해 모든 것을 마무리하기 전에 현재 인프라를 즉시 파괴합시다.
구축 과정의 경우와 마찬가지로 파괴 부분도 단계적으로 수행되어야 합니다.
y
를 입력합니다(예).➜ ping-me-cdk-example$ cdk destroy RoutesToTransitGatewayStack
Are you sure you want to delete: RoutesToTransitGatewayStack (y/n)? y
RoutesToTransitGatewayStack: destroying...
14:08:49 | DELETE_IN_PROGRESS | AWS::CloudFormation::Stack | RoutesToTransitGatewayStack
14:08:51 | DELETE_IN_PROGRESS | AWS::EC2::Route | RouteFromPrivateSubnetOfVpc2ToVpc10
✅ RoutesToTransitGatewayStack: destroyed
y
를 입력합니다(예).➜ ping-me-cdk-example$ cdk destroy --all
Are you sure you want to delete: InstanceVpnDestinationStack, VpcVpnDestinationStack, TransitGatewayStack, RoutesToTransitGatewayStack, PeeringStack, InstanceTransitStack, InstancePeersStack, CustomerGatewayDeviceStack, VpcsMetInTransitStack, VpcVpnSourceStack, VpcPeersStack (y/n)? y
InstanceVpnDestinationStack: destroying...
✅ InstanceVpnDestinationStack: destroyed
VpcVpnDestinationStack: destroying...
✅ VpcVpnDestinationStack: destroyed
TransitGatewayStack: destroying...
14:12:23 | DELETE_IN_PROGRESS | AWS::CloudFormation::Stack | TransitGatewayStack
✅ TransitGatewayStack: destroyed
RoutesToTransitGatewayStack: destroying...
✅ RoutesToTransitGatewayStack: destroyed
PeeringStack: destroying...
✅ PeeringStack: destroyed
InstanceTransitStack: destroying...
14:15:30 | DELETE_IN_PROGRESS | AWS::CloudFormation::Stack | InstanceTransitStack
✅ InstanceTransitStack: destroyed
InstancePeersStack: destroying...
✅ InstancePeersStack: destroyed
CustomerGatewayDeviceStack: destroying...
✅ CustomerGatewayDeviceStack: destroyed
VpcsMetInTransitStack: destroying...
14:16:49 | DELETE_IN_PROGRESS | AWS::CloudFormation::Stack | VpcsMetInTransitStack
14:18:56 | DELETE_IN_PROGRESS | AWS::EC2::InternetGateway | Vpc0/IGW
14:18:56 | DELETE_IN_PROGRESS | AWS::EC2::VPC | Vpc0
✅ VpcsMetInTransitStack: destroyed
VpcVpnSourceStack: destroying...
✅ VpcVpnSourceStack: destroyed
VpcPeersStack: destroying...
✅ VpcPeersStack: destroyed
결론
이 기사 시리즈에서는 어떻게 비교적 쉽게 사용Cloud Development Kit (CDK)하여 다양한 AWS 리소스를 생성, 업데이트 및 삭제하고 요구 사항에 가장 적합한 구성으로 모두 결합할 수 있는지 살펴보았습니다.
IaC(Infrastructure as Code)와 같은 것들에 신경을 쓰는 이유에 대해 논의했습니다.
에서 우리는 첫 번째 클래스를 작성한 다음 스택으로 초기화했습니다.
AWS CLI를 통한 추가 구성이 필요한 보다 복잡한 구조에 중점을 두었습니다.
마지막 부분은 가장 멋진 AWS 네트워크 리소스 중 하나인 TGW(Transit Gateway)를 중심으로 이루어졌습니다.
all of the code is available on GitHub 을 기억하십시오.
"그게 다야!"즐겁게 읽으셨기를 바라며 다음 시간까지!
Reference
이 문제에 관하여(나 한테 알려줘! (3부: CDK를 사용한 Transit Gateway)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/aws-builders/ping-me-part-3-transit-gateway-using-cdk-18bf텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)