DevOps/docker

apk update temporary error (try again later) 해결 - 3

mkdir 2021. 10. 27. 22:35

또 안된다.

DNS 는 제대로 구글 DNS를 보고 있고, 컨테이너의 resolv.conf도 구글 DNS를 보고 있는데 안된다.

  • 문제의 서버에서 본 dockerd의 실행 커맨드

    $ root@dev-server:~# ps -ef
    root         761       1  0 10월06 ?      00:06:25 /usr/bin/dockerd --iptables=false --exec-opt native.cgroupdriver=systemd --data-root=/var/lib/docker --log-opt max-size=50m --log-opt max-file=5 --dns 8.8.8.8 --dns 8.8.4.4 --dns-search default.svc.cluster.local --dns-search svc.cluster.local --dns-opt ndots:2 --dns-opt timeout:2 --dns-opt attempts:2
  • 정상적인 서버에서 본 dockerd의 실행 커맨드

    root@dev201022:/etc/docker# ps -ef|grep docker
    root      1262     1  0  6월14 ?      01:17:03 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
    • 실행 명령이 다름. 기존 k8s를 설치하고 지우는 과정에서 깔끔하지 못해 기존 snap docker에 서비스 및 소켓이 묶여있다.

수동으로 실행시킨 dockerd vs init.d 서비스로 실행된 dockerd

  • 명백한차이가 있다. 나는 이 차이를 docker 서비스의 잘못으로 생각하고 이슈해결에 들어갔다.

  • dockerd와 docker.socket을 중지

    $ root@dev-server:/etc/systemd/system# systemctl stop docker
    $ root@dev-server:/etc/systemd/system# systemctl stop docker.socket
  • systemd에 바인드된 docker service를 지워준다.

    $ root@dev-server:/etc/systemd/system# rm -rf docker.service docker.service.d
  • 도커 데몬을 재시작한다

    $ root@dev-server:/etc/systemd/system# systemctl daemon-reload
  • dockerd와 docker.socket을 init에 등록

    $ root@dev-server:/etc/systemd/system# systemctl enable docker
    $ root@dev-server:/etc/systemd/system# systemctl enable docker.socket
  • dockerd와 docker.socket을 재시작

    $ root@dev-server:/etc/systemd/system# systemctl restart docker.socket
    $ root@dev-server:/etc/systemd/system# systemctl restart docker
  • docker 가동 체크

    $ root@dev-server:/etc/systemd/system# docker version
    $ root@dev-server:/etc/systemd/system# ps -ef|grep docker
  • 안될 경우 데몬을 다시 리로드해주고 도커를 재시작한다

    $ root@dev-server:/etc/systemd/system# systemctl daemon-reload
    $ root@dev-server:/etc/systemd/system# systemctl restart docker

분석

  • 솔직히 이정도쯤 되면 일반적인 해결방법이 아니다. 굉장히 특수한 케이스의 경우에 해당한다. 직접 소켓에 데몬까지 건드리는 Normal한 해결방법이 대체 어디있냐고...
  • 원인을 나열해보자면 다음과 같다.
    • 기존 snap 및 kubernetes runtime으로 이용되던 도커(1.16버전 클러스터이므로 아직 docker가 공식 runtime이었을 때다)가 kubernetes의 불완전한 제거로 인해 kubernetes DNS(10.x.x.x, 127.0.0.53)를 바라보고 있었지만, 클러스터의 핵심인 API서버가 제거되면서 기존 DNS를 바라보고 있는 docker의 요청을 받아줄 네트워크가 사라진 상태여서 외부 인터넷으로의 ping 및 패키지 업데이트가 불가능
    • DNS를 기존으로 다시 잡아주었으나 재부팅을 진행하지 않았고, 그래서 역시 불완전하게 변경된 도커 데몬이 기적적으로 제대로 인터넷 주소를 잡고 돌아가던 와중, 컴퓨터를 재부팅할 일이 생겨 재부팅
    • 재부팅 후 꼬여있는 채로 어찌저찌 돌아가던 데몬과 소켓이 꼬여버리며 사태가 발생.
    • kubernetes의 불완전 제거로 systemd로 권한이 넘어간 도커가 재부팅 이후 기존의 containerd로 다시 런타임이 되돌아갔지만, 따로 중지해주지 않아 여전히 열려있던 docker socket이 예전 systemd 예하의 socket을 보고 있음
    • 당연히 daemon이 보고있는 위치와 socket이 보고잇는 위치가 달라지니 도커는 구동중인데 이미지고 컨테이너고 아무것도 불러오지 못하는 disconnect 상태가 됨
    • 그래서 기존의 소켓 서비스도 중지 후, 다시 init 시스템에 등록 및 재시작해 제대로 containerd로 권한을 넘김
    • 문제 해결!
    • 하지만 내가 알고있는 이 해결 방법 분석이 맞는건지 모르겠다. 왠지 이번에도 어쩌다가 운좋게 해결된것같아 서버를 몇번씩이나 재부팅해봤지만 이상없었다. 일단 당장의 문제는 해결되었으나 좀 더 공부를 한 후에 다시 분석해보는 것이 좋을것같다...