안전한 토렌트 사용을 위해 NordVPN
을 사용중으로 이쪽 계통에서는 사실상 올인원에 가까운 transmission-openvpn
컨테이너를 사용하고 있습니다.
transmission-openvpn
의 경우 단순히 VPN
제공자의 아이디와 비밀번호만 환경변수로 넘겨주면 되기 때문에 복잡한 설정이 필요하지 않고 여러 컨테이너를 거칠 필요 없이 하나로 모든 설정이 가능하다는 장점이 있습니다.
위처럼 VPN
용 컨테이너를 관리하게 되면 해당 컨테이너를 대표 네트워크
로 선언해서 다른 컨테이너들을 추가로 엮어서 운용하는 설정이 몹시 간단한 반면 아쉬운 점도 있습니다.
문제는 컨테이너의 네트워크 연결이 끊어졌을때 각각 알아서 컨테이너를 재시작한다면 편리할텐데 이를 기본으로 지원하지 않고 있어 꽤나 골치아픈 문제입니다.
만약 VPN
의 연결이 끊어지면 재연결을 시도하도록 설정은 가능하나, 그럼에도 연동된 컨테이너들의 네트워크가 별도로 자동으로 갱신되는 것은 아니기 때문입니다.
지금까지는 네트워크 문제 발생 시 전체 Stack(스택)
을 재실행하는 식으로 간간히 해결해왔지만 이번엔 직접 조치할 상황조차 없도록 완전히 자동화
해보도록 하겠습니다.
일단 제 경우 NordVPN
을 연동한 haugene/transmission-openvpn
컨테이너의 경우 기본 설정이 다음과 같습니다.
- OPENVPN_OPTS=--inactive 3600 --ping 10 --ping-exit 60 # VPN 연결이 끊어지면 컨테이너 강제 종료(킬 스위치)
위처럼 별도의 환경 변수로 핑을 날려 VPN
연결에 문제시 아예 컨테이너를 종료해버립니다.
이처럼 완전히 컨테이너를 죽여야하기 때문에 restart: unless-stopped
옵션을 사용하고 있었습니다.
그러나 이런식으로 동작하게 되면 뭔가 안된다 싶을때 관리자가 직접 도커 컨테이너를 재기동 해야하며, 심지어 단순히 transmission-openvpn
컨테이너만 재기동해서는 다른 컨테이너들의 네트워크 문제가 해결되지 않습니다.
따라서 헬스체크를 사용해 각 컨테이너들의 Status(상태)
를 별도로 체크하고 만약 네트워크에 문제가 생기는 경우 Unhealthy
로 변경 되도록 설정을 추가하겠습니다.
상태만 변경하면 되기 때문에 도커 컨테이너에 문제가 발생하더라도 일단 항상 동작하도록 restart: unless-stopped
옵션을 restart: always
로 변경하겠습니다.
healthcheck:
test: ["CMD", "curl", "-f", "https://www.google.com"]
interval: 1m30s
timeout: 15s
retries: 3
다음은 위처럼 추가로 VPN
컨테이너 설정 사이에 healthcheck
블록을 추가합니다.
기본적인 형태는 interval(반복실행 시간)
인 1분 30초
마다 시도해서 3번
의 재시도를 하는동안 작업에 실패하는 경우 컨테이너의 상태를 Healthy
에서 Unhealthy
로 바꾸어주는 역할을 합니다.
그렇다면 이제 VPN
컨테이너는 Unhealthy
상태로 변경이 가능하게 되었으니 AutoHeal
을 적용하기 위해 별도의 라벨
을 추가해야겠습니다.
labels:
- autoheal=true
포테이너의 Stack(YAML 형식)
내용 사이에 위처럼 labels
항목을 추가하도록 하겠습니다.
추가로 오토힐
을 적용하기 위한 플래그 값인 autoheal=true
를 지정해줍니다.
autoheal:
container_name: openvpn-autoheal
image: willfarrell/autoheal:latest
restart: always
environment:
- AUTOHEAL_CONTAINER_LABEL=all
- TZ=Asia/Seoul # 국내 타임존으로 설정
- AUTOHEAL_CONTAINER_LABEL=autoheal # 오토힐 적용할 라
volumes:
- /var/run/docker.sock:/var/run/docker.sock
logging:
driver: json-file
options:
max-size: 10m # log 파일의 용량을 10m로 제한
다음은 컨테이너를 감시하고 Unhealthy
상태인 컨테이너를 재기동 시켜 줄 오토힐
컨테이너를 하단에 추가해주시면 되겠습니다.
반드시 동일한 Stack
안에서 실행하실 필요는 없지만 제 경우 편의상 같은 YAML
안에 추가했습니다.
docker-compose.yml
version: "3.3"
services:
transmission-openvpn:
cap_add:
- NET_ADMIN
volumes:
- "[직접입력]/data:/data"
- "[직접입력]/config:/config"
- "[직접입력]/download:/data/completed"
- "[직접입력]/incomplete:/data/incomplete"
- "[직접입력]/watch:/data/watch"
environment:
- OPENVPN_PROVIDER=NORDVPN
- OPENVPN_CONFIG=us.socks.nordhold.net
- NORDVPN_COUNTRY=US
- NORDVPN_CATEGORY=legacy_p2p
- NORDVPN_PROTOCOL=tcp
- NORDVPN_SERVER=sg460.nordvpn.com
- OPENVPN_USERNAME=[직접입력]
- OPENVPN_PASSWORD=[직접입력]
- OPENVPN_OPTS=--inactive 3600 --ping 10 --ping-exit 60
- TRANSMISSION_SCRAPE_PAUSED_TORRENTS_ENABLED=false
- LOCAL_NETWORK=192.168.0.0/16
- TRANSMISSION_RPC_AUTHENTICATION_REQUIRED=true
- TRANSMISSION_RPC_USERNAME=[직접입력]
- TRANSMISSION_RPC_PASSWORD=[직접입력]
- PUID=1000
- PGID=100
- TZ=Asia/Seoul
- OVERRIDE_DNS_1=8.8.8.8
- OVERRIDE_DNS_2=8.8.4.4
logging:
driver: json-file
options:
max-size: 10m
ports:
- 39091:9091
image: haugene/transmission-openvpn:5.1.0
restart: always
healthcheck:
test:
- CMD
- curl
- -f
- https://www.google.com
interval: 1m30s
timeout: 15s
retries: 3
labels:
- autoheal=true
autoheal:
container_name: openvpn-autoheal
image: willfarrell/autoheal:latest
restart: always
environment:
- AUTOHEAL_CONTAINER_LABEL=all
- TZ=Asia/Seoul
- AUTOHEAL_CONTAINER_LABEL=autoheal
volumes:
- /var/run/docker.sock:/var/run/docker.sock
logging:
driver: json-file
options:
max-size: 10m
따라서 전체적인 예시로 표현하자면 위처럼 transmission-openvpn
에 오토힐
컨테이너를 적용한 위와 같은 YAML
형태가 될 것입니다.
물론 여전히 이 헬스체크 설정이 모든 문제를 해결해주진 못했습니다.
Curl
을 이용해 구글 접속을 체크하는 방식이기 때문에 만약 CMD
에서 Curl
을 기본으로 지원하지 않는 컨테이너라면 헬스체크를 적용할 수가 없었습니다.
대표적으로 틴포일 웹서버 컨테이너의 경우 Curl
이 동작하질 않아 다른 방법을 찾아보아야 할 것 같습니다.
다만 트랜스 미션이나 Sonarr
, Radarr
, Bazarr
, TSharp
등의 컨테이너에는 적용하기 너무나 간단하기 때문에 주요 컨테이너들에게는 쉽게 자동 재시작 설정이 가능하다는 장점이 있었습니다.
현재 헬스체크가 적용되었는지를 확인하기 위해서는 컨테이너의 Status(상태)
를 확인하는 것으로 쉽게 체크가 가능합니다.
만약 healthy
상태라면 헬스체크가 제대로 적용 된 것이고 일반적인 running
상태라면 헬스체크를 적용하고 있지 않은 상황이 되겠습니다.
아직까진 모든 상황에 적용 가능한 최고의 해결 방법을 찾진 못했으나 이 또한 해결이 된다면 따로 포스팅 해보도록 하겠습니다.
도움이 되시길 바랍니다.
감삽합니다.