LabHub
배우기 러닝패스 코스

LFCS — Linux Foundation認定システム管理者

systemd タイマーから podman まで — サービスとネットワークを実際に作る

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

systemd 서비스와 타이머, nginx 리버스 프록시, iptables DNAT/DROP, dummy 인터페이스 위의 브리지·본드와 netplan, chrony 와 시간대, git 병합, 레지스트리 없는 podman 이미지, 영구 sysctl, 부하 지표 — LFCS 의 Operations 와 Networking 도메인에서 파드가 막아 두었던 것을 우분투 24.04 VM 에서 실제로 실행합니다.

왜 중요한가

LFCS 는 "설명" 이 아니라 "결과" 를 봅니다. 유닛 파일을 잘 써도 systemctl is-enableddisabled 면 0점이고, nginx 설정이 문법적으로 맞아도 기본 사이트가 80 을 잡고 있으면 프록시는 동작하지 않습니다. 이 실습의 채점기는 파일만 보지 않고 systemctl is-active, curl, iptables -S, /sys/class/net, sysctl -n, podman inspect지금 시스템의 상태를 봅니다.

세 가지 원칙이 반복됩니다. 첫째, enable 과 start 는 다른 질문입니다(부팅 때 켤 것인가 / 지금 켜져 있는가). 둘째, 파일을 쓴 것과 커널·데몬이 아는 것은 다릅니다(sysctl --system, daemon-reload, nginx reload). 셋째, 되돌아갈 길을 남깁니다 — iptables 의 INPUT 기본 정책을 DROP 으로 바꾸거나 8899·22 를 막으면 채점 에이전트가 끊겨 다음 단계부터 원인 모를 실패가 납니다.

세션은 60분에 시작해 최대 180분까지 연장할 수 있고, VM 은 세션이 끝나면 사라집니다. 이 실습은 85분으로 잡혀 있으니 시작하면서 한 번 연장해 두세요.

단계

  1. /usr/local/bin/lfcs-heartbeat.sh 가 현재 시각을 /var/log/lfcs-heartbeat.log 에 한 줄 덧붙이게 만들고, 이것을 Type=oneshotlfcs-heartbeat.service 와 1분마다 그 서비스를 부르는 lfcs-heartbeat.timer/etc/systemd/system/ 에 작성하세요. 타이머는 enable 과 start 둘 다 되어 있어야 하고, 서비스를 한 번 직접 시작해 로그에 최소 한 줄이 있어야 합니다.
  2. /srv/backend/index.htmlbackend ok 라는 문구를 넣고, python3 -m http.server 8000 --directory /srv/backend 를 systemd 서비스 lfcs-backend.service 로 만들어 enable·start 하세요. 그런 다음 nginx 가 80 포트에서 이 백엔드로 리버스 프록시하도록 /etc/nginx/sites-available/lfcs-proxy 를 만들고 활성화(기본 사이트는 비활성화)하세요. curl http://127.0.0.1/backend ok 를 돌려줘야 합니다.
  3. iptables 로 두 규칙을 넣으세요. (1) nat 테이블 PREROUTING 에서 tcp 8080 으로 들어온 것을 80 으로 보내는 DNAT(또는 REDIRECT). (2) filter 테이블 INPUT 에서 tcp 9999 를 모든 인터페이스에서 DROP. INPUT 의 기본 정책은 ACCEPT 그대로 두고 8899 와 22 는 건드리지 마세요(채점 에이전트와 SSH). 마지막으로 iptables-save 출력을 /root/lfcs/net/rules.v4 에 저장하세요.
  4. 더미 인터페이스 dummy0, dummy1, dummy2 를 만드세요. 브리지 br0dummy0 을 넣고 br0192.0.2.1/24 를 주세요. 본드 bond0active-backup 모드로 만들어 dummy1dummy2 를 넣으세요(eth0 같은 실제 인터페이스는 건드리지 않습니다). 같은 구성을 netplan 문법으로 /root/lfcs/net/99-lab.yaml 에 적되 적용하지는 마세요.
  5. /etc/chrony/chrony.confserver time.cloudflare.com iburst 줄을 추가하고 chrony 를 재시작하세요. 시간대를 Asia/Seoul 로 바꾸세요. 그리고 chronyc sources/root/lfcs/time/sources.txt 에, chronyc tracking/root/lfcs/time/tracking.txt 에, timedatectl/root/lfcs/time/timedatectl.txt 에 저장하세요. (이 VM 은 UDP 123 이 막혀 있어 동기화 자체는 안 될 수 있습니다 — 설정과 상태가 채점 대상입니다.)
  6. /root/lfcs/repo 에 git 저장소를 만들고(기본 브랜치 main) README.md 를 커밋하세요. 브랜치 feature 에서 feature.txt 를 추가해 커밋한 뒤 main 으로 돌아와 병합 커밋이 남도록(--no-ff) 병합하세요. 작업 트리는 깨끗해야 합니다.
  7. /bin/busybox(busybox-static) 하나만 담은 루트 파일시스템을 tar 로 묶어 podman importlocalhost/lfcs-busybox:1 이미지를 만드세요(레지스트리에서 받지 않습니다). 그 이미지로 이름이 bb1 인 컨테이너를 --network none 으로 실행해 hello-from-busybox 를 출력하게 하고, 그 출력을 /root/lfcs/bb/run.txt 에 저장하세요. 컨테이너는 지우지 마세요(종료 코드가 0 이어야 합니다).
  8. /etc/sysctl.d/90-lfcs.confnet.ipv4.ip_forward = 1, vm.swappiness = 10, net.core.somaxconn = 1024 세 값을 적고 지금 커널에도 적용하세요. 적용 뒤 세 값을 sysctl 로 읽어 /root/lfcs/sysctl/runtime.txt 에 저장하세요.
  9. uptime 출력을 /root/lfcs/perf/uptime.txt 에, top -bn1 의 앞 15줄을 /root/lfcs/perf/top.txt 에 저장하세요. 그리고 /root/lfcs/perf/load.txt 를 두 줄로 만드세요: NPROC=<이 VM 의 CPU 개수>, LOAD1=<1분 로드 평균(/proc/loadavg 첫 값)>.

참고

서비스 유닛과 타이머

/usr/local/bin/lfcs-heartbeat.sh 가 현재 시각을 /var/log/lfcs-heartbeat.log 에 한 줄 덧붙이게 만들고, 이것을 Type=oneshotlfcs-heartbeat.service 와 1분마다 그 서비스를 부르는 lfcs-heartbeat.timer/etc/systemd/system/ 에 작성하세요. 타이머는 enable 과 start 둘 다 되어 있어야 하고, 서비스를 한 번 직접 시작해 로그에 최소 한 줄이 있어야 합니다.

타이머는 [Timer] 의 OnBootSec/OnUnitActiveSec 와 [Install] 의 WantedBy=timers.target 이 필요합니다. 유닛 파일을 쓰고 나면 daemon-reload 가 먼저입니다. is-enabled 와 is-active 는 다른 질문입니다.

nginx 리버스 프록시

/srv/backend/index.htmlbackend ok 라는 문구를 넣고, python3 -m http.server 8000 --directory /srv/backend 를 systemd 서비스 lfcs-backend.service 로 만들어 enable·start 하세요. 그런 다음 nginx 가 80 포트에서 이 백엔드로 리버스 프록시하도록 /etc/nginx/sites-available/lfcs-proxy 를 만들고 활성화(기본 사이트는 비활성화)하세요. curl http://127.0.0.1/backend ok 를 돌려줘야 합니다.

server 블록에 listen 80 default_server 와 location / { proxy_pass http://127.0.0.1:8000; } 이 핵심입니다. sites-enabled/default 를 지우지 않으면 두 default_server 가 충돌합니다. nginx -t 로 확인한 뒤 reload.

iptables 로 DNAT 와 DROP

iptables 로 두 규칙을 넣으세요. (1) nat 테이블 PREROUTING 에서 tcp 8080 으로 들어온 것을 80 으로 보내는 DNAT(또는 REDIRECT). (2) filter 테이블 INPUT 에서 tcp 9999 를 모든 인터페이스에서 DROP. INPUT 의 기본 정책은 ACCEPT 그대로 두고 8899 와 22 는 건드리지 마세요(채점 에이전트와 SSH). 마지막으로 iptables-save 출력을 /root/lfcs/net/rules.v4 에 저장하세요.

DNAT 는 -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination <이 VM 의 IP>:80 (또는 -j REDIRECT --to-ports 80). DROP 은 -A INPUT -p tcp --dport 9999 -j DROP. 자기 자신에게 보내는 패킷은 PREROUTING 을 안 지나므로 DNAT 는 규칙 존재로, DROP 은 127.0.0.1:9999 접속이 '거부' 가 아니라 '시간 초과' 인지로 확인합니다.

dummy 위의 브리지와 본드, 그리고 netplan

더미 인터페이스 dummy0, dummy1, dummy2 를 만드세요. 브리지 br0dummy0 을 넣고 br0192.0.2.1/24 를 주세요. 본드 bond0active-backup 모드로 만들어 dummy1dummy2 를 넣으세요(eth0 같은 실제 인터페이스는 건드리지 않습니다). 같은 구성을 netplan 문법으로 /root/lfcs/net/99-lab.yaml 에 적되 적용하지는 마세요.

ip link add <이름> type dummy|bridge|bond. 슬레이브는 ip link set master . 본드 슬레이브는 넣기 전에 down 이어야 합니다. 본드 모드는 /sys/class/net/bond0/bonding/mode 로 확인합니다.

chrony 와 시간대

/etc/chrony/chrony.confserver time.cloudflare.com iburst 줄을 추가하고 chrony 를 재시작하세요. 시간대를 Asia/Seoul 로 바꾸세요. 그리고 chronyc sources/root/lfcs/time/sources.txt 에, chronyc tracking/root/lfcs/time/tracking.txt 에, timedatectl/root/lfcs/time/timedatectl.txt 에 저장하세요. (이 VM 은 UDP 123 이 막혀 있어 동기화 자체는 안 될 수 있습니다 — 설정과 상태가 채점 대상입니다.)

timedatectl set-timezone Asia/Seoul. 우분투의 chrony 서비스 이름은 chrony 입니다. chronyc sources 의 첫 열이 ? 인 것은 아직 응답을 못 받았다는 뜻이고 여기서는 정상입니다.

git 기초 — 브랜치와 병합

/root/lfcs/repo 에 git 저장소를 만들고(기본 브랜치 main) README.md 를 커밋하세요. 브랜치 feature 에서 feature.txt 를 추가해 커밋한 뒤 main 으로 돌아와 병합 커밋이 남도록(--no-ff) 병합하세요. 작업 트리는 깨끗해야 합니다.

git init -b main. 커밋하려면 user.name/user.email 이 필요합니다(git config). 병합 커밋은 git log --merges 로 보입니다. fast-forward 로 병합하면 병합 커밋이 없습니다.

레지스트리 없이 podman 이미지 만들고 실행

/bin/busybox(busybox-static) 하나만 담은 루트 파일시스템을 tar 로 묶어 podman importlocalhost/lfcs-busybox:1 이미지를 만드세요(레지스트리에서 받지 않습니다). 그 이미지로 이름이 bb1 인 컨테이너를 --network none 으로 실행해 hello-from-busybox 를 출력하게 하고, 그 출력을 /root/lfcs/bb/run.txt 에 저장하세요. 컨테이너는 지우지 마세요(종료 코드가 0 이어야 합니다).

rootfs/bin/busybox 를 복사하고 tar -C rootfs -cf bb.tar . → podman import bb.tar localhost/lfcs-busybox:1. 실행은 podman run --name bb1 --network none localhost/lfcs-busybox:1 /bin/busybox echo hello-from-busybox. 이 실습의 podman 은 root 로 돕니다.

커널 파라미터를 영구로

/etc/sysctl.d/90-lfcs.confnet.ipv4.ip_forward = 1, vm.swappiness = 10, net.core.somaxconn = 1024 세 값을 적고 지금 커널에도 적용하세요. 적용 뒤 세 값을 sysctl 로 읽어 /root/lfcs/sysctl/runtime.txt 에 저장하세요.

sysctl --system 이 /etc/sysctl.d/*.conf 를 순서대로 읽어 적용합니다. 파일만 쓰면 재부팅 전까지 커널은 모릅니다. sysctl -n <키> 로 지금 값을 봅니다.

부하 지표 남기기

uptime 출력을 /root/lfcs/perf/uptime.txt 에, top -bn1 의 앞 15줄을 /root/lfcs/perf/top.txt 에 저장하세요. 그리고 /root/lfcs/perf/load.txt 를 두 줄로 만드세요: NPROC=<이 VM 의 CPU 개수>, LOAD1=<1분 로드 평균(/proc/loadavg 첫 값)>.

top -bn1 은 배치 모드로 한 번만 찍습니다. /proc/loadavg 의 첫 필드가 1분 평균이고, CPU 개수는 nproc 입니다. 로드 평균은 CPU 개수와 견줘야 의미가 있습니다.