도커 스터디 4일차(브리지 네트워크 등)

MINK·2023년 3월 22일
0

Docker

목록 보기
4/5

참조 사이트

브리지 네트워크와 --net-alias

  • 브리지 타입의 네트워크와 run 명령어의 --net-alias 옵션을 함께 쓰면 특정 호스트 이름으로 컨테이너 여러 개 접근 가능
  • 위에서 생성한 mybridge 네트워크를 이용해 컨테이너 3개 생성
# --net-alias 옵션의 값은 alicek106으로 설정 - 나는 실수로 06으로 설정함.!
# 다른 컨테이너에서 alicek106이라는 호스트 이름으로 아래 3개의 컨테이너 접근
PS C:\Users\Playdata> docker run -itd --name network_alias_container1 --net mybridge --net-alias alicek06 ubuntu:14.04
95d34bef4bf9056f0b7df4763aa2c39b80fd35a9741d91c5a5f073c1bdf8426c
PS C:\Users\Playdata> docker run -itd --name network_alias_container2 --net mybridge --net-alias alicek06 ubuntu:14.04
6623add3021ee78fbeedc8dbd74e6c9e9ee064b3f709857b1f9c57406980841d
PS C:\Users\Playdata> docker run -itd --name network_alias_container3 --net mybridge --net-alias alicek06 ubuntu:14.04
134b809aeae7422e857e88ea416479ded70fa4564c8e7e9f41e7e3246fa62c83
  • docker inspect network_alias_container1 | grep 172 이런식으로 컨테이너 3개 전부 IP 확인하고, 이 세 개의 컨테이너에 접근할 컨테이너를 생성한 뒤 alicek106이라는 호스트 이름으로 ping 요청을 전송한다.
  • linux에선 grep을 사용할 수 있지만 window cmd 창에서는 findstr로 변환해서 적용
    • findstr
      • [파일내용찾기. 원하는문자열찾기]
C:\Users\mink>docker inspect network_alias_container1 | findstr IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "",
                    "IPAddress": "172.18.0.2",

C:\Users\mink>docker inspect network_alias_container2 | findstr IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "",
                    "IPAddress": "172.18.0.3",

C:\Users\mink>docker inspect network_alias_container3 | findstr IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "",
                    "IPAddress": "172.18.0.4",
# 컨테이너 3개의 IP로 각각 ping이 전송된 것을 확인할 수 있다. 
# 매번 달라지는 IP를 결정하는 것은 별도의 알고리즘이 아닌 라운드 로빈 방식이다. 
# 도커 엔진에 내장된 DNS가 alicek06이라는 호스트 이름을 --net-alias 옵션으로 alicek106을 설정한 컨테이너로 변환하기 때문에 가능하다.
# ping 명령어는 이 IP 리스트에서 첫 번째 IP를 사용하므로 매번 다른 IP로 ping을 전송
PS C:\Users\Playdata> docker run -i -t --name network_alias_ping --net mybridge ubuntu:14.04
root@21e656b4247a:/# ping -c 1 alicek106
ping: unknown host alicek106
root@21e656b4247a:/# ping -c 1 alicek06
PING alicek06 (172.19.0.3) 56(84) bytes of data.
64 bytes from network_alias_container2.mybridge (172.19.0.3): icmp_seq=1 ttl=64 time=0.138 ms

--- alicek06 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.138/0.138/0.138/0.000 ms
root@21e656b4247a:/# ping -c 1 alicek06
PING alicek06 (172.19.0.2) 56(84) bytes of data.
64 bytes from network_alias_container1.mybridge (172.19.0.2): icmp_seq=1 ttl=64 time=0.187 ms

--- alicek06 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.187/0.187/0.187/0.000 ms
root@21e656b4247a:/# ping -c 1 alicek06
PING alicek06 (172.19.0.4) 56(84) bytes of data.
64 bytes from network_alias_container3.mybridge (172.19.0.4): icmp_seq=1 ttl=64 time=0.091 ms

--- alicek06 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.091/0.091/0.091/0.000 ms

  • --link 옵션 : 컨테이너의 IP가 변경돼도 별명으로 컨테이너를 찾을 수 있게 DNS에 의해 자동적 관리

  • 단 이 경우는 디폴트 브리지 네트워크의 컨테이너 DNS라는 점이 다름

  • --net-alias 옵션 또한 --link 옵션과 비슷한 원리

  • mybridge 네트워크에 속한 컨테이너에서 alicek106이라는 호스트 이름으로 접근하면 DNS서버는 라운드 로빈 방식을 이용해 컨테이너의 IP리스트를 반환

  • ping 명령어는 이 IP리스트에서 첫 번째 IP를 사용하므로 매번 다른 IP로 ping을 전송

  • 매번 달라지는 IP를 결정하는 것은 별도의 알고리즘이 아닌 라운드 로빈(round-robin)방식

    • 라운드 로빈

      • 하나의 중앙처리장치를 여러 프로세스들이 우선순위 없이 돌아가며 할당받아 실행되는 방식
# 핑을 전송했는지 확인하기위해선 dig라는 도구를 사용
# dig는 DNS로 도메인 이름에 대응하는 IP를 조회할 때 쓰는 도구
# dig는 ubuntu:14.04 이미지에 설치돼 있지 않음.
# 컨테이너 내부에 설치 및 반환되는 IP 확인
root@21e656b4247a:/# apt-get update

# Unable to locate package dnsutils 발생 시
# source.list 상태 확인 후 설치할 것
root@21e656b4247a:/# apt-get install dnsutils

root@21e656b4247a:/# dig alicek06

  • MacVLAN 네트워크

    • 호스트의 네트워크 인터페이스 카드를 가상화해 물리 네트워크 환경을 컨테이너에게 동일하게 제공

    • MacVLAN을 사용하면 컨테이너는 물리 네트워크상에서 가상의 맥(MAC) 주소를 가짐

    • 해당 네트워크에 연결된 다른 장치와의 통신이 가능

    • MacVLAN에 연결된 컨테이너는 기본적으로 할당되는 IP대역인 172.72.X.X대신 네트워크 장비의 IP할당받음

  • 따라서 MacVLAN을 사용하는 컨테이너들과 동일한 IP 대역을 사용하는 서버 및 컨테이너들은 서로 통신이 가능하다.
# MacVLAN 내용은 더 알아보기!
PS C:\Users\Playdata> docker network create -d macvlan --subnet=192.168.0.0/24 --ip-range=192.168.0.64/28 --gateway=192.168.0.1 -o macvlan_mode=bridge -o parent=eth0 my_macvlan
19aba3697abcd727e5f0fac5ee355af63553fe079486eb5db24ab3773047a4af
PS C:\Users\Playdata> docker run -it --name c1 --hostname c1 --network my_macvlan ubuntu:14.04
root@c1:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
...
root@c1:/# ping 192.168.0.128 -c 1
PING 192.168.0.128 (192.168.0.128) 56(84) bytes of data.
From 192.168.0.64 icmp_seq=1 Destination Host Unreachable

2.2.8 컨테이너 로깅

  • 2.2.8.1 json-file 로그 사용하기
    • 컨테이너 내부에서 어떤 일이 일어나는지 아는 것은 디버깅뿐만 아니라 운영 측면도 중요
    • 애플리케이션 레벨에서 로그가 기록되도록 개발해 별도의 로깅 서비스 사용 가능
    • 단 도커는 컨테이너의 표준 출력(StdOut)과 에러(StdErr) 로그를 별도의 메타데이터 파일저장
# 컨테이너를 생성해 간단한 로그 생성. mysql 5.7 버전의 컨테이너
# 애플리케이션이 잘 구동되는지 여부를 알 순 없음
PS C:\Users\Playdata> docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=1234 mysql:5.7
ffcde61123ab836ea04679300724a7f448a2e86a4d9023bd280b4ea7fb1cd16e

# docker logs 명령어를 써서 컨테이너의 표준 출력을 확인함으로써 애플리케이션의 상태 알 수 있음
# docker logs 명령어는 컨테이너 내부에서 출력을 보여주는 명령어
PS C:\Users\Playdata> docker logs mysql
2022-03-07 14:35:57+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.37-1debian10 started.
2022-03-07 14:35:58+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2022-03-07 14:35:58+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.37-1debian10 started.
....

# 다른 방법으로 컨테이너 생성. 동일한 mysql 컨테이너 생성, -e 옵션 제외
PS C:\Users\Playdata> docker run -d --name no_passwd_mysql mysql:5.7
860001c98fca3b35a0966c804fbf823ffd0f75f4256fe636e9a85498ea81e092

# docker ps 명령어로 목록을 확인하면 컨테이너는 생성됐으나 실행되지 않음. start도 마찬가지
PS C:\Users\Playdata> docker ps --format "table {{.ID}}\t{{.Status}}\t{{.Ports}}\t{{.Names}}"
CONTAINER ID   STATUS             PORTS                   NAMES
ffcde61123ab   Up 6 minutes       3306/tcp, 33060/tcp     mysql
134b809aeae7   Up About an hour                           network_alias_container3
6623add3021e   Up About an hour                           network_alias_container2
95d34bef4bf9   Up About an hour                           network_alias_container1
193c9949d53a   Up 2 hours         0.0.0.0:59318->80/tcp   wordpress
5d1b2095af6b   Up 2 hours         3306/tcp, 33060/tcp     wordpressdb
74027231bfa7   Up 2 hours                                 charming_cerf
  • 이럴 때 docker logs 명령어를 사용하면 애플리케이션에 무슨 문제가 있는지 확인가능

  • 컨테이너가 정상적으로 실행 및 동작하지 않고 docker attach 명령어도 사용하지 못하는 환경에선 docker logs 명령어를 쓰면 간단하고 빠르게 에러 확인

# 컨테이너에서 발생한 로그들
PS C:\Users\Playdata> docker logs no_passwd_mysql
2022-03-07 14:41:09+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.37-1debian10 started.
2022-03-07 14:41:11+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2022-03-07 14:41:11+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.37-1debian10 started.
2022-03-07 14:41:12+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
    You need to specify one of the following:
    - MYSQL_ROOT_PASSWORD
    - MYSQL_ALLOW_EMPTY_PASSWORD
    - MYSQL_RANDOM_ROOT_PASSWORD

# --tail 옵션을 써서 출력할 줄의 수를 설정
PS C:\Users\Playdata> docker logs --tail 2 mysql
2022-03-07T14:37:48.241621Z 0 [Note] mysqld: ready for connections.
Version: '5.7.37'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
# since 옵션에 유닉스 시간을 입력해 특정시간 이후의 로그를 확인
# 유닉스 시간 계산법

PS C:\Users\Playdata> docker logs --since 1474765979 mysql
2022-03-07 14:35:57+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.37-1debian10 started.
2022-03-07 14:35:58+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
..

# -t 옵션으로 타임스탬프를 표시
# -f 옵션을 써서 로그를 스트림으로 확인 <애플리케이션 개발할  유용>
PS C:\Users\Playdata> docker logs -f -t mysql
2022-03-07T14:35:57.979848000Z 2022-03-07 14:35:57+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.37-1debian10 started.
2022-03-07T14:35:58.060013300Z 2022-03-07 14:35:58+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
...

# docker logs 명령어는 run 명령어에서 -i -t 옵션을 설정해 docker attach 명령어를 사용가능
# 컨테이너 내부에서 bash 셀 등을 입출력한 내용 확인가능
PS C:\Users\Playdata> docker run -i -t --name logstest ubuntu:14.04
root@e6281cd0b861:/# echo test!
test!
PS C:\Users\Playdata> docker logs logstest
root@e6281cd0b861:/# echo test!
test!
root@e6281cd0b861:/# exit
exit
  • 기본적으로 위와 같은 컨테이너 로그는 JSON 형태로 도커 내부에 저장
  • 이 파일은 다음 경로에 컨테이너ID로 시작하는 파일명으로 저장된다.
# 아래의 log 파일의 내용을 cat, vi 편집기 등으로 확인하면 logs 명령으로 정제되지 않은 JSON 데이터 확인
# 
# sudo에서
$ cat /var/lib/docker/containers/컨테이너ID/컨테이너ID-json.log

# --log-opt 옵션으로 컨테이너 json 로그 파일의 최대 크기를 지정
# max-size는 로그 파일의 최대 크기, max-file은 로그 파일의 개수를 의미
PS C:\Users\Playdata> docker run -it --log-opt max-size=10k --log-opt max-file=3 --name log-test ubuntu:14.04
  • 어떠한 설정도 하지 않았다면 도커는 위와 같이 컨테이너 로그를 JSON 파일로 저장하지만 그 밖에도 각종 로깅 드라이버를 사용하게 설정해 컨테이너 로그를 수집할 수 있다. 사용 가능한 드라이버의 대표적인 예로 syslog, journald, fluentd, awslogs 등이 있다.

2.2.8.1 SYSLOG 로그

  • 컨테이너의 로그는 JSON뿐 아니라 syslog로 보내 저장하도록 설정
  • syslog는 커널, 보안 등 시스템과 관련된 로그, 애플리케이션의 로그 등 다양한 종류의 로그 수집 및 저장, 그리고 분석
  • 다음 명령어를 입력해 syslog에 로그를 저장하는 컨테이너를 생성하고 로그를 확인
# 리눅스 위에서 돌리신다면 /var/log/syslog or /var/log/messages에서 확인 가능
PS C:\Users\Playdata> docker run -d --name syslog_container --log-driver=syslog ubuntu:14.04 echo syslogtest
043cb065125afd3a705360779de1e633b4e1fa5173c81ecce0d903add6b8e17d
docker: Error response from daemon: failed to initialize logging driver: Unix syslog delivery error.
  • syslog 로깅 드라이버는 기본적으로 로컬호스트의 syslog에 저장하므로 운영체제 및 배포관에따라 syslog 파일의 위치를 알아야 이를 확인
  • 우분투 14.04는 /var/log/syslog, CemtOS와 RHEL은 /var/log/messages 파일에서
  • 우분투 16.04와 CoreOS는 journalctl -u docker.service 명령어로 확인
# 서버 호스트에 rsyslog 서비스가 시작하도록 설정된 컨테이너를 구동하고 rsyslog 컨테이너를 생성
# rsyslog.conf 파일을 열어 syslog 서버를 구동시키는 항목의 주석을 해체한 후 변경사항 저장

PS C:\Users\Playdata> docker run -i -t -h rsyslog --name rsyslog_server -p 514:514 -p 514:514/udp ubuntu:14.04
root@rsyslog:/# vi /etc/rsyslog.conf
..
# provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514

# provides TCP syslog reception
$ModLoad imtcp
$InputTCPServerRun 514
..
# 저장 후 서비스 재시작
root@rsyslog:/# service rsyslog restart
 * Stopping enhanced syslogd rsyslogd                                                          [ OK ]
 * Starting enhanced syslogd rsyslogd                                                          [ OK ]
  • rsyslog는 컨테이너가 아닌 우분투, CentOS 등의 호스트에서도 쓸 수 있으며, 위 방법은 우분투를 기준
  • 컨테이너를 쓰면 호스트가 어떤 운영체제이든 상관없이 rsyslog를 사용할 수 있음
  • 애플리케이션을 컨테이너로 구현하면 도커 엔진이 설치될 수 있는 운영체제라면 어떤 환경이라도 간단 배포
# --log-opt 옵션으로 syslog-facility를 쓰면 로그가 저장될 파일을 바꿈
# facility는 로그를 생성하는 주체에 따라 로그를 다르게 저장
# 여러 애플리케이션에서 수집되는 로그를 분류하는 방법
# facility 옵션을 쓰면 rsyslog 서버 컨테이너에 해당 facility에 해당하는 새로운 로그 파일이 생성
# rsyslog는 우분투에서 쓸 수 있는 기본적인 로깅 방법이므로 별도의 UI를 제공하지 않음
# logentries, LogAnalyzer 등과 같은 로그 분석기와 연동하면 웹 인터페이스를 활용해 편리하게 로그를 확인
docker run -it --log-driver syslog --log-opt syslog-address=tcp://192.168.0.100:514 --log-opt tag="mailog" --log-opt syslog-facility="mail" ubuntu:14.04

TCP와 UDP의 특징과 차이

TCP(Transmission Control Protocol)

  • 전송을 제어하는 프로토콜(규약)

  • 특징

    • 연결 지향 방식
    • 3-way handshaking과정을 통해 연결을 설정하고 4-way handshaking을 통해 해제
    • 흐름 제어 및 혼잡 제어
    • 높은 신뢰성을 보장
    • UDP보다 속도가 느림
    • 전이중(Full-Duplex), 점대점(Point to Point)방식
  • 서버의 특징

    • 서버소켓은 연결만을 담당
    • 연결과정에서 반환된 클라이언트 소켓은 데이터의 송수신에 사용
    • 서버와 클라이언트는 1대1로 연결
    • 스트림 전송으로 전송 데이터의 크기가 무제한
    • 패킷에 대한 응답을 해야하기 때문에(시간 지연, CPU 소모) 성능이 낮다
    • Streaming 서비스에 불리(손실된 경우 재전송 요청을 하므로)

UDP(User Datagram Protocol)

  • 데이터그램 프로토콜(규약)
  • 특징
    • 비연결형 서비스로 데이터그램 방식을 제공
    • 정보를 주고 받을 때 정보를 보내거나 받는다는 신호절차를 거치지 않는다.
    • UDP헤더의 CheckSum 필드를 통해 최소한의 오류만 검출
    • 신뢰성이 낮다
    • TCP보다 속도가 빠르다
  • 서버의 특징
    • UDP에는 연결 자체가 없어서(connect 함수 불필요) 서버 소켓과 클라이언트 소켓의 구분이 없다
    • 소켓 대신 IP를 기반으로 데이터를 전송
    • 서버와 클라이언트는 1대1, 1대N, N대M 등으로 연결
    • 데이터그램(메세지) 단위로 전송되며 그 크기는 65535바이트로, 크기가 초과하면 잘라서 보냄
    • 흐름제어(flow control)가 없어서 패킷이 제대로 전송되었는지, 오류가 없는지 확인할 수 없음
    • 파일 전송과 같은 신뢰성이 필요한 서비스보다 성능이 중요시 되는 경우에 사용

2.2.8.3 fluentd 로깅

  • fluentd는 각종 로그를 수집하고 저장할 수 있는 기능을 제공하는 오픈소스 도구로서, 도커 엔진의 컨테이너 로그를 fluentd를 통해 저장할 수 있도록 플러그인을 공식적으로 제공한다.
  • fluentd은 데이터 포맷으로 JSON을 사용하기 때문에 쉽게 사용할 수 있을뿐만 아니라 수집되는 데이터를 AWS S3, HDFS, MongoDB 등 다양한 저장소에 저장할 수 있는 장점이 있음
  • fluentd와 몽고 DB를 연동해 데이터를 저장하는 방법
  • 어떤 컨테이너가 fluentd에 접근하고, fluentd는 몽고DB에 데이터를 저장하는 구조이다.

  • 위 그림대로 도커 서버,fluentd 서버, 몽고DB 서버로 구성되므로 서버는 최소 3대가 필요하지만 사용자의 환경에 맞게 변경해서 사용
# 몽고DB설치 
PS C:\Users\Playdata> docker run --name mongoDB -d -p 27017:27017 mongo
Unable to find image 'mongo:latest' locally

# 우분투로 접속 < 파워셀에선 이용불가 >
mink@DESKTOP-U4KHBSV:~$ vi fluent.conf

# fluentd.conf 파일이 저장된 디렉토리에서 fluentd 컨테이너 생성
# -v옵션을 이용해 fluentd 컨테이너에 공유 및 설정 파일 사용
# 
mink@DESKTOP-U4KHBSV:~$  docker run -d --name fluentd -p 24224:24224 -v $(pwd)/fluent.conf:/fluentd/etc/fluent.conf -e FLUENTD_CONF=fluent.conf alicek106/fluentd:mongo
Unable to find image 'alicek106/fluentd:mongo' locally
mongo: Pulling from alicek106/fluentd
  • 도커 허브의 fluentd 이미지에는 몽고DB에 연결하는 플러그인이 내장돼 있지 않습니다. alicek106/fluentd:mongo 이미지는 공식 fluentd 이미지에 몽고 DB 플러그인을 설치하는 것
# --log-driver를 fluentd로 설정하고 --log-opt의 fluentd-address 값에 fluentd 서버 주소 지정
# --log-opt tag를 명시함으로써 로그의 태그를 docker.nginx.webserver로 지정했지만
mink@DESKTOP-U4KHBSV:~$ docker run -p 80:80 -d --log-driver=fluentd --log-opt fluentd-address=IP주소:24224 --log-opt tag=docker.nginx.webserver nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx

# 이후는 오류 발생 후에 공부할 예정.
mink@PMK-HS1HH67:~$ docker exec -it mongoDB mongo
OCI runtime exec failed: exec failed: unable to start container process: exec: "mongo": executable file not found in $PATH: unknown

3.21 문제발견 후 검토

# mongo -> mongosh로 변경
mink@PMK-HS1HH67:~$ docker exec -it mongoDB mongosh

docker mongoDB 에러 해결방법

profile
parkminkyu velog

0개의 댓글