요즘 프로젝트를 하고 있는데, 역시나 자바 시스템이 있다. Spring Boot3 을 사용하고 있고 자바 17을 쓰는등 나름대로 괜찮은 환경에서 개발이 이루어지고 있다. 그런데, 이것을 서버에서 배포를 하고 Spring Boot 를 실행해야 하는데, 어떻게 하나 봤더니 초보자 수준도 못 벗어나는 설정을 하고 있으니… 안타까운 마음에 어떻게 하는 것이 좋은 것인지 한번 적어봤다.
Spring boot, jar 실행 파일
Spring Boot3 를 컴파일 하면 jar 파일 나온다. 그리고 별다른 서버 없이도 바로 실행하고 접속이 가능해 진다. 한가지 재미있는 사실은 많은 사람들이 Spring boot3 에 실행 파일 jar 이 내장된 WAS 서버가 구동되면서 실행된다는 걸 모른다는 거다. 심지여 그것이 Tomcat 이라는 것도. 물론 어떤 프로그래밍 모델인지에 따라서 Tomcat 이 되기도 하고 Netty 되기도 하지만, 과연 Reactive Programming Model 로 짜는 사람이 몇이나 있나 싶다. 대부분 Spring MVC 이고 Servlet 이면 기본적으로 Tomcat 이 구동된다. 내장형 Tomcat
node_exporter 디렉토리가 보이고 그 안에 node_exporter 바이너파일이 있다. 이것을 적당한 곳으로 이동시키놓으면 끝난다.
어떻게 시작/중지 할건지…
여기서 이제 고민을 해야한다. 많은 사람들은 이것을 쉘 스크립트와 nohup 을 사용하는 사람들이 있다. 어느 시대에 살고 있는 사람들인지 의심이 될 정도인데, 이제는 init script 도 다 없어질 만큼 대부분의 배포판들이 systemd 로 다 전환이 완료된 상태다.
그러면 당연히 systemd 로 하면 되지! 하지만 여기서 문제가 된다.
현재 systemd 는 지속적으로 지금도 버전업이 되고 있다. 그러다보니 특정 버전을 기준으로 특정 기능이 지원이되고 안되고가 갈리게 된다.
systemd 버전 240 …. (대체 어떻게 버전 관리를.. 어떻게 기능을 많이 집어넣었으면 버전이 240 이여.. -_-;; ) 왠만하면 systemd 버전 240 이상을 사용할 것을 권한다. 그런데, 이게 말처럼,, 240버전을 써라~~ 한다고 되는게 아니다.
systemd 는 리눅스 시스템의 뼈대라고 보면된다. 핵심중에 핵심! 그러다보니 systemd 는 배포판과 함께 제공되고 묶여 있다. 240버전을 쓰고 싶다면 240버전을 가진 배포판을 써야 한다는 뜻이 된다.
Ubuntu 22.04: 249.11-0ubuntu3.12
RHEL 8.10: 239-82.el8_10.1
이런 저런 사유로 배포판을 선택하고 거기다 버전을 선택하게 된다. 내가 하고 있는 프로젝트에서는 CentOS, RHEL 7.9 가 대부분이고 RHEL 8 은 최신형으로 취급하는데.. systemd 만 놓고 보면 RHEL 8 도 그다지 마음에 들지 않는 부분이다.
개인적으로 RHEL 8 도 이제는 끝물이다. RHEL 9 의 버전이 이제는 벌써 9.3을 벗어나고 있기 때문에 이제는 RHEL 9 로가야 한다.
아무튼, 말이 길었는데, systemd 유닛으로 만들어 보자..
일단, node_exporter 에는 많은 옵션들이 있다. Prometheus exporter 들이 많은 옵션들을 제공한다. 이러한 옵션들은 별도의 파일로 작성하고 쉘 변수로 만들어 두고 systemd 유닛에서 읽어들이도록 하면 된다.
/etc/sysconfig/node_exporter 는 RedHat 기반에 적합하다. Ubuntu 면 /etc/sysconfig 디렉토리가 없기 때문에 Ubuntu 레이아웃에 맞는 곳에 넣으면 된다.
systemd 유닛 파일은 별거 없다.
systemd 유닛 파일
INI
1
2
3
4
5
6
7
8
9
10
11
[Unit]
Description=NodeExporter
Wants=network-online.target
After=network-online.target
[Service]
EnvironmentFile=/etc/sysconfig/node_exporter
ExecStart=/usr/local/bin/node_exporter$OPTIONS
[Install]
WantedBy=multi-user.target
딱 보면 별거 없다….. 하지만,,, 240 이하에서는 출력되는 로그들… 일명 Standard Out 들을 어떻게 처리할까? 그냥 이대로 둬도 되나? 결론은 되긴 한다. 이렇게 그대로 두면 node_exporter 가 뭔가를 출력하면 stdout, stderr 로 내보낸다. 그러면 systemd 는 이것을 /var/log/syslog 파일에 기록하게 된다.
하지만, systemd 로 변경되면서 나온 journal 에 기록을 하고 싶을지도 모른다. 이왕이면 그렇게하는게 좋기도 하다. 그래서 다음과 같이 [Service] 세션에 StandardOutput 옵션을 준다.
systemd log 관리
INI
1
StandardOutput=journal+console
콘솔에도 출력을…. 뭐.. 이건 옵션이다. 여기서 systemd 버전에 따라서 파일에 redirect 가 가능하기도 하고 불가능하기도 하다. StandardOutput 에 옵션이 inherit, null, tty, journal, kmsg, journal+console, kmsg+console, file:path, append:path, truncate:path 이렇게 되어 있다. 이게 다 가능한게 아니다. 버전에 따라서 가능하기도 하고 불가능하기도 하다.
Systemd 버전
새로운 배포판에 따라서 systemd 의 버전이 달라진다. 문제는 대부분 systemd 버전이 특정 시점까지만 업데이트가 된다. 시스템에 뼈대이다 보니 확 갈아 엎을 수 없는 것이여서 그럴거다.
이러다보니 특정 기능을 탐이 나는 때가 있는데, OS 를 다 갈아 엎어야하는 고충이 있다. 그래서 이왕이면 새로운 시스템을 구축할때에는 왠만하면 최신판을 쓰는게 좋다. Ubuntu 라면 24.04, RedHat 이면 9.0 을 사용하길 권한다.
최근들어 arm64 아키텍쳐가 인기가 많아졌다. 애플의 실리콘 반도체라고 불리는것도 arm64 기반이며 Windows 11 도 arm64 에서도 작동된다. 리눅스는 오래전부터 다양한 아키텍쳐로 포팅이되었기 때문에 arm64 를 위한 배포판도 다양하게 존재한다. 문제는 arm64 아키텍쳐를 경험하기 위해서 arm64 하드웨어가 있어야 했지만, 이제는 x86_64 기반의 가상머신을 이용하면 arm64 아키텍쳐를 게스트로 운영할 수 있다.
이 문서는 x86_64 기반 가상머신에서 arm64 아키텍쳐기반의 게스트를 실행하는 방법에 대해서 기술한 것이다.
x86_64 가상머신
x86_64 아키텍쳐 기반의 가상머신으로 리눅스 운영체제를 기반으로 KVM 을 활용하고 있다. GUI 툴로서 virt-manager, CLI 로는 virsh 를 활용해서 간단하게 게스트를 생성하고 운영하고 있다. arm64 아키텍쳐 게스트를 운영하기 위한 호스트로서 x86_64 아키텍쳐 기반 가상머신 스펙은 다음과 같다.
OS: Ubuntu 22.04
Kernel: 5.15.0-207.156.6.el9uek.x86_64
CPU: AMD Ryzen 7 2700X Eight-Core Processor
libvirt vs QEMU
arm64 아키텍쳐기반 게스트를 운영하기 위해서는 QEMU 를 사용해야 한다. QEMU 는 가상머신 에뮬레이터라고 생각하면 된다. 문제는 QEMU 는 CLI 기반만 제공한다.
반면에 libvirt 는 KVM/QEMU 등을 지원하는 일종의 핸들러 라이브러리고 생각하면 된다. libvirt 를 이용하면 xml 기반으로 게스트 관련 가상머신 스펙을 정의할 수 있으며 virt-manager 와같은 GUI 툴도 활용할 수 있다.
QEMU 에뮬레이터라고 했기 때문에 arm64 를 위한 QEMU 에뮬레이터를 설치하면 arm64 기반 게스트 운영체제를 운영할 수 있다. 다음과 같이 arm64 를 위한 QEMU 에뮬레이터를 설치해준다.
qemu-system-arm 설치
ZSH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$sudo apt install qemu-system-arm
Reading packagelists...Done
Building dependency tree...Done
Reading state information...Done
The following packages were automatically installed andare no longer required:
처음부터 Arm64 기반 OS 를 게스트로 설치하면서 생성할 수도 있다. 하지만 이미 있는 Arm64 기반 OS를 가져다 쓸 수도 있다. 여기서는 Amazon Linux 를 가져다 사용해 보도록 하겠다.
Amazon Linux 는 Amazon 이 AWS 서비스에서 사용할 목적으로 만든 배포판이다. 현재 Amazon Linux2 와 Amazon Linux3 등 다양한 버전을 제공한다. 최근 프로젝트가 Amazon Linux2 를 많이 사용하고 있어서 Amazon Linux2 Arm64 기반 OS 이미지를 게스트로 한번 실행 보도록 하겠다.
Amazon Linux2 는 기본적으로 ec2-user 라는 시스템 계정이 있으며, 로그인을 위해 패스워드 방식이 아닌 SSH 인증키 방식을 사용한다. 하지만 배포되는 이미지에 맞는 인증키가 따로 없기 때문에 부팅과정에서 이 부분을 변경하도록 해야하는데, 이를 위해서 seed.iso 를 만들어 게스트 OS 에 CD-ROM 에 넣어 부팅해준다. 이 부분에 대한 설명은 다음의 페이지에서 찾을 수 있다.
민트 리눅스 21.03 에서 KVM 가상환경을 구성해 본다. 구성에 핵심은 KVM 의 네트워크 설정이다. 앞서 설정한 OpenvSwitch 를 이용하도록 설정 해야 한다.
네트워크 환경
KVM 가상화를 위해서는 네트워크 환경을 먼저 고려해야 한다. 필자의 경우에는 공유기를 이용하고 있다. 외부 광랜으로 들어온 라인을 모뎀에서 받아서 이더넷로 변환해준다. 여기서 랜선으로 공유기에 연결하고 각 컴퓨터에 연결해서 쓴다.
공유기는 다들 아는 IpTime 인데, IpTime 은 새로운 장비가 접속되면 자동으로 사설IP 를 할당해 준다. 이것을 외부로 내보낼때는 NAT 기능을 이용해서 하나의 인터넷 라인으로 공유기 안쪽에 많은 장비를 사용할 수 있게된다.
KVM 가상화를 하게되면 브릿지 네트워크가 생성된다. 이 브릿지 네트워크는 NAT 모드로 작동된다. 172.x.x.x 대역으로 게스트에게 자동으로 IP 를 할당해 준다. 마치 IpTime 공유기와 같은데, 문제는 이렇게 되면 다른 컴퓨터에서 게스트에 접속할 수가 없게 된다. NAT 는 단반향으로 게시트에서 바깥으로 접속은 할 수 있지만 바깥에서 게스트로 접속은 불가능하다. 가능한 방법은 Port 포워딩인데, 포트마다 설정을 해줘야 하는 번거로움이 있다.
KVM 네트워크 설정을 NAT 가 아닌 브릿지(Bridge) 모드로 설정하고 드라이버를 OpenvSwitch 로 설정하면 호스트 컴퓨터에 브릿지 네트워크인 OpenvSwitch 를 통해서 IpTime 에서 사설 IP를 받게 된다. IpTime 내에 네트워크 모두 접속이 가능해 진다.
만약 이렇게 자동으로 디스크가 인식되지 않는다면 SCSI 디스크 ReScan 기능을 이용해야 한다. Hot Swap 은 SCSI 의 host 번호를 이용해 작동됨으로 SCSI host 번호를 알아야 한다. 하지만 리눅스에서는 /dev/sdc 형식인데 SCSI host 번호와는 다른데, 다음과 같이 알아내야 한다.
Rocky Linux 9 는 RHEL 9 (RedHat Enterprise Linux 9) 의 크론 버전이다. RHEL9는 상용인 반면에 Rokcy Linux 는 무료다.
RHEL9나 Rokcy Linux 9 로 넘어오면서 변화한 것중에 하나가 ifcfg-eth0 파일이다. 이 파일은 /etc/sysconfig/network-scripts 디렉토리에 존재했었고 eth0 네트워크 장치에 대한 네트워크 설정 정보가 저장되었었다. 부팅을하면서 Network-Manager 데몬이 이 파일을 읽어 실행했었다. 하지만 RHEL9과 Rokcy Linux 에서는 이 파일을 더 이상 사용하지 않고 nmcli 명령어를 통해서 세팅을 하도록 변경 되었다.
이러한 변화는 Open vSwitch 세팅에서도 영향을 준다. 우분투와 다르게 RHEL9, Rocky Linux 9 에서는 nmcli 명령어를 통해서 Open vSwitch 를 설정하게 된다.
주의
절대로 원격에서 작업을 해서는 안된다. 외부와 연결하는 네트워크 작업이기 때문에 원격에서 작업을 했을 경우 다시 접속이 안될 수 있다.
Open vSwitch 설치
Rocky Linux 9 에서 Open vSwitch 설치는 패키지로 제공한다. 다음과 같이 설치가 가능하다.
Open vSwitch 설치.
ZSH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
]# dnf install centos-release-nfv-openvswitch
]# dnf search openvswitch
Last metadata expiration check:0:34:49ago on Sun Jul1615:48:152023.
inet6 fe80::47b0:302c:15bb:ad30/64scope link noprefixroute
valid_lft forever preferred_lft forever
RHEL9, Rocky Linux 9 에서 어떻게 Open vSwitch 를 설정하는지 알아 봤다.
WOL 설정
Wake On Lan 은 Ethernet 선과 연결된 상태에서 컴퓨터에 전원을 켜지는 기능을 말한다. 이 기능을 사용하기 위해서는 먼저 메인보드에서 지원을 해줘야 한다. 한가지 더 주의해야 하는 것은 메인보드마다 설정 방법이 다 다르다.
이 작업을 했던 컴퓨터는 ASRock B550M Pro4 였는데, BIOS 설정에 Boot 메뉴에 Power On Lan 설정이 있어서 Enable 을 해줬지만 되지 않았다. Advanced 설정에서 ACPI 메뉴가 존재하는데 여기서 PCIE 를 이용한 Power On Lan 설정이 존재하는데 이것을 Enable 을 해줘야 한다.(정확한 메뉴는 기억이 나지 않는다. 메뉴얼을 찾아보면 쉽게 찾을 수 있다.)
이렇게 했는데도 WOL 기능이 되지 않는다면 이것은 리눅스의 설정을 해줘야 함을 의미 한다. 앞서 Open vSwitch 설정을 해준 관계로 외부 접속을 위한 디바이스의 연결 이름이 일반적으로 다르다.
]# nmcli conn show "ovs-if-enp4s0" | grep wake-on-lan
802-3-ethernet.wake-on-lan:magic
802-3-ethernet.wake-on-lan-password:--
이렇게 한 다음에 가능하면 두번 재부팅하라고 하지만.. 글쎄… 한번만 해줘도 잘됐었다. 여러번 테스트를 해봤는데 문제없이 잘되었다.
한가지 덧붙이자면 WOL 기능을 사용하기 위해서는 절대로 전원 플러그를 뽑아서는 안된다. 멀티탭에 각 구에 전원이 On/Off 스위치가 있을 경우에 전원을 차단해서도 안된다. 전원 플러그를 뽑았다가 다시 꼽아도 안된다. 반드시 전원 플러그를 꼽고 한번은 리눅스로 부팅을 해주고 난 후에 리눅스를 Shutdown 해주고 그리고 전원 플러그는 그대로 연결이 되어 있어야 한다.
WOL 기능은 공유기에 내장되어 있는 경우가 많다. 공유기를 이용하면 원격에서도 컴퓨터를 켤수 있고 공유기의 포워드 기능을 이용하면 켜진 컴퓨터로 외부에서 접속이 가능하다. 프로젝트 할때마다 자주 써먹는 유용한 방법이다.
KVM 가상화를 운영하고 있는데, 운영중인 VM 하나가 용량이 부족해지는 상황이 발생했다. KVM 가상화 VM 의 용량은 결국 이미지 파일 한개임으로 이 이미지 파일의 용량을 늘려주면 VM 의 용량이 사실상 늘어나는 것으로 생각했다.
하지만 현시점(2023) 에서 검색을 해보니 다양한 방법들이 존재했다. 그 중에는 VM 이미지를 로컬에 마운트해서 늘려주는 방법도 존재했지만 너무나 복잡해 보였다. 좀 더 쉬운 방법이 없을까 해서 검색한 결과 가장 쉬워보이는 것을 발견했고 이 방법으로 손쉽게 VM 용량을 늘리는데 성공했다.
VM 상태
용량을 늘리려는 VM 의 상태는 다음과 같다.
VM 용량 상태
ZSH
1
2
3
4
5
6
7
8
# df -h
Filesystem Size Used Avail Use%Mounted on
tmpfs393M8.0M385M3%/run
/dev/vda148G44G794M99%/
tmpfs2.0G52K2.0G1%/dev/shm
tmpfs5.0M05.0M0%/run/lock
tmpfs2.0G02.0G0%/run/qemu
tmpfs393M0393M0%/run/user/1000
/dev/vda1 으로 파티션 하나로 보이지만 사실 SWAP 파티션도 존재한다. 이 SWAP 파티션의 /dev/vda2 디바이스이며 약 2G 용량을 차지한다.
VM 이미지 경로
VM 을 운영하는 Host 서버에서 VM 의 이미지가 어디에 있는지를 다음과 같이 살펴볼 수 있다.
VM 디스크 이미지 정
ZSH
1
2
3
4
5
]# virsh domblklist --domain Ubuntu20.04
대상소스
----------------------------------
vda/opt/kvm/ubuntu20.04.img
sda-
VM 이미지 정보
VM 이미지의 정보를 아는 것은 매우 중요하다. VM 이미지의 타입이 존재하는데 raw, qemu 타입이다. 어떤 타입인지에 따라서 VM 이미지 용량을 늘리는 방법이 달라진다.
이 작업은 매우 중요하다. truncate 명령어를 이용하는 것인데, -r 옵션으로 용량 증설을 위한 이미지를 만들었다. 그리고 그 이미지에 용량 증설을 설정한다. 여기서는 10G 용량을 늘린다
루트(/) 피티션 /dev/sda1 크기 변경
VM 이미지 내의 파티션 정보는 /dev/sda1 으로 보인다. 여기서 주의해야 할 것은 VM 이 가동된 후에 이미지 정보의 디바이스 이름은 /dev/vda1 으로 다르다. virt-df 혹은 virt-filesystems 나온 내용을 기반으로 디바스 이름을 정해야 한다.
[941.1]Expanding/dev/sda1 using the‘resize2fs’method
virt-resize:Resize operation completed with no errors.Before deleting
the old disk,carefully check that the resized disk boots andworks
correctly.
변경 요약을 보면 /dev/sda1 의 용량이 증설될 것인데, 이 파티션의 파일시스템이 ext4 임으로 resize2fs 방법을 이용해서 크기가 확장될 것임을 알려주고 있다.
진행 상태를 보면 Copying /dev/sda1 으로 나오고 실행 명령어에서 변경전 이미지와 truncate 명령어로 새롭게 생성한 이미지를 인자로 줬는데, 아마도 변경전 이미지를 truncate 명령어로 새롭게 생성한 이미지에 순차적인 복사를 하는 것으로 보인다.
이미지 용량에 따라서 작업 시간는 차이를 보일 것이다.
새로운 이미지로 VM 시작한 후 파티션 확인
/mnt7/ubuntu20.04-new.img 이미지로 VM 을 부팅한다. 그리고 난 후 다음과 같이 파티션 용량이 늘었는지 체크한다.
디스크 확인
ZSH
1
2
3
4
5
6
# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sr011:011024M0rom
vda252:0060G0disk
├─vda1252:1058.1G0part/
└─vda2252:201.8G0part[SWAP]
용량이 10G 늘었다.
파일시스템 용량을 봐 본다.
파일 시스템 용량 확인
ZSH
1
2
3
4
5
6
7
8
# df -h
Filesystem Size Used Avail Use%Mounted on
tmpfs393M6.8M386M2%/run
/dev/vda157G44G11G82%/
tmpfs2.0G52K2.0G1%/dev/shm
tmpfs5.0M05.0M0%/run/lock
tmpfs2.0G02.0G0%/run/qemu
tmpfs393M0393M0%/run/user/1000
앞에서 변경 요약을 보면 파일시스템이 뭔지를 파악하고 거기에 맞게 파티션 Resize 작업도 해주는 것으로 보인다. ext4 의 경우 resize2fs, XFS 의 경우에는 xfs_growfs 을 사용하는데 이런 작업은 파티션의 크기를 변경하는 것으로 VM 이미지 용량 증설과 함께 해준다.