kubernetes

Oct 10, 2022 - Kubernetes 개념

jongviet 2022. 10. 10. 16:43

새롭게 몸담은 회사에서 Kubernetes(이하, k8s)를 사용하게 되었다. 그전까지는 nginx, pm2 cluster로 구성된 방식으로 각각의 ec2 instance에 배포하고 ssh로 접근해서 하나하나 관리를 하면서 백엔드를 관리했었는데, docker와 함께 듣기만 했던 k8s를 사용해보게되었다. 개념 잡기에는 여러 문서들도 도움이 되었지만, 하기 유튜브 링크가 가장 많은 도움이 되었던 것 같다. 도식화된 자료와 함께 아주 쉽게 설명해주신다!

 

https://www.youtube.com/watch?v=Ia8IfowgU7s&list=PLIUCBpK1dpsNf1m-2kiosmfn2nXfljQgb 

 

#등장배경

-서버 상태 관리는 아무리 문서화 해도 전달이 잘 안됨.. 다양한언어, 프레임워크 등.. 그래서 서버 하나에 VM 여러개를 돌리는 방법이 등장하였으나, 특정한 클라우드 환경에 대한 의존성이 생겨 다양한 환경으로 옮겨 사용하기가 어려워짐! 그래서 등장한게 도커컨테이너! 도커 컨테이너는 배포와 롤백이 간단하고, 언어와 프레임워크에 관계 없이 어플리케이션을 동일한 방식으로 개발, 테스팅, 운영할 수 있게 해줌!

 

develop -> build(image생성) -> ship(저장소 내 배포) -> run

 

-그러나 각각의 도커에 ssh로 접근해서 docker stop app && docker run 무한 반복하면서 관리하는 방식은 굉장히 귀찮았음... 컨테이너별 버전관리... 롤아웃, 문제 생길 시 롤백... IP 변경 될 때 마다 nginx에 변경된 아이피 반영.... 너무 복잡해짐.

-그에 대한 니즈로 등장한게 클러스터 단위 노드 오케스트레이션! 각 컨테이너끼리의 통신, 상태관리, 롤아웃&롤백, 버저닝, 서비스등록, 각 컨테이너 및 노드 변경에 따른 프록시 서버 설정 변경 및 프로세스 재시작 등 수동으로 조작해야하고 관리해야할 다양한 업무영역을 직접 해주게 됨!

->그러한 일을 해주는 대표적인 것이 k8s!

 

#k8s 아키텍쳐

-마스터와 노드로 나뉘어져 있으며, 마스터 내에는 스케쥴러, 각종 컨트롤러, API 서버, etcd 등이 있고, 노드 내에는 pod으로 감싸진 컨테이너가 존재함!

 

마스터의 구성 요소

*스케쥴러: 서버 별 상태 체크, 네트워크 상태 체크, pod 생성 점검, 노드 할당 등등.. 다 해줌!! - replication, endpoint(LB), namespace, custom, ML(machine learning), CI/CD
*etcd: 마스터에서 상태와 데이터를 저장함, 분산시스템으로 구성하여 안정성을 높임.
*API서버: etcd와 유일하게 통신하는 모듈, restAPI 형태, 권한 체크, 내부 모듈과 통신, 상태를 바꾸거나 조회 등…
*컨트롤러: 끊임없이 상태를 체크하고 원하는 상태를 유지, 복잡성을 낮추기위해 하나의 프로세스로 실행, 무한 루프!! 상태체크.
->if(current state !== desired state) take action

 

노드의 구성 요소

*proxy(iptables, ipvs) 및 kubelet

*kubelet은 API 서버와 각각의 pod을 바라보고 움직임! pod에 대한 상태 체크, 실행, 중지 등을 담당!

*proxy는 내/외부 통신 설정, 네티워크 프록시 및 부하분산 역할을 함!

*그 외 CNI, DNS, visualization 등이 있음!

 

#k8s 오브젝트

-팟이 가장 작은 배포 단위! 팟이 컨테이너를 감싸고 있는 형태이며 그 안에 로그, 캐시 등이 포함 됨! 각 팟은 고유한 IP를 할당 받음! 

-replicaSet은 여러개의 팟을 관리함! 새로운 Pod은 template을 기반으로 생성되며 신규 pod을 생성 또는 제거하여 설정된 replicaSet수를 맞춤! v1 3개에서 v2로 버전업 진행 시, 하나씩 점진적으로 변경됨!

-데몬셋은 모든 노드에 하나씩만 떠있길 원하는 경우 사용, 예를들어 로그수집이나 모니터링
-스테이트풀셋은 순서대로 팟을 실행하고 싶거나 같은 볼륨을 재활용하고 싶을 때 사용
-잡은 한번 실행하고 죽는 팟
-각 팟의 아이피는 죽고 살 때 계속 변경되기에, 중간에 서비스(cluster IP)로 보내서 LB가 됨!

 

-각 노드 별로 앞단에 서비스 LB를 두고, nodePort를 가짐! nodePort를 거쳐 clusterIP에 도달하여 필요한 동작을 수행함.

-ingress란 도메인 또는 경로 별로 라우팅 해주는 역할을 함. nginx라고 생각하면됨! 즉 클라이언트 단에서 특정 도메인으로 접근하여 각 도메인에서 LB를 통해 각 nodePort에 배분 되고, clusterIP에 맞추어 각 팟에 도달하는 구조.

 

abcd.com -> service A

fghd.com/help -> service B

fghd.com/info -> service C

 

-그 외 다양한 기본 오브젝트가 있음


* Volume: storage(EBS, NFS)
* Namespace: 논리적인 리소스 구분
* configMap/secret: 설정
* serviceAccount: 권한계정
* Role/ClusterRole: 권한설정(get, list, watch, create….)

 

#쿠버네티스 API 호출

-원하는 상태를 다양한 오브젝트(pod, service, ingress)로 정의(spec)하고 API서버에 Yaml 형식으로 전달!

-새로운 요청이 API 서버를 통해 접수 되면, 컨트롤러, 스케쥴러 가 캐치하여 node 내 kubelet과 함께 통신한 후, 신규 pod 생성!

 

yaml -> JSON

-yaml의 경우 object는 ' : ' 으로 구분, array는 ' - ' 하이픈으로 구분!

 

apiVersion: v2  // "apiVersion" : "v2"

kind: Pod

metadata:

   name: new-pod-app1

   labels:

      app: app1

spec:

   containers:  // "container" : [ { "name" : "new-container", "image" : "base1", "ports" : [ { "containerPort" : 8080 } ] } ]

   - name: new-contanier

      image: base1

      ports:

      - containerPort: 8080