CDK - Resources

 

Referencing Resources

많은 AWS CDK classes 들은 props 로 AWS CDK resource object를 참조할 수 있습니다.

  • By passing the resource directly
  • By passing the resource's unique identifier, which is typically an ARN, but it could also be an ID or a name


예를 들어, ECS 서비스는 ecs.ICluster 타입의 cluster 속성을 사용합니다. 

모든 리소스는 해당 인터페이스를 구현하므로, AWS CDK 앱에서 정의한 모든 리소스를 직접 전달할 수 있습니다.

const cluster = new ecs.Cluster(this'Cluster', { /* ... */ });
const service = new ecs.Ec2Service(this'Service', { cluster: cluster });

Accessing Resource in a Different Stack

동일한 계정, 리전에 있는 다른 스택의 리소스에 엑세스 할 수 있습니다.  

예제는 아래와 같습니다.

const prod = { account: '123456789012', region: 'us-east-1' };
 
const stack1 = new StackThatProvidesABucket(app, 'Stack1' , { env: prod });
 
// stack2 will take a property { bucket: IBucket }
const stack2 = new StackThatExpectsABucket(app, 'Stack2', {
  bucket: stack1.bucket,
  env: prod
});

Physical Names

CloudFormation 에서의 리소스의 논리적 이름은 리소스를 배포한 후 AWS Management Console 에 표시되는 리소스 이름과 다릅니다.

AWS CDK는 이러한 최종 이름을 물리적 이름이라고 합니다.

<resourceType>Name 속성을 이용해서 물리적 이름을 지정할 수 있습니다.

다음 예제는 my-bucket-name이 물리적 이름은 S3 버킷을 생성합니다.

const bucket = new s3.Bucket(this'MyBucket', {
  bucketName: 'my-bucket-name',
});


물리적 이름을 리소스에 할당하면 몇가지 단점이 있습니다.

리소스의 변경이 필요한 immutable 속성을 배포된 이후에 변경에 실패합니다. 

그러한 경우에 유일한 해결책은 AWS CloudFormation stack을 지우고 새로 배포하는 것입니다.

하지만 어떤 경우에는 CDK 가 올바르게 작동하려면 물리적인 이름이 필요합니다.

이러한 경우에는 PhysicalName.GENERATE_IF_NEEDED 값을 사용할 수 있습니다.

const bucket = new s3.Bucket(this'MyBucket', {
  bucketName: core.PhysicalName.GENERATE_IF_NEEDED,
});

Passing Unique Identifiers

가능한 경우라면 위의 설명들대로 참조로 리소스를 전달해야 합니다.

그러나 속성중 하나를 선택하여 리소스를 참조해야 할 수 밖에 없는 경우도 있습니다.

예를 들어 저수준 AWS CloudFormation 리소스를 사용하거나 Lambda 함수의 환경 변수로 참조할 때와 같이 런타임 구성요소에 리소스를 노출해야하는 경우 입니다.

이러한 경우 다음과 같인 리소스의 속성으로 식별자를 사용 가능합니다.

bucket.bucketName
lambdaFunc.functionArn
securityGroup.groupArn


다음 예제는 생성된 버킷 이름을 AWS Lambda 함수에 전달하는 방법을 보여줍니다.

const bucket = new s3.Bucket(this'Bucket');
 
new lambda.Function(this'MyLambda', {
  /* ... */,
  environment: {
    BUCKET_NAME: bucket.bucketName,
  },
});

Importing Existing External Resources

때때로 AWS 계정에 리소스가 이미 있고, aws CDK 에서 사용하려는 경우가 있습니다.

이 경우에 리소스 클래스의 static factory methods 를 호출하여 현재 stack의 awc CDK object로 전환 할수 있습니다.

// Construct a resource (bucket) just by its name (must be same account)
s3.Bucket.fromBucketName(this'MyBucket''my-bucket-name');
 
// Construct a resource (bucket) by its full ARN (can be cross account)
s3.Bucket.fromArn(this'MyBucket''arn:aws:s3:::my-bucket-name');
 
// Construct a resource by giving attribute(s) (complex resources)
ec2.Vpc.fromVpcAttributes(this'MyVpc', {
  vpcId: 'vpc-1234567890abcde',
});


ec2.Vpc 구성의 경우 복잡하고  VPC 자체, 서브넷, 보안 그룹 및 라우팅 테이블과 같은 많은 AWS 리소스로 구성되기 때문에 속성을 사용하여 해당 리소스를 가져오기가 어려울수 있습니다.

이를 해결하기 위해 VPC 구성에는 fromLookup 메소드가 있고, fromLookup 메소드는 context 메소드를 이용해 합성시 필요한 모든 속성을 해결하고 cdk.context.json에서 나중에 사용할 수 있도록 값을 캐시할 수 있습니다. 

aws 계정에서 VPC를 고유하게 식별하기에 충분한 속성을 제공해야 합니다. 예를 들어 기본 VPC는 하나만 있다면 기본값으로 표시된 VPC 로 지정하면 충분합니다.

ec2.Vpc.fromLookup(this'DefaultVpc', {
  isDefault: true
});

tags 속성을 사용하여 태그별로 쿼리할 수 있습니다. 

태그는  VPC 에 추가될 수 있으며, 언제든 편집할 수 있습니다.  

직접 추가한 태그 외에도 AWS CDK는 생성된 모든 VPC에 다음 태그를 자동으로 추가합니다.

  • Name – The name of the VPC.

  • aws-cdk:subnet-name – The name of the subnet.

  • aws-cdk:subnet-type – The type of the subnet: Public, Private, or Isolated.

ec2.Vpc.fromLookup(this'PublicVpc',
    {tags: {'aws-cdk:subnet-type'"Public"}});
});

Vpc.fromLookup() 은 env 속성에 명시된 계정과 지역으로 정의된 스택에서만 작동합니다. 

가져온 리소스를 어디에서나 사용할 수 있지만 가져온 리소스를 수정할 수 없습니다.

예를 들어 imported 한 s3.IBucket 에서 addToResourcePolicy를 호출하면 아무 작업도 수행되지 않습니다.

Permission Grants

많은 AWS constructs는 하나 이상의 IAM 권한 설명을 수동으로 만들지 않고도 IAM 역할 또는 IAM 사용자와 같은 entity를 쉽게 부여할수 있는 grant 메소드를 제공합니다.

if (bucket.grantReadWrite(func).success) {
  // ...
}

grant 메소드는 iam.Grant object를 반환합니다.

Grant object의 success 속성을 사용하여 grant가 효과적으로 적용되었는지 여부를 판별할 수 있습니다. ( 적용이 안될수도 있음 )

assertSuccess 메소드를 사용하여 권한 부여가 성공적으로 되도록 할수도 있습니다.


만약에 특정 grant 메소드가 특정한 경우에 이용가능하지 않다면, 일반 grant 메소드를 사용하여 지정된 작업 목록에 권한 부여를 정의 할 수도 있습니다.

다음 예제는 lambda 함수에 dynamodb createBackup 작업에 대한 액세스 권한을 부여하는 방법을 보여줍니다.

table.grant(func, 'dynamodb:CreateBackup');


람다 함수와 같은 많은 리소스는 코드를 실행할때 역할을 맡아야 합니다.

configuration 속성을 사용하면 특정 iam.IRole 을 지정할 수 있습니다. 

역할을 지정하지 않으면 람다 함수는 자동으로 role 을 만들어 지정합니다.

그 이후에 grant 메소드를 이용하여 리소스에 role 을 추가할수 있습니다.

grant 메소드는 iam 정책들을 다루기 위해 low-level api로 작성됩니다. 

정책들은 PolicyDocument object 로써 모데링 됩니다.

 addToRolePolicy method 또는 addToResourcePolicy method를 사용하세요.

Metrics and Alarms

많은 리소스가 모니터링 대시 보드 및 경보(alarm)를 설정하는데 cloudwatch 지표를 생성합니다.

aws constructs 는 정확한 이름을 찾을 필요 없이 지표에 쉽게 액세스 할 수 있는 metric methods가 있습니다.

다음 예제는 Amazon SQS 대기열의 ApproximateNumberOfMessageNotVisible 이 100을 초과 할 때 경보(alarm)를 정의하는 방법을 보여줍니다.


import cw = require('@aws-cdk/aws-cloudwatch');
import sqs = require('@aws-cdk/aws-sqs');
import { Duration } from '@aws-cdk/core';
 
const queue = new sqs.Queue(this'MyQueue');
 
const metric = queue.metricApproximateNumberOfMessagesNotVisible({
  label: 'Messages Visible (Approx)',
  period: Duration.minutes(5),
  // ...
});
metric.createAlarm(this'TooManyMessagesAlarm', {
  comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD,
  threshold: 100,
  // ...
});

특정 constructs에 metric 메소드가 없는 경우에는 일반적인 metric 방법을 사용하여 이름을 수동으로 지정할 수 있습니다.

metric(지표)는 cloudWatch 대시보드에 추가될 수 있습니다.

Network Traffic

연결을 설정하거나 수신하는 리소스는 보안그룹 규칙 또는 NACL을 설정을 포함하여 traffic flows를 가능하게 하는 방법을 노출합니다.

IConnectable 리소스에는 네트워크 트래픽 규칙 구성의 게이트웨이인 연결 속성이 있습니다.

allow 메소드를 사용해서 네트워크 경로로 데이터가 흐르도록 합니다.

다음 예제는 웹에 대한 HTTPS 연결과 Amazon EC2 Auto Scaling 그룹 fleet2에서 들어오는 연결을 활성화합니다.

import asg = require('@aws-cdk/aws-autoscaling');
import ec2 = require('@aws-cdk/aws-ec2');
 
const fleet1: asg.AutoScalingGroup = /* ... */
 
// Allow surfing the (secure) web
fleet1.connections.allowTo(new ec2.Peer.anyIpv4(), new ec2.Port({ fromPort: 443, toPort: 443 }));
 
const fleet2: asg.AutoScalingGroup = /* ... */;
fleet1.connections.allowFrom(fleet2, ec2.Port.AllTraffic());


특정 리소스에는 기본 포트와 데이터베이스 엔진이 amazon RDS 데이터베이스 인스탄스에 대한 연결을 허용하는 포트가 있습니다.

이러한 경우 아래 메소드를 이용하여 수동으로 포트를 지정하지 않고도 엄격한 네트워크 제어를 시행할 수 있습니다.

  • allowDefaultPortFrom
  • allowToDefaultPort

다음 예제는 모든 IPV4 주소에서 연결을 설정하고 Auto Scailing 그룹에서 연결하여 데이터베이스에 액세스하는 방법을 보여줍니다.

listener.connections.allowDefaultPortFromAnyIpv4('Allow public access');
 
fleet.connections.allowToDefaultPort(rdsDatabase, 'Fleet can access database');

Amazon CloudWatch Events

일부 리소스는 이벤트 소스를 동작시킬 수 있습니다.

addEventNotification 메소드를 사용하여 자원이 생성한 특정 이벤트 유형에 이벤트 대상을 등록하십시오.

이 이외에도 addXXXNotification 메소드는 공통 이벤트 유형에 대한 핸들러를 등록하는 간단한 방법입니다.

다음 예제는 객제가 S3 버킷에 추가될 때 lambda 함수를 트리거하는 방법을 보여줍니다.

import s3nots = require('@aws-cdk/aws-s3-notifications');
 
const handler = new lambda.Function(this'Handler', { /*…*/ });
const bucket = new s3.Bucket(this'Bucket');
bucket.addObjectCreatedNotification(new s3nots.LambdaDestination(handler));

댓글

이 블로그의 인기 게시물

dailyFocus - Frontend

CDK - Assets

About VPC