Kustomize로 쿠버네티스 오브젝트 관리하기
Kustomize로 쿠버네티스 오브젝트 관리하기 (Declarative Management of Kubernetes Objects Using Kustomize)
Kustomize는 kustomization 파일을 통해 쿠버네티스 오브젝트를 사용자 정의하는 독립형 도구입니다.
출처: 문서
본문
1.14부터 kubectl도 kustomization 파일을 사용한 쿠버네티스 오브젝트 관리를 지원합니다. kustomization 파일이 포함된 디렉터리의 리소스를 보려면 다음 명령을 실행하세요:
kubectl kustomize <kustomization_directory>
그 리소스들을 적용하려면 --kustomize 또는 -k 플래그와 함께 kubectl apply를 실행하세요:
kubectl apply -k <kustomization_directory>
시작하기 전에
kubectl을 설치한다.
Kustomize 개요
Kustomize는 쿠버네티스 구성을 사용자 정의하는 도구입니다. 애플리케이션 구성 파일을 관리하는 다음 기능이 있습니다:
- 다른 소스에서 리소스 생성하기
- 리소스에 교차(cross-cutting) 필드 설정하기
- 리소스 집합 구성·사용자 정의하기
리소스 생성하기 (Generating Resources)
ConfigMap과 Secret은 파드 같은 다른 쿠버네티스 오브젝트가 사용하는 구성 또는 민감한 데이터를 보관합니다. ConfigMap이나 Secret의 정보 출처(source of truth)는 보통 .properties 파일이나 SSH 키 파일 같은 클러스터 외부에 있습니다. Kustomize는 secretGenerator와 configMapGenerator를 가지는데, 이는 파일이나 리터럴에서 Secret과 ConfigMap을 생성합니다.
configMapGenerator
파일에서 ConfigMap을 생성하려면 configMapGenerator의 files 목록에 항목을 추가하세요. 다음은 .properties 파일에서 데이터 항목이 있는 ConfigMap을 생성하는 예시입니다:
# Create a application.properties file
cat <<EOF >application.properties
FOO=Bar
EOF
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-1
files:
- application.properties
EOF
생성된 ConfigMap은 다음 명령으로 검사할 수 있습니다:
kubectl kustomize ./
생성된 ConfigMap은 다음과 같습니다:
apiVersion: v1
data:
application.properties: |
FOO=Bar
kind: ConfigMap
metadata:
name: example-configmap-1-8mbdf7882g
env 파일에서 ConfigMap을 생성하려면 configMapGenerator의 envs 목록에 항목을 추가하세요. 다음은 .env 파일에서 데이터 항목이 있는 ConfigMap을 생성하는 예시입니다:
# Create a .env file
cat <<EOF >.env
FOO=Bar
EOF
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-1
envs:
- .env
EOF
생성된 ConfigMap은 다음 명령으로 검사할 수 있습니다:
kubectl kustomize ./
생성된 ConfigMap은 다음과 같습니다:
apiVersion: v1
data:
FOO: Bar
kind: ConfigMap
metadata:
name: example-configmap-1-42cfbf598f
.env 파일의 각 변수는 생성하는 ConfigMap에서 별도의 키가 됩니다. 이는 application.properties라는 파일(과 그 모든 항목)을 단일 키의 값으로 포함하는 이전 예시와 다릅니다.
ConfigMap은 리터럴 키-값 쌍에서도 생성할 수 있습니다. 리터럴 키-값 쌍에서 ConfigMap을 생성하려면 configMapGenerator의 literals 목록에 항목을 추가하세요. 다음은 키-값 쌍에서 데이터 항목이 있는 ConfigMap을 생성하는 예시입니다:
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-2
literals:
- FOO=Bar
EOF
생성된 ConfigMap은 다음 명령으로 확인할 수 있습니다:
kubectl kustomize ./
생성된 ConfigMap은 다음과 같습니다:
apiVersion: v1
data:
FOO: Bar
kind: ConfigMap
metadata:
name: example-configmap-2-g2hdhfc6tk
생성된 ConfigMap을 Deployment에서 사용하려면 configMapGenerator의 이름으로 참조하세요. Kustomize가 이 이름을 생성된 이름으로 자동 교체합니다.
다음은 생성된 ConfigMap을 사용하는 예시 deployment입니다:
# Create an application.properties file
cat <<EOF >application.properties
FOO=Bar
EOF
cat <<EOF >deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: my-app
volumeMounts:
- name: config
mountPath: /config
volumes:
- name: config
configMap:
name: example-configmap-1
EOF
cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
configMapGenerator:
- name: example-configmap-1
files:
- application.properties
EOF
ConfigMap과 Deployment를 생성한다:
kubectl kustomize ./
생성된 Deployment는 이름으로 생성된 ConfigMap을 참조합니다:
apiVersion: v1
data:
application.properties: |
FOO=Bar
kind: ConfigMap
metadata:
name: example-configmap-1-g4hk9g2ff8
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: my-app
name: my-app
spec:
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- image: my-app
name: app
volumeMounts:
- mountPath: /config
name: config
volumes:
- configMap:
name: example-configmap-1-g4hk9g2ff8
name: config
secretGenerator
파일이나 리터럴 키-값 쌍에서 Secret을 생성할 수 있어요. 파일에서 Secret을 생성하려면 secretGenerator의 files 목록에 항목을 추가하세요. 다음은 파일에서 데이터 항목이 있는 Secret을 생성하는 예시입니다:
# Create a password.txt file
cat <<EOF >./password.txt
username=admin
password=secret
EOF
cat <<EOF >./kustomization.yaml
secretGenerator:
- name: example-secret-1
files:
- password.txt
EOF
생성된 Secret은 다음과 같습니다:
apiVersion: v1
data:
password.txt: dXNlcm5hbWU9YWRtaW4KcGFzc3dvcmQ9c2VjcmV0Cg==
kind: Secret
metadata:
name: example-secret-1-t2kt65hgtb
type: Opaque
리터럴 키-값 쌍에서 Secret을 생성하려면 secretGenerator의 literals 목록에 항목을 추가하세요. 다음은 키-값 쌍에서 데이터 항목이 있는 Secret을 생성하는 예시입니다:
cat <<EOF >./kustomization.yaml
secretGenerator:
- name: example-secret-2
literals:
- username=admin
- password=secret
EOF
생성된 Secret은 다음과 같습니다:
apiVersion: v1
data:
password: c2VjcmV0
username: YWRtaW4=
kind: Secret
metadata:
name: example-secret-2-t52t6g96d8
type: Opaque
ConfigMap처럼 생성된 Secret은 secretGenerator의 이름을 참조해 Deployment에서 사용할 수 있습니다:
# Create a password.txt file
cat <<EOF >./password.txt
username=admin
password=secret
EOF
cat <<EOF >deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: my-app
volumeMounts:
- name: password
mountPath: /secrets
volumes:
- name: password
secret:
secretName: example-secret-1
EOF
cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
secretGenerator:
- name: example-secret-1
files:
- password.txt
EOF
generatorOptions
생성된 ConfigMap과 Secret에는 콘텐츠 해시 접미사가 추가됩니다. 이는 콘텐츠가 변경되면 새 ConfigMap이나 Secret이 생성되도록 보장합니다. 접미사 추가 동작을 비활성화하려면 generatorOptions를 사용할 수 있어요. 그 외에도 생성된 ConfigMap과 Secret에 대한 교차 옵션을 지정할 수 있습니다.
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-3
literals:
- FOO=Bar
generatorOptions:
disableNameSuffixHash: true
labels:
type: generated
annotations:
note: generated
EOF
kubectl kustomize ./를 실행해 생성된 ConfigMap을 본다:
apiVersion: v1
data:
FOO: Bar
kind: ConfigMap
metadata:
annotations:
note: generated
labels:
type: generated
name: example-configmap-3
교차 필드 설정하기
프로젝트의 모든 쿠버네티스 리소스에 교차 필드를 설정하는 것은 꽤 흔합니다. 교차 필드 설정의 몇 가지 사용 사례:
- 모든 리소스에 같은 네임스페이스 설정
- 같은 이름 접두사 또는 접미사 추가
- 같은 라벨 집합 추가
- 같은 어노테이션 집합 추가
다음은 예시입니다:
# Create a deployment.yaml
cat <<EOF >./deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
EOF
cat <<EOF >./kustomization.yaml
namespace: my-namespace
namePrefix: dev-
nameSuffix: "-001"
labels:
- pairs:
app: bingo
includeSelectors: true
commonAnnotations:
oncallPager: 800-555-1212
resources:
- deployment.yaml
EOF
kubectl kustomize ./를 실행해 그 필드들이 모두 Deployment Resource에 설정되었는지 본다:
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
oncallPager: 800-555-1212
labels:
app: bingo
name: dev-nginx-deployment-001
namespace: my-namespace
spec:
selector:
matchLabels:
app: bingo
template:
metadata:
annotations:
oncallPager: 800-555-1212
labels:
app: bingo
spec:
containers:
- image: nginx
name: nginx
리소스 구성·사용자 정의하기
프로젝트에서 리소스 집합을 구성하고 같은 파일이나 디렉터리 안에서 관리하는 것은 흔합니다. Kustomize는 서로 다른 파일의 리소스 구성과 그 리소스에 패치나 다른 사용자 정의를 적용하는 것을 제공합니다.
구성하기 (Composing)
Kustomize는 다른 리소스의 구성을 지원합니다. kustomization.yaml 파일의 resources 필드는 구성에 포함할 리소스 목록을 정의합니다. resources 목록에 리소스의 구성 파일 경로를 설정하세요. 다음은 Deployment와 Service로 구성된 NGINX 애플리케이션의 예시입니다:
# Create a deployment.yaml file
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
EOF
# Create a service.yaml file
cat <<EOF > service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
run: my-nginx
EOF
# Create a kustomization.yaml composing them
cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
- service.yaml
EOF
kubectl kustomize ./의 리소스에는 Deployment와 Service 객체가 모두 포함됩니다.
사용자 정의하기 (Customizing)
패치는 리소스에 다른 사용자 정의를 적용하는 데 사용할 수 있습니다. Kustomize는 patches 필드를 통해 StrategicMerge와 Json6902의 서로 다른 패치 메커니즘을 지원합니다. patches는 파일이나 인라인 문자열일 수 있으며, 단일 또는 여러 리소스를 대상으로 합니다.
patches 필드는 지정된 순서대로 적용되는 패치 목록을 포함합니다. 패치 대상은 group, version, kind, name, namespace, labelSelector, annotationSelector로 리소스를 선택합니다.
한 가지 일만 하는 작은 패치가 권장됩니다. 예를 들어 deployment replica 수를 늘리는 패치 하나와 메모리 limit을 설정하는 패치 하나를 만드세요. 대상 리소스는 패치 파일의 group, version, kind, name 필드를 사용해 일치시킵니다.
# Create a deployment.yaml file
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
EOF
# Create a patch increase_replicas.yaml
cat <<EOF > increase_replicas.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 3
EOF
# Create another patch set_memory.yaml
cat <<EOF > set_memory.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
template:
spec:
containers:
- name: my-nginx
resources:
limits:
memory: 512Mi
EOF
cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
patches:
- path: increase_replicas.yaml
- path: set_memory.yaml
EOF
kubectl kustomize ./를 실행해 Deployment를 본다:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 3
selector:
matchLabels:
run: my-nginx
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- image: nginx
name: my-nginx
ports:
- containerPort: 80
resources:
limits:
memory: 512Mi
모든 리소스나 필드가 strategicMerge 패치를 지원하는 것은 아닙니다. 임의의 리소스에서 임의 필드를 수정하는 것을 지원하려면 Kustomize가 Json6902를 통해 JSON patch 적용을 제공합니다. Json6902 패치에 올바른 Resource를 찾으려면 kustomization.yaml에서 target 필드를 지정하는 것이 필수입니다.
예를 들어 Deployment 객체의 replica 수를 늘리는 것도 Json6902 패치로 할 수 있습니다. 대상 리소스는 target 필드의 group, version, kind, name을 사용해 일치시킵니다.
# Create a deployment.yaml file
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
EOF
# Create a json patch
cat <<EOF > patch.yaml
- op: replace
path: /spec/replicas
value: 3
EOF
# Create a kustomization.yaml
cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
patches:
- target:
group: apps
version: v1
kind: Deployment
name: my-nginx
path: patch.yaml
EOF
kubectl kustomize ./를 실행해 replicas 필드가 업데이트되었는지 본다:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 3
selector:
matchLabels:
run: my-nginx
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- image: nginx
name: my-nginx
ports:
- containerPort: 80
패치 외에도 Kustomize는 패치를 만들지 않고 컨테이너 이미지를 사용자 정의하거나 다른 객체의 필드 값을 컨테이너에 주입하는 것을 제공합니다. 예를 들어 kustomization.yaml의 images 필드에 새 이미지를 지정해 컨테이너 안에서 사용되는 이미지를 바꿀 수 있습니다.
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
EOF
cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
images:
- name: nginx
newName: my.image.registry/nginx
newTag: "1.4.0"
EOF
kubectl kustomize ./를 실행해 사용되는 이미지가 업데이트되었는지 본다:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 2
selector:
matchLabels:
run: my-nginx
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- image: my.image.registry/nginx:1.4.0
name: my-nginx
ports:
- containerPort: 80
때로는 파드에서 실행되는 애플리케이션이 다른 객체의 구성 값을 사용해야 할 수 있습니다. 예를 들어 Deployment 객체의 파드가 Env 또는 명령 인자로 해당 Service 이름을 읽어야 할 수 있습니다. kustomization.yaml 파일에 namePrefix 또는 nameSuffix가 추가되면 Service 이름이 바뀔 수 있으므로, 명령 인자에 Service 이름을 하드코딩하는 것은 권장되지 않습니다. 이런 용도로 Kustomize는 replacements를 통해 Service 이름을 컨테이너에 주입할 수 있습니다.
# Create a deployment.yaml file (quoting the here doc delimiter)
cat <<'EOF' > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
command: ["start", "--host", "MY_SERVICE_NAME_PLACEHOLDER"]
EOF
# Create a service.yaml file
cat <<EOF > service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
run: my-nginx
EOF
cat <<EOF >./kustomization.yaml
namePrefix: dev-
nameSuffix: "-001"
resources:
- deployment.yaml
- service.yaml
replacements:
- source:
kind: Service
name: my-nginx
fieldPath: metadata.name
targets:
- select:
kind: Deployment
name: my-nginx
fieldPaths:
- spec.template.spec.containers.0.command.2
EOF
kubectl kustomize ./를 실행해 컨테이너에 주입된 Service 이름이 dev-my-nginx-001인지 본다:
apiVersion: apps/v1
kind: Deployment
metadata:
name: dev-my-nginx-001
spec:
replicas: 2
selector:
matchLabels:
run: my-nginx
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- command:
- start
- --host
- dev-my-nginx-001
image: nginx
name: my-nginx
Bases와 Overlays
Kustomize에는 bases와 overlays 개념이 있습니다. base는 kustomization.yaml이 있는 디렉터리로, 리소스 집합과 관련 사용자 정의를 포함합니다. base는 안에 kustomization.yaml이 있는 한 로컬 디렉터리일 수도 있고 원격 저장소의 디렉터리일 수도 있습니다. overlay는 다른 kustomization 디렉터리를 bases로 참조하는 kustomization.yaml이 있는 디렉터리입니다. base는 overlay에 대해 알지 못하며 여러 overlay에서 사용할 수 있습니다.
overlay 디렉터리의 kustomization.yaml은 여러 bases를 참조해, 그 bases에 정의된 모든 리소스를 통합된 구성으로 결합할 수 있습니다. 또한 이러한 리소스 위에 특정 요구 사항을 충족하도록 사용자 정의를 적용할 수 있습니다.
다음은 base의 예시입니다:
# Create a directory to hold the base
mkdir base
# Create a base/deployment.yaml
cat <<EOF > base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
EOF
# Create a base/service.yaml file
cat <<EOF > base/service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
run: my-nginx
EOF
# Create a base/kustomization.yaml
cat <<EOF > base/kustomization.yaml
resources:
- deployment.yaml
- service.yaml
EOF
이 base는 여러 overlay에서 사용할 수 있습니다. 다른 overlay에서 다른 namePrefix나 다른 교차 필드를 추가할 수 있습니다. 다음은 같은 base를 사용하는 두 overlay입니다.
mkdir dev
cat <<EOF > dev/kustomization.yaml
resources:
- ../base
namePrefix: dev-
EOF
mkdir prod
cat <<EOF > prod/kustomization.yaml
resources:
- ../base
namePrefix: prod-
EOF
Kustomize로 객체 적용/보기/삭제하기
kubectl 명령에서 --kustomize 또는 -k를 사용해 kustomization.yaml이 관리하는 리소스를 인식한다. -k는 kustomization 디렉터리를 가리켜야 합니다. 예:
kubectl apply -k <kustomization directory>/
다음 kustomization.yaml이 있다고 가정한다:
# Create a deployment.yaml file
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
EOF
# Create a kustomization.yaml
cat <<EOF >./kustomization.yaml
namePrefix: dev-
labels:
- pairs:
app: my-nginx
includeSelectors: true
resources:
- deployment.yaml
EOF
다음 명령을 실행해 Deployment 객체 dev-my-nginx를 적용한다:
> kubectl apply -k ./
deployment.apps/dev-my-nginx created
다음 명령 중 하나를 실행해 Deployment 객체 dev-my-nginx를 본다:
kubectl get -k ./
kubectl describe -k ./
다음 명령을 실행해 Deployment 객체 dev-my-nginx 를, 매니페스트가 적용되었다면 클러스터가 있을 상태와 비교한다:
kubectl diff -k ./
다음 명령을 실행해 Deployment 객체 dev-my-nginx를 삭제한다:
> kubectl delete -k ./
deployment.apps "dev-my-nginx" deleted
Kustomize 기능 목록
| 필드 | 유형 | 설명 |
|---|---|---|
| bases | []string | 이 목록의 각 항목은 kustomization.yaml 파일을 포함하는 디렉터리로 해석되어야 한다 |
| commonAnnotations | map[string]string | 모든 리소스에 추가할 어노테이션 |
| commonLabels | map[string]string | 모든 리소스와 선택자에 추가할 라벨 |
| configMapGenerator | []ConfigMapArgs | 이 목록의 각 항목은 ConfigMap을 생성한다 |
| configurations | []string | 이 목록의 각 항목은 Kustomize 변환기 구성을 포함하는 파일로 해석되어야 한다 |
| crds | []string | 이 목록의 각 항목은 Kubernetes 유형에 대한 OpenAPI 정의 파일로 해석되어야 한다 |
| generatorOptions | GeneratorOptions | 모든 ConfigMap과 Secret 생성기의 동작을 수정한다 |
| images | []Image | 각 항목은 패치를 만들지 않고 하나의 이미지에 대한 이름, 태그 및/또는 다이제스트를 수정한다 |
| labels | map[string]string | 해당 선택자를 자동 주입하지 않고 라벨을 추가한다 |
| namePrefix | string | 이 필드의 값은 모든 리소스의 이름 앞에 붙는다 |
| nameSuffix | string | 이 필드의 값은 모든 리소스의 이름 뒤에 붙는다 |
| patchesJson6902 | []Patch | 이 목록의 각 항목은 Kubernetes 객체와 Json Patch로 해석되어야 한다 |
| patchesStrategicMerge | []string | 이 목록의 각 항목은 Kubernetes 객체의 strategic merge patch로 해석되어야 한다 |
| replacements | []Replacements | 리소스의 필드에서 값을 임의 개수의 지정된 대상에 복사한다 |
| resources | []string | 이 목록의 각 항목은 기존 리소스 구성 파일로 해석되어야 한다 |
| secretGenerator | []SecretArgs | 이 목록의 각 항목은 Secret을 생성한다 |
| vars | []Var | 각 항목은 한 리소스의 필드에서 텍스트를 캡처한다 |