들어가기 전에, 서비스라는 것은 파드의 형태로 띄워지는 것이 아니다. 서비스를 클러스터에 적용하면, 모든 워커 노드의 kube-proxy 컴포넌트 파드가 자신이 속한 노드의 운영체제 커널의 네트워크 시스템에 iptables 또는 IPVS 규칙을 수정하는 것이다. 즉, 서비스는 클러스터 내의 모든 워커 노드에 적용되는 네트워크 라우팅 규칙 그 자체인 셈이다. 

 

1. ClusterIP

내부적으로 Service 와 동일한 이름의 Endpoint 오브젝트가 생성되고, 이 Endpoint 에 Service 의 selector 에 매칭되는 Pod 들의 IP 가 subsets 항목으로 등록된다. 이를 서비스 레지스트리라고 한다.

클러스터 내부에 DNS 가 생성되며, 각 서비스들의 IP(클러스터 내부 IP)가 서비스명과 매핑되어 등록된다. 그래서 클러스터 내부의 파드에서 서비스명으로도 서비스를 호출할 수 있다. 이를 서비스 디스커버리라고 한다.

clusterIP 를 명시적으로 "None" 으로 지정하면 서비스에 IP가 할당되지 않으며, 서비스명으로 질의시 실제 selector 로 연결된 파드의 IP 목록이 조회된다.(서비스 진입 가능한 IP가 없어서 헤드리스 서비스라고 함) 사용 용도로는 파드 상태 수집용 서버가 호출하는 용도, StatefulSet 으로 관리하는 DB용 파드를 직접 호출하는 용도가 있다.(StatefulSet 으로 관리되는 파드는 파드명이 고정된 index suffix 로 생성된다.) 먼저 첫번째 케이스에서는, 파드 상태 수집용 서버에서 각 파드 IP를 aware 하고 있어야 하기 때문에 헤드리스 서비스를 호출하여 파드 IP 목록을 조회해서 사용한다. 두번째 케이스에서는, DB용 파드가 여러개 있고 각 파드가 목적이 다를 때(읽기용, 일기/쓰기용 등), 헤드리스 서비스로 연결된 파드라면 백엔드 애플리케이션 파드에서는 <파드명>.<서비스명> 형태의 도메인 형식으로 특정 파드를 지정해 호출할 수 있게 된다.

 

2. NodePort

서비스의 nodePort 항목을 지정하지 않으면 자동으로 각 워커노드의 30000~32768 포트 중에 하나가 오픈된다.(모든 워커노드의 동일한 포트가 오픈된다.) 내부적으로는 ClusterIP 처럼 서비스 레지스트리와 서비스 디스커버리에 해당하는 네트워크 규칙이 자동으로 생성된다. 열려진 노드 포트로 외부 네트워크에서 직접 접속이 가능하며(서비스 퍼블리싱), 해당 노드에 파드가 없더라도 다른 노드로 라우팅되기 때문에 클러스터 내의 적절한 파드로 트래픽이 분산된다.

 

3. LoadBalancer

온프레미스의 메탈LB나 퍼블릭 클라우드 제공자의 로드밸런서를 생성한다. 이 로드밸런서에는 공인IP가 부여되어 외부 네트워크에서 접속하는 단일 진입점으로 활용된다.(서비스 퍼블리싱) 내부적으로는 NodePort 서비스가 생성되고, 로드밸런서에서 모든 노드의 IP와 Port 를 aware 하고 트래픽을 적절히 분산한다. 그 이후의 트래픽 흐름은 NodePort 서비스와 동일하다.

 

4. ExternalName

다른 서비스 타입들이 클러스터 외부에서 내부로 통신이 가능하게 해주는 반면, ExternalName 서비스는 클러스터 내부에서 외부 공인 DNS 에 질의할 수 있도록 해주는 서비스이다. externalName 이라는 속성에 연결하고자 하는 도메인을 지정한다. 클러스터 내부에서는 ExternalName 서비스명으로 질의하게 되면 외부 공인 DNS 서버에서 도메인명을 해석하게 된다. 여러 파드들에서 목적지 도메인을 수정하지 않고도 ExternalName 서비스의 externalName 도메인만 수정하면 한번에 연결되는 도메인을 변경할 수 있어 유용하다. 하지만, Pod -> ExternalName 서비스 -> 공인 DNS 도메인 해석 -> 해석받은 IP로 호출되는 과정에서 Pod 에서 질의한 도메인이 ExternalName 서비스명이 되기 때문에, 목적지 서버에서 https 프로토콜을 쓴다면 변조된 트래픽으로 판단하여 통신할 수 없다는 큰 단점이 있다.(거의 사용 안함)

 

5. 그 외

ClusterIP, NodePort 서비스인 경우 externalIPs 항목이 쓰이기도 하는데, externalIPs 항목에 특정 노드의 IP 를 지정하면 외부 네트워크에서 해당 노드로 직접 접속이 가능하게 된다.(서비스 퍼블리싱) 이때 노드에서 개방되는 Port 는 port 항목과 동일하며, 포트 범위의 제한이 없다. 다만, 선택한 노드만으로 접속 가능하다는 점과 노드 IP를 직접 고정해야 한다는 제약이 있어 학습/테스트 용도로만 쓰인다.

블로그 이미지

망원동똑똑이

프로그래밍 지식을 자유롭게 모아두는 곳입니다.

,

쿠버네티스 클러스터에 Argo CD 와 ArgoCD Image Updater 를 설치했다면 이제 Argo CD application 에 자동 배포 설정을 해야 한다. 이때 아래 그림처럼 application 에 annotation 설정만 해주면 된다.

 

각각의 항목은 다음과 같은 규칙으로 세팅한다.

key value 의미
argocd-image-updater.argoproj.io/image-list <alias>=<Dockerhub-Username>/<Dockerhub-Repositoryname> 도커 허브에서 이미지 대상 지정
argocd-image-updater.argoproj.io/<alias>.update-strategy name|semver|latest|digest 업데이트 전략 선택
argocd-image-updater.argoproj.io/<alias>.allow-tags regexp:<Tag-Regular-Expressions> 태그 정규식 설정

 

key 의 <alias> 부분은 image-list annotation 에서 지정한 value 의 alias 로 지정하면 된다. 해당 이미지에 대해 적용할 규칙/전략을 세팅한다는 의미이다.

update-strategy 는 name, semver, latest, digest 가 올 수 있는데, 각각의 의미는 아래와 같다.

전략 의미 특징
name/alphabetical 알파벳 오름차순으로 정렬된 목록의 마지막 태그로 업데이트 YYYY-MM-DD 형태의 캘린더 버저닝 처럼 문자열 정렬만으로 우선순위 비교가 가능한 경우에 적합하다.
semver 주어진 이미지 제약 조건에 따라 허용되는 가장 높은 버전으로 업데이트(Semantic Versioning)(기본값) 1.x, 1.2.x와 같이 버전 제약 조건을 지정하여 특정 마이너/패치 버전 범위 내에서 가장 높은 버전을 찾아 업데이트한다. 태그 이름에 X.Y.Z 형태의 숫자가 포함되어야 한다.
latest/newest-build 가장 최근에 생성된 이미지 태그로 업데이트(빌드 날짜(Build Date)가 가장 최신인 이미지) Git 커밋 SHA나 랜덤 문자열처럼 버전 순서를 매길 수 없는 태그를 사용할 때 유용하다. 단, 태그가 생성되거나 푸시된 날짜가 아니라 이미지 내부의 ' 빌드 날짜 '를 기준으로 판단한다는 점에 유의하자.
digest 고정된 단일 태그(예: latest, dev, stage)를 모니터링하다가, 해당 태그의 SHA 다이제스트(Digest)가 변경되면 업데이트 동일한 태그 이름을 계속 재사용하는 가변 태그(Mutable Tag) 방식을 사용할 때 유일하게 사용 가능한 전략이다.

 

'CICD > Argo' 카테고리의 다른 글

[ARGO] Argo CD 아키텍쳐  (0) 2026.06.01
[ARGO] Argo 의 대표적인 제품  (0) 2026.05.28
블로그 이미지

망원동똑똑이

프로그래밍 지식을 자유롭게 모아두는 곳입니다.

,

ArgoCD 를 사용하던 중 application 을 생성할 때 설정하는 GENERAL > Prune Propagation Policy 이 눈에 띄었다.

항상 기본값(foreground)로 두고 사용하는데, 각각의 값들은 어떤 의미를 가질까?
 

1. Prune Propagation Policy 이 실제로 하는 일

이 설정에 따라 실제 내부에서 kube-apiserver 로 날리는 kubectl delete 커맨드의 --cascade 옵션 값이 달라진다. 예를 들어 kubectl 에서는
$ kubectl delete deployment sample-deployment --cascade=background

와 같이 옵션을 줄 수 있다. cascade 옵션에 올 수 있는 값은 foreground, background, orphan 이 있으며, 그 설명은 아래와 같다.

옵션 값 삭제 순서 특징
foreground 자식 -> 부모(synchronous) 기본값. 자식 오브젝트가 모두 삭제될 때까지 부모 오브젝트가 terminating 상태로 대기한다. 가장 안전한 방식.
background 부모 -> 자식(garbage collection. asynchronous 효과) 부모 오브젝트를 바로 삭제하고 바로 응답함. 자식 오브젝트는 백그라운드에서 가비지 컬렉터가 정리한다.
orphan 부모 부모 오브젝트만 삭제하고 자식 오브젝트는 유지(가비지 컬렉트 대상 아님)
deployment > replicaset > pod 순서로 부모-자식 관계가 설정되는데, 이는 리눅스의 프로세스 트리와 비슷하다. background 에서의 동작처럼, 부모 프로세스가 삭제되면 자식 프로세스가 자동으로 삭제되는 식이다. 
 

2. orphan 은 왜 garbage collection 대상이 아닐까?

쿠버네티스서는 부모-자식 관계를 Owner Reference 메커니즘으로 설명하고 있다. 자식 오브젝트들은 본인의 부모 오브젝트가 어떤 오브젝트인지 특정 필드에 그 참조를 저장하고 있다. --cascade=orphan 으로 부모 오브젝트를 삭제하면 아래와 같은 일들이 일어난다.

  1. 소유권 연결고리 변경: kube-apiserver 는 부모를 지우기 직전에 자식들의 설정에 적힌 ownerReferences(부모가 누구인지 적어둔 필드)를 삭제한다.
  2. 독립된 오브젝트가 됨: 부모가 사라진 자식들은 클러스터상에서 부모 없는 독립적인 오브젝트로 인식된다.
  3. 가비지 컬렉터 패스: 가비지 컬렉터는 부모가 명시되어있지만 존재하지는 않는 오브젝트를 정리하는 것이므로, ownerReferences 필드 자체가 없는 오브젝트는 건드리지 않는다.

 

3. orphan 은 언제 쓸까?

pod 들은 유지한 채로, 이를 관리하는 상위 컨트롤러만 교체하고 싶을 때 사용한다. 예를 들어, deployment 설정이 꼬여서 새로 만들고 싶지만, pod 들은 유지해야 하는 경우 사용한다. 다시 부모-자식을 부착하기 위해서는 동일한 라벨을 가진 deployment 를 다시 생성하면 된다. 기존의 pod 들은 다시 그 deployment 의 관리하에 들어가게 된다.

 

참고

https://kubernetes.io/ko/docs/tasks/administer-cluster/use-cascading-deletion/#set-orphan-deletion-policy

 

클러스터에서 캐스케이딩 삭제 사용

이 페이지에서는 가비지 수집 중 클러스터에서 사용할 캐스케이딩 삭제 타입을 지정하는 방법을 보여준다. 시작하기 전에쿠버네티스 클러스터가 필요하고, kubectl 커맨드-라인 툴이 클러스터와

kubernetes.io

https://kubernetes.io/ko/docs/concepts/architecture/garbage-collection/

 

가비지(Garbage) 수집

쿠버네티스가 클러스터 자원을 정리하기 위해 사용하는 다양한 방법을 종합한 용어이다. 다음과 같은 리소스를 정리한다: 종료된 잡 소유자 참조가 없는 오브젝트 사용되지 않는 컨테이너와 컨

kubernetes.io

 

블로그 이미지

망원동똑똑이

프로그래밍 지식을 자유롭게 모아두는 곳입니다.

,

아래 이미지를 참고하며 글을 읽으면 이해에 도움이 된다.

 

1. Argo CD 컴포넌트

Argo CD 를 설치하면 생성되는 컴포넌트들과 그 역할은 다음과 같다.

컴포넌트명(Pod) 역할
Server Argo CD 의 API 서버이면서, Argo CD 대시보드 역할. argocd CLI 명령을 받는 서버임
Repo Server 배포용 Git Repository 에 연결되어 클러스터에 배포할 매니페스트를 생성해줌
Application Controller k8s 클러스터의 리소스를 모니터링하며, Repo Server 로부터 받아온 Git 의 매니페스트와 클러스터의 리소스 상태가 동일한지 비교함. 동일하지 않은 경우 Git 매니페스트 기반으로 리소스 apply 를 하도록 Kube API 로 요청을 보냄 
Notification Argo CD 에서 발생하는 이벤트를 외부로 트리거해줌(Slack 연동 등에 사용)
Dex 연결된 솔루션에 대한 통합 인증을 위해 SSO 같은 IAM 솔루션을 연동해줌
Redis Kube API 에 대한 요청, 배포용 Git Repository 에 대한 요청을 캐싱해줌
ApplicationSet Controller CICD 서버에서 모든 환경의 k8s 클러스터를 배포하는 경우, 여러 환경(멀티 클러스터)에 대한 app 패키징이 필요한데, 이를 관리하기 편하도록 템플릿화 해줌
Kube API kube-apiserver 로 배포 명령어를 전송해줌

 

2. Argo CD 가 배포용 Git 의 배포구성을 클러스터에 적용하는 워크플로우

  1. Argo CD 가 배포용 Git 저장소의 배포구성 변경사항을 쿠버네테스 클러스터에 적용하는 순서는 아래와 같다.
  2. Repo Server 는 배포파일이 저장된 Git Repository 를 감시하며, 변경사항이 존재하면 해당 변경사항으로 배포할 매니페스트를 생성한다.(=> Desired Manifest) 참고로, Argo CD 는 패키지 매니저인 Helm, Kustomize 를 내장하고 있기 때문에 별도로 설치할 필요가 없으며, Git Repository 의 배포 파일 구성에 따라 자동으로 패키지 매니저(또는 기본 매니페스트)를 인식하여 작동한다.
  3. 매니페스트를 Application Controller 로 전달한다.
  4. Application Controller 는 클러스터의 현재 리소스와 전달받은 매니페스트를 비교하며, 변경사항이 있을시 Kube API 로 변경사항을 전달한다.
  5. Kube API 는 전달받은 변경사항을 클러스터에 적용하도록 kube-apiserver 에 배포명령을 전달한다.
  6. 클러스터에 적용이 완료되면 클러스터의 현재 리소스 상태를 기반으로 Live Manifest 를 생성한다.

 

3. Desired Manifest vs Live Manifest

Live Manifest 는 클러스터의 실제 리소스를 기반으로 만들어진다.(Live Manifest 가 먼저 만들어지고, 이를 기반으로 클러스터에 배포되는 것이 아님에 유의하자.) Argo CD 에서 편의기능으로 Live Manifest 를 수정하면 클러스터에 동기화 되도록 지원해주긴 한다.

Desired Manifest 는 Argo CD 의 Repo Server 가 만들며, 배포용 Git 의 매니페스트를 기반으로 만든다. 기본적으로 Git 의 수정사항이 발생하면 최대 3분 이내에 Desired Manifest 가 생성된다.(3분 주기 Sync)

주의할 점은, Argo CD 대시보드에서 볼 수 있는 Diff 는 Desired Manifest vs Live Manifest 가 아니라, 배포시 변경될 부분을 표시해준다. 즉, Live Manifest 를 직접 수정해서 k8s 클러스터에 변경 배포가 일어났더라도, 그 사항이 Desired Manifest 에도 설정된 사항이 아니라면, 덮어씌워지지 않을 것이기 때문에 Diff 에 표시되지 않는다는 점에 주의하자.

'CICD > Argo' 카테고리의 다른 글

[ARGO] Image Updater 의 자동배포 설정하기  (0) 2026.06.07
[ARGO] Argo 의 대표적인 제품  (0) 2026.05.28
블로그 이미지

망원동똑똑이

프로그래밍 지식을 자유롭게 모아두는 곳입니다.

,

1. Argo CD

쿠버네티스 전용 배포 솔루션이다. 배포파일(쿠버네티스 리소스 매니페스트, helm 패키지, kustomize 패키지) 레포지토리로 git 저장소가 요구된다. 지정한 배포파일 저장소의 특정 디렉토리를 감시하며, 변경사항이 발생하면 클러스터의 현재 배포상태와 비교하여 변경된 부분을 자동으로 배포해준다.

 

2. Argo Image Updater

Argo CD 에 추가하여 사용하는 배포 솔루션이다.(Argo CD 없이 독립적으로 사용 불가) Argo CD 는 기본적으로 연결해놓은 git 기반 배포 레포지토리의 소스코드 변경사항을 지켜보고, 변경이 일어날 시 자동으로 클러스터에 배포를 진행한다. 하지만 Argo Image Updater 를 설치하면 Docker Hub 같은 컨테이너 레지스트리의 이미지를 지켜보게 할 수 있고, 이미지의 태그(버전)이 변경되면 이 변경사항을 github 의 배포 레포지토리에 커밋해준다. 배포 레포지토리의 소스코드가 변경되었으므로, 이후의 배포 과정은 Argo CD 가 기존대로 진행한다.

 

3. Argo Rollouts

쿠버네티스의 Deployment 는 기본 배포 전략으로 RollingUpdate 와 Recreate 만 지원한다. Argo Rollouts 는 Blue/Green 배포나 Canary 배포를 지원해주는 솔루션이다. ArgoCD 를 사용하지 않고 Rollouts 만 사용할 수도 있다.

 

4. Argo Events

kafka 와 같이 이벤트 버스 역할을 하는 솔루션이다. 여러 시스템간에 이벤트를 주고 받는 통로의 역할을 한다.

 

5. Argo Workflow

airflow, kubeflow 와 같은 워크플로우 관리 도구이다. 작업의 실행 순서도를 정의할 수 있다.

'CICD > Argo' 카테고리의 다른 글

[ARGO] Image Updater 의 자동배포 설정하기  (0) 2026.06.07
[ARGO] Argo CD 아키텍쳐  (0) 2026.06.01
블로그 이미지

망원동똑똑이

프로그래밍 지식을 자유롭게 모아두는 곳입니다.

,

1. CICD 서버에 저장해두고 사용하는 방식의 단점

k8s 로 배포하는 구성을 Jenkins 로 진행하는 경우, Jenkins가 설치된 CICD 서버에서 아래 두가지 스테이지를 진행하게 된다.

  • 빌드된 이미지를 container registry 에 push(docker push)
  • k8s 클러스터에 오브젝트들을 배포(helm upgrade --install 또는 kubectl apply)

docker push 를 위해서는 CICD 서버에서 docker hub에 로그인이 되어 있어야 한다. 아래와 같은 경로에 계정 정보가 base64 인코딩 되어있다.

$ cat ~/.docker/config.json
{
    "auths": {
        "https://index.docker.io/v1/": {
            "auth": "<base64 인코딩 된 id:password 값>"
        }
    }
}

<id>:<passowrd> 평문을 base64 인코딩 한 값이라서, 이 값을 알게 되면 누구나 실제 id, password 값을 쉽게 알 수 있다.

또한 k8s 클러스터의 관리자 인증서는 아래와 같은 경로에 존재한다.

$ cat /var/lib/jenkins/.kube/config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: ...
    server: ...
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: ...
    client-key-data: ...

이 인증서 정보를 알게되면 관리자 권한으로 k8s 클러스터에 명령어를 보낼 수 있게 되어 매우 위험하다. 이러한 중요한 기밀정보를 CICD 서버에 영구 저장해두고 사용하는 방식은 바람직하지 않다.

 

2. Jenkins 의 Credentials 으로 생성하기

따라서 이러한 중요한 데이터를 암호화하여 관리하기 위해 Jenkins 의 Credentials 을 사용할 수 있다.

아래와 같은 경로로 이동한다.

 

Jenkins 관리 > Credentials > System > Global > Add Credentials

 

여기서 먼저 Username with password 를 선택해서 Docker hub 계정정보를 credentials 로 생성해준다.

 

다음으로 아래 이미지처럼 k8s 인증서를 Secret file 로 등록한다. 인증서는 미리 CICD 서버에서 로컬 컴퓨터로 복사해두고 업로드한다.

 

3. CICD 서버에서 인증정보 삭제하기

아래 명령어로 docker logout 하여 도커 허브 인증정보를 삭제한다.

$ docker logout
Removing login credentials for https://index.docker.io/v1/

// 인증정보가 삭제됨을 확인
$ cat ~/.docker/config.json
{
        "auths": {}
}

 

아래 명령어로 쿠버네티스 인증서 파일을 삭제한다.

$ rm -rf ~/.kube/config

// kubectl 명령어를 날려 권한 없음 확인
$ kubectl get pods -A
E0526 23:17:54.778287   22685 memcache.go:265] couldn't get current server API group list: <html><head><meta http-equiv='refresh' content='1;url=/login?from=%2Fapi%3Ftimeout%3D32s'/><script id='redirect' data-redirect-url='/login?from=%2Fapi%3Ftimeout%3D32s' src='/static/8c86e82d/scripts/redirect.js'></script></head><body style='background-color:white; color:white;'>
Authentication required
<!--
-->

</body></html>

 

 

4. Jenkinsfile 에서 credentials 사용하기

아래와 같이 컨테이너 업로드가 포함된 스텝에서 withCredentials 와 usernamePassword 를 이용해 docker hub 계정정보를 취득하여 사용한다. credentialsId 의 값으로 사용할 credentials 의 id 를 지정해야 한다.

stage('이미지 빌드 및 업로드') {
    steps {
        ...
        script{
            // credentials 에서 가져온 계정정보로 도커 로그인
            withCredentials([usernamePassword(credentialsId: 'docker_username_password', passwordVariable: 'PASSWORD', usernameVariable: 'USERNAME')]) {
                sh "echo " + '${PASSWORD}' + " | docker login -u " + '${USERNAME}' + " --password-stdin"
            }
        ...
        }
    }

    post {
        always {
            // 도커 로그아웃하여 config.json 파일을 정리해줌
            sh "docker logout"
        }
    }
}

 

쿠버네티스 인증서는 파일로 생성했기 때문에 아래와 같이 withCredentials 와 file 을 이용해 취득한다. 마찬가지로 credentialsId 의 값으로는 사용할 credentials 의 id 를 지정한다. helm upgrade 명령어의 옵션으로 --kubeconfig ${KUBECONFIG} 를 넘겨 인증서를 사용할 수 있게 한다.(그 이외의 변수는 신경쓰지 말자)

stage('헬름 배포') {
    steps {
        // 클러스터 인증서 정보를 가져와 KUBECONFIG 변수에 담아 사용
        withCredentials([file(credentialsId: 'k8s_admin_config', variable: 'KUBECONFIG')]) {
            sh "helm upgrade sample-api ./sample-api -f ./sample-api/values-${params.PROFILE}.yaml" +
            " -n sample-ns --install --kubeconfig " + '${KUBECONFIG}' +
            " --wait --timeout=10m" +
            " --set image.tag=${TAG}" +
            " --set image.repository=${DOCKERHUB_USERNAME}/sample-api"
        }
    }
}

 

5. Jenkins pipeline 에서 credentials 사용 확인

docker_username_password 확인

k8s_admin_config 확인

블로그 이미지

망원동똑똑이

프로그래밍 지식을 자유롭게 모아두는 곳입니다.

,

helm template 의 변수 치환 개념helm 차트 디렉토리/파일 구성 설명에서 "--set <key>=<value>" 또는 value.yaml 파일로 치환될 변수를 지정해 줄 수 있다고 하였다. 그러나 "--set" 방식으로 모든 파라미터를 넘기기에는 그 갯수가 너무 많고, value.yaml 에만 지정하여 사용하면 환경별로 다른 변수들을 관리하기 힘들다는 단점이 있다. 따라서 환경별로 다른 변수들만 지정해놓은 value-<환경명>.yaml 같은 파일을 만들고, 이를 helm 배포 커맨드에서 지정하여 사용하는 방법을 소개한다.

 

1. helm 패키지 디렉토리 구성

my-chart/
├── .helmignore 
├── Chart.yaml
├── values.yaml
├── values-dev.yaml  // 추가
├── values-qa.yaml   // 추가
├── values-prod.yaml // 추가
├── charts/
└── templates/
    ├── NOTES.txt
    ├── _helpers.tpl
    ├── deployment.yaml
    ├── hpa.yaml
    ├── ingress.yaml
    ├── service.yaml
    ├── serviceaccount.yaml
    └── tests/

 

위와 같이 패키지 루트에 values.yaml 의 형제로 values-<환경명>.yaml 파일을 생성해준다. 해당 파일에는 환경별로 다르게 지정해주고 싶은 변수들을 아래 예시처럼 선언해준다.(예시: values-dev.yaml)

replicaCount: 1
resources:
  limits:
    cpu: 200m
    memory: 200Mi
  requests:
    cpu: 100m
    memory: 100Mi

 

2. 배포 커맨드

helm upgrade <배포명> <helm 패키지 경로> -f <환경별 values.yaml 경로> --install

위와 같은 형식으로 "-f" 옵션을 통해 배포할 환경의 values-<환경명>.yaml 경로를 지정해주면 실제 기본 values.yaml 내용 위에 해당 내용이 오버레이된다. 즉, 기본으로 values.yaml 내용을 사용하되, values-<환경명>.yaml 파일에 지정된 변수가 override 된다. 만약 위의 예시에서처럼 values-dev.yaml 파일에 replicaCount: 1 이 지정되어있고, 기본 values.yaml 에는 replicaCount: 2 가 지정되어있다면, 최종적으로 replicaCount 는 1이 된다.

 

참고로, helm install 은 헬름 패키지를 클러스터에 처음 배포할 때에만 사용할 수 있는 명령어이고(이미 동일한 이름의 릴리즈가 있으면 에러 발생), helm upgrade 는 이미 클러스터에 배포되어있는 헬름 패키지 릴리즈의 내용이나 버전을 수정배포할 때 쓰인다. 하지만, upgrade 명령어를 사용하면서 --install 옵션을 추가하면 릴리즈가 없을때는 install 과 동일하게 동작하게 되어서 보통 helm install 을 따로 쓰기보다는 helm upgrade --install 형식으로 쓰인다.

 

3. --set 파라미터와 -f 파일 지정을 함께 썼을 때

위에서 말했듯 helm install 또는 helm upgrade 실행시에 "--set <key>=<value>" 형식으로 파라미터를 지정할 수 있다. 그렇다면 동일한 변수를 --set 으로도 지정하고, -f 로도 지정하면 어떻게 될까?

결론은 --set 파라미터가 최종적으로 override 하게 된다. 따라서 --set 과 함께 사용할때는 의도대로 변수가 오버라이드되는지 유의하여야 한다.

블로그 이미지

망원동똑똑이

프로그래밍 지식을 자유롭게 모아두는 곳입니다.

,

1. Release 객체란

helm 패키지를 사용하다보면 사용자 정의 변수를 지정할 수 있는 _helpers.tpl 내에 {{ .Release.Name }} 같이 ".Release" 로 접근하는 변수를 접하게 된다. ".Chart" 나 ".Values" 는 각각 Chart.yaml, values.yaml 파일에 선언된 변수를 가져온다는 것을 알겠는데, ".Release" 는 어디서 가져오는 것일까?

Release 객체는 특정 파일에 정의된 변수가 아니라, Helm 이 실행될 때 자체적으로 생성하여 제공하는 빌트인 객체이다.

 

2. Release 객체가 제공하는 주요 속성

다음과 같은 동적인 배포 정보에 접근 가능하다.

속성명 정보
Name 사용자가 helm install <릴리즈명> 명령어에서 지정한 <릴리즈명>
Namespace 패키지가 배포되는 k8s 의 네임스페이스명
Service 리소스 매니페스트를 렌더링하는 서비스 이름(기본값 Helm)
IsUpgrade 현재 릴리즈가 install(최초 배포) 이 아닌 upgrade(버전 업데이트) 인지 여부(true/false)
IsInstall 현재 릴리즈가 install (최초 배포) 인지 여부 (true/false)

 

3. _helpers.tpl 에서의 활용 예시

주로 동일한 리소스의 이름이 중복되지 않도록 릴리즈 이름을 조합할 때 많이 사용한다.

{{/* 릴리즈 이름과 차트 이름을 조합하여 고유한 리소스 이름을 생성하는 _helpers.tpl 예시 */}}
{{- define "my-chart.fullname" -}}
{{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-" }}
{{- end }}
블로그 이미지

망원동똑똑이

프로그래밍 지식을 자유롭게 모아두는 곳입니다.

,

아래 명령으로 헬름 패키지를 생성한다.

helm create <헬름 패키지명>

현재 경로에 <헬름 패키지명> 으로 디렉토리가 생성되며, 그 하위로 아래와같은 구조의 파일 트리가 생성된다. 아래는 helm create my-chart 를 실행한 결과이다.

my-chart/
├── .helmignore 
├── Chart.yaml
├── values.yaml
├── charts/
└── templates/
    ├── NOTES.txt
    ├── _helpers.tpl
    ├── deployment.yaml
    ├── hpa.yaml
    ├── ingress.yaml
    ├── service.yaml
    ├── serviceaccount.yaml
    └── tests/

각각의 파일/디렉토리의 용도는 아래와 같다.

파일/디렉토리명 용도 예시
.helmignore 렌더링(헬름이 배포 가능한 매니페스트를 만드는 과정)시 제외할 파일/디렉토리 지정 배포하지 않을 참고용 샘플 yaml 파일
Chart.yaml 차트 기본정보 선언 패키지의 이름, 버전, 설명 및 API 버전 등 메타데이터를 정의
values.yaml 배포될 yaml 파일에 들어갈 변수 기본값 선언. 환경별 배포 설정시 사용. templates/service.yaml 의 {profile} 부분에 들어갈 값
charts/ main app 과 함께 배포되어야 하는 sub app 폴더. 즉, main app 이 의존하고 있는 다른 app 들의 패키지를 지정. my-chart 앱 배포시 함께 배포되어야 하는 앱을 지정
templates/ . main app 폴더  
NOTES.txt 배포 후 표시될 안내문구  
_helpers.tpl 사용자 정의 전역변수 선언(helper 함수 형태)  
리소스 매니페스트 파일들 main app 리소스 매니페스트 템플릿들. values.yaml 에서 주입받은 값으로 최종 매니페스트가 렌더링됨.  
tests/ main app 배포 후 통신상태 확인을 위한 pod 템플릿 디렉토리  

 

블로그 이미지

망원동똑똑이

프로그래밍 지식을 자유롭게 모아두는 곳입니다.

,

helm kubernetes 패키지 매니저는 변수 치환 방식으로 helm 매니페스트 템플릿을 동적으로 클러스터에 배포할 수 있다.

kind: Service
metadata:
  name: sample-api
spec:
  selector:
    profile: {profile}
  ports:
    - port: {port}
      targetPort: 8080
      nodePort: {nodePort}

 

위와 같은 매니페스트 파일이 sample-api/templates/service.yaml 경로에 존재한다고 하자.(sample-api 디렉토리는 헬름 차트 디렉토리로 구성되어있다.) 이제 아래 커맨드를 실행해보자.

helm install sample-api ./sample-api --set port="80" --set profile="dev" --set nodePort="33333"

helm install 은 k8s 클러스터에 헬름 패키지를 처음 배포할 때 쓰는 명령어이고, 위와 같은 명령어로 배포하면 "sample-api" 라는 임의의 인스턴스명으로 ./sample-api 헬름 패키지가 배포된다. --set 으로 파라미터를 <key>=<value> 형식으로 지정하면 template 파일 내에서 해당 {변수}가 치환된다.

 

블로그 이미지

망원동똑똑이

프로그래밍 지식을 자유롭게 모아두는 곳입니다.

,