23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
SpringBoot 어플리케이션에 대한 helm chart 는 deployment 로 타입으로 쉽게 만들 수 있다.
이 때 최소한 다음과 같은 기능을 고려해서 만들어야 한다.
deployment 혹은 service 명 지정
네임스페이스 지정
Replicas 수 지정
이미지 경로 지정
스케줄링 기능
nodeSelector 사용
nodeAffinity 사용
podAffinity 사용
taint / toleration 사용
environment 설정 기능
pod 에 대한 annotations 와 labels 지정
Pod Resource 지정
reqeuests 지정
limits 지정
Service 생성
Type 변경
포트 변경
ingress 생성 여부
아래는 customer-service 라는 springboot 어플리케이션에 대한 helm chart 디렉토리 구조이다.
customer-service
├── Chart.yaml
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── service.yaml
│ └── serviceaccount.yaml
└── values.yaml먼저 Chart.yaml 을 보자.
일반적인 메타데이터가 들어있다.
# Chart.yaml
apiVersion: v2
name: customer-service
description: A Helm chart for MSA Pattern customer-service
type: application
version: 1.0.0
appVersion: "1.0.0"values.yaml 은 다음 값들이 들어 있다.
사실 value 값만 봐도 무엇을 지정할 수 있는지 쉽게 알 수 있다.
# values.yaml
replicaCount: 1
image:
repository: seungkyua/customer-service
pullPolicy: Always
tag: "1.0.0"
imagePullSecrets: []
nameOverride: ""
fullnameOverride: "customer-service"
serviceAccount:
create: true
automount: true
annotations: {}
name: ""
podAnnotations: {}
podLabels: {}
podSecurityContext: {}
# fsGroup: 2000
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
env:
- name: JAVA_OPTS
value: "-Dspring.profiles.active=prod"
service:
type: LoadBalancer
port: 8082
ingress:
enabled: false
className: "nginx"
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: customer-service.taco-cat.xyz
paths:
- path: /
pathType: ImplementationSpecific
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
resources: {}
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 100
targetCPUUtilizationPercentage: 80
# targetMemoryUtilizationPercentage: 80
volumes: []
# - name: foo
# secret:
# secretName: mysecret
# optional: false
volumeMounts: []
# - name: foo
# mountPath: "/etc/foo"
# readOnly: true
nodeSelector: {}
tolerations: []
affinity: {}_helpers.tpl 파일에는 기본 name 에 대한 함수들이 정의되어 있다.
# _helpers.tpl
{{- define "springboot-docker.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "springboot-docker.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}values.yaml 파일에 정의된 fullnameOverride 값을 쓰고 이게 없으면 chart 이름과 릴리즈 이름을 사용한다.
chart 에 지정한 이름이 릴리즈 이름에 포함되면 중복을 피하기 위해서 릴리즈 이름만 사용한다.
릴리즈 이름에 차트 이름이 포함되어 있지 않으면 릴리즈 이름과 차트을 합쳐서 이름을 만든다.
아래는 리소스에 대해 기본적인 label 을 추가하는 코드이다.
# _helpers.tpl
{{- define "springboot-docker.labels" -}}
helm.sh/chart: {{ include "springboot-docker.chart" . }}
{{ include "springboot-docker.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{- define "springboot-docker.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "springboot-docker.selectorLabels" -}}
app.kubernetes.io/name: {{ include "springboot-docker.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}이제 deployment.yaml 을 보자.
#deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "springboot-docker.fullname" . }}
labels:
{{- include "springboot-docker.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "springboot-docker.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "springboot-docker.labels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "springboot-docker.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
{{- with .Values.env }}
env:
{{- toYaml . | nindent 12 }}
{{- end }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
livenessProbe:
httpGet:
path: /healthz
port: http
readinessProbe:
httpGet:
path: /healthz
port: http
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.volumeMounts }}
volumeMounts:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.volumes }}
volumes:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}전체 소스는 위와 같으며, 이제 조금씩 나눠서 살펴보자.
name 은 앞에서 설명한 values.yaml의 fullnameOverride 으로 지정할 수 있다.
labels 은 특정 지정된 labels 로 되어 있는데 이는 selector 의 matchLabels 와 template 의 labels 가 같아야 하기 때문이다.
pod 에 줄 수 있는 annotation 과 추가로 줄 수 있는 labels 가 toYmal 을 사용하여 values.yaml 의 podAnnotations 과 podLabels 값으로 지정할 수 있게 하였다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "springboot-docker.fullname" . }}
labels:
{{- include "springboot-docker.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "springboot-docker.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "springboot-docker.labels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}containers 를 추가로 보면 image 를 values.yaml 로 지정할 수 있게 되어 있다.
이는 보통 프로젝트마다 가지고 있는 이미지 리파지토리를 활용할 수 있게 하기 위해서 변경 가능하게 만든 것이다.
그리고 container 의 env 를 추가할 수 있게 되어 있다.
port 는 컨테이너 포트와 Service 의 포트를 다르게 가져갈 수 도 있지만 일단은 둘 다 동일하게 사용하는 방식으로 맞추었다.
liveness 와 readiness 는 경로와 포트가 수정할 수 없게 되어 있는데 이 또한 변수로 만들 수 있다.
여기서는 springboot 소스에서 해당 path 로 헬스 체크를 열어 놓았기 때문에 하드 코딩 하였다.
그리고 container 를 띄울 때 자원에 대한 requests, limits 을 지정할 수 있게 하였다.
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
{{- with .Values.env }}
env:
{{- toYaml . | nindent 12 }}
{{- end }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
livenessProbe:
httpGet:
path: /healthz
port: http
readinessProbe:
httpGet:
path: /healthz
port: http
resources:
{{- toYaml .Values.resources | nindent 12 }}추가로 volume 과 스케줄링을 위한 소스를 보자.
volumes 와 volumeMounts, nodeSelector, affinity, tolerations 는 toYaml 과 nindent 를 사용해서 values.yaml 에 넣은 값들을 그대로 활용할 수 있게 만들었다.
{{- with .Values.volumeMounts }}
volumeMounts:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.volumes }}
volumes:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}service.yaml 에 대한 내용도 살펴보자.
deployment 를 만들면 네트워크 통신을 위해서 반드시 service.yaml 도 만들어야 한다.
Service 이름은 동일하게 fullnameOverride 값으로 지정할 수 있고 type 을 넣어서 원하는 방식을 생성할 수 있게 하였다.
앞에서도 설명하였지만 deployment 의 container port 와 service 의 port 가 동일하게 사용된다.
둘을 다르게 지정하고 싶으면 value.yaml 에서 키 값을 다르게 지정하면 된다.
apiVersion: v1
kind: Service
metadata:
name: {{ include "springboot-docker.fullname" . }}
labels:
{{- include "springboot-docker.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "springboot-docker.selectorLabels" . | nindent 4 }}
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.