DevOps/AWS

[API Gateway] Private VPC 로 구축 방법

깜태 2022. 11. 24. 16:14
728x90

상황 설명

Private VPC 망에서 간단한 API를 작업할 일이 생겼다.

서버를 구축하기엔 API 빈도가 적어서 오버헤드가 크다고 판단하여, API Gateway + Lambda를 사용하기로 결정했다.

API Gateway 에서는 사용하려는 망의 종류에 따라 [”Private”, “Edge”, “Regional”] 으로 분류된다.

“Edge” 는 API Gateway를 Cloudfront 와 연결하여 사용하는 방법이고,

”Regional”은 Cloudfront 없이 API Gateway로만 사용하는 방법,

”Private”는 VPC 안에서 사용되는 경우를 말한다.

방법

먼저 zappa를 이용하기로 했다. zappa는 Lambda 쪽에서 Flask의 코드를 배포를 자동화시켜줄 수 있는 도구여서

써보니 편리하기도 했다. 설치 방법은 인터넷에서 검색하면 나오는데,

마침 ubuntu 인스턴스 남는게 있어서 python 3.8 버전의 가상 환경을 구축하였다.

먼저 준비물로 flask application이 필요하다.

나의 경우는 update_metadata.py 파일에 flask app을 준비했다.

1. zappa init

위에 언급한 .py 파일이 있는 폴더를 따로 구축하는 것이 좋다.

zappa init 명령어를 생성하면 zappa_settings.json 이란 파일이 생성되는데 기존의 구축한 것이 있어

경로가 겹칠 경우 꼬일 수 있기 때문에 분리를 위해 폴더 생성을 추천한다.

zappa init

만드는 env 환경에 따라 선택하면 되는데, 별 문제될 게 없다면 엔터를 여러번 눌러서 스킵해도 무방하다.

2. VPC Endpoint 생성하기

aws ec2 페이지에 들어가서 좌측 탭에 “엔드포인트” 를 클릭한다.

아직 생성이 안 되어있다면, 엔드포인트 생성을 클릭한다.

하단의 서비스에 execute-api 를 설정하고, VPC를 선택, 서브넷은 privateSubnet으로 선택하고,

알맞은 보안 그룹을 선택하여 생성한 다음, vpce id를 복사한다.

3. json 파일 추가

zappa 에서 api gateway를 자동으로 생성해주기 때문에,

api gateway에서 적용될 정책도 명시를 해주는 작업이 필요하다.

VPC 내부에서만 사용하는 경우는 특정 Endpoint만을 제외한 나머지는 거부하는 정책이 필요하다.

따라서 아래와 같이 설정하여 json 파일을 생성한다.

주의할 점은 위에서 Endpoint를 생성했기 때문에 aws:sourceVpc가 아닌 aws:sourceVpc”e” 가 필요하다.

apigateway_resource_policy.json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "execute-api:/*",
            "Condition": {
                "StringNotEquals": {
                    "aws:sourceVpce": {my-vpce-id} // "vpce-0f0e3b5ee07de2052"
                }
            }
        },
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "execute-api:/*"
        }
    ]
}

4. zappa_settings.json 수정

처음 만들어진 zappa_settings.json 에는 최초의 설정값만 들어가있으므로 어떠한 옵션을 설정할 수 있는지 확인이 어렵다.

(https://github.com/zappa/Zappa 세부적으로 필요한 옵션들이 있다면 링크에 들어가서 확인할 수 있다.)

Private으로 구축할 경우 아래[1]의 옵션을 추가하는 게 필요했고,

결론적으로 추가한 zappa_settings.json은 아래와 같다.

vpc endpoint

[1]

{
    "dev": {
        ...
        "endpoint_configuration": ["PRIVATE"],
        "apigateway_policy": "apigateway_resource_policy.json",
        ...
    },
    ...
}

[2]

{
    "production": {
        "app_function": "update_metadata.app",
        "aws_region": "us-west-1",
        "profile_name": "default",
        "project_name": "update-metadata",
        "runtime": "python3.8",
        "endpoint_configuration": ["PRIVATE"],
        "apigateway_policy": "apigateway_resource_policy.json",
        "s3_bucket": "zappa-foyu2krjn",
        "slim_handler": true,
        "vpc_config": {
            "SubnetIds": ["subnet-09f21425f2eb1fa19", "subnet-0b6a7eb44744d48ea"],
            "SecurityGroupIds" : ["sg-0fa5c80aad0863b7f"]
        }
    }
}

5. zappa 배포

마지막으로 배포작업이 남았다.

zappa deploy

위의 명령어를 입력하여 api gateway를 배포한다.

API Gateway에서 구축하기까지 시간이 어느정도 걸린다.

배포 시, CloudFormation 에서 해당 스택이 반영되는 것을 확인은 가능하지만,

넉넉하게 시간을 갖고 테스트해보면 된다.

zappa 배포가 성공했다면 endpoint URL이 출력된다.

6. 테스트 및 확인

정상적으로 생성된 것을 확인할 수 있다.

flask API에서 ‘/’ endpoint에 대해 HELLO WORLD를 반환하도록 만들어놓았으므로

정상적으로 테스트가 되는지 확인한다.

마지막으로 VPC 내부망에서 확인하는지 확인한다.

만들어진 Endpoint는 192.168.x.x 의 IP를 갖고 있으므로 정상적으로 작동한다.

반대로 다른 VPC망에서 접근했을 땐, 작동하지 않는 것을 확인할 수 있다.

이상 zappa를 이용하여 VPC 내부에서 API Gateway를 구축하는 방법을 알아보았다.

에러 시 참고할 것

  1. EC2에서 엔드포인트를 생성 시, 상태가 “사용 가능”인지 확인할 것
  2. 배포 시 VPC에 반영되기까지 10분 정도의 시간이 조금 걸린다. (천천히 테스트 해볼 것)
  3. AWS Configure로 충분한 권한을 갖는 IAM User인지 확인할 것
  4. 용량이 클 경우, "slim_handler": true 옵션을 추가했는지 확인할 것

참고

https://tech.junhabaek.net/zappa와-github-action을-활용한-서버리스-django-application-aws-배포-트러블-슈팅-15604ed6bbcc

https://github.com/zappa/Zappa#enabling-secure-endpoints-on-api-gateway https://dulajra.medium.com/how-to-create-a-vpc-endpoint-for-api-gateway-a84bc7eeba28

https://aws.amazon.com/ko/blogs/compute/introducing-amazon-api-gateway-private-endpoints/

 

728x90