1. 필요한 도구 설치
데이터를 JSON 형식으로 내보낸 후, 불필요한 필드를 삭제하고 yq를 통해 YAML 형식으로 변환합니다. 이 작업은 YAML 파일로 내보낼 때 특정 필드를 필터링하는 방법을 모를 때 유용합니다.
[root@k8s-master test]# yum install jq -y # JSON 파싱
[root@k8s-master ~]# curl -LO https://github.com/mikefarah/yq/releases/download/v4.34.1/yq_linux_amd64 # 최신 버전 다운로드
[root@k8s-master ~]# chmod +x yq_linux_amd64
[root@k8s-master ~]# mv yq_linux_amd64 /usr/bin/yq
[root@k8s-master ~]# yq --version
yq (https://github.com/mikefarah/yq/) version 4.34.1
2. 스크립트 작성
V1.13 버전
아래는 Kubernetes 리소스를 YAML 파일로 백업하는 Bash 스크립트입니다.
#!/bin/bash
CURRENT_TIME=$(date +%Y%m%d%H%M%S) # 시간 기반 디렉토리 생성
BACKUP_PATH=/tmp/k8s-backup-restore # 백업 경로
NAMESPACE_LIST="change-battery-demo nginx-ingress-port tools tsp" # 백업할 네임스페이스 목록
RESOURCE_TYPES="service deployment ingress" # 백업할 리소스 타입
for namespace in ${NAMESPACE_LIST}; do
TARGET_DIR="${BACKUP_PATH}/${namespace}/${CURRENT_TIME}" # 네임스페이스별 백업 디렉토리
mkdir -p "${TARGET_DIR}" && cd "${TARGET_DIR}"
for resource in ${RESOURCE_TYPES}; do
item_count=$(kubectl get "${resource}" -n "${namespace}" 2>/dev/null | wc -l)
if [ "${item_count}" -lt 2 ]; then continue; fi # 리소스가 없는 경우 건너뜀
ITEMS=$(kubectl get "${resource}" -n "${namespace}" -o custom-columns=NAME:.metadata.name --no-headers)
for item in ${ITEMS}; do
FILE_NAME="${TARGET_DIR}/${resource}_${item}.yaml"
kubectl get "${resource}" "${item}" -n "${namespace}" -o=json | \
jq 'del(
.spec.clusterIP,
.metadata.uid,
.metadata.selfLink,
.metadata.resourceVersion,
.metadata.creationTimestamp,
.metadata.generation,
.metadata.annotations,
.status
)' | yq eval -P > "${FILE_NAME}"
done
done
done
V1.22 버전
다음은 보다 고급 기능을 포함한 업데이트된 스크립트입니다.
#!/bin/bash
CURRENT_TIME=$(date +%Y-%m-%d-%H-%M-%S) # 현재 시간 기반 이름 설정
BASE_BACKUP_PATH="/mnt/k8s-backup-restore" # 기본 백업 경로
CURRENT_BACKUP_PATH="${BASE_BACKUP_PATH}/${CURRENT_TIME}" # 실제 백업 경로
SCRIPT_DIR="$(cd "$(dirname "$0")"; pwd)" # 스크립트 위치
# 백업 대상 네임스페이스 목록
NAMESPACE_LIST=$(kubectl get namespaces -o jsonpath='{.items[?(@.status.phase=="Active")].metadata.name}' | \
grep -vE 'ahas|ahas-sentinel-pilot|arms-pilot|arms-prom|edas-oam-system|kube-public|kube-node-lease|kube-system')
RESOURCE_TYPES="svc deploy ingress cm secret statefulset" # 백업할 리소스 타입
# 필터링 로직 정의
FILTER_CM='del(.metadata.uid, .metadata.resourceVersion, .metadata.creationTimestamp)'
FILTER_SECRET='del(.metadata.uid, .metadata.resourceVersion, .metadata.creationTimestamp)'
FILTER_SVC='del(.metadata.uid, .metadata.resourceVersion, .metadata.creationTimestamp, .status, .spec.clusterIP)'
FILTER_DEPLOY='del(.metadata.uid, .metadata.resourceVersion, .metadata.creationTimestamp, .status)'
FILTER_STATEFULSET='del(.metadata.uid, .metadata.resourceVersion, .metadata.creationTimestamp, .status)'
backup_to_yaml() {
for ns in ${NAMESPACE_LIST}; do
TARGET_DIR="${CURRENT_BACKUP_PATH}/${ns}"
mkdir -p "${TARGET_DIR}" && cd "${TARGET_DIR}"
for resource in ${RESOURCE_TYPES}; do
item_count=$(kubectl get "${resource}" -n "${ns}" 2>/dev/null | wc -l)
if [ "${item_count}" -lt 2 ]; then continue; fi
ITEMS=$(kubectl get "${resource}" -n "${ns}" -o custom-columns=NAME:.metadata.name --no-headers)
for item in ${ITEMS}; do
FILE_NAME="${TARGET_DIR}/${resource}_${item}.yaml"
FILTER_LOGIC=""
case "${resource}" in
"cm") FILTER_LOGIC="${FILTER_CM}";;
"secret") FILTER_LOGIC="${FILTER_SECRET}";;
"svc") FILTER_LOGIC="${FILTER_SVC}";;
"deploy") FILTER_LOGIC="${FILTER_DEPLOY}";;
"statefulset") FILTER_LOGIC="${FILTER_STATEFULSET}";;
esac
kubectl get "${resource}" "${item}" -n "${ns}" -o=json | jq "${FILTER_LOGIC}" | yq eval -P > "${FILE_NAME}"
done
done
done
}
archive_and_upload() {
ARCHIVE_FILE="k8s-backup-${CURRENT_TIME}.tar.gz"
tar -czf "${ARCHIVE_FILE}" -C "${BASE_BACKUP_PATH}" "${CURRENT_TIME}" &>/dev/null
if [[ -s "${ARCHIVE_FILE}" ]]; then
python3 "${SCRIPT_DIR}/oss_upload.py" "k8s_backup/${ARCHIVE_FILE}" "${BASE_BACKUP_PATH}/${ARCHIVE_FILE}"
fi
}
main() {
backup_to_yaml
archive_and_upload
}
main
OSS에 업로드하기 위한 Python 스크립트
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import oss2
import sys
OSS_FILE_NAME = sys.argv[1]
LOCAL_FILE_NAME = sys.argv[2]
auth = oss2.Auth('YOUR_ACCESS_KEY_ID', 'YOUR_ACCESS_KEY_SECRET')
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'YOUR_BUCKET_NAME')
bucket.put_object_from_file(OSS_FILE_NAME, LOCAL_FILE_NAME)
생성된 디렉토리 구조는 다음과 같습니다:
root@tsp-prod-ansible:~/script_dir# tree -L 3 /mnt
/mnt/
└── k8s-backup-restore
├── 2022-11-10-14-24-01
│ ├── bmp-prd
│ ├── change-battery-demo
│ ├── default
│ ├── mk1-prod
│ ├── mk1-website