[Serverless Framework] Function

bluewhale·2021년 12월 29일
0

Serverless Framework

목록 보기
2/2
post-thumbnail

Configurations

Permissions

Serverless Framework에서는 IAM 설정을 통해 AWS Lambda의 실행 권한(Execution Role)을 확장할 수 있다.

Serverless Framework를 통해 배포되는 AWS Lambda 함수는, 기본적으로 CloudWatch의 LogStream 및 LogGroup에 대한 생성/쓰기 권한을 부여받는다. 만약, 사용자가 VPC 관련 설정을 추가한 경우, VPC 내부 통신을 위해 AWSLambdaVPCAccessExecutionRole 권한이 추가로 부여된다.

사용자는 provider.iam.role.statements 경로에 IAM 정책들을 추가함으로써 기본적으로 제공되는 IAM 권한을 확장할 수 있다.

	
# serverless.yml
service: myService
 
provider:
  name: aws
  runtime: nodejs12.x
  iam:
    role:
      statements: # permissions for all of your functions can be set here
        - Effect: Allow
          Action: # Gives permission to DynamoDB tables in a specific region
            - dynamodb:DescribeTable
            - dynamodb:Query
            - dynamodb:Scan
            - dynamodb:GetItem
            - dynamodb:PutItem
            - dynamodb:UpdateItem
            - dynamodb:DeleteItem
          Resource: 'arn:aws:dynamodb:us-east-1:*:*'

혹은, 이미 생성된 IAM의 ARN을 명시하여 사용할 수도 있다.

# serverless.yml
service: new-service

provider:
  name: aws
  iam:
    role: arn:aws:iam::YourAccountNumber:role/YourIamRole

Architecture

AWS Lambda는 기본적으로 64-bit x86 아키텍처 CPU에서 실행된다. 2021년 9월 말부터, 주요 리전에서 AWS Lambda에서 arm64 아키텍처 기반의 AWS Graviton2 processor를 정식으로 지원하기 시작하였다. AWS에 따르면 Graviton2 프로세서는 64-bit x86 CPU와 비교하여 가격 대비 성능이 약 34% 향상되었다고 한다.

Serverless Framework에서는 아래와 같이 lambda runtime이 실행될 CPU 아키텍처를 수정할 수 있다.

provider:
  ...
  architecture: arm64

아래와 같이 각 Function에 대해서 CPU 아키텍처를 세부적으로 설정하는 것도 가능하다. 이 경우, provider scope에서 선언된 값을 덮어쓴다.

functions:
  hello:
    ...
    architecture: arm64

VPC Configuration

AWS Lambda and Hyperplane ENI

AWS에서는 Lambda 서비스를 특정 VPC와 연결하여, 해당 VPC의 프라이빗 서브넷에 배포된 리소스들과 통신하도록 설정할 수 있다. 뿐만 아니라, VPC의 NAT Gateway를 활용해 Lambda의 Outbound IP를 고정하여 IP 화이트 리스트 보안 등에 활용할 수 있다.

Lambda는 기본적으로 Lambda가 소유한 secure VPC에 독립적으로 배포된다. 따라서, Lambda는 secure VPC와 사용자의 VPC를 연결하기 위해, 사용자의 VPC 내부 서브넷에 Hyperplane ENI를 생성한다. Hyperplane ENI는 Lambda가 생성/관리하는 ENI로, 사용자의 VPC와 통신하기 위한 VPC-to-VPC NAT(V2N) 역할을 한다.

Hyperplane ENI은 서브넷/보안그룹의 조합 별로 각각 생성되며, 최초 생성 시, 수 분이 소요된다. Hyperplane ENI가 생성되기 전까지, Lambda 함수에 대한 모든 요청은 실패한다.

따라서, Serverless Framework에서 VPC 관련 설정을 최초로 추가한 경우, Lambda 함수가 준비되기까지 다소 시간이 소요될 수 있다. 다행히도, 기존 VPC 관련 설정을 수정한 경우에는, 새로운 Hyperplane ENI가 모두 생성된 후, 기존의 ENI를 삭제하기 때문에 중단이 발생하지 않는다.

Execution Role

이처럼, Lambda를 VPC에 연결하기 위해서는 Lambda의 실행 권한에 Hyperplane ENI를 생성하기 위한 다음의 권한이 필수적으로 요구된다.

  • ec2:CreateNetworkInterface
  • ec2:DescribeNetworkInterfaces
  • ec2:DeleteNetworkInterface

위 권한들은 AWSLambdaVPCAccessExecutionRole에 포함되어 있다. Serverless Framework는 서비스에 VPC 관련 설정을 추가한 경우에 Lambda의 실행 권한에 자동으로 AWSLambdaVPCAccessExecutionRole 규칙을 추가하여 ENI 관련 작업을 실행할 수 있도록 한다.

또한, AWS Lambda에 VPC 관련 설정을 추가하기 위해서는 사용자의 IAM 계정에 다음의 권한이 요구된다.

  • ec2:DescribeSecurityGroups
  • ec2:DescribeSubnets
  • ec2:DescribeVpcs

Internet access

Lambda를 VPC에 연결할 때에는 일반적으로 인터넷 접근이 막힌 프라이빗 서브넷과 연결된다. 따라서, Lambda가 인터넷에 접근하기 위해서는 NAT Gateway를 거쳐야 한다. 따라서, 이와 관련된 라우팅 테이블 등의 규칙을 적절히 설정하여야 한다.

VPC와 연결된 Lambda 함수가 S3DynamoDB에 접근하기 위해서는, VPC Endpoint를 필요로 한다.

Example

Serverless Framework에서는 provider.vpc 혹은 functions[].<function-name>.vpc 키를 통해 VPC 관련 설정을 추가할 수 있다.

# serverless.yml
service: service-name
provider:
  name: aws
  vpc:
    securityGroupIds:
      - securityGroupId1
      - securityGroupId2
    subnetIds:
      - subnetId1
      - subnetId2
 
functions:
  hello: # this function will overwrite the service level vpc config above
    handler: handler.hello
    vpc:
      securityGroupIds:
        - securityGroupId1
        - securityGroupId2
      subnetIds:
        - subnetId1
        - subnetId2
  users: # this function will inherit the service level vpc config above
    handler: handler.users

Environment Variables

Serverles Framework에서는 Lambda 런타임에 필요한 환경변수를 아래와 같이 선언할 수 있다.

# serverless.yml
service: service-name
provider:
  name: aws
  environment:
    SYSTEM_NAME: mySystem
    TABLE_NAME: tableName1
 
functions:
  hello:
    # this function will have SYSTEM_NAME=mySystem and TABLE_NAME=tableName1 from the provider-level environment config above
    handler: handler.hello
  users:
    # this function will have SYSTEM_NAME=mySystem from the provider-level environment config above
    # but TABLE_NAME will be tableName2 because this more specific config will override the default above
    handler: handler.users
    environment:
      TABLE_NAME: tableName2
profile
안녕하세요

0개의 댓글