오브젝트란?
쿠버네티스 시스템에서 영속성을 가지는 오브젝트이다. 하나의 의도를 담은 레코드이며, 영속성의 특징에 따라 오브젝트 생성을 보장하기 위해 지속적으로 작동한다. 이 오브젝트를 생성함으로써 클러스터의 워크로드를 어떤 형태로 보이고자 하는지에 대해 효과적으로 쿠버네티스 시스템에 전한다.
- 컨테이너화된 애플리케이션이 동작중인지 (그리고 어느 노드에서 동작 중인지)
- 애플리케이션이 이용할 수 있는 리소스
- 애플리케이션이 어떻게 재구동, 업그레이드, 내고장성(시스템의 일부가 고장이 나도 전체에는 영향을 주지 않고, 항상 시스템의 정상 작동을 유지하는 능력)과 같은 부분들을 동작해야 하는지에 대한 정책
즉, 오브젝트는 가장 기본적인 구성 단위가 된다. 그리고 이 오브젝트를 생성,수정,삭제 동작을 입력받아 전달해줄 때, 지금껏 사용했던 kubectl 커멘드라인 인터페이스를 이용할 수 있다.
이때, kubectl은 대부분의 경우 정보를 .yaml 파일을 받아서 Json형태로 포맷을 전환하여 쿠버네티스 API를 호출해준다.
1] 데몬셋(DaemonSet)
데몬셋은 클러스터 전체에 pod를 띄울때 사용하는 컨트롤러이다. 데몬셋을 이용하여 pod를 실행하면 항상 그 pod가 클러스터 전체 node에 떠있게 된다. 그리고 클러스터내에 새롭게 node가 추가되었을때 자동으로 그 node에 데몬셋으로 띄운 포드가 실행된다. 반대로 node가 클러스터에서 빠졌을때는 node에 있는 pod는 그대로 사라지며, 다른 곳으로 옮겨가서 실행되지 않는다. 그렇기 때문에 데몬셋은 보통 로그수집기를 실행하거나 node를 모니터링 하는 모니터링용 데몬 등. 클러스터 전체에 항상 실행시켜 두어야 하는 pod를 실행하는데 사용한다.
사용예)
= Calico 네트워크 플러그인과 kube-proxy를 생성
= MetalLB의 speaker
데몬셋 생성해보기
= https://xggames.tistory.com/69 => 인그레스와 로드밸런서 내용중 metallb.yaml 배포했던 내용을 가지고 계속 진행한다.
# MetalLB의 스피커가 각 노드에 분포되어 있는 상태 확인
[root@m-k8s-ys vagrant]# kubectl get pods -n metallb-system -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
controller-5f98465b6b-j4q5p 1/1 Running 1 27d 172.16.138.83 w3-k8s-ys <none> <none>
speaker-6z9q7 1/1 Running 1 27d 192.168.56.101 w1-k8s-ys <none> <none>
speaker-k9vwj 1/1 Running 1 27d 192.168.56.103 w3-k8s-ys <none> <none>
speaker-v2rh7 1/1 Running 1 27d 192.168.56.10 m-k8s-ys <none> <none>
speaker-w8wgp 1/1 Running 1 27d 192.168.56.102 w2-k8s-ys <none> <none>
VagrantFile에 "N = 3 # 워커노드 수" 를 4로 변경한다. 그리고 vagrant up 명령어로 w4-k8s-ys-config 워커 노드를 추가해주자. 그리고 다시 마스터노드로 들어가 "kubectl get pods -n metallb-system -o wide -w" (w는 watch의 약어)를 실행시키면 (linux의 tail -f와 비슷) 변경내용을 실시간으로 확인할 수 있다.
command + c 를눌러 취소하고, -w 명령어를빼고 추가된 워커노드에 demonset인 speaker가 설치되었는지 확인해보자.
[이후 생략...]
2] 컨피그맵(ConfigMap)
설정을 목적으로 key-value 쌍인 데이터를 저장하는데 사용하는 API 오브젝트이다. pod는 볼륨에서 환경 변수, 커맨드-라인 인수 또는 구성 파일로 컨피그맵을 사용할 수 있다. 컨피그맵을 사용하면 컨테이너 이미지에서 환경별 구성을 분리하여, 애플리케이션을 쉽게 이식할 수 있다.
컨피그맵으로 MetalLB IP 설정 변경해보기
# 컨피그맵 deployment생성
[root@m-k8s-ys vagrant]# kubectl create deployment ys-configmap --image=sysnet4admin/echo-hname
deployment.apps/ys-configmap created
# 로드밸런서를 통해 노출
[root@m-k8s-ys vagrant]# kubectl expose deployment ys-configmap --type=LoadBalancer --name=ys-configmap-svc --port=80
service/ys-configmap-svc exposed
[root@m-k8s-ys vagrant]# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 62d
ys-configmap-svc LoadBalancer 10.97.193.64 192.168.56.11 80:31380/TCP 30s
# EXTERNAL-IP 192.168.56.11-13을 192.168.56.21-23 으로 변경하기
[root@m-k8s-ys vagrant]# sed -i 's/11/21/;s/13/23/' metallb-l2config.yaml
# 변경내용 적용
[root@m-k8s-ys vagrant]# kubectl apply -f metallb-l2config.yaml
configmap/config configured
# 로드밸런서의 speaker pod 삭제
[root@m-k8s-ys vagrant]# kubectl delete pods --all -n metallb-system
pod "controller-5f98465b6b-j4q5p" deleted
pod "speaker-6z9q7" deleted
pod "speaker-k9vwj" deleted
pod "speaker-qlqrp" deleted
pod "speaker-v2rh7" deleted
pod "speaker-w8wgp" deleted
# speaker 확인시, 새로 pod가 생성되어있다.
[root@m-k8s-ys vagrant]# kubectl get pods -n metallb-system -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
controller-5f98465b6b-wzl5w 1/1 Running 0 19s 172.16.138.84 w3-k8s-ys <none> <none>
speaker-2ftzn 1/1 Running 0 19s 192.168.56.102 w2-k8s-ys <none> <none>
speaker-9c86w 1/1 Running 0 19s 192.168.56.101 w1-k8s-ys <none> <none>
speaker-9xjsp 1/1 Running 0 19s 192.168.56.10 m-k8s-ys <none> <none>
speaker-sxjg8 1/1 Running 0 19s 192.168.56.103 w3-k8s-ys <none> <none>
speaker-wm2jr 1/1 Running 0 19s 192.168.56.104 w4-k8s-ys <none> <none>
# EXTERNAL-IP가 변경되어있는 모습 확인
[root@m-k8s-ys vagrant]# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 62d
ys-configmap-svc LoadBalancer 10.97.193.64 192.168.56.21 80:31380/TCP 5m26s
# 192.168.56.21로 접속확인
3] PV와 PVC
쿠버네티스에서는 의도적으로 pod가 언제든지 생성되고 삭제가 되도록 설계하였다. 하지만 파드에서 생성한 내용을 기록하고 보관하거나 모든 파드가 동일한 설정 값을 유지하고 관리하기 위해 볼륨으로부터 공통된 설정을 가지고 올 수 있도록 설계를 해야하는 경우도 있을 것이다. 이때 많은 쿠버네티스 볼륨 스토리지중에서 PV와 PVC에 대한 설명이다.
- PV: (=PersistentVolume) 지속적으로 사용 가능한 볼륨. 볼륨을 사용할 수 있게 준비하는 단계
- PVC: (=PersistentVolumeClaim) 지속적으로 사용 가능한 불륨 요청 준비된 볼륨에서 일정 공간을 할당받는다.
NFS 볼륨에 PV/PVC를 만들고 pod에 연결하기
= nfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
spec:
capacity: # 사용하는 용량 제한이 아닌, 쓸 수 있는 용량
storage: 100Mi
accessModes: # PV를 어떤 방식으로 사용할지 정의
- ReadWriteMany
# ReadWriteMany: 여러개의 노드가 읽고 쓸 수 있도록 마운트
# ReadWriteOnce: 하나의 노드에서만 불륨을 읽고 쓸 수 있도록 마운트
# ReadWriteOnce: 여러 개의 노드가 읽도록 마운트
persistentVolumeReclaimPolicy: Retain # PV가 제거됐을 때 작동하는 방법을 정의함. (Retain: 유지|Delete:삭제|Recycle:재활용)
nfs: # NFS 서버 연결 위치 설정
server: 192.168.56.10
path: /home/vagrant/nfs_shared
= nfs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Mi
# nfs_shared 폴더 생성 (/home/vagrant 폴더내)
[root@m-k8s-ys vagrant]# mkdir nfs_shared
# NFS로 받아들일 IP영역 + 읽기/쓰기, 쓰기작업 동기화, root 계정 사용 등 옵션 적용
# 오류발생!! ip가 틀림. [root@m-k8s-ys vagrant]# echo '/home/vagrant/nfs_shared 192.168.50.0/24(rw,sync,no_root_squash)' >> /etc/exports
[root@m-k8s-ys vagrant]# echo '/home/vagrant/nfs_shared 192.168.56.0/24(rw,sync,no_root_squash)' >> /etc/exports
# NFS서버 활성화(다음에 시작할 때도 자동으로 적용)
[root@m-k8s-ys vagrant]# systemctl enable --now nfs
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.
# nfs-pv.yaml 오브젝트 생성 (PV)
[root@m-k8s-ys vagrant]# kubectl apply -f nfs-pv.yaml
persistentvolume/nfs-pv created
# PV의 상태가 Available(사용 가능)임을 확인
[root@m-k8s-ys vagrant]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfs-pv 100Mi RWX Retain Available 4m47s
# nfs-pvc.yaml 오브젝트 생성 (PVC)
[root@m-k8s-ys vagrant]# kubectl apply -f nfs-pvc.yaml
persistentvolumeclaim/nfs-pvc created
# PVC 생성 확인
[root@m-k8s-ys vagrant]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
nfs-pvc Bound nfs-pv 100Mi RWX 10s
# PVC 생성후, PV의 상태가 Bound(묶여짐)임을 확인
[root@m-k8s-ys vagrant]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfs-pv 100Mi RWX Retain Bound default/nfs-pvc 10m
PVC는 PV와 구성이 거의 동일하지만, PV는 사용자가 요청할 볼륨 공간을 관리자가 만들고, PVC는 사용자(개발자)간 볼륨을 요청하는 데 사용한다는 차이가 있다.
= nfs-pvc-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-pvc-deploy
spec:
replicas: 4
selector:
matchLabels:
app: nfs-pvc-deploy
template:
metadata:
labels:
app: nfs-pvc-deploy
spec:
containers: # audit-trail 이미지를 가지고 온다. - 요청을 처리할 때마다 접속 정보를 로그로 기록
- name: audit-trail
image: sysnet4admin/audit-trail
volumeMounts: # 볼륨이 마운트될 위치를 지정
- name: nfs-vol
mountPath: /audit
volumes: # PVC로 생성된 볼륨을 마운트하기 위해서 nfs-pvc라는 이름을 사용하였다
- name: nfs-vol
persistentVolumeClaim:
claimName: nfs-pvc
# nfs-pvc-deploy.yaml 배포 (pod생성)
[root@m-k8s-ys vagrant]# kubectl apply -f nfs-pvc-deploy.yaml
deployment.apps/nfs-pvc-deploy created
# nfs pod확인
[root@m-k8s-ys vagrant]# kubectl get pods
............ 아무리 기다려봐도
ContainerCreating에서 Running 상태로 넘어가지 않고있는 이슈가 발생하였다. (이경우 .yaml파일이 잘못되었거나, 논리적으로 맞지
않다는 뜻이다) 이때
[root@m-k8s-ys vagrant]# kubectl describe pods # pod에 어떤 오류가 발생했는지 확인
를 쳐보면 어떤 오류가 발생했는지 확인할 수 있다.
폴더에 access denied!!!가 발생하고 있었다..
열심히 뭐지뭐지하고 열심히 삽질한 결과..
/etc/exports 파일에 192.168.50.0/24 ...로 잘못입력했다. 192.168.56.0/24 (노드들 포트범위)로 수정했다..ㅠㅠ
/etc/exports을 수정하고, [exportfs -r] 로 nfs서비스 동기화 실행
(참고자료: https://ccambo.blogspot.com/2020/12/centos-nfs-centos-8-nfs.html)
두둥! 정상적으로 마운트되고, pod들이 Running상태로 되었다. 그럼 계속 예제를 진행해보자.
# NFS서버에 마운팅한 파드중 하나에 접속
[root@m-k8s-ys vagrant]# kubectl exec -it nfs-pvc-deploy-5fd9876c46-2r726 -- /bin/bash
# 192.168.56.10:/home/vagrant/nfs_shared가 /audit와 마운트 되어있는 모습.
root@nfs-pvc-deploy-5fd9876c46-2r726:/audit# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 37G 2.8G 35G 8% /
tmpfs 1.3G 0 1.3G 0% /dev
tmpfs 1.3G 0 1.3G 0% /sys/fs/cgroup
192.168.56.10:/home/vagrant/nfs_shared 37G 3.3G 34G 9% /audit
/dev/mapper/centos_k8s-root 37G 2.8G 35G 8% /etc/hosts
shm 64M 0 64M 0% /dev/shm
tmpfs 1.3G 12K 1.3G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 1.3G 0 1.3G 0% /proc/acpi
tmpfs 1.3G 0 1.3G 0% /proc/scsi
tmpfs 1.3G 0 1.3G 0% /sys/firmware
# 다시 master노드로 와서 LB 생성
[root@m-k8s-ys vagrant]# kubectl expose deployment nfs-pvc-deploy --type=LoadBalancer --name=nfs-pvc-deploy-svc --port=80
service/nfs-pvc-deploy-svc exposed
그리고 CURL명령어로 열심히 호출해주고..
master노드의 /home/vagrant/nfs_shared 폴더에도 pod에서 생성된 로그파일이 있는지 확인해보자!
# 테스트했던 deployment, pvc, pv 정리
[root@m-k8s-ys vagrant]# kubectl delete deployment nfs-pvc-deploy
deployment.apps "nfs-pvc-deploy" deleted
[root@m-k8s-ys vagrant]# kubectl delete pvc nfs-pvc
persistentvolumeclaim "nfs-pvc" deleted
[root@m-k8s-ys vagrant]# kubectl delete pv nfs-pv
persistentvolume "nfs-pv" deleted
그밖에 사용자가 관리자와 동일한 단일 시스템이라면 PV와 PVC를 사용할 필요가 없다. 이때 아래의 yaml파일을 실행시켜서도 사용이 가능하다.
= nfs-ip.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-ip
spec:
replicas: 4
selector:
matchLabels:
app: nfs-ip
template:
metadata:
labels:
app: nfs-ip
spec:
containers:
- name: audit-trail
image: sysnet4admin/audit-trail
volumeMounts:
- name: nfs-vol
mountPath: /audit
volumes:
- name: nfs-vol
nfs:
server: 192.168.56.10
path: /home/vagrant/nfs_shared
4] 스테이트풀셋
: 지금까지는 레플리카셋(spec의 replicas)을 통하여 이름과 순서 등 Random한 파드 생성을 진행하였다. 반대로 스테이트폴셋은 레플리카셋과는 반대로 고정된 이름, 볼륨, 설정등을 가지고 파드를 생성하는 방법을 말한다. 아래의 표로 비교해보자.
레플리카셋 | 스테이트풀셋 | |
파드 생성시 이름 설정 | Random 이름으로 설정 | Ordinal index 이름으로 생성 |
파드 생성시 순서 | 동시 생성 | 순차 생성 |
파드 Recreate시 | 파드 이름 변경 | 파드 이름 유지 |
파드 삭제시 순서 | 동시 삭제 | 인덱스 높은 순부터 순차 삭제 |
불륨 생성하는 방법 | PVC를 직접 생성 | volumeClainTemplates을 통한 동적 생성 |
파드의 수를 늘리면 PVC는? | 1개의 PVC에 모두 연결 | 각각의 PV를 생성한 뒤 연결 |
PVC 연결된 특정 파드가 죽으면? | NodeSelector가 설정 되어 있다면 해당 노드에 동일한 서비스로 랜덤한 파드이름 생성 (같은 노드에 PVC, 파드가 생성되지 않으면 연결되지 않음) |
특정 파드와 동일한 파드를 생성 후 기존 PVC와 연결 |
PVC 연결된 파드 수를 0으로 하면? | PVC도 삭제함 | PVC는 삭제하지 않음 |
= 스테이트풀셋이 사용되는 경우
1) 안정적이고 고유한 네트워크 식별자가 필요한 경우
2) 안정적이고 지속적인 스토리지를 사용해야 하는 경우
3) 질서 정연한 파드의 배치와 확장을 원하는 경우
4) 파드의 자동 롤링 업데이트를 사용하기 원할때
주로 레디스(Redis), 주키퍼(Zookeeper), 카산드라(Cassandra), 몽고DB(MongoDB) 등의 마스터-슬레이브 구조 시스템에서 사용한다.
= 스테이트풀셋 사용시 유의해야할 점
1) 스테이트풀셋과 관련된 볼륨이 삭제되지 않기때문에, 별도의 관리가 필요하다.
2) 파드의 스토리지는 PV나 스토리지클래스로 프로비저닝을 수행해야 한다
3) 롤링업데이트를 수행하는 경우 수동으로 복구해야 할 수 있음 (롤링업데이트 수행시 기존의 스토리지와 충돌로 인한 애플리케이션 오류 발생 우려)
4) 파드 네트워크 ID를 유지하기 위해 headless서비스가 필요
(?) 롤링 업데이트란? https://kubernetes.io/ko/docs/tutorials/kubernetes-basics/update/update-intro/
=> 따라서, 레플리카셋을 사용할지, 스테이트풀셋을 사용할지는 프로젝트의 상황에따라 달라질 수 있다.
= 스테이트풀셋 사용해보기
= nfs-pvc-sts.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nfs-pvc-sts
spec:
replicas: 4
serviceName: sts-svc-domain #statefulset need it
selector:
matchLabels:
app: nfs-pvc-sts
template:
metadata:
labels:
app: nfs-pvc-sts
spec:
containers:
- name: audit-trail
image: sysnet4admin/audit-trail
volumeMounts:
- name: nfs-vol # same name of volumes's name
mountPath: /audit
volumes:
- name: nfs-vol
persistentVolumeClaim:
claimName: nfs-pvc
# nfs-pv와 nfs-pvc 먼저 실행하고나서 nfs-pvc-sts.yaml 실행할 것.
# 스테이트풀셋 LB적용
[root@m-k8s-ys vagrant]# kubectl expose statefulset nfs-pvc-sts --type=LoadBalancer --name=nfs-pvc-sts-svc --port=80
error: cannot expose a StatefulSet.apps
# ==> expose명령어는 스테이트풀셋을 지원하지 않는다!! 따라서 yaml파일을 통해 service를 실행해주자.
= nfs-pvc-sts-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: nfs-pvc-sts-svc
spec:
selector:
app: nfs-pvc-sts
ports:
- port: 80
type: LoadBalancer
[root@m-k8s-ys vagrant]# kubectl apply -f nfs-pvc-sts-svc.yaml
service/nfs-pvc-sts-svc created
[root@m-k8s-ys vagrant]# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 64d
nfs-pvc-sts-svc LoadBalancer 10.108.72.139 192.168.56.21 80:30913/TCP 29s
[root@m-k8s-ys nfs_shared]# ls -al
합계 24
drw-rw-r--. 2 vagrant vagrant 233 3월 27 22:37 .
drwx------. 5 vagrant vagrant 4096 3월 27 22:35 ..
-rw-r--r--. 1 root root 240 3월 27 22:06 audit_nfs-pvc-deploy-5fd9876c46-2r726.log
-rw-r--r--. 1 root root 48 3월 27 22:06 audit_nfs-pvc-deploy-5fd9876c46-lm99l.log
-rw-r--r--. 1 root root 188 3월 27 22:06 audit_nfs-pvc-deploy-5fd9876c46-rnd2m.log
-rw-r--r--. 1 root root 94 3월 27 22:06 audit_nfs-pvc-deploy-5fd9876c46-srkz8.log
-rw-r--r--. 1 root root 376 3월 27 22:38 audit_nfs-pvc-sts-2.log
# 마찬가지로 스테이트풀셋을 사용해서 PV, PVC를 통해 - audit_nfs-pvc-sts-2.log 파일이 master node 마운트 폴더에 추가되어있다
# 외부노출 서비스 및 스테이트풀셋 삭제
[root@m-k8s-ys vagrant]# kubectl delete services nfs-pvc-sts-svc
service "nfs-pvc-sts-svc" deleted
# (!) 이때, 파드의 삭제가 생성의 역순으로 진행된다.
[root@m-k8s-ys vagrant]# kubectl delete statefulset nfs-pvc-sts
statefulset.apps "nfs-pvc-sts" deleted
참고자료
= 서적 - 컨테이너 인프라 환경 구축을 위한 쿠버네티스/도커, 길벗 - 제 3장
= https://kubernetes.io/ko/docs/concepts/overview/working-with-objects/kubernetes-objects/
= https://arisu1000.tistory.com/27834
= https://nearhome.tistory.com/107
'Docker & Kubernetes' 카테고리의 다른 글
쿠버네티스(Kubernetes) - k8s에서 Docker 컨테이너 사용하기 (0) | 2022.04.05 |
---|---|
Docker - DockerFile (0) | 2022.04.05 |
쿠버네티스(Kubernetes) - 인그레스와 로드밸런서(Load Balancer) (0) | 2022.02.27 |
쿠버네티스(Kubernetes) - 베이그런트 (Vagrant) (0) | 2022.01.29 |
쿠버네티스(Kubernetes) - 기본적인 사용방법 (0) | 2022.01.29 |