Incus 는 LXD 의 포크 (fork) 로, LXD 와 유사한 기능을 제공합니다. Incus 는 LXD 와 동일한 기능을 제공하지만, Incus 프로젝트의 유지보수자 및 사용자 커뮤니티에 의해 별도로 관리됩니다. Incus 를 설치하고 사용하는 방법은 다음과 같습니다.
* 아래 내용은 공식 Document 를 참고하여 재작성 하였습니다.
https://linuxcontainers.org/incus/docs/main/
1. Incus 설치
Incus 는 apt 패키지를 통해 쉽게 설치할 수 있습니다.
# apt -y update
# apt -y upgrade
# apt -y install incus incus-tools incus-migrate
컨테이너가 아닌 VM 을 생성할 경우 아래 패키지가 추가로 필요합니다.
# apt -y install qemu-kvm libvirt-clients libvirt-daemon-system bridge-utils virt-manager
2. Incus 초기화
Incus 설치 후, incus admin init 명령을 사용하여 초기화를 진행합니다. 초기화 과정에서 저장소, 네트워크 및 기타 환경 설정을 구성합니다.
테스트 당시 모든 항목을 기본값 (그냥 엔터) 으로 사용하였습니다.
# incus admin init
Would you like to use clustering? (yes/no) [default=no]:
Do you want to configure a new storage pool? (yes/no) [default=yes]:
Name of the new storage pool [default=default]:
Name of the storage backend to use (lvm, lvmcluster, btrfs, dir) [default=btrfs]:
Create a new BTRFS pool? (yes/no) [default=yes]:
Would you like to use an existing empty block device (e.g. a disk or partition)? (yes/no) [default=no]:
Size in GiB of the new loop device (1GiB minimum) [default=5GiB]:
Would you like to create a new local network bridge? (yes/no) [default=yes]:
What should the new bridge be called? [default=incusbr0]:
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
Would you like the server to be available over the network? (yes/no) [default=no]:
Would you like stale cached images to be updated automatically? (yes/no) [default=yes]:
Would you like a YAML "init" preseed to be printed? (yes/no) [default=no]:
3. 스토리지 생성
이미지나 컨테이너를 저장할 스토리지가 있어야 하는데, 하드를 추가하여 특정파티션을 스토리지화 하거나 외부 장치를 이용하는 방법이 있습니다.
여기에서는 ZFS 파일시스템 형식의 파일을 만들고 LXC 를 생성해 보도록 하겠습니다.
ZFS 형식으로 생성하기위해 관련 패키지를 설치합니다.
# apt -y install zfsutils-linux
2GiB 크기의 빈 파일을 생성합니다. 이 파일은 ZFS 풀을 만들기 위한 디스크 이미지 파일로 사용됩니다.
# truncate -s 2GiB /var/lib/incus/disks/pool1.img
앞서 만든 디스크 이미지를 기반으로 pool1 이라는 이름의 ZFS 풀을 생성합니다.
# zpool create pool1 /var/lib/incus/disks/pool1.img
Incus 에서 pool1 이라는 이름으로 ZFS 스토리지 풀을 생성하고, ZFS 풀 pool1 을 사용하도록 연결합니다.
# incus storage create pool1 zfs source=pool1
(관련 명령)
스토리지 풀 리스트 보기
# incus storage list
+---------+--------+----------------------------------+-------------+---------+---------+
| NAME | DRIVER | SOURCE | DESCRIPTION | USED BY | STATE |
+---------+--------+----------------------------------+-------------+---------+---------+
| default | btrfs | /var/lib/incus/disks/default.img | | 1 | CREATED |
+---------+--------+----------------------------------+-------------+---------+---------+
| pool1 | zfs | pool1 | | 0 | CREATED |
+---------+--------+----------------------------------+-------------+---------+---------+
스토리지 풀 상세 보기
# incus storage show pool1
config:
source: pool1
volatile.initial_source: pool1
zfs.pool_name: pool1
description: ""
name: pool1
driver: zfs
used_by: []
status: Created
locations:
- none
스토리지 풀 리사이즈
# incus storage set pool1 size=3GiB
* 스토리지 풀에 대한 고찰
스토리지 풀 한개에 여러개의 LXC 디스크를 생성하거나, ISO OS 이미지를 저장할 수도 있습니다.
스토리지 풀 한개에 여러개의 LXC 를 사용하는 중, 용량을 변경하는 방법을 확인하지 못하였기 때문에 이부분은 추가로 작성하기로 하고, 한개의 풀에 한개의 LXC 를 생성하는 방법만 기술하겠습니다.
* 참고1 : Btrfs 스토리지 풀 및 VM 생성
# incus storage create pool1 btrfs size=5GB
# incus image list images: | grep -i Ubuntu | grep VIRTUAL-MACHINE // 설치 가능한 VM OS 확인
# incus launch images:ubuntu/noble/desktop sysdocu1 --config limits.cpu=2 --config limits.memory=2048MiB -s pool1 --vm
* 참고2 : Cluster 가 구성된 상태에서 풀 생성하기
모든 클러스터 멤버에 걸쳐 새 스토리지 풀을 정의하고 구성합니다.
Cluster 멤버가 node1, node2 이렇게 있을때 두군데 볼륨을 생성해야 합니다.
# incus storage create --target node1 newpool1 zfs
# incus storage create --target node2 newpool1 zfs
# incus storage create newpool1 zfs
참고로 네트워크를 먼저 만들고 VM 또는 LXC 생성시 네트워크 옵션을 사용하는 것이, 경고나 추가 안내글 없이 생성되어 좋습니다.
4. LXC 생성
다음은 Incus 를 사용하여 컨테이너를 관리하는 예제입니다.
1) 컨테이너 이미지 가져오기
Incus 이미지를 목록에서 확인합니다.
(전체 이미지 출력)
# incus image list images:
(같은 버전은 최신본만 출력)
# incus image list images: |grep arm64 |grep --color=never '^| [a-z].*'
이미지를 아래와 같이 다운로드 할 수 있습니다.
# incus image copy images:ubuntu/24.04 local: --alias ubuntu-24.04
다운로드 받은 이미지를 확인합니다.
# incus image list
+--------------+--------------+--------+-------------------------------------+--------------+-----------+-----------+----------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE | TYPE | SIZE | UPLOAD DATE |
+--------------+--------------+--------+-------------------------------------+--------------+-----------+-----------+----------------------+
| ubuntu-24.04 | e11d95790cc9 | no | Ubuntu noble amd64 (20240731_07:42) | x86_64 | CONTAINER | 123.68MiB | 2024/08/02 15:06 KST |
+--------------+--------------+--------+-------------------------------------+--------------+-----------+-----------+----------------------+
이미지는 호스트에 한 번만 받아놓으면 컨테이너 생성시마다 활용할 수 있습니다.
2-1) 컨테이너 생성 및 시작 : 스토리지풀 한개에 LXC 한개 생성하는 방법
가져온 이미지를 사용하여 pool1 스토리지 풀에 컨테이너를 생성하고 시작합니다.
생성 노드 지정, VM 타입, 디스크 용량 지정 등 다양한 타입으로 생성 가능하므로 공식 URL을 참고해 주세요.
(https://linuxcontainers.org/incus/docs/main/howto/instances_create/)
# incus launch ubuntu-24.04 sysdocu-lxc --config limits.cpu=1 --config limits.memory=512MiB -s pool1
* 참고로 네트워크 브릿지를 먼저 생성했다면 --network vlan10 과 같이 옵션을 사용하여 네트워크 그룹에 할당 할 수 있습니다.
실행 중인 컨테이너의 상태를 확인합니다.
# incus list
+-----------------+---------+----------------------+-----------------------------------------------+-----------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+-----------------+---------+----------------------+-----------------------------------------------+-----------+-----------+
| sysdocu-lxc | RUNNING | 10.53.166.120 (eth0) | fd42:9307:e6bd:b0e9:216:3eff:fe05:8991 (eth0) | CONTAINER | 0 |
+-----------------+---------+----------------------+-----------------------------------------------+-----------+-----------+
[ 잠깐 : 서비스 제공시 incus 흔적 지우기 ] ===========
(컨테어너 내에서)
mv /etc/sudoers.d/90-incus /etc/sudoers.d/90-user
umount /dev/incus
umount /dev/.incus-mounts
rmdir /dev/incus
rmdir /dev/.incus-mounts
==========================================
실행 중인 컨테이너에 명령을 내리거나 쉘 로그인이 가능합니다.
# incus start sysdocu-lxc // LXC 시작
# incus stop sysdocu-lxc // LXC 중지
# incus exec sysdocu-lxc -- bash // 쉘 로그인
# incus exec sysdocu-lxc -- nproc // CPU 개수 확인
# incus exec sysdocu-lxc -- free -m // 메모리 사용량 확인
# incus exec sysdocu-lxc -- df -h // 파티션 용량 확인
Filesystem Size Used Avail Use% Mounted on
pool1/containers/sysdocu-lxc 1.8G 308M 1.5G 18% /
none 492K 4.0K 488K 1% /dev
tmpfs 100K 0 100K 0% /dev/incus
tmpfs 100K 0 100K 0% /dev/.incus-mounts
tmpfs 2.0G 0 2.0G 0% /dev/shm
tmpfs 784M 112K 784M 1% /run
tmpfs 5.0M 0 5.0M 0% /run/lock
2-2) 컨테이너 생성 및 시작 : 스토리지풀 한개에 LXC 여러개 생성하는 방법
아래는 default 풀에 2G 크기의 LXC 를 생성하는 예제입니다.
# mount /var/lib/incus/disks/default.img /mnt
# btrfs filesystem resize 2G /mnt
# umount /mnt
# incus launch ubuntu-24.04 sysdocu-default --config limits.cpu=1 --config limits.memory=512MiB -s default
※ 참고
파일시스템 형식에 따라 출력되는 장치명이 아래와 같습니다.
(Zfs 일때 : containers 라고 출력)
# incus exec sysdocu-lxc -- df -h | grep /$
pool1/containers/sysdocu-lxc 9.2G 3.9G 5.4G 42% /
(Btrfs 일때 : 컨테이너 용량 표기 / container 글씨 없음 / 하지만 컨테이너 추가 생성시 loop1, ... 이름으로 생성 / df -Th 명령시 btrfs 파티션으로 표기)
# incus exec sysdocu-default -- df -h | grep /$
/dev/loop0 3.0G 550M 2.0G 22% /
(dir 일때 : 호스트 전체 용량이 출력)
# incus exec sysdocu4 -- df -h | grep /$
/dev/vda1 24G 11G 13G 47% /
(LVM 일때 : containers_name 형식으로 출력)
# incus exec sysdocu5 -- df -h | grep /$
/dev/pool5/containers_sysdocu5 9.8G 543M 8.8G 6% /
3) 컨테이너 관리 명령
컨테이너가 실행되는 동안 필요한 리소스 구성을 업데이트할 수도 있습니다. (디스크 제외)
# incus config set sysdocu-lxc limits.memory=1GiB
구성이 적용되었는지 확인합니다.
# incus config show sysdocu-lxc
컨테이너를 중지, 시작, 재부팅 및 삭제할 수 있습니다.
# incus stop sysdocu-lxc
# incus start sysdocu-lxc
# incus restart sysdocu-lxc
# incus delete sysdocu-lxc --force // 실행중이라는 메세지가 출력될때는 중지 후 삭제하거나 --force 옵션 사용
컨테이너 내 파일을 복사해 오기
# incus file pull sysdocu-lxc/etc/hosts .
컨테이너로 파일을 복사해 넣기
# incus file push hosts sysdocu-lxc/etc/
5. 디스크 확장 및 볼륨 추가
1) 디스크 확장
pool1 스토리지 풀을 사용하는 모든 컨테이너를 중지합니다.
# incus stop sysdocu-lxc
스토리지 풀 이미지 파일 크기를 확장합니다.
기존 2G 였으므로 1G 를 추가해 3G 로 변경해 보겠습니다.
(+ 없이 그냥 3G 로 해도 됩니다)
# truncate -s +1G /var/lib/incus/disks/pool1.img
ZFS 풀에서 크기를 반영합니다.
# zpool set autoexpand=on pool1
# zpool online -e pool1 /var/lib/incus/disks/pool1.img
컨테이너를 시작합니다.
# incus start sysdocu-lxc
변경된 용량을 확인합니다.
# incus exec sysdocu-lxc -- df -h
Filesystem Size Used Avail Use% Mounted on
pool1/containers/sysdocu-lxc 2.8G 254M 2.6G 10% /
none 492K 4.0K 488K 1% /dev
tmpfs 100K 0 100K 0% /dev/incus
tmpfs 100K 0 100K 0% /dev/.incus-mounts
tmpfs 2.0G 0 2.0G 0% /dev/shm
tmpfs 784M 116K 784M 1% /run
tmpfs 5.0M 0 5.0M 0% /run/lock
2) 볼륨 추가하기
순서는 풀을 생성합니다.
# incus storage create my-pool zfs size=1GB
그 안에 볼륨을 생성합니다.
# incus storage volume create my-pool my-volume
컨테이너에 연결합니다.
컨테이너내 디렉토리는 생성해 두지 않아도 됩니다.
# incus storage volume attach my-pool my-volume sysdocu-lxc /data
마운트된 것을 확인합니다.
# incus exec sysdocu-lxc -- df -h
Filesystem Size Used Avail Use% Mounted on
pool1/containers/sysdocu-lxc 3.8G 255M 3.6G 7% /
none 492K 4.0K 488K 1% /dev
tmpfs 100K 0 100K 0% /dev/incus
tmpfs 100K 0 100K 0% /dev/.incus-mounts
tmpfs 2.0G 0 2.0G 0% /dev/shm
tmpfs 784M 112K 784M 1% /run
tmpfs 5.0M 0 5.0M 0% /run/lock
my-pool/custom/default_my-volume 768M 128K 768M 1% /data
연결 해제 방법
# incus storage volume detach my-pool my-volume sysdocu-lxc
6. 네트워크 설정
아래는 vlan 설정을 통하여 각각의 그룹 내 컨테이너 끼리만 통신이 가능하게 하는 예제입니다.
- vlan10 브릿지 사용 컨테이너 : sysdocu1, sysdocu2
- vlan20 브릿지 사용 컨테이너 : sysdocu3, sysdocu4
1) 네트워크 브리지 생성
기본 네트워크 브리지를 생성합니다.
# incus network create vlan10
# incus network create vlan20
컨테이너에 네트워크 브리지를 연결합니다.
# incus network attach vlan10 sysdocu1 eth0
# incus network attach vlan10 sysdocu2 eth0
# incus network attach vlan20 sysdocu3 eth0
# incus network attach vlan20 sysdocu4 eth0
연결 전 네트워크 IP
# incus list
+----------+---------+-----------------------+-----------------------------------------------+-----------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+----------+---------+-----------------------+-----------------------------------------------+-----------+-----------+
| sysdocu1 | RUNNING | 10.219.126.53 (eth0) | fd42:c68c:ea28:a8b7:216:3eff:fecc:5c4a (eth0) | CONTAINER | 0 |
+----------+---------+-----------------------+-----------------------------------------------+-----------+-----------+
| sysdocu2 | RUNNING | 10.219.126.246 (eth0) | fd42:c68c:ea28:a8b7:216:3eff:fea2:5e9e (eth0) | CONTAINER | 0 |
+----------+---------+-----------------------+-----------------------------------------------+-----------+-----------+
| sysdocu3 | RUNNING | 10.219.126.159 (eth0) | fd42:c68c:ea28:a8b7:216:3eff:febc:9ea4 (eth0) | CONTAINER | 0 |
+----------+---------+-----------------------+-----------------------------------------------+-----------+-----------+
| sysdocu4 | RUNNING | 10.219.126.243 (eth0) | fd42:c68c:ea28:a8b7:216:3eff:fe3f:6571 (eth0) | CONTAINER | 0 |
+----------+---------+-----------------------+-----------------------------------------------+-----------+-----------+
연결 후 네트워크 IP
그룹별 새로운 사설 IP 로 셋팅 된 것이 확인됩니다.
# incus list
+----------+---------+-----------------------+-----------------------------------------------+-----------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+----------+---------+-----------------------+-----------------------------------------------+-----------+-----------+
| sysdocu1 | RUNNING | 10.143.217.53 (eth0) | fd42:bf49:3da2:3054:216:3eff:fecc:5c4a (eth0) | CONTAINER | 0 |
+----------+---------+-----------------------+-----------------------------------------------+-----------+-----------+
| sysdocu2 | RUNNING | 10.143.217.246 (eth0) | fd42:bf49:3da2:3054:216:3eff:fea2:5e9e (eth0) | CONTAINER | 0 |
+----------+---------+-----------------------+-----------------------------------------------+-----------+-----------+
| sysdocu3 | RUNNING | 10.107.13.159 (eth0) | fd42:fa98:efb:f314:216:3eff:febc:9ea4 (eth0) | CONTAINER | 0 |
+----------+---------+-----------------------+-----------------------------------------------+-----------+-----------+
| sysdocu4 | RUNNING | 10.107.13.243 (eth0) | fd42:fa98:efb:f314:216:3eff:fe3f:6571 (eth0) | CONTAINER | 0 |
+----------+---------+-----------------------+-----------------------------------------------+-----------+-----------+
2) 브릿지 간 통신 차단
이제 iptables 를 이용해야 합니다.
forward 기본 정책을 DROP 으로 설정합니다.
# iptables -P FORWARD DROP
vlan10 내 통신을 허용합니다.
# iptables -A FORWARD -i vlan10 -o vlan10 -j ACCEPT
# iptables -A FORWARD -i vlan20 -o vlan20 -j ACCEPT
추가되는 브릿지마다 한 줄씩 추가해주면 됩니다.
3) 브릿지 외부 통신 허용 (필요한 경우에 사용. 미사용시 Private 구성 가능)
테스트 환경에서는 ens3 가 외부 네트워크와 연결된 인터페이스입니다.
따라서 NAT 설정에서 ens3 를 사용해야 합니다.
아래와 같이 NAT 설정 및 외부 트래픽을 허용합니다.
# iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
외부에서 들어오는 응답 트래픽을 허용합니다.
# iptables -A FORWARD -i ens3 -m state --state ESTABLISHED,RELATED -j ACCEPT
외부로 나가는 트래픽을 허용합니다.
# iptables -A FORWARD -i vlan10 -o ens3 -j ACCEPT
# iptables -A FORWARD -i vlan20 -o ens3 -j ACCEPT
추가되는 브릿지마다 한 줄씩 추가해주면 됩니다.
설정된 룰 상태를 출력합니다.
# iptables -L -v -n
sysdocu1 에서 sysdocu2 와 외부 네트워크는 통신이 되지만, 다른 브릿지의 sysdocu3, sysdocu4 컨테이너와 통신이 되지 않는 것을 확인할 수 있습니다.
7. 백업 및 복원
인스턴스의 스냅샷을 생성하여 인스턴스를 이전 상태로 쉽게 복원할 수 있습니다.
1) 스냅샷 생성
backup1 이라는 스냅샷을 생성합니다.
# incus snapshot create sysdocu-lxc backup1
스냅샷이 생성되었는지 확인합니다.
# incus list first // 맨 우측에 스냅샷 개수가 출력됩니다.
# incus info first // 맨 하단에 스냅샷 정보가 출력됩니다.
2) 스냅샷으로 복원
컨테이너를 스냅샷 상태로 복원합니다.
# incus snapshot restore sysdocu-lxc backup1
3) 스냅샷 삭제
# incus snapshot delete sysdocu-lxc backup1
8. 클러스터 구성
호스트 여러대를 묶어 노드간 컨테이너 이동을 용이하게 하거나 서비스 확장이 가능한 방법입니다.
첫번째 노드에서 아래 명령을 실행합니다.
incus 사용중이여도 괜찮습니다.
# incus admin init
Would you like to use clustering? (yes/no) [default=no]: yes
What IP address or DNS name should be used to reach this server? [default=10.101.0.29]:
Are you joining an existing cluster? (yes/no) [default=no]:
What member name should be used to identify this server in the cluster? [default=localhost]: node1
Do you want to configure a new local storage pool? (yes/no) [default=yes]:
Name of the storage backend to use (dir, lvm, btrfs) [default=btrfs]:
Create a new BTRFS pool? (yes/no) [default=yes]:
Would you like to use an existing empty block device (e.g. a disk or partition)? (yes/no) [default=no]:
Size in GiB of the new loop device (1GiB minimum) [default=5GiB]:
Do you want to configure a new remote storage pool? (yes/no) [default=no]:
Would you like to use an existing bridge or host interface? (yes/no) [default=no]:
Would you like stale cached images to be updated automatically? (yes/no) [default=yes]:
Would you like a YAML "init" preseed to be printed? (yes/no) [default=no]:
두번째 노드를 받아들이기 위한 토큰을 생성합니다. 노드명은 node2 라고 임의로 정했습니다.
# incus cluster add node2
Member node2 join token:
eyJzZXJ2ZXJfbmFtZSI6Im5vZGUyIiwiZmluZ2VycHJpbnQiOiJiNzNhZGUwMDk5ZWZhM2NiOGRjNmExMGNhNGFjMTk0ZWU2MDFmOGZjNTQyZDEwNmYyMTU3YTI1NjVlMmQwMjE2IiwiYWRkcmVzc2VzIjpbIjEwLjEwMS4wLjI5Ojg0NDMiXSwic2VjcmV0IjoiNzdkZWVjMjI3YTI3MzI3ZGM1Y2YxNzQ3YmEwZTE3Y2EyOTk1YzNiMWUxYmYwYmVmOGI3NmJhNmRlOGRiNDgxOCIsImV4cGlyZXNfYXQiOiIyMDI0LTA4LTA3VDEyOjAyOjI0LjM1OTM2MjY3MiswOTowMCJ9
두번째 노드에서 아래 명령을 실행합니다.
설정 도중에 첫번째 노드에서 확인한 토큰을 입력해야 합니다.
# incus admin init
Would you like to use clustering? (yes/no) [default=no]: yes
What IP address or DNS name should be used to reach this server? [default=10.101.0.3]:
Are you joining an existing cluster? (yes/no) [default=no]: yes
Please provide join token: eyJzZXJ2ZXJfbmFtZSI6Im5vZGUyIiwiZmluZ2VycHJpbnQiOiJiNzNhZGUwMDk5ZWZhM2NiOGRjNmExMGNhNGFjMTk0ZWU2MDFmOGZjNTQyZDEwNmYyMTU3YTI1NjVlMmQwMjE2IiwiYWRkcmVzc2VzIjpbIjEwLjEwMS4wLjI5Ojg0NDMiXSwic2VjcmV0IjoiNzdkZWVjMjI3YTI3MzI3ZGM1Y2YxNzQ3YmEwZTE3Y2EyOTk1YzNiMWUxYmYwYmVmOGI3NmJhNmRlOGRiNDgxOCIsImV4cGlyZXNfYXQiOiIyMDI0LTA4LTA3VDEyOjAyOjI0LjM1OTM2MjY3MiswOTowMCJ9
All existing data is lost when joining a cluster, continue? (yes/no) [default=no] yes
Choose "size" property for storage pool "default":
Choose "source" property for storage pool "default":
Choose "size" property for storage pool "local":
Choose "source" property for storage pool "local":
Would you like a YAML "init" preseed to be printed? (yes/no) [default=no]:
이렇게 하면 두 번째 노드가 첫 번째 노드가 포함된 클러스터에 참여하게 됩니다.
이 과정을 반복하여 추가 노드를 클러스터에 참여시킬 수 있습니다.
클러스터 가입 정보는 어느 노드에서도 동일하게 아래 명령으로 확인이 됩니다.
# incus cluster list
+---------------+--------------------------+------------------+--------------+----------------+-------------+--------+-------------------+
| NAME | URL | ROLES | ARCHITECTURE | FAILURE DOMAIN | DESCRIPTION | STATE | MESSAGE |
+---------------+--------------------------+------------------+--------------+----------------+-------------+--------+-------------------+
| node1 | https://10.101.0.29:8443 | database-leader | x86_64 | default | | ONLINE | Fully operational |
| | | database | | | | | |
+---------------+--------------------------+------------------+--------------+----------------+-------------+--------+-------------------+
| node2 | https://10.101.0.3:8443 | database-standby | x86_64 | default | | ONLINE | Fully operational |
+---------------+--------------------------+------------------+--------------+----------------+-------------+--------+-------------------+
9. 마이그레이션
마이그레이션을 수행하려면 CRIU (Checkpoint/Restore In Userspace) 도구가 필요합니다.
CRIU 는 컨테이너의 상태를 저장하고 복원하여 실행 중인 컨테이너를 마이그레이션할 수 있도록 합니다.
CRIU 패키지는 컨테이너를 보내고 받는 노드에 설치가 되어 있어야 합니다.
CRIU 패키지를 제공하는 외부 PPA 를 추가합니다.
# add-apt-repository ppa:criu/ppa
# apt -y update
PPA를 통해 CRIU를 설치합니다.
# apt -y install criu
클러스터 구성을 하였다면 컨테이너 리스트 확인시 노드 정보가 추가되어 출력됩니다.
# incus list
+----------+---------+----------------------+-----------------------------------------------+-----------+-----------+---------------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | LOCATION |
+----------+---------+----------------------+-----------------------------------------------+-----------+-----------+---------------+
| sysdocu1 | RUNNING | 10.194.49.116 (eth0) | fd42:b6f1:bf2c:f766:216:3eff:fe43:ba13 (eth0) | CONTAINER | 0 | node1 |
+----------+---------+----------------------+-----------------------------------------------+-----------+-----------+---------------+
| sysdocu2 | RUNNING | 10.194.49.80 (eth0) | fd42:b6f1:bf2c:f766:216:3eff:fe56:96f0 (eth0) | CONTAINER | 0 | node1 |
+----------+---------+----------------------+-----------------------------------------------+-----------+-----------+---------------+
| sysdocu3 | RUNNING | 10.91.111.49 (eth0) | fd42:cdfb:ea77:7cde:216:3eff:fec9:8466 (eth0) | CONTAINER | 0 | node1 |
+----------+---------+----------------------+-----------------------------------------------+-----------+-----------+---------------+
| sysdocu4 | RUNNING | 10.91.111.235 (eth0) | fd42:cdfb:ea77:7cde:216:3eff:fe09:db03 (eth0) | CONTAINER | 0 | node1 |
+----------+---------+----------------------+-----------------------------------------------+-----------+-----------+---------------+
sysdocu1 컨테이너를 node1 에서 node2 로 변경해 보겠습니다.
# incus stop sysdocu1
# incus move sysdocu1 --target node2
# incus start sysdocu1
변경된 상태를 확인합니다.
# incus list |grep sysdocu1
| sysdocu1 | RUNNING | 10.194.49.116 (eth0) | fd42:b6f1:bf2c:f766:216:3eff:fe43:ba13 (eth0) | CONTAINER | 0 | node2 |
* 옮긴 컨테이너는 sysdocu2 랑 통신이 되지 않음. iptables 가 하나의 노드에만 적용되기 때문인 것 같은데, 확인해 봐야 함.
* 현재까지의 해결책 : 모든 노드에 동일한 iptables 룰셋을 적용하고, 같은 네트워크를 사용하는 컨테이너끼리 한 노드에 모아 두어야 함.
* 확인할 것 : apt -y install openvswitch-switch 을 통하여 iptables 를 활용하지 않고 SDN 기능을 제공할 수 있을 것으로 보임.
10-1. 웹 UI 설치 (lxconsole) - 사용해보니 이게 좋아 보임
- VM 으로 생성시 Graphic console 사용 가능
참고 : https://github.com/PenningLabs/lxconsole/tree/main
# git clone https://github.com/PenningLabs/lxconsole.git
# cd lxconsole
# apt -y install python3-pip python3.12-venv
가상 환경 생성, 활성화 및 관련된 python 패키지 설치
# python3 -m venv myenv // 가상화 만드는 명령이므로 한번만 하면 됩니다.
# source myenv/bin/activate // 가상화로 전환
(myenv) root@kuru80-256844:~/lxconsole# pip install -r requirements.txt
(myenv) root@kuru80-256844:~/lxconsole# python3 run.py
* Serving Flask app 'lxconsole'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:5000
* Running on http://10.101.0.20:5000
Press CTRL+C to quit
위 내용은 개발용이니 프로덕션에 사용하려면 WSGI 서버를 사용하라는 말입니다.
CTRL+C 를 눌러 취소하고, 아래 명령을 실행하여 WSGI 서버를 실행합니다.
(myenv) root@kuru80-256844:~/lxconsole# pip install uwsgi // 한번만 설치 해두면 됨
(myenv) root@kuru80-256844:~/lxconsole# uwsgi --http 0.0.0.0:5000 --module run:app --processes 4 --threads 2 --logto /root/5000_access.log & // 백그라운드로 실행
(myenv) root@kuru80-256844:~/lxconsole# deactivate // 백그라운드 프로세스는 그대로 두고 가상화 종료
※ 참고 ==========================
여기까지의 작업을 반복하지 않도록 시스템 부팅시 자동으로 lxconsole 이 실행되게 합니다.
# vi /root/start_lxconsole.sh
#!/bin/bash
cd /root/lxconsole source myenv/bin/activate uwsgi --http 0.0.0.0:5000 --module run:app --processes 4 --threads 2 --logto /root/5000_access.log & deactivate |
실행 권한을 부여합니다.
# chmod 700 /root/start_lxconsole.sh
부팅 시 자동으로 스크립트가 실행되도록 systemd 서비스를 만듭니다.
# vi /etc/systemd/system/lxconsole.service
[Unit] Description=lxconsole uWSGI service After=network.target
[Service] ExecStart=/bin/bash /root/start_lxconsole.sh Restart=always User=root WorkingDirectory=/root/lxconsole Environment="PATH=/root/lxconsole/myenv/bin" Type=forking
[Install] WantedBy=multi-user.target |
* 백그라운드 데몬이 있으므로 Type=forking 사용하였음.
systemd 서비스 파일을 활성화하고 부팅 시 실행되도록 설정합니다.
# systemctl daemon-reload
# systemctl enable lxconsole
# systemctl start lxconsole
================================
계속 이어서 진행합니다.
데몬을 실행 했으면, 아래 주소와 같이 5000 번 포트를 통해 웹 UI 에 접근할 수 있습니다.
http://115.68.249.148:5000
처음 접속시 관리자 ID / PW 를 생성하고 로그인 하도록 되어 있습니다.
처음에 관리할 서버를 추가해야 합니다.
우측 상단의 [+Server] 버튼 클릭 합니다.
빈칸을 채우기 전에, 위를 살펴보면 here 링크가 보입니다. 이것을 누르면 incus 서버에 접근 인증을 해야한다고 인증 키값을 출력해주는데, 내용을 복사해서 lxconsole.crt 파일로 생성하고, 아래 명령으로 적용하면 서버 리스트에 node1 이 출력됩니다.
# incus config trust add-certificate lxconsole.crt
# incus config set core.https_address=[::]:8443
이후 서버 추가 메뉴로 돌아가 아래 내용을 입력 합니다.
Before adding an LXD/Incus server, it must first trust your client certificate.
Click here for instructions on trusting certificates.
- Host Addr (필수) : 115.68.249.148
- Port (필수) : 8443
- Proxy : (입력 안함)
- SSL Verify: (선택 안함. 기본 False)
노드 이름을 누르면 대시보드 출력과 함께 다양한 설정 메뉴가 제공되며, 이와 같이 다른 노드도 추가를 할 수 있습니다.
이밖에 Python 가상환경이 아닌, Docker 로 실행하는 방법을 원할 경우 참고 URL 을 확인해 주세요.
10-2. 웹 UI 설치 (Zabbly)
참고 : https://github.com/zabbly/incus?tab=readme-ov-file#installation
리포지토리 키를 확인합니다.
# curl -fsSL https://pkgs.zabbly.com/key.asc | gpg --show-keys --fingerprint
다음 디렉토리를 생성합니다.
# mkdir -p /etc/apt/keyrings/
키를 로컬에 저장합니다.
# curl -fsSL https://pkgs.zabbly.com/key.asc -o /etc/apt/keyrings/zabbly.asc
다음 명령으로 6.0 LTS 리포지토리를 추가합니다.
# sh -c 'cat <<EOF > /etc/apt/sources.list.d/zabbly-incus-lts-6.0.sources
Enabled: yes
Types: deb
URIs: https://pkgs.zabbly.com/incus/lts-6.0
Suites: $(. /etc/os-release && echo ${VERSION_CODENAME})
Components: main
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/zabbly.asc
EOF'
리포지토리 목록을 업데이트 하고 incus-ui-canonical 을 설치합니다.
incus-ui-canonical 은 LXD UI 의 리브랜딩 버전입니다.
# apt-get update
# apt-get install incus-ui-canonical
아래 주소로 접근합니다.
https://<서버 IP>:8443/
접속하면 새 인증서를 만들고 설정하는 단계가 나옵니다.
절차에 따라 인증서를 설정하고 브라우저로 재연결하면 됩니다.
10-3. 웹 UI 설치 (lxd-UI)
- VM 으로 생성시 Graphic console 사용 가능
참고 : https://github.com/canonical/lxd-ui
# snap install lxd
# snap refresh --channel=latest/stable lxd
# lxc config set core.https_address :8443 // 포트는 변경해도 됨
그리고 브라우저를 통해 SSL 접근하면 됩니다.
https://115.68.249.148:8443
페이지 접근 후, 가운데 녹색버튼을 눌러 인증서를 생성합니다.
크롬 브라우저에서 인증서를 등록 후, 다시 접근하면 자동 로그인되며, 인스턴스를 생성할 수 있게 됩니다.