kubernetes version을 1.18에서 1.28로 업그레이드한 뒤에 operator를 빌드하여 배포했더니 error가 발생했다.
kubectl get po -A
NAMESPACE NAME READY STATUS RESTARTS AGE
nginx-operator-system nginx-operator-controller-manager-86f64ff54c-5c8wr 1/2 ErrImagePull 0 17m
왜 ErrImagePull
이 발생했다. version up이 되어 이제는 container runtime을 dockershim이 아니라, containerd를 쓰기 때문에 발생하는 문제이다. 참고로 kubernetes v1.24부터는 container runtime기로 docker가 아니라 containerd를 사용한다.
장기적인 해결 방법은 해당 이미지를 생성하는 script를 docker
에서 crictl
로 바꾸는 것이 좋다. 이미 upgrade를 대비해서 script의 대부분을 그렇게 수정했지만, 일부의 경우 makefile
에 의존해서 crictl
로 바뀌지 않았나 보다.
단기적인 해결 방법으로는 docker에 있는 image를 tar
파일로 만들어 save한 다음에 ctr
로 load하면 된다.
docker save controller:latest > controller.tar
controller:latest
가 이미지 명이다.
이제 해당 local image 파일을 ctr
을 통해서 containerd에 넣으주면 된다.
넣어주기 전에 kubernetes에서 image를 다룰 때 사용하는 namespace를 알아내야한다. 이는 containerd에는 있고 docker에는 없는 부분인데, docker가 spec을 따르지 않고 독자적으로 구현했기 때문에 namespace를 적어주지 않아도 된 것이다. containerd는 spec를 따르기 때문에 namespace를 지정해주어야 image를 구분하여 사용할 수 있다.
ctr namespace ls
NAME LABELS
default
k8s.io
k8s.io
가 쓰이는 것을 확인할 수 있다.
이제 해당 namespace에 우리의 docker image file을 import시켜주면 된다.
ctr --namespace k8s.io image import ./controller.tar
다음으로 잘 들어갔는 지 확인해보도록 하자.
ctr images ls
REF TYPE DIGEST SIZE PLATFORMS LABELS
docker.io/library/controller:latest application/vnd.oci.image.manifest.v1+json sha256:fdf2424ac8c27cb87e7c5479ec0a26eb78b78e94d9297a191ea8a80676d57d0b 52.8 MiB linux/amd64
잘 들어간 것을 확인할 수 있다. 참고로 ctr
대신에 crictl
을 사용하는 것을 추천드린다.
마지막으로 nginx-operator-controller-manager가 잘 동작하는 지 확인해보도록 하자.
kubectl get po -n nginx-operator-system
NAME READY STATUS RESTARTS AGE
nginx-operator-controller-manager-86f64ff54c-w4fm7 2/2 Running 0 16m
성공적으로 동작하였다.