| Docker의 DNS 및 서비스 디스커버리
| DNS란?
DNS(Domain Name System)는 인터넷의 전화번호부와 비슷함. 우리가 웹사이트 주소를 입력하면, DNS가 주소를 컴퓨터가 이해할 수 있는 IP 주소로 변환해줌
| Docker의 내장 DNS 시스템
docker는 자체 DNS 서버를 가지고 있음. 이 DNS 서버는 컨테이너들이 서로 이름으로 찾을 수 있게 해줌
| 작동 방식
1. 컨테이너를 생성할 때 docker가 자동으로 이름을 DNS에 등록함
2. 같은 네트워크에 있는 다른 컨테이너들은 이 이름을 사용해 통신할 수 있음
예
# 네트워크 생성
docker network create sample_network
# 두 개의 컨테이너 생성
docker run -d --name webserver --network sample_network nginx
docker run -d --name database --network sample_network mysql
# webserver 컨테이너에서 database 컨테이너로 ping 테스트
docker exec -it webserver ping database
'webserver'는 'database'라는 이름만으로 다른 컨테이너와 통신할 수 있음
| 서비스 디스커버리
서비스 디스커버리는 "어떤 서비스가 어디에 있는지 자동으로 찾아주는 것"임
동적 환경에서 서비스의 위치를 자동으로 찾을 수 있게 해줌
- 컨테이너의 ip주소는 자주 변경될 수 있고,
- 여러 개의 같은 서비스 컨테이너가 실행 중일 수 있기 때문에
서비스 디스커버리는 중요하다.
Docker에서의 구현:
- Docker Swarm을 사용하면, 서비스 이름으로 자동 로드 밸런싱이 됨
- 외부 도구(예: Consul, etcd)를 사용해 더 복잡한 서비스 디스커버리를 구현할 수 있음
| 네트워크 구성과 성능
Bridge 네트워크
가장 일반적인 네트워크 모드
약간의 성능 저하가 있지만, 대부분의 경우 충분히 빠름
컨테이너 간 통신과 외부 통신 모두 가능
Host 네트워크
가장 빠른 네트워크 모드
컨테이너가 호스트의 네트워크를 직접 사용
보안상 위험할 수 있음
Overlay 네트워크
여러 docker 호스트에 걸친 통신에 사용
약간의 성능 저하가 있지만, 여러 컴퓨터에 걸친 통신을 가능하게 함
| 성능 최적화
1. Host 네트워크 사용
단일 호스트에서 최고의 성능이 필요할 때 사용
2. 같은 물리적 호스트에 관련 컨테이너 배치
네트워크 지연 줄일 수 있음
3. 불필요한 네트워크 트래픽 줄이기
필요한 포트만 노출하기
4. 컨테이너 네트워크 모드 선택시 고려 사항
보안 vs 성능
단일 호스트 vs 다중 호스트
| Docker의 네트워크 보안
| 사용자 정의 네트워크 vs 기본 네트워크
기본 네트워크
- 모든 컨테이너가 기본적으로 이 네트워크에 연결됨
- 컨테이너 간 ip 주소로만 통신 가능
- 보안상 취약할 수 있음
사용자 정의 네트워크
- 사용자가 직접 만든 네트워크
- 같은 네트워크의 컨테이너끼리만 통신 가능
- 컨테이너 이름으로 통신 가능 (내장DNS 사용)
- 더 나은 격리와 보안 제공
| 네트워크 격리 통한 보안 강화 방법
1. 별도의 네트워크 생성하기
docker network create --internal secure_network
"--internal" 는 네트워크가 외부와 통신할 수 없게 만듦
2. 민감한 서비스는 내부 네트워크에만 연결하기
docker run -d --name database --network secure_network mysql
3. 필요한 경우에만 컨테이너 간 통신 허용하기
어플리케이션 서버만 데이터베이스와 통신할 수 있게 설정
4. 외부 연결이 필요한 서비스는 별도의 네트워크와 연결하기
docker network create public_network
docker run -d --name webserver --network public_network --network secure_network nginx
"webserver"는 외부와 통신할 수 있지만, database는 직접 외부와 통신할 수 없음
각 서비스를 필요한 만큼 노출시켜 전체 시스템의 보안을 강화할 수 있다고 한다.
| 실제 프로덕션 환경에서의 Docker 네트워크 활용 사례
| MSA에서 네트워크 구성
(MSA: 큰 애플리케이션을 작은 독립적인 서비스들로 나누는 방식)
1. API 게이트웨이: 외부 요청을 받아 적절한 서비스로 라우팅
2. 사용자 서비스: 사용자 정보 관리
3. 상품 서비스: 상품 정보 관리
4. 주문 서비스: 주문 처리
5. 데이터베이스: 각 서비스의 데이터 저장
| 네트워크 구성
# 외부 네트워크 생성
docker network create external_network
# 내부 네트워크 생성
docker network create --internal internal_network
# API 게이트웨이 실행 (외부 및 내부 네트워크에 연결)
docker run -d --name api_gateway --network external_network --network internal_network api_image
# 내부 서비스들 실행 (내부 네트워크에만 연결)
docker run -d --name user_service --network internal_network user_service_image
docker run -d --name product_service --network internal_network product_service_image
docker run -d --name order_service --network internal_network order_service_image
# 데이터베이스 실행 (내부 네트워크에만 연결)
docker run -d --name database --network internal_network database_image
API 게이트웨이만 외부에서 접근 가능하고, 다른 서비스들은 내부 네트워크를 통해 안정하게 통신함
| 멀티 티어 애플리케이션에서의 네트워크 설계
멀티 티어 애플리케이션: 프론트엔드, 백엔드, 데이터베이스 등 여러 계층으로 구성된 애플리케이션
1. 프론트엔드: 사용자 인터페이스
2. 백엔드: 비즈니스 로직 처리
3. 데이터베이스: 데이터 저장
| 네트워크 구성
# 프론트엔드 네트워크 (외부 접근 가능)
docker network create frontend_network
# 백엔드 네트워크 (내부 통신용)
docker network create --internal backend_network
# 프론트엔드 실행
docker run -d --name frontend --network frontend_network -p 80:80 frontend_image
# 백엔드 실행 (양쪽 네트워크에 연결)
docker run -d --name backend --network frontend_network --network backend_network backend_image
# 데이터베이스 실행
docker run -d --name database --network backend_network database_image
프론트엔드는 외부에서 접근 가능하고, 백엔드는 프론트엔드와 데이터베이스 양쪽에서 통신할 수 있음.
데이터베이스는 직접적인 외부 접근이 불가능
| Docker 네트워크 트러블슈팅
| 주요 문제 해결 명령어
# 모든 Docker 네트워크 목록을 보여줌
docker network ls
# 특정 네트워크의 상세 정보 보여줌
docker network inspect my_network
# 컨테이너의 로그 확인
docker logs my_container
# 실행 중인 컨테이너 내부에서 명령 실행
docker exec -it my-container ping google.com
| 주요 문제 해결 명령어
1. 컨테이너 간 통신 불가
같은 네트워크에 있는 컨테이너들이 서로 통신할 수 없는 경우
a. 컨테이너들이 같은 네트워크에 있는지 확인
docker network inspect my_network
b. 방화벽 설정 확인, 컨테이너 내부에서 ping 테스트
docker exec -it container1 ping container2
2. 포트 바인딩 충돌
컨테이너를 시작할 때 "port is already allocated" 오류 발생
a. 사용중인 포트 확인
docker ps
b. 다른 포트 사용 또는 충돌하는 서비스 중지
docker run -p 8080:80 my_image # 8080 포트로 변경
등...
최근에 겪었던 네트워크 오류 중 기억에 남는 건..
docker-compose로 띄운 elk 컨테이너와 mysql 컨테이너의 네트워크가 달라 logstash가 동기화하지 못했었다.
그래서 기존 컨테이너는 내리고, docker-compose내에 mysql도 추가해 같은 네트워크에 묶었다.
version: '3.8'
services:
es:
image: docker.elastic.co/elasticsearch/elasticsearch:7.17.10
container_name: WB-es
environment:
- discovery.type=single-node
- ES_JAVA_OPTS=-Xms512m -Xmx512m
- TZ=Asia/Seoul # 추가된 시간대 설정
volumes:
- esdata:/usr/share/elasticsearch/data
ports:
- "9200:9200"
networks:
- wb-net
kibana:
image: docker.elastic.co/kibana/kibana:7.17.10
container_name: WB-kibana
environment:
- ELASTICSEARCH_HOSTS=http://WB-es:9200
ports:
- "5601:5601"
networks:
- wb-net
logstash:
image: arm64v8/logstash:7.17.10
container_name: WB-logstash
volumes:
- ./logstash/pipeline:/usr/share/logstash/pipeline
- ./logstash/mysql-connector-java-8.0.30.jar:/usr/share/logstash/mysql-connector-java-8.0.30.jar
- logstash_data:/usr/share/logstash/data
environment:
- xpack.monitoring.enabled=false
ports:
- "9600:9600"
networks:
- wb-net
mysql:
image: mysql:latest
container_name: WB-mysql
environment:
- MYSQL_ROOT_PASSWORD=********
- MYSQL_DATABASE==********
- TZ=Asia/Seoul # 추가된 시간대 설정
volumes:
- mysqldata:/var/lib/mysql
ports:
- "3306:3306"
- "33060:33060"
networks:
- wb-net
redis:
image: redis:latest
container_name: WB-redis
volumes:
- /Users/tars/Documents/WB/redis:/data
ports:
- "6379:6379"
networks:
- wb-net
volumes:
esdata:
logstash_data:
mysqldata:
networks:
wb-net:
| Docker Swarm 및 Kubernetes와의 연계
Docker Swarm과 Kubernetes는 컨테이너 오케스트레이션 도구로, 여러 Docker 호스트를 관리하고 애플리케이션을 쉽게 확장할 수 있게 해준다.
| 오케스트레이션 환경에서의 네트워크 개념 확장
1. 멀티 호스트 네트워킹
여러 물리적 서버에 걸쳐 있는 컨테이너들이 서로 통신할 수 있게 해줌
Overlay 네트워크를 사용해 구현함
2. 서비스 디스커버리
새로운 컨테이너를 생성하거나 제거될 때 자동으로 감지하고 업데이트함
내장 DNS를 사용하여 서비스 이름으로 접근할 수 있게 함
3. 로드 밸런싱
트래픽을 여러 컨테이너 인스턴스에 고르게 분산시킴
서비스 이름으로 접근하면 자동으로 로드밸런싱됨
| 오케스트레이션 환경에서의 네트워크 개념 확장
Overlay 네트워크는 여러 Docker 호스트에 걸쳐 있는 컨테이너들이 서로 통신할 수 있게 해주는 가상 네트워크임
- 여러 물리적 서버에 걸쳐 있는 컨테이너 간 통신 가능
- 암호화된 통신 옵션 제공
- 서비스 수준의 네트워크 정의 및 관리
사용 예
# Swarm 초기화
docker swarm init
# Overlay 네트워크 생성
docker network create --driver overlay my_overlay_network
# 서비스 배포
docker service create --name my_web --network my_overlay_network --replicas 3 nginx
3개의 nginx 컨테이너가 생성되고, 모두 "my_overlay_network"를 통해 서로 통신할 수 있음
| 네트워크와 볼륨 관리의 연관성
Docker에서 네트워크와 볼륨은 별개의 개념이지만, 때로는 밀접하게 관련되기도 함
| 네트워크 구성이 볼륨 관리에 미치는 영향
1. 분산 스토리지 시스템
- 여러 호스트에 걸쳐 있는 컨테이너들이 같은 데이터에 접근해야 할 때 사용함
- 네트워크 성능이 데이터 접근 속도에 큰 영향을 미침
2. 백업 및 복구
- 네트워크를 통해 원격 위치에 볼륨을 백업할 수 있음
- 네트워크 구성에 따라 백업 속도와 보안이 달라질 수 있음
| 네트워크 구성이 볼륨 관리에 미치는 영향
네트워크 attached storage(NAS)는 네트워크를 통해 접근할 수 있는 저장소임
사용 예 (NFS 볼륨)
# NFS 볼륨 생성
docker volume create --driver local \
--opt type=nfs \
--opt o=addr=192.168.1.1,rw \
--opt device=:/path/to/dir \
nfs_volume
# NFS 볼륨을 사용하는 컨테이너 실행
docker run -d --name nfs_container --volume nfs_volume:/data my_image
NFS(network file system) 서버(192.168.1.1)의 특정 디렉토리를 Docker 볼륨으로 마운트하고, 이를 컨테이너에서 사용함
-> 여러 물리적으로 분리된 Docker 호스트나 컨테이너들이 네트워크를 통해 하나의 공유 스토리지(NAS)를 사용하는 상황
장점:
- 여러 Docker 호스트에서 같은 데이터에 접근 가능
- 데이터의 중앙 관리 용이
- 호스트 간 데이터 이동이 쉬움
주의사항:
- 네트워크 성능이 데이터 접근 속도에 영향 줄 수 있음
- 네트워크 연결이 끊기면 데이터 접근 불가
- 보안 설정에 주의 필요
'docker' 카테고리의 다른 글
[docker] 네트워킹 기본 _bridge, host, overlay (0) | 2024.08.12 |
---|---|
[docker] 컨테이너간 통신 이해 (0) | 2024.08.12 |
[docker] 컨테이너 볼륨 백업 (1) | 2024.07.24 |
쿠버네티스 오버뷰 (1) | 2024.06.17 |
[docker] 오라클 컨테이너 백업하고 바인드 마운트하기 1_실패 (0) | 2024.06.09 |