해당 포스팅은 쿠버네티스 어나더 클래스 (지상편) - Sprint 1, 2 강의 내용을 기반으로 작성했습니다.
Namespace
apiVersion: v1
kind: Namespace
metadata:
name: anotherclass-123
labels:
part-of: k8s-anotherclass
managed-by: dashboard
네임스페이스(Namespace)는 기본적으로 Object를 그룹핑해주는 역할을 한다. 메타데이터(metadata) field에는 name과 labels가 있다.
Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
# 해당 deployment는 이 namespace 소속이 된다.
namespace: anotherclass-123
name: api-tester-1231
labels:
part-of: k8s-anotherclass
component: backend-server
name: api-tester
instance: api-tester-1231
version: 1.0.0
managed-by: dashboard
spec:
selector:
matchLabels:
part-of: k8s-anotherclass
component: backend-server
name: api-tester
instance: api-tester-1231
replicas: 2 # 파드를 2개 생성해라
# deployment 기능의 핵심. 업데이트 방식을 의미한다.
strategy:
type: RollingUpdate
# template의 내용으로 pod가 생성된다.
template:
metadata:
labels:
part-of: k8s-anotherclass
component: backend-server
name: api-tester
instance: api-tester-1231
version: 1.0.0
spec:
# pod를 띄울 node를 선택한다.
nodeSelector:
kubernetes.io/hostname: k8s-master
# docker hub에서 해당 name의 image를 다운받는다.
containers:
- name: api-tester-1231
image: 1pro/api-tester:v1.0.0
ports:
- name: http
containerPort: 8080
# application의 환경변수를 configmap의 값으로 pod에 제공해줌.
envFrom:
- configMapRef:
name: api-tester-1231-properties
# startupProbe는 App이 잘 기동이 됐는지 체크를 하고 있다가
# 기동이 안되면 App을 재기동시킨다.
startupProbe:
httpGet:
path: "/startup"
port: 8080
periodSeconds: 5
failureThreshold: 24
# App에 트래픽을 연결할 건지를 결정하는 속성
readinessProbe:
httpGet:
path: "/readiness"
port: 8080
periodSeconds: 10
failureThreshold: 3
# App이 정상이 아니면 재시작을 시킬 건지 판단하는 속성
livenessProbe:
httpGet:
path: "/liveness"
port: 8080
periodSeconds: 10
failureThreshold: 3
# pod 하나에 CPU, Memory를 할당해주는 속성.
# 이걸 설정하지 않으면 pod가 모든 자원을 써버리게 된다.
resources:
requests:
memory: "100Mi"
cpu: "100m"
limits:
memory: "200Mi"
cpu: "200m"
# pod 내부에 만들어지는 디렉토리
volumeMounts:
- name: files
mountPath: /usr/src/myapp/files/dev
- name: secret-datasource
mountPath: /usr/src/myapp/datasource
# volumeMounts와 매칭이 되어 연결된다.
volumes:
- name: files
persistentVolumeClaim:
claimName: api-tester-1231-files
- name: secret-datasource
secret:
secretName: api-tester-1231-postgresql
디플로이먼트는 실질적인 Application이 돌아가는 Object이다.
해당 yaml 파일은 규모가 제법 있는데, 여기서 중요한 field 값들이 무엇을 의미하는지 알아보자.
- metadata.namespace: 디플로이먼트가 소속되는 namespace
- metadata.name: 디플로이먼트의 이름. 하나의 namespace 안에서 같은 name을 가질 수 없다.
- spec.replicas: 생성할 pod 개수
- template: 이 template의 내용으로 pod가 생성된다.
- ~.spec.nodeSelector: 파드를 띄울 노드 이름
- ~.spec.containers: 파드에서 실행되는 컨테이너들의 정의.
- ~.envFrom: Application의 환경변수와 관련된 사항. configmap이 환경변수 값을 제공해준다.
- ~.startUpProbe: App이 기동이 안되면 App의 재기동을 결정하는 속성.
- ~.readinedProbe: App에 트래픽을 연결할 건지를 결정하는 속성.
- ~.livenessProbe: App이 정상이 아니면 재시작을 할 것인지의 속성.
- ~.resources: pod 하나에 cpu, memory의 리소스 할당의 최소, 최대를 결정하는 속성
- ~.volumeMounts: 이 속성의 mountPath는 pod 내부에 만들어지는 디렉토리. 이름과 일치하는 spec.Volume을 마운트 한다.
- ~.spec.Volumes: persistentVolumeClaim과 secret 오브젝트와 연결되는 오브젝트.
Service
apiVersion: v1
kind: Service
metadata:
namespace: anotherclass-123
name: api-tester-1231
labels:
part-of: k8s-anotherclass
component: backend-server
name: api-tester
instance: api-tester-1231
version: 1.0.0
managed-by: dashboard
spec:
selector:
part-of: k8s-anotherclass
component: backend-server
name: api-tester
instance: api-tester-1231
ports:
- port: 80
targetPort: http
nodePort: 31231
type: NodePort
서비스의 역할은 Pod에 트래픽을 연결해주는 역할이다.
metadata.name이 deployment의 name과 겹치는데, 이는 서로 다른 타입의 object라서 허용된다.
Configmap
apiVersion: v1
kind: ConfigMap # 위 Deployment에 환경 변수를 제공하는 역할
metadata:
namespace: anotherclass-123
name: api-tester-1231-properties
labels:
part-of: k8s-anotherclass
component: backend-server
name: api-tester
instance: api-tester-1231
version: 1.0.0
managed-by: dashboard
# 환경변수로 들어갈 값의 내용
data:
spring_profiles_active: "dev"
application_role: "ALL"
postgresql_filepath: "/usr/src/myapp/datasource/postgresql-info.yaml"
---
apiVersion: v1
kind: Secret # 좀 더 중요한 값들을 저장.
metadata:
namespace: anotherclass-123
name: api-tester-1231-postgresql
labels:
part-of: k8s-anotherclass
component: backend-server
name: api-tester
instance: api-tester-1231
version: 1.0.0
managed-by: dashboard
stringData:
postgresql-info.yaml: |
driver-class-name: "org.postgresql.Driver"
url: "jdbc:postgresql://postgresql:5431"
username: "dev"
password: "dev123"
Configmap은 Deployment의 envFrom과 연결되어 App에 환경변수 값을 부여해주는 역할을 한다.
Secret 또한 환경변수 같은 역할을 하는데 password 같이 좀 더 중요한 값들을 저장한다.
PVC, PV
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
namespace: anotherclass-123
name: api-tester-1231-files
labels:
part-of: k8s-anotherclass
component: backend-server
name: api-tester
instance: api-tester-1231
version: 1.0.0
managed-by: kubectl
spec:
resources:
requests:
storage: 2G
accessModes:
- ReadWriteMany
selector:
matchLabels:
part-of: k8s-anotherclass
component: backend-server
name: api-tester
instance: api-tester-1231-files
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: api-tester-1231-files
labels:
part-of: k8s-anotherclass
component: backend-server
name: api-tester
instance: api-tester-1231-files
version: 1.0.0
managed-by: dashboard
spec:
capacity:
storage: 2G
volumeMode: Filesystem
accessModes:
- ReadWriteMany
# 이 path를 volume 으로 사용하겠다. 미리 디렉토리를 만들어 놓아야 한다.
local:
path: "/root/k8s-local-volume/1231"
# Master node를 지정하는 내용.
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- {key: kubernetes.io/hostname, operator: In, values: [k8s-master]}
PV(Persistent Volume), PVC(Persistent Volume Claim)는 스토리지와 관련된 object라고 이해할 수 있다.
간단히 말해 PV가 스토리지이고, PVC에서 해당 스토리지를 요청하여 pod와 연결되는 개념이다.
따라서 PVC의 resource와 PVC의 capacity에
PV에는 namespace가 없다. Namespace와 PV는 Cluster level의 object이라 같은 계층이다.
앞에서 설명한 Deployment, Service 등은 Namespace level의 object이다.
nodeAffinity는 Volume을 생성할 노드를 지정해주는 것이다.
HPA
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
namespace: anotherclass-123
name: api-tester-1231-default
labels:
part-of: k8s-anotherclass
component: backend-server
name: api-tester
instance: api-tester-1231
version: 1.0.0
managed-by: dashboard
spec:
# scaling 대상을 지정한다.
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-tester-1231
# 최소 2개를 유지하고 부하가 생기면 최대 4개까지 생성한다.
minReplicas: 2
maxReplicas: 4
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60 # CPU 사용량이 평균 60%가 늘어나면 스케일 아웃하라고 설정
# pod가 한번 증가를 한 후에 120초동안 또 pod가 또 추가적으로 늘어나지 않게 하는 설정
behavior:
scaleUp:
stabilizationWindowSeconds: 120
HPA(Horizontal Pod Autoscaler)는 파드의 스케일링과 관련된 오브젝트이다.
스케일링 대상으로 deployment를 지정하고 최소 2개 최대 4개의 pod 생성을 지시하고
CPU의 사용량을 기준으로 60%가 넘으면 스케일 아웃하라고 설정하고,
한번 파드를 증가시킨 후 120초 동안 pod가 추가적으로 늘어나지 않게 하는 설정이다.
labels / selector / naming
앞에서 설명한 Object 들을 보면 간략히 설명했는데도 종류도 많고 정보도 많고 굉장히 복잡해 보인다.
이러한 object 간의 복잡한 관계를 연결시켜주는 요소가 바로 labels, selector, naming 규칙들이다.
이러한 라벨링을 잘 해놓으면 어떤 object 끼리 연관이 있는지, 어떻게 만들어 졌는지 등 많은 정보를 쉽게 파악할 수 있다.
프로메테우스 스택
그 예시로 라벨링에 대한 규격을 잘 표현하고 있는 프로메테우스 스택을 살펴보자.
Pod의 각 라벨들은 다음과 같은 정보를 의미한다.
- part-of: 어플리케이션의 전체 이름. 전체 서비스를 대표한다
- component: 이 서비스를 구성하고 있는 각각의 구성요소를 의미한다. 메트릭을 수집하고, 성능 API를 제공하는 component는 prometheus가 담당. 메트릭 제공은 exporter, 마지막으로 시각화는 grafana component가 담당한다.
- name: 어플리케이션의 실제 이름. prometheus는 구성요소와 이름이 같아서 component와 name이 동일하다. 반면 메트릭을 제공하는 exporter에는 여러가지 App이 있는데, k8s의 cluster 정보는 kube-state-metrics가, 노드 vm의 정보는 node-exporter가 제공한다.
- instance: 만약 여러개의 prometheus를 설치할 경우 각 instance에 대한 식별자.
- version: 다른 요소들은 한번 라벨링하면 변경할 일이 거의 없지만, 버전에 대한 라벨은 App을 업데이트할 때마다 변경되어야 한다.
또한 naming 규칙을 보면 namespace의 경우 해당 namespace에 들어가는 App들에 대한 범위를 나타내는 이름이 좋다.
namespace에 포함되는 object의 naming은 어플리케이션의 instance 명으로 하면 왠만해서 겹칠 일이 없다.
다만 Configmap에는 뒤에 rule이라는 네이밍이 추가되는데(prometheus-k8s-rule), 이는 환경변수를 담당하는 configmap은 여러 개가 정의될 수 있기 때문에 각 사용 목적에 따른 네이밍을 추가한 것이다.
추가적으로 쿠버네티스 권고 라벨링에는 Managed-by라는 항목이 있다.
이는 어떤 도구로 배포 됐는지에 대한 툴 이름을 적는 것이다.
이 라벨을 통해 Object를 생성하고 관리하는 주체를 알 수 있다.
쿠버네티스 어나더클래스
쿠버네티스 어나더클래스 강의에서 사용되는 object들의 네이밍이 어떻게 이루어지는지 알아보자.
먼저 anotherclass-123 namespace는 각 수업에 대한 넘버링으로 네이밍이 되어있다.
그 다음 Deployment를 만들면 replicaset이 생성되고, 이 replicaset에서 pod를 생성한다.
따라서 각 하위로 만들어지는 object들은 상위 object의 name 뒤에 임의 문자가 추가되어 생성된다.
(Deploymet: api-tester-1231 / replicaset: api-tester-1231-xxxx / pod: api-tester-1231-xxxx-yyy)
가장 하위 object인 pod의 라벨은 프로메테우스 스택의 규칙처럼 라벨링 되어있다. (component: backend-server)
사실 이 label 들은 App 정보를 파악하기 위한 용도로만 사용되지 않고 추가적인 기능이 있다.
상위 object의 selector와 하위 object의 label이 동일해야 매칭이 되어 두 object들이 연결된다.
따라서 replicaset의 selector에 있는 내용들이 pod의 라벨과 매칭되어있다.
이 라벨 내용들은 무조건 동일해야하는 것은 아니고, selector labels ⊆ pod labels 관계를 만족하면 된다.
사실 instance가 유니크하기 때문에 selector에 instance만 넣어도 하위 object가 잘 매칭이 될 수 있다.
Pod에 트래픽을 뿌려주는 service 객체도 selector를 통해 pod와 연결되고, PV와 PVC도 이러한 관계를 가진다.
Configmap, secret의 경우에는 pod에서 직접 선택할 수 있다(envFrom, secretFrom).
최종적인 어나더 클래스의 object cluster 도식은 위와 같다.
서로 연결되는 object들은 selector-labels 관계가 매칭되어있고,
node에도 쿠버네티스가 자동으로 설정한 label이 존재하는데 (서버 계정을 의미하는 kubernetes.io/hostname)
이를 통해 pod의 nodeSelector, PV의 nodeAffinity가 이 label과 연결해 해당 object가 배치될 node를 선택할 수 있다.
label에는 정보와 기능성 역할을 하는 label과 정보 역할만 하는 label이 존재한다.
또한 label 앞에 prefix를 붙일 수 있는데 특히 쿠버네티스 문서의 yaml 파일들에서 이런 예제가 많은데
이는 도메인을 가리키며 옵션 사항이라 꼭 넣을 필요는 없다.
label은 언제든지 owner, stage와 같이 필요하다고 생각되는 사항을 추가할 수 있다.
'인프라' 카테고리의 다른 글
[Kubernetes] 쿠버네티스 기능 이해하기 - Configmap, Secret (0) | 2024.04.29 |
---|---|
[Kubernetes] 쿠버네티스 기능 이해하기 - Probe (0) | 2024.04.29 |
[Kubernetes] 쿠버네티스가 실무에서 편한 이유 (0) | 2024.04.25 |
[Kubernetes] 쿠버네티스와 컨테이너에 대한 한방 정리 (0) | 2024.04.24 |
[Kubernetes] 쿠버네티스를 Ubuntu OS에 설치하기 (with kubeadm, containerd) (0) | 2024.04.21 |