yq로 YAML 구성 파일 편집
yq를 사용하여 구조와 주석을 유지하면서 Kubernetes 및 CI YAML을 제자리에서 읽고 수정합니다.
yq로 YAML 구성 파일 편집은(는) CoddyKit의 무료 DevOps Bootcamp 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 DevOps Bootcamp 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. DevOps Bootcamp 강의에는 총 4개의 강의가 포함되어 있습니다.
yq란 무엇이며 YAML에 사용하는 이유는 무엇인가요
yq는 이식 가능한 명령줄 YAML 처리기로, jq가 JSON을 처리하는 방식과 비슷합니다. Python이나 Ruby로 스크립트를 작성하지 않고도 YAML 파일을 읽고, 필터링하고, 편집할 수 있습니다.
yq라는 이름의 인기 도구는 두 가지가 있습니다.
- mikefarah/yq(Go) — 활발하게 유지 관리되며 YAML, JSON, XML, TOML을 지원합니다. 이 레슨에서는 이 버전을 사용합니다.
- kislyuk/yq(Python) — YAML용
jq래퍼이며 구문이 다릅니다.
Go 버전을 설치합니다.
- macOS에서는
brew install yq - Linux에서는
snap install yq - 또는 바이너리를 다운로드합니다:
wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/local/bin/yq && chmod +x /usr/local/bin/yq
확인하려면 yq --version을 실행합니다. v4.x.x가 출력되어야 합니다. 버전 4는 v3와 표현식 구문이 다르므로 버전이 중요합니다.
# Install yq (Go version) on Linux
wget -q https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 \
-O /usr/local/bin/yq
chmod +x /usr/local/bin/yq
# Confirm version
yq --versionKubernetes 배포 YAML에서 값 읽기
무언가를 편집하기 전에 YAML 필드를 읽는 방법을 익혀 보겠습니다. Kubernetes Deployment가 주어지면 점 표기법 경로로 중첩된 값을 추출할 수 있습니다.
예시 deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: production
spec:
replicas: 3
template:
spec:
containers:
- name: app
image: my-app:1.0.0주요 읽기 명령:
yq '.metadata.name' deployment.yaml—my-app을 출력합니다.yq '.spec.replicas' deployment.yaml—3을 출력합니다.yq '.spec.template.spec.containers[0].image' deployment.yaml—my-app:1.0.0을 출력합니다.
기본적으로 출력은 일반 텍스트이며 인용 부호가 없습니다. 스크립트에서 원시 문자열이 필요하면 -r 플래그를 추가하거나 | yq -r을 사용합니다.
# Create a sample deployment YAML
cat > /tmp/deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: production
spec:
replicas: 3
template:
spec:
containers:
- name: app
image: my-app:1.0.0
EOF
# Read individual fields
echo "App name: $(yq '.metadata.name' /tmp/deployment.yaml)"
echo "Replicas: $(yq '.spec.replicas' /tmp/deployment.yaml)"
echo "Image: $(yq '.spec.template.spec.containers[0].image' /tmp/deployment.yaml)"-i 플래그로 원본 파일 직접 편집하기
실제 사용에서 가장 중요한 플래그는 -i(원본 파일 직접 편집)입니다. 이 플래그가 없으면 yq는 결과를 표준 출력에 표시하고 파일은 변경하지 않습니다.
구문:
- 읽기만 하기(표준 출력):
yq '.spec.replicas' file.yaml - 원본 파일 직접 편집:
yq -i '.spec.replicas = 5' file.yaml
할당 연산자 =는 값을 설정합니다. 표현식은 완전한 yq 필터이므로 한 번의 실행에서 읽기와 쓰기를 결합할 수 있습니다.
중요: yq -i는 파일 전체를 다시 작성합니다. 필드와 같은 줄에 있는 주석은 일반적으로 보존되지만, 독립된 주석 블록은 위치가 바뀔 수 있습니다. 원본 파일을 직접 대량 편집하기 전에 항상 YAML을 버전 관리 시스템에 커밋하세요.
먼저 -i 없이 테스트한 다음 출력이 만족스러울 때 추가하세요.
# Start with the deployment from the previous scene
echo 'Before:' && yq '.spec.replicas' /tmp/deployment.yaml
# Edit in place: scale to 5 replicas
yq -i '.spec.replicas = 5' /tmp/deployment.yaml
echo 'After:' && yq '.spec.replicas' /tmp/deployment.yaml컨테이너 이미지 태그 업데이트하기
매우 흔한 CI 작업은 새 이미지를 빌드한 후 Kubernetes 매니페스트의 Docker 이미지 태그를 올리는 것입니다. yq를 사용하면 한 줄 명령으로 처리할 수 있습니다.
패턴은 다음과 같습니다.
select()를 사용하여 이름으로 컨테이너를 지정하면 배열 인덱스 0을 코드에 직접 지정하지 않아도 됩니다.|=(업데이트 연산자) 또는=를 사용하여 새 값을 설정합니다.
배열 인덱스 사용(컨테이너 목록이 변경되면 취약함):
yq -i '.spec.template.spec.containers[0].image = "my-app:2.1.0"' deployment.yaml
select() 사용(견고함):
yq -i '(.spec.template.spec.containers[] | select(.name == "app")).image = "my-app:2.1.0"' deployment.yaml
CI 파이프라인에서는 셸 변수로 태그를 전달합니다.
NEW_TAG="my-app:2.1.0"
CONTAINER_NAME="app"
# Robust update: target by container name, not index
yq -i \
"(.spec.template.spec.containers[] | select(.name == \"${CONTAINER_NAME}\")).image = \"${NEW_TAG}\"" \
/tmp/deployment.yaml
# Verify
yq '.spec.template.spec.containers[0].image' /tmp/deployment.yaml필드 추가 및 삭제하기
기존 필드를 업데이트하는 것 외에도 yq로 새 키를 추가하거나 기존 키를 삭제할 수 있습니다.
필드 추가:
- 존재하지 않는 경로에 값을 할당하기만 하면 됩니다:
yq -i '.metadata.labels.version = "v2"' file.yaml - 상위 키(
labels)가 없으면 yq가 자동으로 만듭니다.
필드 삭제:
del()함수를 사용합니다:yq -i 'del(.metadata.annotations)' file.yaml- 인덱스로 배열 요소를 삭제합니다:
yq -i 'del(.spec.template.spec.containers[1])' file.yaml
배열에 요소 추가:
yq -i '.spec.template.spec.containers += [{"name": "sidecar", "image": "envoy:latest"}]' file.yaml
# Add a label to the deployment
yq -i '.metadata.labels.version = "v2"' /tmp/deployment.yaml
yq -i '.metadata.labels.managed-by = "ci-pipeline"' /tmp/deployment.yaml
echo '--- Labels after adding ---'
yq '.metadata.labels' /tmp/deployment.yaml
# Delete one label
yq -i 'del(.metadata.labels.managed-by)' /tmp/deployment.yaml
echo '--- Labels after delete ---'
yq '.metadata.labels' /tmp/deployment.yaml여러 문서로 구성된 YAML 파일 다루기
Kubernetes 매니페스트는 여러 리소스를 ---로 구분하여 하나의 파일에 묶는 경우가 많습니다. 기본적으로 yq는 이러한 파일의 모든 문서를 처리합니다.
주요 기법:
- 모든 문서 종류 나열:
yq '.[].kind' multi.yaml— 문서를 반복 처리하려면 앞에.[]가 필요합니다. - 종류로 특정 문서 지정:
yq 'select(.kind == "Service")' multi.yaml - 일치하는 문서만 원본 파일에서 직접 편집:
yq -i 'select(.kind == "Deployment").spec.replicas = 2' multi.yaml
select() 조건과 일치하지 않는 문서는 변경 없이 그대로 전달되므로 Service, ConfigMap 및 다른 리소스는 유지됩니다.
여러 문서 파일을 개별 파일로 나누려면 yq 출력을 반복 처리하거나 다음 명령을 사용할 수 있습니다.
yq -s '.kind' multi.yaml— 각 문서의.kind값으로 이름을 지정한 파일을 문서마다 하나씩 작성합니다.
cat > /tmp/multi.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 1
---
apiVersion: v1
kind: Service
metadata:
name: web-svc
spec:
port: 80
EOF
# Scale ONLY the Deployment, leave Service untouched
yq -i 'select(.kind == "Deployment").spec.replicas = 4' /tmp/multi.yaml
echo '--- Deployment replicas ---'
yq 'select(.kind == "Deployment").spec.replicas' /tmp/multi.yaml
echo '--- Service port (unchanged) ---'
yq 'select(.kind == "Service").spec.port' /tmp/multi.yamlGitHub Actions CI YAML 패치하기
CI 구성 파일(.github/workflows/*.yml, .gitlab-ci.yml)도 YAML입니다. 경로가 깊게 중첩될 수 있지만 동일한 yq 명령을 사용할 수 있습니다.
일반적인 CI 패치 작업:
- 실행기 버전 고정: 모든 작업의
runs-on을 업데이트합니다. - 액션 버전 업데이트: 특정 액션을 사용하는 단계를 찾아 해당 액션의
uses필드를 올립니다. - 플래그 전환: 작업 흐름 수준 설정을 활성화하거나 비활성화합니다.
예시: actions/checkout을 사용하는 모든 단계를 v4로 업데이트합니다.
yq -i '(.jobs[].steps[] | select(.uses == "actions/checkout@v3")).uses = "actions/checkout@v4"' .github/workflows/ci.yml이 관용구인 []로 반복하고, select()로 범위를 좁히고, =로 할당하기가 구조화된 YAML 편집의 핵심 패턴입니다.
cat > /tmp/ci.yml << 'EOF'
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm test
lint:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- run: npm run lint
EOF
# Bump all checkout steps from v3 → v4
yq -i '(.jobs[].steps[] | select(.uses == "actions/checkout@v3")).uses = "actions/checkout@v4"' \
/tmp/ci.yml
# Verify both jobs were updated
yq '.jobs[].steps[] | select(.uses | test("checkout")).uses' /tmp/ci.ymlyq 표현식에서 환경 변수 사용하기
yq 표현식에 값을 직접 작성하면 스크립트가 쉽게 깨질 수 있습니다. yq는 env() 함수 또는 strenv() 단축형을 사용하여 셸 변수를 주입할 수 있습니다.
env(VAR_NAME)— 환경 변수를 읽어 적절한 YAML 형식으로 변환합니다(숫자는 숫자로, 문자열은 문자열로 유지됨).strenv(VAR_NAME)— 항상 문자열을 반환하며 이미지 태그에 유용합니다.
이 방법을 사용하면 YAML 경로가 포함된 큰따옴표 셸 문자열 안에서 변수를 보간할 때 발생하는 복잡한 인용 부호 문제를 피할 수 있습니다.
패턴:
export IMAGE_TAG="my-app:3.0.0"
yq -i '.spec.template.spec.containers[0].image = strenv(IMAGE_TAG)' deployment.yamlreplicas와 같은 숫자 필드를 설정할 때는 env()를 사용하여 YAML 형식(인용 부호가 붙은 문자열이 아닌 정수)을 유지하세요.
export APP_IMAGE="my-app:3.0.0"
export REPLICA_COUNT=6
# Set image using strenv() — result is a YAML string
yq -i '.spec.template.spec.containers[0].image = strenv(APP_IMAGE)' \
/tmp/deployment.yaml
# Set replicas using env() — result is a YAML integer
yq -i '.spec.replicas = env(REPLICA_COUNT)' \
/tmp/deployment.yaml
# Confirm types are correct in the output
yq '.spec.replicas, .spec.template.spec.containers[0].image' /tmp/deployment.yaml두 YAML 파일 병합
때로는 패치 파일(작은 재정의 YAML)을 기본 구성에 적용해야 합니다. 예를 들어 Kustomize 스타일의 작업 흐름에서 환경별 재정의를 적용할 때가 그렇습니다.
yq에서는 * 병합 연산자를 사용하여 두 파일을 병합할 수 있습니다.
yq '. *= load("patch.yaml")' base.yaml— 패치를 기본 구성에 깊이 병합하고 표준 출력으로 씁니다.- 기본 구성 파일을 제자리에서 업데이트하려면
-i를 추가합니다.yq -i '. *= load("patch.yaml")' base.yaml
병합 동작은 다음과 같습니다.
- 패치의 스칼라 값이 기본 구성의 값을 덮어씁니다.
- 매핑은 깊이 병합됩니다. 패치에 없는 키는 유지됩니다.
- 시퀀스(배열)는 기본적으로 이어 붙이지 않고 대체합니다. 이어 붙이려면
*+를 사용합니다.
이 패턴을 사용하면 공백 변경 시 깨지기 쉬운 sed 스크립트를 대신할 수 있습니다.
cat > /tmp/base.yaml << 'EOF'
app:
name: my-service
port: 8080
debug: false
database:
host: localhost
port: 5432
EOF
cat > /tmp/patch.yaml << 'EOF'
app:
port: 9090
debug: true
database:
host: db.production.svc
EOF
# Deep-merge patch into base (stdout preview first)
yq '. *= load("/tmp/patch.yaml")' /tmp/base.yaml
# Apply in place
yq -i '. *= load("/tmp/patch.yaml")' /tmp/base.yamlYAML 검증 및 JSON 변환
패치가 적용된 YAML을 클러스터에 적용하기 전에 검증하고, 필요하면 다른 도구에서 사용할 수 있도록 JSON으로 변환하는 것이 좋습니다.
구문 검증:
yq '.' file.yaml && echo "Valid"— 구문 분석 오류가 발생하면 yq가 종료 코드 1로 종료되므로 CI 게이트에서 사용할 수 있습니다.
YAML을 JSON으로 변환:
yq -o=json '.' file.yaml— 보기 좋게 형식이 지정된 JSON을 출력합니다.- 이후 JSON 처리를 하려면
jq로 파이프를 연결합니다.yq -o=json '.' file.yaml | jq '.metadata.name'
JSON을 YAML로 변환:
yq -P '.' file.json— 입력이 JSON일 때-P플래그가 YAML(보기 좋게 형식이 지정된) 출력을 강제합니다.
이러한 변환을 통해 yq는 YAML 기반 도구(Helm, kubectl)와 JSON 기반 도구(Terraform, AWS CLI, jq)를 연결하는 다리 역할을 합니다.
# Validate YAML (exits 0 on success, 1 on parse error)
if yq '.' /tmp/deployment.yaml > /dev/null 2>&1; then
echo "YAML is valid"
else
echo "YAML parse error!" >&2
exit 1
fi
# Convert to JSON and query with jq
yq -o=json '.' /tmp/deployment.yaml \
| jq '{name: .metadata.name, image: .spec.template.spec.containers[0].image}'
# Round-trip: JSON snippet back to YAML
echo '{"replicas": 7, "strategy": "RollingUpdate"}' \
| yq -P '.'완전한 CI 배포 패치 스크립트
지금까지의 기법을 모두 결합하여 GitOps 파이프라인의 일부로 Kubernetes Deployment 매니페스트를 패치하는 실제 CI 스크립트를 살펴보겠습니다.
이 스크립트는 다음 작업을 수행합니다.
- 입력 YAML을 수정하기 전에 검증합니다.
- 모든 변수 치환에
env()/strenv()를 사용합니다. - 이름을 기준으로 하는
select()를 사용하여 컨테이너 이미지 태그를 업데이트합니다. - 복제본 수를 늘립니다.
- 현재 타임스탬프로
deploy-time주석을 기록합니다. - 커밋하기 전에 출력을 다시 검증합니다.
이 패턴을 사용하면 파이프라인이 동시에 실행되더라도 각 단계가 원자적으로 수행되고 감사 추적이 가능합니다.
#!/usr/bin/env bash
set -euo pipefail
MANIFEST="/tmp/deployment.yaml"
export NEW_IMAGE="my-app:$(date +%Y%m%d)-abc1234"
export NEW_REPLICAS=3
export DEPLOY_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
export CONTAINER="app"
# 1. Validate before patching
yq '.' "$MANIFEST" > /dev/null
# 2. Update image (by container name)
yq -i \
'(.spec.template.spec.containers[] | select(.name == strenv(CONTAINER))).image = strenv(NEW_IMAGE)' \
"$MANIFEST"
# 3. Set replicas
yq -i '.spec.replicas = env(NEW_REPLICAS)' "$MANIFEST"
# 4. Stamp annotation
yq -i '.metadata.annotations."deploy-time" = strenv(DEPLOY_TIME)' "$MANIFEST"
# 5. Validate result
yq '.' "$MANIFEST" > /dev/null && echo "Patch applied successfully"
# 6. Show diff summary
yq '{image: .spec.template.spec.containers[0].image, replicas: .spec.replicas}' "$MANIFEST"지식 확인: 안전한 다중 문서 편집
yq를 사용하여 다중 문서 Kubernetes YAML 파일을 편집하는 방법을 얼마나 이해했는지 확인해 보십시오.
레슨 요약: yq로 YAML 편집
yq로 YAML 구성 파일 편집 레슨을 완료하셨습니다. 지금까지 다룬 내용을 간단히 요약하면 다음과 같습니다.
- 설치: mikefarah/yq Go 바이너리(v4)를 사용합니다.
yq --version으로 확인합니다. - 읽기:
.spec.replicas와 같은 점 표기 경로를 사용하고,[0]또는[]반복으로 배열에 접근합니다. - 제자리 편집:
-i플래그는 파일을 다시 씁니다. 항상 먼저-i없이 미리 확인하십시오. - 견고한 대상 지정: 하드 코딩된 배열 인덱스보다
select(.name == "app")를 우선 사용하십시오. - 추가 / 삭제: 새 경로에 값을 할당하여 경로를 만들고, 필드를 제거하려면
del()을 사용합니다. - 다중 문서 파일:
select(.kind == "...")를 사용하여 하나의 리소스를 대상으로 지정하고 다른 리소스는 수정하지 않습니다. - CI 변수: 문자열에는
strenv(VAR)를, 형식이 있는 값에는env(VAR)를 사용하여 셸 인용 오류를 방지합니다. - 병합:
. *= load("patch.yaml")는 패치되지 않은 키를 잃지 않고 재정의 파일을 깊이 병합합니다. - 검증 및 변환: 린트 게이트로
yq '.'를 사용하고, 형식 변환에는-o=json및-P를 사용합니다.
CI에서 YAML 패치를 적용할 때의 핵심 패턴은 검증 → 선택 → 할당 → 검증입니다. 여기에 strenv()와 select()를 함께 사용하면 취약한 sed 한 줄 명령을 더 이상 사용할 필요가 없습니다.
자주 묻는 질문
“yq로 YAML 구성 파일 편집” 강의는 무료인가요?
네 — “yq로 YAML 구성 파일 편집” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 DevOps Bootcamp 강의 전체를 잠금 해제할 수 있습니다. DevOps Bootcamp 강의에는 총 4개의 강의가 포함되어 있습니다.
“yq로 YAML 구성 파일 편집”에서 뭘 배우나요?
yq를 사용하여 구조와 주석을 유지하면서 Kubernetes 및 CI YAML을 제자리에서 읽고 수정합니다. 브라우저에서 직접 실행하는 실습 코드로 DevOps Bootcamp을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
DevOps Bootcamp을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 DevOps Bootcamp은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“yq로 YAML 구성 파일 편집” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 DevOps Bootcamp 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 DevOps Bootcamp 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.