Files
document-haness/docs/keycloak-session-store/tech-log-studio/operations-that-report-success/question/question-does-the-renewal-timer-actually-renew.md
T
DongHyeonkaandClaude Opus 5 2109f726fe feat(pipeline): keycloak-session-store 25편·virtualization 59편을 S3→S5→S6 으로 돌린다
기록 84편을 계약 에이전트로 다시 썼다. 기존 71편(kss 25 · virt 46)과, 계약에만
있고 안 쓰여 있던 새 글감 13편이다. 원장 84개를 열어 단계마다 스킬 영수증과 관문
종료 코드를 적었고 verify-pipeline-run.py 가 error 0 으로 닫는다.

SSOT 결함 둘을 고쳤다.

- kss 의 `약 58일` 이 반입 중 `약 59일` 로 바뀌어 있었다. 원 증거 파일이
  「남은 일수: 88일 … 실제 갱신까지 약 58일」로 산수를 직접 적는다. D-4a 쪽
  `약 59일` 은 강제 갱신 뒤(`VALID: 89 days`)라 맞는 값이라 그대로 뒀다.
- virt §198 의 `11.6GB` 는 §178 의 원 측정 `Mem: 11648`(MiB)과 어긋나는데
  원 가이드의 표기 그대로라 고치지 않고 쓰이는 자리에 대조를 적었다.

기록의 수치 오류 셋을 고쳤다 — CASE 요약의 「게스트 셋에 8240MB」(5120+3120 은
둘이다), k3s 편이 같은 것을 여섯·일곱·여덟로 세던 것, no-docker 편의 「셋을 더
든다」(§281 의 표는 네 행이고 디스크 행이 빠져 있었다).

계약을 셋 고쳤다.

- kss 의 sourceRepository 리비전이 cdac9b8 이었는데 그 커밋에는 docs/guides/**
  28개가 아예 없다. 9465582b 로 바꾸고, 반입한 바이트가 어느 커밋과도 같지 않다는
  것을 측정값과 함께 적었다 — 반입은 커밋이 아니라 그 시점의 작업 트리에서 떠 온
  것이다(kss 297/306 · virt 12/14 가 작업 트리와 같고, 200 커밋을 거슬러 전수
  대조했을 때 가장 가까운 커밋도 28개가 어긋났다).
- virt 계약이 「2026-09-11 재배분」이라고 적는데 SSOT 는 재배분 날짜를 적지 않고
  재배분 뒤 값은 이미 2026-09-10 측정에 찍혀 있다.
- kss 후보 대장이 지나친 절 아홉에 처분을 적었다(warn 9 → 0). 새 글감은 0건이고
  넷은 앵커가 h3 슬러그의 접두가 아니라 중간 토막이라 검사기가 못 본 것이었다.

style_profile.mjs 의 결함 둘을 고쳤다 — frontmatter 가 문장으로 세어져
(실측 398자짜리 「문장」 하나) 평균 길이를 기준 안으로 밀어 올리고 있었고,
engPerSent 의 분자는 목록을 포함한 글에서, 분모는 목록을 걷어낸 글에서 세고
있었다(Question 기록에서 11.94 → 3.86).

verify-pipeline.py 전 항목 PASS · error 0 · unittest 334건 OK.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 11:01:55 +09:00

6.3 KiB

kind, slug, title, topic, topicName, project, status, questionStatus, sourceRevision, source, evidence
kind slug title topic topicName project status questionStatus sourceRevision source evidence
QUESTION does-the-renewal-timer-actually-renew 갱신 타이머가 실제 갱신에서도 도는가 operations-that-report-success 운영 절차의 완료 판정 — 백업 · 판올림 · Secret · 인증서 갱신 keycloak-session-store 게시 전 OPEN cdac9b8178391311d8eca1ebc6cac15bb62d79af
final/document.md#얻은-것-잃은-것-적용하지-않을-때-재보지-않은-것
final/document.md#선택이-코드와-흐름에-반영되는-방식-d4a
../../../final/evidence/raw/d4-certificate-renewal__07-renewal-hook-missing.txt
../../../final/evidence/raw/d4-certificate-renewal__12-certbot-state.txt
../../../final/evidence/raw/d4-certificate-renewal__13-verdict.txt
../../../final/evidence/raw/d4a-deploy-hook__01-hook-verified.txt
../../../final/evidence/raw/d4a-deploy-hook__03-after-state.txt

갱신 타이머가 실제 갱신에서도 도는가

deploy 훅은 강제 갱신으로만 검증했고, 타이머가 스스로 갱신하는 날도 그 훅이 도는지는 재지 않았다. 만료 30일 전에야 조건이 성립해 약 59일 뒤에나 시험할 수 있다. 그때까지 타이머는 매번 SUCCESS 를 찍는다.

관계

  • 새 인증서가 디스크에 있고 38분 25초 동안 옛 인증서가 나갔다 이 질문이 나온 결함이다. reload 를 부르는 경로가 셋 다 비어 있었다.
  • deploy 훅 하나가 그 공백을 1~2초로 줄였다 그 훅을 강제 갱신으로만 시험했고, 타이머 경로는 남겨 두었다.

사실

  • certbot-renew.timer 는 하루 두 번 도는 일정으로 잡혀 있다. RandomizedDelaySec : 12h Persistent : true
  • 2026-09-04 에 그 타이머가 두 번 돌았고 둘 다 status=0/SUCCESS 로 끝났다.
  • 같은 날 서빙 인증서는 만료까지 88일 남아 있었다. 두 번의 SUCCESS 는 갱신을 하지 않은 채 끝난 것이다.
  • certbot 의 인증서 상태 출력이 남은 일수를 VALID: 89 days 로 찍었다. 89일은 만료까지 남은 일수다. 다만 그 출력은 D-4 의 강제 갱신이 만든 인증서를 본 것이고, D-4a 가 다시 받은 인증서에 대해서는 같은 출력이 증거에 없다. 두 장은 만료 시각이 다르다. certbot 은 30일 남았을 때 갱신하므로 갱신 조건은 약 59일 뒤에 성립한다.
  • D-4 에서 새 인증서가 디스크에 기록된 시각과 실제 서빙이 바뀐 시각 사이가 2305초, 38분 25초 비었다. 그 사이 428회 관측했다.
  • 그때 reload 를 건 것은 사람이었다. certbot-renew.service 에 ExecStartPost 가 없었고 renewal-hooks 의 deploy · post · pre 세 디렉터리가 다 비어 있었으며 certbot 의 nginx 플러그인도 없었다.
  • D-4a 에서 deploy 훅 하나를 넣고 강제 갱신하자 갱신에서 서빙까지가 1~2초로 줄었다.
  • 누가 reload 를 걸었는지는 워커 프로세스 번호(PID)로 갈린다. 사람이 걸었을 때 28829, 훅이 걸었을 때 37252 였고 마스터 585 는 그대로였다.
  • 훅이 돌 때 certbot 은 Hook 'deploy-hook' ran with error output 을 찍었다. 실패는 아니었고 nginx 의 types_hash 경고가 stderr 로 나간 것이며 내용은 test is successful · signal process started 였다.

가정

  • 타이머가 스스로 갱신하는 경로도 같은 certbot renew 를 부르고 같은 deploy/ 훅을 실행한다. 이 실험대의 기록이 그렇게 판단했고, 그 판단대로라면 남은 미지수는 타이머가 뜨는가 하나이며 그것은 D-4 에서 확인됐다. 훅 실행까지 같다는 부분은 실행으로 확인하지 않았다.
  • 갱신일까지 아무도 이 호스트의 타이머 유닛과 훅 파일을 건드리지 않는다.

미지수

  • 타이머가 실제 갱신을 수행하는 날에도 deploy/ 훅이 도는가. 이 실험대가 훅을 확인한 경로는 --force-renewal 하나뿐이다.
  • --dry-run 에서 Running deploy-hook command 줄이 나오는가. 강제 갱신으로 바로 검증하는 바람에 dry-run 경로 자체를 거치지 않았다.
  • 훅이 실제로 실패하면 certbot 이 무엇을 찍는가. 성공한 훅의 출력만 봤다.
  • 훅이 /tmp 에 로그를 남기도록 만들면 타이머가 돌렸을 때 그 파일을 밖에서 찾을 수 있는가. certbot-renew.service 는 PrivateTmp=true 이고, 이 실험은 훅에 로그를 넣지 않았다.

제약

  • 만료 30일 전에야 갱신 조건이 성립하므로 실제 갱신은 약 59일 뒤다. 다만 기다리는 것 말고도 이 실험대가 적어 둔 길이 하나 있다 — certbot renew --dry-run 은 인증서를 발급하지 않고 발급 한도도 깎지 않으면서 훅이 호출되는지까지는 보여 준다.
  • 강제 갱신으로는 이 질문에 답할 수 없다. 그 경로는 D-4a 에서 이미 검증했고, 지금 묻는 것은 타이머가 스스로 도는 경로다.
  • deploy 훅 파일은 지우지 않고 남긴다. 지우면 D-4 의 상태로 돌아간다.
  • 발급 한도가 있다. 강제 갱신을 쓸 때는 이번 주에 몇 장 발급했는지 센다.

선택지

갱신일이 와야 끝까지 시험할 수 있지만 그 전에 고를 수 있는 것이 하나 있다.

certbot renew --dry-run 을 먼저 돌려 훅이 호출되는지만 본다 : 발급도 한도 소모도 없다. 다만 실제 갱신에서 훅이 무엇을 받는지까지는 답하지 않는다. 이 실험대는 이 줄을 미검증으로 표시했고 돌리지 않았다.

약 59일을 기다렸다가 실제 갱신을 본다 : 이 질문에 온전히 답하는 유일한 경로다.

다음 검증

약 59일 뒤, 만료 30일 전 조건이 성립해 타이머가 갱신을 수행한 날에 두 가지를 읽는다.

  1. nginx 워커의 lstart 를 읽어 갱신 시각 근처인지 본다. 마스터는 그대로이고 워커만 새것이어야 한다.
  2. 서빙 인증서의 serial 과 notAfter 를 읽어 notAfter 가 밀렸는지 본다.

판정은 이 둘로 한다. certbot 이 찍는 문구로는 갈리지 않는다 — D-4a 에서 ran with error output 은 실패가 아니었다.

닫는 조건 : 워커 PID 가 바뀌고 서빙 일련번호가 새 인증서와 같으면 닫는다. 그렇지 않으면 훅이 강제 갱신에서만 도는 것이므로 타이머 유닛 쪽에 훅을 다시 건다.