728x90
반응형
SMALL
SMALL

 

Variables

이번엔 Variable을 사용해서 코드에서 사용할 수 있도록 해보자.

이전 포스팅에서 사용했던 main.tf 파일에서 다음을 추가한다.

variable "vpc_name" {
		
}

 

이 코드는 vpc_name 이라는 변수를 만든 것이다. 여기에 기본값을 설정하지 않으면 Apply를 할 때 변수 이름을 받도록 되어 있다.

그래서 이 변수를 사용해보기 위해 VPC의 name 값을 var.vpc_name 으로 변경해보자.

module "vpc" {
  source  = "tedilabs/network/aws//modules/vpc"
  version = "0.24.0"

  name       = var.vpc_name
  cidr_block = "10.0.0.0/16"

  internet_gateway_enabled = true

  dns_hostnames_enabled = true
  dns_support_enabled   = true

  tags = {}
}

 

최종 소스 코드는 다음과 같다.

#main.tf

provider "aws" {
  region = "ap-northeast-2"
}

variable "vpc_name" {
		
}

module "vpc" {
  source  = "tedilabs/network/aws//modules/vpc"
  version = "0.24.0"

  name       = var.vpc_name
  cidr_block = "10.0.0.0/16"

  internet_gateway_enabled = true

  dns_hostnames_enabled = true
  dns_support_enabled   = true

  tags = {}
}

module "subnet_group__public" {
  source  = "tedilabs/network/aws//modules/subnet-group"
  version = "0.24.0"

  name                    = "${module.vpc.name}-public"
  vpc_id                  = module.vpc.id
  map_public_ip_on_launch = true

  subnets = {
    "${module.vpc.name}-public-001/az1" = {
      cidr_block           = "10.0.0.0/24"
      availability_zone_id = "apne2-az1"
    }
    "${module.vpc.name}-public-002/az2" = {
      cidr_block           = "10.0.1.0/24"
      availability_zone_id = "apne2-az2"
    }
  }

  tags = {}
}

module "subnet_group__private" {
  source  = "tedilabs/network/aws//modules/subnet-group"
  version = "0.24.0"

  name                    = "${module.vpc.name}-private"
  vpc_id                  = module.vpc.id
  map_public_ip_on_launch = false

  subnets = {
    "${module.vpc.name}-private-001/az1" = {
      cidr_block           = "10.0.10.0/24"
      availability_zone_id = "apne2-az1"
    }
    "${module.vpc.name}-public-002/az2" = {
      cidr_block           = "10.0.11.0/24"
      availability_zone_id = "apne2-az2"
    }
  }

  tags = {}
}

 

Apply를 실행해보자. 다음과 같이 변수 값을 받는다. 이는 vpc_name의 기본값을 설정해주지 않았기 때문이다.

 

나는 다음과 같이 변수값을 지정했다.

 

이렇게 하고 Enter를 입력하면 이제 Plan 정보들이 나온다.

그 Plan 정보를 잘 보면 내가 넣은 "tftf"값이 보여진다.

 

이제 생성을 완료해서 AWS Console에서 확인해보자. 잘 만들어졌다.

 

Variables 지정 방식들

이러한 변수를 설정하고 지정하는 방식에는 여러 방법이 있는데 문서를 살펴보면 자세히 나와있다.

 

Input Variables - Configuration Language | Terraform | HashiCorp Developer

Input variables allow you to customize modules without altering their source code. Learn how to declare, define, and reference variables in configurations.

developer.hashicorp.com

 

이 문서에 보면 다음과 같은 코드 예시가 있다. 위에서 우리가 작성한 것과 다른 부분은 type을 지정한다거나 default 값을 지정한다.

variable "image_id" {
  type = string
}

variable "availability_zone_names" {
  type    = list(string)
  default = ["us-west-1a"]
}

variable "docker_ports" {
  type = list(object({
    internal = number
    external = number
    protocol = string
  }))
  default = [
    {
      internal = 8300
      external = 8300
      protocol = "tcp"
    }
  ]
}

 

실행 시 옵션으로 변수 지정

그리고 이 변수에 기본값을 지정했더라도 다음처럼 실행 시 변수값을 변경할 수 있다.

terraform apply -var="image_id=ami-abc123"
terraform apply -var='image_id_list=["ami-abc123","ami-def456"]' -var="instance_type=t2.micro"
terraform apply -var='image_id_map={"us-east-1":"ami-abc123","us-east-2":"ami-def456"}'

 

환경변수로 등록해서 변수 지정

또는 다음과 같이 환경변수로도 설정할 수 있다.

export TF_VAR_image_id=ami-abc123

 

변수 파일(.tfvars / .tfvars.json)로 변수 지정

또는 다음과 같이 여러 변수가 있는 경우 변수만을 위한 파일을 만들어서 그 파일을 가리키게 할 수 있다.

파일명은 ".tfvars" 또는 ".tfvars.json"형식이어야 한다.

 

근데, 기본으로 파일명은 "terraform.tfvars"라는 파일만을 바라보게 되어있다. 그래서 이런 파일명이 아닌 경우 Apply시에 인지를 못하는데 그 때 해결하는 방법은 다음처럼 실행 시 옵션을 주는 것이다.

terraform apply -var-file="testing.tfvars"

이 변수 파일은 main.tf 파일이랑 같은 경로에 있으면 된다. 그리고 아래와 같이 작성해주면 된다.

#terraform.tfvars

vpc_name = "varsfile"

 

Local Variables

이 Local Variable은 main.tf 파일 내에서만 공통으로 사용할 변수를 선언하고 그 변수를 사용하기에 적합한 방식이다. 

기존 main.tf 파일에 다음과 같은 코드를 추가해보자.

locals {
  common_tags = {
	Project = "Network"
	Owner = "cwchoi"
  }
}

 

그리고 이 로컬 변수를 각 모듈의 태그에서 사용해보자.

provider "aws" {
  region = "ap-northeast-2"
}

variable "vpc_name" {

}

locals {
  common_tags = {
	Project = "Network"
	Owner = "cwchoi"
  }
}

module "vpc" {
  source  = "tedilabs/network/aws//modules/vpc"
  version = "0.24.0"

  name       = var.vpc_name
  cidr_block = "10.0.0.0/16"

  internet_gateway_enabled = true

  dns_hostnames_enabled = true
  dns_support_enabled   = true

  tags = local.common_tags
}

module "subnet_group__public" {
  source  = "tedilabs/network/aws//modules/subnet-group"
  version = "0.24.0"

  name                    = "${module.vpc.name}-public"
  vpc_id                  = module.vpc.id
  map_public_ip_on_launch = true

  subnets = {
    "${module.vpc.name}-public-001/az1" = {
      cidr_block           = "10.0.0.0/24"
      availability_zone_id = "apne2-az1"
    }
    "${module.vpc.name}-public-002/az2" = {
      cidr_block           = "10.0.1.0/24"
      availability_zone_id = "apne2-az2"
    }
  }

  tags = local.common_tags
}

module "subnet_group__private" {
  source  = "tedilabs/network/aws//modules/subnet-group"
  version = "0.24.0"

  name                    = "${module.vpc.name}-private"
  vpc_id                  = module.vpc.id
  map_public_ip_on_launch = false

  subnets = {
    "${module.vpc.name}-private-001/az1" = {
      cidr_block           = "10.0.10.0/24"
      availability_zone_id = "apne2-az1"
    }
    "${module.vpc.name}-public-002/az2" = {
      cidr_block           = "10.0.11.0/24"
      availability_zone_id = "apne2-az2"
    }
  }

  tags = local.common_tags
}

 

이렇게 해당 파일 내에서 반복적으로 사용되는 변수를 로컬 변수라는 형식으로 지정할 수 있다.

 

 

Outputs

Outputs은 Apply를 진행 후 결과를 저장할 때 사용한다. 예를 들어 다음과 같은 코드를 추가했다고 가정해보자.

output "vpc_name" {
  value = module.vpc.name
}

output "vpc_id" {
  value = module.vpc.id
}

output "public_subnet_group" {
  value = module.subnet_group__public
}

output "subnets" {
  value = {
    public  = module.subnet_group__public
    private = module.subnet_group__private
  }
}

 

지금 3개의 output이 있는것을 확인할 수 있다. 이렇게 3개의 아웃풋이 Apply를 진행 후 만들어지는 데이터라고 생각하면 된다.

이 Output을 다른곳에서 가져다가 사용할 수도 있고 Apply 진행 후 결과를 알고 싶을때도 사용할 수 있다. Apply를 해보자.

 

다음과 같은 Outputs 결과를 볼 수 있다.

public_subnet_group = {
  "arns" = [
    "arn:aws:ec2:ap-northeast-2:135149110460:subnet/subnet-0a3d08dd50460e153",
    "arn:aws:ec2:ap-northeast-2:135149110460:subnet/subnet-00c04ce3dead87b6d",
  ]
  "availability_zone_ids" = tolist([
    "apne2-az1",
    "apne2-az2",
  ])
  "availability_zones" = tolist([
    "ap-northeast-2a",
    "ap-northeast-2b",
  ])
  "cache_subnet_group_id" = null
  "cidr_blocks" = [
    "10.0.0.0/24",
    "10.0.1.0/24",
  ]
  "dax_subnet_group_id" = null
  "db_subnet_group_arn" = null
  "db_subnet_group_id" = null
  "dms_replication_subnet_group_id" = null
  "docdb_subnet_group_arn" = null
  "docdb_subnet_group_id" = null
  "ids" = [
    "subnet-0a3d08dd50460e153",
    "subnet-00c04ce3dead87b6d",
  ]
  "ipv6_cidr_blocks" = tolist([])
  "name" = "varsfile-public"
  "neptune_subnet_group_arn" = null
  "neptune_subnet_group_id" = null
  "redshift_subnet_group_arn" = null
  "redshift_subnet_group_id" = null
  "subnets" = [
    {
      "arn" = "arn:aws:ec2:ap-northeast-2:135149110460:subnet/subnet-0a3d08dd50460e153"
      "assign_ipv6_address_on_creation" = false
      "availability_zone" = "ap-northeast-2a"
      "availability_zone_id" = "apne2-az1"
      "cidr_block" = "10.0.0.0/24"
      "customer_owned_ipv4_pool" = ""
      "enable_dns64" = false
      "enable_lni_at_device_index" = 0
      "enable_resource_name_dns_a_record_on_launch" = false
      "enable_resource_name_dns_aaaa_record_on_launch" = false
      "id" = "subnet-0a3d08dd50460e153"
      "ipv6_cidr_block" = ""
      "ipv6_cidr_block_association_id" = ""
      "ipv6_native" = false
      "map_customer_owned_ip_on_launch" = false
      "map_public_ip_on_launch" = true
      "outpost_arn" = ""
      "owner_id" = "135149110460"
      "private_dns_hostname_type_on_launch" = "ip-name"
      "tags" = tomap({
        "Name" = "varsfile-public-001/az1"
        "Owner" = "cwchoi"
        "Project" = "Network"
        "module.terraform.io/full-name" = "terraform-aws-network/subnet-group"
        "module.terraform.io/instance" = "varsfile-public"
        "module.terraform.io/name" = "subnet-group"
        "module.terraform.io/package" = "terraform-aws-network"
        "module.terraform.io/version" = "0.24.0"
      })
      "tags_all" = tomap({
        "Name" = "varsfile-public-001/az1"
        "Owner" = "cwchoi"
        "Project" = "Network"
        "module.terraform.io/full-name" = "terraform-aws-network/subnet-group"
        "module.terraform.io/instance" = "varsfile-public"
        "module.terraform.io/name" = "subnet-group"
        "module.terraform.io/package" = "terraform-aws-network"
        "module.terraform.io/version" = "0.24.0"
      })
      "timeouts" = null /* object */
      "vpc_id" = "vpc-01166744a0ba4ca4a"
    },
    {
      "arn" = "arn:aws:ec2:ap-northeast-2:135149110460:subnet/subnet-00c04ce3dead87b6d"
      "assign_ipv6_address_on_creation" = false
      "availability_zone" = "ap-northeast-2b"
      "availability_zone_id" = "apne2-az2"
      "cidr_block" = "10.0.1.0/24"
      "customer_owned_ipv4_pool" = ""
      "enable_dns64" = false
      "enable_lni_at_device_index" = 0
      "enable_resource_name_dns_a_record_on_launch" = false
      "enable_resource_name_dns_aaaa_record_on_launch" = false
      "id" = "subnet-00c04ce3dead87b6d"
      "ipv6_cidr_block" = ""
      "ipv6_cidr_block_association_id" = ""
      "ipv6_native" = false
      "map_customer_owned_ip_on_launch" = false
      "map_public_ip_on_launch" = true
      "outpost_arn" = ""
      "owner_id" = "135149110460"
      "private_dns_hostname_type_on_launch" = "ip-name"
      "tags" = tomap({
        "Name" = "varsfile-public-002/az2"
        "Owner" = "cwchoi"
        "Project" = "Network"
        "module.terraform.io/full-name" = "terraform-aws-network/subnet-group"
        "module.terraform.io/instance" = "varsfile-public"
        "module.terraform.io/name" = "subnet-group"
        "module.terraform.io/package" = "terraform-aws-network"
        "module.terraform.io/version" = "0.24.0"
      })
      "tags_all" = tomap({
        "Name" = "varsfile-public-002/az2"
        "Owner" = "cwchoi"
        "Project" = "Network"
        "module.terraform.io/full-name" = "terraform-aws-network/subnet-group"
        "module.terraform.io/instance" = "varsfile-public"
        "module.terraform.io/name" = "subnet-group"
        "module.terraform.io/package" = "terraform-aws-network"
        "module.terraform.io/version" = "0.24.0"
      })
      "timeouts" = null /* object */
      "vpc_id" = "vpc-01166744a0ba4ca4a"
    },
  ]
  "vpc_id" = "vpc-01166744a0ba4ca4a"
}
subnets = {
  "private" = {
    "arns" = [
      "arn:aws:ec2:ap-northeast-2:135149110460:subnet/subnet-0396c6b38c61fb88f",
      "arn:aws:ec2:ap-northeast-2:135149110460:subnet/subnet-058b0d0699a85f174",
    ]
    "availability_zone_ids" = tolist([
      "apne2-az1",
      "apne2-az2",
    ])
    "availability_zones" = tolist([
      "ap-northeast-2a",
      "ap-northeast-2b",
    ])
    "cache_subnet_group_id" = null
    "cidr_blocks" = [
      "10.0.10.0/24",
      "10.0.11.0/24",
    ]
    "dax_subnet_group_id" = null
    "db_subnet_group_arn" = null
    "db_subnet_group_id" = null
    "dms_replication_subnet_group_id" = null
    "docdb_subnet_group_arn" = null
    "docdb_subnet_group_id" = null
    "ids" = [
      "subnet-0396c6b38c61fb88f",
      "subnet-058b0d0699a85f174",
    ]
    "ipv6_cidr_blocks" = tolist([])
    "name" = "varsfile-private"
    "neptune_subnet_group_arn" = null
    "neptune_subnet_group_id" = null
    "redshift_subnet_group_arn" = null
    "redshift_subnet_group_id" = null
    "subnets" = [
      {
        "arn" = "arn:aws:ec2:ap-northeast-2:135149110460:subnet/subnet-0396c6b38c61fb88f"
        "assign_ipv6_address_on_creation" = false
        "availability_zone" = "ap-northeast-2a"
        "availability_zone_id" = "apne2-az1"
        "cidr_block" = "10.0.10.0/24"
        "customer_owned_ipv4_pool" = ""
        "enable_dns64" = false
        "enable_lni_at_device_index" = 0
        "enable_resource_name_dns_a_record_on_launch" = false
        "enable_resource_name_dns_aaaa_record_on_launch" = false
        "id" = "subnet-0396c6b38c61fb88f"
        "ipv6_cidr_block" = ""
        "ipv6_cidr_block_association_id" = ""
        "ipv6_native" = false
        "map_customer_owned_ip_on_launch" = false
        "map_public_ip_on_launch" = false
        "outpost_arn" = ""
        "owner_id" = "135149110460"
        "private_dns_hostname_type_on_launch" = "ip-name"
        "tags" = tomap({
          "Name" = "varsfile-private-001/az1"
          "Owner" = "cwchoi"
          "Project" = "Network"
          "module.terraform.io/full-name" = "terraform-aws-network/subnet-group"
          "module.terraform.io/instance" = "varsfile-private"
          "module.terraform.io/name" = "subnet-group"
          "module.terraform.io/package" = "terraform-aws-network"
          "module.terraform.io/version" = "0.24.0"
        })
        "tags_all" = tomap({
          "Name" = "varsfile-private-001/az1"
          "Owner" = "cwchoi"
          "Project" = "Network"
          "module.terraform.io/full-name" = "terraform-aws-network/subnet-group"
          "module.terraform.io/instance" = "varsfile-private"
          "module.terraform.io/name" = "subnet-group"
          "module.terraform.io/package" = "terraform-aws-network"
          "module.terraform.io/version" = "0.24.0"
        })
        "timeouts" = null /* object */
        "vpc_id" = "vpc-01166744a0ba4ca4a"
      },
      {
        "arn" = "arn:aws:ec2:ap-northeast-2:135149110460:subnet/subnet-058b0d0699a85f174"
        "assign_ipv6_address_on_creation" = false
        "availability_zone" = "ap-northeast-2b"
        "availability_zone_id" = "apne2-az2"
        "cidr_block" = "10.0.11.0/24"
        "customer_owned_ipv4_pool" = ""
        "enable_dns64" = false
        "enable_lni_at_device_index" = 0
        "enable_resource_name_dns_a_record_on_launch" = false
        "enable_resource_name_dns_aaaa_record_on_launch" = false
        "id" = "subnet-058b0d0699a85f174"
        "ipv6_cidr_block" = ""
        "ipv6_cidr_block_association_id" = ""
        "ipv6_native" = false
        "map_customer_owned_ip_on_launch" = false
        "map_public_ip_on_launch" = false
        "outpost_arn" = ""
        "owner_id" = "135149110460"
        "private_dns_hostname_type_on_launch" = "ip-name"
        "tags" = tomap({
          "Name" = "varsfile-public-002/az2"
          "Owner" = "cwchoi"
          "Project" = "Network"
          "module.terraform.io/full-name" = "terraform-aws-network/subnet-group"
          "module.terraform.io/instance" = "varsfile-private"
          "module.terraform.io/name" = "subnet-group"
          "module.terraform.io/package" = "terraform-aws-network"
          "module.terraform.io/version" = "0.24.0"
        })
        "tags_all" = tomap({
          "Name" = "varsfile-public-002/az2"
          "Owner" = "cwchoi"
          "Project" = "Network"
          "module.terraform.io/full-name" = "terraform-aws-network/subnet-group"
          "module.terraform.io/instance" = "varsfile-private"
          "module.terraform.io/name" = "subnet-group"
          "module.terraform.io/package" = "terraform-aws-network"
          "module.terraform.io/version" = "0.24.0"
        })
        "timeouts" = null /* object */
        "vpc_id" = "vpc-01166744a0ba4ca4a"
      },
    ]
    "vpc_id" = "vpc-01166744a0ba4ca4a"
  }
  "public" = {
    "arns" = [
      "arn:aws:ec2:ap-northeast-2:135149110460:subnet/subnet-0a3d08dd50460e153",
      "arn:aws:ec2:ap-northeast-2:135149110460:subnet/subnet-00c04ce3dead87b6d",
    ]
    "availability_zone_ids" = tolist([
      "apne2-az1",
      "apne2-az2",
    ])
    "availability_zones" = tolist([
      "ap-northeast-2a",
      "ap-northeast-2b",
    ])
    "cache_subnet_group_id" = null
    "cidr_blocks" = [
      "10.0.0.0/24",
      "10.0.1.0/24",
    ]
    "dax_subnet_group_id" = null
    "db_subnet_group_arn" = null
    "db_subnet_group_id" = null
    "dms_replication_subnet_group_id" = null
    "docdb_subnet_group_arn" = null
    "docdb_subnet_group_id" = null
    "ids" = [
      "subnet-0a3d08dd50460e153",
      "subnet-00c04ce3dead87b6d",
    ]
    "ipv6_cidr_blocks" = tolist([])
    "name" = "varsfile-public"
    "neptune_subnet_group_arn" = null
    "neptune_subnet_group_id" = null
    "redshift_subnet_group_arn" = null
    "redshift_subnet_group_id" = null
    "subnets" = [
      {
        "arn" = "arn:aws:ec2:ap-northeast-2:135149110460:subnet/subnet-0a3d08dd50460e153"
        "assign_ipv6_address_on_creation" = false
        "availability_zone" = "ap-northeast-2a"
        "availability_zone_id" = "apne2-az1"
        "cidr_block" = "10.0.0.0/24"
        "customer_owned_ipv4_pool" = ""
        "enable_dns64" = false
        "enable_lni_at_device_index" = 0
        "enable_resource_name_dns_a_record_on_launch" = false
        "enable_resource_name_dns_aaaa_record_on_launch" = false
        "id" = "subnet-0a3d08dd50460e153"
        "ipv6_cidr_block" = ""
        "ipv6_cidr_block_association_id" = ""
        "ipv6_native" = false
        "map_customer_owned_ip_on_launch" = false
        "map_public_ip_on_launch" = true
        "outpost_arn" = ""
        "owner_id" = "135149110460"
        "private_dns_hostname_type_on_launch" = "ip-name"
        "tags" = tomap({
          "Name" = "varsfile-public-001/az1"
          "Owner" = "cwchoi"
          "Project" = "Network"
          "module.terraform.io/full-name" = "terraform-aws-network/subnet-group"
          "module.terraform.io/instance" = "varsfile-public"
          "module.terraform.io/name" = "subnet-group"
          "module.terraform.io/package" = "terraform-aws-network"
          "module.terraform.io/version" = "0.24.0"
        })
        "tags_all" = tomap({
          "Name" = "varsfile-public-001/az1"
          "Owner" = "cwchoi"
          "Project" = "Network"
          "module.terraform.io/full-name" = "terraform-aws-network/subnet-group"
          "module.terraform.io/instance" = "varsfile-public"
          "module.terraform.io/name" = "subnet-group"
          "module.terraform.io/package" = "terraform-aws-network"
          "module.terraform.io/version" = "0.24.0"
        })
        "timeouts" = null /* object */
        "vpc_id" = "vpc-01166744a0ba4ca4a"
      },
      {
        "arn" = "arn:aws:ec2:ap-northeast-2:135149110460:subnet/subnet-00c04ce3dead87b6d"
        "assign_ipv6_address_on_creation" = false
        "availability_zone" = "ap-northeast-2b"
        "availability_zone_id" = "apne2-az2"
        "cidr_block" = "10.0.1.0/24"
        "customer_owned_ipv4_pool" = ""
        "enable_dns64" = false
        "enable_lni_at_device_index" = 0
        "enable_resource_name_dns_a_record_on_launch" = false
        "enable_resource_name_dns_aaaa_record_on_launch" = false
        "id" = "subnet-00c04ce3dead87b6d"
        "ipv6_cidr_block" = ""
        "ipv6_cidr_block_association_id" = ""
        "ipv6_native" = false
        "map_customer_owned_ip_on_launch" = false
        "map_public_ip_on_launch" = true
        "outpost_arn" = ""
        "owner_id" = "135149110460"
        "private_dns_hostname_type_on_launch" = "ip-name"
        "tags" = tomap({
          "Name" = "varsfile-public-002/az2"
          "Owner" = "cwchoi"
          "Project" = "Network"
          "module.terraform.io/full-name" = "terraform-aws-network/subnet-group"
          "module.terraform.io/instance" = "varsfile-public"
          "module.terraform.io/name" = "subnet-group"
          "module.terraform.io/package" = "terraform-aws-network"
          "module.terraform.io/version" = "0.24.0"
        })
        "tags_all" = tomap({
          "Name" = "varsfile-public-002/az2"
          "Owner" = "cwchoi"
          "Project" = "Network"
          "module.terraform.io/full-name" = "terraform-aws-network/subnet-group"
          "module.terraform.io/instance" = "varsfile-public"
          "module.terraform.io/name" = "subnet-group"
          "module.terraform.io/package" = "terraform-aws-network"
          "module.terraform.io/version" = "0.24.0"
        })
        "timeouts" = null /* object */
        "vpc_id" = "vpc-01166744a0ba4ca4a"
      },
    ]
    "vpc_id" = "vpc-01166744a0ba4ca4a"
  }
}
vpc_id = "vpc-01166744a0ba4ca4a"
vpc_name = "varsfile"

 

 

728x90
반응형
LIST

'AWS' 카테고리의 다른 글

AWS DynamoDB를 Python과 연동해보기  (2) 2024.03.05
AWS Lambda와 DynamoDB를 연동해보기  (0) 2024.03.04
AWS Lambda와 Step functions  (0) 2024.03.04
AWS Lambda와 Layers  (0) 2024.03.04
AWS Lambda와 API Gateway로 Canary Release 하기  (0) 2024.03.03
728x90
반응형
SMALL
SMALL

 

Requisites

 

우선 AWS CLI를 사용해야한다. 그러기 위해서 AWS CLI를 먼저 설치를 해야하고 구성도 해야한다. 이 부분은 이전 포스팅에서도 다루기도 했고 공식 문서로도 잘 되어 있으니까 생략한다.

 

boto3

Python과 DynamoDB를 연동하기 위해서 필요한 패키지인 'boto3'를 설치해야한다. 

근데 설치하기 앞서, 나는 Global로 파이썬 패키지를 설치하는것을 싫어한다. 그래서 가상환경을 세팅해줄 것이다.

 

작업하길 원하는 경로에서 다음 명령어를 입력한다. 이는 가상환경을 구성하는 명령어이다.

python3 -m venv ./

 

가상환경을 구성했으면 가상환경을 실행한다.

source ./bin/activate

 

가상환경을 실행하면 자동으로 가상환경 내부로 들어온다. 이 내부에서 다음 명령어를 실행한다.

pip3 install boto3

 

이제 동일 경로에서 파일 하나를 만든다. 나는 다음과 같이 dynamoaccess.py 라는 파일을 만들었다.

# dynamoaccess.py

import boto3

client = boto3.client('dynamodb')

data = client.put_item(TableName='Orders', Item={'OrderID': {'S': '1'}, 'Date': {'S': '20240305'}})

 

따로 어떤 dynamodb를 사용할지 내가 누구인지는 작성할 필요없다. 왜냐하면 aws-cli에서 이미 설정을 했기 때문이다.

이 파일을 실행하면 된다.

python3 dynamoaccess.py

 

실행해서 아무런 반응이 없이 실행이 끝나면 성공한 것. 이제 넣으려고 했던 데이터가 잘 들어갔는지 확인해보면 된다.

 

아래와 같이 정상적으로 데이터가 들어갔다.

 

이제 이렇게 DynamoDB에 데이터를 넣어봤으니 한번 읽기도 해보자.

파일 하나를 더 만들자. 나는 dynamoread.py 라는 파일을 만들었다.

 

# dynamoread.py

import boto3

client = boto3.client('dynamodb')

data = client.get_item(TableName='Orders', Key={'OrderID': {'S': '1'}, 'Date':{'S': '20240305'}})

print(data)

 

이 파일을 실행시켜보자.

python3 dynamoread.py

 

다음과 같이 잘 읽어오는 것을 확인할 수 있다.

 

728x90
반응형
LIST

'AWS' 카테고리의 다른 글

AWS + Terraform (Variable)  (0) 2024.03.06
AWS Lambda와 DynamoDB를 연동해보기  (0) 2024.03.04
AWS Lambda와 Step functions  (0) 2024.03.04
AWS Lambda와 Layers  (0) 2024.03.04
AWS Lambda와 API Gateway로 Canary Release 하기  (0) 2024.03.03
728x90
반응형
SMALL
SMALL

 

DynamoDB

DynamoDB를 알기 전에 기존의 데이터베이스 형태에 대해서 먼저 알아보자. 기존의 데이터베이스의 형태는 거의 대부분이 관계형 데이터베이스였다. 예를 들면 MySQL, PostgreSQL 등이 있다. 

이런 관계형 데이터베이스의 가장 큰 특징은 데이터에 대한 형식이 아주 견고하게 존재한다는 것이다. 그래서 형식에 맞지 않는 데이터를 넣지 못한다. 그 말은 어떤 데이터를 넣더라도 예측 가능한 데이터가 된다. 그러나 이러한 점이 단점으로 부각되기 시작한다. 그 내용은 기업이 활용할 수 있는 데이터가 다양해지면서 데이터의 형식이 다양해지고 내용이 방대해졌다는 뜻이다. 그 말은 예측이 불가능한 데이터가 더 많아진다는 뜻이다. 

 

그래서 이러한 단점(자유도가 떨어진다)을 극복하기 위해 다른 방식의 데이터베이스가 생겨나기 시작했다. 

즉, 어떤 정제가 되지 않은, 있는 그대로의 데이터를 모두 받아들일 수 있는 AWS S3와 같은 DataLakeNoSQL(Not Only SQL)과 같은 데이터베이스가 점점 두각되는 추세이다. 이 NoSQL의 하나가 DynamoDB이다.

 

NoSQL은 말 그대로 SQL만을 취급하지 않는다는 것이다. 즉, 형식이 지정되어 있기도 하지만 지정되지 않은 상태여도 무방하다라는 뜻이다. 

 

DynamoDB 키 포인트

DynamoDB의 특징은 다음과 같다.

  • NoSQL
  • 수평확장(Scale-Out)이 쉽고 유연
  • Auto-Scaling 지원 / 일정 기간 백업 지원
  • 스키마 지정이 필요 X
  • 트랜잭션, 조인과 같은 복잡한 쿼리 불가능

 

Attribute, Partition Key, Sort Key, Primary Key, GSI

- Attribute: Key/Value쌍으로 된 형식이 고정되지 않은 자유로운 데이터.

- Partition Key: Primary key는 아니지만 그와 비슷한 키를 의미한다. 중복이 될 수 있다.

- Sort Key: 또 하나의 키. 이 또한 중복이 될 수 있다.

- Primary Key: Partition Key + Sort Key. 이는 중복이 될 수 없다. 중복된 데이터가 들어오면 받아주지 않는다.

- GSI(Global Secondary Index): 아이템에 대한 키 역할을 하지는 않지만 인덱스(필터링하기 위한)로서의 역할을 할 수 있는 데이터가 Attribute내에 존재할 때 그 값을 따로 빼어내서 인덱스로 만드는 것.

Partition Key Sort Key GSI Attribute
OrderID Date Region Attribute
1 210701 Seoul {...json...}
2 210701 Busan {...json...}
2 210702 Busan {...json...}
3 210703 Daegu {...json...}

 

Sort Key, GSI와 같은 인덱스는 없어도 된다. 그러나 없을 때 Partition Key가 고유값이 아니면 데이터에 대한 무결성을 장담할 수 없게된다. 이렇기 때문에 Sort Key가 필요해지고 이 Sort key와 Partition key의 결합이 Primary key가 되는 것.

 

 

DynamoDB 생성하기

AWS Console에 'DynamoDB'를 검색해서 나온 서비스를 클릭한다.

 

최초 화면은 다음과 같이 보여질 것이다. 우측 'Create table' 버튼 클릭

 

이제 설정하는 부분인데 이 설정 부분이 꽤나 양이 많다. 우선 다음을 보자.

- Table name: Orders

- Partition key: OrderID

- Sort key: Date

위에서 배운대로 Partition key와 Sort key 두 개를 모두 설정하겠다. 이 두개가 더해진 것이 Primary key가 된다. 다른 말로 이 두개가 같은 Item은 있을 수 없다.

 

- Table settings: Customize settings

- Table class: DynamoDB Standard

- Read/write capacity settings: On-demand

Provisioned를 사용하지 않는 이유는 Provisioned는 미리 할당된 만큼의 데이터 비용을 지불한다는 것인데 나는 실습차원에서 만드는 것도 있고 Provisioned는 일반적으로 예측 가능한 트래픽인 경우에 사용한다. 트래픽의 등락이 크면 On-demand가 유리하다.

 

- Secondary indexes: 여기서 Global Index가 위에서 말한 GSI이다. 이후에 생성해도 되고 지금은 필요도 없기 때문에 넘어간다.

- Encryption at rest: Owned by Amazon DynamoDB

 

이렇게 설정한 후 테이블을 최종적으로 만든다. 테이블을 만들면 다음과 같이 리스트에 만든 테이블 하나가 노출된다.

 

저 안으로 들어가보면 다음과 같이 생겼다. 테이블에 대한 정보가 이렇게 보여지고, 아이템을 추가할 수 있다.

 

우측 상단 Actions > Create item 버튼을 클릭해서 아이템 하나를 만들어보자.

 

이러한 화면에서 원하는 값을 입력하면 된다.

 

이 상태에서 새로운 속성을 더 넣어주고 싶으면 우측 "Add new attribute" 버튼을 클릭해서 자유롭게 추가가 가능하다. 이게 위에서 말한 형식에서의 자유로움이다.

 

그리고 이 상태에서 우측 상단 "JSON view" 버튼을 클릭하면 이 데이터를 JSON으로는 어떻게 넣는지 보여준다.

여기서 "S"가 어떤 의미냐면 "String"의 의미이다. 

 

이 상태에서 "Create item" 버튼을 클릭해보자. 그럼 다음과 같이 리스트에 만든 아이템 하나가 보여진다.

 

그리고 이 화면에서 쿼리도 날릴 수 있다. 내가 원하는 데이터만 추출할 때 유용하다.

 

이런식으로 DynamoDB를 이용할 수 있다. 이제 Lambda를 만들어서 이 DynamoDB와 연동해보자.

 

Lambda function에서 DynamoDB 접근하기

다음과 같이 만들어 준다. 런타임은 Node.js 16.x를 사용해보자.

우선 코드를 수정하기 전 이 람다함수가 DynamoDB에 접근할 수 있도록 권한 설정을 해주어야한다.

다음과 같이 Configuration > Permissions 에 들어가보면 적용된 Role이 보여진다. Role 클릭.

 

다음과 같이 해당 역할 내부로 들어와서 Permissions policies 섹션에 우측 Add permissions > Attach policies 버튼 클릭

 

DynamoDB를 검색해서 나오는 AmazonDynamoDBFullAccess를 선택 후 Add permissions 클릭

 

그럼 이렇게 Permissions policies 섹션에 이제 방금 추가한 정책이 들어가 있다.

 

 

이제 람다의 코드를 수정해보자. 다음과 같이 작성한다.

 

 

우선 "aws-sdk"를 임포트해야 한다. 이 녀석으로부터 AWS에 접근해야 하기 때문이다.

const AWS = require("aws-sdk");

 

그리고 이 녀석을 통해 DynamoDB를 가져온다. 가져올 땐 지역을 설정해줘야 한다. 당연히 내가 만든 DynamoDB에 대한 지역을 설정.

const ddb = new AWS.DynamoDB.DocumentClient({"region": "ap-northeast-2"});

 

그리고 리턴할 handler를 만든다. 이 함수는 비동기 함수로 우선 requestId를 받아 저장한다.

그리고 하단에 만든 createMessage()를 호출하는데 이 함수는 인자로 requestId를 넘겨주고 콜백함수를 호출한다. 이는 리턴 객체를 보내기 위함이다.

exports.handler = async (event, context, callback) => {
  const requestId = context.awsRequestId;
  
  await createMessage(requestId).then(() => {
    callback(null, {
      statusCode: 201,
      body: "",
      headers: {
        "Access-Control-Allow-Origin": "*"
      }
    })
  }).catch((err) => console.error(err))
};

 

하단 createMessage()는 변수로 requestId를 받아서 DynamoDB에 아이템 하나를 추가한다. 그리고 최종적으로 위에서 선언한 DynamoDB 객체에 해당 아이템을 put()한다.

function createMessage(requestId) {
  const params = {
    TableName: "Orders",
    Item: {
      "OrderID": requestId,
      "Date": "20240304"
    }
  }
  
  return ddb.put(params).promise();
}

 

이제 Deploy를 하고 테스트를 진행해보자. 다음과 같이 테스트를 만들고 실행한다.

 

실행하면 다음과 같이 정상 결과가 출력된다.

 

이제 DynamoDB에 가서 정상적으로 아이템이 추가됐는지 확인해보자. 다음과 같이 잘 넣어졌다.

 

 

 

728x90
반응형
LIST

'AWS' 카테고리의 다른 글

AWS + Terraform (Variable)  (0) 2024.03.06
AWS DynamoDB를 Python과 연동해보기  (2) 2024.03.05
AWS Lambda와 Step functions  (0) 2024.03.04
AWS Lambda와 Layers  (0) 2024.03.04
AWS Lambda와 API Gateway로 Canary Release 하기  (0) 2024.03.03
728x90
반응형
SMALL
SMALL

 

Step functions

AWS에서 Step functions이라는 서비스가 있다. 이 서비스는 Step by Step으로 어떤 작업을 수행해나가는 서비스를 말한다. 비즈니스 워크플로우에 맞춰 수행되는 작업이 정해지는 것인데 그것을 람다와 연동해서 사용할 수 있다. 말보다 직접 해보면서 이해하는게 훨씬 더 이해가 수월한듯해서 바로 만들어보자.

 

IAM Role 생성

우선 Step function을 람다와 사용하기 위해선 Role을 새롭게 만들어야 한다. 왜냐하면 Step Functions이 람다 함수에 접근하기 위해 AWS에서 기본으로 제공해주는 역할이 없기 때문이다.

 

역할을 만들기 위해 IAM > Roles > Create role 클릭

 

설정 부분은 다음과 같다.

- Trusted entity type: AWS service

- Use case: Step Functions

 

선택하면 다음과 같이 정책이 미리 선택되어 있다. 확인 후 'Next'

 

다음 화면에서 이름을 적절하게 입력 후 "Create role" 클릭

 

Role을 정상적으로 만들었으면 Roles 리스트에 만든 역할이 잘 보여져야한다.

 

이렇게 Role을 만들었으면 이제 Step Functions에서 사용될 람다 함수를 만들어야한다.

 

Lambda Function 만들기

이름을 Step-1으로 하고 Runtime을 Python3.12로 만들어 볼 예정이다.

 

아래와 같이 간단한 코드를 작성하고 Deploy한다.

 

이제 Step-2 람다 함수를 만든다. 마찬가지로 같은 코드로 작성 후 Deploy한다.

이렇게 간단하게 두개의 람다 함수를 만들고 Step functions을 만들어보자.

 

Step Functions 만들기

AWS Console에 "Step functions"을 검색해서 나오는 서비스를 클릭한다.

 

Step functions을 만들기를 시작하면 다음과 같은 화면이 보이는데 여기서 상단에 "Code" 버튼을 클릭해서 다음과 같은 상태로 만들어주자.

 

"StartAt"은 시작점이 어디인지를 말한다. 아래 States에 여러개의 컴포넌트를 만들면 되는데 컴포넌트들 중 어떤 컴포넌트에서 시작할지를 말한다. 그리고 저 "Code"를 다음과 같이 수정해보자.

 

여기서 "Start"라는 State는 둘 중 하나를 선택하는 형태이다. 그래서 Type은 "Choice"가 된다. 그리고 그 선택지는 "Choices"로 설정해준다. 각 Choice는 Variable 값에 따라 정해진다. 변수로 들어오는 "type"이라는 값이 "first" 또는 "second" 어느것이냐에 따라 다음 State를 결정해준다. 그 State는 Step1, Step2인데 이 녀석들은 만든 람다함수가 된다.

 

Step1, Step2 모두 람다 함수이기 때문에 "Resource"를 지정해주는데 여기서 Resource는 람다 함수의 ARN이 된다.

그리고 이 이후에 끝난다는 것을 알려주기 위해 각 Step1, Step2 모두 "End": true를 입력해준다.

 

이렇게 코드를 작성하면 우측 다이어그램처럼 모양이 나온다.

이렇게 만들고 상단에 "Config" 버튼을 클릭해서 위에서 만든 IAM Role을 적용하자.

 

이 상태에서 우측 상단 'Create' 버튼을 클릭해보자. 그럼 다음과 같이 Step Functions이 만들어진다.

 

여기서 우리가 만든 Step Functions을 테스트해보기 위해 우측 상단 "Start execution" 버튼을 클릭해보자.

그럼 이러한 화면이 노출된다. 여기서 우리가 변수로 받기로 한 "type"을 명시해주면 된다.

 

"Start execution" 버튼을 클릭하면 실행이 된다. 그리고 다음과 같은 화면이 보인다.

 

이 하단에 보면 다이어그램을 통해 어떤 흐름으로 수행됐는지 시각적으로 확인이 가능하다. 

당연히 "type"값을 "first"로 주었기 때문에 Step1이 실행된 모습이다.

 

그럼 만약 "type"이라는 값 말고 "type1" 이라는 키로 잘못 입력하면? 다음과 같은 결과를 얻는다.

 

 

이렇게 Step Functions과 Lambda를 연동해서 사용하는 법을 알아보았다.

728x90
반응형
LIST
728x90
반응형
SMALL
SMALL

 

Lambda의 Layers

Lambda에서 Layer라는 개념이 있다. 이 Layer는 어떤 기능을 하고 왜 있는지 알아보고 직접 적용해보자.

 

Lambda는 너무나도 독립적이기 때문에 생기는 문제가 있다. 예를 들면, 정확히 동일한 패키지와 환경을 사용하더라도 각각의 람다 함수는 독립적으로 해당 환경을 구성해줘야한다. 단적인 예시로 20개의 람다 함수가 있고 그 20개의 람다 함수가 모두 같은 패키지를 사용할때도 각각의 람다함수마다 같은 패키지를 업로드해줘야한다. 이건 효율성도 떨어지지만 비용 측면에서도 상당히 불리하다. 이를 해결하기 위해 어떤 기반으로된 환경위에 람다 함수를 올리게 하는 Layer가 존재한다. Layer는 말 그대로 람다 함수가 올라갈 자리를 말하는것이다. 기본적으로 필요한 패키지나 환경에 대한 설정을 Layer에 깔아둔 후 그 Layer 위에 람다함수를 올리는 것이다.

 

그래서 이 Layer를 만드는 것부터 시작해보자.

 

Layer 생성하기

AWS Console에서 "Lambda"를 검색해서 나오는 서비스를 클릭한다.

 

좌측 사이드바에서 'Layers'를 클릭한 후 나오는 메인 화면에서 우측 상단 Create layer 버튼 클릭.

 

여기서 업로드 할 패키지가 있어야 하는데 이 패키지를 업로드할 때 Zip 파일로 업로드해 볼 예정이다. 그래서 우선 패키지를 내려받아야한다. "requests"라는 파이썬 패키지를 업로드해 볼 것이고 이 패키지를 내려받을 경로 하나를 설정해야 하는데 그 경로가 중요하다. 왜냐하면 경로에 맞는 곳에서 이 Lambda가 패키지를 내려받기 때문에 경로 설정이 상당히 중요한데 이 경로를 당연히 AWS 문서에서 잘 알려준다.

나는 위 문서에 따라 "python/lib/python3.12/site-packages" 이러한 경로 내부에 requests를 내려받기 위해 아래처럼 입력했다.

pip install requests -t .

 

"-t" 옵션을 부여해서 특정 경로에 패키지를 내려받겠다고 선언해주면 해당 경로에 requests 패키지를 사용하기 위해 필요한 모든 dependencies가 내려받아진다.

 

그런 다음 해당 경로 전체를 .zip 파일로 만들어준다.

zip -r python.zip python

 

 이렇게 zip 파일로 필요한 패키지를 묶은 다음 다시 Layer 생성화면으로 돌아가보자.

 

설정 부분은 다음과 같다.

- Name: cwchoiit-python3-layer

- Description: requests package layer

- Upload a .zip file

- Runtimes: Python 3.12

'Create' 버튼을 클릭해서 Layer를 생성하자. 그럼 Layers 리스트에 만든 Layer가 잘 노출된다.

 

이제 기존에 람다함수가 없다고 가정하고 람다함수를 새로 생성해보자. 설정 부분은 다음과 같다. 런타임을 위에 만든 Layer와 잘 맞춰주자.

 

람다 함수를 만들고 나면 만들어진 람다 함수 내부로 들어가서 하단으로 스크롤을 내려보면 다음과 같이 Layers 섹션이 있다. 여기에 "Add a layer" 버튼 클릭

 

Layer를 추가하는 화면이다. 설정 부분은 다음과 같다.

- Layer source: Custom layers

- Custom layers: 방금 만든 layer

- Version: 원하는 버전 선택 (지금은 1밖에 없을 것)

 

Layer가 람다 함수에 잘 추가가 되면 상단에 다이어그램에 다음과 같이 Layer가 0에서 1로 적용된 수가 바뀜을 알 수 있다.

 

그럼 "requests"라는 패키지를 추가했으니까 이 패키지를 임포트할 수 있어야 한다. 임포트 한 후 테스트를 실행해보자.

 

코드에 임포트를 시키고, Deploy - Test를 수행해보자. 

다음과 같이 테스트가 정상적으로 수행되면 Layer가 잘 적용된 것이다.

728x90
반응형
LIST

'AWS' 카테고리의 다른 글

AWS Lambda와 DynamoDB를 연동해보기  (0) 2024.03.04
AWS Lambda와 Step functions  (0) 2024.03.04
AWS Lambda와 API Gateway로 Canary Release 하기  (0) 2024.03.03
AWS Lambda를 API Gateway에 등록하기  (0) 2024.03.03
AWS Lambda  (0) 2024.03.03
728x90
반응형
SMALL
SMALL

 

API Gateway 생성

AWS Console에 API Gateway를 입력하고 나오는 서비스를 클릭

 

종류는 다음과 같이 3가지에 + REST API Private 형태가 있다. 나는 REST API 타입을 선택하겠다.

 

설정 부분은 다음과 같이 설정한다.

- New API

- API name: cwchoiit-api-gateway

- API endpoint type: Regional

 

만들고 나면 다음과 같은 화면이 노출된다.

 

좌측 'Create resource' 버튼을 클릭하면 새로운 path를 생성할 수 있고 현재는 그게 아니라 이 기본 루트 path에 메서드를 생성해서 내가 만든 람다 함수를 연결해보자. 우측 'Create method' 버튼 클릭

 

설정 부분은 다음과 같다.

- Method type: GET

- Integration type: Lambda fuction

- Lambda function: ap-northeast-2 / 만든 람다 함수

 

만들고 나면 다음과 같이 "/" path에 GET으로 호출하는 API 하나가 보여진다.

 

이제 이 API Gateway를 배포해보자. 우측 Deploy API 버튼 클릭

설정 부분은 다음과 같다.

- Stage: New stage

- Stage name: prod

 

배포하면 다음과 같이 API Gateway가 만들어진다. 아래 URL로 접속해보자. 

 

우리가 만든 람다 함수가 실행되고 응답하는 모습을 볼 수 있다.

 

이렇게 간단하게 람다를 사용해서 서버가 필요없이 REST API 서버를 구축할 수 있다.

728x90
반응형
LIST

'AWS' 카테고리의 다른 글

AWS Lambda와 Layers  (0) 2024.03.04
AWS Lambda와 API Gateway로 Canary Release 하기  (0) 2024.03.03
AWS Lambda  (0) 2024.03.03
AWS KMS를 사용해서 암호화 - 복호화하기  (0) 2024.02.26
NACL과 Security Group  (0) 2024.02.21
728x90
반응형
SMALL
SMALL

AWS Lambda

Lambda는 AWS에서 제공해주는 서버리스 서비스이다. 서버리스(Serverless)란 말 그대로 서버가 없다는 의미고 그 말은 진짜 서버가 아예 없다는게 아니라 관리할 서버가 없다. 즉, 관리할 필요가 없다란 의미가 된다.

 

개발자는 서버를 관리할 필요없이 애플리케이션을 빌드하고 실행할 수 있도록 하는 클라우드 네이티브 개발 모델을 서버리스 아키텍트라고 한다. 이 구조의 장점은 항상 대기하고 있는 전용 서버가 없어서 실행이 끝나면 자원을 반납하고 사용할 때만 자원을 가져다가 사용하는 구조라고 할 수 있다. 그러나 장점만 있는 구조는 없다. 장점과 단점을 둘 다 알아보자.

 

  • 장점
    • 서버 관리(자동 확장, 장애 방지)가 불필요
    • 관리보다 개발에 집중이 가능
    • 사용한 만큼 과금
    • 급격한 트래픽 변화에 유연
  • 단점
    • 다른 클라우드 컴퓨팅 자원보다 비쌈
    • 느림(호출과 동시에 서버가 세팅되기 때문)
    • 장기적인 작업에는 적합하지 않음
    • 함수의 처리 결과에 따라 상태를 따로 저장

 

단점 중 장기적인 작업에는 적합하지 않다라고 되어 있는데 이 말은 한 작업이 1시간, 2시간 또는 그 이상의 시간을 소요하는 작업이라면 그 시간만큼 과금이 되기 때문에 다른 클라우드 컴퓨팅 자원보다 비싼 과금을 내는 서버리스보단 온프레미스나 클라우드 컴퓨팅 서버를 사용하는게 더 유리할 수 있다는 소리다. 

 

서버리스의 2가지 서비스 형태

  • BaaS(Backend As a Service)
    • 클라우드 공급자가 제공하는 서비스를 이용해 백엔드 기능들을 쉽게 구현
    • Customizing이 어렵다
    • Google Firebase
  • FaaS(Function As a Service)
    • FaaS는 기능을 하나의 함수로 구현
    • 함수가 실행할 때마다 서버 자원을 할당받아 사용
    • 로직을 개발자가 작성하므로 Customizing이 가능
    • AWS Lambda

 

AWS Lambda 구축하기

이제 람다가 어떤것인지 알았으니 한번 만들어보고 사용해보자.

우선 AWS Console에 "Lambda"를 입력하고 나온 서비스를 클릭한다.

 

Create a function 버튼 클릭

 

설정화면은 다음과 같이 설정한다.

 

- Author from scratch

- Function name: cwchoiit-first-lambda

- Runtime: Python 3.12

Runtime은 어떤 환경을 사용할 것인지를 의미한다. NodeJS, Java 등등 다양하게 있다. 본인은 Python을 선택했다.

 

이 상태로 Create function 버튼을 클릭하면 Lambda가 만들어지면서 다음 화면이 노출된다.

 

아래 코드를 보자. 간단한 파이썬 코드로 된 함수 하나가 있다. 이 코드가 곧 하나의 람다 함수가 된다. 이 소스를 실행하기 위해 "Test" 버튼을 클릭해보자.

 

그럼 이러한 화면이 보여지는데 우선 Event name만 입력해보고 "Save" 버튼을 클릭해보자.

 

그러면 이렇게 내가 만든 이벤트 하나가 리스트에 보여진다. 이 이벤트를 클릭하면 아까 구성한대로 이벤트가 트리거될 준비가 된 상태이고 "Test" 버튼을 클릭하면 그 이벤트가 실행된다.

 

다음은 테스트 실행 결과다. 이벤트 이름, 응답 등등이 보여지고 코드에서 리턴하는 내용처럼 응답에는 statusCodebody값이 있다.

 

그럼 아까 이벤트를 만들 때 이 부분이 무엇인지 알아보자.

 

람다 함수는 이 함수로 들어오는 데이터 같은 것들을 이벤트로 받아준다. 그 이벤트를 출력해보자.

 

이렇게 소스를 변경하면 Deploy 버튼을 클릭해서 새롭게 소스를 배포해야 한다.

 

배포가 끝나면 다시 테스트 버튼을 클릭해보자. 이 이벤트에 대한 내용이 출력될 것이다.

 

이렇게 이벤트를 출력하면 테스트 구성시에 작성했던 데이터가 담겨있는 것을 알 수 있다. 이렇듯 람다 함수에 뭔가를 전달할 때 이벤트라는 파라미터안에 그 데이터들이 담긴다고 생각하면 된다.

 

그리고 이 실행에 대한 로그를 볼 수 있는데 로그는 CloudWatch에 기록된다. 한번 확인해보자. 위에 탭 중에 Monitor 탭이 있다. 해당 탭을 누르면 다음 화면이 보이는데 여기서 View CloudWatch logs 버튼을 클릭하자.

 

그럼 이러한 화면이 보여진다. 내가 만든 람다 함수에 대한 로그가 기록되어있다. 그리고 저 아래 빨간 표시로 해둔것은 배포 버전별로 다르게 기록되는 로그이다. 처음 람다함수를 만들면 그게 최초 배포버전이고 내가 중간에 이벤트를 찍어보겠다고 소스를 변경하고 배포를 다시했기 때문에 저렇게 두 개의 다른 로그가 쌓인다고 보면된다. 배포를 새로 또 하면? 3개가 된다.

 

안으로 들어가보면 다음처럼 화면이 보여진다. 내가 찍은 "print(event)" 역시 로그로 남게 된다. 이렇게 로그도 확인이 가능하다.

 

이렇게 간단하게 AWS Lambda 함수를 생성해서 서버리스 서비스를 구현해보았다. 이 서버리스를 API Gateway에 붙여서 실제 서버가 있는것처럼 실행하게 만들수도 있다. 그 부분을 다음 포스팅에서 해보자.

728x90
반응형
LIST
728x90
반응형
SMALL
SMALL

 

이번엔 데이터를 보관하고 읽어들일 수 있는 스토리지인 S3 서비스를 생성해보자.

 

S3 버킷 만들기

Amazon S3에서 데이터들을 담고 보관하는 장소를 버킷이라고 표현한다. 버킷을 만들어보자.

AWS Console에서 'S3'를 검색한다. 

 

메인화면 우측 상단에 'Create bucket' 버튼을 클릭한다.

 

상단부터 버킷 이름지역을 선택한다.

 

'Object ownership'은 기본 설정인 'ACLs disabled'를 선택한다. 이건 모든 오브젝트들은 현재 버킷을 만들고 있는 유저가 전부 Owner인 케이스를 말한다.

 

Block Public Access settings for this bucket 설정은 'Block all public access'를 선택 해제하고 진행한다. 외부에서 바로 이 Object에 접근해보는걸 테스트해보기 위함이다.

 

그 외 나머지 세팅 역시 전부 기본으로 설정된 채로 진행하고 하단 'Create bucket' 버튼을 클릭한다. 그러면 다음처럼 버킷이 생성된다.

 

버킷안으로 들어가보면 여러 탭이 존재하는데 'Objects' 라는 탭이 실제 업로드 되는 데이터들이 모여져 있는 곳이다. 그니까 파일이 3개면 3개 하나하나가 각각 오브젝트 하나하나가 되는 것이다. 여기에 우측 상단 'Upload' 버튼을 눌러 아무 이미지나 업로드해보자.

본인은 이미 이미지 하나를 업로드 한 상태이다.

 

업로드하고 'Permissions' 탭을 눌러 버킷 정책을 설정할 수 있다. 해당 탭을 눌러 화면을 살짝 내려가보면 'Bucket policy' 부분이 있다. 여기서 버킷 정책을 설정할 수 있다. 'Edit' 버튼을 눌러 버킷 정책을 만들어보자.

 

다음과 같이 설정한다.

 

  • Version: '2012-10-17'이 의미하는 건 policy language의 현재 버전을 의미한다. 그래서 반드시 이 값을 사용해야 한다. 이 값 말고 하나 더 유효한 게 2008-10-17이 있다. 이건 이전 버전이다. 이 버전은 사용하지 말고 지금처럼 2012-10-17 버전으로 사용하면 된다. 
  • Statement: 이 요소는 정책에 대해서 주 요소이다. 필수 값이고 하나 이상의 개별적인 statement가 포함된다. 그러니까 쉽게 말해 정책에 대한 실질적인 적용을 하는 부분으로 생각하면 되겠다.
  • Sid: Statement ID의 약자이다. 그냥 policy statement의 identifier라고 생각하면 된다. 없어도 무방하다.
  • Effect: 필수값이며 유효한 값은 "Allow", "Deny"가 있고 Resource에 대한 Action을 허가 또는 제어하는 키워드이다. 
  • Principal: resource-based JSON policy에서 사용되며 resource 기반의 정책에서는 이 값은 필수이다. 쉽게 말해 Resource에 대한 Action을 행하는 대상을 지정하는 것이다. 예를 들면 AWS account가 '123456789012' '555555555555' 인 두명의 유저에 대해서 적용하겠다하면 다음처럼 작성한다.  
"Principal" : { 
"AWS": [ 
  "123456789012",
  "555555555555" 
  ]
}

더 많은 내용은 공식 홈페이지 참조해서 정책에서 사용되는 JSON elements를 공부해보자.

 

AWS JSON policy elements: Principal - AWS Identity and Access Management

If your Principal element in a role trust policy contains an ARN that points to a specific IAM user, then IAM transforms the ARN to the user's unique principal ID when you save the policy. This helps mitigate the risk of someone escalating their privileges

docs.aws.amazon.com

 

 

 

참고로 이 Principal과 같이 알아야할 게 NotPrincipal이 있는데 이건 부정이다. 즉, Effect가 Allow일 때 NotPrincipal은 제외시키는 것이고 Effect가 Deny일 때 NotPrincipal은 허가하는 것.

  • Action: 구체적인 행위를 서술한다. 이 값은 필수값이고 "s3:GetObject"라고 작성하면 S3 서비스의 버킷 오브젝트를 Get하는것에 대한 행위를 말한다.
  • Resource: 말 그대로 리소스를 말한다. arn:aws:s3:::my-first-s3-bucket-cwchoi/* 이렇게 적으면 S3 서비스의 my-first-s3-bucket-cwchoi 이름으로 된 버킷의 모든 오브젝트 리소스를 뜻한다.

 

이렇게 버킷 정책을 만들고 하단 'Save changes' 버튼을 클릭한다. 적용된 화면은 다음과 같다.

 

이제 방금 올린 Object의 리소스를 HTTPS 프로토콜을 통해 접근해보자. 특정 Object에 들어가면 하단 사진처럼 Object URL이 있다.

들어가보면 이미지가 정상 노출되어야 한다. 버킷 정책에서 모든 유저에게 읽기 권한을 부여했으므로. 

 

 

S3 버킷 삭제하기

버킷을 만들었으니 삭제도 해보자. EC2 인스턴스 삭제하는 것과 유사해서 간단하다.

우선 버킷을 삭제하기 전 Object가 있으면 안된다. 그래서 오브젝트를 전체 지우고 버킷을 지워야한다. 

Objects 탭에서 전체 선택해서 'Delete' 버튼 클릭해서 지우자.

 

다 지웠으면 버킷 페이지로 돌아와서 버킷 선택 후 'Delete' 클릭

 

 

728x90
반응형
LIST
728x90
반응형
SMALL
SMALL

 

공동 책임 모델은 장애가 발생했을 때 책임이 누구에게 있는지를 규정한 것을 말한다. 

 

AWS Shared Responsibility Model

출처: AWS 공식 홈페이지

위 그림이 AWS가 책임지는 부분과 AWS를 사용하는 고객이 책임지는 부분을 나뉘어 놓은 공동 책임 모델이다. 

AWS가 책임져야 하는 부분으로는 AWS에서 제공하는 모든 하드웨어 관련 인프라에 대한 책임을 지고 관리형으로 제공하는 소프트웨어 중에 모든 책임을 가지고 있다. 

 

예를 들어, EC2 인스턴스 자체에 문제가 생기는 경우 AWS가 책임을 진다. 그러나 EC2 인스턴스 위에 올라가 있는 애플리케이션에 문제가 생기면 그것은 고객의 책임이다. EC2 인스턴스 위에 올라가있는 구성 시스템에 대한 모든 보안 작업은 고객의 책임이다. OS 업데이트, 보안 패치도 직접 관리해야 하고 인스턴스에 설치한 모든 소프트웨어, 유틸리티 관리는 모두 고객에게 책임이 있다. 

 

 

AWS Compliance Programs

AWS 규정 준수 프로그램이다. AWS위에 구축하고자 하는 서비스가 특정 규정을 반드시 준수해야 할 때 그것이 AWS 규정 준수 프로그램에 포함되어 있는지 반드시 확인해야 한다. 

 

AWS 규정 준수 프로그램은 다음 사진처럼 있다.

출처: AWS 공식 홈페이지

 

 

마무리

AWS를 사용하기 전 이러한 정보를 알고 서비스를 그 위에 올려야 한다. 

 

728x90
반응형
LIST

'AWS' 카테고리의 다른 글

Part 6. EC2 서비스 생성 및 Nginx 실행해보기  (0) 2024.01.11
Part 5. AWS IAM  (0) 2024.01.11
Part 3. AWS 주요 서비스  (0) 2024.01.10
Part 2. AWS Region, Availability Zone, Edge Location  (2) 2024.01.10
Part 1. 클라우드 서비스  (0) 2024.01.10
728x90
반응형
SMALL
SMALL

 

AWS에서 제공하는 주요 서비스들을 알아보자. 

AWS에는 무수히 많은 서비스가 있고 위 그림만 봐도 각 카테고리 별 주요 서비스들이 있다. 차근차근 알아보자.

 

EC2 (Compute)

Elastic Compute Cloud의 약자이다. AWS에서 가장 대표적인 IaaS로 가상 머신 서비스이다. 

다양한 OS를 지원하며 (Linux(CentOS, Ubuntu, RedHat, SUSE), Windows,...) Auto Scaling을 통한 탄력적 확장/축소가 가능하다. 

 

성능에 따라 다양한 인스턴스의 타입이 있는데 다음 표를 보자.

컴퓨팅 목적 종류(Family) 의미
범용 컴퓨터 타입 (General Purpose) T-family (T2, T3, T3a, T4g,...)
M-family (M4, M5zn, M5n, M5a,...)
T - Tiny
M - Main
컴퓨팅 최적화 (Compute Optimized) C-family (C4, C5n, C5a, C5,...) C - Compute
메모리 최적화 (Memory-Optimized) X-family (X1, X1e, X2gd)
R-family (R4, R5n, R5b,...)
X - eXtreme
R - RAM
가속 컴퓨팅 (Accelerated Computing) G-family (G3, G4ad, G4dn,...)
P-family (P2, P3, P4)
F - FPGA
G - Graphics
Inf - Inference
P - Picture
스토리지 최적화 (Storage Optimized) I-family (I3, I3en,...)
D-family (D2, D3, D3en)
H - HDD
I - IOPS
D - Dense

 

이러한 목적에 따라 종류(family)가 나뉘어져 있고 예를 들어 다음 그림을 보자.

 

이처럼 여러 종류가 있는데 이 각 인스턴스 타입이 뭘 의미하는지는 다음과 같다.

  • t4g.xlarge: t(인스턴스 패밀리)4(인스턴스 세대)g(추가 기능).xlarge(인스턴스 사이즈)

 

 

Lambda (Compute)

서버리스 컴퓨팅 서비스이다. FaaS(Function as a Service)이며 단순히 Function을 생성해서 애플리케이션을 개발하고 실행할 수 있도록 해주는 서비스. 다양한 언어를 지원한다(Go, Java, Python, NodeJS, C#,...)

실제로 서버가 없는 서버리스 서비스이기 때문에 함수가 동작하지 않을 땐 과금되지 않는다. 이에 따라 배치성 작업에 자주 사용된다.

 

 

 

Amazon S3 (Storage)

Simple Storage Service의 약자 S3이다. 객체 스토리지 서비스이며 OS상에서 마운트하여 사용하는 블록 스토리지와는 다르게 Restful API를 사용하여 객체에 엑세스한다. 그렇기 때문에 HTTP/HTTPS 프로토콜을 사용하며 이미지, 동영상과 같은 정적 컨텐츠를 다루는데 자주 사용된다. 저장 가능한 파일 개수 제한은 없지만 단일 파일 크기가 5TB 까지 가능하다.

 

높은 내구성(99.999999999%)을 가지는 것으로 유명하다. 

S3는 버킷(Bucket)이라는 개념이 있는데 이 버킷이 말 그대로 파일을 저장하는 스토리지라고 생각하면 되고 이 버킷에 들어가는 파일 하나하나를 Object라고 한다. 그래서 사용자는 Object를 REST API를 통해 접근하게 되고 당연히 접근 권한을 제어할 수 있다.

 

 

Amazon EBS (Storage)

Elastic Block Storage Service의 약자로 블록 스토리지 서비스이다. OS 내부에서 마운트하여 사용하는 블록 스토리지다. EC2에 붙이거나 뗄 수 있고 SSD/HDD 볼륨 타입을 가지고 있다. EBS는 용량이 부족한 경우 확장이 가능하나 축소는 불가한 점이 있다.

 

 

Amazon EFS (Storage)

Elastic File System의 약자로 파일 스토리지 서비스이다. Network File System(NFS) 버전4를 지원하고 그에 따라 여러 곳에서 동시에 같은 파일(공유 스토리지)에 접근하는 경우가 빈번할 때 주로 사용한다. EFS는 EBS와는 다르게 처음에 스토리지를 미리 확보해두지는 않고 사용한 만큼 용량을 차지하고 그만큼만 비용을 지불한다. 

 

이 EFS 역시 기본적으로 버스팅 기능을 제공하기 때문에 잦은 읽기/쓰기가 발생하는 경우 성능 저하가 발생할 수 있다.

 

 

Amazon VPC (Network)

Virtual Private Network Computing의 약자로 IP 대역(CIDR)을 할당하여 가상 사설 네트워크를 구성한다.

가상의 사설망으로 구성하기 때문에 On-Premise에서 사설 네트워크망을 구축하는 것과 동일하게 구축이 가능하다.

 

서브넷과 라우팅테이블을 이용해서 외부에서 접근 가능한 Public 네트워크 Subnet과 외부에서 접근 불가한 Private 네트워크 Subnet을 구성할 수 있다. 특정 대역을 구분해서 여러 서브넷을 구분할 수 있다.

 

VPC Flow Log라는 기능을 사용해서 내부에서 일어나는 트래픽을 분석할 수 있다. 

 

또한, VPC는 사설망으로 구성되기 때문에 서로 다른 VPC끼리 통신이 불가능한게 원칙이지만 여러개의 VPC를 하나의 사설 네트워크망으로 사용할 수 있도록 하려면 VPC Peering/Transit Gateway를 사용하면 된다.

 

VPC Peering

위 그림처럼 여러 VPC를 연결하여 같은 Region이든 다른 Region이든 서로 통신이 가능하도록 설정하는 것이 가능하다.

 

 

Transit Gateway

 Transit Gateway는 여러 VPC간 연결 정책을 중앙에서 관리해주는 서비스이다. 이 Transit Gateway를 사용하면 VPC연결뿐 아니라 VPN Connection을 통해 On-Premise와의 연결 또한 중앙에서 관리가 가능하다. 연결을 해야하는 VPC가 많으면 많을수록 관리적인 측면에서 중앙에서 관리해주는 Transit Gateway가 VPC Peering보다 더 효율적일 것으로 생각된다.

 

VPC Peering과 Transit Gateway의 차이점을 살펴보자면 다음과 같다.

VPC Peering Transit Gateway
대역폭 제한이 없음 최대 대역폭 50Gbps
Peering 연결 수는 VPC당 125개 Transit Gateway당 최대 5000개의 VPC 연결 가능
Transit Gateway 대비 약 1.5배 가량 저렴  

 

 

AWS Cloudfront (Network)

 

CDN(Contents Delivery Network) 서비스이다. CDN은 클라이언트가 인터넷에 접속하는 곳(지역)과 가까운 곳에서 원본 데이터 서버(Origin)로부터 컨텐츠를 캐싱해둔 서버(Edge Location)에서 빠르게 응답하는 기술(캐싱)이다.

 

또한, 로드밸런싱과 장애 발생 시 다른 인스턴스로부터 데이터를 가져오는 장애처리 기술도 가지고 있다.

 

위 설명에서 이 CloudFront를 사용할 때 캐싱의 도움을 받을 수 있다는 것은 새로운 컨텐츠가 원본 서버에 업데이트 되면 그 캐시에 대한 무효화도 일어나야 한다는 것을 암시한다. 이 CloudFront에서는 이 캐시를 무효화하는 것을 Invalidation이라고 하는데 다음 그림과 같다.

 

 

 

Amazon Route53 (Network)

 

AWS DNS 서비스로 도메인을 구매 또는 등록할 수 있는 서비스이다. 인터넷 트래픽을 리소스로 라우팅을 해주며 여러 라우팅 정책이 있다. (simple, weighted, latency, failover, geolocation,...)

 

한 블로그에서 아주 잘 만든 라우팅 정책 그림이 있길래 가져왔다. 

 

What are the different Route 53 Routing Policies?

Simple Route traffic to a single resource. As simple as that ! Weighted Specify how much % of...

dev.to

 

 

 

Amazon RDS (Database)

Relational Database Service의 약자로 관계형 데이터베이스 서비스이다. 다양한 DB 엔진(Oracle, MariaDB, MySQL, PostgreSQL,...)을 제공하며  즉각적인 DB 컴퓨팅 사이즈 조정이 가능하다. 자동 백업을 통해 가용성과 내구성을 향상시킬 수 있다. 관리 부담 감소와 사용성 편의도 장점으로 볼 수 있다.

 

Multi AZ 구성을 이용해 장애처리 기술을 보유하고 있다.

 

RDS Read Replica 구성도 취할 수 있는데 이는 무엇이냐면 Master DB에 부하분산처리를 위해 읽기 전용 Replication을 여럿 만들어 두고 Master DB에 부하 발생 시 읽기 트랜잭션을 Replication에게 위임하는 것이다. 

 

 

 

Amazon DynamoDB (Database)

완전관리형 NoSQL 데이터베이스이다. SSD기반의 무제한 스토리지로 Key/Value 형태로 데이터를 저장한다.

10m/s 미만의 빠른 응답 시간을 가지고 있으며 확장이 단순하고 신속하다. 자동 이중화 백업을 해준다. 

 

 

 

Elasticache (Database)

 

완전관리형 In-Memory Cache 서비스이다. 인 메모리 캐시에서는 가장 대표적인 기술로 Redis, Memcached가 있는데 그것들의 기술 엔진을 이용한다. Elasticache for Redis는 3가지 클러스터 형태가 존재하는데 다음과 같다.

  싱글 클러스터 클러스터 모드 비활성 클러스터 모드
Replication X O(최대 5개) O
Data Partitioning O X O
Scaling Scale Up/Down Scale Up/Down Scale In/Out(Shard)
Multi AZ X 최소 1개 Replica 필요 O

 

 

 

Amazon WAF (Security)

관리형 웹 방화벽 서비스로 HTTP/HTTPS의 트래픽을 관리하고 부정 접근을 차단하여 고객의 애플리케이션을 보호하는 서비스이다. 방어하는 웹 공격의 종류에는 OWASP TOP 10(SQL injection, XSS,...)을 대응하며 이에 대응할 수 있는 보안 규칙을 설정할 수 있다. WAF는 CloudFront, Application LB에서 기본적으로 사용할 수 있도록 내재되어 있는 서비스이다. AWS 관리형 규칙과 사용자 지정 규칙을 지정할 수 있고 사용자 지정 규칙이라함은 IP, 국가, 헤더 등 차단 규칙을 설정하는 것을 말한다. 

 

Cloudwatch를 통해 실시간으로 웹 보안 모니터링이 가능하고 AWS 서비스를 활용한 로그 통합(Kinesis Data Firehose, S3)을 하여 분석도 가능하다.

 

AWS WAF Architecture

 

1. CloudFront가 웹 애플리케이션 앞 단에서 요청들을 받고, 요청에 대한 구체적인 정보들을 담아서 S3 버킷으로 access log를 보낸다.

2. S3 버킷에 신규 액세스 로그들이 저장될 때 마다 람다 펑션이 동작한다.

3. 람다 펑션은 어떤 IP로부터 기준치 이상의 요청이 들어 왔는지 분석하고, AWS WAF 블랙리스트에 추가한다. AWS WAF는 지정된 기간동안 해당 IP를 블락한다. 이 지정된 기간이 끝나면 AWS WAF는 다시 해당 IP로부터의 요청을 수락한다. 단, 해당 IP로부터의 트래픽 모니터링은 계속된다.

4. 람다 펑션은 분석된 요청들의 갯수나 블락된 IP 주소의 갯수같은 CloudWatch 매트릭들을 퍼블리시한다.

 

AWS WAF는 수정 가능한 웹 보안 규칙을 정의하고 이것을 통해 웹 애플리케이션으로의 트래픽을 허용하거나 차단하는 기능을 제공한다. 이 서비스에서는 아래와 같이 3가지 규칙을 사용하게 된다.

  • 자동 블락킹 - 이 규칙은 악성 요청으로 식별된 IP주소를 추가한다. 이 규칙을 설정함과 동시에 블랙리스트된 IP주소들로부터 들어오는 모든 신규 요청을 드랍하고 람다가 지정한 폐기 기간이 지나 해당 IP를 블랙리스트에서 제거하기 전까지 유효하게 동작한다.
  • 수동 블락킹 - 이 규칙은 수작업으로 특정 IP 주소를 블랙리스트에 추가하는데 사용된다. 해당 IP주소는 관리자가 수작업으로 리스트에서 제거하기 전까지 계속 블락된다.
  • 자동 카운트 - 지정된 IP로부터의 요청이 바로 블락킹되지는 않고, 준 실시간성으로 요청 갯수가 트랙킹됩니다. 이를 통해 자동 블락 리스트에서 제거된 이후 해당 IP의 행동에 대한 가시성을 제공해 줄 수 있습니다.

 

 

Amazon Shield (Security)

관리형 DDOS 차단 솔루션이다. DDOS 공격은 네트워크 트래픽을 의도적으로 과다하게 키워 컴퓨터 자원에 과부하를 거는 공격인데 이 DDOS 공격을 받으면 서비스 성능 저하나 다운 현상이 일어나게 되는데 이를 막기 위해 이 서비스가 있다. 이 서비스는 Standard 형태로 무료로도 사용할 수 있다. 그렇다는 것은 Advanced 형태로 유상 서비스도 있다.

 

 

 

Amazon KMS (Security)

Key Management Service의 약자로 AWS 키 관리 서비스이다. 리소스 데이터 암호화/복호화 기능과 디지털 서명 및 확인 기능이 있다.

 

 

 

 

Amazon Cloudwatch (Administration/Monitoring)

AWS 사용하면서 가장 많이 보게 되는 서비스 중 하나가 이 CloudWatch 서비스이다. 관리형 AWS 리소스 모니터링 서비스로 AWS 리소스의 상태에 대한 다양한 Metrics 제공을 한다. 이 다양한 리소스 상태에 대한 메트릭을 대시보드로 구성할 수 있고 SNS 서비스를 통한 알람 기능도 있다. 

 

그러니까 AWS 리소스가 사용되고 모니터링 지표 수집이 되면 CloudWatch가 그 데이터를 받아서 대시보드로 보여주고 특정 Event가 발생하는 경우 SNS 기능을 통해 정해진 유저로부터 알람 기능도 제공할 수 있다. 

 

 

Amazon SNS (Administration/Monitoring)

관리형 메시지 서비스. SMS 문자, 푸시 알림, 이메일 등을 통해 고객에게 알림(A2P, Application To Person)을 배포할 수 있으며 A2A(Application To Application)알림을 제공하여 분산 애플리케이션을 통합하고 분리할 수 있다.

 

 

 

Amazon Cloudtrail (Administration/Monitoring)

관리형 이벤트 추적/감사 도구. AWS 서비스가 수행하는 모든 작업들을 이벤트 로그로 기록을 한다. 이 때 이벤트는 AWS CLI, AWS SDK, Console등 API로 수행하는 모든 작업을 말하며 이 CloudTrail을 통해 AWS 인프라 전반에 걸친 계정 활동을 관리 콘솔 UI를 통해 쉽게 검색하여 확인이 가능하다. 로그 양이 굉장히 많기 때문에 로그 분석 지원 서비스인 Athena를 같이 이용하기도 한다.

 



728x90
반응형
LIST

+ Recent posts