Red Hat Certified System Administrator (RHCSA) #14 컨테이너 관리: Podman, systemd integration (quadlet)

9 분 소요

RHEL 실무 트랙 21편으로 사용자 관리,스토리지,systemd,SELinux를 직접 만져 보았다면, 그다음 자연스러운 단계는 그 감각을 자격증으로 검증받는 일입니다. 이번 글은 RHCSA 출제 영역의 마지막 축인 컨테이너를 다룹니다. RHEL의 컨테이너 엔진은 도커가 아니라 Podman이며, RHCSA에서는 단순히 컨테이너를 띄우는 것을 넘어 그 컨테이너를 systemd로 등록해 부팅 시 자동 실행하는 작업까지 손으로 끝낼 수 있어야 합니다.

이 영역은 명령 개수는 많지 않지만 rootless 실행quadlet으로 systemd 연동이라는 두 함정이 합격을 가릅니다. 둘 다 빠지기 쉬운 지점이라 이번 글에서 정확한 절차를 직접 쳐 보며 잡겠습니다.

Podman을 쓰는 이유 #

RHEL 8부터 도커 대신 Podman이 기본 컨테이너 엔진입니다. Podman은 도커와 명령 호환성이 거의 같아서 docker 자리에 podman을 넣으면 대부분 그대로 동작합니다. 다만 RHCSA가 Podman을 선택한 진짜 이유는 두 가지입니다.

  • 데몬이 없습니다. 도커는 root 권한으로 도는 dockerd 데몬에 명령을 보내는 구조이지만, Podman은 데몬 없이 명령이 직접 컨테이너 프로세스를 띄웁니다. 그래서 컨테이너를 systemd로 직접 관리하기에 자연스럽습니다.
  • rootless를 정식 지원합니다. 일반 사용자가 root 없이 자신의 컨테이너를 띄울 수 있습니다. RHCSA는 보통 특정 일반 사용자로 rootless 컨테이너를 돌리라고 요구하므로 이 점이 중요합니다.

먼저 패키지가 설치되어 있는지 확인하겠습니다.

# Podman 설치 (보통 RHEL 9에 기본 포함)
sudo dnf install -y container-tools

# 버전 확인
podman --version

레지스트리 로그인과 이미지 다루기 #

RHEL이 제공하는 공식 이미지는 Red Hat 레지스트리에 있습니다. 인증이 필요한 레지스트리는 먼저 로그인합니다.

# Red Hat 레지스트리 로그인 (계정 자격 증명 입력)
podman login registry.access.redhat.com

# 로그인 정보는 사용자별 인증 파일에 저장됨
#   $XDG_RUNTIME_DIR/containers/auth.json

로그인한 뒤 이미지를 검색하고 받습니다.

# 이미지 검색
podman search ubi9

# 이미지 받기 (registry.access.redhat.com의 ubi9)
podman pull registry.access.redhat.com/ubi9/ubi

# 로컬에 받은 이미지 목록
podman images

podman search는 설정된 레지스트리에서 이미지를 찾고, podman pull은 받은 이미지를 로컬에 저장합니다. 시험에서는 이미지 이름을 레지스트리 경로까지 전부 적는 편이 안전합니다. 짧은 이름은 레지스트리 검색 순서에 따라 엉뚱한 이미지를 받을 수 있기 때문입니다.

컨테이너 실행과 기본 명령 #

컨테이너를 백그라운드로 실행하면서 포트,볼륨,환경변수를 매핑하는 명령이 RHCSA의 핵심입니다.

# 백그라운드 실행 (-d), 포트 매핑 (-p), 이름 지정 (--name)
podman run -d --name web -p 8080:80 \
  registry.access.redhat.com/ubi9/httpd-24

# 실행 중인 컨테이너 목록
podman ps

# 멈춘 컨테이너까지 모두 보기
podman ps -a

# 로그 확인
podman logs web

# 컨테이너 안에서 명령 실행 (셸 진입)
podman exec -it web /bin/bash

# 중지와 삭제
podman stop web
podman rm web

-d는 detached(백그라운드) 실행, -p 호스트포트:컨테이너포트는 포트 매핑, --name은 다루기 쉽도록 이름을 붙입니다. podman exec -it로 실행 중인 컨테이너 안에 들어가 상태를 확인할 수 있습니다.

볼륨 매핑 #

컨테이너는 삭제하면 내부 데이터가 사라지므로, 유지해야 할 데이터는 호스트 디렉터리를 볼륨으로 마운트합니다.

# 호스트 디렉터리 준비
mkdir -p ~/web-content
echo "hello from host" > ~/web-content/index.html

# 볼륨 매핑 (-v 호스트경로:컨테이너경로:Z)
podman run -d --name web -p 8080:80 \
  -v ~/web-content:/var/www/html:Z \
  registry.access.redhat.com/ubi9/httpd-24

-v 호스트경로:컨테이너경로로 마운트하며, 끝의 **:Z**가 RHCSA에서 빠지기 쉬운 함정입니다. RHEL은 SELinux가 켜져 있어서, :Z를 붙여야 Podman이 해당 호스트 디렉터리에 container_file_t 컨텍스트를 자동으로 설정합니다. 이것을 빼면 컨테이너가 볼륨에 접근하지 못해 권한 오류가 납니다.

환경변수 전달 #

# 환경변수 전달 (-e KEY=VALUE)
podman run -d --name db \
  -e POSTGRESQL_USER=appuser \
  -e POSTGRESQL_PASSWORD=secret \
  -e POSTGRESQL_DATABASE=appdb \
  -p 5432:5432 \
  registry.redhat.io/rhel9/postgresql-15

-e KEY=VALUE로 환경변수를 넘깁니다. 컨테이너 이미지는 보통 이런 환경변수로 초기 설정(사용자,비밀번호,DB 이름)을 받습니다. 어떤 변수를 요구하는지는 이미지 문서에 적혀 있으므로, 시험에서는 문제 지문이 알려 주는 값을 그대로 넣으면 됩니다.

rootless 컨테이너 #

RHCSA는 거의 항상 일반 사용자로 rootless 컨테이너를 돌리라고 요구합니다. 핵심은 단순합니다. 해당 사용자로 로그인한 상태에서 sudo 없이 podman 명령을 실행하면 됩니다.

# root가 특정 사용자로 전환할 때는 로그인 셸로 들어가야 함
sudo su - appuser

# 이제 appuser로서 rootless 실행 (sudo 없이)
podman run -d --name web -p 8080:80 \
  registry.access.redhat.com/ubi9/httpd-24

# appuser의 컨테이너만 보임
podman ps

rootless에는 두 가지 주의점이 있습니다.

  • 1024 미만 포트를 호스트에 직접 매핑할 수 없습니다. rootless는 권한이 없는 사용자이므로 -p 80:80처럼 80번을 호스트 포트로 쓰면 실패합니다. 그래서 위 예제처럼 -p 8080:80로 1024 이상 포트를 씁니다.
  • 사용자 전환은 반드시 로그인 셸로 합니다. su - 사용자처럼 대시를 붙여야 해당 사용자의 환경변수(XDG_RUNTIME_DIR 등)가 제대로 잡힙니다. 이것이 어긋나면 rootless Podman이 동작하지 않습니다.

quadlet으로 systemd 연동 #

RHCSA의 컨테이너 영역에서 합격을 가르는 작업이 바로 이것입니다. “이 컨테이너를 systemd 서비스로 만들어 부팅 시 자동 실행하라"는 문제가 단골로 나옵니다. RHEL 9.3부터는 quadlet이 권장 방식입니다.

quadlet은 .container 파일에 컨테이너 정의를 적어 두면, systemd가 그것을 읽어 자동으로 서비스로 생성해 주는 구조입니다. 일반 사용자(rootless)라면 파일을 ~/.config/containers/systemd/ 아래에 둡니다.

# rootless 사용자의 quadlet 디렉터리 생성
mkdir -p ~/.config/containers/systemd

이제 .container 파일을 작성합니다. 파일 이름이 곧 서비스 이름이 됩니다. 예를 들어 web.containerweb.service가 됩니다.

# ~/.config/containers/systemd/web.container
[Container]
Image=registry.access.redhat.com/ubi9/httpd-24
PublishPort=8080:80
Volume=%h/web-content:/var/www/html:Z
Environment=KEY=VALUE

[Install]
WantedBy=default.target

각 키의 의미는 다음과 같습니다.

  • Image=. 사용할 이미지(레지스트리 경로까지 명시 권장)
  • PublishPort=. 포트 매핑(podman run -p에 해당)
  • Volume=. 볼륨 매핑(-v에 해당). %h는 사용자 홈 디렉터리로 확장되며, SELinux 때문에 :Z를 붙임
  • Environment=. 환경변수(-e에 해당)
  • [Install] WantedBy=. 자동 시작 대상. systemd가 이 서비스를 어떤 target에 연결할지 지정

파일을 만든 뒤에는 systemd에 새 정의를 읽히고 서비스를 시작합니다.

# quadlet 정의를 다시 읽어 서비스 생성 (rootless는 --user)
systemctl --user daemon-reload

# 서비스 시작 (파일명 web.container → 서비스명 web.service)
systemctl --user start web.service

# 상태 확인
systemctl --user status web.service

여기서 흔히 막히는 지점이 두 가지입니다.

  • quadlet 서비스는 systemctl --user enable을 직접 실행하지 않습니다. 자동 시작은 .container 파일의 [Install] WantedBy=로 결정되며, daemon-reload가 그것을 반영합니다. enable을 시도하면 “정적(static) 서비스라 enable할 수 없다"는 오류를 만날 수 있습니다.
  • 정의를 고친 뒤에는 반드시 daemon-reload를 다시 실행해야 변경이 반영됩니다.

loginctl enable-linger로 부팅 시 자동 시작 #

rootless 사용자의 systemd 서비스는 기본적으로 그 사용자가 로그인해 있을 때만 돌아갑니다. 로그아웃하면 사용자 서비스가 함께 종료되므로, 부팅 직후나 로그아웃 상태에서도 컨테이너가 떠 있게 하려면 linger를 켜야 합니다.

# 해당 사용자의 linger 활성화 (root 권한 필요)
sudo loginctl enable-linger appuser

# 또는 그 사용자 자신이 실행 가능
loginctl enable-linger

# 상태 확인 (Linger=yes 여야 함)
loginctl show-user appuser | grep Linger

enable-linger를 켜면 해당 사용자가 로그인하지 않아도 그 사용자의 systemd 인스턴스가 부팅 시 시작되고, 거기에 연결된 rootless 컨테이너 서비스도 함께 자동 실행됩니다. rootless 컨테이너를 부팅 시 자동 시작하라는 문제에서 이 단계를 빼면 재부팅 후 컨테이너가 뜨지 않아 실점합니다.

전체 흐름 정리 #

rootless 컨테이너를 systemd로 부팅 시 자동 실행하는 전체 절차를 한 번에 보면 다음과 같습니다.

# 1) 대상 사용자로 로그인 셸 진입
sudo su - appuser

# 2) quadlet 디렉터리와 .container 파일 작성
mkdir -p ~/.config/containers/systemd
vi ~/.config/containers/systemd/web.container

# 3) systemd에 정의 반영하고 시작
systemctl --user daemon-reload
systemctl --user start web.service

# 4) 부팅 시 자동 시작을 위해 linger 활성화
loginctl enable-linger

시험 포인트 #

RHCSA 컨테이너 영역에서 점수를 가르는 지점을 정리하겠습니다.

  • rootless는 su - 사용자로 로그인 셸 진입 후 sudo 없이 podman 실행. 대시를 빠뜨려 환경변수가 깨지는 실수가 잦습니다.
  • rootless는 1024 미만 호스트 포트를 못 씁니다. -p 8080:80처럼 1024 이상으로 매핑합니다.
  • 볼륨에는 :Z를 붙입니다. SELinux 컨텍스트 때문이며, 빼면 컨테이너가 볼륨에 접근하지 못합니다.
  • quadlet 파일은 rootless라면 ~/.config/containers/systemd/*.container에 둡니다. 파일명이 곧 서비스명입니다.
  • quadlet 서비스는 enable하지 않습니다. 자동 시작은 [Install] WantedBy=로 정하고, systemctl --user daemon-reload로 반영합니다.
  • 부팅 시 자동 실행에는 loginctl enable-linger가 필수입니다. 이 한 줄을 빠뜨리면 재부팅 후 컨테이너가 사라집니다.

특히 quadlet의 [Install] 섹션과 loginctl enable-linger 두 가지가 RHCSA 컨테이너 문제의 핵심 채점 포인트입니다. 컨테이너를 띄우는 데서 멈추지 말고, 재부팅 후에도 컨테이너가 살아 있는지 반드시 확인하겠습니다.

정리 #

이번 글에서 잡은 것:

  • Podman은 데몬 없는 rootless 컨테이너 엔진. 도커와 명령 호환성이 높고 systemd 연동에 자연스러움
  • 이미지 다루기. podman login registry.access.redhat.com으로 로그인, search,pull,images로 이미지 관리
  • 컨테이너 실행. run -d -p -v -e로 백그라운드,포트,볼륨,환경변수, ps,logs,exec,stop,rm로 운영
  • rootless. 일반 사용자로 로그인 셸 진입 후 sudo 없이 실행, 1024 이상 포트, 볼륨 :Z
  • quadlet 연동. ~/.config/containers/systemd/*.container[Container] 정의, systemctl --user daemon-reload + start
  • 부팅 시 자동 시작. loginctl enable-linger로 로그아웃 후에도 rootless 서비스 유지

컨테이너의 systemd 연동은 RHEL 심화 트랙에서 더 넓은 운영 맥락으로 이어집니다. RHCSA 범위에서는 quadlet과 linger로 재부팅 후 자동 실행을 만드는 것까지가 목표입니다.

다음: 시험 팁 #

이로써 RHCSA의 출제 영역을 모두 다뤘습니다. 도구와 스크립트, 부팅과 운영, 스토리지와 파일 시스템, 패키지와 네트워킹, 사용자와 보안, 그리고 이번 컨테이너까지 손으로 익혔습니다. 이제 남은 일은 이 작업들을 2.5시간 안에 정확히 끝내는 운영 감각을 다듬는 것입니다.

#15 시험 팁과 시간 관리, 자주 틀리는 패턴에서는 문제를 푸는 순서, 영구 적용을 놓치지 않는 점검 루틴, man page를 빠르게 찾는 법, 그리고 응시자들이 반복해서 틀리는 패턴을 정리해 합격선 210점을 안정적으로 넘기는 전략을 다루겠습니다.

X