22년 연말에 쿠버네티스 장애나서 혼자 야근한 썰이에요
결론부터 말하면, 알 수 없는 이유로 네트워크 설정값이 초기화되었는데
상상도 못햇던 일이라 원인을 찾는데 좀 오래 걸렷어요
”장애 인지 -> 원인 파악 -> 해결“의 흐름으로 정리해봤습니다ㅎ
요약
- k8s pod 내부에서 외부 domain 접근 못함
- 인프라팀 서버 작업 중, ip_forward 설정값이 초기화됨
예상 독자
- coredns 관련 에러가 나는 분들
목차
- 장애 인지
- 원인 파악
- 문제 해결
- 후기
1. 장애 인지
서버 재시작 후, K8S Airflow Job 실패
인프라팀이 ‘펌웨어 업그레이드`한다고 서버를 재시작했어요.
재시작하고 나니, Airflow 장애가 발생하며 메신저에 불이 났어요
심호흡을 하고, 상황 파악부터 시작했습니다.
- Airflow에 Job이 fail 난다.
- 모든 작업이 에러가 나지는 않는다.
- 에러 나는 Job의 공통점은 무엇일까?
확인해보니 `Pod 내부에서 외부 domain을 찾지 못하는 로그`를 출력하고 있었어요.
2. 원인 파악
1: 외부/내부 중 어디가 문제인지 확인하기
2: 담당자에게 네트워크 작업 했는지 확인하기
3: 네트워크 설정값 무엇이 바뀌었는지 확인하기
표면적인 문제는 파악했으니, 근본적인 문제를 찾으려 스무고개를 했습니다
(할 때는 죽겠지만ㅜ, 하고나면 재밌는 작업ㅎ)
[1: 외부/내부 중 어디가 문제인지 확인하기]
- 외부
- DNS 서버 -> 가능성 거의 없음
- 서비스 -> 가능성 낮음
- 내부
- K8S와 `펌웨어 업그레이드`가 충돌하는걸까?
서버 재시작 후 문제가 생긴거니까, 문제는 `내부` 에 있다고 생각했어요
혹시 몰라 확인은 해봤어요ㅎ
+ 외부 서비스는 k8s master node에서 접근이 되고 있더라고요
#k8smaster node
$curl hgkim.test.domain -> 정상
+ pod 내부에 `hostalias`로 host명을 명시하니 접근이 되고요
apiVersion: v1
kind: Pod
metadata:
name: hostaliases-pod-test
namespace: airflow
spec:
restartPolicy: Never
hostAliases:
- ip: "10.120.50.79" # 무작위
hostnames:
- "hgkim.test.domain" # 무작위
containers:
- name: airflow-hosts
image: private-harbor/library/apache/testairflow:0.0.4
command: [ "/bin/bash", "-c", "--" ]
args: [ "while true; do sleep 999; done;" ]
위의 코드처럼 pod를 만들고, 들어가서 curl로 확인하니 /etc/hosts에 추가되었어요
$ k exec -it hostaliases-pod-test -n airflow -- /bin/sh
$ cat /etc/hosts
# Kubernetes-managed hosts file.
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
10.244.2.33 hostaliases-pod-test
# Entries added by HostAliases.
10.120.50.79 hgkim.test.domain # 무작위
$ curl hgkim.test.domain -> 정상
펌웨어 없그레이드 하면서 뭔가 꼬였구나.. 라고 결론 내렸어요
Coredns 로그를 보니가 I/O timeout 나더라고요
$k logs pod/coredns-74cc8dbb74-h6bzt -n kube-system |grep gmes [ERROR] plugin/errors: 2 hgkim.test.domain. AAAA: read udp 10.244.2.146:54549->8.8.4.4:53: i/o timeout [ERROR] plugin/errors: 2 hgkim.test.domain. A: read udp 10.244.2.146:46963->8.8.4.4:53: i/o timeout [ERROR] plugin/errors: 2 hgkim.test.domain. A: read udp 10.244.2.146:50075->8.8.8.8:53: i/o timeout [ERROR] plugin/errors: 2 hgkim.test.domain. AAAA: read udp 10.244.2.146:56772->8.8.4.4:53: i/o timeout [ERROR] plugin/errors: 2 hgkim.test.domain. A: read udp 10.244.2.146:34370->8.8.4.4:53: i/o timeout [ERROR] plugin/errors: 2 hgkim.test.domain. A: read udp 10.244.2.146:60831->8.8.4.4:53: i/o timeout [ERROR] plugin/errors: 2 hgkim.test.domain. A: read udp 10.244.2.146:56370->8.8.4.4:53: i/o timeout [ERROR] plugin/errors: 2 hgkim.test.domain. A: read udp 10.244.2.146:59227->8.8.4.4:53: i/o timeout [ERROR] plugin/errors: 2 hgkim.test.domain. A: read udp 10.244.2.146:40221->8.8.4.4:53: i/o timeout |
로그가 왜 밖으로 나가지? 여기는 외부망 아예 접근 못하는 폐쇄망인데..
펌웨어 업그레이드하면서 네트워크를 건드렸구나!
[2: 담당자에게 네트워크 작업 했는지 확인하기]
- 질문
- 펌웨어 업그레이드한다고 했는데, 혹시 네트워크 작업도 같이 하셨냐?
- 답변
- 네트워크 1G -> 10G로 변경했다.
- 하지만, 우리는 k8s 네트워크에 영향 줄 만한 작업하지 않았다. (변명)
- /etc/hosts에 넣어두면, coredns가 pod에 알아서 잡는다. (훈수)
하하하하하핳하하하하하핳
평화로운 연말에 이게 무슨 신기한 소리일까요?
내가 coredns에 config에 host 설정 안했는데... 그럼 resolve.conf가 잡는건데?
계속 말하면 싸울 것 같아서, 알겠다고 이야기를 마무리했어요
[3: 네트워크 설정값 무엇이 바뀌었는지 확인하기]
- k8s 사전 작업 설정값 확인하기
- /etc/modules-load.d/k8s.conf
- /etc/sysctl.d/k8s.conf
- /etc/sysctl.conf
- 일부 서버는 남아있고, 일부 서버는 없음
설정값을 확인하니 개판이었습니다.
거의 무작위로 어떤 서버는 남아있고, 어떤 서버는 없고...
그냥 root 달라고 해서 제가 바꾸기로 결정했습니다.
3. 문제 해결
root 주세요. 제가 수정할게요.
계속 네트워크 10G 작업은 k8s 네트워크와 관련 없다고 하길래, root 권한 달라고 했어요
아래 파일들을 수정하고 coredns를 재시작했더니 문제가 해결되었습니다.
/etc/modules-load.d/k8s.conf 수정
br_netfilter가 없어져서 master와 worker에 모두 다시 만들어줬어요.
(이상하게 worker 1개에는 남아있더라고요..)
sudo cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
# 적용
$ sudo modprobe overlay
$ sudo modprobe br_netfilter
/etc/sysctl.d/k8s.conf 수정
ip_forward도 확인해줍니다.
(이건 master는 1로 그대로고 worker들이 모두 0으로 바뀌어 있었어요)
$ sudo cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# 적용
$ sudo sysctl --system
/etc/sysctl.conf 수정
마지막에 추가했던 k8s 관련 설정들도 날라갔네요. 이쯤되니 속에서 열이 나더라고요
$ cat /etc/sysctl.conf
#for kubernetes
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-arptables = 1
net.ipv4.ip_local_reserved_ports = 30000-32767
vm.max_map_count = 262144
vm.swappiness = 1
그리고 resolv.conf도 worker에서 초기화되서 추가해줫어요.
(제가 알기로는 worker의 resolv.conf는 상관없지만 원상 복구의 의미에서)
$ /etc/resolv.conf
nameserver 10.55.192.15 # 무작위
nameserver 10.55.193.15 # 무작위
이제 coredns 를 재시작해주고, 아무 로그가 올라오지 않기를 기도해줍니다.
$ k rollout restart deployment.apps/coredns -n kube-system
pod의 로그를 보니 깨끗합니다.
흥분해서 busyvox로 이거저거 다 날려봣어요
# pod 내부에서 외부 domain 접근 가능한지 확인
## 1. curl -v 로 확인
* Trying 10.120.50.79... #무작위
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x55f3dbadffb0)
* Connected to hgkim.test.domain (10.120.50.79) port 80 (#0) #무작위
> GET / HTTP/1.1
> Host: hgkim.test.domain #무작위
> User-Agent: curl/7.64.0
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Date: Wed, 28 Dec 2022 08:14:24 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 21
< Connection: keep-alive
<
* Connection #0 to host hgkim.test.domain left intact
default backend - 404
---
## 2. nslookup
$ nslookup hgkim.test.domain
Server: 10.55.0.13 #무작위
Address: 10.55.0.13:53 #무작위
Name: hgkim.test.domain #무작위
Address: 10.120.50.79 #무작위
*** Can't find hgkim.test.domain: No answer
---
## 3. ping
$ ping hgkim.test.domain #무작위
PING hgkim.test.domain (10.120.50.79): 56 data bytes
64 bytes from 10.120.50.79: seq=0 ttl=253 time=0.166 ms
64 bytes from 10.120.50.79: seq=1 ttl=253 time=0.185 ms
---
## 4. traceroute, icmp
$ traceroute hgkim.test.domain
traceroute to hgkim.test.domain (10.120.50.79), 30 hops max, 46 byte packets
1 10.***.2.1 (10.***.2.1) 0.003 ms 0.002 ms 0.002 ms
2 10.**.74.2 (10.**.74.2) 0.521 ms 0.536 ms 0.619 ms
3 ***-hgkim.test.domain (10.**.***.79) 0.211 ms 0.197 ms 0.099 ms
4 * 10.**.74.11 (10.**.74.11) 995.360 ms !H *
5 10.**.74.11 (10.**.74.11) 995.447 ms !H * 995.353 ms !H
+ 아래는 구글에서 재시작해야한다고 알려주던 글들입니다.
이런 경우는 ip_forward를 해주지 않아서 upstream을 찾지 못하는 경우라고 해요.
서버 재시작해야한다고 하는데, 저는 하지 않아도 되서 기분이 좋네요
i/o timeout in coredns pod #1427
참고: https://github.com/canonical/microk8s/issues/1427
I experienced the same problem and after looking around I noticed that the DNS requests from the endpoints would not be routed via the master interface to the Internet and all my DNS requests would timeout.
I found that IP forwarding was not working for me even though I had net.ipv4.ip_forward = 1 properly across my nodes and master.
After I rebooted my servers, I could see the DNS request being properly routed via the interface and NATed to the interface IP. This resolved it for me at least
Unable to connect internet/google.com from pod. Docker and k8 are able to pull images
This issue is a pure networking issue that is not related to any of EKS upgrade in any way.
The root cause for our issue was the fact that the Worker Node AWS EKS Linux 1.21 AMI being hardened by our security department which turns off the following setting in this file
/etc/sysctl.conf:
net.ipv4.ip_forward = 0
After switching this setting to: net.ipv4.ip_forward = 1 and rebooting the EC2 Node,
everything started working properly. Hope this helps!
Airflow에서 외부 domain에 접근 가능한 것을 확인하고 장애 대응은 마무리가 되었어요
작업량이 많지 않았던 연말이어서 다행이에요
6. 후기
이제 남은건 오리발 내민 담당자에게 전달하는것.
최대한 담백하게 메신저를 보냈습니다.
"root로 무엇을 어디에 수정했고, 정상 작동 확인했습니다."
사과나 수고했다는 이야기 없이,
알겟다면서 임시 root 권한 가져가겠다는 말부터 하네요.
ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
연말이고, 인프라팀과 싸워봐야 득될 것이 없어서
"수고하셨습니다" 로 마무리 했습니다.
덕분에, 2022년의 마지막은 다이나믹했습니다ㅎ
참고
https://discuss.kubernetes.io/t/coredns-error-plugin-errors-2/16106/6
https://github.com/canonical/microk8s/issues/1427
https://stackoverflow.com/questions/72048337/unable-to-connect-internet-google-com-from-pod-docker-and-k8-are-able-to-pull-i/72104194#72104194
'기타 > K8S' 카테고리의 다른 글
K8S) 인증서 갱신하기 (0) | 2023.02.26 |
---|---|
mc)mc cp와 mc mirror 차이 (1) | 2023.01.09 |
mc) mc cp 사용시 인증서 오류날 때_s3v2,s3v4 (0) | 2022.12.23 |
Grafana) helm grafana admin 비밀번호 초기화 해결 (0) | 2022.10.20 |
(Helm) helm3 upgrade failed 이슈 (0) | 2022.08.01 |