[docker] CentOS7에서 Docker Container 생성 시 ping, ssh, Networking Resource 없는 증상 발생 시
필자는 전례없는 이상한 오류를 얼마전에 겪었습니다.
도커 이미지를 빌드하여, 이미지내에서 다른 장비로 통신을 하려고,
ping하니 글쎄... 아래와 같이 통신을 할 수 없다는 에러가 나왔습니다.
에러: ping: connect: Resource temporarily unavailable
증상
: 도커 컨테이너 내부에서 ping: connect: Resource temporarily unavailable 발생으로 외부와 통신이 되지않음
docker-image# ping 8.8.8.8
ping: connect: Resource temporarily unavailable
위의 증상은 다른 호스트 OS(ubuntu, 하모니카OS)에서는 정상적으로 ping이 되었는데,
이상하게 CentOS 7 에서만 같은 이미지인데 ping이 되지않았습니다.
# ssh root@172.17.0.2
ssh: connect to host 172.17.0.2 port 22: Cannot assign requested address
행여나 싶어 ssh로 해봤는데도 역시나 Network 리소스 할당이 되지않는다고 나오네요..
증상 분석
1. 무작정 구글링
: 방화벽을 꺼라.. --> https://stackoverflow.com/questions/62459831/net-core-docker-centos-httprequest-error-socket-exception-resource-temporari
: centos 7이 문제다.. --> https://stackoverflow.com/questions/64921176/networking-not-working-on-docker-centos-7-9
: 호스트 OS의 docker info에 MAX Connection 할당 수를 늘려라..
: 여러가지 도커의 보안 옵션을 모두 적용해보았지만..
기타 등등이 무지하게 보았지만,, 아무것도 해결되지 않았습니다.
2. 호스트 OS와 도커 이미지 내부의 통신 확인
: 호스트 OS -> 도커 컨테이너로는 통신이 정상
: 도커 컨테이너는 증상처럼 시도조차 되지않았습니다.
3. 도커 이미지 커널 리소스 영역 확인
그러던 와중 문뜩 도커 컨테이너 영역안에서 커널 파라메터가 어떻게 설정되어 있는지 궁금했습니다.
구글링 하던 와중 오아시스와 같은 해결 방안 블로그를 찾게 되었습니다.
https://blog.actorsfit.com/a?ID=01000-861c2331-ae1c-4f4c-b891-f1060e3d54ef
아래 정리해서 원인과 조치를 설명 드릴게요.
원인
도커 컨테이너는 호스트 OS의 커널 파라미터를 참조하여 로딩되기 때문에,
OS의 설정에 따라 상응하는 동작을 합니다.. ㅠㅠ
이는 앞서 문제점의 컨테이너가 같고, 호스트 OS가 다를때 증상이 발생하기도 하고, 발생하지 않기도 하네요.. ㅠㅠ (흑)
문제의 발생 컨테이너에서는 아래와 같이 커널 파라미터가 설정되어 있었습니다
# sysctl -a |grep ipv4
...
net.ipv4.ip_forward = 1
net.ipv4.ip_forward_use_pmtu = 0
net.ipv4.ip_local_port_range = 32768 60999 <-- 문제의 녀석
net.ipv4.ip_no_pmtu_disc = 0
net.ipv4.ip_nonlocal_bind = 0
net.ipv4.tcp_mem = 618390 824522 1236780
net.ipv4.tcp_min_snd_mss = 48
net.ipv4.xfrm4_gc_thresh = 32768
# syscntl -a |grep somaxconn
net.core.somaxconn = 128 <-- 문제의 녀석
커널 튜닝의 내용을 여기 말하기엔 너무 내용이 긴 관계로 아래의 정보를 참고해주세요!
https://meetup.toast.com/posts/54
조치
이제 증상의 원인을 알았으니, 조치는 방법에 따라 달리하시면 됩니다.
방안 1. 도커 내부 컨테이너의 커널 파라미터를 변경
(변경 시 주의사항!! 장비의 리눅스와 달리 컨테이너는 sysctl.conf를 수정해도 재부팅 시 영구적용이 되지않습니다.)
--> 커널 파라미터 수정
# vi /etc/sysctl.conf
net.core.somaxconn = 1024
net.ipv4.ip_local_port_range = 1024 65535
--> 커널 파라미터 적용
# sysctl -p
net.core.somaxconn = 1024
net.ipv4.ip_local_port_range = 1024 65535
--> 통신 확인 (된다 내눈물모아..ㅠ)
# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=114 time=30.9 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=114 time=31.1 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=114 time=30.9 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=114 time=30.9 ms
※ 커널 파라미터 영구 적용방법
https://blog.51cto.com/nanfeibobo/1716792
https://gist.github.com/ruseel/704de385e6abd381f557
방안 2. 도커 컨테이너의 네트워크 영역을 호스트 OS와 공유하여 사용
docker run 시 --network host 옵션을 사용
원인 분석처럼 컨테이너의 커널영역의 문제로 많은것들이 부딫힐 수 있다.
역으로 바꿔 생각하면 보안상의 문제가 되지않는다면 --net=host 옵션으로 공유해서 쓰면 좋은 해결방법이라고 생각합니다.
하지만 이 방법은 모든 호스트의 네트워크 트래픽을 컨테이너가 동일하게 바라보고 있기때문에, 자원 분리 및 영역에 대한 침법으로 도커의 이념과는 맞지않을수 있으니 잘 고려해서 사용하시기 바랍니다.
조치방안 둘다 각자의 스타일대로 조치하여 용도에 맞게 사용하시면 될거같습니다.^^
제가한 삽질이 누군가에게 도움이 되었으면 좋겠네요. ㅋㅋ
추가적으로 궁금하신 사항이 있거나 이에대해 조언을 하실분이 있으시면 언제든지 댓글로 남겨주세요!
토론 좋아합니다.!!