Terraform 활용하여 AWS Media컨텐츠 제공하는 인프라 구성 - Backend

empty·2020년 9월 28일
0

백엔드 인프라

구성순서

백엔드 인프라

  • 1. IAM
    • MediaConvert를 사용할 seunghyeon-mediaconvert
    • Lambda를 사용할 seunghyeon-lambda
      • MediaConvert의 권한 즉, seunghyeon-mediaconvert의 role을 얻어야 한다.
  • 2. S3
    • 원본 미디어가 저장될 seunghyeon-project-originalmedia
    • 변환된 미디어가 저장될 seunghyeon-project-transcodedmedia
  • 3. Lambda
    • MediaConvert

1. IAM

iam.tf

# Create MediaConvert IAM Role
resource "aws_iam_role" "seunghyeon-mediaconvert" {
  name = "seunghyeon-mediaconvert"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "mediaconvert.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
}
# Attach Policy for MediaConvert IAM Role
resource "aws_iam_role_policy_attachment" "AmazonS3FullAccess" {
  role       = aws_iam_role.seunghyeon-mediaconvert.id
  policy_arn = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
}
resource "aws_iam_role_policy_attachment" "AmazonAPIGatewayInvokeFullAccess" {
  role       = aws_iam_role.seunghyeon-mediaconvert.id
  policy_arn = "arn:aws:iam::aws:policy/AmazonAPIGatewayInvokeFullAccess"
}

# Create Lambda IAM Role
resource "aws_iam_role" "seunghyeon-lambda" {
  name = "seunghyeon-lambda"
  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
}
# Attach Policy for Lambda IAM Role
resource "aws_iam_role_policy_attachment" "AWSLambdaBasicExecutionRole" {
  role = aws_iam_role.seunghyeon-lambda.id
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
resource "aws_iam_role_policy_attachment" "AWSLambdaFullAccess" {
  role = aws_iam_role.seunghyeon-lambda.id
  policy_arn = "arn:aws:iam::aws:policy/AWSLambdaFullAccess"
}
resource "aws_iam_role_policy_attachment" "AmazonS3FullAccess2" {
  role       = aws_iam_role.seunghyeon-lambda.id
  policy_arn = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
}

resource "aws_iam_role_policy" "customizing" {
  role = aws_iam_role.seunghyeon-lambda.id
  policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "*",
            "Effect": "Allow",
            "Sid": "Logging"
        },
        {
            "Action": [
                "iam:PassRole"
            ],
            "Resource": [
                "${aws_iam_role.seunghyeon-mediaconvert.arn}"
            ],
            "Effect": "Allow",
            "Sid": "PassRole"
        },
        {
            "Action": [
                "mediaconvert:*"
            ],
            "Resource": [
                "*"
            ],
            "Effect": "Allow",
            "Sid": "MediaConvertService"
        },
        {
            "Action": [
                "s3:*"
            ],
            "Resource": [
                "*"
            ],
            "Effect": "Allow",
            "Sid": "S3Service"
        }
    ]
}
EOF
}

야물딱지게 요약

  • aws_iam_role: seunghyeon-mediaconvert
    • aws_iam_role_policy_attachment: AmazonS3FullAccess
    • aws_iam_role_policy_attachment: AmazonAPIGatewayInvokeFullAccess
  • aws_iam_role: seunghyeon-lambda
    • aws_iam_role_policy_attachment: AWSLambdaBasicExecutionRole
    • aws_iam_role_policy_attachment: AWSLambdaFullAccess
    • aws_iam_role_policy: customizing
      #이 곳에는 사용자 정의 정책을 정의한다.

유의사항

aws_iam_role로 롤을 생성하면 assume_role_policy을 필수로 기입해야 하는데 이 곳에는 신뢰할 수 있는 개체를 정의해야 한다.

즉, lambda에서 해당 롤을 사용하려면 assume_role_policy에 lambda 서비스를 신뢰할 수 있게 정책을 설정해야 한다. (설정하지 않으면 role 선택을 못함)

2. S3

s3.tf

# Create Original S3
resource "aws_s3_bucket" "original" {
  bucket = "seunghyeon-project-original"
  acl = "private"

  versioning {
    enabled = true
  }
  cors_rule {
    allowed_headers = ["*"]
    allowed_methods = ["GET"]
    allowed_origins = ["*"]
    max_age_seconds = 3000
  }

  website {
    index_document = "index.html"
  }
}
resource "aws_s3_bucket_policy" "b" {
  bucket = aws_s3_bucket.original.id

  policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": [
              "arn:aws:s3:::${aws_s3_bucket.original.id}/*"
              ]
        }
    ]
}
EOF
}

# Create transcoded S3
resource "aws_s3_bucket" "transcoded" {
  bucket = "seunghyeon-project-transcoded"
  acl = "private"

  versioning {
    enabled = true
  }
}
resource "aws_s3_bucket_policy" "c" {
  bucket = aws_s3_bucket.transcoded.id
  policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": [
              "arn:aws:s3:::${aws_s3_bucket.transcoded.id}/*"
              ]
        }
    ]
}
EOF
}

# Upload 'test.mp4' to Original Bucket
resource "aws_s3_bucket_object" "test" {
  bucket = aws_s3_bucket.original.id
  key = "test.mp4"
  source = "test.mp4"
  depends_on = [aws_s3_bucket_notification.original-bucket-trigger]
}

설명

원본 미디어가 저장될 "seunghyeon-project-original" 버킷과 Lambda에 의해 변환된 미디어가 저장될 "seunghyeon-project-transcoded" 버킷을 생성한다.

이 때 원본미디어 버킷에 CORS 설정을 해주고 정적 웹사이트 호스팅 기능을 설정해준다. (CloudFront에 연결하기 위함????? 정확히 몰라)

정책은 [추가예정]

버킷설정이 끝나면 원본 미디어가 저장될 버킷에 test.mp4 파일을 업로드 한다. (test.mp4파일은 terraform 명령어를 실행하는 디렉터리에 같이 존재해야 한다.)

  • depends_on을 추가하여 S3 bucket 트리거(aws_s3_bucket_notification)가 추가된 후에 업로드가 되는걸로 설정한다.

야물딱지게 요약

  • aws_s3_bucket: seunghyeon-project-original
    • aws_s3_bucket_policy: b
  • aws_s3_bucket: seunghyeon-project-transcoded
    • aws_s3_bucket_policy: c
  • aws_s3_bucket_object: test.mp4
    #이 곳에는 사용자 정의 정책을 정의한다.

3. lambda

lambda.tf

resource "aws_lambda_function" "mediaconvert" {
  function_name = "seunghyeon-testing"
  handler = "convert.handler"
  filename = "VODLambdaConvert.zip"
  role = aws_iam_role.seunghyeon-lambda.arn
  runtime = "python3.8"

  environment {
    variables = {
      "DestinationBucket" = aws_s3_bucket.transcoded.id,
      "MediaConvertRole" = aws_iam_role.seunghyeon-mediaconvert.arn
      "Application" = "VOD"
    }
  }
}

resource "aws_lambda_permission" "function_permission" {
  action = "lambda:InvokeFunction"
  function_name = aws_lambda_function.mediaconvert.function_name
  principal = "s3.amazonaws.com"
  source_arn = aws_s3_bucket.original.arn
}

resource "aws_s3_bucket_notification" "original-bucket-trigger" {
  bucket = aws_s3_bucket.original.id

  lambda_function {
    lambda_function_arn = aws_lambda_function.mediaconvert.arn
    events = [
      "s3:ObjectCreated:Put"]
  }
}

이제 백엔드 인프라를 구성완료 하였다. 다음 포스팅에서는 프론트엔드를 구성한다.

0개의 댓글