데비안 9(Stretch)에서 10(Buster)으로 업그레이드 시 주의 사항

In 네트워크와 시스템 관리 by Choi Kyung-sik

데비안 9에서 데비안 10으로 업그레이드 하면서 내가 부딪쳤던 문제들을 정리해 본다.

eth0 네트워크 인터페이스 이름의 미지원

네트워크 인터페이스 이름으로 eth0 등을 사용하고 있다면 데비안 10으로 업그레이드하기 전에 새로운 방식의 이름으로 변경해 주어야 한다. 이에 대한 이해를 위해 네트워크 인터페이스에 이름을 부여하는 방법의 변화 과정을 보자. 원래의 간단한 체계(Original Simple Scheme)는 리눅스 커널이 단순히 eth0, eth1 등으로 이름을 붙인다. 이 체계의 문제는 부팅 후에 eth0과 eth1의 이름이 서로 바뀔 수 있다는 점이다. 이 문제를 해결하기 위한 여러 방법이 생겨났는데 그중의 하나가 영속적인 이름 체계(Persistent Names Scheme)이다. 이 체계는 Mac 주소를 사용하여 고정된 eth0 등의 이름을 부여한다. 이 체계도 완전하지 않고 특히 가상머신(virtualization)에서 문제가 있다. 그래서 나온 것이 펌웨어/BIOS에서 제공하는 정보를 사용하는 예측가능한 이름 체계(Predictable Name Scheme)이다.

데비안 5(Lenny) 즈음부터 영속적인 이름 체계를 사용해 왔다. 데비안 9(Stretch)에서 예측가능한 이름 체계가 들어 왔다. 데비안 9를 새로 설치하면 예측가능한 이름 체계를 사용한다. ‘ip a‘ 명령어를 실행하면 기존의 eth0 대신 하드웨어에 따라 달라지는 eno1, enp0s1, wlp1s0 등의 이름을 볼 수 있을 것이다. 새로 설치하는 것이 아니라 업그레이드로 데비안 9까지 왔다면 여전히 영속적인 이름 체계를 사용할 것이다. /etc/udev/rules.d/70-persistent-net.rules 파일의 존재로 확인할 수 있다.

데비안 10(Buster)에서 실제 제작자(upstream)가 영속적인 이름 체계를 공식적으로 지원하지 않는다. NetworkInterfaceNames – Debian Wiki 페이지에서는 영속적인 이름 체계를 데비안 10까지는 사용할 수 있고 데비안 11(Bullseye) 무렵에 완전히 없어질 것이라 나온다. 데비안 10 — 릴리스 노트 5장에서는 영속적인 이름 체계가 가능할지도 모르지만, 위험할 수 있어 새로운 이름으로 변경할 것을 권고하고 있다. 어쨌든 영속적인 이름 체계는 피하는 것이 나을 것이고 이에 대한 몇 가지 방법이 있다.

1. 원래의 간단한 체계 사용하기

네트워크 인터페이스를 하나만 가지고 있고 예측가능한 이름 체계를 싫어한다면 원래의 간단한 체계를 사용할 수 있는 다양한 방법이 있다. 그러나 이것이 지속 가능할지는 알 수 없다. 다음에서 커널의 옵션을 설정하는 방법을 설명한다.

1.1. /etc/default/grub 파일의 GRUB_CMDLINE_LINUX_DEFAULT의 값으로 "net.ifnames=0"을 추가한다.

...
GRUB_CMDLINE_LINUX_DEFAULT="quiet net.ifnames=0"
...

1.2. update-grub 명령어를 실행한다.

# update-grub

데비안 9를 새로 설치했다면 위까지 작업한 후 시스템을 재시작하면 eth0을 사용할 수 있을 것이다. 그러나 영속적인 이름 체계를 사용하여 /etc/udev/rules.d/70-persistent-net.rules 파일을 가지고 있다면 추가적인 작업이 필요하다.

1.3. /etc/udev/rules.d/70-persistent-net.rules 파일을 삭제하거나 이름을 바꾼다.

# cd /etc/udev/rules.d
# mv 70-persistent-net.rules 70-persistent-net.rules.old

1.4. 다음의 명령어로 initrd를 재생성한다.

# update-initramfs -u
...

1.5. 시스템을 재시작한다.

# systemctl reboot
2. ssh로 접속하여 예측가능한 이름 체계로 변경하기

ssh로 접속하여 원격 시스템의 네트워크 인터페이스 이름을 바꾸는 것은 신중하게 해야 한다. 오타 하나 때문에 ssh로 접속할 수 없는 불상사가 발생한다. 내가 사용하는 시스템이 모니터와 키보드 없이 구석에 자리하고 있는데 작업에서 실수가 발생한다면 상당히 귀찮을 것이다. 시스템이 모니터와 키보드를 가지고 있어 콘솔로 직접 접근할 수 있다면 작업은 좀 더 편할 것이다. 다음의 설명 중 @reboot cronjob 등은 콘솔을 가지고 있다면 생략할 수 있으므로 참작하여 보자.

2.1. 먼저 자신이 현재 사용하고 있는 네트워크 인터페이스 이름을 확인한다. 여기에는 다양한 방법들이 있다.

# ip a
# cat /etc/udev/rules.d/70-persistent-net.rules
# echo /sys/class/net/[ew]*

2.2. 영속적인 이름 체계에서 특별한 경우가 아니라면 eth0을 사용하고 있을 것이다. 다음의 명령어로 eth0을 사용하고 있는 설정 파일들을 찾는다.

# grep -r eth0 /etc
...

위의 결과로 나온 대부분은 주석으로 처리한 것이고 실제 변경이 필요한 파일은 /etc/network/interfaces일 것이다.

2.3. 다음의 명령어로 예측가능한 이름 체계에서 사용할 네트워크 인터페이스 이름을 찾는다.

# udevadm test-builtin net_id /sys/class/net/eth0 2> /dev/null
ID_NET_NAME_MAC=enxf46d04d4b9f6
ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC.
ID_NET_NAME_PATH=enp3s0

라인 4에서 나온 enp3s0이 내가 앞으로 사용해야 할 이름이다. 여러분이 가지고 있는 하드웨어에 따라 이름은 달라질 것이다. VirtualBox 가상머신의 데비안은 enp0s3 이름이 나온다.

2.4. 다음으로 진행하기 전에 무언가 잘못되었을 때를 위한 대비책을 세우자!

2.4.1. 다음의 스크립트는 아래에서 작업할 내용을 복구하는 스크립트이다.

#!/bin/bash

sleep 5m

ip a >> /root/network_interfaces.txt
mv -f /etc/network/interfaces /etc/network/interfaces.fail
cp -a -f /etc/network/interfaces.bak /etc/network/interfaces
cp -a -f /etc/udev/rules.d/70-persistent-net.rules.old /etc/udev/rules.d/70-persistent-net.rules
#cp -a -f /root/99-default.link /etc/systemd/network/99-default.link
update-initramfs -u
systemctl reboot

이 스크립트를 부팅 시 실행할 수 있게 Crontab에 등록할 것이다. 라인 3은 5분을 대기하기 위한 것이다. 시스템을 재시작하고 ssh로 접속을 할 수 있는지 확인한다. 접속에 성공하면 이 스크립트를 실행하는 프로세스를 찾아 죽여야 한다. ssh 접속에 실패한다면 5분 후 라인 5부터 복구 작업을 시작한다. 라인 5는 ‘ip -a’ 명령어로 네트워크 인터페이스의 이름을 확인하기 위한 것이다. 라인 6은 네트워크 이름 enp3s0으로 변경했던 /etc/network/interfaces 파일의 이름을 변경하여 보관해 둔다. 라인 7에서 기존의 eth0 이름을 가진 /etc/network/interfaces로 복구한다. 라인 8은 /etc/udev/rules.d/70-persistent-net.rules 파일을 복구한다. 라인 9는 가상머신에 설치한 데비안을 위한 것이다. 가상머신의 데비안을 사용한다면 라인 8을 주석 처리하고 라인 9의 주석을 제거한다. 라인 10에서 initrd를 재생성한다. 라인 11에서 시스템을 재시작한다. 시스템을 재시작하면 기존의 eth0으로 다시 접속할 수 있을 것이다. 접속하자마자 위의 실행 프로세스를 찾아 죽여야 한다.

2.4.2. 다음의 명령으로 위에서 작성한 스크립트에 실행 모드를 추가한다.

# chmod +x /root/revoke_net.sh

2.4.3. crontab -e 명령어를 사용하여 다음의 내용을 추가한 후 저장한다.

# crontab -e
...
@reboot /root/revoke_net.sh

crontab -l 명령어를 실행하여 제대로 등록하였는지 확인해 볼 수 있다.

2.5. /etc/network/interfaces 파일을 복구에 사용할 수 있도록 백업해 둔다.

# cp -a /etc/network/interfaces /etc/network/interfaces.bak

/etc/network/interfaces 파일에서 eth0을 2.3.에서 나온 enp3s0으로 변경한다.

...
auto enp3s0
iface enp3s0 inet static
...

2.6. /etc/udev/rules.d/70-persistent-net.rules 파일의 이름을 바꾼다. 가상머신의 데비안이라면 /etc/systemd/network/99-default.link 파일을 /root 디렉토리로 옮겨준다.

# cd /etc/udev/rules.d
# mv 70-persistent-net.rules 70-persistent-net.rules.old

2.7. 다음의 명령어로 initrd를 재생성한다.

# update-initramfs -u
...

2.8. 시스템을 재시작한다.

# systemctl reboot

2.9. ssh로 접속해 본다. 접속에 성공한다면 다음과 같이 revoke_net.sh 스크립트를 실행하는 프로세스를 찾아 죽인다.

# ps -ef | grep revoke
root       723   717  0 14:58 ?        00:00:00 /bin/sh -c /root/revoke_net.sh
root       724   723  0 14:58 ?        00:00:00 /bin/bash /root/revoke_net.sh
root      1849  1779  0 14:58 pts/0    00:00:00 grep revoke
# kill -9 724
# ps -ef | grep revoke
root      1917  1779  0 14:59 pts/0    00:00:00 grep revoke

2.10. ‘ip a‘ 명령어로 네트워크 인터페이스의 이름이 enp3s0으로 나오는지 확인해 본다.

2.11. 성공적으로 작업을 마쳤으면 정리에 들어간다. crontab -e 명령어를 사용하여 2.4.3.에서 추가한 ‘@reboot /root/revoke_net.sh‘를 삭제한 후 저장한다. crontab -l 명령어로 확인해 본다. /etc/network/interfaces.bak 파일을 삭제한다. /etc/udev/rules.d/70-persistent-net.rules.old 파일은 따로 보관하거나 삭제한다.

기존의 PostgreSQL 데이터베이스는 reindex 필요

데비안 10은 glibc 로케일 데이터를 업그레이드하기 때문에 PostgreSQL의 기존 데이터베이스에 대한 인덱스를 다시 만들어야 한다. 가능하다면 PostgreSQL의 데이터베이스를 사용하는 응용 프로그램을 업그레이드가 끝날 때까지 잠시 중단하는 것이 좋을 것이다. 업그레이드를 완료한 즉시 다음의 명령어를 실행한다.

# sudo -u postgres reindexdb --all
...
관련 글
참고 자료