Repository navigation
EXPIRE_SESSIONS_JOB
orchestration-server의 비활성 세션(24시간 이상last_activity_at갱신 없음)을 자동 종료(users.ended_at세팅)하는 K8s CronJob.소스:
orchestration-server/cmd/expire-sessions,Dockerfile.expire-sessions차트:devops/charts/job
orchestration-server는 세션(=사용자, users 테이블) 활성 상태를 두 가지 방식으로 관리한다.
| 방식 | 위치 | 주기 | 비고 |
|---|---|---|---|
| 인메모리 정리 루프 |
internal/mqttx/session_store.go SessionStore.StartCleanup
|
1분 | 서버 프로세스가 떠 있는 동안만 동작 |
| K8s CronJob (이 문서) | cmd/expire-sessions |
스케줄 설정값 (기본 매시 13분) | 서버 재시작 직후 공백 구간, 인메모리 상태 유실 등을 커버하는 이중 안전망 |
두 메커니즘 모두 같은 규칙을 쓴다: ended_at IS NULL AND last_activity_at < now - TTL 인 사용자를 ended_at = now로 종료 처리.
주의:
ended_at을 세팅해도 MQTT 핸들러(task/start,task/complete,task/skip등)는 현재ended_at을 체크하지 않는다. 디바이스가 만료된 세션 ID로 계속 발행하면 서버는 여전히 처리한다 — 별도 이슈로 트래킹 중, 아직 미해결.
orchestration-server/.github/workflows/ci.yml의 expire-sessions-docker-build 잡이
main/master/develop 브랜치 푸시마다 자동으로:
-
Dockerfile.expire-sessions로 이미지 빌드 -
ghcr.io/<repository_owner>/orchestration-server-expire-sessions:latest로 태깅 - GHCR에 푸시 (버전 태그 없음, latest 단일 태그 — 용량 절약을 위해 backend/backoffice 이미지와 동일한 정책)
수동으로 로컬 빌드하려면:
cd orchestration-server
docker build -f Dockerfile.expire-sessions -t orchestration-server-expire-sessions:local .차트: devops/charts/job — 상시 서비스(infra, backoffice)와 분리된 배치 전용 chart.
기본값은 expireSessions.enabled: false이므로 필요한 클러스터에서만 명시적으로 켠다.
이 배치는 클러스터 내부 infra chart의 DB를 보지 않는다. 외부(운영) DB 주소를
직접 넘겨야 한다. 두 가지 방법:
A. 이미 존재하는 Secret 참조 (권장 — values에 평문 노출 없음)
kubectl create secret generic expire-sessions-db -n oc \
--from-literal=database-url='postgres://user:pass@external-db.example.com:5432/orchestration?sslmode=require'
helm install job ./charts/job -n oc --create-namespace \
--set expireSessions.enabled=true \
--set database.existingSecret.name=expire-sessions-db \
--set database.existingSecret.key=database-urlB. URL 값을 바로 넘겨서 chart가 Secret 생성
helm install job ./charts/job -n oc --create-namespace \
--set expireSessions.enabled=true \
--set database.url='postgres://user:pass@external-db.example.com:5432/orchestration?sslmode=require'
-n oc는 예시 namespace다. 어떤 namespace를 쓰든 Secret과 이 chart는 반드시 같은 namespace에 있어야 한다. namespace는 설치 후엔 못 옮기니(5.4 참고) 처음부터 정해서 시작하는 게 좋다.
| 키 | 기본값 | 설명 |
|---|---|---|
expireSessions.enabled |
false |
CronJob 생성 여부 |
expireSessions.image.repository |
ghcr.io/zero1ne-26/orchestration-server-expire-sessions |
이미지 |
expireSessions.image.tag |
latest |
태그 |
expireSessions.schedule |
"13 * * * *" |
매시 13분 (정각 부하 회피) |
expireSessions.sessionTtlHours |
24 |
비활성 허용 시간 |
expireSessions.concurrencyPolicy |
Forbid |
이전 실행이 안 끝났으면 새 실행 스킵 |
expireSessions.activeDeadlineSeconds |
120 |
잡이 이 시간 넘게 돌면 강제 종료 |
expireSessions.backoffLimit |
2 |
실패 시 재시도 횟수 |
database.url / database.existingSecret.*
|
"" |
위 3.1 참고 |
값을 바꾸고 싶으면 --set key=value를 추가하거나 -f my-values.yaml로 오버라이드한다.
# CronJob 등록 확인
kubectl get cronjob -n oc
# 스케줄을 기다리지 않고 즉시 1회 실행해보기
kubectl create job --from=cronjob/job-expire-sessions manual-test-run -n oc
# 실행 로그 확인 (JSON 구조화 로그, expired 필드로 처리 건수 확인)
kubectl logs job/manual-test-run -n oc
# 과거 실행 이력 (successfulJobsHistoryLimit/failedJobsHistoryLimit 만큼 보관)
kubectl get jobs -n oc -l app.kubernetes.io/name=expire-sessions정상 종료 시 로그 예:
{"level":"INFO","msg":"expire-sessions done","expired":3,"ttl_hours":24,"cutoff":"2026-08-07T13:13:00Z"}helm upgrade job ./charts/job -n oc --reuse-values \
--set expireSessions.schedule="5 * * * *"-
--reuse-values: 이번에 안 건드린 값(DB Secret 등)은 이전 설치 때 값 그대로 유지 -
-n oc: 설치할 때 쓴 namespace와 반드시 동일해야 함 (다르면 새 release로 취급되거나 리소스를 못 찾음)
--set을 계속 이어붙이는 대신, 바꿀 값을 파일 하나에 모아두고 그 파일로 upgrade하는 게 관리하기 쉽다:
# values-oc.yaml
expireSessions:
enabled: true
schedule: "5 * * * *"
database:
existingSecret:
name: expire-sessions-dbhelm upgrade job ./charts/job -n oc -f values-oc.yaml이 파일을 git에 커밋해두면 "지금 설정이 뭐였는지"를 파일 하나로 바로 확인할 수 있고, 다음에 값을 또 바꿀 때도 이 파일만 고쳐서 같은 명령을 반복하면 된다.
Headlamp(또는 kubectl edit)로 이미 떠 있는 CronJob 리소스의 spec.schedule을 직접 고치면 그 순간엔 적용된다. 하지만 Helm은 그 변경을 모른 채 "이 release의 값은 여전히 13분"이라고 기억하고 있어서, 나중에 (스케줄과 전혀 상관없는 값을 바꾸려는 것이었어도) helm upgrade를 한 번이라도 실행하면 Helm이 기억하는 값으로 조용히 되돌아간다.
- 잠깐 테스트만 하고 버릴 거면 → Headlamp 직접 수정 OK
- 계속 쓸 값이면 → 반드시 5.1/5.2처럼 Helm을 통해 바꿔서 Helm이 그 값을 "기억"하게 해야 함
Helm/K8s에는 이미 설치된 release의 namespace를 옮기는 기능이 없다. 잘못된 namespace에 설치했다면 지우고 다시 설치해야 한다:
# 1. 기존 namespace에서 제거
helm uninstall job -n default
# 2. DB Secret을 목표 namespace에 새로 생성 (Secret은 namespace 안에서만 보임)
kubectl create secret generic expire-sessions-db -n oc \
--from-literal=database-url='postgres://...'
# 3. 목표 namespace에 재설치
helm install job ./charts/job -n oc --create-namespace \
--set expireSessions.enabled=true \
--set database.existingSecret.name=expire-sessions-dbhelm uninstall job -n oc- Google ADK 검토 (프레임워크·모델 비교)
- 페르소나 + 상황 카드 모델 (2차 시나리오 구동 방식)
- Mac Studio 로컬 LLM + Claude Opus 하이브리드 라우팅 전략
- 개발 일정·할 일 점검표 (단계별 진행 점검)
- 로봇 Adapter 개발 온보딩 (HA·MQTT 계정 등록, 토픽 적용, 테스트 송수신, 상태 확인)
- LG ThinQ 가전 연동 (HA 통합 · REST 데이터 취득 · 제어)
- 장소 도착 자동화 (태스크/이벤트/장소 규칙 → SPOT·로봇팔·반려로봇·Hub 자동 명령)
- 엔딩 화면 데이터 출처 점검 (차량 3필드 · 세션 종료 엔딩 5화면)