Elastic Network Interface

글쓴이 상배 윤 날짜

간단한 네트워크에서 개발자가 ENI(Elastic Network Interface)에 대해서 신경쓸 일은 없을 것이다. 개발자 입장에서 ENI는 자유롭게 뗐다 붙였다 할 수 있는 NIC(네트워크 인터페이스 카드)일 뿐이다. 그냥 EC2 인스턴스를 만들 때, 딸려나오는 1개 ENI를 쓰는 것으로 대부분의 작업을 수행 할 수 있기 때문에 신경 쓸 필요가 없다.

하지만 보안에 신경을 써야 하는 서비스를 만들어야 한다면 혹은 일반 데이터센터(IDC)의 인프라를 AWS로 마이그레이션 해야 하며, 데이터센터의 네트워크 구성도 마이그레이션 대상에 포함돼 있다면 ENI를 알고 있어야 한다.

네트워크 성능이 중요한 워크로드를 다뤄야 할 때도 ENI의 특징을 알고 있어야 한다.

ENI에 대해서

AWS ENI는 VPC에 배치된 인스턴스에 연결 할 수 있는 가상의 네트워크 인터페이스다. ENI의 특징은 아래와 같다.

  • 사설 IPv4 주소를 가진다.
  • 사설 IP 주소 하나당 하나의 EIP(Elastic IP)를 연결 할 수 있다.
  • 하나 이상의 보조 사설 IPv4 주소를 가질 수 있다.
  • 하나 이상의 Security group을 가질 수 있다.
  • 하나 이상의 IPv6 주소를 가질 수 있다.
  • Source/Destination IP를 체크 할 수 있다.
  • MAC 주소를 가진다.

모든 인스턴스는 primary ENI를 가진다. 인스턴스를 만들 때, (보통은 별 신경 쓰지 않겠지만)확인 할 수 있다.

Primary IP는 사설 IP다. Auto-assign이니, DHCP로 서브넷에 영역의 IP가 자동 할당 된다. 추가적으로 Secondary IP addresses를 할당 할 수 있는데, 주로 관리 목적으로 사용 한다.

모든 ENI는 “eni-xxxxxxx”로 시작한다. aws cli로 네트워크 인스턴스 정보를 확인했다.

ec2 describe-network-interfaces 
{
    "NetworkInterfaces": [
        {
            "Status": "in-use", 
            "MacAddress": "0a:68:7b:3b:a2:82", 
            "SourceDestCheck": true, 
            "AvailabilityZone": "ap-northeast-2c", 
            "Description": "Primary network interface", 
            "NetworkInterfaceId": "eni-0ca1f696291d45b32", 
            "PrivateIpAddresses": [
                {
                    "Primary": true, 
                    "PrivateIpAddress": "10.10.2.156"
                }
            ], 
            "RequesterManaged": false, 
            "SubnetId": "subnet-096df9942bd02e1b6", 
            "VpcId": "vpc-0700d43bd5ba9b0a4", 
            "InterfaceType": "interface", 
            "Attachment": {
                "Status": "attached", 
                "DeviceIndex": 0, 
                "AttachTime": "2018-12-19T14:50:07.000Z", 
                "InstanceId": "i-02e8600cb8c6b8e12", 
                "DeleteOnTermination": true, 
                "AttachmentId": "eni-attach-0b99561c08acd92c3", 
                "InstanceOwnerId": "522373083963"
            }, 
            "Groups": [
                {
                    "GroupName": "www-joinc-co-kr", 
                    "GroupId": "sg-033e0767c3e5475c4"
                }
            ], 
            "Ipv6Addresses": [], 
            "OwnerId": "522373083963", 
            "TagSet": [], 
            "PrivateIpAddress": "10.10.2.156"
        }
    ]
}
  • MacAddress : 인터페이스 MAC 주소
  • SourceDestCheck : 출발지/목적지 IP를 확인할지를 결정한다. 기본 설정은 true 다. 이 속성을 비활성화 하면, 예정되지 않은 네트워크 트래픽(예를 들어 다른 서브넷으로 향하는)을 처리 할 수 있다. VPN, 라우팅, 방화벽 같은 서비스를 실행하려면 false 상태로 해야 한다. AWS 마켓플레이스에서 찾을 수 있는 VPN, UTM 어플라이언스들은 대부분 fasle 상태다.
  • NetworkInterfaceId : ENI 식별 값
  • Attachment : attached 상태인지, attached 상태라면 어느 인스턴스에 attached 됐는지 정보를 출력 한다.
  • Groups : Security group 정보.
  • PrivateIpAddress : primary 사설 IP
  • PrivateIpAddresses : primary 사설 IP를 비롯한 추가적인 사설 IP

인스턴스 유형별 ENI 갯수 제한

인스턴스 유형별로 ENI 갯수가 제한된다. 방화벽, UTM 어플라이언스를 사용 할 거라면 인스턴스 선택에 주의해야 한다.

인스턴스 유형별 ENI 갯수는 구글 스프레드쉬트에 정리한 내용을 참고하자.

ENI 사용 시나리오

VPC 네트워크에서 보안 어플라이언스의 사용

개인정보와 결재를 다루는 서비스의 경우 AWS에서 제공하는 Security Group, VPC에서의 subnet 분리 혹은 VPC의 분리만으로는 보안 요구사항을 충족할 수 없다. 모든 트래픽이 보안 어플라이언스를 통과하도록 네트워크 & 시스템을 구성해야 한다. 대략 아래와 같은 구성이 될 것이다.

인터넷 게이트웨이(Interget Gateway)를 통하는 모든 트래픽은 ELB가 아닌 보안 어플라이언스가 받도록 구성을 해야 한다. 그리고 보안 어플라이언스는 네트워크 인터페이스 레벨에서 퍼블릭망과 프라이빗망을 격리할 수 있어야 한다. 결국 보안 어플라이언스(역시 EC2 인스턴스다.)는 2개 이상의 ENI를 이용 망을 격리해야 한다.

운영 네트워크과 관리 네트워크의 분리

보안을 위해서 운영 네트워크와 관리 네트워크를 분리하는 건 데이터센터에서 흔히 볼 수 있다. 보통 서버는 두 개 이상의 인터페이스를 가지고 있는데, 첫 번째 인터페이스는 인터넷에 연결되도록 하고, 두 번째 인터페이스는 데이터센터내에서만 접근 할 수 있도록 구성하는 식이다.

AWS도 동일하게 구성 할 수 있다.

웹 애플리케이션 서버(Web App) 서버는 2개의 ENI를 가진다. 하나는 Public subnet에 위치해서 유저 요청(80/443 혹은 앞에 ELB가 있을 수도 있다.)을 읽어서 처리한다.

다른 하나는 Private subnet에 위치한다. Corporate Data Center에 있는 시스템 어드민은 이 ENI에 ssh 연결해서 작업을 수행 할 수 있다. Private subnet과 Corporate Data center는 VPN으로 연결해서 트래픽을 격리한다.

고가용성 솔류션 구성

ENI는 인스턴스 사이를 자유롭게 이동 할 수 있다. 이러한 특징을 이용해서 Active 인스턴스와 Standby 인스턴스를 구성해서, Active 인스턴스에 문제가 생겼을 때, Standby가 백업 하도록 고가용성 시스템을 만들 수 있다.

ELB로 구성하면 간단할 거라고 생각 할 수 있다. 대부분의 경우 ELB로 고가용성 시스템을 구성 할 수 있겠지만 애플리케이션의 제약(마이그레이션 해야 하는 애플리케이션의 특징 등으로) 때문에 Active&Standby 방식으로 구성해야 할 때가 있다.

네트워크 인터페이스가 떠다니기 때문에 “Floating Interface Pattern”으로 부르기도 한다.

인스턴스가 실패 했거나 업그레이드가 필요할 때 사용 할 수 있다. 인스턴스를 만들 때, 붙어있는 ENI(eth0)은 인스턴세에서 뗄 수가 없다. 따라서 인스턴스에 새로운 ENI(eth1)을 만들어야 한다. 인스턴스에 문제가 생기면, ENI를 떼어내서 다른 인스턴스에 붙이면 된다. 인터페이스를 그대로 옮기는 거라서 MAC, IP, DNS 정보가 그대로 유지된다.

ENI를 붙여보자.

ENI를 만들어서 EC2 인스턴스에 붙여보기로 했다. 아래와 같이 VPC 네트워크를 만들고 EC2 instance를 배치했다.

ENI는 인스턴스와 같은 가용 영역에 있는 서브넷에만 전개 할 수 있다. 가용 영역은 물리적인 데이터 센터다. 네트워크 인터페이스는 인스턴스와 같은 물리적 위치에 있어야 하므로, 같은 가용 영역에 있어야 하는게 당연하다.

테스트를 위해서 ap-northeast-2a에 두 개의 서브넷을 만들었다. 인스턴스는 10.10.0.0/24에 배치하고, 두 번째 ENI는 10.10.1.0/24에 두기로 했다. 인스턴스의 이름은 eni-test-web.joinc.co.kr 로 했다.

인스턴스 정보를 확인해 보자.

Public IP를 할당하지 않았다. 2개의 Private IP, 2개의 Network Interfaces를 확인 할 수 있다. EIP를 할당해서 접근해 보자. EC2 대시보드 > Elastic IPs 에서 EIP를 할당 받아서, 인스턴스에 붙일 수 있다. 인스턴스에 붙이는 건 간단하지만 지금 처럼 멀티닉인 경우 “인스턴스 단위가 아닌, 인터페이스 단위로 EIP를 붙여줘야”한다.

  • Resource type : 멀티닉인 경우 Network interface를 선택한다.
  • Network interface : EIP를 네트워크 인터페이스(ENI)를 선택한다.
  • Private IP : ENI는 두 개 이상의 Private IP를 가질 수 있다. EIP를 붙일 Private IP를 선택한다.

인스턴스에 접근해서 IP 정보를 확인하자.

$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9001
        inet 10.10.0.70  netmask 255.255.255.0  broadcast 10.10.0.255
        inet6 fe80::16:f0ff:fe7d:6ac  prefixlen 64  scopeid 0x20<link>
        ether 02:16:f0:7d:06:ac  txqueuelen 1000  (Ethernet)
        RX packets 556  bytes 63248 (61.7 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 794  bytes 76854 (75.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9001
        inet 10.10.1.112  netmask 255.255.255.0  broadcast 10.10.1.255
        inet6 fe80::b5:6fff:feea:d31a  prefixlen 64  scopeid 0x20<link>
        ether 02:b5:6f:ea:d3:1a  txqueuelen 1000  (Ethernet)
        RX packets 43  bytes 2853 (2.7 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 80  bytes 6576 (6.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

아래는 라우팅 테이블이다.

$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.10.0.1       0.0.0.0         UG    0      0        0 eth0
0.0.0.0         10.10.1.1       0.0.0.0         UG    10001  0        0 eth1
10.10.0.0       0.0.0.0         255.255.255.0   U     0      0        0 eth0
10.10.1.0       0.0.0.0         255.255.255.0   U     0      0        0 eth1
169.254.169.254 0.0.0.0         255.255.255.255 UH    0      0        0 eth0

10.10.0.0/24로 향하는 패킷은 eth0, 10.10.1.0/24로 향하는 패킷은 eth1로 흐르도록 설정된 걸 확인 할 수 있다. Default gateway가 2개 인데, 리눅스는 항상 가장 낮은 값의 Metric를 사용하므로 0.0.0.0/0으로 향하는 모든 패킷은 eth0으로 향한다.

다음 10.10.1.0/24 서브넷에 테스트 인스턴스를 만들었다. 이 인스턴스의 이름은 eni-test-db.joinc.co.kr 이다.

ENI Security Group

보통 하나의 인스턴스가 하나의 eni를 가지도록 구성하기 때문에 신경쓰지 못했을 수도 있는데, 시큐리티 그룹은 ENI 단위로 설정된다. eni-test-web.joinc.co.kr의 eth1 ENI에 대한 security group은 따로 설정해줘야 할 것이다.


댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다

Bitnami