EC2 인스턴스에서 호스팅되는 ECS 태스크의 네트워킹 동작은 Task definition에 정의된 네트워크 모드에 따라 다르다.

Fargate의 ECS 태스크 네트워킹 동작은 기본적으로 private ip가 포함된 ENI가 제공된다.(awsvpc)

다른 네트워크 모드를 사용해야 할 특별한 필요가 있지 않는 한 awsvpc 네트워크 모드를 사용하는 것이 좋다.

더 자세히 살펴보자!


AWS ECS Task Network Mode

  • awsvpc: 태스크에 고유한 ENI(Elastic Network Interface)와 기본 private IPv4 주소 할당
    • 태스크에 EC2 인스턴스와 동일한 네트워킹 속성 적용
  • bridge: 태스크를 호스팅하는 각 EC2 인스턴스에서 실행되는 Docker의 기본 가상 네트워크를 이용
    • Docker의 기본 가상 네트워크
  • host: Docker의 기본 가상 네트워크를 우회하여 컨테이너 포트를 태스크를 호스팅하는 EC2 인스턴스의 ENI에 직접 매핑
    • 포트 매핑을 사용할 때 단일 EC2 인스턴스에서 동일 태스크에 대해 다중 인스턴스화 실행 불가능
  • none: 태스크에 외부 네트워크 연결 없음

Docker의 기본 네트워킹

  • Docker 컨테이너 및 서비스가 강력한 이유 중 하나: 함께 연결하거나 Docker가 아닌 워크로드에 연결 가능
    • 플랫폼에 구애받지 않음!
  • 네트워크 드라이버
    • https://docs.docker.com/network/ 
    • Docker의 네트워킹 하위 시스템은 드라이버를 사용하여 플러그 가능
    • bridge: 기본 네트워크 드라이버, 일반적으로 통신이 필요한 독립 실행형 컨테이너에서 애플리케이션 실행할 때
      • 동일한 Docker 호스트에서 통신하기 위해 여러 컨테이너가 필요할 때
    • host: 독립형 컨테이너의 경우 컨테이너와 Docker 호스트 간의 네트워크 격리를 제거하고 호스트의 네트워킹을 직접 사용
      • 네트워크 스택을 Docker 호스트에서 격리해서는 안되지만 컨테이너의 다른 측면을 격리하려는 경우
    • overlay: 여러 Docker 데몬을 함께 연결하고 스웜 서비스가 서로 통신할 수 있도록
      • 통신을 위해 서로 다른 Docker 호스트에서 실행되는 컨테이너가 필요하거나 Swarm 서비스를 사용하여 여러 애플리케이션이 함께 작동할 때
    • ipvlan: 사용자에게 IPv4 및 IPv6 주소 지정에 대한 완전한 제어 제공
    • macvlan: MAC 주소를 할당하여 네트워크에서 물리적 장치로 표시
      • VM 설정에서 마이그레이션하거나 컨테이너가 고유한 MAC 주소를 가진 네트워크의 물리적 호스트처럼 보일 때
    • none: 모든 네트워킹 비활성화
    • 네트워크 플러그인: Docker와 함께 타사 네트워크 플러그인을 설치하고 사용할 수 있음
      • Docker를 특수 네트워크 스택과 통합 가능

이제 ECS 태스크 네트워킹 하나씩 따져보자!

awsvpc 네트워크 모드

  • ECS 태스크에 EC2 인스턴스와 동일한 네트워킹 속성을 제공
  • 컨테이너 네트워킹을 간소화하고 컨테이너화된 애플리케이션이 서로, 그리고 VPC 내 다른 서비스와 통신하는 방식을 더 세부적으로 제어 가능
  • 태스크 내에서 더 세부적으로 보안 그룹 및 네트워크 모니터링 도구를 사용 가능하게 만들어 컨테이너의 보안을 강화
  • 각 태스크는 고유한 ENI를 받으므로 VPC Flow Log와 같은 기타 EC2 네트워킹 기능을 이용하여 태스크에서 주고받는 트래픽을 모니터링 가능
  • 같은 태스크에 속한 컨테이너는 localhost 인터페이스로 통신 가능
  • Task ENI
    • ECS의 완전 관리형 기능
    • ENI를 생성하고 지정된 보안 그룹이 있는 호스트 EC2 인스턴스에 연결
    • 기본적으로 private ip 할당, VPC가 듀얼 스택모드를 사용하도록 설정

 

  • EC2 인스턴스는 ENI에 할당, ENI는 호스트 수준에서 네트워크 통신에 사용되는 EC2 인스턴스의 IP 주소를 나타냄: 172.31.16.0
  • 각 태스크에는 해당 ENI 및 private ip 주소 있음: 172.31.16.1 / 172.31.16.2
  • 각 ENI는 분리되어 있으므로 각 컨테이너는 포트에 바인딩 가능 :80 → 포트 번호 추적할 필요 없음
  • 장점: 각 태스크에 트래픽을 허용하거나 거부하는 별도의 보안그룹
  • 단점: EC2 인스턴스에 연결할 수 있는 ENI 개수에는 한도가 있음 → Trunk ENI 기능 제공

  • 단점: 태스크에 별도의 IP 주소를 할당하면 보안 강화에 좋지만, IP 소진으로 이어질 수 있음
    • 특히 ENI 트렁킹을 사용하면 시작하는 각 EC2 인스턴스에는 두 개의 ip 주소 필요
    • → 호스트와 다른 IP 주소 공간에서 ENI를 사용하도록 VPC CNI 구성

 

bridge 네트워크 모드

  • 각 컨테이넌 인스턴스에서 실행되는 Docker의 기본 가상 네트워크 이용
  • bridge: 동일한 브리지 네트워크에 연결된 각 컨테이너가 서로 통신할 수 있도록 하는 내부 네트워크 네임스페이스
  • 동일한 브리지 네트워크에 연결되지 않은 컨테이너에서 격리 경계도 제공
  • 정적 또는 동적 포트 매핑을 사용하여 컨테이너의 포트를 EC2 호스트 포트와 매핑

  • 정적 포트 매핑 사용: 컨테이너 포트에 매핑할 호스트 포트를 명시적으로 정의 가능
    • 위 그림에서 컨테이너화된 응용 프로그램의 관점에서 포트의 인바운드 트래픽은 3000 포트
    • 트래픽 포트만 변경하려는 경우에 적합
    • 단점: 각 호스트에서 태스크의 인스턴스화를 하나 이상 실행할 수 없음(단일 컨테이너만 80 포트에 연결 가능)

  • 동적 포트 매핑 사용: 포트 매핑에 호스트 포트를 지정하지 않으면 Docker가 임시 포트 범위에서 사용되지 않는 임의의 포트를 선택해 컨테이너의 공용 호스트 포트로 할당하도록
    • 호스트에서 해당 컨테이너의 여러 복사본 실행 가능
    • 각 컨테이너는 호스트에 자체 포트 할당 가능
    • Task definition 과정에서 호스트 포트를 0번으로 설정
      • (에페메랄 포트 범위의 포트가 자동으로 할당, target group의 포트는 무시)
    • 단점: 사용되지 않는 임의의 포트에 할당될 수 있어 호스트 간에 광범위한 포트 범위를 열어야 함.
      • 특정 서비스가 다른 특정 서비스와만 통신할 수 있도록 특정 규칙을 만들기 어렵다.
  • Fargate 지원 안함.

 

host 네트워크 모드

  • 컨테이너가 실행 중인 EC2 인스턴스 호스트에 직접 연결됨.
  • 각 컨테이너는 이를 호스팅하는 EC2 인스턴스의 IP 주소를 통해 트래픽을 수신
  • ECS에서 지원되는 가장 기본적인 네트워크 모드

  • 단점: 각 호스트에서 태스크의 인스턴스화를 하나 이상 실행할 수 없음
    • 첫 번째 태스크만 EC2 인스턴스의 필수 포트에 바인딩할 수 있기 때문
    • 특정 포트 번호에서 수신 대기해야하는 경우 포트 번호를 직접 다시 매핑 불가능
    • → 응용 프로그램 구성을 변경하여 포트 충돌을 관리해야함.
  • Fargate 지원 안함.

사실 저 위의 내용이 크게 와닿진 않는다..😥

전체적인 ECS 네트워킹 과정(?)을 훑어보면, https://docs.aws.amazon.com/ko_kr/AmazonECS/latest/bestpracticesguide/networking.html

1. 인터넷에 연결하기: 대부분의 컨테이너화된 응용 프로그램에는 인터넷에 대한 아웃바운드 액세스가 필요한 일부 구성 요소 있음.(퍼블릭 서브넷 + igw / 프라이빗 서브넷 + ngw)

2. 인터넷에서 인바운드 연결 수신: 퍼블릭 IP 주소 사용 / ALB / NLB / API Gateway HTTP API

3. 네트워크 모드 선택: 인바운드 및 아웃바운드 네트워크 연결을 설계하기 위해선 다른 수준의 네트워킹을 고려해야함

"여러 컨테이너를 단일 호스트에 압축" → 동일한 호스트에서 실행중인 컨테이너를 네트워크화하는 방법을 선택

(awsvpc / bridge / host)

 

그냥 단순히 생각을 해보면.. 컨테이너의 네트워크 관리를 어떻게 할건지의 느낌인 것 같은데 

포트 매핑에 있어서 어떻게 할 건지.. (호스트 포트 / 컨테이너 포트) 포트 번호 선택의 문제인 듯?

(호스트 포트를 지정할 경우 각 호스트에서 태스크의 인스턴스화를 하나 이상 실행할 수 없음!)

awsvpc로 하면 알아서 관리해주는 거고, bridge로 하면 사용자가 매핑을 하는 느낌..

 

❗ 어렵다 어려워! ❗

나는 EC2로 구축을 진행할려고 한다. 후에 Fargate로도 해봐야지!

https://dev.classmethod.jp/articles/ecs-container-service-establishment-2/


  • 클러스터 생성

NAT Gateway 생성: 클러스터에서 private subnet에 있는 ec2 인스턴스를 인식할 수 있게..

private rtb에 붙여준다.

 

클러스터를 생성해주자.

1) vpc는 private subnet으로

2) 인프라는 ec2 인스턴스로(새 ASG 생성 - Amazon Linux2 / t3.medium / 2-4 / 키페어 없음)

거의 깡통의 클러스터를 생성한 듯

 

  • ASG 관리

EC2 → ASG로 들어가면 클러스터를 만들면서 생성한 ASG가 보인다.

이를 손봐주자..

1) 시작템플릿 관련

현재 상황이다. 보안그룹을 변경해주자.(ecs-sg(container)) 

그러면 새로운 시작 템플릿 버전이 생기는데 이를 ASG에 연결해주자.

새로생성한 Latest(2)를 선택한다.

변경된 것을 확인할 수 있다.

후에 인스턴스 새로고침 진행

시작 템플릿 변경된 것을 적용시키기 위함이다!  → ec2 인스턴스의 정보를 확인해서 ecs-sg로 연결이 잘 되어있는지 확인.

 

  • 작업 정의(Task definition)

ALB를 먼저 생성해주자.

1) vpc는 퍼블릭으로

2) 보안그룹은 ecs-alb-sg로

3) 대상그룹은 생성하자.(ec2는 클러스터 생성을 통해 만들어진 인스턴스를 추가한다.)

4) alb로 돌아가 생성한 대상그룹 선택

alb를 생성하자.

 

  • 작업 정의(Task definition)

1) 컨테이너 생성의 경우 생성했던 ECR 리포지토리의 URI 삽입

2) 앱 환경은 EC2, 네트워크 모드는 브릿지

 

  • 서비스 생성

1) 클러스터의 경우 생성했던 클러스터 선택

2) 시작 유형 - EC2

3) 배포 구성에서 원하는 태스크의 수를 2개로

4) ELB 구성의 경우 위에서 생성했던 것들로 선택해서 진행

후에 배포를 진행..

타겟 그룹을 확인해 보면 49153 포트 번호로 EC2 인스턴스가 추가된 것을 확인할 수 있음.

위에서 설정을 동적 포트 매핑을 사용했기 때문에 호스트 포트를 0으로 설정하면 에페메랄 포트(32768-61000) 범위의 포트가 자동으로 할당되며 alb에 설정해놓은 target grp의 포트는 무시됨.

 

  • alb 확인

 

  • ECS 컨테이너에 접속

EC2 인스턴스에 연결되어 있는 ecsInstanceRole을 수정(EC2RoleforSSM 추가)

EC2를 Session Manager를 통해 들어가보자.

근데 연결이 되질 않네..? → 적용될 때 까지 시간이 걸림..ㅎㅎ

 

들어가서 설치 잘 되었는지 확인..

sudo -s
cd /var/lib/docker/overlay2
ls
find / -name "*.html"

변경해줘야할 index.html 파일을 찾아야하는데 find / -name "*.html" 명령어를 활용해서 찾자..

/var/lib/docker/overlay2/b2b5c3ddc547fd0347e12b129d7f3f52a5776b20b5d59e4b770a8dab2e6dd504/merged/usr/share/nginx/html/index.html

나는 위의 파일에 해당 내용이 있다.(참고로 merged 폴더 안의 파일이어야 한다..)

원하는대로 html 파일을 변경해주고 적용시키자!

 

A AZ에는 hello ecs! 가

C AZ에는 hello c AZ ecs! 가 나와야 한다. 확인해보자.

 

 

❗ 더 찾아봐야할 것! ❗

위와 같이 진행할 경우 target group에 맨 처음 생성했었던 흔적(?)이 남는다.. 물론 ec2의 경우 종료되어있지만 저거 어떻게 지우지?

→ 일단 내가 네트워크 모드를 bridge - 호스트포트 0번으로 설정을 했기에 포트가 변경된 것...

ECS 서비스를 이용해 타겟 그룹에 인스턴스를 등록하는 경우 타겟 그룹의 포트는 무시됨.

(+) 서비스에 지정하는 컨테이너 포트는 태스크 정의의 컨테이너 포트와 같아야한다.

정적 매핑
동적 매핑

 

근데 보통 awsvpc로 하니까 다음 실습 땐 awsvpc 모드로 실행해보자

'Cloud > AWS' 카테고리의 다른 글

[AWS] ECS Task Network Mode  (0) 2022.09.19
[AWS] Cloud9 - Github 연동  (0) 2022.09.16
[AWS] ECS 개념 + 실습 -1(Docker image push)  (1) 2022.09.14
[AWS] ECS에 HTTP API 구축  (0) 2022.09.13
[AWS] Mobile Backend 구성  (1) 2022.09.08

Amazon Elastic Container Service(ECS)

  • 컨테이너화된 애플리케이션의 손쉬운 배포, 관리 및 조정에 도움이 되는 완전 관리형 컨테이너 오케스트레이션 서비스
  • "ECS Anywhere": 온프레미스 또는 클라우드 모두에서 ECS에서 확인하려는 유사한 클러스터 관리, 워크로드 예약 및 모니터링 이용 가능
  • 오케스트레이터: 컨테이너 배포, 컨테이너 상태 확인, 상태가 좋지 않은 노드 교체, 새 배포 처리를 통해 컨테이너의 수명 주기 관리

https://tech.cloud.nongshim.co.kr/2021/08/30/%EC%86%8C%EA%B0%9C-amazon-ecs%EB%9E%80/

구성 요소

  • Cluster: 클러스터에 배포된 모든 컨테이너를 그룹화하는 논리적 구조
  • Task definition: 컨테이너 이미지 위치, CPU 및 메모리 용량, 로그 구성 등과 같은 속성을 포함
  • Task: 클러스터 내 태스크 정의를 인스턴스화
  • Service: 클러스터에서 원하는 수의 태스크를 동시에 실행하고 유지 가능
  • ECR: Amazon에서 제공하는 컨테이너 이미지 저장소

시작 유형

  • Fargate: 서버리스 컴퓨팅 엔진
  • EC2
  • External: 온프레미스 서버 또는 가상 머신

실습

  • VPC 생성

퍼블릭 서브넷 2 / 프라이빗 서브넷 2

퍼블릭 rtb에 igw 추가

 

  • 보안그룹

(docker 설치 및 dockerfile 만들 ec2 보안그룹) ssh만 열어주자

(로드 밸런서 보안그룹) HTTP 열어주자

(컨테이너 보안그룹) private subnet 배치, alb에서만 받아오자

 

  • docker 환경 구축

ec2 인스턴스 생성

위에서 생성했던 vpc와 sg 적용 시키기, 퍼블릭 ip 활성화

(❗ vpc 적용시킬 때 public인지 확인해라...)

 

이후에 ssh 접속 해서 docker 설치를 해보자!

sudo -s
yum install -y docker
service start docker | systemctl start docker
docker images

docker images 명령어 입력 후 위의 그림과 같은 화면이 나오면 성공적으로 설치된 것.

 

dockerfile 작성

mkdir dockerfile-folder
cd dockerfile-folder/
vi index.html

//index.html
<!doctype html>
<h1>hello ecs!</h1>

vi dockerfile

//dockerfile
FROM nginx:latest
MAINTAINER "kim.jaewook@classmethod.jp"

COPY ./index.html /usr/share/nginx/html/index.html

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

docker build -t ecs-nginx .

docker images 명령어를 입력해보면

위와 같이 업로드를 확인할 수 있다.

ECR로 이미지를 푸시하기 전 현재 생성한 docker image가 정상 작동하는지 테스트 해보자.

(create 명령어로 container 생성)

docker create -i -t --name ecs-nginx-container -p 8000:80 ac167921553f //ecs-nginx image id

컨테이너 아이디를 확인하고 start 명령어로 컨테이너 실행

docker ps -a
docker start 362972fc9628 // container id

ec2 보안그룹에서 8000번 포트 열고 확인!

컨테이너는 필요없으니 삭제 해주자

docker stop 362972fc9628
docekr rm 362972fc9628

 

  • ECR 리포지토리 생성

이름은 docker image와 같게 만들자.

 

  • EC2에서  프로필 설정

 ECR에 이미지를 푸시하기 위해선 EC2에 IAM Role이 연결되어 있어야 한다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecr:Describe*",
                "ecr:Get*",
                "ecr:BatchCheckLayerAvailability",
                "ecr:BatchGetImage"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ecr:PutImage",
                "ecr:InitiateLayerUpload",
                "ecr:UploadLayerPart",
                "ecr:CompleteLayerUpload",
                "ecr:BatchDeleteImage"
            ],
            "Resource": [
                "arn:aws:ecr:REGION:AWS_ACCOUNT_ID:repository/REPOSITORY_NAME"
            ]
        }
    ]
}

나는 위의 내용을 정책으로 만들고 만든 정책으로 역할을 생성했다.

역할을 업데이트 해준다.

 

  • ECR 로그인
$ aws ecr get-login-password --region REGION | docker login --username AWS --password-stdin AWS_ACCOUNT_ID.dkr.ecr.REGION.amazonaws.com/리포지토리

로그인 성공!

 

  • ECR Push

해당 명령어들을 따라간다..(얘는 ECR 리포지토리 선택 후 '푸시 명령 보기' 클릭하면 나옴..)

2번까진 위에서 테스트 했기 때문에 3번 명령어부터 진행하면 된다.

3번 명령어 까진 실행이 잘 되었다는 것을 알 수 있음.(TAG 명령어)

4번 명령어 실행하면

이와 같은 오류가 뜬다. 아마 aws configure 문제 일듯?

IAM user를 생성한다.

후에 aws configure 작업 진행

ECR 리포지토리의 권한도 설정해준다.(귀찮으니까 모든 사람으로 설정해버림)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowPushPull",
      "Effect": "Allow",
      "Principal": "*",
      "Action": [
        "ecr:BatchCheckLayerAvailability",
        "ecr:BatchGetImage",
        "ecr:CompleteLayerUpload",
        "ecr:GetDownloadUrlForLayer",
        "ecr:InitiateLayerUpload",
        "ecr:PutImage",
        "ecr:UploadLayerPart"
      ]
    }
  ]
}

다시한번 더 4번 명령어(push) 하면 성공이다.

위와 같이 이미지가 잘 올라간 것을 볼 수 있음!

 

❗ 글이 길어지니까 ECS 구축 관련한 내용은 다음 포스팅에 올리자.. ❗

'Cloud > AWS' 카테고리의 다른 글

[AWS] Cloud9 - Github 연동  (0) 2022.09.16
[AWS] ECS 실습 -2(ECS 구축)  (0) 2022.09.15
[AWS] ECS에 HTTP API 구축  (0) 2022.09.13
[AWS] Mobile Backend 구성  (1) 2022.09.08
[AWS] AWS Amplify -1(Amplify Studio)  (0) 2022.09.07

https://docs.aws.amazon.com/ko_kr/apigateway/latest/developerguide/http-api-private-integration.html#http-api-private-integration-create-api

"VPC에서 실행되는 ECS 서비스에 연결하는 서버리스 API 생성"

아무래도 api gateway의 경우 서버리스(lambda, ecs와 같은) 서비스와 함께 사용된다.. 

api gateway + lambda는 저번에 해봤으니까..

이번엔 api gateway + ecs다!(http api 구축이랑 rest api 구축이랑 콘솔 디자인이 다르다.. rest 꾸짐)

VPC link

(그림 아래의 사이트에 들어가 cloudformation 템플릿으로 한번에 올려서 테스트가 가능함..)

나는 차례대로 한 번 따라가 볼 예정!


  • ECS 생성(ALB를 사용하는 ECS 서비스 생성)

문서에서 제공하는 템플릿을 cloudformation에 스택을 올린다.(template.yaml)

관련된 서비스들이 어떻게 올라갔는지 확인해보자.

1. VPC

vpc 안에 public subnet 2개 / private subnet 2개 생성

ngw의 경우 public subnet에 2개 생성(private rtb과 각각 연결) - 이중화를 기본으로 하는 듯

 

2. ECS

클러스터 생성

태스크 정의 생성

태스크 역할: https://docs.aws.amazon.com/ko_kr/AmazonECS/latest/developerguide/task-iam-roles.html

태스크 실행 역할: https://docs.aws.amazon.com/ko_kr/AmazonECS/latest/developerguide/task_execution_IAM_role.html

 

태스크 실행 후에 서비스 배포(태스크 정의 카테고리에서 작업 → 태스크 실행 / 서비스 생성 해야 바로 ELB 붙일 수 있음..)

Task: Task definition 대로 배포된 container set(cluster에 속한 container instance에 배포됨)

Service: Task들의 라이프 사이클 관리(Task를 cluster에 몇 개 배포할 건지, ELB 관리, Auto Scaling 관리)

 

3. ALB

alb 생성(스키마: 내부 / 가용영역: private /보안그룹: 인바운드 80포트 - all ipv4)

listener(80포트 - 대상 그룹)

대상 그룹: ecs의 태스크 ip 등록

(얘는 서비스 생성 전에 만들어야 위의 서비스 생성 과정에서 ALB 붙일 수 있을듯?)

❗ 위의 내용은 나중에 따로 혼자서 해보는걸로... 현재는 그냥 cloudformation 템플릿 사용해서 올렸을 뿐 ❗

 

  • VPC link

api gateway → vpc link 클릭

서브넷의 경우 private들 선택

보안그룹 없어도 됨

 

  • HTTP API

api gateway → http api build

경로는 나중에 생성할 예정

  • 경로 생성

  • 통합 생성

경로 선택 → 통합 대상(프라이빗 리소스) → 수동 선택 → ALB/NLB(ALB 선택) → 리스너(HTTP 80) → VPC link 선택

 

  • API Test

api url에 들어가면 아래와 같은 화면을 얻을 수 있음.

새로 고침 여러번 누르고 ecs 서비스 상태를 확인해보면

다음과 같이 잘 동작하고 있는 것을 확인할 수 있다...

 

 

❗ 아직 ecs의 개념이 확실치 않으니 다음에는 ecs 정리편으로 돌아오겠다.. ❗

'Cloud > AWS' 카테고리의 다른 글

[AWS] ECS 실습 -2(ECS 구축)  (0) 2022.09.15
[AWS] ECS 개념 + 실습 -1(Docker image push)  (1) 2022.09.14
[AWS] Mobile Backend 구성  (1) 2022.09.08
[AWS] AWS Amplify -1(Amplify Studio)  (0) 2022.09.07
[AWS] Lambda와 RDS 연동(+ API Gateway)  (0) 2022.09.06

+ Recent posts