LFCS 120분 종합 모의 실습
여러 도메인을 섞어 문제 해석, 상태 구성과 최종 검증까지 연습하는 120분 시나리오
이 문서는 LFCS 실제·복원·기출 문제가 아니다. 공개된 공식 competency를 섞어 독자적으로 만든 연습 세트다. 실제 시험과 문제 수·난이도·채점 방식이 같다고 가정하지 않는다.
작성·검증 상태: AI가 문제·풀이 구조화를 보조했다. domain을 섞는 학습용 시나리오이며 전체 세트를 동일 VM에서 end-to-end 실행한 공개 검증 기록은 아직 없다.
진행 방법
전체 120분을 다음처럼 나눈다.
0~5분 기준 상태와 대상 호스트 확인
5~105분 10개 문제 수행
105~120분 미완료 문제와 영속성·부수 효과 재검증
규칙:
- 풀이 예시는 끝날 때까지 열지 않는다.
- 각 문제를
대상·동작·조건·지속성·검증으로 분해한다. - 4분 동안 시작 방법도 찾지 못하면 표시하고 다음 문제로 이동한다.
- 삭제·포맷·네트워크 변경 전에는 대상과 복구 경로를 확인한다.
- 완료한 문제에는 검증 명령과 핵심 출력 한 줄을 남긴다.
실습 환경 전제
- 검사점으로 되돌릴 수 있는 Linux VM 2대:
node1,node2 - OS와 분리된 빈 보조 디스크 1개
node1콘솔 접근 가능node2에는deploy사용자와 연습용 HTTP backend가 준비됨- 패키지는 배포판 기본 저장소에서 설치 가능
환경이 다르면 이름·장치·주소를 바꾸되 문제의 요구 상태는 유지한다.
문제 1. 협업 계정과 ACL — 10분
node1에서 다음 상태를 만들어라.
ops그룹과operator사용자를 만든다.operator의 기본 shell은 Bash이며 홈 디렉터리가 있어야 한다./srv/ops는root:ops, mode2770이다.auditor사용자는 파일을 수정하지 못하고 읽기·진입만 할 수 있다.- 앞으로 생성되는 항목에도
auditor의 읽기 권한이 적용돼야 한다.
검증: id, stat, getfacl, 실제 사용자 파일 생성·읽기.
풀이 방향
groupadd ops
useradd -m -s /bin/bash operator
getent passwd auditor >/dev/null || useradd -m -s /bin/bash auditor
usermod -aG ops operator
install -d -o root -g ops -m 2770 /srv/ops
setfacl -m u:auditor:rx,d:u:auditor:rx /srv/ops
runuser -u operator -- touch /srv/ops/report.txt
id operator
stat -c '%A %a %U:%G %n' /srv/ops /srv/ops/report.txt
getfacl /srv/ops /srv/ops/report.txt
runuser -u auditor -- test -r /srv/ops/report.txt && echo readable
파일의 default ACL은 실제 생성 mode와 ACL mask의 영향도 받으므로 getfacl 결과를 확인한다.
문제 2. 환경과 resource limit — 8분
operator의 새 로그인 shell에만 다음을 적용하라.
EDITOR=vim- PATH 앞에
/opt/ops/bin추가 - open files soft
2048, hard4096
현재 shell이 아니라 새 session에서 결과를 확인한다.
풀이 방향
사용자 전용 환경은 홈의 login profile에 두고, limit은 PAM limits 설정에 둔다.
cat >> /home/operator/.bash_profile <<'PROFILE'
export EDITOR=vim
case ":$PATH:" in
*:/opt/ops/bin:*) ;;
*) export PATH="/opt/ops/bin:$PATH" ;;
esac
PROFILE
chown operator:operator /home/operator/.bash_profile
# /etc/security/limits.d/operator.conf
operator soft nofile 2048
operator hard nofile 4096
runuser -l operator -c 'printf "%s\n%s\n" "$EDITOR" "$PATH"; ulimit -Sn; ulimit -Hn'
문제 3. Git 변경 기록 — 7분
/srv/config-repo 저장소에서 다음을 수행하라.
- 현재 변경과 branch를 확인한다.
service.conf만feature/timeoutbranch에 commit한다.notes.tmp는 commit에 포함하지 않는다.main에 병합하고 최근 이력을 그래프로 확인한다.
풀이 방향
cd /srv/config-repo
git status
git diff -- service.conf
git config user.name >/dev/null || git config user.name "LFCS Lab"
git config user.email >/dev/null || git config user.email "lfcs@example.invalid"
git switch -c feature/timeout
git add service.conf
git diff --cached
git commit -m 'Adjust service timeout'
git switch main
git merge feature/timeout
git status
git log --oneline --graph -5
문제 4. custom systemd 서비스 — 12분
/usr/local/bin/write-heartbeat.sh가 15초마다 현재 시각을 출력하도록 작성하고 heartbeat.service로 관리하라.
operator로 실행한다.- 실패 시 3초 후 재시작한다.
- 지금 실행하고 부팅 시에도 자동 시작한다.
- unit 문법, 실행 사용자, 상태와 journal을 확인한다.
풀이 방향
cat > /usr/local/bin/write-heartbeat.sh <<'SCRIPT'
#!/bin/bash
while true; do
echo "$(date -Is) heartbeat"
sleep 15
done
SCRIPT
chmod 755 /usr/local/bin/write-heartbeat.sh
restorecon -v /usr/local/bin/write-heartbeat.sh
# /etc/systemd/system/heartbeat.service
[Unit]
Description=LFCS heartbeat practice
[Service]
User=operator
ExecStart=/usr/local/bin/write-heartbeat.sh
Restart=on-failure
RestartSec=3
[Install]
WantedBy=multi-user.target
systemd-analyze verify /etc/systemd/system/heartbeat.service
systemctl daemon-reload
systemctl enable --now heartbeat.service
systemctl is-enabled heartbeat.service
systemctl is-active heartbeat.service
systemctl show heartbeat.service -p User -p MainPID
journalctl -u heartbeat.service -n 5 --no-pager
문제 5. LVM과 영구 마운트 — 12분
빈 보조 디스크를 사용해 다음 상태를 만들어라.
- VG
vgdata - LV
lvapp, 크기 1GiB - 파일시스템은 환경에서 지원되는 ext4 또는 XFS
/srv/appdata에 UUID로 영구 마운트- 이후 LV와 파일시스템을 512MiB 확장
풀이 방향
먼저 OS 디스크가 아닌 빈 장치를 정확히 식별한다.
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS
findmnt
pvs; vgs; lvs
장치를 /dev/sdb라고 확인한 경우의 예다.
pvcreate /dev/sdb
vgcreate vgdata /dev/sdb
lvcreate -L 1G -n lvapp vgdata
mkfs.xfs /dev/vgdata/lvapp
install -d /srv/appdata
blkid /dev/vgdata/lvapp
조회한 UUID로 다음 형식의 항목을 /etc/fstab에 추가한다.
cp -a /etc/fstab /etc/fstab.before-lfcs-mixed
UUID=<조회한-UUID> /srv/appdata xfs defaults 0 0
UUID로 /etc/fstab에 추가한 뒤:
mount -a
findmnt /srv/appdata
lvextend -L +512M /dev/vgdata/lvapp
xfs_growfs /srv/appdata
lvs
df -hT /srv/appdata
ext4를 만들었다면 확장 단계에서 resize2fs /dev/vgdata/lvapp를 사용한다. pvcreate와 mkfs는 데이터를 파괴하므로 장치 확인 없이 실행하지 않는다.
문제 6. 정적 네트워크와 route — 10분
콘솔을 사용할 수 있는 격리된 실습 NIC에 다음을 영구 설정하라.
- IPv4
192.0.2.10/24 - gateway
192.0.2.1 - DNS
192.0.2.53 198.51.100.0/24는192.0.2.254를 next hop으로 사용
주소, route 선택과 이름 해석 설정을 확인한다.
풀이 방향
연결 이름을 먼저 찾는다.
nmcli connection show
nmcli device status
연결 이름이 lab-static이라고 확인한 예:
nmcli connection modify lab-static \
ipv4.method manual \
ipv4.addresses 192.0.2.10/24 \
ipv4.gateway 192.0.2.1 \
ipv4.dns 192.0.2.53 \
ipv4.route-metric 500 \
+ipv4.routes '198.51.100.0/24 192.0.2.254'
nmcli connection up lab-static
ip -br address
ip route
ip route get 198.51.100.10
nmcli device show
원격 SSH를 제공하는 유일한 NIC에서 그대로 실행하지 않는다. 연결·장치 이름을 같다고 가정하지 않는다.
문제 7. OpenSSH 키 인증 — 10분
node1에서 node2의 deploy 사용자로 키 인증할 수 있게 하라.
- 새 Ed25519 키를 사용한다.
- 서버의
.ssh와authorized_keys권한이 안전해야 한다. - server 설정 문법을 검사한 뒤 reload한다.
- 별도 session에서 키 인증과 로그를 확인한다.
풀이 방향
install -d -m 700 ~/.ssh
ssh-keyscan -t ed25519 node2 > /tmp/node2.hostkey
ssh-keygen -lf /tmp/node2.hostkey
# node2 콘솔의 `ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub` 결과와 비교한 뒤:
cat /tmp/node2.hostkey >> ~/.ssh/known_hosts
chmod 600 ~/.ssh/known_hosts
ssh-keygen -t ed25519 -f ~/.ssh/lfcs_deploy
ssh-copy-id -i ~/.ssh/lfcs_deploy.pub deploy@node2
ssh -i ~/.ssh/lfcs_deploy -o IdentitiesOnly=yes deploy@node2 id
서버에서:
namei -l /home/deploy/.ssh/authorized_keys
sshd -t
sshd -T | grep -E 'pubkeyauthentication|passwordauthentication'
구문 검사가 통과한 뒤 배포판에 맞는 service를 reload하고 로그를 확인한다.
# Rocky/RHEL
systemctl reload sshd
journalctl -u sshd -n 20 --no-pager
# Debian/Ubuntu
systemctl reload ssh
journalctl -u ssh -n 20 --no-pager
비밀번호 인증을 끄는 요구가 추가되더라도 새 키 로그인을 별도 session에서 성공시킨 뒤 기존 접근을 제한한다.
문제 8. 컨테이너와 SELinux — 12분
node1의 /srv/site/index.html을 제공하는 site 컨테이너를 실행하라.
- 호스트
8080→ 컨테이너80 - bind mount의 콘텐츠가 영구적으로 남아야 함
- SELinux Enforcing 유지
- 컨테이너 상태, port, label, log와 실제 HTTP 응답 확인
풀이 방향
podman ps -a --filter name=site
ss -lntp | grep ':8080' || true
install -d -m 755 /srv/site
printf 'LFCS mixed lab\n' > /srv/site/index.html
podman run -d --name site -p 8080:80 \
-v /srv/site:/usr/share/nginx/html:Z \
docker.io/library/nginx:stable-alpine
podman ps --filter name=site
podman port site
podman inspect site
podman logs site
ls -ldZ /srv/site
curl http://127.0.0.1:8080
문제 9. 디스크 공간과 성능 진단 — 7분
/var 사용률이 높고 응답이 느리다는 신고가 들어왔다. 변경이나 삭제 없이 다음을 구분해 기록하라.
- block 공간과 inode
- 같은 filesystem 안의 큰 경로
- 삭제됐지만 열린 파일
- I/O를 많이 만드는 장치와 프로세스
풀이 방향
findmnt /var
df -hT /var
df -i /var
du -xhd1 /var | sort -h
lsof -a +L1 /var
vmstat 1 5
iostat -xz 1 5
pidstat -d 1 5
iostat·pidstat는 sysstat 패키지가 필요할 수 있다. 진단 전에 로그나 대형 파일을 삭제하지 않는다.
문제 10. 인증서와 reverse proxy — 12분
api.example.test용 private key와 CSR을 만들고 SAN을 확인하라. 이어서 미리 실행 중인 127.0.0.1:9000 backend를 Nginx가 8081에서 reverse proxy하도록 구성하라.
완료 조건
- private key 권한은
0600이다. - CSR의 subject와 SAN이 올바르다.
- key와 CSR의 public key가 일치한다.
- backend 직접 응답과 proxy 응답을 모두 확인했다.
- Nginx 문법 검사 뒤 reload했다.
풀이 방향
install -d -m 700 /root/lfcs-cert
cd /root/lfcs-cert
openssl req -new -newkey rsa:2048 -nodes \
-keyout api.example.test.key \
-out api.example.test.csr \
-subj '/CN=api.example.test' \
-addext 'subjectAltName=DNS:api.example.test'
chmod 600 api.example.test.key
openssl req -in api.example.test.csr -noout -text
openssl pkey -in api.example.test.key -pubout -outform DER | sha256sum
openssl req -in api.example.test.csr -pubkey -noout | \
openssl pkey -pubin -outform DER | sha256sum
Nginx server block 핵심:
server {
listen 8081;
server_name api.example.test;
location / {
proxy_pass http://127.0.0.1:9000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
curl http://127.0.0.1:9000/
nginx -t
systemctl reload nginx
ss -lntp | grep ':8081'
curl -H 'Host: api.example.test' http://127.0.0.1:8081/
journalctl -u nginx -n 20 --no-pager
마지막 15분 검산
문제별로 다음을 확인한다.
| 검증 층 | 질문 |
|---|---|
| 상태 | 이름, 주소, 권한, 크기와 설정값이 정확한가? |
| 동작 | 실제 사용자·client·process로 성공하는가? |
| 지속성 | 새 session, service enable, fstab·connection profile에 남는가? |
| 부수 효과 | 기존 그룹, route, 서비스, 디스크를 바꾸지 않았는가? |
systemctl --failed
findmnt --verify
ip route
ss -lntup
미완료 문제는 명령 개수보다 문제 해석·명령 탐색·설정·실행·검증 중 어디에서 막혔는지 기록한다. 그 층만 보충한 뒤 초기 상태에서 다시 120분 세트를 수행한다.