- Authors

- Name
- Youngju Kim
- @fjvbn20031

- 런북 개요
- 사전 준비 체크리스트
- 프로덕션 업그레이드 실행 절차
- 롤백 절차
- 트러블슈팅: 멀티클러스터 업그레이드 중 실제 장애 시나리오
- 업그레이드 후 관찰 기간
- 포스트모템 템플릿
- 자동화: CI/CD 파이프라인에서의 업그레이드
- References
런북 개요
This document covers 2개 이상의 Kubernetes 클러스터를 운영하는 팀이 버전 업그레이드를 실행할 때 따라야 할 단계별 절차서(Runbook)다. 장애 발생 시 판단을 최소화하고, 사전에 정한 절차대로 실행할 수 있도록 작성했다.
적용 대상
- 멀티 리전 또는 멀티 환경(dev/staging/prod) 클러스터 운영
- 관리형 서비스(EKS, GKE, AKS)와 자체 관리(kubeadm, kOps) 혼용 환경
- 업그레이드 대상 버전: v1.32 → v1.33 (또는 유사 마이너 버전 업그레이드)
버전 skew 정책 요약
Kubernetes는 마이너 버전 건너뛰기를 허용하지 않는다. must 순차적으로 업그레이드해야 한다.
| 컴포넌트 | 허용 skew | 예시 (CP가 v1.33일 때) |
|---|---|---|
| kubelet | CP 기준 -2 | v1.31, v1.32, v1.33 허용 |
| kube-proxy | CP와 동일 마이너 | v1.33만 허용 |
| kubectl | CP 기준 +/-1 | v1.32, v1.33, v1.34 허용 |
| etcd | 특정 버전 조합 | 릴리스 노트에서 확인 |
사전 준비 체크리스트
업그레이드 작업 D-7(1주 전)부터 아래 항목을 순서대로 완료한다.
D-7: 변경 사항 분석
#!/bin/bash
# d7-changelog-review.sh
# 업그레이드 대상 버전의 변경 사항을 정리한다
TARGET_VERSION="v1.33"
echo "=== ${TARGET_VERSION} 변경 사항 체크 ==="
echo ""
echo "[1] Deprecated API 확인"
echo " - 릴리스 노트에서 Removed/Deprecated 섹션 확인"
echo " - Endpoints API → EndpointSlice 마이그레이션 필요 여부"
echo " - flowcontrol.apiserver.k8s.io/v1beta3 → v1 전환"
echo ""
echo "[2] Feature Gate 변경 확인"
echo " - InPlacePodVerticalScaling: Beta (기본 활성화)"
echo " - UserNamespacesSupport: Stable"
echo " - SidecarContainers: Stable"
echo " - NFTablesProxyMode: Stable"
echo ""
echo "[3] 사용 중인 Addon 호환성 확인"
# 각 addon의 호환성 매트릭스를 확인한다
ADDONS=(
"calico"
"cilium"
"ingress-nginx"
"cert-manager"
"external-dns"
"prometheus-operator"
"argocd"
)
for addon in "${ADDONS[@]}"; do
echo " - $addon: [ ] 호환성 확인 완료"
done
D-5: 스테이징 클러스터 업그레이드
프로덕션 전에 must 스테이징에서 먼저 업그레이드한다. 스테이징이 없다면, dev 클러스터라도 먼저 진행한다.
# 멀티클러스터 환경에서 클러스터 목록 확인
kubectl config get-contexts
# 스테이징 클러스터 컨텍스트로 전환
kubectl config use-context staging-cluster
# 스테이징 업그레이드 실행 (관리형 서비스 예시: EKS)
aws eks update-cluster-version \
--name staging-cluster \
--kubernetes-version 1.33
# 업그레이드 상태 모니터링
aws eks describe-update \
--name staging-cluster \
--update-id <update-id>
D-3: 스테이징 검증 완료
스테이징에서 최소 48시간 이상 관찰한 후 아래 항목을 확인한다.
- [ ] 모든 노드 Ready
- [ ] 모든 시스템 Pod Running
- [ ] 애플리케이션 Pod 정상 동작
- [ ] Ingress/Service 트래픽 정상
- [ ] CronJob 1회 이상 성공
- [ ] HPA/VPA 정상 동작
- [ ] 모니터링 메트릭 수집 정상
- [ ] 로그 파이프라인 정상
- [ ] Deprecated API 경고 없음
- [ ] 성능 테스트 통과 (응답 시간, 처리량)
D-1: 프로덕션 업그레이드 최종 준비
#!/bin/bash
# d1-final-prep.sh
echo "=== D-1 최종 준비 ==="
# 1. 변경 공지
echo "[1] 변경 공지 발송 여부: [ ]"
echo " - 내부 팀 슬랙 공지"
echo " - 외부 상태 페이지 업데이트"
echo " - 유지보수 시간대 공유"
# 2. 온콜 담당자 확인
echo "[2] 온콜 담당자:"
echo " - Primary: ___________"
echo " - Secondary: ___________"
echo " - 에스컬레이션 경로: Primary → Secondary → Tech Lead"
# 3. 롤백 준비
echo "[3] 롤백 준비 상태:"
echo " - [ ] etcd 스냅샷 생성 완료"
echo " - [ ] 이전 버전 바이너리 보관"
echo " - [ ] 롤백 절차 문서 확인"
echo " - [ ] 롤백 소요 시간 추정: ___분"
# 4. 유지보수 시간대
echo "[4] 작업 시간대:"
echo " - 시작: ___:___ (KST)"
echo " - 예상 종료: ___:___ (KST)"
echo " - 최대 허용: ___:___ (KST)"
프로덕션 업그레이드 실행 절차
Phase 1: 업그레이드 시작 선언
# 슬랙 웹훅으로 작업 시작 알림
curl -X POST "$SLACK_WEBHOOK_URL" \
-H 'Content-type: application/json' \
-d '{
"text": ":wrench: [MAINTENANCE] Kubernetes 업그레이드 시작\n클러스터: prod-cluster-01\n대상 버전: v1.33\n작업자: @oncall\n예상 소요: 2시간"
}'
Phase 2: 멀티클러스터 순차 업그레이드
멀티클러스터 환경에서는 트래픽 비중이 낮은 클러스터부터 순차적으로 업그레이드한다.
업그레이드 순서:
1. canary-cluster (트래픽 5%) ← 먼저 업그레이드, 1시간 관찰
2. prod-cluster-02 (트래픽 30%) ← canary 안정 후
3. prod-cluster-01 (트래픽 65%) ← 마지막
관리형 서비스별 업그레이드 명령
EKS:
# Control Plane 업그레이드
aws eks update-cluster-version \
--name prod-cluster-01 \
--kubernetes-version 1.33
# 업그레이드 완료 대기
aws eks wait cluster-active --name prod-cluster-01
# Managed Node Group 업그레이드
aws eks update-nodegroup-version \
--cluster-name prod-cluster-01 \
--nodegroup-name workers-general \
--kubernetes-version 1.33
# Addon 업그레이드
for ADDON in vpc-cni coredns kube-proxy; do
LATEST=$(aws eks describe-addon-versions \
--addon-name $ADDON \
--kubernetes-version 1.33 \
--query 'addons[0].addonVersions[0].addonVersion' \
--output text)
aws eks update-addon \
--cluster-name prod-cluster-01 \
--addon-name $ADDON \
--addon-version $LATEST
done
GKE:
# Control Plane 업그레이드
gcloud container clusters upgrade prod-cluster-01 \
--master \
--cluster-version 1.33.0-gke.100 \
--zone asia-northeast3-a
# Node Pool 업그레이드
gcloud container clusters upgrade prod-cluster-01 \
--node-pool workers-general \
--cluster-version 1.33.0-gke.100 \
--zone asia-northeast3-a
AKS:
# 업그레이드 가능 버전 확인
az aks get-upgrades \
--resource-group myResourceGroup \
--name prod-cluster-01 \
--output table
# Control Plane + Node Pool 동시 업그레이드
az aks upgrade \
--resource-group myResourceGroup \
--name prod-cluster-01 \
--kubernetes-version 1.33.0
Phase 3: 클러스터별 건강성 확인
각 클러스터 업그레이드 완료 후 must 실행한다.
#!/bin/bash
# cluster-health-check.sh <cluster-context>
CONTEXT=$1
echo "=== Health Check: $CONTEXT ==="
kubectl --context "$CONTEXT" get nodes -o wide
# 모든 노드 버전 확인
echo ""
echo "Node versions:"
kubectl --context "$CONTEXT" get nodes \
-o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.nodeInfo.kubeletVersion}{"\n"}{end}'
# 시스템 Pod 상태
echo ""
echo "System pods:"
FAILING=$(kubectl --context "$CONTEXT" -n kube-system get pods --no-headers | \
grep -v "Running\|Completed" | wc -l)
echo "Failing system pods: $FAILING"
# 프로덕션 워크로드 상태
echo ""
echo "Production workloads:"
kubectl --context "$CONTEXT" -n production get deployments -o wide
# Pending Pod 확인
echo ""
echo "Pending pods:"
kubectl --context "$CONTEXT" get pods -A --field-selector=status.phase=Pending
# 이벤트 확인 (최근 10분)
echo ""
echo "Recent warnings:"
kubectl --context "$CONTEXT" get events -A --sort-by='.lastTimestamp' \
--field-selector type=Warning | tail -20
Phase 4: 트래픽 이동과 관찰
멀티클러스터에서 트래픽을 제어하는 방법은 인프라에 따라 다르다.
# AWS Route53 가중치 기반 라우팅 예시
# canary 클러스터로 트래픽을 점진적으로 이동
# 단계 1: canary에 5% 트래픽
# prod-cluster-01: weight 65
# prod-cluster-02: weight 30
# canary-cluster: weight 5
# 단계 2: canary 안정 확인 후 30분 대기
# 단계 3: canary에 20% 트래픽
# prod-cluster-01: weight 50
# prod-cluster-02: weight 30
# canary-cluster: weight 20
# Route53 가중치 업데이트
aws route53 change-resource-record-sets \
--hosted-zone-id Z1234567890 \
--change-batch '{
"Changes": [{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "api.example.com",
"Type": "A",
"SetIdentifier": "canary",
"Weight": 20,
"AliasTarget": {
"HostedZoneId": "Z9876543210",
"DNSName": "canary-alb.ap-northeast-2.elb.amazonaws.com",
"EvaluateTargetHealth": true
}
}
}]
}'
롤백 절차
업그레이드 후 문제가 발생하면, 아래 판단 기준에 따라 롤백 여부를 결정한다.
롤백 판단 기준
| 심각도 | 증상 | 대응 |
|---|---|---|
| P1 - Critical | API Server 응답 불가, 대규모 Pod CrashLoop, 데이터 유실 위험 | 즉시 롤백 |
| P2 - High | 특정 워크로드 장애, 10% 이상 에러율 증가, 메트릭 수집 불가 | 30분 내 원인 파악 불가 시 롤백 |
| P3 - Medium | 마이너 기능 장애, 경고성 에러 증가, 성능 저하 10% 이내 | 원인 분석 후 핫픽스 우선 시도 |
| P4 - Low | 로그 경고만 발생, 동작에 영향 없음 | 모니터링 유지, 다음 유지보수에서 처리 |
관리형 서비스 롤백
관리형 서비스에서는 Control Plane 다운그레이드가 지원되지 않는 경우가 많다. 대신 노드 그룹을 이전 버전으로 교체한다.
# EKS: 이전 버전 노드 그룹 생성
aws eks create-nodegroup \
--cluster-name prod-cluster-01 \
--nodegroup-name workers-rollback \
--kubernetes-version 1.32 \
--node-role arn:aws:iam::123456789:role/eks-node-role \
--subnets subnet-abc subnet-def \
--instance-types m6i.xlarge \
--scaling-config minSize=3,maxSize=10,desiredSize=5
# 기존 노드 그룹의 Pod를 새 노드 그룹으로 이동
kubectl cordon -l eks.amazonaws.com/nodegroup=workers-general
kubectl drain -l eks.amazonaws.com/nodegroup=workers-general \
--ignore-daemonsets --delete-emptydir-data
# 기존 노드 그룹 삭제
aws eks delete-nodegroup \
--cluster-name prod-cluster-01 \
--nodegroup-name workers-general
멀티클러스터 트래픽 롤백
문제가 발생한 클러스터에서 트래픽을 제거한다.
# 문제 클러스터의 트래픽 가중치를 0으로 설정
aws route53 change-resource-record-sets \
--hosted-zone-id Z1234567890 \
--change-batch '{
"Changes": [{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "api.example.com",
"Type": "A",
"SetIdentifier": "canary",
"Weight": 0,
"AliasTarget": {
"HostedZoneId": "Z9876543210",
"DNSName": "canary-alb.ap-northeast-2.elb.amazonaws.com",
"EvaluateTargetHealth": true
}
}
}]
}'
트러블슈팅: 멀티클러스터 업그레이드 중 실제 장애 시나리오
시나리오 1: Node Group 업그레이드 중 PDB 위반으로 drain 실패
$ kubectl drain node-xyz --ignore-daemonsets
error: Cannot evict pod as it would violate the pod's disruption budget.
원인: PDB의 minAvailable이 현재 Running Pod 수와 같아서 한 개도 퇴거할 수 없는 상태.
해결:
# PDB 상태 확인
kubectl get pdb -A -o wide
# 출력 예시:
# NAMESPACE NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS
# production web-pdb 3 N/A 0
# ↑ 0이면 drain 불가
# 옵션 1: 레플리카 수를 먼저 늘려서 여유분 확보
kubectl -n production scale deployment web --replicas=4
# 1~2분 후 다시 drain 시도
# 옵션 2: PDB를 일시적으로 완화 (주의: 가용성 감소)
kubectl -n production patch pdb web-pdb \
--type=merge -p '{"spec":{"minAvailable":2}}'
# drain 완료 후 원복
kubectl -n production patch pdb web-pdb \
--type=merge -p '{"spec":{"minAvailable":3}}'
시나리오 2: 업그레이드 후 Addon 비호환
$ kubectl -n kube-system logs ingress-nginx-controller-xyz
Error: the server could not find the requested resource (get ingresses.networking.k8s.io)
원인: Ingress Controller 버전이 새 Kubernetes API 버전과 호환되지 않음.
해결:
# Addon 호환 버전 확인 및 업그레이드
helm repo update
# ingress-nginx 호환 버전 확인
helm search repo ingress-nginx/ingress-nginx --versions | head -10
# 호환 버전으로 업그레이드
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
--namespace kube-system \
--version 4.12.0 \
--reuse-values
시나리오 3: 멀티클러스터 간 버전 불일치로 서비스 메시 장애
# 클러스터 A: v1.33, 클러스터 B: v1.32
# Istio 멀티클러스터 구성에서 일부 트래픽 라우팅 실패
$ istioctl proxy-status
NAME CLUSTER CDS LDS EDS RDS
web-v1-xyz.production cluster-a SYNCED SYNCED SYNCED SYNCED
web-v1-abc.production cluster-b STALE STALE STALE STALE
원인: Istio 버전이 양쪽 클러스터의 Kubernetes 버전 모두를 지원하는지 확인 필요.
해결:
# Istio 호환성 확인
istioctl version
# 양쪽 클러스터에서 지원하는 Istio 버전으로 통일
# Istio 1.24+는 Kubernetes v1.31~v1.33 지원
istioctl upgrade --set revision=1-24-0
시나리오 4: EKS Addon 업그레이드 순서 오류
$ aws eks update-addon --addon-name vpc-cni ...
An error occurred (InvalidParameterException): Addon version v1.19.0 is not
compatible with cluster version 1.33. Available versions: v1.19.2, v1.20.0
해결:
# 호환 가능한 최신 버전 조회
aws eks describe-addon-versions \
--addon-name vpc-cni \
--kubernetes-version 1.33 \
--query 'addons[0].addonVersions[:5].{version:addonVersion,default:compatibilities[0].defaultVersion}' \
--output table
# 호환 버전으로 업데이트
aws eks update-addon \
--cluster-name prod-cluster-01 \
--addon-name vpc-cni \
--addon-version v1.20.0 \
--resolve-conflicts OVERWRITE
업그레이드 후 관찰 기간
관찰 항목과 기간
| 관찰 항목 | 확인 주기 | 정상 기준 | 이상 시 대응 |
|---|---|---|---|
| API Server 에러율 | 5분 | < 0.1% | 로그 확인 + 에스컬레이션 |
| Pod 재시작 횟수 | 15분 | 업그레이드 전 대비 증가 없음 | 재시작 Pod 로그 확인 |
| 노드 상태 | 10분 | 전체 Ready | NotReady 노드 조사 |
| 서비스 응답 시간 (p99) | 5분 | 업그레이드 전 대비 10% 이내 | 프로파일링 |
| etcd latency | 5분 | < 100ms | etcd 디스크 I/O 확인 |
| Deprecated API 경고 | 1시간 | 0건 | 해당 컴포넌트 코드 수정 |
관찰 기간 정의
업그레이드 후 0~2시간: 집중 관찰 (5분 간격 확인)
업그레이드 후 2~24시간: 일반 관찰 (30분 간격)
업그레이드 후 24~72시간: 경계 관찰 (이상 알림 대응)
업그레이드 후 72시간~: 정상 운영 전환, 포스트모템 작성
포스트모템 템플릿
업그레이드 완료 후 72시간 이내에 포스트모템을 작성한다. 장애 유무와 관계없이 작성하여 다음 업그레이드에 반영한다.
# 클러스터 업그레이드 포스트모템
## 기본 정보
- 대상 클러스터: \_\_\_
- 이전 버전: v1.32.x → 현재 버전: v1.33.x
- 작업 시간: YYYY-MM-DD HH:MM ~ HH:MM (총 \_\_\_시간)
- 작업자: \_\_\_
## 진행 요약
- [ ] 스테이징 업그레이드: 문제 없음 / 문제 발생 (상세: \_\_\_)
- [ ] 프로덕션 업그레이드: 문제 없음 / 문제 발생 (상세: \_\_\_)
- [ ] 롤백 실행 여부: Yes / No
## 발견된 이슈
| 이슈 | 심각도 | 해결 방법 | 소요 시간 |
| ------ | ------ | --------- | --------- |
| \_\_\_ | P1~P4 | \_\_\_ | \_\_\_분 |
## 개선 사항 (다음 업그레이드에 반영)
1. ***
2. ***
3. ***
## 업데이트 필요한 문서
- [ ] 이 런북
- [ ] 온콜 가이드
- [ ] 모니터링 대시보드
자동화: CI/CD 파이프라인에서의 업그레이드
반복되는 멀티클러스터 업그레이드를 GitHub Actions로 자동화하는 예시.
# .github/workflows/cluster-upgrade.yml
name: Kubernetes Cluster Upgrade
on:
workflow_dispatch:
inputs:
target_version:
description: 'Target Kubernetes version'
required: true
default: '1.33'
cluster:
description: 'Cluster to upgrade'
required: true
type: choice
options:
- canary-cluster
- prod-cluster-02
- prod-cluster-01
dry_run:
description: 'Dry run mode'
required: true
type: boolean
default: true
jobs:
pre-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ap-northeast-2
- name: Pre-upgrade checks
run: |
aws eks describe-cluster --name ${{ inputs.cluster }} \
--query 'cluster.{version:version,status:status}' \
--output table
# 현재 버전 확인
CURRENT=$(aws eks describe-cluster --name ${{ inputs.cluster }} \
--query 'cluster.version' --output text)
echo "Current version: $CURRENT"
echo "Target version: ${{ inputs.target_version }}"
# Addon 호환성 확인
for ADDON in vpc-cni coredns kube-proxy; do
echo "Checking $ADDON compatibility..."
aws eks describe-addon-versions \
--addon-name $ADDON \
--kubernetes-version ${{ inputs.target_version }} \
--query 'addons[0].addonVersions[0].addonVersion' \
--output text
done
upgrade:
needs: pre-check
runs-on: ubuntu-latest
if: ${{ !inputs.dry_run }}
environment: production # 수동 승인 필요
steps:
- name: Upgrade Control Plane
run: |
aws eks update-cluster-version \
--name ${{ inputs.cluster }} \
--kubernetes-version ${{ inputs.target_version }}
echo "Waiting for control plane upgrade..."
aws eks wait cluster-active --name ${{ inputs.cluster }}
- name: Upgrade Node Groups
run: |
NODEGROUPS=$(aws eks list-nodegroups \
--cluster-name ${{ inputs.cluster }} \
--query 'nodegroups[]' --output text)
for NG in $NODEGROUPS; do
echo "Upgrading node group: $NG"
aws eks update-nodegroup-version \
--cluster-name ${{ inputs.cluster }} \
--nodegroup-name $NG \
--kubernetes-version ${{ inputs.target_version }}
done
- name: Upgrade Addons
run: |
for ADDON in vpc-cni coredns kube-proxy; do
LATEST=$(aws eks describe-addon-versions \
--addon-name $ADDON \
--kubernetes-version ${{ inputs.target_version }} \
--query 'addons[0].addonVersions[0].addonVersion' \
--output text)
aws eks update-addon \
--cluster-name ${{ inputs.cluster }} \
--addon-name $ADDON \
--addon-version $LATEST \
--resolve-conflicts OVERWRITE
done
post-verify:
needs: upgrade
runs-on: ubuntu-latest
steps:
- name: Health Check
run: |
aws eks update-kubeconfig --name ${{ inputs.cluster }}
echo "Node status:"
kubectl get nodes -o wide
echo "System pods:"
kubectl -n kube-system get pods
echo "Failing pods:"
kubectl get pods -A --field-selector=status.phase!=Running,status.phase!=Succeeded
- name: Notify
run: |
curl -X POST "${{ secrets.SLACK_WEBHOOK }}" \
-H 'Content-type: application/json' \
-d "{
\"text\": \":white_check_mark: Cluster upgrade complete\nCluster: ${{ inputs.cluster }}\nVersion: ${{ inputs.target_version }}\"
}"
퀴즈
Q1. 멀티클러스터 업그레이드에서 canary 클러스터를 먼저 업그레이드하는 이유는?
정답: ||트래픽 비중이 가장 낮은 클러스터에서 먼저 업그레이드하여 문제 발생 시 영향 범위를
최소화한다. canary에서 안정성이 확인된 후 나머지 클러스터를 진행한다.||
Q2. kubelet의 버전 skew 허용 범위가 CP 기준 -2인 것의 실무적 의미는?
정답: ||Control Plane을 v1.33으로 업그레이드해도 Worker 노드는 v1.31까지 호환되므로, Worker 노드를
한꺼번에 업그레이드하지 않고 점진적으로 진행할 수 있다.||
Q3. PDB의 ALLOWED DISRUPTIONS가 0일 때 drain이 실패하는 이유와 해결 방법은?
정답: ||PDB의 minAvailable이 현재 Running Pod 수와 같아서 한 개도 퇴거할 여유가 없는 상태다.
레플리카 수를 먼저 늘려서 여유분을 확보하거나, PDB를 일시적으로 완화해야 한다.||
Q4. 스테이징 업그레이드 후 최소 48시간 관찰하는 이유는?
정답: ||CronJob, 주기적 배치 처리, 인증서 갱신 등 즉시 드러나지 않는 문제를 발견하려면 최소
1~2일의 관찰이 필요하다. 일부 장애는 트래픽 패턴 변화(주간/야간) 속에서만 발현된다.||
Q5. 관리형 서비스(EKS/GKE/AKS)에서 Control Plane 롤백이 어려운 이유는?
정답: ||관리형 서비스는 Control Plane 다운그레이드를 지원하지 않는다. 대신 노드 그룹을 이전
버전으로 생성하고 트래픽을 이동하거나, 새 클러스터를 만들어 마이그레이션해야 한다.||
Q6. 포스트모템을 장애 유무와 관계없이 작성해야 하는 이유는?
정답: ||업그레이드 과정에서 발견한 개선점, 예상보다 오래 걸린 단계, 문서와 실제 절차의 차이 등을
기록해야 다음 업그레이드 때 런북을 개선할 수 있다. 장애가 없었더라도 프로세스 자체를 개선할 수
있는 기회다.||
Q7. GitHub Actions에서 production environment에 수동 승인을 거는 이유는?
정답: ||자동화된 파이프라인이라도 프로덕션 업그레이드는 사람이 최종 승인해야 한다. pre-check
결과를 사람이 확인하고, 현재 시점의 서비스 상태를 고려하여 진행 여부를 판단하기 위해서다.||