클러스터를 새로 만들거나 올릴 때 확인해야 하는 조합은 정해져 있다. 어느 버전이 맞는지는 시간이 지나면 바뀌므로, 숫자를 외우기보다 어디서 확인하는지를 알아 두는 편이 낫다.
| 대상 | 확인처 |
|---|---|
| 지원 OS·커널 | Kubernetes 설치 문서의 요구사항 |
| 컨테이너 런타임 | containerd · CRI-O 릴리스 노트의 Kubernetes 호환 표 |
| CNI | Calico · Cilium 등 각 제품의 요구사항 페이지 |
| kubectl · Helm · Kustomize | 각 도구의 버전 차이 정책 |
| 애드온(ingress 컨트롤러 등) | 제품별 지원 표 |
Kubernetes 자체는 구성 요소 사이의 허용 버전 차이를 정해 두고 있다. 어긋나면 동작은 하다가 예상 못 한 지점에서 깨진다.
Helm 도 비슷한 정책을 둔다. 빌드된 Kubernetes 클라이언트 기준으로 몇 마이너 아래까지 지원한다고 선언하므로, 클러스터를 크게 올린 뒤에는 Helm 도 함께 올려야 한다. 차트 쪽에서 kubeVersion 제약을 걸어 둔 경우도 있어, 최신 클러스터에서 옛 차트의 설치가 거부되기도 한다.
kubectl version
kubeadm version
helm version
containerd --version
crictl version
배포판 버전보다 커널이 먼저다. kubeadm 은 preflight 에서 커널을 검사하고 오래된 커널이면 설치를 막는다. cgroup v2 를 쓰려면 커널과 배포판이 모두 그것을 기본으로 지원해야 한다.
RHEL 7 계열은 커널이 3.10 이라 최근 Kubernetes 를 올릴 수 없다. 자세한 사정은 RHEL 7 폐쇄망용 Docker · Kubernetes RPM 수집 에 있다. 새로 구성한다면 RHEL 9 계열이나 Ubuntu LTS 로 간다.
런타임은 CRI 버전으로 맞춘다. 최근 kubelet 은 CRI v1 만 쓰므로 그것을 제공하지 못하는 오래된 런타임은 붙지 못한다. 증상은 unknown service runtime.v1.RuntimeService 로 나타난다.
모든 노드의 런타임 버전을 같게 맞춘다. 노드마다 다르면 특정 노드에서만 이미지 pull 이 실패하거나 파드가 죽는, 재현이 어려운 문제가 생긴다.
cgroup 드라이버도 양쪽을 맞춘다. systemd 를 쓰는 배포판에서는 둘 다 systemd 다.
grep SystemdCgroup /etc/containerd/config.toml
grep cgroupDriver /var/lib/kubelet/config.yaml
CNI 는 제품이 직접 테스트한 조합만 신뢰한다. "동작 보고가 있다" 와 "테스트된 조합이다" 는 다르다. 신규 구축이라면 그 클러스터 버전을 테스트 대상으로 명시한 CNI 버전을 고른다. 이미 돌고 있는 클러스터를 올릴 때는 CNI 를 먼저 지원 범위로 올린 뒤 클러스터를 올린다.
폐쇄망이라면 CNI 이미지를 미리 받아 사내 레지스트리에 올리고 매니페스트의 이미지 주소를 바꾼다.
# 인터넷 되는 곳에서
docker pull calico/node:vX.Y.Z
docker tag calico/node:vX.Y.Z harbor.example.com/calico/node:vX.Y.Z
docker push harbor.example.com/calico/node:vX.Y.Z
# 매니페스트 치환
sed -i 's#docker.io/calico#harbor.example.com/calico#g' calico.yaml
필요한 이미지 목록은 매니페스트에서 뽑는다.
grep -oE 'image: *\S+' calico.yaml | awk '{print $2}' | sort -u
새 조합으로 가기 전에 검증 환경에서 한 번 세우고 다음을 본다. 노드가 모두 Ready 인지, CNI 파드가 전부 Running 인지, 파드 사이 통신과 DNS 조회가 되는지, 그리고 PVC 가 붙는지다.
kubectl get nodes -o wide
kubectl -n kube-system get pod
kubectl run -it --rm t --image=busybox:1.36 --restart=Never -- nslookup kubernetes.default