이쿠의 슬기로운 개발생활

함께 성장하기 위한 보안 개발자 EverNote 내용 공유

클라우드/Kubernetes

87. kubernetes docker에서 containerd로 마이그레이션

이쿠우우 2021. 10. 5. 20:40
반응형

 

kubernetes docker에서 containerd로 마이그레이션

 

목표

kubernetes container runtime tool을 docker에서 containerd로 변경하는 작업을 진행해봄

순서는 master node 부터 containerd로 migration을 진행하고

다음으로 worker node를 진행함.

 


 

Test 환경

on-premise 환경에서 진행.

 

[Master Node server]

OS = CentOS 7

리눅스 커널 버전 : Linux 3.10.0-1062.el7.x86_64

docker version : 20.10.8

docker api verison : 1.41

 

[Worker Node server]

OS = CentOS 7

리눅스 커널 버전 : Linux 3.10.0-1062.el7.x86_64

docker version : 20.10.8

docker api verison : 1.41

 

[kubernetes version]

1.22.2

 

 


 

 

1. 현재 kubernetes container runtime tool 확인

 

[명령어]

kubectl get nodes -o wide

 

[결과]

현재 container runtime tool은 docker임.

 

docker 구조에서 사용되는 containerd의 어떤 namespace에서 container가 실행 중인지 확인

 

[명령어]

namespace 항목 확인

ctr namespace list

 

[결과]

moby 확인

[명령어]

moby namespace 에서 실행 중인 container 목록 확인

ctr -n moby containers list

 

[결과]

moby namespace에서 runC를 통해 container들이 실행되고 있음을 확인함.

 

2. Master Node Cordon and Drain 

 

Master Node 부터 containerd 마이그레이션 작업을 시작함

마이그레이션 작업을 위해 master node 스케줄링을 정지하기위해 cordon 설정을 하고

실행되고 있던 pod들을 다른 node로 이동시키기 위해 drain 설정을 함.

 

[cordon 명령어]

kubectl cordon [master node name]

ex) kubectl cordon kube.master.node

 

[drain 명령어]

kubectl drain [master node name] --ignore-daemonsets

ex) kubectl drain kube.master.node --ignore-daemonsets

 

3. docker kubelet 종료

systemctl stop kubelet

systemctl stop docker

 

4. Docker 삭제 (선택 사항)

docker를 삭제는 선택사항임.

이유는 docker image build등 docker 자체 기능이 필요한 경우가 있어서

docker를 유지를 선택할 수 있음.

하지만 보다 확실한 작업을 위해서 삭제를 진행함.

일단 test 상황에서는 삭제함.

 

[명령어]

yum remove docker-ce docker-ce-cli

 

[결과]

해당 명령어로 docker를 삭제하면

실제 docker구조에 있는 docker-shim, dockerd, docker cli만 삭제되고

docker 구조에 포함되어있는 containerd는 삭제되지 않음.

어차피 docker 내부 구조를 뜯어보면 실제 container를 실행 시키는건 containerd임.

 

즉 기존 container runtime tool이 docker였다면

별도로 containerd를 설치하지 않고 

기존 docker에서 동작하던 containerd를 사용하면 됨.

 

실제로 docker 삭제 후 containerd 명령을 실행해보면 아직 정상적으로 실행됨.

하지만 docker가 삭제되었기 때문에 실행되고 있었던 container는 모두 제거됨.

 

5. containerd 설정 변경

이제 containerd가 kubernetes의 container runtime tool로 선정되야니

기존에 containerd가 container runtime tool로 선정되지 않도록 하던 설정을 제거 해야함.

/etc/containerd/config.toml 파일에서

disabled_plugins = ["cri"] 항목을 주석처리함.

 

만약 /etc/containerd/config.toml 파일이 없다면

아래 명령을 통해 config.toml 파일을 생성한 후 진행함.

containerd config default > /etc/containerd/config.toml

 

[명령어]

vi /etc/containerd/config.toml

 

[결과]

 

6. containerd 재기동

 

[명령어]

systemctl restart containerd

 

 

 

7. kubernetes container runtime tool 변경

 

containerd를 containerd runtime tool로 설정하기 위해

/var/lib/kubelet/kubeadm-flags.env 파일을 편집함.

default로 기존에 설정은 아래와 같음

KUBELET_KUBEADM_ARGS="--network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.5"

해당 설정을 아래과 같이 변경함

KUBELET_KUBEADM_ARGS="--network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.5 --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock"

마지막으로 현재 kubernetes는 cgroup driver를 cgroupfs가 아닌 systemd를 권장하고 있음

이에 따라 cgroup driver를 systemd로 설정하기 위해 아래 설정을 추가함.

KUBELET_KUBEADM_ARGS="--network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.5  --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock --cgroup-driver=systemd"

 

[결과]

 

8. kubelet 시작

 

[명령어]

systemctl start kubelet 

 

[결과]

정상 실행 확인

systemctl status kubelet

 

9. Master Node container runtime tool 확인

 

[명령어]

kubectl get nodes -o wide

정상적으로 containerd로 설정되어있는 것을 확인할 수 있음.

 

10. Master Node Cordon and Drain 해제

상위 결과를 보면 master node의 STATUS가 Ready 이지만 SchedulingDisabled 상태인 것을 확인 할 수 있음.

2번 단계에서 cordon 과 drain 설정을 했기 때문임

이제 container runtime tool을 성공적으로 변경했으니 해당 설정을 해제해야함.

 

[명령어]

kubectl uncordon [master node name]

ex) kubectl uncordon kube.master.node

[결과]

kubectl get nodes -o wide

확인해보면 정상으로 동작 중인 것을 확인할 수 있음.

 

11. containerd namespace확인

 

kubernetes 의 container runtime tool을 containerd로 설정한 후에

contaienrd의 namespace는 어떤 변화가 있는지 확인해봄.

 

[containerd namespace 목록 확인]

ctr namespace list

 

결과를 확인해보면 기존에는 moby 만 있었는데 추가로 k8s.io가 생성되어있는 것을 확인할 수 있음.

 

[moby와 k8s.io namespace에서 실행되는 container 목록 확인]

ctr -n moby containers list

ctr -n k8s.io containers list

 

결과를 확인해보면 

moby namespace는 현재 실행되고 있는 container가 없는 반면

k8s.io namespace에서 모든 kubernetes 관련 container가 실행되고 있는 것을 확인할 수 있음.

 

이를 통해 containerd가 docker에서 실행된다면 moby namespace에 container가 생성이 되고

kubernetes 를 통해 실행된다면 k8s.io namespace에 container가 생성되는 것을 알 수 있음.

 

작업 완료.

 

worker node도 위와 동일하게 작업하면 containerd로 migration 가능함.

 

 

참고

containerd namespace 이슈

[1.]

기존의 k8s가 docker를 사용하고 있었다면

containerd는 moby namespace를 사용하고 있었을 것임.

해당 환경에서 k8s를 1.23 version으로 update한다면

kubelet은 자동으로 host를 CRI에 해당하는 container runtime tool을 찾을 것이고

기존 host의 docker가 사용하던 containerd를 찾게 될 것임.

update 후 kubelet -> containerd의 k8s namespace를 확인하게 될탠데

host는 기존에 docker를 통해서 containerd가 실행되고 있었기 때문에 

기존에 동작하고 있던 container 정보들은 moby namespace에 있어서

k8s namespace에는 정보가 없을 것임.

 

[2.]

k8s namespace에 생성된 containerd의 container 정보는

docker ps 같은 명령으로 확인이 안됨.

즉 kubelet -> containerd 구조의 kubernetes 환경이라면

docker 명령으로 container를 확인할 수 없음.

 

[3.]

docker CLI를 통해서 로컬에 pull 받은 image라던가 local에서 build한 image는

moby namespace를 사용하는 containerd 에서 사용할 수 있지만, (docker)

k8s namespace를 사용하는 containerd 에서는 사용할 수 없음. (k8s)

 

 

 


제 글을 복사할 시 출처를 명시해주세요.
글에 오타, 오류가 있다면 댓글로 알려주세요! 바로 수정하겠습니다!


 

 

 

참고

 

https://github.com/containerd/containerd/blob/main/docs/namespaces.md

https://blog.mobyproject.org/containerd-namespaces-for-docker-kubernetes-and-beyond-d6c43f565084

https://kruyt.org/migrate-docker-containerd-kubernetes/

https://www.slideshare.net/JoHoon1/systemd-cgroup

 

반응형