@BeforeAll
- 인프런에 존재하는 [대세는 쿠버네티스]라는 강의를 보고 내용을 정리
- 강의 내용 외의 내용은 따로 여러 블로그나 책, 쿠버네티스 공식 사이트에서 발췌했습니다.
- ref : https://kubernetes.io/ko/docs/concepts/overview/working-with-objects/kubernetes-objects
쿠버네티스 오브젝트
쿠버네티스 오브젝트의 이해
쿠버네티스 오브젝트
- 쿠버네티스 시스템에서 영속성을 가지는 오브젝트
- 쿠버네티스는 클러스터 상태를 나타내기 위해 이 오브젝트를 이용함
- detail
- 어떤 컨테이너화된 애플리케이션이 동작 중인지 (그리고 어느 노드에서 동작 중인지)
- 그 애플리케이션이 이용할 수 있는 리소스
- 그 애플리케이션이 어떻게 재구동 정책, 업그레이드, 그리고 내고장성과 같은 것에 동작해야 하는지에 대한 정책
- 하나의 “의도를 담은 레코드”
- 오브젝트를 생성하면/
- 쿠버네티스 시스템은 그 오브젝트 생성을 보장하기 위해
Pod - Container, Label, NodeSchedule
파드
- 쿠버네티스에서 어플리케이션 디플로이의 단위, 적어도 하나 이상의 컨테이너로 이루어짐
- 쿠버네티스에서는 여러 개의 컨테이너를 모아서 파드(pod)에 담을 수 있음
- 이 구조가 완두콩이 콩을 담고 있는 모양과 비슷해서 ‘꼬투리’를 의미하는 영어 단어인 Pod이라는 이름이 되었다
- 파드 단위로 컨테이너의 조작(생성, 시작, 정지 삭제)을 한다 → 쿠버네티스의 최소 실행 단위
- 파드는 하나의 목적을 위해서 생성된 컨테이너를 부품처럼 조합가능하도록 설계되었다
- 파드 내부의 컨테이너들은 파드의 IP와 포트번호를 공유한다
- 파드 내부의 컨테이너들은 반드시 동일한 노드에 할당되며 동일한 생명 주기를 갖는다
- 파드 내부의 컨테이너들은 localhost로 서로 통신이 가능하다
- 파드 내부의 컨테이너들은 System V 프로세스 통신이나 POSIX 공유메모리를 사용해 서로 통신 가능
- 파드 내부의 컨테이너들은 파드 볼륨을 마운트해서 파일 시스템을 공유 가능
- 위의 기능은 같은 pod안의 컨테이너 끼리만 가능
- 파드는 일시적 존재
- 파드내의 컨테이너는 이미지로부터 매번 생성된다.
- 같은 오브젝트 이름으로 몇번이고 기동해도 이전에 수행한 변경 이력 없이 이미지 초기 상태에서 시작한다
- 컨트롤러에 의해 동적으로 기동/삭제 → 고정ip가 아님 → 파드 요청시 서비스가 반드시 필요
레이블(Label) - ref : https://kubernetes.io/ko/docs/concepts/overview/working-with-objects/labels
- 쿠버네티스의 리소스를 식별하기 위한 임의의 정보의 정의
- 말그대로 임의의 라벨 쪽지를 붙인다고 이해하는게 편함
- 쿠버네티스는 레이블만으로 관리 대상 구분 - 컨트롤러와 파드의 loose coupling 지향
- 유형
- Key - Value형
- Key는 필수, 길이는 63자 이내, 맨앞과 뒤는 반드시 알파벳이나 숫자
중간에는 대시(-), 언더스코어(_), 닷(.)도 사용 가능 - /로 구분된 prefix 지정 가능
- DNS 서브도메인에서 길이 253자 제한
- 단
kubernetes.io/
는 쿠버네티스 시스템에서 이용하므로 지정 불가
- label selector
- 특정 레이블을 선택할 떄 사용
- 두 가지 방식 : 등호 기반(equality-based), 집합 기반(set-based)
- 등호 기반
- 연산자 : 같다(=,==), 다르다(!=)
- ex :
environment=develop
- 여러 조건 : ,로 연결 ex)
environment=develop, release=stable
- 집합 기반
- 여러개 값을 조건으로 설정해서 해당 키가 있는 레이블 값이
조건에 속하는지(in) 아닌지(notin) 확인 - 특정 레이블의 키가 존재(exists)하는지도 가능노드 스케쥴링
1
environment in (develop, stage)
- 여러개 값을 조건으로 설정해서 해당 키가 있는 레이블 값이
- 기본 : 자동 스케쥴링, 노드 셀렉터
- 자동 : 쿠버가 알아서 노드를 선택하고 스케쥴링
- 노드셀렉터
- 파드가 클러스터 안의 어떤 노드에서 실행될지 key-value 쌍으로 설정
- ex) A노드는 SSD, B노드는 HDD로 사용할 떄 , 특정 Pod에 한해서 SSD를 이용하게 하고 싶은 경우
Service - ClusterIP, NodePort, LoadBalancer Service
서비스
외부에서 쿠버네티스 클러스터에 접속하는 방법
쿠버네티스 클러스터 안에서 replicaset등의 pod의 집합에 대한 경로나 서비스 디스커버리를 제공
필요 이유 : 파드는 일시적 존재 - ip가 계속 바뀜 - 클라이언트의 요청을 전달할 서비스가 필요
서비스 디스커버리를 수행하는 도메인 이름 기반의 엔드포인트 제공
동작
- 서비스는 로드발란서의 역할을 가지며, 클라이언트 요청을 받기 위한 대표 ip 주소를 획득
- 서비스가 만들어질 때 서비스 이름이 내부 DNS 등록된다
따라서 클라이언트는 서비스 이름만으로 서비스의 ip를 획득할 수 있다 - 서비스는 selector에 지정된 label과 일치하는 파드중 하나에게 요청을 전달한다
- 파드는 기동될때 자신의 정보(label, ip등)를 마스터 노드의 etcd에 등록해놓았다
- 따라서 해당 프로세스 중에 selector의 라벨에 일치하는 파드를 etcd에 조회해서 전송할 파드의 ip를 취득한다
- 서비스가 만들어지고 나서 생성 파드의 컨테이너에는 서비스 정보가 담긴 환경변수가 자동으로 설정된다
서비스의 종류
- ClusterIP
서비스 리소스의 가장 기본이 되는 타입, 타입 지정 없으면 기본값 선택
쿠버네티스 클러스터 내부 IP에 서비스가 공개
클러스터 내부에서만 접근 가능하며 외부에서 접근 불가
존재이유
- 많은 경우 제한된 엔드 포인트 외에는 직접 트래픽을 전달 받지 않음(네트워크 보안 및 관리)
대신 외부로 열린 엔드포인트로부터 트래픽을 전달받아 서비스를 제공 - 더 확장된 쿠버네티스 네트워킹을 위한 기본 빌딩 블럭
ClusterIP를 기반으로 더 복잡한 네트워킹 수행 가능
- 많은 경우 제한된 엔드 포인트 외에는 직접 트래픽을 전달 받지 않음(네트워크 보안 및 관리)
사용처 : 인가된 사용자(운영자), 내부 Dashboard, pod서비스상태 디버깅
- NodePort
- ClusterIP를 만드는 점은 1번과 동일
- 각 노드에서 서비스 포트로 접속하기 위한 글로벌 포트를 개방하는 점이 차이
- 모든 Node에 똑같은 포트가 할당됨
- k8s는 클러스터 시스템 → 특정 노드 가 아니라 모든 노드에 동일하게 적용됨
- kube-proxy
- 리눅스 커널의 netfilter를 이용해서 커널 레벨에서 특정 트래픽을
중간에 가로채서 다른 곳으로 라우팅 해주는 역할을 수행 - 이를 통해 Pod이 위치한 노드 뿐 아니라 모든 노드에서
동일한 NodePort로 원하는 서비스에 접근 할 수 있게 제공
(externalTrafficPolicy: Cluster
인 경우)
- 리눅스 커널의 netfilter를 이용해서 커널 레벨에서 특정 트래픽을
- kube-proxy
- k8s는 클러스터 시스템 → 특정 노드 가 아니라 모든 노드에 동일하게 적용됨
- 물리적인 로컬호스트의 ip를 통해서 pod 접근 가능
- 사용처 : 클러스터 밖에 있지만 내부망 연결시 사용 ,일시적 데모
why? 대부분 host ip는 보안적으로 내부망에서만 접근 가능하게 네트워크가 구성되어 있음
- LoadBalancer
- 역시 NodePort를 만드는 점은 2번과 동일하다
- 다만 이때 요청을 받은 노드 내에 있는 파드로만 전송하도록 설정할 수 있다((
externalTrafficPolicy: local
인 경우)) - 노드들 앞에 LB가 있다면 매우 유용한 설정이다
- 다만 이때 요청을 받은 노드 내에 있는 파드로만 전송하도록 설정할 수 있다((
- 이후 외부ip를 가진 Loadbalancer가 각각node의 nodeport를 가르키게 됨
- 퍼블릭 클라우드 플랫폼의 LB 지원 - GCP의 Cloud Load Balancing, AWS의 Elastic Load Balancing을 지원한다
- 기본적으로는 사용이 안되며 로컬에서 사용하려면 metalLB등을 사용해야함
- LB 사용 이유
- 보안성
- 호스트 서버의 NodePort 대역(30000~23767)을 외부에 노출할 필요가 없음
- LB만 외부 네트워크에 위치해서 endpoint 제공 - 네트워크 보안성 증가
- 디스커버리 편의성
- 사용자가 master,worker를 직접 알 필요 없이 LB의 도메인이나 ip로 요청 가능
- 실무에서는 Pod처럼 노드들도 생성및 삭제가 잦음 - 그떄마다 노드 ip 추적은 비효율적
- ClusterIP 타입 서비스가 Pod레벨의 안정적 서비스 엔드포인트를 제공한다면
LB 타입 서비스는 노드 레벨에서의 안정적인 서비스 엔드포인트를 제공한다
- ExternalName
- 셀렉터도 포트 정의도 없는 상당히 특이한 서비스임
- 쿠버네티스 클러스터에서 외부 호스트를 네임 레졸루션하기 위한 별명 제공
- 쿠버네티스 클러스터에 편입되지 않은 외부서비스에 쿠버네티스 네트워킹 기능을 연결하고 싶은 경우
1
2
3
4
5
6
7
8# order.service.co.kr을 order로 참조가능
apiVersion: v1
kind: Service
metadata:
name: order
spec:
type: ExternalName
externalName: orderr.service.co.kr
Volume
볼륨
- pod 내부 스토리지 생명주기는 pod와 동일
- 내부의 데이터를 pod 생명주기와 상관없이 저장 및 유지 하고 싶다면? 볼륨 연결 필요(emptyDir빼고)
볼륨의 종류 : 사실상 emptyDir, hostPath는 자쥬 사용되지 않는다
emptyDir
- pod 안에 생성되는 임시볼륨 - 같은 pod의 컨테이너들끼리 데이터 공유할 때 사용
- 최초 생성시 비어있음
- pod 재생성시 만들어지고 없어짐
hostPath
- 도커의
-v
옵션과 유사하게 host 의 공간에 pod가 데이터를 저장하는 방식 - pod 이 죽어도 사라지지 않는 볼륨
- 각 노드에 자신만을 위해 사용되는 파일들을 위해 사용하면 좋음 - 모든 노드에 배치되는 특수한 pod이라던지
- 각 pod들이 host에 대한 정보등을 읽고 쓸 때 사용
- 문제점
- pod이 다른 노드에서 재생성되면 해당 볼륨을 사용할 수 없다
- 해결책
- Node 추가할 때마다 Mount
- 운영자가 직접 리눅스 mount 사용
- 어렵지 않으나 사람이 개입되는 프로세스 - 실수의 여지가 있음
- 클러스터에 더 적합한 방법이 필요해 보임
- 도커의
PVC/PV
- 사용 이유
- 위의 단점 : pod이 다른 노드에서 재생성시 문제
- 볼륨과 어플리케이션의 정의가 강하게 연관되서 분리할 수 없는 상황
예) NFS로 MySQL Deployment를 사용할 거에요 - 하고 yaml 생성
해당 yaml에는 NFS가 명시 되어있으므로 이 yaml로 MySQL을 생성하려면 반드시 NFS 사용 필요
다른 볼륨타입을 만들려면 별도의 YAML을 여러개 만들어서 배포가 필요
PV / PVC : pod이 볼륨의 세부사항을 몰라도 볼륨을 사용하게 만드는 추상화 역할
pod 를 만드는(사용자의) YAML에서는 NFS인지 EBS인지 상관없이 볼륨을 사용하게 만드는게 핵심
PV : Persistent Volume
- 어느 노드에서도 접근해서 사용할 수 있는 볼륨
- worker 노드들이 네트워크상에서 스토리지를 마운트해서 영속적으로 데이터를 저장 가능
- pod이 장애가 생겨 다른 노드에 옮겨가도 옮겨간 노드에서 PV에 네트워크로 연결해 계속 사용 가능
- 네트워크 볼륨 예시 : NFS, AWS의 EBS(Elastic Block Store), Ceph, GlusterFS
- 쿠버네티스 클러스터를 관리하는 인프라 관리자 영역
- 인프라 관리자가 네트워크 볼륨을 이용해서 PV 리소스를 미리 생성
PVC : Persistent Volume Claim
- 쿠버네티스 클러스터에 어플리케이션을 배포하려는 사용자(개발자) 영역
- accessMode, 볼륨 크기, 스토리지 클래스, 레이블 셀렉터로 PV 선택 가능
쿠버네티스는 기본 관리자가 생성한 PV 속성과 사용자가 요청한 PVC 요청이 일치하면
두개의 리소스를 매칭시켜 bind
ConfigMap, Sercret - Env, Mount
컨피그 맵 - 컨테이너에 필요한 환경 설정을 컨테이너와 분리해서 제공 가능한 기능
- 개발과 상용은 서로 다른 설정이 필요한 부분이 많다.
- 해당 설정을 컨테이너에 넣으면? 다른 이미지가 되어버림!
- 클라우드 네이티브 아키텍처에서 컨테이너는 immutable 해야한다
- dev환경과 prod환경의 컨테이너는 동일한 이미지어야 함
- 그래야 개발과 운영의 환경차이에서 오는 잠재적 문제를 없앨 수 있음
- 컨피그맵을 사용하면 같은 컨테이너 이미지에 다른 설정의 주입이 가능
시크릿
- 민감한 정보(패스워드, OAuth Token, SSH Key등) 저장하는 용도
- 디스크에 저장되지 않고 tmpfs라는 메모리 기반 파일시스템 사용 - 보안에 강함
- 리소스 조회시 base64로 한번 인코딩 되어 표시됨
- built-in 시크릿
- 쿠버네티스 클러스터 안에서 쿠버네티스 API 접근시 사용
- 클러스터 안에서 사용하는 ServiceAccount라는 계정을 생성하면 자동으로 관련 시크릿 생성
- 사용자 정의 시크릿 : 사용자가 만든 시크릿
- etcd에 암호화 되지 않은 텍스트로 저장됨 - etcd에 직접 접근하면 내용확인 가능
- 개별 시크릿 데이터의 최대 용량은 1MB
컨피그맵, 시크릿의 데이터 타입
- 상수(Literal)
- 문자열
- 시크릿의 Value는 base64인코딩되어있으며 주입시 자동 decode되서 주입된다
- file
- 파일 이름이 key
- volume mount
- 컨피그 맵 차체가 볼륨으로 마운트 하여 파일처럼 사용 - 컨피그맵 리소스 활용 방법
Namespace, ResourceQuota, LimitRange
강의 내용
네임스페이스 - ref : https://kubernetes.io/ko/docs/concepts/overview/working-with-objects/namespaces/
- 쿠버네티스는 클러스터 안에 가상 클러스터를 다시 만들 수 있다
- 쿠버네티스 클러스터 하나를 여러 개의 논리적 단위로 나누어서 사용하는 것
- 네임스페이스를 이용해서 한 클러스터를 여러 팀이나 사용자가 함께 공유 가능
- 개발자나 팀마다 자신만의 네임스페이스를 두면 메인 네임스페이스가 어질러지는 것을 막을 수 있음
- 네임 스페이스마다 권한을 설정할 수 있으므로 더욱 견고하고 세세하게 권한을 제어할 수 있다
- 네임스페이스 리소스
- 대부분의 쿠버네티스 리소스가 네임스페이스 안에 포함되어 존재 - Pod, Deployment, Service등
리소스쿼터(ResourceQuota)
- 특정 네임스페이스가 자원을 낭비하거나 다른 네임 스페이스에 영향을 주지 않도록 쿼터를 둠
- requests, limit를 이용해서 리소스를 관리
- requests : 최소 리소스 사용량 보장
- cpu : cpu 최소 사용량 정의
- memory : 메모리 최소 사용량 정의
- limit : 최대 리소스 사용량 제한
- cpu : cpu 최대 사용량 정의, 최대치 넘으면 throttling발생
- memory : 메모리 최대 사용량 정의, 최대치 넘으면 Out of Memory 에러 발생, 강제 중단
- requests : 최소 리소스 사용량 보장
리미트레인지(LimitRange)
- 각각의 pod의 최대크기 제한
- 특정 pod 크기가 설정한 값보다 크면 들어올 수 없음
이해가 안되서 정리
리소스 quota 설정은 무엇을 위한 quota인가
Resource Limits, Resource Requests : Pod의 QOS에 영향을 준다
- 어플리케이션 리소스 요구량 - 개발자 책임
- request, limnit를 맞추면 우선 순위가 높은 Qos Guaranteed를 구할 수 있음
- 즉 어플리케이션을 위한 제약 - 부정적이 아니라 긍정적으로 활용해야함
- 관리자의 입장에서는 검토, 리소스 부족시 증설도 검토 필요
LimitRange, ResourceQuota : 클러스터를 위한 제약
- 클러스터 전체에 영향을 주는 리소스 소비를 억제
- 클러스터 이용자 전원을 보호하기 위한 제약
이상적?
- 정답은 없음, 현실적인 대안은?
- 우선 가이드라인을 만들고 프로젝트의 희망사항을 들으면서 상한 변경 하기
- 프로젝트 개별적으로 네임스페이스 상한을 완화 하기