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를 준비한다.
| 항목 | 제공 상태 |
|---|---|
| node1 | 192.168.56.11, 관리 대상·client·proxy |
| node2 | 192.168.56.12, DNS·NTP·NFS·iSCSI·HTTP backend |
| storage A | node1의 비어 있는 5 GiB disk /dev/sdb |
| storage B | node1의 basevg/applv, ext4 1 GiB, /srv/appdata mount |
| network | management connection과 별도 private lab connection |
| LDAP | TLS 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, GID4810 - user
builder, UID4810, home directory와 Bash login shell builder를 기존 supplementary group을 보존하면서release에 추가- 모든 새 login shell에서
RELEASE_ENV=staging builder의nofile: soft2048, hard4096
검증: getent, id, 새 login session의 environment와 limit.
Task 2 — shared directory·ACL·LDAP · 7분
node1에서 다음 상태를 만들어라.
/srv/reports는root:release, mode2770- 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를 만들어라.
builderaccount로 실행/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, mode0600 - 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 LVswaplv를 만들고 즉시·영구 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 domainlab.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.12persistent 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 backend8081로 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,8082backend를 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을 제공하는 containermockweb- host
8090/tcp→ container80/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·limitauditor의 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 test | 1 |
| 영속성·기존 상태 보존 | 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만 고치지 않는다.
- 시작 snapshot으로 복원한다.
- user·group·path·size·port·address 중 최소 두 값을 바꾼다.
- task 순서를 섞는다.
- 답안과 shell history를 보지 않고 다시 120분을 잰다.
- 최종 준비도 점검에 Green·Yellow·Red만 기록한다.