Terraform을 사용하여 AWS Lambda를 VPC에 배포
36958 단어 tutorialawsserverlessterraform
VPC에서 Lambda를 실행하면 다음과 같은 단점이 있습니다.
전용 서브넷에서 Lambda를 사용할 수 있도록 대량의 AWS 자원을 만들고 설정해야 한다는 것을 감안하면, Lambda를 정확하게 사용하는 것은 도전일 수 있습니다. 특히 네트워크 엔지니어가 아니라면.나는 확실히 약간의 시간을 들여서야 비로소 이해했다.
인터넷상의 많은 강좌는 AWS 콘솔을 사용하여 자원을 제공하는 과정을 설명한다.빠른 실험에 있어서는 충분할 수도 있지만, 더 장기적인 프로젝트에 대해서는 인프라를 코드로 정의하는 데 시간을 들여야 할 수도 있습니다.
만약 당신이 Terraform을 사용한다면, 이 글은 당신에게 유용할 것입니다.
기본적이고 비VPC인 람다 테라폼 모듈부터 OUBOND(인터넷) 접속이 있는 VPC에서 이 기능을 실행하는 한 걸음 한 걸음 발자국으로 업그레이드한다.
선결 조건
따라가려면 다음이 필요합니다.
일부 AWS 리소스는 비용을 발생시킬 수 있으므로 NAT 게이트웨이의 경우 월별로 약 32달러가 소요됩니다.
영토로 돌아가다
Terraform을 사용하여 표준 Lambda 함수를 만들고 먼저 작동할지 확인합니다.이 함수는 Node 소절을 실행합니다.js 코드.인터넷과의 연결을 테스트하고자 하므로 이 함수는 타사 API에서 일부 데이터를 가져옵니다.신뢰성을 높이기 위해, 우리는 무작위 Chuck Norris 사실을 제공하는 API와 통합할 것이다. (비록 낡았지만 여전히 좋다.)
When Chuck Norris enters a room, he doesn't turn the lights on, he turns the dark off.
Lambda 사이즈
const https = require('https')
exports.handler = async function () {
const res = await fetch('https://api.chucknorris.io/jokes/random')
const randomFact = JSON.parse(res).value
return randomFact
}
async function fetch(url) {
return new Promise((resolve, reject) => {
const request = https.get(url, { timeout: 1000 }, (res) => {
if (res.statusCode < 200 || res.statusCode > 299) {
return reject(new Error(`HTTP status code ${res.statusCode}`))
}
const body = []
res.on('data', (chunk) => body.push(chunk))
res.on('end', () => {
const resString = Buffer.concat(body).toString()
resolve(resString)
})
})
request.on('error', (err) => reject(err))
request.on('timeout', (err) => {
console.log('timed out', err)
reject(err)
})
})
}
코드는 간단합니다. API에서 무작위 사실을 가져와 호출자에게 되돌려줍니다.간단하게 보기 위해서, 나는 어떠한 의존항도 추가하고 싶지 않으며, 본 기기
https
노드 모듈을 사용하여 요청합니다.Lambda 지형 모듈
우리는 두 가지 변수로부터 시작한다.
project
는 자원 이름의 접두사로 사용되고,region은 자원이 배치될 곳이다.# terraform/variables.tf
variable "project" {
type = string
description = "Project name"
}
variable "region" {
type = string
description = "Azure region"
default = "us-east-1"
}
만약 Terraform으로 Lambda를 배치한다면, 어떠한 의외의 일도 없을 것이다.최소 리소스 세트에는 호스팅AWSLambdaBasicExecutionRole
정책이 추가된 IAM 역할, 함수 자체, Lambda에 코드를 업로드하는 아카이브가 포함됩니다.코드를 변경할 때마다 ZIP 파일의 해시 값이 변경되고 Lambda 코드는 Terraform에서 업데이트됩니다.현실 세계에서, 코드 업데이트를 Lambda로 전송하기 위해 CI/CD 파이프를 설정해야 할 수도 있습니다.# terraform/main.tf
provider "aws" {
profile = "default"
region = var.region
}
provider "archive" {}
data "archive_file" "lambda" {
type = "zip"
source_dir = "../lambda"
output_path = "lambda.zip"
}
data "aws_iam_policy_document" "AWSLambdaTrustPolicy" {
version = "2012-10-17"
statement {
actions = ["sts:AssumeRole"]
effect = "Allow"
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
}
}
resource "aws_iam_role" "iam_role" {
assume_role_policy = data.aws_iam_policy_document.AWSLambdaTrustPolicy.json
name = "${var.project}-iam-role-lambda-trigger"
}
resource "aws_iam_role_policy_attachment" "iam_role_policy_attachment_lambda_basic_execution" {
role = aws_iam_role.iam_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
resource "aws_lambda_function" "lambda_function" {
code_signing_config_arn = ""
description = ""
filename = data.archive_file.lambda.output_path
function_name = "${var.project}-lambda-function"
role = aws_iam_role.iam_role.arn
handler = "index.handler"
runtime = "nodejs14.x"
source_code_hash = filebase64sha256(data.archive_file.lambda.output_path)
}
지상파 0시를 AWS에 배포
AWS CLI 이미지를 기반으로 dev Docker 컨테이너를 시작합니다.
docker run --rm -it -v $(pwd):/var/app -w /var/app --entrypoint bash amazon/aws-cli
Terraform에서 사용할 AWS 자격 증명(액세스 키 ID, 비밀 액세스 키)을 다음과 같이 구성합니다.aws configure
Terraform 설치:yum install -y yum-utils
yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo
yum -y install terraform
배포 모듈:cd terraform
terraform init
terraform apply
Lambda가 올바르게 작동하는지 확인합니다.aws lambda invoke --function-name lambda-vpc-tf-lambda-function out.txt
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
cat out.txt
"If you spell Chuck Norris in Scrabble, you win. Forever."
전용 네트워크 리소스
준비를 잘하면 많은 자원이 있을 것이다.하지만 Terraform의 도움말은 매우 큽니다. 클라우드formation에서 같은 효과 설정을 검사하면 더욱 상세해질 것입니다.
높은 수준에서 2개의 서브넷을 포함하는 새 VPC를 만듭니다.하나는 공공(인터넷으로 통하는 노선이 있음)이고, 다른 하나는 개인(직접적인 노선이 없음)이다.Lambda를 VPC에 연결하는 방법은 최소한의 개인 서브넷과 연결하는 것이다.이 기능을 사용하면 독점 네트워크의 리소스에 액세스할 수 있습니다.그러나 아직 개방된 연결은 없다.이렇게 하려면 NAT 구성 요소가 필요합니다.
독점 네트워크 만들기
각 AWS 계정에는 미리 만들어진 기본 VPC가 있습니다.너는 그것을 사용할 수 있지만, 어떻게 만드는지 보여 줘.
필요한 유일한 매개 변수는 가상 네트워크의 주소 공간(CIDR 형식)입니다.
# terraform/variables.tf
...
variable "vpc_cidr_block" {
type = string
description = "VPC CIDR"
}
65536개의 IP 주소vpc_cidr_block = "10.0.0.0/16"
를 사용합니다.# terraform/main.tf
...
resource "aws_vpc" "vpc" {
cidr_block = var.vpc_cidr_block
tags = {
Name = "${var.project}-vpc"
}
}
Name
라벨의 빠른 주석.일반적으로 VPC Terraform 리소스 자체에는 "name"속성이 없지만 Name
태그를 추가하면 같은 용도로 사용됩니다.이 값은 AWS 콘솔의 이름 열에서 사용됩니다.공통 서브넷 생성
서브넷 자체를 제외하고 지원 자원을 만들 것입니다.
공통 서브넷
# terraform/variables.tf
...
variable "subnet_public_cidr_block" {
type = string
description = "Public subnet CIDR"
}
# terraform/terraform.tfvars
...
subnet_public_cidr_block = "10.0.0.0/21"
# terraform/main.tf
...
resource "aws_subnet" "subnet_public" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.subnet_public_cidr_block
map_public_ip_on_launch = true
tags = {
Name = "${var.project}-subnet-public"
}
}
인터넷 게이트웨이각 VPC는 하나의 인터넷 게이트웨이와 연결할 수 있습니다.이것은 AWS가 제공하는 관리된 고가용성 서비스로 전용 네트워크에서 공공 IP를 지원하는 실례를 위해 인터넷과의 연결을 제공한다.
# terraform/main.tf
...
resource "aws_internet_gateway" "internet_gateway" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "${var.project}-internet-gateway"
}
}
공통 라우팅 테이블공공 서브넷을 공개하는 것은 인터넷 게이트웨이로 가는 경로입니다.이렇게 해서 네트워크 요청을 인터넷 게이트웨이로 지정하는 루트 테이블을 만듭니다.그런 다음 공용 라우팅 테이블을 공용 서브넷과 연관시킵니다.VPC에는 트래픽을 허용하는 암시적인 라우팅이 있습니다.
# terraform/main.tf
...
resource "aws_route_table" "route_table_public" {
vpc_id = aws_vpc.vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.internet_gateway.id
}
tags = {
Name = "${var.project}-route-table-public"
}
}
resource "aws_route_table_association" "route_table_association_public" {
subnet_id = aws_subnet.subnet_public.id
route_table_id = aws_route_table.route_table_public.id
}
유연한 IP 및 NAT 게이트웨이NAT 게이트웨이는 전용 네트워크의 디바이스를 아웃바운드 연결할 수 있는 네트워크 디바이스입니다.게이트웨이는 요청을 전용 서브넷에서 인터넷으로 전환합니다. (발송자의 전용 'from' IP를 게이트웨이의 공공 IP로 바꾸고 그것을 다시 보내서 발송자에게 응답을 보냅니다.)이곳의 관계는 한 쌍의 NAT 장치가 개인 서브넷에 있는 여러 클라이언트에게 서비스를 제공하는 것이다.NAT 장치는 공용 IP 주소가 있어야 하며, 인터넷에 접근할 수 있는 공용 서브넷에 설치해야 합니다.
AWS에서 NAT 게이트웨이를 도입하기 전에 NAT를 구성한 EC2 인스턴스를 시작할 수 있습니다.이것은 NAT 게이트웨이보다 저렴한 유효한 옵션이지만, 실례 (디스크 공간, 운영체제, 보안 업그레이드 등) 에 주목해야 합니다.NAT 게이트웨이 가격은 지역에 따라 다르며, 이 문서를 작성할 때까지 시간당 0.045달러에 가장 저렴합니다.
AWS는 중요한 워크플로우의 경우 AZ 다운타임 시 단일 장애를 방지하기 위해 가용성 영역별로 최소 2개의 NAT 게이트웨이를 구성하는 것이 좋습니다.간단함을 유지하기 위해서, 우리는 단지 하나의 스위치만 만들 것이다.
# terraform/main.tf
...
resource "aws_eip" "eip" {
vpc = true
depends_on = [aws_internet_gateway.internet_gateway]
tags = {
Name = "${var.project}-eip"
}
}
# terraform/main.tf
...
resource "aws_nat_gateway" "nat_gateway" {
allocation_id = aws_eip.eip.id
subnet_id = aws_subnet.subnet_public.id
tags = {
Name = "${var.project}-nat-gateway"
}
}
개인 서브넷 생성
우리는 람바다를 개인 서브넷과 연결할 것이다.Lambda가 확장될 때 ENIs에 할당된 모든 IP를 수용할 수 있도록 주소 공간이 충분해야 합니다.
사설 서브넷
# terraform/variables.tf
...
variable "subnet_private_cidr_block" {
type = string
description = "Private subnet CIDR"
}
# terraform/terraform.tfvars
...
subnet_private_cidr_block = "10.0.8.0/21"
# terraform/main.tf
...
resource "aws_subnet" "subnet_private" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.subnet_private_cidr_block
map_public_ip_on_launch = false
tags = {
Name = "${var.project}-subnet-private"
}
}
전용 라우팅 테이블공용 서브넷에서처럼 트래픽을 서브넷에서 NAT 게이트웨이로 지정하는 라우팅 테이블이 필요합니다.기본적으로 독점 네트워크 서브넷의 장치는 서로 통신할 수 있다.우리의 예에서, 개인 서브넷의 Lambda가 공공 서브넷의 NAT 스위치를 호출하는 것이다.
# terraform/main.tf
...
resource "aws_route_table" "route_table_private" {
vpc_id = aws_vpc.vpc.id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.nat_gateway.id
}
tags = {
Name = "${var.project}-route-table-private"
}
}
resource "aws_route_table_association" "route_table_association_private" {
subnet_id = aws_subnet.subnet_private.id
route_table_id = aws_route_table.route_table_private.id
}
보안 리소스 만들기
VPC에서 사용할 수 있는 보안 제어는 네트워크 액세스 제어 목록과 보안 그룹입니다.이 두 가지는 서로 보완하는 것으로 단독으로 사용할 수도 있고 조합해서 사용할 수도 있다.
NACL은 무상태입니다(지정된 연결의 경우 인바운드 및 아웃바운드 규칙을 모두 지정해야 함). 그리고 서브넷과 연결됩니다.
보안 그룹은 상태입니다(포트의 인바운드 트래픽을 허용하면 해당 포트의 회신이 자동으로 허용됨).장치(EC2 인스턴스, Lambda)를 보안 그룹에 연관시킵니다.
VPC를 만들 때마다 NACL 및 보안 그룹이 암시적으로 생성됩니다.너는
aws_default_...
지형 자원으로 이 자원을 관리할 수 있다.아래에 제공된 입구와 출구 규칙은 AWS에서 기본적으로 만든 규칙과 일치합니다.염화나트륨
기본 설정과 마찬가지로 네트워크 수준의 모든 데이터를 허용합니다.
# terraform/main.tf
...
resource "aws_default_network_acl" "default_network_acl" {
default_network_acl_id = aws_vpc.vpc.default_network_acl_id
subnet_ids = [aws_subnet.subnet_public.id, aws_subnet.subnet_private.id]
ingress {
protocol = -1
rule_no = 100
action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 0
to_port = 0
}
egress {
protocol = -1
rule_no = 100
action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 0
to_port = 0
}
tags = {
Name = "${var.project}-default-network-acl"
}
}
보안 그룹기본 설정과 마찬가지로 모든 아웃바운드 트래픽을 허용하고 동일한 VPC에서 들어오는 트래픽을 허용합니다.
# terraform/main.tf
...
resource "aws_default_security_group" "default_security_group" {
vpc_id = aws_vpc.vpc.id
ingress {
protocol = -1
self = true
from_port = 0
to_port = 0
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
# cidr_blocks = ["127.0.0.1/32"]
}
tags = {
Name = "${var.project}-default-security-group"
}
}
VPC에 Lambda 추가
현재 VPC를 설치했으므로 기존 Lambda 기능을 네트워크에 연결할 수 있습니다.이를 위해서는 VPC 서브넷과 보안 그룹이 필요합니다.AWS에서는 고가용성을 위해 최소 2개의 서브넷에 Lambda를 추가하는 것이 좋습니다.여러 NAT 게이트웨이를 사용하는 권장 사항과 함께 각 전용 서브넷을 전용 NAT 게이트웨이와 연관시키기 위한 추가 라우팅 테이블을 만들어야 합니다.
독점 네트워크 액세스 정책
Lambda 서비스는 전용 서브넷에 ENIs(가상 NIC)를 만들어야 하기 때문에 추가 IAM 권한이 필요합니다.이것들은
AWSLambdaVPCAccessExecutionRole
관리 정책을 통해 수여할 수 있다.권한이 없으면, 배치하는 동안 오류: 오류: Lambda 함수 (Lambda vpc tf Lambda 함수) 설정을 수정하는 중 오류: InvalidParameterValueException: 제공하는 실행 역할이 EC2에서CreateNetworkInterface를 호출할 권한이 없습니다.
# terraform/main.tf
...
resource "aws_iam_role_policy_attachment" "iam_role_policy_attachment_lambda_vpc_access_execution" {
role = aws_iam_role.iam_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
}
Lambda 함수 VPC 구성Lambda를 전용 서브넷에 연결하도록 구성했습니다.또한 보안 그룹 규칙의 제약을 받는다.
# terraform/main.tf
...
resource "aws_lambda_function" "lambda_function" {
...
vpc_config {
subnet_ids = [aws_subnet.subnet_private.id]
security_group_ids = [aws_default_security_group.default_security_group.id]
}
}
모든 설정이 정확한지 확인하려면 이 함수를 다시 호출하십시오.Cloudwatch에서 "시간 초과"오류가 발생하면, 함수가 API에 접근할 수 없기 때문에 NAT 게이트웨이 설정에 문제가 있을 수 있습니다.도구책
。。。
만약 당신이 경험이 풍부한 인터넷 전문가가 아니라면 VPC 설정은 매우 까다로울 것이다.마지막으로 마이클'sqlbot'의 이 글Stack Overflow answer을 추천합니다. 이것은 사유/공공 서브넷의 개념을 잘 설명합니다.
만약 당신이 이런 내용을 좋아한다면 트위터에서 최신 업데이트를 얻을 수 있습니다.
Reference
이 문제에 관하여(Terraform을 사용하여 AWS Lambda를 VPC에 배포), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/maxivanov/deploy-aws-lambda-to-vpc-with-terraform-6i5텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)