소개
로컬환경에 구축한 multipass + kubernetes 환경에 github self-hosted runner 을 구축하면서 만난 네트워크 문제의 해결 과정에 대해 정리해보려합니다.
kubernetes 환경에서 github ARC(Actions Runner Controller) 를 통해 self-hosted runner 를 구축하였는데요. self-hosted runner 는 잘 구축이 되어 Action workflow 를 돌려도 그런데로 잘 구동이 되었습니다.
그런데 Action workflow 구동 과정에서 network 관련 error 가 너무 자주 발생하여 디버깅을 해보았습니다.
현상
주 현상은 self-hosted runner 에서 구동되는 Action workflow 가 잘 되다가도 간헐적으로 아래와 같은 network error 를 발생시키는 문제였는데요.
에러는 아래와 같았습니다.
node 관련 docker registry 접속 중에도 net/http: TLS handshake timeout
이 발생하고..
Error: buildx failed with: ERROR: failed to solve: failed to compute cache key: failed to copy: httpReadSeeker: failed open: failed to do request: Get "https://registry-1.docker.io/v2/library/node/blobs/sha256:c6cf28de8a067787ee0d08f8b01d7f1566a508b56f6e549687b41dfd375f12c7": net/http: TLS handshake timeout
trivy 취약점 스캔을 위한 db 다운로드 중에도 net/http: TLS handshake timeout
에러가 발생…
024-05-24T16:29:49Z INFO Downloading DB... repository="ghcr.io/aquasecurity/trivy-db:2"
2024-05-24T16:30:19Z FATAL Fatal error init error: DB error: failed to download vulnerability DB: database download error: OCI repository error: 1 error occurred:
* Get "https://ghcr.io/v2/": net/http: TLS handshake timeout
buildx 다운 중에도 완료가 되지 않고 지속 다운로드 시도등…
처음에는 host 나 container 의 Network 문제인줄 알았으나.. 지속적으로 발생이 되어 디버깅 모드로도 확인을 해보 관련 github issue 와 docs 를 뒤졌습니다. build-push-sction Action 레포의 issue 에서도 비슷한 문제에 대한 답변을 찾을 수 있었습니다.
해결
문제는 kubernetes pod 내 container 의 기본 네트워크 Interface 와 docker 데몬의 bridge network interface 간 MTU 설정 문제로 인한 패킷 손실로 발생하는 네트워크 문제였습니다.
배포하였던 self-hosted runner 의 container 로 shell 접속 후 ip a
명령어를 확인해보면, 아래와 같이 network interface 를 확인할 수 있습니다.
여기서 eth0
은 container interface 이고 docker0
은 docker demon 의 brige interface 인데요.
ip a
명령어를 통해서 Interface 각각의 MTU 값을 확인할 수 있었는데, 위의 캡처에에서는 조치를 하고난 이후이지만..
초기에는 docker0 의 MTU 값이 1500 으로 설정이 되어있어 eth0 보다 높게 설정이 되어있었는데요.
네트워크 에러가 발생한 시점과 같이 `docker0 의 MTU 값 > eth0 의 MTU 값` 로 설정이 되면 패킷 손실이 발생할 수 있습니다.
container 내부의 패킷 flow 가 아래와 같을텐데,
여기서 더 내부에 위치한 docker demon interface 의 MTU 가 container interface 의 MTU 보다 높을 경우, docker demon interface 에서 보내는 최대 크기의 데이터 패킷 크기가 container interface 의 MTU 를 초과하여 container interface 단에서 패킷 손실이 발생하게 되고, 이로인한 네트워크 문제가 발생하게 됩니다.
그래서 docker0 의 MTU 값을 eth0 의 MTU 와 같거나 작게 만들어 주면 됩니다.
docker MTU 를 조절하는 방법은 github 의 ARC 레포에서도 확인할 수 있는데요.
runner 를 배포할때 사용하였던 manifest 에서 아래와 같이 dockerMTU
값을 지정해주고 재배포 해주면 됩니다.
apiVersion: actions.summerwind.dev/v1alpha1
kind: RunnerDeployment
metadata:
name: runnerdeploy
spec:
replicas: 2
template:
spec:
dockerMTU: 1400
repository: jangdoyeon/checkingress-local
env:
- name: ARC_DOCKER_MTU_PROPAGATION
value: "true"