LFCS 120분 종합 모의 B

공식 5개 domain을 섞은 20개 독립 실습 task를 120분에 구성·검증하는 두 번째 종합 모의


이 세트는 공개된 실제·복원·기출 문제가 아니다. Linux Foundation의 공개 domains & competencies를 조합해 독자적으로 만든 연습 task다. 실제 시험의 문제·배점·난이도를 보장하지 않는다.

작성·검증 상태: AI가 task 구성과 초안 작성을 보조했다. 공식 범위는 2026-08-13에 대조했지만 20개 task 전체를 한 번의 깨끗한 2노드 VM에서 아직 end-to-end 실행하지 않은 공개 전 초안이다.

진행 규칙

0~4분      host·disk·interface와 보호 대상 확인
4~104분    20개 task 수행
104~120분  표시한 문제와 상태·동작·영속성 검산
  • task별 추천 시간은 우선순위를 위한 학습 기준이다.
  • 처음 4분 안에 시작 경로를 찾지 못하면 표시하고 다음 task로 이동한다.
  • 접힌 답안과 기존 shell history를 보지 않는다.
  • local man page, command help, /usr/share의 설치 문서만 사용한다.
  • task에서 지정하지 않은 user·group·route·rule·service를 삭제하지 않는다.
  • 완료한 task에는 검증 command와 핵심 출력 한 줄을 남긴다.

실습 환경 전제

종합 모의시험 시작 상태의 30-mock-b-start snapshot을 사용하거나 표와 동일한 기능의 별도 fixture를 준비한다.

항목제공 상태
node1192.168.56.11, 관리 대상·client·proxy
node2192.168.56.12, DNS·NTP·NFS·iSCSI·HTTP backend
storage Anode1의 비어 있는 5 GiB disk /dev/sdb
storage Bnode1의 basevg/applv, ext4 1 GiB, /srv/appdata mount
networkmanagement connection과 별도 private lab connection
LDAPTLS CA, URI, base DN, alice account가 제공됨
libvirt/root/web01.xml과 disk image가 준비됨

실제 device·connection 이름이 다르면 task를 시작하기 전에 값만 치환한다. /dev/sdb가 정말 비어 있는 연습 disk가 아니면 이 세트를 실행하지 않는다.

Task 1 — account·group·profile·limit · 6분

node1에 다음 상태를 만들어라.

  • group release, GID 4810
  • user builder, UID 4810, home directory와 Bash login shell
  • builder를 기존 supplementary group을 보존하면서 release에 추가
  • 모든 새 login shell에서 RELEASE_ENV=staging
  • builder의 nofile: soft 2048, hard 4096

검증: getent, id, 새 login session의 environment와 limit.

Task 2 — shared directory·ACL·LDAP · 7분

node1에서 다음 상태를 만들어라.

  • /srv/reports는 root:release, mode 2770
  • local user auditor는 현재와 앞으로 생성되는 report를 읽고 경로에 진입할 수 있지만 수정할 수 없음
  • provided LDAP account alice가 getent passwd와 id에 나타남
  • LDAP login의 home directory가 첫 login 때 생성됨

기존 local administrator session과 인증 경로를 유지한다.

Task 3 — Git 변경 기록 · 4분

/srv/config-repo는 기존 Git repository다. app.conf, README.md, debug.log가 수정돼 있다.

  • app.conf와 README.md만 commit한다.
  • commit message는 Update application configuration이다.
  • debug.log는 수정 상태로 남겨 두고 commit하지 않는다.
  • 기존 branch와 history를 재작성하지 않는다.

검증: staged diff, latest commit과 남은 working-tree 변경.

Task 4 — custom systemd service · 6분

/usr/local/libexec/heartbeat가 foreground에서 실행되는 기존 executable이다. 다음 heartbeat.service를 만들어라.

  • builder account로 실행
  • /srv/heartbeat를 working directory로 사용
  • 실패할 때만 3초 후 재시작
  • network online 이후 시작
  • 현재 실행하고 boot 때 자동 시작

vendor unit directory는 수정하지 않는다. unit 문법과 process user를 검증한다.

Task 5 — disk space와 service constraint · 4분

logwriter.service가 No space left on device로 실패한다. 다음을 구분해 원인을 보고하고, 요구된 경우에만 안전하게 공간을 회수하라.

  • block capacity
  • inode exhaustion
  • 삭제됐지만 process가 열고 있는 file
  • 상위 directory permission과 service user

가장 큰 원인 객체와 관련 PID·service를 증거로 남긴다. /var/log 전체를 삭제하지 않는다.

Task 6 — private key와 CSR · 5분

node1에서 다음 파일을 생성하라.

  • private key: /etc/pki/tls/private/app.lab.example.key, RSA 2048 bit, unencrypted, mode 0600
  • CSR: /etc/pki/tls/certs/app.lab.example.csr
  • subject CN: app.lab.example
  • SAN: DNS:app.lab.example, IP:192.168.56.11

private key의 내용을 출력하지 말고 CSR subject·SAN과 key 일치를 검증한다.

Task 7 — LVM과 UUID mount · 7분

node1의 빈 /dev/sdb만 사용한다.

  • VG examvg
  • LV data, 1 GiB
  • XFS filesystem
  • /srv/examdata에 즉시 mount
  • filesystem UUID로 boot 후에도 mount

다른 disk와 기존 VG를 수정하지 않는다. mount -a와 findmnt로 검증한다.

Task 8 — 기존 LV·filesystem 확장 · 5분

기존 basevg/applv를 512 MiB만큼 확장하고 그 위 ext4 filesystem도 online으로 확장하라. /srv/appdata mount point와 기존 data를 유지한다.

검증: 변경 전후 LV size, filesystem size와 기존 test file checksum.

Task 9 — persistent swap·autofs · 5분

node1에서:

  • examvg에 512 MiB LV swaplv를 만들고 즉시·영구 swap으로 활성화
  • node2의 NFS export /srv/nfs/projects를 /net/projects에서 요청 시 mount
  • autofs idle timeout은 60초

일반 fstab NFS mount로 autofs를 대체하지 않는다.

Task 10 — NFS·iSCSI·storage diagnosis · 6분

node1에서:

  • node2 NFS export를 /mnt/team에 read-only로 즉시 mount하고 source·version·option 확인
  • node2 portal에서 target을 discovery·login하고 새 2 GiB block device를 식별
  • 새 device에 filesystem을 만들지 않음
  • 현재 filesystem의 block·inode 사용량과 I/O wait를 구분해 기록

iSCSI logout은 요구하지 않는다.

Task 11 — IPv4·IPv6·DNS·time · 6분

node1의 private connection을 다음 상태로 만들어라.

  • IPv4 192.168.56.11/24
  • IPv6 2001:db8:56::11/64
  • DNS 192.168.56.12, search domain lab.example
  • node2 192.168.56.12를 NTP source로 사용

management default route를 보존한다. app.lab.example의 NSS resolution과 실제 time source를 확인한다.

Task 12 — OpenSSH client·server · 5분

node1의 SSH server에서:

  • direct root login을 금지
  • public-key authentication을 허용
  • password authentication은 금지
  • 제공된 public key /root/builder_authorized_key.pub를 builder의 올바른 path와 permission으로 설치

syntax test 후 reload하고, 기존 session을 유지한 채 node2에서 builder key login 성공과 root login 실패를 검증한다.

Task 13 — static route·forwarding·source NAT · 6분

node1은 node2를 router로 사용한다.

  • node1에 198.51.100.0/24 via 192.168.56.12 persistent route 추가
  • node2에서 IPv4 forwarding을 즉시·영구 활성화
  • node2 private zone에서 198.51.100.0/24로 나가는 source NAT를 요구된 범위에만 적용

node1의 management default route와 node2의 기존 rule을 보존한다. ip route get, counter와 실제 packet으로 검증한다.

Task 14 — packet filter와 port redirection · 5분

node2에서:

  • private network의 TCP 8080 요청을 local backend 8081로 redirect
  • private network에서만 8080/tcp 접근 허용
  • runtime과 persistent 상태를 일치시킴

node1에서 HTTP 응답을 확인한다. 전체 ruleset을 flush하지 않는다.

Task 15 — bridge·bond·reverse proxy · 6분

node1의 제공된 추가 NIC를 사용한다.

  • br0와 그 port 하나를 persistent profile로 구성
  • bond0를 active-backup과 두 slave로 구성하고 active slave를 확인
  • 주소는 slave가 아니라 logical interface에 둠
  • nginx 8088/tcp가 node2의 8081, 8082 backend를 round-robin으로 proxy

management NIC는 bridge·bond의 member로 사용하지 않는다. nginx 문법과 backend 하나 중지 시 응답을 검증한다.

Task 16 — sysctl과 scheduled job · 4분

node1에서:

  • vm.swappiness=15를 즉시 적용
  • /etc/sysctl.d/91-mock.conf로 영구화
  • root의 cron으로 매 10분마다 /usr/bin/date -u를 /var/log/mock-time.log에 append

같은 sysctl key의 중복 설정과 cron 실행 환경을 확인한다.

Task 17 — package·repository·failed process · 5분

node1에서:

  • 활성 repository에서 haproxy의 후보 package를 찾고 설치
  • 설치 version과 package가 제공한 main configuration file 확인
  • service는 시작하지 않음
  • 별도로 실패 중인 reporter.service의 최초 exit code와 journal 원인을 찾아 /etc/reporter.conf의 잘못된 output path만 수정

package 설치와 service activation을 구분한다.

Task 18 — filesystem failure recovery · 5분

/etc/fstab.mock에는 기존 basevg/applv를 /mnt/recovery에 mount하는 entry가 있지만 UUID가 잘못되어 있다.

  • 실제 filesystem UUID와 type을 확인
  • mock file의 해당 entry만 수정
  • actual /etc/fstab을 변경하지 않음
  • mock table을 사용해 /mnt/recovery에 mount하고 기존 data 확인

OS disk와 mounted source에 offline repair를 실행하지 않는다.

Task 19 — libvirt domain · 5분

제공된 /root/web01.xml을 사용해:

  • domain을 persistent definition으로 등록
  • 현재 시작
  • host boot 때 autostart
  • block device와 interface 연결 확인

이미 같은 이름이 있으면 먼저 현재 definition을 확인하고 덮어쓰지 않는다. destroy를 정상 종료처럼 사용하지 않는다.

Task 20 — container와 SELinux · 6분

node1에서:

  • /srv/mockweb/index.html을 제공하는 container mockweb
  • host 8090/tcp → container 80/tcp
  • bind-mounted content는 container를 다시 만들어도 유지
  • SELinux Enforcing 유지
  • host directory에 영구적으로 적절한 content context 적용

container log·port·inspect와 실제 HTTP response를 확인한다. chmod 777이나 SELinux disable을 사용하지 않는다.

종료 전 검산

문제별 host와 요구를 다시 읽고 관련 항목만 확인한다.

systemctl --failed
findmnt --verify
mount -a
swapon --show
pvs; vgs; lvs
ip -brief address
ip route
ss -lntup
getenforce 2>/dev/null || true

추가 점검:

  • builder의 새 login environment·limit
  • auditor의 read 성공·write 실패와 new file ACL
  • Git에 debug.log가 commit되지 않음
  • systemd service의 user·active·enabled
  • NFS·iSCSI source와 device 식별
  • SSH positive·negative test
  • proxy backend 하나 실패 시 응답
  • container data와 SELinux context

자체 채점

각 task는 5점, 총 100점이다.

항목점수
핵심 요구 상태3
실제 동작·negative test1
영속성·기존 상태 보존1

학습 판정:

점수판정
80 이상, 고위험 실패 없음다음 mock으로 이동
67~79실패 domain의 단계별 실전 재수행
66 이하영역별 안내형 lab부터 복구

공식 합격선과 숫자가 같아도 이 자체 채점은 공식 scoring을 재현하지 않는다. Storage target 오류, management network 단절, 인증 lockout, SELinux disable 같은 고위험 실패가 있으면 총점과 관계없이 해당 domain을 다시 수행한다.

채점용 답안

20개 풀이 방향 열기 — 120분 종료 후 확인

1. account·group·profile·limit

groupadd -g 4810 release
useradd -u 4810 -m -s /bin/bash builder
usermod -aG release builder

printf 'export RELEASE_ENV=staging\n' > /etc/profile.d/release-env.sh
chmod 0644 /etc/profile.d/release-env.sh

cat > /etc/security/limits.d/90-builder.conf <<'EOF'
builder soft nofile 2048
builder hard nofile 4096
EOF

getent group release
id builder
su - builder -c 'printf "%s\n" "$RELEASE_ENV"; ulimit -Sn; ulimit -Hn'

2. shared directory·ACL·LDAP

getent passwd auditor >/dev/null || useradd -m -s /bin/bash auditor
install -d -o root -g release -m 2770 /srv/reports

# 기존 객체와 앞으로 생길 객체를 구분해 ACL을 적용한다.
find /srv/reports -type d -exec setfacl -m u:auditor:rx,d:u:auditor:rx {} +
find /srv/reports -type f -exec setfacl -m u:auditor:r-- {} +

runuser -u builder -- sh -c 'umask 0022; printf "report\n" > /srv/reports/new.txt'
getfacl /srv/reports /srv/reports/new.txt
runuser -u auditor -- test -r /srv/reports/new.txt
! runuser -u auditor -- sh -c 'printf x >> /srv/reports/new.txt'

LDAP는 제공된 URI·base DN·CA로 고급 사용자 lab의 SSSD 구성을 적용한다. getent passwd alice, id alice, sssctl user-checks alice와 별도 새 login의 home을 확인한다.

3. Git

cd /srv/config-repo
git status --short
git diff -- app.conf README.md debug.log
git add -- app.conf README.md
git diff --cached
git commit -m 'Update application configuration'
git show --stat --oneline HEAD
git status --short

4. custom service

# /etc/systemd/system/heartbeat.service
[Unit]
Description=Heartbeat service
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=builder
WorkingDirectory=/srv/heartbeat
ExecStart=/usr/local/libexec/heartbeat
Restart=on-failure
RestartSec=3s

[Install]
WantedBy=multi-user.target
install -d -o builder -g builder -m 0750 /srv/heartbeat
systemd-analyze verify /etc/systemd/system/heartbeat.service
systemctl daemon-reload
systemctl enable --now heartbeat.service
systemctl is-active heartbeat.service
systemctl is-enabled heartbeat.service
systemctl show heartbeat.service -p User -p MainPID
journalctl -u heartbeat.service -b --no-pager

5. disk space와 constraint

df -hT
df -i
findmnt -T /srv/mock-enospc/logwriter.log
df -hT /srv/mock-enospc
df -i /srv/mock-enospc
du -xah /srv/mock-enospc | sort -h | tail
lsof +L1
systemctl status logwriter.service --no-pager -l
systemctl show logwriter.service -p User -p Group
journalctl -u logwriter.service -b --no-pager
namei -l /srv/mock-enospc/logwriter.log

이 fixture의 실제 원인은 작은 loopback filesystem의 block capacity다. inode 여유와 root filesystem 여유를 함께 기록해 원인을 구분한다. deleted-open file이 다른 문제의 핵심 원인이면 관련 service를 정상 restart할 수 있는지 확인하고, data 보존 요구가 있으면 먼저 log copy 가능성을 판단한다. 결과는 같은 df·inode·service 동작으로 검증한다.

6. key와 CSR

test -d /etc/pki/tls/certs || install -d -m 0755 /etc/pki/tls/certs
test -d /etc/pki/tls/private || install -d -m 0700 /etc/pki/tls/private

openssl req -new -newkey rsa:2048 -nodes \
  -keyout /etc/pki/tls/private/app.lab.example.key \
  -out /etc/pki/tls/certs/app.lab.example.csr \
  -subj '/CN=app.lab.example' \
  -addext 'subjectAltName=DNS:app.lab.example,IP:192.168.56.11'

chmod 0600 /etc/pki/tls/private/app.lab.example.key
openssl req -in /etc/pki/tls/certs/app.lab.example.csr \
  -noout -subject -text | grep -A1 'Subject Alternative Name'

openssl pkey -in /etc/pki/tls/private/app.lab.example.key -pubout -outform DER 2>/dev/null | sha256sum
openssl req -in /etc/pki/tls/certs/app.lab.example.csr -pubkey -noout | \
  openssl pkey -pubin -outform DER 2>/dev/null | sha256sum

두 public-key digest가 같아야 한다.

7. LVM과 mount

lsblk -f
pvs; vgs; lvs
pvcreate /dev/sdb
vgcreate examvg /dev/sdb
lvcreate -L 1G -n data examvg
mkfs.xfs /dev/examvg/data
install -d -m 0755 /srv/examdata
blkid /dev/examvg/data

/etc/fstab에 UUID=<filesystem UUID> /srv/examdata xfs defaults 0 0을 추가한 뒤:

findmnt --verify
mount -a
findmnt /srv/examdata
lvs -o lv_name,vg_name,lv_size,devices

8. LV와 ext4 확장

sha256sum /srv/appdata/preserve.txt > /root/appdata.before.sha256
lvs basevg/applv
df -hT /srv/appdata
lvextend -L +512M /dev/basevg/applv
resize2fs /dev/basevg/applv
lvs basevg/applv
df -hT /srv/appdata
sha256sum -c /root/appdata.before.sha256

현재 filesystem type을 먼저 확인하고 XFS라면 resize2fs가 아니라 mount point를 대상으로 한 XFS grow 절차를 사용한다.

9. swap과 autofs

lvcreate -L 512M -n swaplv examvg
mkswap /dev/examvg/swaplv
swapon /dev/examvg/swaplv
blkid /dev/examvg/swaplv

swap UUID를 /etc/fstab에 UUID=<값> none swap defaults 0 0 형태로 추가하고 findmnt --verify로 검사한다. autofs:

# /etc/auto.master.d/projects.autofs
/- /etc/auto.projects --timeout=60

# /etc/auto.projects
/net/projects -fstype=nfs4,rw 192.168.56.12:/srv/nfs/projects
systemctl enable --now autofs
systemctl reload autofs
ls /net/projects
findmnt /net/projects
swapon --show

10. NFS·iSCSI·storage diagnosis

showmount -e 192.168.56.12
install -d -m 0755 /mnt/team
mount -t nfs -o ro,vers=4 192.168.56.12:/srv/nfs/projects /mnt/team
findmnt -no SOURCE,TARGET,FSTYPE,OPTIONS /mnt/team

lsblk -o NAME,PATH,SIZE,TYPE,FSTYPE,MOUNTPOINTS
iscsiadm -m discovery -t sendtargets -p 192.168.56.12:3260
iscsiadm -m node -T iqn.2026-08.example.lab:storage.lun0 \
  -p 192.168.56.12:3260 --login
iscsiadm -m session -P 1
ls -l /dev/disk/by-path | grep -i iscsi

df -hT
df -i
iostat -xz 1 3

11. address·DNS·time

nmcli connection modify PRIVATE_CONNECTION \
  ipv4.method manual ipv4.addresses 192.168.56.11/24 \
  ipv4.dns 192.168.56.12 ipv4.dns-search lab.example \
  ipv4.gateway '' ipv4.never-default yes ipv4.ignore-auto-dns yes \
  ipv6.method manual ipv6.addresses 2001:db8:56::11/64 \
  ipv6.dns 2001:db8:56::12 \
  ipv6.gateway '' ipv6.never-default yes ipv6.ignore-auto-dns yes
nmcli connection up PRIVATE_CONNECTION

ip -brief address
ip route
getent hosts app.lab.example

chrony source file의 지원 위치를 chrony.conf(5)에서 확인해 server 192.168.56.12 iburst를 추가하고 restart한다.

chronyd -p
systemctl restart chronyd
chronyc sources -v
chronyc tracking

12. SSH

server configuration은 package file 전체를 덮어쓰지 않고 지원되는 include directory의 전용 file을 우선한다. RHEL-compatible 환경에서 /etc/ssh/sshd_config가 sshd_config.d/*.conf를 include하는 것을 먼저 확인한 뒤 다음 내용을 /etc/ssh/sshd_config.d/60-lfcs-mock.conf에 둔다.

PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
install -d -o builder -g builder -m 0700 /home/builder/.ssh
install -o builder -g builder -m 0600 /root/builder_authorized_key.pub \
  /home/builder/.ssh/authorized_keys
restorecon -Rv /home/builder/.ssh 2>/dev/null || true
sshd -t
systemctl reload sshd
sshd -T | grep -E 'permitrootlogin|pubkeyauthentication|passwordauthentication'

node2에서 지정 private key로 builder login을 확인한다. root negative test는 인증이 실패하는지 확인하되 account lock이나 반복 시도를 만들지 않는다.

13. route·forwarding·NAT

# node1
nmcli connection modify PRIVATE_CONNECTION \
  +ipv4.routes '198.51.100.0/24 192.168.56.12'
nmcli connection up PRIVATE_CONNECTION
ip route get 198.51.100.2

node2:

sysctl -w net.ipv4.ip_forward=1
printf 'net.ipv4.ip_forward = 1\n' > /etc/sysctl.d/91-mock-forward.conf
sysctl -p /etc/sysctl.d/91-mock-forward.conf

private connection을 internal, fixture의 dst-host를 external zone에 연결한 예:

firewall-cmd --permanent --zone=internal --change-interface=PRIVATE_INTERFACE
firewall-cmd --permanent --zone=external --change-interface=dst-host
firewall-cmd --permanent --new-policy=mock-lab-to-dst
firewall-cmd --permanent --policy=mock-lab-to-dst --add-ingress-zone=internal
firewall-cmd --permanent --policy=mock-lab-to-dst --add-egress-zone=external
firewall-cmd --permanent --policy=mock-lab-to-dst --set-target=ACCEPT
firewall-cmd --permanent --policy=mock-lab-to-dst \
  --add-rich-rule='rule family="ipv4" source address="192.168.56.0/24" destination address="198.51.100.0/24" masquerade'
firewall-cmd --reload
firewall-cmd --info-policy mock-lab-to-dst

node1에서 ping 198.51.100.2를 실행하고 node2에서 ip netns exec lfcs-dst tcpdump -ni dst-ns icmp로 packet source가 node2의 downstream address로 변환되는지 관찰한다. nft list ruleset의 counter도 함께 확인한다. 현재 firewalld version이 policy rich rule을 지원하는지는 firewall-cmd --help, firewalld.richlanguage(5)와 firewalld.policy(5)에서 확인한다.

14. filter와 redirect

node2의 private connection이 속한 zone을 확인한 뒤:

firewall-cmd --permanent --zone=PRIVATE_ZONE --add-port=8080/tcp
firewall-cmd --permanent --zone=PRIVATE_ZONE \
  --add-forward-port=port=8080:proto=tcp:toport=8081
firewall-cmd --reload
firewall-cmd --zone=PRIVATE_ZONE --list-all
nft list ruleset

node1:

curl http://192.168.56.12:8080/

15. bridge·bond·proxy

interface 이름을 확인해 네트워킹 lab의 NetworkManager 흐름으로 br0, bond0와 port/slave를 만든다.

nginx upstream:

upstream mock_pool {
    server 192.168.56.12:8081 max_fails=1 fail_timeout=10s;
    server 192.168.56.12:8082 max_fails=1 fail_timeout=10s;
}

server {
    listen 8088;
    location / {
        proxy_pass http://mock_pool;
        proxy_next_upstream error timeout http_502 http_503;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
nginx -t
systemctl reload nginx
cat /proc/net/bonding/bond0
bridge link
curl http://127.0.0.1:8088/

16. sysctl과 cron

sysctl -w vm.swappiness=15
printf 'vm.swappiness = 15\n' > /etc/sysctl.d/91-mock.conf
sysctl -p /etc/sysctl.d/91-mock.conf
grep -R 'vm.swappiness' /etc/sysctl.conf /etc/sysctl.d 2>/dev/null

printf '*/10 * * * * root /usr/bin/date -u >> /var/log/mock-time.log 2>&1\n' \
  > /etc/cron.d/mock-time
chmod 0644 /etc/cron.d/mock-time
systemctl enable --now crond
systemctl is-active crond
systemctl is-enabled crond

17. package와 failed service

dnf repolist
dnf info haproxy
dnf install -y haproxy
rpm -qi haproxy
rpm -ql haproxy | grep -E '/etc/.*haproxy.*conf'
systemctl is-active haproxy

haproxy가 active이면 task의 “시작하지 않음” 조건을 위반한 것이다. is-active의 non-zero exit status 자체를 오류로 오해하지 않는다.

reporter.service:

systemctl status reporter.service --no-pager -l
systemctl show reporter.service -p ExecMainStatus -p User
journalctl -u reporter.service -b --no-pager
namei -l /srv/reporter-output/missing/summary.txt

오류와 존재하는 상위 directory를 대조해 /etc/reporter.conf를 OUTPUT=/srv/reporter-output/summary.txt로 수정한다. unit이나 executable은 바꾸지 않는다. systemctl restart reporter.service 뒤 exit status와 /srv/reporter-output/summary.txt 내용을 확인한다.

18. mock fstab recovery

lsblk -f
blkid /dev/basevg/applv
findmnt /srv/appdata
cp -a /etc/fstab.mock /etc/fstab.mock.before

mock file의 UUID와 filesystem type을 실제 값으로 고친 뒤:

install -d -m 0755 /mnt/recovery
findmnt --verify --tab-file /etc/fstab.mock
mount -a -T /etc/fstab.mock
findmnt /mnt/recovery
diff -u /etc/fstab.mock.before /etc/fstab.mock

source filesystem이 이미 다른 곳에 mounted되어 있을 때 동일 filesystem을 추가 mount하는 조건과 부수 효과를 확인한다.

19. libvirt

virsh list --all
if virsh dominfo web01 >/dev/null 2>&1; then
  virsh dumpxml web01 > /root/web01.existing.xml
  printf 'web01 already exists; compare the existing definition before continuing\n' >&2
else
  virsh define /root/web01.xml
fi
virsh start web01
virsh autostart web01
virsh dominfo web01
virsh domblklist web01
virsh domiflist web01

20. container와 SELinux

install -d -m 0755 /srv/mockweb
printf 'mock web\n' > /srv/mockweb/index.html

semanage fcontext -a -t container_file_t '/srv/mockweb(/.*)?'
restorecon -Rv /srv/mockweb

podman run -d --name mockweb -p 8090:80 \
  -v /srv/mockweb:/usr/share/nginx/html:Z \
  docker.io/library/nginx:stable-alpine

getenforce
ls -ldZ /srv/mockweb /srv/mockweb/index.html
podman ps --filter name=mockweb
podman port mockweb
podman inspect mockweb
podman logs mockweb
curl http://127.0.0.1:8090/

semanage fcontext·restorecon은 path의 영구 base type을 container_file_t로 만들고, :Z는 해당 container 전용 MCS label까지 적용한다. 둘의 역할을 matchpathcon /srv/mockweb/index.html과 실제 ls -Z로 구분한다. bind mount만 요구하는 task라면 engine의 SELinux volume option만으로도 동작할 수 있지만, 이 문제는 host path의 영구 context도 명시적으로 요구한다.

재도전 규칙

답안을 본 뒤 같은 snapshot에서 command만 고치지 않는다.

  1. 시작 snapshot으로 복원한다.
  2. user·group·path·size·port·address 중 최소 두 값을 바꾼다.
  3. task 순서를 섞는다.
  4. 답안과 shell history를 보지 않고 다시 120분을 잰다.
  5. 최종 준비도 점검에 Green·Yellow·Red만 기록한다.

참고 자료