docker

[docker] 네트워킹 심화: DNS부터 볼륨 관리까지

99duuk 2024. 8. 12. 20:29

| 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에서의 구현:

  1. Docker Swarm을 사용하면, 서비스 이름으로 자동 로드 밸런싱이 됨
  2. 외부 도구(예: 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도 추가해 같은 네트워크에 묶었다. 

 

 

NCP Search Engine Service to Local ELK

|  배경woosan 프로젝트에서 네이버 클라우드 플랫폼의 Search Engine Service를 사용해 elasticsearch를 사용했다. https://github.com/LuckyVickys/woosan-back/blob/main/Readme.assets/config/ELK.md woosan-back/Readme.assets/config/E

99duuk.tistory.com

더보기
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 호스트에서 같은 데이터에 접근 가능

- 데이터의 중앙 관리 용이

- 호스트 간 데이터 이동이 쉬움

 

주의사항: 

- 네트워크 성능이 데이터 접근 속도에 영향 줄 수 있음

- 네트워크 연결이 끊기면 데이터 접근 불가

- 보안 설정에 주의 필요