amkorousagi / Trendup

OIDC2020
0 stars 0 forks source link

container간 통신 실험하기(0703) #6

Closed amkorousagi closed 4 years ago

amkorousagi commented 4 years ago

Flask로 구동되는 웹서버에서 주소뒤에 오는 "/"와 것으로 구분하여 IP와 Port 번호로 직접 컨테이너간 통신하는 코드와 실행 결과를 스샷찍어서 올리기

amkorousagi commented 4 years ago

이제부터 본격적으로 container간 통신을 조사 및 구현하겠다

amkorousagi commented 4 years ago

https://docs.oracle.com/cd/E37670_01/E75728/html/section_rsr_p2z_fp.html 같은 노드내에서는 --link 옵션을 통해 컨테이너 끼리 연결 및 통신 할 수 있는 듯 하다

amkorousagi commented 4 years ago

https://dzone.com/articles/docker-to-docker-networking-between-tcp-client-and 서로 다른 노드에 있는 docker contianer 끼리 tcp로 통신하는 step-by-step 예제이다. 3시간 정도 있으면 만들 수 있을 것 같기도 하다

amkorousagi commented 4 years ago

근본적으로 server-client 구조와 동일할 것이다. multi server?

생성되는 정보는 모두 DB에 저장.

(제어컨) --데이터수집시작해-->(유튜브컨),(웹크롤링컨) (유튜브컨)--데이터수집끝남-->(제어컨),(웹크롤링컨) (제어컨)--그래프그려-->(그래프컨) (제어컨)--머신러닝해-->(머신러닝컨) (그래프컨)--그래프끝남-->(제어컨) (머신러닝컨)--머신러닝끝남-->(제어컨)

(프런트엔드)--정보줘-->(백엔드컨)--정보줘-->DB DB--정보-->(백엔드컨)--정보-->(프런트엔드)

amkorousagi commented 4 years ago

echo server? 먼저 자신이 어떤 컨테이너인지 알려줌. multi echo 서버를 응용해서 각 container 마다 상태를 나타내는 전역변수를 두고 하면 될듯.

다음은 python tcp multi echo 예제

amkorousagi commented 4 years ago

https://webnautes.tistory.com/1381

amkorousagi commented 4 years ago

python3로 돌릴때 멀티 에코 서버 정상적으로 작동됨. 이제 container port 설정 및 구동해볼것. 이후 전역변수나 약속등을 정해서 적절히 코딩할 것

amkorousagi commented 4 years ago

--coding:utf-8--

import socket from _thread import *

쓰레드에서 실행되는 코드입니다.

접속한 클라이언트마다 새로운 쓰레드가 생성되어 통신을 하게 됩니다.

def threaded(client_socket, addr): print('Connected by :', addr[0], ':', addr[1])

# 클라이언트가 접속을 끊을 때 까지 반복합니다.
while True:

    try:

        # 데이터가 수신되면 클라이언트에 다시 전송합니다.(에코)
        data = client_socket.recv(1024)

        if not data:
            print('Disconnected by ' + addr[0], ':', addr[1])
            break

        print('Received from ' + addr[0], ':', addr[1], data.decode())

        client_socket.send(data)

    except ConnectionResetError as e:

        print('Disconnected by ' + addr[0], ':', addr[1])
        break

client_socket.close()

HOST = '127.0.0.1' PORT = 9999

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_socket.bind((HOST, PORT)) server_socket.listen()

print('server start')

클라이언트가 접속하면 accept 함수에서 새로운 소켓을 리턴합니다.

새로운 쓰레드에서 해당 소켓을 사용하여 통신을 하게 됩니다.

while True: print('wait')

client_socket, addr = server_socket.accept()
start_new_thread(threaded, (client_socket, addr))

server_socket.close()

amkorousagi commented 4 years ago

--coding:utf-8--

import socket

HOST = '127.0.0.1' PORT = 9999

client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

client_socket.connect((HOST, PORT))

키보드로 입력한 문자열을 서버로 전송하고

서버에서 에코되어 돌아오는 메시지를 받으면 화면에 출력합니다.

quit를 입력할 때 까지 반복합니다.

while True:

message = input('Enter Message : ')
if message == 'quit':
    break

client_socket.send(message.encode())
data = client_socket.recv(1024)

print('Received from the server :',repr(data.decode()))

client_socket.close()

amkorousagi commented 4 years ago

와 ㄹㅇ 무슨 이런 경우가 다있을까? docker container에선 port를 직접 하나씩 listen시키고 forwarding 시켜야 되기 때문에 tcp 통신에서 client가 무슨 port로 통신하는지 확인해보니 randorm이다? 어떻게 지정할순 없나?

server start wait wait Connected by : 127.0.0.1 : 47338 Disconnected by 127.0.0.1 : 47338 wait Connected by : 127.0.0.1 : 47340

amkorousagi commented 4 years ago

bind()를 통해 자신의 port를 지정할수 있다. 서버만 쓰는게 아니라 client도 필요하다면 bind를 쓸수 있다.


client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) client_socket.bind(('0.0.0.0',5001)) client_socket.connect((HOST, PORT))

amkorousagi commented 4 years ago

한 컨테이너 내에서 tcp통신은 된다(port 설정만 잘하면)[ 스크린샷, 2020-08-06 22-26-14

amkorousagi commented 4 years ago

그런데 다른 컨테이너 끼리 tcp 통신은 되지 않는다. 왜 그럴까? 자꾸 ConnectionRefusedError: [Errno 111] Connection refused 라고 나온다

amkorousagi commented 4 years ago

구글링해봐도 server측이 해당 port를 closed 한 상태라서 연결요청이 거절되는 거라고 하는데 나는 server container의 해당 port를 분명히 listen하고 forwarding까지 해놓았다.

여기서 유츄할 수 있는 건 아마 127.0.0.0 으로 주소 설정하면 container에게 돌아오기만 한다? 공인 ip주소를 쓴다면 달라질까? 일단 hostname을 서버의 세부 주소를 확인하고 127.0.0.1을 넣던지 해봐야겠다

amkorousagi commented 4 years ago

내가 알기론 container의 port forwarding은 외부 네트워크에 노출된 port를 컨테이너의 내부 port로 돌리는 것이다. 그렇다면 127.0.0.0은 실질적으로 network를 거치지 않고 그저 loop back 주소로서 2계층은 data link 계층까지 갔다가 다시 돌아오는 것 뿐이라 했다.

그렇다면 server에서 공인 ip를 사용해서 실질적인 network를 타고 오면 port forwarding이 될것이다.

amkorousagi commented 4 years ago

http://pyrasis.com/Docker/Docker-HOWTO https://docs.docker.com/engine/reference/builder/

amkorousagi commented 4 years ago

스크린샷, 2020-08-06 23-57-52

왜 안되는지 모르겠다

amkorousagi commented 4 years ago

127.0.0.1이 loopback 이며 이는 network를 거치지 않고 동작함을 확인했다. port를 닫아놔도 같은 컨테이너 안에 있다면 동작한다 스크린샷, 2020-08-07 00-35-43

amkorousagi commented 4 years ago

근데 아무리 뱅이 쳐도 서로다른 컨테이너 끼리 안되는 걸 보면 앞서서 client의 port를 bind해 주었듯, 아마 각 client마다 새로운 port로 응답을 돌려주는 것 같기도 하고... 아니면 그냥 방화벽에 막히는 것 같기도하고.. 머지 설정문제인가? 포트포워딩? ACG?

모르겠다 왜 안되는 지 모르겠다. 인터넷에서 tcp 예제라고 찾은건 --network를 통해서 같은 local내에서 그냥 tcp로 통신하는 것 같던데, 다른 node끼리 tcp 통신하는 예제는 없나>

amkorousagi commented 4 years ago

https://bluese05.tistory.com/53 아니 그저 컨테이너의 포트를 외부에 노출시키고 tcp 주고 받는 건데 왜 안되지? 방화벽 iptables 도 한번확인해보자. ncp 포트포워딩과 ACG는 문제없음을 확인했다.

머지 머지 머지 머지 머지

만물의 백과사전이 있으면 좋겠다 동문서답하는 구글말고

amkorousagi commented 4 years ago

왜그런지 알았다

내가 ACG, container port forwarding, .. 다했지만, docker host의 방화벽을 신경을 안썻다 ㄹㅇ 개발환경 세팅이 제일 힘드네. 한숨자고 생각하니 더 잘된다

root@psc:~# netstat -tnlp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:111 0.0.0.0: LISTEN 494/rpcbind
tcp 0 0 127.0.0.53:53 0.0.0.0:
LISTEN 665/systemd-resolve tcp 0 0 0.0.0.0:22 0.0.0.0: LISTEN 907/sshd
tcp6 0 0 :::111 :::
LISTEN 494/rpcbind
tcp6 0 0 :::22 :::* LISTEN 907/sshd

amkorousagi commented 4 years ago

root@psc:~# ufw allow 5001/tcp Rules updated Rules updated (v6) root@psc:~# ufw allow 5002/tcp Rules updated Rules updated (v6)

amkorousagi commented 4 years ago

그래도 안된다 --net 설정을 파봐야겠다

amkorousagi commented 4 years ago

머지 contianer가 아니라 서버에서 해도 똑같은 결과가 나오는데? bind의 host가 잘못됬다?

스크린샷, 2020-08-07 14-16-05

amkorousagi commented 4 years ago

와 server의 bind에 쓰는 host가 사설 ip여야 되네? 왜 공인이 아니고 사설이지? 스크린샷, 2020-08-07 14-19-15

amkorousagi commented 4 years ago

와 됬다. server의 bind의 host는 hostname -I 쳤을때 뜨는 값으로 하고 client는 server의 공인 ip를 알려주니 됬다. 할때는 ACG, ufw, portforwarding을 다 신경써줘야되고. 각 ip는 server-bind, client-bind, clinet-destnation-ip 전부 다르게 해줘야된다.

개발환경설정 네트워크 무슨 원리인지 잘모르겠다. 서버가 왜 사설 ip로 binding되는 거지?

amkorousagi commented 4 years ago

인터넷에도 자료가 없다 모든 예제가 '127.0.0.1'f로 되어있다

amkorousagi commented 4 years ago

container tcp communication 예제 성공, 개발환경 세팅 성공. 이제 실질적 코드를 개발하고 백그라운드에서 돌리면 되겠다