ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 44BITS (6)쿠버네티스 아키텍처 2, 각종 오브젝트, 최종구성, yaml
    k8s 2022. 2. 8. 19:42

    ===

    https://youtu.be/-gIyfII5eak

    ===

    지금까지 쿠버네티스가 내부적으로 어떻게 동작하는지 봄

    계속 체크를 하는데 뭘 체크하는지를 보겠음

     

    ===

    쿠버네티스는 컨테이너를 직접 관리하지 않고 Pod이라는걸로 감싸서 관리

    컨테이너를 배포하는게 아니라 pod를 배포

     

    pod의 특징으로 각 pod마다 고유한 IP를 부여받음

    이 IP를 통해 내부적으로 통신을 할 수도 있고 

     

    중요한 특징으로 이 pod안에 컨테이너가 하나만 존재하는게 아님

    보통 하나가 존재하긴 하지만 두개가 존재할 수 있다

    왼쪽은 로그를 수집하는 컨테이너 까지 총 두개 : host에 있는 폴더를 공유할 수 있다

    ->컨테이너에서 로그를 생성하는 폴더를 로그수집하는 컨테이너와 같이 읽을 수가 있음

     

    특정 컨테이너가 캐시가 필요하다, 모든 컨테이너마다 캐시를 붙이고 싶다 했을 때, 하나의 pod에 컨테이너와 캐시 두개를 띄워놓고 port를 localhost로 공유할 수가 있다

     

    ===

    pod은 컨테이너를 관리하는 단위였다면,

    replicaset은 몇개의 팟을 관리할지를 결정함.

    3에서 4로 바꾸게 되면 ReplicaSet이 원하는게 4개인데 지금 3개만 떠있네 그럼 pod template를 보고 하나를 더 띄워줌

    5개가되면 4개로 줄이고 3개가 되면 4개로 늘리고

     

    ===

    이 ReplicaSet을 또 감싼 Deployment, 배포버전을 관리하는 오브젝트가 있다

    현재 Deployment가 버전1인데, 버전2로 바꾸고 싶을 때 무중단으로 배포를 해야하는데,

    그때 ReplicaSet을 사용함.

    버전2로 올리면 순간적으로 replicaset을 2개로 만듦

    하나 더 만들어서 2개 1개로 나눔

    2개는 v1인 상태, 하나는 v2로 올라간 상태 여기서 개수를 다시 바꿔줌

    v1은 1개로 설정을 하니 하나가 죽고, v2는 2개로 설정을 하니 늘어남

    또 바꿔주면, 겉에서 봤을 땐 자연스럽게 업데이트가 된 것. pod가 3개는 똑같지만, 순간적으로 개수가 4개됐다 그럴순 있겠지만 

     

    deployment라는건 내부적으로 관리하는 알고리즘을 쓰는게 아니라, replicaset자체를 활용해서 버전관리를 한다.

     

    ===

    쿠버네티스에서 기본적으로 제공하는 Workload 방식, 쿠버네티스는 replicaset, deployment말고도 다양한 방식을 제공하는데

     

    DAEMON SET은 모든 노드에 꼭 하나씩만 떠있길 원하는 POD을 만들고 싶을 때 : 로그수집, 모니터링 등에 적합

    STATEFUL SETS : 순서대로 POD을 실행하고 싶거나 같은 볼륨을 계속 재활용하고싶다 할 때 씀

    JOB : 한번 실행하고 죽는 

     

    ===

    네트워크도 별도의 오브젝트로 관리한다

    서비스라는게 있고,

    서비스 중에서도 ClusterIP라는건 pod3개를 로드밸런서하는 별도의 서비스다.

    ClusterIP로 요청을 보내면 자동으로 저 세개중에 하나로 요청이 감

     

    이렇게 하는 이유는

    ReplicaSet, Deployment를 보면 pod이 업데이트될 때 IP를 유지한상태로 업데이트되는게 아니라, pod이죽고, 새로운 pod이 뜨는 그런 개념이라, IP가 언제든지 사라졌다가 바뀌거나하는게 자연스럽다

    그래서 요청을 보낼 때 pod으로 바로 보내는게 아니라 

     

    서비스라는걸 먼저 만들고, 그 서비스의 IP는 고정, 거기에 요청을 보내면 뒤에 pod은 늘든 줄든, IP가 바뀌건 상관없이 정상적으로 원하는 pod에 요청을 보낼 수 있기 때문에 앞에 ClusterIP타입의 서비스를 붙임

     

    ===

    내부적으로 이렇게 통신,

     

    웹서버에서 redis로 통신을 하고싶다?

    그럼 내부 DNS에서 redis라는 도메인이 생김.

    그래서 redis로 요청을 보내면 저 ClusterIP로 요청을 보내고, 그 요청이 다시 안쪽에 있는 pod으로 요청이 감

     

    그리고 웹에서 mysql로 요청을 보내면 1차적으로 ClusterIP로 요청이 간 다음에, 그 요청이 다시 또 mysql pod으로 

     

    ===

    여기서 애매한 것, ClusterIP는 내부에서만 통신할 수 있다, 외부 브라우저로는 접근을 할 수가 없어

     

    외부에서 접근하기 위해 NodePort라는 개념이 생김

    노드에 포트가 생기고, 거기로 접속을 하면 그 요청이 다시 ClusterIP로 가고 그 요청이 다시 또 pod으로 가는 구조

    노드가 2개가 있고 노트포트를 생성하게 되면 1번노드에도 생기고 2번노드에도 생김

    그래서 1번노드에 요청을 보내도, 원했던 ClusterIP로 요청이가고, 2번노드로 요청을 보내도, 그 안에서 자동으로 저 ClusterIP를 찾아가 줌

     

    1번으로 요청을 보내나 2번으로 요청을 보내나 상관이 없는 것

     

    노드가 10개면 10개중에 아무데나 보내도 내부에 있는 네트워크를 잘 찾아감 그런 기능

     

    ===

    또 문제가 뭐냐면

    도메인을 1번 노드를 연결해놨는데, 갑자기 1번 노드가 죽으면?서버 자체가 사라질 수가 있다.

    그럼 2번 노드로 붙어야되는데 설정을 1번노드로 해놨기 때문에 순간적으로 접속이 안됨 그래서 이걸 방지하기 위해

    앞에 로드밸런서를 별도로 둠

    사용자는 로드밸런서로 요청을 보내고, 그 요청이 다시 NodePort로 가고 그 NodePort가 다시 ClusterIP로 가고 그 ClusterIP가 다시 pod으로 가는 구조

     

    ===

    지금까진 IP 포트로만 접속을 하는거라고 하면

    Ingress는

    도메인이름, 도메인 뒤에 붙는 패스에 따라 내부에 있는 ClusterIP에 연결을 할 수가 있다

    저런 세개의 요청이 들어왔을때, 세개 전부 노드포트를 만들거나 전부다 로드밸런서를 만들면 자원이 낭비가 된다

    그 대신에 ingress하나로 만들고 그 ingress가 내부적으로 서비스를 분기칠 수가 있다

     

    ingress는 새로 만든다기보단 기존에 있던 Nginx, HAProxy, ALB... 를 재활용해서 쿠버네티스에 맞게 포장을 해서 사용한다

     

    ===

    그래서 일반적인 구성은

    pod을 띄우는 경우는 잘 없다

    deployment를 생성하면,

    deployment가 replicaset을 자동으로 생성하고,

    replicaset이 자동으로 pod을 생성하는 구조

     

    이걸 외부에 노출해야되니까 서비스를 붙임

    그리고 그걸 Ingress를 붙여.  Ingress를 붙이면 NodePort랑 로드밸런서가 자동으로 따라옴

     

    실제 클라이언트는 저 도메인으로 접속을 하게되면 저 로드밸런서를 거쳐서 노드포트를 거쳐서 클러스터IP를 거쳐서 pod으로 연결된다.

     

    ===

    그 외에도 다양한 오브젝트가 있다.

    쿠버네티스가 어려운게 추상화를 많이 해놨고, 알아야할 오브젝트들이 많다

    Volume : 스토리지에 대한 오브젝트

    Namespace : 내부적으로 리소스를 이걸로 구분할 수가 있다

    ConfigMap/Secret : 설정같은걸 이걸로

    권한을 위해 ServiceAccount, Role, ClusterRole

     

    이것말고도 많지만, 원리를 알면 하나씩 하나씩 이해하면 어렵진 않다

     

    ===

    어떻게 구성 돼 있고, 어떻게 설계가 돼 있는지

    어떤 오브젝트를 사용하는지

    를 봤다

     

    이제 실제로 API를 어떻게 호출하는지 알아보기

     

    ===

    pod이라는 오브젝트를 띄우고싶다, 생성하고 싶다

    이런식으로 생성함.

    yaml이라는 포맷 :  키, 밸류, 띄어쓰기를 사용해서 표현을 하는 방식

     

    spec은 containers인데 여러개 들어갈 수 있으니 그 중에 하나가 이름은 저거고 이미지는 저거고

     

    이렇게 명세를 설명하면

    처음에 설명했던 API Server가 이 명세를 보고 etcd에 정보를 저장함 + 각 Controller들이 동작하게됨

     

    ===

    replicaset을 만들고 싶으면

    pod이랑 비슷한데, 조금더 정보가 추가가되는것

    apiVersion, kind, metadata는 공통으로 쓰고

    종류마다 spec은 아예 다름

     

    ===

    ArgoCD라는 커스텀 리소스인데, 형식 자체는 다 동일하다 라는걸 보여주기 위해 넣음

    spec은 ArgoCD만의 spec을 작성

     

    ===

    정리

    apiVersion은 굉장히 종류가 많다. v1, 베타원, 네트워킹의 버전 원...

     

    kind

     

    metadata는 보통 이름을 주거나 네임스페이스, 라벨을 설정할 수 있다

     

    spec은 어떤 종류냐에 따라 다양, 저기 저 사이트가서 보면서 설정하면 됨

     

    status는 시스템에서 해당하는 오브젝트의 현재상태를 보기위해 read-only로 관리되고 있는 항목

    내부 컨트롤러가 현재 상태가 어떻지?라고 볼때 저 status를 확인함

     

    ===

    그러므로

    API를 호출한다는건

    desired state라는 상태가 있는데, 그걸 어떤 오브젝트를 쓸지는 몰라.

    deployment, service, ingress...를 써야 하나의 온전한 웹서비스가 탄생함

    그 object를 잘 모아서 정의를 함

    이 deployment는 배포되는 개수가 몇개고 어떤 이미지를 쓸거고 

    service는 어떤 deployment 어떤 pod 을 바라볼지 정의를 하고

    ingress는 어떤 도메인으로 들어왔을 때 어떤 서비스를 바라볼지 정의를 하는 것

     

    원하는 상태를 다양한 오브젝트로 정의를 한 다음에 API Server에 yaml형식으로 전달하면 쿠버네티스가 알아서 오브젝트를 원하는 상태로 뿅 띄워줌

     

    ===

    replicaset을 생성하는 샘플

    API Server요청

    Controller가 체크 : 감시 + 요청 하는애구나

    Scheduler가 할당 : 감시 + 할당 하는애구나

    Kubelet이 다시 받아서 띄우고...

     

    이런게 쿠버네티스의 과정, 사실 이게 전부

     

    각 오브젝트가 뭔지, 어떤 스펙이 있는지, 띄우면 어떤 일이 벌어지는지

    만 이해하면 쿠버네티스를 사용할 수 있다

     

    ===

    쿠버네티스는 큰 컨테이너를 관리하기 좋은 시스템

    저거 뒷좌석에 놔도 되는데 저렇게 하는건 아닌지

    우리 시스템이 쿠버네티스에 적절할까는 한번 생각해볼 필요가 있다

Designed by Tistory.