쿠버네티스란?
- 쿠버네티스는 컨테이너화된 워크로드와 서비스를 관리하기 위한 이식성이 있고, 확장가능한 오픈소스 플랫폼이다.
컨테이너화 되었다구?
- 전통적인 방식의 배포는 한 물리서버내에 여러 애플리케이션을 배포하는 방식이었다. 이는 하나의 애플리케이션이 많은 리소스를 차지하면 다른 애플리케이션에 성능저하를 불러오는 등 리소스 할당에 문제가 있었다. 이에대한 해결책으로 여러 물리서버에 각 애플리케이션을 배포하였는데 이는 각각의 물리서버의 리소스를 충분히 활용하지 못하는 작은 애플리케이션이라면 자원 및 비용의 낭비를 불러일으키는 문제가 있어, 확장가능하다고 보기 어렵다.
- 가상화를 사용한 배포는 단일 물리 서버의 CPU에서 여러 가상 시스템 (VM)을 실행할 수 있다. 가상화를 사용하면 VM간에 애플리케이션을 격리하고 애플리케이션의 정보를 다른 애플리케이션에서 자유롭게 액세스 할 수 없으므로, 일정 수준의 보안성을 제공할 수 있다. 가상화를 사용하면 물리 서버에서 리소스를 보다 효율적으로 활용할 수 있으며, 쉽게 애플리케이션을 추가하거나 업데이트할 수 있고 하드웨어 비용을 절감할 수 있어 더 나은 확장성을 제공한다. 각 VM은 가상화된 하드웨어 상에서 자체 운영체제를 포함한 모든 구성 요소를 실행하는 하나의 완전한 머신이다. 이런 가상화 기술보다 한층 더 리소스낭비를 최적화 시킨것이 바로 컨테이너 방식이라 할 수 있다.
- 컨테이너를 사용한 배포는 VM과 유사하지만 격리 속성을 완화하여 애플리케이션 간에 운영체제(OS)를 공유한다. 그러므로 컨테이너는 가볍다고 여겨진다. VM과 마찬가지로 컨테이너에는 자체 파일 시스템, CPU 점유율, 메모리, 프로세스 공간 등이 있다. 기본 인프라와의 종속성을 끊었기 때문에, 클라우드나 OS 배포본에 모두 이식할 수 있다.
쿠버네티스 컴포넌트
Cluster
쿠버네티스 클러스터는 컨테이너화된 애플리케이션을 실행하는 노드라고 하는 워커 머신의 집합. 모든 클러스터는 최소 한 개의 워커노드를 가진다.
클러스터 전체를 관리하는 컨트롤러로서 마스터가 존재하고, 컨테이너가 배포되는 물리적인 머신을 노드라고 한다. 노드는 애플리케이션의 구성요소인 파드를 호스트한다
Control plan (Master)
클러스터 내부 요소들을 제어한다. 애플리케이션을 스케줄링하거나, 애플리케이션의 항상성을 유지하거나, 애플리케이션을 스케일링하고, 새로운 변경사항을 순서대로 반영(rolling out)하는 일과 같은 클러스터 내 모든 활동을 조율한다.
마스터 노드는 홀수로 구성한다. 클러스터를 관리할 때 상태값에 대한 합의를 진행하는데 짝수인경우 합의가 되지 않는 경우를 방지하기 위함이다. 1대만 설치할 수도 있지만 고가용성을 위해 3대 또는 5대를 구성하기도 한다.
1. api server
클러스터의 각 요소들을 모니터링하며 작업을 수행하도록 해주는 중앙 접근 포인트의 역할을 한다. 사용자가 kubectl 명령을 통해 또는 오브젝트를 통해 Kubernetes 를 조작하는 것이 API 를 통해 조작한다고 생각하면 된다. Etcd와 유일하게 통신하는 모듈이다. 권한을 체크하여 적절한 권한이 없을 경우 요청을 차단하기도 하며, 관리자 요청 뿐 아니라 다양한 내부 모듈과 통신한다.
2. etcd
모든 클러스터 데이터(Node들의 상태 값, 하드웨어 리소스 값 등)를 담는 쿠버네티스 뒷단의 저장소로 사용되는 일관성·고가용성 key-value 저장소이다. 마치 DataBase 라 비유할 수 있다. 이때 etcd를 뒷단의 저장소로 사용한다면, 이 데이터를 백업하는 계획은 필수이다.
3. Scheduler
노드가 배정되지 않은 새로 생성된 Pod(하나 이상의 컨터이너를 묶어 실행하는 단위) 를 감지하고, 실행할 노드를 선택하는 컴포넌트이다.
4. Controller
로보틱스와 자동화에서 컨트롤 루프 는 시스템 상태를 조절하는 종료되지 않는 루프이다. 예를들어 컨트롤 루프라 할 수 있는 온도 조절기는 장비를 켜거나 꺼서 현재 상태를 의도한 상태에 가깝게 만든다.
쿠버네티스에서 컨트롤러는 클러스터 의 상태를 관찰 한 다음, 필요한 경우에 API 서버로 생성 또는 변경을 요청하는 컨트롤 루프이다. 각 컨트롤러는 현재 클러스터 상태를 의도한 상태에 가깝게 이동한다.
논리적으로, 각 컨트롤러는 분리된 프로세스이지만, 복잡성을 낮추기 위해 모두 단일 바이너리로 컴파일되고 단일 프로세스 내에서 실행된다.
- 노드 컨트롤러: 노드가 다운되었을 때 통지와 대응에 관한 책임을 가진다.
- 레플리케이션 컨트롤러: 시스템의 모든 레플리케이션 컨트롤러 오브젝트에 대해 알맞은 수의 파드들을 유지시켜 주는 책임을 가진다.
- 엔드포인트 컨트롤러: 엔드포인트 오브젝트를 채운다(즉, 서비스와 파드를 연결시킨다.)
- 서비스 어카운트 & 토큰 컨트롤러: 새로운 네임스페이스(pod 들을 효율적으로 묶어 관리하기 위한, 구분지을 수 있게 해주는 논리적인 공간)에 대한 기본 계정과 API 접근 토큰을 생성한다.
- 라우트 컨트롤러: 기본 클라우드 인프라에 경로를 구성한다
- 등등
Node
마스터에의해 명령을 받고 실제 워크로드를 생성해서 서비스한다.
이러한 노드의 컴포넌트로는 kubelet, 컨테이너 런타임 그리고 kube-proxy가 포함되며, 노드 컴포넌트는 동작 중인 파드를 유지시키고 쿠버네티스 런타임 환경을 제공하며, 모든 노드 상에서 동작한다.
1. Kubelet
master와 통신하며 Pod에서 Container가 확실하게 동작하도록 관리한다. 이때 Kubelet은 쿠버네티스를 통해 생성되지 않는 컨테이너는 관리하지 않는다.
2. proxcy
kube-proxy는 클러스터의 각 노드에서 실행되는 네트워크 프록시로, 쿠버네티스의 서비스 개념의 구현부이다.
kube-proxy는 노드의 네트워크 규칙을 유지 관리하며, 내부 네트워크 세션이나 클러스터 바깥에서 파드로 네트워크 통신을 할 수 있도록 해준다.
3. 컨테이너 런타임
컨테이너 런타임은 컨테이너 실행을 담당하는 소프트웨어이다.
컨테이너 런타임 인터페이스(CRI)는 kubelet과 컨테이너 런타임 사이의 통신을 위한 주요 프로토콜이며, gRPC를 사용한다.
쿠버네티스는 containerd, CRI-O, Docker Engine와 같은 컨테이너 런타임 및 모든 Kubernetes CRI (컨테이너 런타임 인터페이스) 구현체를 지원한다.
* gRPC는 모든 환경에서 실행할 수 있는 최신 오픈 소스 고성능 RPC(원격 프로시저 호출) 프레임워크이다.
파드(pod)
쿠버네티스에서 배포할 수 있는 가장 작은 단위로, 쿠버네티스는 컨테이너를 바로 관리하는것이 아닌 pod으로 컨테이너를 감싸서 관리한다.
한 개 이상의 컨테이너와 스토리지, 네트워크 속성을 가진다.
Pod에 속한 컨테이너는 스토리지와 네트워크를 공유하고 고유의 아이피를 부여받아 서로 localhost로 접근할 수 있다.
파드 (고래 떼(pod of whales)나 콩꼬투리(pea pod)와 마찬가지로)는 하나 이상의 컨테이너의 그룹이다.
따라서 파드는 두 가지의 경우로 나눌 수 있다.
- 단일 컨테이너를 실행하는 파드.
- 함께 작동해야 하는 여러 컨테이너를 실행하는 파드.
파드의 라이프 싸이클
Pending
-> Running
-> Succeeded
or Failed
or Unknown
ReplicaSet
신규 Pod를 생성하거나 기존 pod을 제거하여 원하는 수를 유지 할 때는 반드시 ReplicaSet을 사용해야 합니다. ReplicaSet은 복제할 개수, 개수를 체크할 라벨 선택자, 생성할 Pod의 설정값(템플릿)등을 가지고 있습니다.
주로 직접적으로 ReplicaSet을 사용하기보다는 Deployment등 다른 오브젝트에 의해서 사용되는 경우가 많습니다.
Deployment
deployment를 통해 컨테이너 관리
ReplicaSet을 이용하여 Pod을 업데이트하고 이력을 관리하여 롤백하거나 특정 버전으로 돌아갈 수 있습니다 (=배포 버전을 관리)
deployment가 replicaset을 만들고 replicaset이 pod을 만드는게 일반적입니다.
Service
네트워크와 관련된 오브젝트입니다. Pod을 외부 네트워크와 연결해주고 여러 개의 Pod을 바라보는 내부 로드 밸런서를 생성할 때 사용합니다. 내부 DNS에 서비스 이름을 도메인으로 등록하기 때문에 서비스 디스커버리 역할도 합니다.
ex) 도커에서 이미지를 가져와 deployment 해보자
kubectl create deployment test --image=docker.io/hooneats/kube-project:latest
kubectl expose deployment test --type="NodePort" --port=8080
- kubectl create deployment : deployment 생성
- kubectl expose deployment : service 생성
http://localhost:30477 로 접속하면(NodePort : 30477/TCP) 다음과 같이 서비스가 작동하는것을 확인할 수 있다.
NodePort( 30000 - 32767 )
- 외부에서 접속하기 위해 사용하는 포트
port
- Cluster 내부에서 사용할 Service 객체의 포트
targetPort
- Service객체로 전달된 요청을 Pod(deployment)로 전달할때 사용하는 포트
* 전체 서비스 흐름으로 보면 NodePort --> Port --> targetPort
Volume
저장소와 관련된 오브젝트입니다. 호스트 디렉토리를 그대로 사용할 수도 있고 EBS 같은 스토리지를 동적으로 생성하여 사용할 수도 있습니다.
쿠버네티스 오브젝트
쿠버네티스 시스템에서 영속성을 가지는 오브젝트이다.
쿠버네티스 오브젝트는 하나의 "의도를 담은 레코드"이다. 오브젝트를 생성하게 되면, 쿠버네티스 시스템은 그 오브젝트 생성을 보장하기 위해 지속적으로 작동할 것이다. 오브젝트를 생성함으로써, 여러분이 클러스터의 워크로드를 어떤 형태로 보이고자 하는지에 대해 효과적으로 쿠버네티스 시스템에 전한다.
생성이든, 수정이든, 또는 삭제든 쿠버네티스 오브젝트를 동작시키려면, 쿠버네티스 API를 이용해야 한다. 예를 들어, kubectl 커맨드-라인 인터페이스를 이용할 때, CLI는 여러분 대신 필요한 쿠버네티스 API를 호출해 준다. 또한, 여러분은 클라이언트 라이브러리 중 하나를 이용하여 여러분만의 프로그램에서 쿠버네티스 API를 직접 이용할 수도 있다.
오브젝트 명세(spec)와 상태(status)
쿠버네티스 컨트롤 플레인은 오브젝트 명세(spec)를 읽어 의도하고자한 상태와 실제 상태를 일치시키기 위해 끊임없이 그리고 능동적으로 관리한다.
- ex1) 쿠버네티스 디플로이먼트는 클러스터에서 동작하는 애플리케이션을 표현해줄 수 있는 오브젝트이다. 디플로이먼트를 생성할 때, 디플로이먼트 spec에 2개의 애플리케이션 레플리카가 동작되도록 설정할 수 있다. 쿠버네티스 시스템은 그 디플로이먼트 spec을 읽어 spec에 일치되도록 상태를 업데이트하여 2개의 의도한 애플리케이션 인스턴스를 구동시킨다. 만약, 그 인스턴스들 중 어느 하나가 어떤 문제로 인해 멈춘다면(상태 변화 발생), 쿠버네티스 시스템은 보정(이 경우에는 대체 인스턴스를 시작하여)을 통해 spec과 status간의 차이에 대응한다.
- deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # tells deployment to run 2 pods matching the template
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
위 예시와 같이 .yaml 파일을 이용하여 명세와 상태를 반영한 디플로이먼트를 생성하기 위한 하나의 방식으로는 kubectl 커맨드-라인 인터페이스에 인자값으로 .yaml 파일을 건네 kubectl apply 커맨드를 이용하는 것이다.
kubectl apply -f deployment.yaml
어떠한 변경이 이루어질지 확인 후 적용 시킬수도 있다.
kubectl diff -f deployment.yaml
kubectl apply -f deployment.yaml or kubectl replace -f deployment.yaml
apply 는 없으면 새로 생성
관련글 : create, apply, replace , fetch
apiVersion
- 이 오브젝트를 생성하기 위해 사용하고 있는 쿠버네티스 API 버전이 어떤 것인지kind
- 어떤 종류의 오브젝트를 생성하고자 하는지metadata
-이름
문자열,UID
, 그리고 선택적인네임스페이스
를 포함하여 오브젝트를 유일하게 구분지어 줄 데이터spec
- 오브젝트에 대해 어떤 상태를 의도하는지
네임스페이스
쿠버네티스에서, 네임스페이스 는 단일 클러스터 내에서의 리소스 그룹 격리 메커니즘을 제공한다. 리소스의 이름은 네임스페이스 내에서 유일해야 하며, 네임스페이스 간에서 유일할 필요는 없다.
쉽게말해 리소스를 그룹지어 관리하기 위한 논리적 공간이라 생각하면 된다.
개발, 스테이징, 운영과 같이 여러 네임스페이스 내에서 동일한 설정을 사용하는 경우에 유용하다.
쿠버네티스는 처음에 네 개의 초기 네임스페이스를 갖는다.
- default 다른 네임스페이스가 없는 오브젝트를 위한 기본 네임스페이스
- kube-system 쿠버네티스 시스템에서 생성한 오브젝트를 위한 네임스페이스
- kube-public 이 네임스페이스는 자동으로 생성되며 모든 사용자(인증되지 않은 사용자 포함)가 읽기 권한으로 접근할 수 있다. 이 네임스페이스는 주로 전체 클러스터 중에 공개적으로 드러나서 읽을 수 있는 리소스를 위해 예약되어 있다. 이 네임스페이스의 공개적인 성격은 단지 관례이지 요구 사항은 아니다.
- kube-node-lease 이 네임스페이스는 각 노드와 연관된 리스 오브젝트를 갖는다. 노드 리스는 kubelet이 하트비트를 보내서 컨트롤 플레인이 노드의 장애를 탐지할 수 있게 한다.
ex1) 요청에 네임스페이스 설정하기
kubectl run nginx --image=nginx --namespace=<insert-namespace-name-here>
kubectl get pods --namespace=<insert-namespace-name-here>
ex2) 선호하는 네임스페이스 설정하기(이후 모든 kubectl 명령에서 사용하는 네임스페이스를 컨텍스트에 영구적으로 저장할 수 있다.)
kubectl config set-context --current --namespace=<insert-namespace-name-here>
# 확인하기
kubectl config view --minify | grep namespace:
ex3) 다음은 네임스페이스에 속하거나 속하지 않는 쿠버네티스 리소스를 조회하는 방법이다.
# 네임스페이스에 속하는 리소스
kubectl api-resources --namespaced=true
# 네임스페이스에 속하지 않는 리소스
kubectl api-resources --namespaced=false
레이블과 셀렉터
레이블 은 파드와 같은 오브젝트에 첨부된 키와 값의 쌍이다. 레이블은 오브젝트의 특성을 식별하는 데 사용되어 사용자에게 중요하지만, 코어 시스템에 직접적인 의미는 없다. 쉽게말해 태그와 비슷하다 생각하면 된다.
레이블은 오브젝트를 생성할 때에 붙이거나 생성 이후에 붙이거나 언제든지 수정이 가능하다. 오브젝트마다 키와 값으로 레이블을 정의할 수 있다. 오브젝트의 키는 고유한 값이어야 한다.
ex1) 다음과 같은 Pod를 띄웠을 때 레이블을 가지고 쉽게 pod 를 선턱할 수도 있다.
apiVersion: v1
kind: Pod
metadata:
name: label-demo
labels:
environment: production
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
kubectl get pods --show-labels
kubectl get pods -l environment=production
셀렉터는 쉽게말해 레이블의 체크 조건이라 할 수 있다. 다음과 같은 예시로 이해해 보자.
label 을 삭제해 보자
kubectl label pod/label-demo environment-
kubectl get pods --show-labels
label 이 삭제된 것을 볼 수있다. 만약 우리가 selector 를 활용해 label 체크 조건을 입력한다면 어떻게될까?
ex2) 생성했던 pod 를 지우고 ReplicaSet 으로 다시 진행해보자.
kubectl delete pod label-demo
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: label-demo
spec:
replicas: 1
selector:
matchLabels:
environment: production
app: nginx
template:
metadata:
labels:
environment: production
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
- spec.replicas : 원하는 Pod의 개수
- spec.selector : label 체크 조건
- spec.template : 생성할 Pod의 명세
방금전과 똑같이 label 을 삭제해 보자
kubectl get pods --show-labels
kubectl label pod/<pod-Name> environment-
kubectl get pods --show-labels
위와같이 selector 에 명시한 label 상태를 유지시키기위해 새로운 pod를 띄운것을 확인할 수 있다.
레이블의 키는 접두사를 가질 수 있으며, 접두사를 생략하면 키 레이블은 개인용으로 간주한다.
kubernetes.io/와 k8s.io/ 접두사는 쿠버네티스의 핵심 컴포넌트로 예약되어 있다.
kubectl
kubectl
은 config 파일을 $HOME/.kube 에서 찾는다. KUBECONFIG 환경 변수를 설정하거나 --kubeconfig
플래그를 설정하여 다른 kubeconfig 파일을 지정할 수 있다.
Kubectl 기본명령어
- apply : 원하는 상태를 적용
- get : 리소스 목록을 보여줌
- describe : 리소스의 상태를 자세하게 보여줌
- delete : 리소스를 제거
- logs : 컨테이너의 로그 보기
- exec: 컨테이너에 명령어 전달 컨테이너에 접근할 때 주로 사용한다
- config : kubectl 설정 관리
- kubectl api-resources -o wide : api resource의 약어( ex: pods = pod =po 다 같은 pod을 가르키는 말), namespace기반, 사용할수 있는 verb(권한)을 확인 할 수 있음
'DevOps' 카테고리의 다른 글
Docker container 를 활용해 CI/CD 실습해보자 feat(Jenkin, Ansible, Minikube) (0) | 2022.09.14 |
---|---|
Kubernetes 구조 이해하기 (0) | 2022.08.10 |
최신 (k8s - 2022.07 기준) kubernetes 설치 (0) | 2022.07.31 |
Terraform 을 사용해 AWS EC2 Instance 를 올려보자 (0) | 2022.07.26 |
AWS를 통한 효과적인 데브옵스 구축 2/e 2장 중 AWS CLI 로 EC2 구성하기 (0) | 2022.07.20 |