Kubernetes Service - MetalLB
온프레미스 클러스터는 Load Balancer를 구매하지 않는 한 부하분산 기능 및 외부연견용 IP 제공하는 리소스가 필요
MetalLb는Bare Metal 환경(가상화 하지 않고 사용한느 고성능 물리 서버)에서 사용 할 수 있는 Loda Balancer 기능을 제공(CNCF 오픈소스 프로젝트)
MetalLb는 네트워크 로드 밸런서를 통해 “외부 IP 주소 풀”을 사용하여 온프레미스 및 VM등의 가상 환경 클러스터에서 외부 서비스 접근 가능
—
MetalLB 특징
온프레미스 환경에서 Service “type:LoadBalancer”의 EXTERNAL-IP\<pending\> 할당
Load Balencer IP로 전달되는 트래픽을 Node로 전달 하면 MetalLB의 역할은 끝남
제공되는 서비스 IP(EXTERNAL-IP)는 ping 작동 안되며 서비스에 대한 동작은 제동된 IP를 통해 애플리케이션에 액세스하여 확인 가능
MetalLB 모드
Layer2 mode (https://metallb.universe.tf/concepts/layer2/)
- 클러스터 노드 중 하나(리더 노드)가 외부에서 접속 가능한 IP의 ARP request를 네트워크 인터페이스에서 할당처리
- ARP(Address Resolution Protocol)?
- IP주소를 MAC주소와 매칭 시키기 위한 프로토콜
- 구성이 단순하여 대용량 처리에 부하가 심하여 테스트용으로 권장
BGP mode (https://metallb.universe.tf/concepts/bgp/)
- 고가용성이 구성가능하여 운영환경에서 주로 사용
MetalLB 구성요소
Controller(Deployment)
- 구성된 IP pool에서 로드 밸런싱을 수행할 EXTERNAL_IP 주소를 할당하는 역할
Speaker(DaemonSet)
- Layer2 or BGP모드를 통해 할당된 IP를 알리는 역할 수행
- speak pod는 node IP를 사용
서비스 계정(컨트롤러 및 스피커)
- 서비스 계정은 컨트롤러 및 스피커 구성요서 작동에 필요한 RABC 사용 권한이 포함
MetalLB L2모드
사용할 IP 주소의 대역 설정을 통해 IP제공
설치 후 필수 → “EXTERNAL_IP 대역”, “설정 모드” 지정을 위한 configmap 배포
Node NIC에 IP를 바인딩 하지 않고 로컬 네트워크의 ARP 요청에 응답하여 컴퓨터의 MAC주소를 클라이언트에게 제공하는 방식으로 작동
LoadBalancer 생성 → MetalLB L2 Controller는 APIserver를 통해 EXTERNAL-IP를 리더 Speaker pod에 할당→ Speaker pod는 소유하고 있다는 것을 ARP를 이용해 모든 노드 Speak Pod에 전파
Service type: LoadBalancer ?
- Node앞에 위치해 각 Node들로 트래픽을 분산하는역할
- L4 LoadBalancer가 생성되고 ClusterIP서비스 및 NodePort 서비스 가 암시적으로 생성됨
- NodePort(30000\~32767)서비스 위에 적용
- Public으로 사용 가능한 IP주소 및 DNS주소를 제공을 통해 Private IP 주소 및 NodePort포트로 클러스터의 Node에 트래픽을 Load Balanceing 하고 전달
- 웹 애플리케이션이나 API와 같이 높은 트래픽 양을 처리햐애 하는 애플리케이션에 유용
- 클라우드 환경이 아닌 온프레미스(VM)환경에서 LoadBalancer를 사용할경우 Public주소를 제공 할 수 있는 MetalLB(bare metal load balacer)모듈을 설치해주어야 한다.
설치
Kubernetes Service (ClusterIP, NodePort, LoadBalancer)
Service는 네트워크 추상화 object로 생성된 Pod에 동적접근 및 이를통하여 Application을 cluster내의 네트워크 서비스로 노출 할 수 있으며 IP 주소 또는 DNS이름을 통해 특정 포트에 직접 액세스 할 수 있도록 Pod를 논리적 그룹화가 가능하다. 또한 Pod집합에 대한 단일 DNS명을 부하하여 분산을 수행 할 수있다.
Service는 왜 필요한가?
- Pod에 문제가 생기면 Kubernetes는 그 Pod를 삭제 후 재생성 한다.
- 이때 기존 Pod IP가 같을 확률은 매우 낮다.(Kubernetes 설계 사상: App를 유지 목적, Pod는 언제즌 장에에 의해 Down 될 수 있고 재시작 될 수 있다. )
- IP가 새로이 부여 될때마다 Application을 매번 수정해야하는 불편함을 없애기 위해 Service 사용하게 설계되었다.
- 클라이언트에서 내부에 있는 Pod Application 접근을 위한 단일 진입점 역할을 하며 Proxy(Load Balancer)처럼 연결된 Pod들에 트래픽을 전달하는 object(Servece object)로 Clien요청 트래픽을 각각의 Pod로 포워딩한다.
Service는 어떻게 연결될까?
- 가상IP와 port를 가지고 생성
- Kube-proxy를 통해 Service의 가상IP, port를 관리
- Service object는 Pod를 트래픽에 노출, Endpoint object는 Pod IP, port가 존재
- 트래픽 ↔ Service object ↔ Endpoint object ↔ IP, port 를 이용하여 Pod 특정
- Service를 사용하여 Pod를 노출하면 kube-proxy는 Service를 통하여 그룹화된 Pod로 트래픽을 보내는 네트워크 규칙(Rules)생성
- kube-proxy → Service(Pod:nginx1, Pod:nginx2, Pod:nginx3)
- kube-proxy는 Service 변경사항 및 Endpoint 모니터링(변경사항)하여 트래픽을 Routing 하기 위한 규칙을 설정된 Mode를 사용하여 생성 및 업데이트 한다
- Iptable mode(기본): kube-proxy는 iptabels를 관리하는 역할만 수행(트래픽 X), 모든 요청은 iptable를 거쳐 pod로 직접 전달
- IPVS mode(IP Virtual Server): Netfilter Framework 기반으로 구현된 LInux kernel Level에서 동작하는 Layer4 Load Balancing 도구(모듈: RR, LC, DH, SH, SEC)
- round-robin
- least connection
- destination hashing
- source hashing
- shortest expected delay
- kube-proxy는 DaemonSet object type으로 모든 노드에서 실행
—
dnsutils
- 서비스의 정보를 보기위하여 사용
Kubernetes StatefulSet
읽기전 Volume PV&PVC 와 Volume StorageClass먼저 읽어 볼 것
애플리케이션의 statefulSet을 관리하는 workload 리소스
Stateless 애플리케이션은 Deployment로 배포하고, Stateful인 DB 같은 경우는 StatefulSet로 배포
- StatefulSet으로 실행시킨 Pod는 Deployment(deploy-app-5skdw)와 다르게 pod-0, pod-1과 같은 순서값과 안적적인 네트워크 ID를 Pod에 할당
- Pod는 오름차순으로 생성되고, 다음 Pod는 이전 Pod가 준비되고 실행상태가 된 후에만 생성, 삭제는 큰 수의 Pod부터 삭제됨 → “OrderedReady”
- Pod를 순서없이 병렬로 실행되거나 종료 시킬려면 “Parallel” 사용(spec.podManagemetPolicy: “Parallel”)
- kubectl explain statefulset.spe.podManagementPolicy
특징
StatefulSet의 각 Pod들은 동일 spec으로 생성되지만 서로 교체는 불가능. 즉 re-scheduling이 되도 지속적으로 동일 식별자 유지
- sts-0-pod를 지워도 sts-0-pod 이름으로 재생성됨
statefulSet 애플리케이션은 서버, 클라이언트, 애플리케이션에서 사용 할 수 있도록 영구볼륨에 데이터 저장 → StorageClass를 사용한 PVC 사용(동적 볼륨)
- 복제본 증가 시 자동으로 PV/PVC 생성
- 복제본 축소 시 사용했던 PV/PVC는 삭제되지 않고 유지
- 유지되는 이유는 스토리지지가 고유한 상태를 유지해야하는데 scale로 인해 삭제되면 상태 데이토도 같이 삭제 되기 때문
- StatefulSet은 Headless service를 사용해야한다
- StatefulSet은 논리적으로 Pod집합을 만들어주는 Service만 있으면 되므로 Headless Service를 사용한다.
- IP가 없어도 DNS에 등록되므로 nslookup을 통해 Pod의 주소를 확인하여 연결 가능하다.
- https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/
- visit-cnt-stfs.yaml
Kubernetes Volume - NFS
Kubernetes는 Storage Volume 정의를 통해 Pod의 Volume을 정의한다
Pod컨테이너 내에 저장된 파일은 별도 설저이 없으면 Host의 임시 디스크에 보관
- Pod 삭제 및 재시작 시 입시 시스크의 데이터 함께 소실
- 멀티 컨테이너 Pod는 내부 컨테이너 간 데이터 공유 수행 필요
- volum 추상하는 이러한 문제를 해결하는 매커니즘을 제공
- Volume은 Pod.spec에 포함하여, Pod내 filesystem에 mount됨
- Pod.spec → .spec.volumes 구문으로 볼륨기술 및 이름 지정
- .spec.containers[\*].volumeMounts. 컨테이너 내부 FS에 mount → df -h 확인
- 데이터 공유 및 지속성, API 기능을 통한 데이터 이전효과 지원
Volume 사용 예시 ELK
- 임시 volume
- Tomcat의 /usr/local/tomcat/logs 와 emptyDir 볼륨연결
- emptyDir을 Logstash /mnt에 마운트 하여 Tomcat 로그 Elasticsearch App로 보냄
- 로그를 보내기위한 공유→ 임시 볼륨처리
- 영구 volume
- Elasticsearch App는 LogStash로 받은 데이터를 기록 분석 할 수 있음
- 상태 저장데이터는 Pod가 비정상 종료가 되어 재시작 되더라도 석을 위해서 보존되어야 함
Volume 방식
이름 설명 emptDir Pod가 생성될 때 생성되고 Pod가 삭제될 때 삭제 hostPath Node의 로컬 볼륨 awsElasticBlockStore AWS EBS 볼륨 azureDisk Microsoft Azure 볼륨 cephfs Ceph 볼륨 cinder 오픈스택 Cinder 볼륨 gcePoesistentDisk GCE 볼륨 gitRepo Git Repository의 콘텐츠를 생성 초기에 저장한 볼륨 iSCSI iSCSI 볼륨 NFS NFS(네트워크 파일시스템) 볼륨
—
emptyDir
Kubernetes Volume - PV & PVC
PV object로 Storage를 추상화하고 PVC object로 Storage를 할당받아 사용
PV(Persistent Volume)는 관리자나 StorageClass에 의해 생성되는 Volume
PVC(PV Claim)는 사용자가 Volume을 사용하기 위해 PV에 요청
Provisioning
PV를 만드는 단계
PV를 미리만들고 사용하는 정적(static)방법과 요청이 있을때 만드는 동적(dynamic)방법이 있다.
Binding
PV를 PVC와 연결하는단계
PVC는 스토리지 용량과 접근방법에따라 PV와 연결, 대응되는 PV가 없으면 대응되는 PV가 생성될때까지 Pending
PV와 PVC는 1:1 관계
Using
Pod에서 PVC를 통해 PV의 볼륨으로 인식하고 사용하는 단계
Reclaiming(회수)
사용이 끝난 PVC가 초기화 되는 단계
- Retain: PVC 삭제 → PV Status(bound → Released)로 바뀌며 다른 PVC가 연결 될 수 없는 상테 PV 속 데이터는 유지
- Delete: PVC 삭제 → PV 삭제
- Recycle: PVC 삭제 → PV Status(bound → Pending)로 바뀜, 다른 PVC 대기
accessMode
PV 생성시 설정하는 접근 권한
- ROX(ReadOnlyMany) - 일기만 가능, 모든 노드 접근 가능
- RWX(ReadWriteMany) - 읽기, 쓰기, 모든 노드 접근 가능
- RWO(ReadWriteOnce) - 읽기, 쓰기, 단일노드
- PV123.yaml
Kubernetes Volume - StorageClass
스토리지 정적 프로비저닝(Static Provisioning)
관리자가 수동으로 PV생성
하위 세부요소인 용량, 액세스 도드 및 저장소 유형을 지정
정의된 PV는 사용자가 생성하는 PVC의 요구사항과 일치하는 사용 가능한 PV에 Binding
스토리지 동적 프로비저닝(Dynamic Provisioning)
PVC요청에 맞게 PV생성을 자동화
관지라는 PV 생성하기 위한 템플릿 StorageClass 정의
사용자가 특정 StoargeClass를 참조하는 PVC를 생성하면 프로비저너는 PVC요구사항에 맞는 PV를 자동 생성
프로비저너(Porvisioner)는 일반적으로 CSP가 제공하는 볼륨플러그인을 사용
동적 프로비정닝, StorageClass 전략
운영환경에서는 성능을 최대로 높게
개발환경에서는 느리지만 안전한 volume에 저장하도록 구성
운영정책에 따라 StorageClass를 정의하여 그에 맞는 PV를 자동 생성 가능
설치 OpenEBS hostpath
OpenEBS hostpath는 Pod가 실행되는 Node의 디렉토리(hostpath)를 Pod의 볼륨으로 할당
Kubernetes 설치 (containerd, kubelet, kubeadm, kubectl)
docker → image 개발 및 테스트containerd → Kubernetes에서 사용하는 container runtime
Kubernetes 클러스터 초기화 (kubeadm init)
master node
Kubeshark - 트래픽 분석 도구
컨테이너, 포드, 노드 및 클러스터에 들어오고 나가는 모든 트래픽과 페이로드를 캡처하고 모니터링하는 API 트래픽 분석기
내부 네트워크에 대한 실시간 프로토콜 가시성 제공
eBPF를 통해 구현, 커널 공관과 유저 공간의 모니터링을 통해 인사이트 제공
kprobe를 사용해 TCP 커넥션에 대한 정보(Source, Destination IP Port)를 수집(Trace)하여 Request/Reponse를 하나로 묶어 제공
실제 TCP 패킷은 PCAP 파일로 임시 저장하여 다운로드 가능
TLS로 암호화된 패킷은 평문으로 확인 가능
통신 간 발생하는 Request, Reponse Header 확인을 통한 애플리케이션 인증 문제확인
Network, Memory 자원을 많이 사용하므로 ks tab 명령 사용 시 대상을 정확히 지정하여 trace 하는 것을 권장
Pod - Init Container
Application container이전에 실행되는 특수 컨테이너 → app.Container 실행환경 준비
다양한 목적으로 사용 가능하지만 Application container 가 원하는 방향으로 실행 될수 준비하는것이 주목적 →메인프로세스 환경의 초기화
App.Container 소스코드 변경 할 필요 없이 환경을 구성가능하게 함
Initial container 동작
- Pod에 관련된 모든 네트워킹 및 스트리지가 프로비저닝 된 후에 실행
- Pod의 initial container가 실피시 kublet은 성공 할 때 까지 init.Container를 반복적으로 재시작
- 단, Pod restartPolicy: Never가 지정되었을땐, init.Container가 실패하면 Kubernetes는 전체 Pod를 실패 처리 후 종료
Initial container 사례
- MSA 소스로부터 최신 구성 파일을 가져오는 작업 → App.Container는 항상 최신 구성이 가능 해짐
- DB init 또는 초기(기본) 데이터를 채우는 작업 구성(스키마 생성, 데이터 마이그레이션)을 처리하여 DB가 App.Container와 상호 작용 준비가 되었는지 확인 할 수 있음 → App.Container 경량화
Initial container 예시
- Local volume 영역을 생성
- Init.Container는 curl로 외부 리소스를 받아 해당데이터를 Local volume에 기록
- App.Container는 시작과 함게 Local volume에서 필요한 데이터를 읽어 작동