컨테이너는 여전히 제어 브리지에서 응답하지만, 나가는 패킷은 모두 사무실 macvlan으로 빠져나갑니다. 실패한 것은 없습니다. 두 연결이 각각 게이트웨이를 제공하고, 유일한 기본 경로가 의도하지 않은 쪽으로 향했기 때문에 서비스는 계속 동작하되 트래픽만 더 먼 길을 갑니다. 누군가 알아차릴 때쯤 증거는 오류 메시지가 아니라 라우팅 테이블입니다.

흔한 설명은 Docker가 네트워크를 우연히 골랐다는 것입니다. 실제로 예전 결정은 연결된 네트워크 이름의 알파벳 순서를 따랐고, 그래서 라우팅이 레이블의 부작용이 되었습니다. gw_priority는 그것을 의도적으로 고르는 숫자로 바꿉니다. 레이아웃을 적어 두면 도입에는 약 일 분이 걸립니다.

기본 경로가 잘못된 네트워크에 떨어지는 이유

서비스가 참여하는 모든 네트워크는 자기 게이트웨이를 제시할 수 있지만 컨테이너가 갖는 기본 경로는 결국 정확히 하나입니다. Compose 2.33.1 이전에는 네트워크 이름을 정렬해 동점을 깨뜨렸기 때문에 control처럼 office보다 앞서는 레이블이 트래픽의 행선지를 결정했습니다. 컨테이너 안에는 그 결정이 임의적이었다는 기록이 없어서 코드 리뷰를 통과하고 나중에 이상한 경로로 드러납니다. compose 파일에 정책을 두는 것이 선택을 검사 가능하게 만드는 유일한 방법입니다.

어느 네트워크가 이기는지를 실제로 바꾸는 것은 두 가지입니다. 지정하는 gw_priority 값과, 어떤 네트워크가 연결되어 있는지입니다. 세 번째 네트워크를 더하면 후보 집합이 커지고, macvlan을 빼면 브리지와 경쟁할 대상이 없어집니다. 어느 쪽도 애플리케이션 로그에는 나타나지 않습니다. 잘못된 기본 경로는 연결을 완전히 끊는 일이 드물고, 응답이 상대가 예상하지 못한 주소에서 도착하게 만들 뿐입니다.

gw_priority로 게이트웨이 고정하기

Compose는 2.33.1 버전부터 모든 서비스-네트워크 연결에 gw_priority를 노출하며 가장 큰 숫자가 이깁니다. 서비스별 게이트웨이 키는 없으므로 값은 서비스의 networks 블록에 들어갑니다. 아래 예시는 기본 경로를 control에 넘기고 office는 직접 연결된 LAN을 위해 도달 가능한 상태로 둡니다.

services:
  vpn:
    networks:
      control:
        gw_priority: 1
      office:
        gw_priority: 0

networks:
  control:
    driver: bridge
    ipam:
      config:
        - subnet: 172.30.50.0/24
  office:
    driver: macvlan
    driver_opts:
      parent: eno1.120
      macvlan_mode: bridge
    ipam:
      config:
        - subnet: 192.168.120.0/24
          ip_range: 192.168.120.192/27
          gateway: 192.168.120.1

블록을 두 개의 별개 제어로 읽으십시오. gw_priority가 기본 경로를 정하고 ipam 절이 주소 지정을 정합니다. subnet만 바꾸면 출구 선택은 그대로 남으며, 이 수정이 절반만 적용되는 가장 흔한 방식입니다. 우선순위는 그것이 지배하는 네트워크 옆에 두어 다음 독자가 결정을 찾아 헤매지 않게 하십시오.

gw_priority를 옆에 있는 평범한 priority 속성과 혼동하지 마십시오. 그쪽은 연결 생성 순서를 정할 뿐 라우팅에 대해서는 아무것도 말하지 않으므로 기본 게이트웨이를 고를 수 없고 인터페이스 이름도 고치지 않습니다. 트래픽을 유도하려고 priority를 올리라고 권하는 사람이 있다면, 결과 순서가 우연히 맞아 보이더라도 그 권고는 틀렸습니다.

기본 경로를 실제로 어떤 네트워크가 나르는지 검증하기

실행 중인 컨테이너 안에서 확인하십시오. 호스트의 라우팅 테이블은 호스트를 설명할 뿐 서비스가 쓰는 네임스페이스를 설명하지 않습니다. 먼저 구성 검사를 실행해 오타가 재시작 전에 걸리게 하고, 그다음 컨테이너가 실제로 설치한 경로를 읽으십시오.

docker compose config --quiet
docker exec vpn ip -4 route show default
docker exec vpn cat /proc/net/route

올바른 결과는 브리지 장치와 172.30.50.1을 지목합니다. 잘못된 결과는 192.168.120.1과 macvlan 장치를 지목합니다. 이미지에 iproute2 패키지가 없더라도 /proc 파일은 기본 경로를 보고하며, 목적지는 00000000이고 게이트웨이 바이트는 뒤집혀 있습니다. 장치 이름이 분명하지 않을 때는 인터페이스 열을 docker inspect와 비교하십시오.

macvlan은 물리 포트이지 브리지의 복제본이 아니다

macvlan은 컨테이너에 케이블 위의 두 번째 신원을 부여하며, 바로 그것이 로컬 장치 접근을 동작하게 만듭니다. 또한 스위치 포트와 하이퍼바이저가 추가 MAC 주소를 받아들여야 한다는 뜻이고, 많은 클라우드 네트워크는 이를 조용히 거부합니다. 함대를 계획하기 전에 컨테이너 하나로 시험하십시오. 거부된 MAC은 보통 링크는 올라와 있는데 아무것도 통과하지 않는 상태로 나타납니다.

macvlan_mode: bridge 설정은 macvlan 드라이버의 모드이며 Docker의 소프트웨어 브리지가 아니고, passthru는 기본값이 아니라 별도의 특수 모드입니다. Linux는 또한 macvlan 컨테이너가 자기 호스트에 도달하지 못하게 합니다 같은 상위 인터페이스를 거치기 때문이며, 하나의 연결이 두 역할을 하리라 기대하지 않고 제어 브리지를 남기는 이유가 여기에 있습니다.

Compose가 보기 전에 VLAN 상위를 명명하십시오

Docker는 eno1.120 같은 점이 있는 상위를 802.1Q 하위 인터페이스로 취급하고 VLAN 장치를 직접 만듭니다. 그 편의에는 한계가 있습니다. 파생된 이름은 물리 인터페이스 이름에 의존하고, 긴 이름은 결과를 주변 도구의 기대 밖으로 밀어낼 수 있습니다. 호스트 네트워크 구성에서 이름 있는 VLAN 인터페이스를 만들고 parent를 그것으로 향하게 하면 양쪽 끝이 예측 가능해집니다.

networks 아래의 키는 Compose 이름이지 Linux 장치가 아님을 기억하십시오. 호스트에서 office라는 인터페이스를 찾는 것은 실패합니다. 커널은 상위 인터페이스와 컨테이너 뒤의 veth 쌍만 보기 때문입니다.

그 위에 VPN을 위한 자리를 만들기

VPN 클라이언트는 이 네트워크들이 존재한 뒤에 연결되므로 gw_priority와 무관하게 더 구체적인 경로, 정책 규칙, 필터를 추가할 수 있습니다. 원격 프리픽스는 두 로컬 subnet 모두를 기준으로 계획하고, 제어 경로가 필요로 하는 응답도 포함하십시오. 원격 프리픽스가 사무실 LAN과 겹치면 터널에서 사설 범위를 통째로 뽑아내지 말고 주소 계획을 고치십시오.

VPN이 시작된 뒤와 다시 연결된 뒤에 주소, 경로, 서비스 경로를 다시 확인하십시오. 손으로 추가한 경로가 사라지는 곳이 바로 재연결 시점입니다. 첫 시험 전에 기대하는 표를 적어 두면 이후 비교는 기억력 시험이 아니라 diff가 됩니다. 네트워크의 지속적 소유권은 Compose에 두고 VPN 구성은 자기 정책만 소유하게 하십시오.

관련 글