lxc.container.conf(5) | lxc.container.conf(5) |
lxc.container.conf - LXC 컨테이너 설정파일
linux 컨테이너(lxc)는 항상 사용하기 전에 생성된다. 생성 작업은 가상화할 자원 및 컨테이너 내에서 실행되는 프로세스로부터 고립할 시스템 자원들을 정의하는 것이다. 기본적으로 pid, sysv ipc, 마운트 포인트가 가상화되고 고립된다. 명시적으로 설정파일에서 정의되기 전까지, 다른 시스템 자원들은 컨테이너 간에 공유된다. 예를 들어, 네트워크 설정이 되어 있지 않다면, 컨테이너 생성한 쪽과 컨테이너 간에 네트워크를 서로 공유할 것이다. 그러나 네트워크가 지정이되었다면, 컨테이너를 위해 새로운 네트워크 스택이 생성된다. 그리고 컨테이너는 더이상 그를 생성한 쪽과 네트워크를 공유하지 않는다.
설정파일은 컨테이너에 할당될 시스템 자원들을 정의한다. 현재는 utsname, 네트워크, 마운트포인트, 루트 파일시스템, 사용자 네임스페이스 그리고 컨트롤 그룹이 지원된다.
설정파일의 옵션은 key = value의 한 줄로 이루어져 있다. '#' 문자를 앞에 붙여 주석임을 나타낼 수 있다. capability와 cgroup 옵션과 같은 리스트 옵션들은, 값을 지정하지 않고 사용할 수 있다. 값이 지정되지 않은 경우 이전에 설정했던 모든 값들을 지운다.
연관된 컨테이너들을 쉽게 관리하기 위해서, 컨테이너 설정파일은 다른 파일을 불러올 수 있다. 예를 들어서, 네트워크 설정은 여러 컨테이너들을 위해 공통된 하나의 파일로 정의될 수 있다. 그리고 만약 컨테이너들이 다른 호스트로 이동된다면, 해당 파일 하나만 수정하면 된다.
컨테이너에 아키텍처를 지정할 수 있다. 예를 들어, 64비트 호스트에서 32비트 바이너리를 실행하는 컨테이너라면 32비트 아키텍처로 지정할 수 있다. 패키지를 다운로드 받는 등의 작업을 수행하는 아키텍처에 의존적인 컨테이너 스크립트가 잘 동작할 수 있도록 해준다.
가능한 옵션은 아래와 같다. x86, i686, x86_64, amd64
utsname 섹션은 컨테이너 내에서 설정할 호스트 이름을 정의한다. 컨테이너는 시스템의 호스트 이름을 변경하지 않고도 자신의 호스트 이름을 변경할 수 있다. 즉, 컨테이너마다 호스트 이름을 설정할 수 있다.
lxc-stop이 컨테이너를 깨끗이 종료를 시키기 위해서 보낼 시그널의 이름이나 숫자를 지정할 수 있다. init 시스템마다 깨끗한 종료를 위해 각기 다른 시그널을 사용할 수 있다. 이 옵션은 kill(1)에서 사용하는 것 처럼 시그널을 지정할 수 있다. 예를 들어 SIGPWR, SIGRTMIN+14, SIGRTMAX-10 또는 숫자를 지정할 수 있다. 기본 시그널은 SIGPWR이다.
lxc-stop이 컨테이너를 재부팅하기 위해 보낼 시그널의 이름이나 숫자를 지정할 수 있다. 이 옵션은 kill(1)에서 사용하는 것 처럼 시그널을 지정할 수 있다. 예를 들어 SIGINT, SIGRTMIN+14, SIGRTMAX-10 또는 숫자를 지정할 수 있다. 기본 시그널은 SIGINT이다.
lxc-stop이 컨테이너를 강제종료하기 위해 보낼 시그널의 이름이나 숫자를 지정할 수 있다. 이 옵션은 kill(1)에서 사용하는 것 처럼 시그널을 지정할 수 있다. 예를 들>어 SIGKILL, SIGRTMIN+14, SIGRTMAX-10 또는 숫자를 지정할 수 있다. 기본 시그널은 SIGKILL이다.
컨테이너의 init으로 사용할 명령어를 설정한다. 이 옵션은 lxc-execute을 사용할 때는 무시된다. 기본값은 /sbin/init이다.
lxc-execute가 실행하는 컨테이너의 init 및 명령어가 사용할 UID/GID를 지정한다. 이 옵션들은 lxc-execute가 사용자 네임스페이스 안에서 실행될 때만 적용된다. 기본 값: UID(0), GID(0)
컨테이너가 종료될 때, 해당 컨테이너를 제거할지 여부를 지정할 수 있다.
네트워크 섹션은 어떻게 네트워크를 컨테이너 내에서 가상화할지를 정의한다. 네트워크 가상화는 2개의 계층으로 동작한다. 네트워크 가상화를 위해서, 컨테이너의 네트워크 인터페이스가 인수로 지정되어야 한다. 시스템이 하나의 물리적인 네트워크 인터페이스를 갖고 있어도, 컨테이너 내에서 여러개의 가상화 인터페이스들을 사용할 수 있다.
none: 호스트의 네트워크 네임스페이스를 공유한다. 이렇게 하면 호스트의 네트워크 장치를 컨테이너 내에서 사용가능하다. 컨테이너와 호스트 둘다 init에서 upstart를 사용하는 경우, (예를 들어) 컨테이너에서 'halt'를 하면, 호스트의 것도 종료된다.
empty:는 루프백 인터페이스만 생성한다.
veth: 한 쪽은 컨테이너로, 다른 한쪽은 lxc.net.[i].link 옵션으로 지정한 브리지로 붙은 가상 이더넷(veth) 장치 쌍을 생성한다. 만약 브리지가 지정되지 않았다면, 어떤 브리지에도 붙지 않은 veth 장치 쌍을 만든다. 브리지는 컨테이너 시작전에 시스템에서 생성해야 한다. lxc는 컨테이너 이외의 설정에 대해서는 다루지 않는다. 기본값으로 lxc는 컨테이너 바깥에 속할 네트워크 디바이스의 이름을 정해준다. 이름을 변경하기 원한다면, lxc가 지정한 이름으로 설정하도록 lxc.net.[i].veth.pair 옵션을 사용하여야 한다. (비특권 컨테이너는 불가능하다. 이 옵션은 보안상의 이유로 무시될 것이다)
vlan: vlan 인터페이스는 lxc.net.[i].link로 지정한 인터페이스에 연결되고, 컨테이너로 할당된다. vlan의 식별자는 lxc.net.[i].vlan.id 옵션으로 지정한다.
macvlan: macvlan 인터페이스는 lxc.net.[i].link로 지정한 인터페이스에 연결되고, 컨테이너로 할당된다. lxc.net.[i].macvlan.mode은 같은 상위 디바이스에 있는 다른 macvlan과 통신할 때 사용하는 모드를 지정한다. 지정할 수 있는 모드는 private、vepa、bridge、passthru이다. private모드는 디바이스가 같은 상위디바이스의 어떤 장치와도 통신하지 않는다. (기본값) 새로운 가상 이더넷 포트 통합모드(Virtual Ethernet Port Aggregator), 즉 vepa 모드는 인접한 브리지가 소스와 목적지가 로컬인 모든 프레임들을 macvlan 포트로 반환한다고 가정한다. 즉, 브리지가 reflective relay로 설정되어 있다는 것이다. 상위장치에서 들어오는 브로드캐스트 프레임들은 모든 macvlan 인터페이스에게 보내져버린다. 로컬 프레임들은 로컬로 보내지지 않는다. bridge 모드는 같은 포트의 다른 macvlan 인터페이스 사이에 간단한 브리지를 제공한다. 어떤 인터페이스에서 다른 인터페이스로 프레임은 직접 전달된다. 하지만 외부로는 보내지지 않는다. 브로드캐스트 프레임들은 모든 다른 브리지 포트들과 외부 인터페이스에 전달된다. 그러나 reflective relay로 다시 돌아왔을 때는, 그것들을 다시 전송하지 않는다. 모든 MAC 주소를 알기 때문에, macvlan 브리지모드는 브리지 모듈처럼 학습이나 STP를 요구하지 않는다. passthru모드는 물리 인터페이스로 부터 받은 모든 프레임들을 macvlan 인터페이스로 포워딩한다. passthru모드만이 하나의 물리 인터페이스를 설정하는게 가능하다.
phys: lxc.net.[i].link로 지정한 이미 존재하는 인터페이스를 컨테이너로 할당된다.
up: 인터페이스를 활성화시킨다.
스크립트의 표준출력은 debug 수준 로그로 납겨진다. 표준 에러는 로그로 남겨지지는 않지만, 표준 에러를 표준 출력으로 리다이렉션하여 로그로 남길 수 있다.
스크립트의 표준출력은 debug 수준 로그로 납겨진다. 표준 에러는 로그로 남겨지지는 않지만, 표준 에러를 표준 출력으로 리다이렉션하여 로그로 남길 수 있다.
강한 고립을 위해 컨테이너는 자기자신만의 pseudo tty를 가질 수 있다.
컨테이너에 루트 파일시스템이 설정되어 있고 inittab 파일에 콘솔을 사용하는 것이 설정되어 있다면, 콘솔의 출력을 어디로 할지 지정할 수 있다.
컨테이너에 루트 파일시스템이 설정되어 있고 inittab 파일에 tty에서 getty를 실행하는 것이 설정되어 있다면, 이 옵션은 유용하다. 이 옵션은 컨테이너에서 사용가능한 tty의 개수를 지정한다. 컨테이너의 inittab 파일에 설정된 getty의 개수는 이 옵션에서 정한 tty의 개수보다 크면 안된다. 그렇지 않으면 초과된 getty 세션은 무한히 죽고 다시 살아나기를 반복하며 콘솔이나 /var/log/messages에 계속 메시지를 띄울 것이다.
LXC 콘솔은 호스트에서 생성된 Unix98 PTY와 컨테이너 내에 바인드 마운트될 장치들을 통해 제공된다. 기본적으로 /dev/console와 /dev/ttyN를 바인드 마운트 한다. 이것은 게스트에서 패키지 업그레이드를 방해하는 요인이 된다. 그래서 /dev 밑에 LXC가 파일을 생성하고 바인드 마운트할 디렉토리의 위치를 따로 지정해 줄 수 있다. 그리고 만들어진 파일들은 /dev/console와 /dev/ttyN에 심볼릭 링크된다. 심볼릭 링크들은 삭제하거나 대체하는 것이 가능하므로 패키지 업그레이드는 성공적으로 이루어질 수 있다.
기본적으로 lxc는 약간의 심볼릭 링크(fd, stdin, stdout, stderr)를 컨테이너의 /dev 디렉토리에 생성한다. 그러나 자동으로 장치 노드 항목들을 생성해주지 않는다. 컨테이너의 루트 파일시스템에서 필요로하는 /dev를 생성할 수 있게 하는 것이다. lxc.autodev가 1로 지정되었다면, 컨테이너 루트 파일시스템을 마운트 한 후, LXC가 /dev 밑에 새로운 tmpfs(최대 500k)를 마운트 해준다. 그리고 최소한의 장치만을 채워준다. 이것은 "systemd" 기반의 "init" 환경의 컨테이너를 시작할 때 일반적으로 필요하지만, 다른 환경의 경우는 선택적인 요소이다. 컨테이너의 부가적인 장치들은 lxc.hook.autodev 훅 스크립트를 사용하여 /dev 디렉토리에 생성할 수 있다.
/dev/console에 대한 심볼릭 링크로 /dev/kmsg를 생성한다.
마운트 포인트 섹션은 마운트가 될 각각의 장소를 지정한다. 이 마운트 포인트들은 컨테이너에서만 보이고 외부에서 실행하는 프로세스들에겐 보이지 않는다. 이는 예를 들어 /etc, /var, /home을 마운트할 때 유용하다.
주의 - 보통 LXC는 마운트 대상과 상대 경로로 된 바인드 마운트 소스들이 컨테이너의 루트 아래에 있도록 보장할 것이다. 이는 호스트 디렉토리와 파일들을 겹쳐서 마운트하는 유형의 공격을 피하기 위한 것이다. (절대 경로로 된 마운트 소스 내에 존재하는 심볼릭 링크들은 무시될 것이다.) 하지만, 만약 컨테이너 설정에서 컨테이너 사용자가 제어할 수 있는, 예를 들어 /home/joe와 같은 디렉토리를 컨테이너 내의 path에 먼저 마운트 하고 나서, path 내에 또 마운트를 하는 경우가 있다면, 컨테이너 사용자가 자신의 home 디렉토리에 있는 심볼릭링크를 정확한 시간에 조작하여, TOCTTOU (역주 : Time of check to time of use) 공격이 가능할 것이다.
proc proc proc nodev,noexec,nosuid 0 0 .fi 위의 예는 proc 파일시스템을 컨테이너 루트 파일시스템의 위치와 상관없이 컨테이너의 /proc에 마운트시키는 예제이다. 이는 백엔드 파일시스템 블록 장치뿐만 아니라 컨테이너의 복제에도 유연하게 대처할 수 있다. 이미지 파일이나 블록 장치에서 마운트된 파일시스템의 경우, 3번째 필드 (fs_vfstype)는 mount(8) 와 같이 auto를 지정할수 없으며, 명시적으로 지정해야 한다.
fstab의 형식으로, 한 줄당 마운트 포인트 하나를 지정한다. 또한 마운트 옵션에 아래 2가지 옵션을 추가적으로 사용할 수 있다. 이는 LXC 자체적으로 사용하는 옵션이다. optional은 마운트를 못하더라도, 실패로 처리하지 않게 한다. create=dir와 create=file는 마운트할 때, 디렉토리(dir) 또는 파일(file)을 생성한다.
일반적인 커널의 파일시스템을 자동으로 마운트할지 지정한다. 이 옵션을 사용하면 설정을 매우 편하게 할 수 있다. 사용할 수 있는 파일시스템들은 아래와 같다.
proc:mixed (or proc): /proc 을 읽기/쓰기 가능으로 마운트, 그러나 /proc/sys과 /proc/sysrq-trigger는 읽기 전용으로 다시 마운트 (보안상의 이유 및 컨테이너 고립을 위해)
proc:rw: /proc 전체를 읽기/쓰기 가능으로 마운트
sys:mixed (or sys): /sys/devices/virtual/net는 쓰기 가능으로, /sys는 읽기 전용으로 마운트.
sys:ro: /sys를 읽기 전용으로 마운트 (보안상의 이유 및 컨테이너 고립을 위해)
sys:rw: /sys를 읽기/쓰기 가능으로 마운트
cgroup:mixed: /sys/fs/cgroup를 tmpfs로 마운트. 컨테이너가 추가될 모든 계층의 디렉토리 생성. cgroup 이름의 하위 디렉토리 생성. 컨테이너 자신의 cgroup을 해당 디렉토리에 마운트. 컨테이너는 자신의 cgroup 디렉토리에는 쓰기가 가능하지만 부모의 디렉토리는 읽기전용으로 마운트 하므로 쓰기가 불가능하다.
cgroup:ro: cgroup:mixed와 유사, 단, 전부 읽기 전용으로 마운트
cgroup:rw: cgroup:mixed와 유사, 단, 전부 읽기/쓰기 가능으로 마운트. 컨테이너 자신의 cgroup에 이르기까지의 경로가 모두 쓰기 가능이 되지만, cgroup 파일시스템이 아닌 /sys/fs/cgroup의 tmpfs의 일부로써 존재하게 되는 것에 주의해야 한다.
cgroup (별다른 옵션 없이): 컨테이너가 CAP_SYS_ADMIN capability를 유지하고 있는 경우 cgroup:rw을 기본으로 사용한다. 그렇지 않다면 cgroup:mixed를 사용한다.
cgroup-full:mixed: /sys/fs/cgroup을 tmpfs로 마운트. 컨테이너가 추가될 모든 계층의 디렉토리 생성. 호스트의 디렉토리들을 컨테이너로 바인드 마운트하고 컨테이너 자신의 cgroup을 제외한 모든 디렉토리는 읽기 전용으로 변경. 비교하자면, cgroup의 경우에는 컨테이너 자신의 cgroup에 이르기까지 모든 경로는 단순하게 tmpfs 아래에 있는 디렉토리에 불과하다. 하지만, 여기서는 비록 컨테이너 자신의 cgroup 이외에는 모두 읽기 전용이긴 하나 /sys/fs/cgroup/$hierarchy이 호스트의 모든 cgroup 계층구조를 포함하고 있다. 이는 컨테이너에게 너무 많은 정보를 노출시킬 수 있다.
cgroup-full:ro: cgroup-full:mixed와 유사, 단, 전부 읽기 전용으로 마운트
cgroup-full:rw: cgroup-full:mixed와 유사, 단, 전부 읽기/쓰기 가능으로 마운트. 이 경우는 컨테이너가 자기자신의 cgroup을 벗어날 수 있다. (만약 컨테이너가 CAP_SYS_ADMIN을 갖고 있다면, cgroup 파일시스템 자체를 마운트할 수 있음을 주의해야 한다. 이렇게 하면 같은 결과를 가져올 수 있다)
cgroup-full (별다른 옵션 없이): 컨테이너가 CAP_SYS_ADMIN capability를 유지하고 있는 경우 cgroup-full:rw을 기본으로 사용한다. 그렇지 않다면 cgroup-full:mixed를 사용한다.
cgroup 네임스페이스가 사용 가능한 경우, cgroup 마운트 옵션들은 전부 무시될 것이다. 컨테이너가 직접 파일시스템을 마운트하기 때문이며, 컨테이너 초기화시 해당 옵션이 혼란을 줄 수 있기 때문이다. cgroup 파일시스템이 자동으로 마운트되는게 활성화되어 있다면, /sys/fs/cgroup 밑의 tmpfs는 언제나 읽기/쓰기 가능으로 마운트 된다.(단, :mixed과 :ro의 경우에는 각각 계층 /sys/fs/cgroup/$hierarchy이 읽기전용이 될 수는 있다) 아래의 Ubuntu 명령어에 대응하기 위함이다. mountall(8) 해당 명령어는 컨테이너 부팅시에 /sys/fs/cgroup가 읽기전용으로 마운트되어 있고, 컨테이너가 CAP_SYS_ADMIN을 갖고 있지 않아 이를 읽기/쓰기 전용으로 다시 마운트 못할 경우, 부팅시에 사용자의 입력을 기다리게 만들기 때문이다. 예제:
lxc.mount.auto = proc sys cgroup lxc.mount.auto = proc:rw sys:rw cgroup-full:rw
컨테이너의 루트 파일시스템은 호스트 시스템과 다르게 구성할 수 있다.
디렉토리 또는 간단한 블록 장치로 구성된 컨테이너를 위해서 경로이름이 사용될 수 있다. 만약 루트 파일시스템이 nbd 장치의 경우, nbd:file:1는 file을 nbd 장치로 사용하고 1번 파티션이 루트 파일시스템으로 마운트되도록 지정한다. nbd:file는 nbd 장치 자체가 마운트되어야 한다고 지정한다. overlayfs:/lower:/upper는 루트 파일시스템이 읽기전용으로 마운트된 /lower를 /upper가 읽기/쓰기 가능으로 오버레이 마운트되도록 지정한다. aufs:/lower:/upper는 aufs에서 위와같이 지정한다. overlayfs와 aufs는 여러개의 /lower 디렉토리를 지정할 수 있다. loop:/file는 lxc가 /file을 loop 장치로 사용하고 loop 장치를 마운트하도록 지정한다.
컨트롤 그룹 섹션은 (lxc와는) 다른 서브시스템의 설정을 포함한다. lxc는 서브시스템의 이름을 정확히 체크하지 않는다. 이는 컨테이너를 시작할 때까지는 설정 상의 에러를 잡아내기 힘들게 한다. 그러나 다른 차후에 들어올 수 있는 서브시스템을 지원할 수 있는 장점도 있다.
컨테이너가 root로 실행된다면, 컨테이너 내에서 capability를 제거할 수 있다.
lxc가 apparmor를 지원하도록 컴파일된 후 설치되었고, 호스트 시스템에서 apparmor가 활성화되었다면, 컨테이너에서 따라야할 apparmor 프로파일을 컨테이너 설정에서 지정할 수 있다. 기본값은 호스트 커널이 cgroup 네임스페이스를 지원하면 lxc-container-default-cgns이고, 그렇지 않다면 lxc-container-default이다.
lxc.apparmor.profile = unconfined
apparmor 프로파일이 변경되지 않아야 한다면(중첩 컨테이너 안에 있고, 이미 confined된 경우), 아래와 같이 지정하면 된다.
lxc.apparmor.profile = unchanged
만약 이 플래그가 0(기본값)이라면, 커널에 apparmor의 마운트 기능이 부족했을때 컨테이너가 시작되지 않는다. 커널을 업그레이드한 후에 해당 기능이 빠졌는지 여부를 검사하기 위함이다. 부분적인 apparmor 보호 하에서도 컨테이너를 시작하려면, 플래그를 1로 지정하면 된다.
lxc가 SELinux를 지원하도록 컴파일된 후 설치되었고, 호스트 시스템에서 SELinux 컨텍스트가 활성화되었다면, 컨테이너에서 따라야할 SELinux 컨텍스트를 컨테이너 설정에서 지정할 수 있다. 기본값은 unconfined_t이다. 이는 lxc는 컨텍스트를 변경하지않음을 의미한다. 정책 예제와 추가적인 정보를 원한다면 /usr/share/lxc/selinux/lxc.te를 참고하면 된다.
lxc.selinux.context = system_u:system_r:lxc_t:s0:c22
컨테이너는 seccomp 프로파일을 로드하여 사용가능한 시스템콜의 수를 줄인 체로 실행할 수 있다. seccomp 설정파일은 첫번째 행이 버전번호, 두번째 행이 정책 타입, 시작하며 그 이후에 설정 사항들이 포함되어야 한다.
현재는 버전1과 2만 지원된다. 버전 1에서는 정책은 단순한 화이트리스트이다. 그러므로 두번째 라인은 반드시 "allowlist"여야 한다. 파일의 나머지 내용은 한 줄에 하나의 시스템콜 번호로 채워진다. 화이트리스트에 없는 번호는 컨테이너에서 블랙리스트로 들어간다.
버전 2에서는 폴리시는 블랙리스트 또는 화이트리스트가 될 수 있다. 그리고 각 규칙와 각 정책의 기본 동작, 아키텍쳐별 시스템콜 설정, 텍스트로된 이름을 지원한다.
아래는 블랙리스트 정책 예제이다. 아래 정책에서는 mknod를 제외한 모든 시스템콜이 허용된다. mknod시에는 아무것도 수행하지 않고 0(성공)을 반환한다.
2 denylist mknod errno 0 .fi
컨테이너가 시작되기전에 읽어올 seccomp 설정이 담긴 파일을 지정한다.
PR_SET_NO_NEW_PRIVS가 적용되면, execve()는, execve()를 호출되기 전에는 실행하지 못했던 것을 수행하기 위해 권한을 부여하는 류의 동작을 하지 않게 된다. (예를 들어, set-user-ID와 set-group-ID 모드, 파일 캐퍼빌리티가 동작하지 않는 것이다.) 일단 적용되면 이 비트는 해제할 수 없다. 이 비트는 fork()와 clone()으로 생성된 자식에게도 상속되며, execve() 이후에도 그대로 적용된다. PR_SET_NO_NEW_PRIVS는 컨테이너의 AppArmor 프로필 또는 SELinux 문맥이 변경된 이후에 적용된다.
컨테이너는 사용자와 그룹 ID 매핑을 통해 자신만의 사용자 네임스페이스 내에서 실행될수 있다. 예를 들어서 컨테이너의 UID 0번을 호스트의 UID 200000으로 매핑할 수 있다. 컨테이너의 루트 사용자는 컨테이너에서는 특권을 가지고 있지만, 호스트에서는 특권을 가지고 있지 않게 된다. 보통 시스템 컨테이너는 ID들의 범위를 지정하려 할텐데 그 역시도 지정 가능하다. 예를 들어서, 컨테이너의 UID와 GID를 0 ~ 20,000를 호스트의 200,000 ~ 220,000로 설정 가능하다.
컨테이너 훅은 컨테이너의 생명주기 내에서 다양한 상황에 실행되는 프로그램 또는 스크립트이다.
컨테이너 훅이 실행될 때, 정보는 명령어 인수나 환경 변수를 통해 넘겨진다. 인수 :
환경 변수 :
훅의 표준출력은 debug 수준 로그로 납겨진다. 표준 에러는 로그로 남겨지지는 않지만, 표준 에러를 표준 출력으로 리 다이렉션하여 로그로 남길 수 있다.
훅이 시작될때 설정 정보를 제공하고 훅의 기능을 돕기 위해 몇가지 환경 변수가 사용 가능하다. 모든 컨텍스트에서 모든 변수가 사용 가능하진 않다. 특히, 모든 경로는 호스트 시스템에서의 경로이며, lxc.hook.start 훅에서는 유효하지 않다.
로그는 각 컨테이너마다 설정할 수 있다. 기본적으로 lxc 패키지가 어떻게 컴파일되었는지에 달려있지만, 컨테이너 시작시에는 error 수준 로그만 기록된다. 컨테이너 경로나 /var/log/lxc 밑에 컨테이너의 이름을 따서(뒤에 '.log'를 붙여서) 로그 파일을 생성한다.
기본 로그 수준과 로그파일은 컨테이너 설정파일로 지정 가능하며, 기본 동작을 덮어버린다. 마찬가지로 설 정파일 항목들은 lxc-start 명령어의 옵션으로 덮어쓸 수 있다.
(훅 스크립트 및 네트워크 인터페이스 up/down 스크립트 같은) 스크립트가 호출이되면, 스크립트의 표준 입출력은 1 번, debug 수준으로 기록된다.
자동시작 옵션들은 자동시작할 컨테이너 지정 및 순서 설정이 가능하다. 이 옵션들은 LXC 도구로 직접 사용하거나 배포판들이 제공하는 외부 도구에 의해 사용될 수도 있다.
각각의 컨테이너는 여러 그룹에 속할수도 있고 아무그룹에도 속하지 않을 수 있다. 두개의 그룹은 특수한데, 하나는 NULL 그룹이고 컨테이너가 아무그룹에도 속하지 않을때 사용된다. 그리고 나머지 하나는 "onboot" 그룹이다.
LXC 서비스가 활성화된 상태로 시스템이 부팅될 때, 먼저 lxc.start.auto == 1이고 "onboot" 그룹인 컨테이너들을 시작하려고 시도한다. 시작과정은 lxc.start.order의 순서대로 이루어진다. 만약 lxc.start.delay가 지정 되었다면, 다음 컨테이너를 시작하려고 시도>하기 전, 현재 컨테이너의 초기화 및 호스트 시스템의 부하를 줄이기 위해서 지연시간을 준다. "onboot" 그룹의 멤버들을 시작시킨 후, LXC 시스템은 lxc.start.auto == 1이고 어떤 그룹에도 속하지 않은(NULL 그룹) 컨테이너들을 시작한다.
컨테이너에 환경변수를 념겨주고 싶다면(환경변수를 컨테이너의 init과 그 자손 전체가 사용할 수 있다), lxc.environment를 사용할 수 있다. 민감한 정보를 넘기지 않도록 주의해야 한다. 왜냐면 컨테이너의 모든 프로세스가 이 환경변수를 획득할 수 있기 때문이다. 환경변수는 항상 /proc/PID/environ를 통해 획득할 수 있다.
이 설정항목은 여러번을 지정할 수 있으며, 설정하려는 환경변수마다 한번씩 지정한다.
lxc.environment = APP_ENV=production lxc.environment = SYSLOG_SERVER=192.0.2.42
아래에 소개하는 몇가지 예제말고도 다른 예제들이 /usr/share/doc/lxc/examples에 위치하고 있다.
이 설정은 컨테이너가 한 쪽은 (이전에 시스템에 이미 생성된) br0 브리지에 연결되어 있는 veth 장치 쌍을 사용하도록 세팅한다. 가상 네트워크 장치는 컨테이너 내에서 eth0라는 이름을 갖는다.
lxc.uts.name = myhostname lxc.net.0.type = veth lxc.net.0.flags = up lxc.net.0.link = br0 lxc.net.0.name = eth0 lxc.net.0.hwaddr = 4a:49:43:49:79:bf lxc.net.0.ipv4.address = 1.2.3.5/24 1.2.3.255 lxc.net.0.ipv6.address = 2003:db8:1:0:214:1234:fe0b:3597
이 설정은 UID와 GID 둘다를 컨테이너의 0 ~ 9999를 호스트의 100000 ~ 109999로 매핑한다.
lxc.idmap = u 0 100000 10000 lxc.idmap = g 0 100000 10000
이 설정은 어플리케이션을 위해 몇가지 컨트롤 그룹을 설정한다. cpuset.cpus는 정의된 cpu만 사용하도록 제한한다. cpus.share은 컨트롤 그룹(cpu) 우선순위를 지정한다. devices.allow는 특정 장치를 사용 가능하게 한다.
lxc.cgroup.cpuset.cpus = 0,1 lxc.cgroup.cpu.shares = 1234 lxc.cgroup.devices.deny = a lxc.cgroup.devices.allow = c 1:3 rw lxc.cgroup.devices.allow = b 8:0 rw
아래의 예제는 복잡한 네트워크 스택, 컨트롤 그룹 사용, 호스트 이름 설정, 몇몇 장소 마운트, 루트 파일시스템 변경 등의 복잡한 설정을 보여준다.
lxc.uts.name = complex lxc.net.0.type = veth lxc.net.0.flags = up lxc.net.0.link = br0 lxc.net.0.hwaddr = 4a:49:43:49:79:bf lxc.net.0.ipv4.address = 10.2.3.5/24 10.2.3.255 lxc.net.0.ipv6.address = 2003:db8:1:0:214:1234:fe0b:3597 lxc.net.0.ipv6.address = 2003:db8:1:0:214:5432:feab:3588 lxc.net.1.type = macvlan lxc.net.1.flags = up lxc.net.1.link = eth0 lxc.net.1.hwaddr = 4a:49:43:49:79:bd lxc.net.1.ipv4.address = 10.2.3.4/24 lxc.net.1.ipv4.address = 192.168.10.125/24 lxc.net.1.ipv6.address = 2003:db8:1:0:214:1234:fe0b:3596 lxc.net.2.type = phys lxc.net.2.flags = up lxc.net.2.link = random0 lxc.net.2.hwaddr = 4a:49:43:49:79:ff lxc.net.2.ipv4.address = 10.2.3.6/24 lxc.net.2.ipv6.address = 2003:db8:1:0:214:1234:fe0b:3297 lxc.cgroup.cpuset.cpus = 0,1 lxc.cgroup.cpu.shares = 1234 lxc.cgroup.devices.deny = a lxc.cgroup.devices.allow = c 1:3 rw lxc.cgroup.devices.allow = b 8:0 rw lxc.mount.fstab = /etc/fstab.complex lxc.mount.entry = /lib /root/myrootfs/lib none ro,bind 0 0 lxc.rootfs.path = dir:/mnt/rootfs.complex lxc.cap.drop = sys_module mknod setuid net_raw lxc.cap.drop = mac_override
lxc(7), lxc-create(1), lxc-copy(1), lxc-destroy(1), lxc-start(1), lxc-stop(1), lxc-execute(1), lxc-console(1), lxc-monitor(1), lxc-wait(1), lxc-cgroup(1), lxc-ls(1), lxc-info(1), lxc-freeze(1), lxc-unfreeze(1), lxc-attach(1), lxc.conf(5)
Daniel Lezcano <daniel.lezcano@free.fr>
2023-11-30 |