์๋ 8์๋ถํฐ ์งํํ๋ Pinpoint Helm Chart ์ค Agent์ ๋ํ Helm Chart ์ ์ ๊ณผ์ ์ ๋ํด์ ๋ค๋ฃจ์ด๋ณด๊ณ ์ ํฉ๋๋ค.
Introduction
Pinpoint Agent๋ Java, Go, NodeJS, C ๋ฑ ๋ค์ํ ์ธ์ด์ ๋ํ agent๊ฐ ์กด์ฌํ๊ณ ๊ฐ๊ธฐ ๋ค๋ฅธ ์ฌ์ฉ๋ฐฉ๋ฒ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ๊ทธ ์ค ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ Java Agent์ ๋ํด Helm Chart ์์ฑ์ ์์ํ์์ต๋๋ค. Java Agent๋ ์คํ์ ์ํ jar ํ์ผ๊ณผ ์ ์ฉํ config๋ฅผ ํ์๋ก ํฉ๋๋ค. jar ํ์ผ๊ณผ config option์ target application์ ์คํํ ๋ ๋ถ์ฐฉํจ์ผ๋ก์จ data๋ฅผ ์์ง, collector๋ก ์ ์กํ๊ฒ ๋ฉ๋๋ค. ์ฆ, application๊ณผ ๋์ผํ ์ปจํ ์ด๋์ agent๋ฅผ ์ํ ํ์ผ์ด ์กด์ฌํ์ฌ์ผ ํฉ๋๋ค.
์ด๊ธฐ ๊ณํํ๋ ๋ฐฉ๋ฒ์ init-container๋ฅผ ์ฌ์ฉํ์ฌ Pod ์์ ์ ํ์ํ ํ์ผ์ ๋ค์ด๋ฐ๋ ๋ฐฉ๋ฒ์ด์์ต๋๋ค. ํ์ง๋ง init-container๋ก ์ค์ ํ๊ฒ ๋๋ค๋ฉด ๋ชจ๋ Pod๋ค์ ๋ํด ๋์ผํ ํ์ผ(release)๋ฅผ ๋ค์ด๋ฐ๋ ๊ณผ์ ์ด ์ค๋ณต๋๊ฒ ๋ฉ๋๋ค. ๋ํ ๋ ธ๋์ ์ง์ญ์ ๋ฐ๋ผ ๋คํธ์ํฌ ์ด์๋ก ์ธํด ํ์ผ์ ๋ค์ด ๋ฐ๋ ๊ณผ์ ์์ ์๋นํ ์๊ฐ์ด ์์๋ ์ ์์ต๋๋ค. Pod์ด ์์๋ ๋ ๋ง์ ์๊ฐ์ด ์์๋๋ค๋ ๊ฒ์ ๋ฐฐํฌ ๋ฐ ๋กค๋ฐฑ ๊ณผ์ ์์ ๋ฐ์ํ๋ ์๊ฐ์ด ์ฆ๊ฐํ๋ ๊ฒ๊ณผ ๋์ผํ๊ธฐ ๋๋ฌธ์ ์๋น์ค ์ด์ ์ธก๋ฉด์์ ์ง์ํด์ผ ํ๋ ๋ถ๋ถ์ ๋๋ค.
์ด์ ๋ฐ๋ผ ๊ฒฐ์ ํ ๋ฐฉ๋ฒ์ ์ด๊ธฐ ์ํ๋ ๋ฒ์ ์ ๋ํ Volume์ ์์ฑํ๊ณ , ํด๋น ๋ณผ๋ฅจ์ Target Application์ด ์กด์ฌํ๋ Pod์์ ๋ง์ดํธํ์ฌ ์ฌ์ฉํ๋ ๋ฐฉ์์ ๋๋ค. ์ด๋ฅผ ์งํํ๋ฉด์ ๊ฒช์๋ ๋ฌธ์ ์ํฉ, ๊ณ ๋ฏผ์ ๋ํด ๊ณต์ ํด๋ณด๊ณ ์ ํฉ๋๋ค.
์๊ตฌ์ฌํญ
Agent Helm Chart๊ฐ ์ํํด์ผ ํ ์ญํ ์ ์ ๋ฆฌํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ์ํ๋ ๋ฒ์ ์ Agent Release๋ฅผ ๋ค์ด๋ฐ์ ๋ณผ๋ฅจ์ ์ ์ฅ
- ์ฌ์ฉ์๊ฐ ์ํ๋ Custom Config๋ฅผ ConfigMap์ผ๋ก ์์ฑ
PVC ์์ฑ ๋ฐ Read-Only ์ค์
๊ฐ์ฅ ๋จผ์ ํด์ผํ๋ ์์ ์ ๊ณต์ ํ ๋ณผ๋ฅจ์ ์์ฑํ๋ ์์ ์ ๋๋ค.
๋ณผ๋ฅจ์ ์์ฑํ๋ ๋ฐฉ๋ฒ์ PV๋ฅผ ์ ์ํ๊ณ ์ด๋ฅผ ์ ์ ํ๋ก๋น์ ธ๋ํ๋ ๋ฐฉ๋ฒ๋ ์กด์ฌํ์ง๋ง ์ต๋ํ ์ผ๋ฐ์ ์ธ ์ํฉ์ ์ ์ฉํด์ผ ํ๋ ์คํ์์ค์ ํน์ฑ๊ณผ ๋ง์ง ์๋ค๊ณ ์๊ฐํ๊ณ , PVC์ StorageClass๋ฅผ ํตํด ๋์ ํ๋ก๋น์ ธ๋์ ์ง์ํ ์ ์๋๋ก ์ค์ ํ์์ต๋๋ค. ๊ธฐ๋ณธ๊ฐ์ ํด๋ฌ์คํฐ์ ์ค์ ๋ default StorageClass๋ฅผ ์ฌ์ฉํ๊ณ , ๋ง์ฝ ๊ฐ์ธ์ ์ผ๋ก ์ ์๋ StorageClass๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๋ฉด ํด๋น ๊ฐ์ ์ฝ์ ํ ์ ์๋๋ก ์ค์ ํ์์ต๋๋ค.
PVC๋ฅผ ์์ฑํ๋ฉฐ ๋ ํ๋ ๊ณ ๋ คํด์ผ ํ ์ ์ ๋์ผํ ๋ณผ๋ฅจ์ ์ฌ๋ฌ Pod์์ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ ์์์น ๋ชปํ ํ์ผ ๋ณ๊ฒฝ์ด ๋ฐ์ํ ์๋ ์๋ค๋ ์ ์ ๋๋ค. ์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด PVC์ accessMode๋ฅผ ReadOnlyMany๋ก ์ค์ ์ ํตํด ๋ค์์ Pod์ด ๋ณผ๋ฅจ์ ๋ง์ดํธํ์ฌ ์ฝ์ ์ ์์ง๋ง, ๋ณผ๋ฅจ์ ์ฐ๋ ์์ ์ ๋ถ๊ฐ๋ฅํ๋๋ก ์ค์ ํ์์ต๋๋ค. ํ์ง๋ง, ์ด๋ฅผ ํ ์คํธ ํ๋ฉฐ ์์์น ๋ชปํ ๋ฌธ์ ๋ฅผ ๊ฒช์๋๋ฐ ์ด๋ ROX(ReadOnlyMany)๋ก PVC๋ฅผ ์ค์ ํ์ฌ ๋ง์ดํธํ๋๋ฐ๋ ๋ถ๊ตฌํ๊ณ Pod์์ ๋ง์ดํธ ๊ฒฝ๋ก์ ํ์ผ์ ์ธ ์ ์๋ ํ์์ด์์ต๋๋ค. ์์ธ์ ์ฐพ๊ธฐ ์ํด kubectl describe pod์ ํตํด ํ์ธํด๋ณด๋ ๋ง์ดํธ ๋ ๋ณผ๋ฅจ์ด rw ๊ถํ์ ๊ฐ์ง๊ณ ์์์ต๋๋ค.
๋ํ GKE์์ StorageClass๋ฅผ ์ค์ ํ์ง ์์์ ๋ ์ ํ๋๋ pd-standard๋ก ๋์ ํ๋ก๋น์ ธ๋ ๋ PV๋ฅผ ์ดํด๋ณด๋ ์ฌ๊ธฐ์๋ readOnly: false๋ก ์ค์ ๋์ด ์์์ต๋๋ค.
ํ์ง๋ง PVC๋ ๋ถ๋ช ROX๋ก ์ค์ ๋์ด ์๋ ๊ฒ์ ํ์ธํ ์ ์์์ต๋๋ค.
์ด์ ๋ํด ์ฐพ์๋ณธ ๊ฒฐ๊ณผ, ๋์ผํ ์ด์๊ฐ ์ด๋ฏธ ์กด์ฌํ์์ต๋๋ค. GooglePersistentDisk๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ PVC์ ROX๋ก ์ค์ ํด์ฃผ๋๋ผ๋ ์ํฌ๋ก๋์์ readOnly: true๋ฅผ ์ค์ ํด์ค์ผ readOnly๊ฐ ์ ์ฉ๋๋ค๊ณ ํ์ฌ ์ด๋ฅผ ์ ์ฉํด์ ํด๊ฒฐํ์์ต๋๋ค.
์ด์ ๋ํ ์์ธ์ ์ด์์์๋ ๋ช
ํํ ์ ์๋์ง ์์์ ์ถํ ๋ ์ฐพ์๋ณผ ์์ ์
๋๋ค.
Init Job ์์ฑ
๋ค์์ผ๋ก ์งํํด์ผ ํ ์์ ์ Job์ ํตํด ์ํ๋ ๋ฒ์ ์ pinpoint-agent ํ์ผ์ ๋ค์ด๋ฐ์ ๋ณผ๋ฅจ์ ๊ณต์ ํ๋ ์์ ์ ๋๋ค. Job์ Pod์ ํ์ผ์ ์ ์ฅํด์ผ ํ๊ธฐ ๋๋ฌธ์ readOnly: true๋ฅผ ์๋ตํ์์ต๋๋ค.
Job์์ ์ํํ๋ ์์ ์ values.yaml์ ์ค์ ๋ agent-version์ ๋ง๋ release๋ฅผ ๋ค์ด๋ฐ์ ๋ณผ๋ฅจ์ /agent/config์ ์ ์ฅํ๊ฒ ๋ฉ๋๋ค.
Helm Lifecycle Hook ์ค์
Job์ ์ฌ์ฉํจ์ผ๋ก์จ ๊ณ ๋ คํด์ผ ํ ์ ์ ํด๋น Job์ ์ด๋ป๊ฒ ํธ๋ฆฌ๊ฑฐ ์ํฌ ๊ฒ์ธ์ง ์ ๋๋ค. Job์ ์คํํ๋ ์คํฌ๋ฆฝํธ๋ฅผ ์งค ์๋ ์์ง๋ง ์ด๋ ์์ ํ ์๋ํ๊ฐ ์๋๋ผ๊ณ ์๊ฐํ๊ณ ๊ด๋ จ ๋ด์ฉ์ ์ฐพ๋ ์ค Helm Lifecycle Hook์ ๋ํ ๋ด์ฉ์ ์ ํ์ต๋๋ค.
Helm Lifecycle Hook ์ค "helm.sh/hook"์ ์ธ์ ํด๋น ์์
์ ์คํํ ์ง ๊ฒฐ์ ํ๋ ์ญํ ์ ํฉ๋๋ค. PVC๋ฅผ ์์ฑํ๊ณ Job์ ์คํํด์ผ ํ๋ ์์ ์ Helm Chart๋ฅผ ์ค์นํ ๋, ๊ทธ๋ฆฌ๊ณ ๋ฒ์ ์
๊ทธ๋ ์ด๋๋ฅผ ์งํํ ๋์ด๊ธฐ ๋๋ฌธ์ "helm.sh/hook": pre-install,pre-upgrade ์ด๋
ธํ
์ด์
์ ์ถ๊ฐํ์ฌ ํด๋น ์์
์ด ์ค์น ๋ฐ ์
๊ทธ๋ ์ด๋ ์ ์๋์ผ๋ก ์ด๋ฃจ์ด์ง ์ ์๋๋ก ์ค์ ํ์์ต๋๋ค.
๋ค์์ผ๋ก ๊ณ ๋ คํ ์ ์ PVC์ Job ์์ฑ์ ์์์ ๋ํ ๋ถ๋ถ์ ๋๋ค. PVC๊ฐ ๋จผ์ ์ํ๋ ์ดํ์ Job์ด ์ํ๋์ด์ผ ํ๋ฏ๋ก hook์ ๊ฐ์ค์น๋ฅผ ์ค์ ํ๋ "helm.sh/hook-weight" ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํด ์์๋ฅผ ์ ์ดํ์์ต๋๋ค. PVC์ ๊ฐ์ค์น๋ 1๋ก Job์ ๊ฐ์ค์น๋ 2๋ก ์ค์ ํ์ฌ PVC๊ฐ ์์ฑ๋ ์ดํ Job์ด ์์ฑ๋๋๋ก ์ค์ ํ์์ต๋๋ค.
Helm Lookup
๋ค์์ผ๋ก ๊ณ ๋ คํ ์ ์ Agent์ ๋ฒ์ ์ด ๋ณ๊ฒฝ๋์ง ์์์ง๋ง ๋ค๋ฅธ ์ค์ ๋ค์ด ๋ณ๊ฒฝ๋๋ ์ํฉ์ ๋๋ค(์๋ฅผ ๋ค๋ฉด external configuation์ด ์ถ๊ฐ๋ ๊ฒฝ์ฐ). agent์ ๋ฒ์ ์ด ๋ณํ์ง ์๋ ๊ฒฝ์ฐ์๋ PVC๊ฐ ์ด๋ฏธ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ PVC ์์ฑ ๋ฐ Job ์์ฑ ์์ ์ด ์คํจํ๊ฒ ๋ฉ๋๋ค. ๋ฐ๋ผ์ ์ํ๋ Agent Version์ ํด๋นํ๋ PVC๊ฐ ์กด์ฌํ๋ ๊ฒฝ์ฐ์๋ ์์ ์์ ์ ์ํํ์ง ๋ง์์ผ ํฉ๋๋ค. Helm ๋ฌธ์๋ฅผ ์ฐพ์๋ณธ ๊ฒฐ๊ณผ kubectl get <resource-type> <name>๊ณผ ๋์ผํ ์ญํ ์ ํ๋ lookup ํจ์๋ผ๋ ๊ฒ์ด ์๋ค๋ ๊ฒ์ ๋ฐ๊ฒฌํ๊ณ ์ด๋ฅผ ํตํด์ agent version์ด ๋ณํ์ง ์๋ ๊ฒฝ์ฐ์๋ PVC ๋ฐ Job ์์ฑ์ ํ์ง ์๋๋ก ์ค์ ํ์์ต๋๋ค.
์ต์ข ์ ์ผ๋ก ์ค์ ํ PVC์ Job์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
PVC
{{- $agentpvc := (lookup "v1" "PersistentVolumeClaim" .Release.Namespace (printf "agent-%s-pvc" .Values.agent.version )) }}
{{- if not $agentpvc }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: agent-{{ .Values.agent.version }}-pvc
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "1"
labels:
{{ include "pinpoint-agent.labels" . | indent 4}}
spec:
{{- if .Values.agent.storageClass }}
storageClassName: {{ .Values.agent.storageClass}}
{{- end}}
accessModes:
- ReadOnlyMany
resources:
requests:
storage: 1Gi
{{- end -}}
Job
{{- $agentJob := (lookup "batch/v1" "Job" .Release.Namespace (printf "agent-%s-downloader" .Values.agent.version )) }}
{{- if not $agentJob }}
apiVersion: batch/v1
kind: Job
metadata:
name: agent-{{.Values.agent.version}}-downloader
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation
"helm.sh/hook-weight": "2"
labels:
{{ include "pinpoint-agent.labels" . | indent 4}}
spec:
template:
spec:
containers:
- name: downloader
image: alpine
command:
- sh
- -c
- |
wget https://github.com/pinpoint-apm/pinpoint/releases/download/v{{ .Values.agent.version }}/pinpoint-agent-{{ .Values.agent.version }}.tar.gz
tar xvzf pinpoint-agent-{{ .Values.agent.version }}.tar.gz
mv pinpoint-agent-{{ .Values.agent.version }} ./agent-init/pinpoint-agent
volumeMounts:
- name: agent-init
mountPath: /agent-init
volumes:
- name : agent-init
persistentVolumeClaim:
claimName: agent-{{ .Values.agent.version }}-pvc
restartPolicy: Never
backoffLimit: 3
{{- end -}}
์์ ์์ ์ ํตํด ๊ณตํต์ ์ผ๋ก ์ฌ์ฉ๋๋ Pinpont Agent Release ํ์ผ์ ์ค๋น๊ฐ ๋์์ต๋๋ค. ๋ค์์ผ๋ก ํด์ผํ ์์ ์ ๊ฐ ์ดํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ Custom ์ค์ ์ ์ฃผ์ ํ๋ ๋ฐฉ๋ฒ์ ๋๋ค.
ConfigMap ์์ฑ
๊ฐ์ธ์ ์ผ๋ก Config ํ์ผ์ ConfigMap์ ์ค์ ํ๋ ๋ฐฉ๋ฒ์ ๊ฐ๋
์ฑ์ด ๋จ์ด์ง๋ค๊ณ ์๊ฐํ์ฌ(๊ฐ์ธ์ ์ธ ์๊ฒฌ์
๋๋ค.) ์ธ๋ถ์ ์ค์ ํ์ผ์ ์์น์ํค๋ ๊ฒ์ ์ ํธํฉ๋๋ค. ๋ฐ๋ผ์ files/conf ์ด๋ผ๋ ๋๋ ํ ๋ฆฌ๋ฅผ ์์ฑํ๊ณ ํด๋น ๋๋ ํ ๋ฆฌ ํ์์ ์๋ ํ์ผ์ ConfigMap์ผ๋ก ์ฌ์ฉํ ์ ์๋๋ก ํ์์ต๋๋ค.
์ด ๋ ๋ชจ๋ ์ค์ ํ์ผ์ ํ๋์ ConfigMap์ ์ค์ ํ ์๋ ์์ง๋ง ๊ฒฐ๊ตญ ํ๋์ ์ดํ๋ฆฌ์ผ์ด์ ์์ ํ์ํ ์ค์ ํ์ผ์ ํ๋์ด๊ณ ๋๋จธ์ง ํ์ผ๋ค์ ๋ถํ์ํ๋ค๊ณ ์๊ฐํ์ฌ values.yaml์์ externalConfigName์ ํตํด application์ ์ถ๊ฐํ๊ธฐ ์ํ๋ ์ค์ ํ์ผ์ ์ด๋ฆ์ ์ฃผ์ ํ๋ฉด ํด๋นํ๋ configmap๋ง ์์ฑํ๋๋ก ์ค์ ํ์์ต๋๋ค.
ํ์ผ์ ConfigMap์ผ๋ก ์ ์ฅํ๋ ๋ถ๋ถ์ Files.Get์ ์ฌ์ฉํ์์ต๋๋ค.
ConfigMap
{{ if .Values.agent.externalConfigName }}
apiVersion: v1
kind: ConfigMap
metadata:
name: external-config-{{ .Values.agent.externalConfigName }}
labels:
{{ include "pinpoint-agent.labels" . | indent 4}}
data:
{{ .Values.agent.externalConfigName}}.config: |
{{ .Files.Get (printf "files/conf/%s.config" .Values.agent.externalConfigName ) | indent 4 }}
{{- end -}}
์ต์ข ์ ์ผ๋ก agent ์ฌ์ฉํ๊ณ ์ ํ๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ๋ค์๊ณผ ๊ฐ์ ์ค์ ์ด ํ์ํฉ๋๋ค.
- EXTERNAL_CONFIG_PATH : ์ปค์คํ ์ค์ ์ ์์น๋ฅผ ์คํ ์ ์ต์ ์ผ๋ก ๋ฃ์ด์ฃผ๊ธฐ ์ํ ํ๊ฒฝ๋ณ์์ ๋๋ค.
- ConfigMap VolumeMount : ์ํ๋ ์ปค์คํ ์ค์ ์ ๋ง์ดํธํ๊ธฐ ์ํ ์ต์ ์ ๋๋ค.
- PVC VolumeMount : ์ํ๋ ๋ฒ์ ์ release ํ์ผ์ ๋ง์ดํธํ๊ธฐ ์ํ ์ต์ ์ ๋๋ค.
์์ ์ดํ๋ฆฌ์ผ์ด์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deploy-1
labels:
app: test-deploy-1
spec:
replicas: 1
selector:
matchLabels:
app: test-deploy
template:
metadata:
labels:
app: test-deploy
spec:
containers:
- name: test
image: alpine
command:
- sh
- -c
- |
tail -f /dev/null
env:
- name: EXTERNAL_CONFIG_PATH
value: "/pinpoint/config/{{ .Values.agent.externalConfigName}}"
volumeMounts:
- name: agent-init
mountPath: /agent-init
- name: agent-external-config
mountPath: /pinpoint/config
volumes:
- name: agent-init
persistentVolumeClaim:
claimName: agent-{{ .Values.agent.version }}-pvc
readOnly: true
- name: agent-external-config
configMap:
name: external-config-{{ .Values.agent.externalConfigName }}
๋ถ์กฑํ ๋ถ๋ถ์ด ๋ฌผ๋ก ๋ง์ง๋ง ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ๊ธ์ ์์ฑํ๋ ์ด์ ๋ ํด๋น ์์ ์ ์งํํ๋ฉด์ ํ์ ๋์น๊ณ ์์๋ accessMode๋ Helm์ ๋ถ๊ฐ ๊ฐ๋ฅ์ ๋ํด์ ์ ์ ์๋ ์๊ฐ์ด์๊ณ ์ด๋ฅผ ๊ณต์ ํ๊ธฐ ์ํด์์ ๋๋ค. Agent๋ฅผ ์ํ Helm Chart ์์ฑ ์์ ์ ์ฌ์ ํ ์งํ ์ค์ด๊ณ ๋ ์ข์ ์๊ฒฌ์ด ์์ผ์ ๋ถ๋ค์ ๊ณต์ ํด์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค!
๋ชจ๋ ์ฝ๋๋ Github์์ ํ์ธํ์ค ์ ์์ต๋๋ค.
2021.03.23 ์์
- jar ํ์ผ์ ๋ํด ์ฌ๋ฌ Pod์ด ์ฌ์ฉํ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์, PV๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
'๐ Kubernetes' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Dynamic Admission Controller ์ฌ์ฉํ๊ธฐ (0) | 2021.04.29 |
---|---|
[Kubernetes ๋ด๋ถ ๊ตฌ์กฐ ์ดํดํ๊ธฐ] 1. ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ ๊ตฌ์ฑ ์์ (0) | 2021.04.12 |
Elasticsearch Operator ๊ฐ๋ฐํ๊ธฐ (0) | 2020.12.18 |
Kubernetes Operator (feat. Operator SDK) (0) | 2020.12.18 |
Argo Project๋ฅผ ์ฌ์ฉํ์ฌ CI/CD ๊ตฌ์ถํ๊ธฐ (0) | 2020.12.18 |
๋๊ธ