[대세는쿠버네티스] 2. 기본 오브젝트

@BeforeAll

쿠버네티스 오브젝트

쿠버네티스 오브젝트의 이해

쿠버네티스 오브젝트

  • 쿠버네티스 시스템에서 영속성을 가지는 오브젝트
  • 쿠버네티스는 클러스터 상태를 나타내기 위해 이 오브젝트를 이용함
  • detail
    • 어떤 컨테이너화된 애플리케이션이 동작 중인지 (그리고 어느 노드에서 동작 중인지)
    • 그 애플리케이션이 이용할 수 있는 리소스
    • 그 애플리케이션이 어떻게 재구동 정책, 업그레이드, 그리고 내고장성과 같은 것에 동작해야 하는지에 대한 정책
  • 하나의 “의도를 담은 레코드”
    • 오브젝트를 생성하면/
    • 쿠버네티스 시스템은 그 오브젝트 생성을 보장하기 위해

Pod - Container, Label, NodeSchedule

파드

  • 쿠버네티스에서 어플리케이션 디플로이의 단위, 적어도 하나 이상의 컨테이너로 이루어짐
  • 쿠버네티스에서는 여러 개의 컨테이너를 모아서 파드(pod)에 담을 수 있음
  • 이 구조가 완두콩이 콩을 담고 있는 모양과 비슷해서 ‘꼬투리’를 의미하는 영어 단어인 Pod이라는 이름이 되었다
  • 파드 단위로 컨테이너의 조작(생성, 시작, 정지 삭제)을 한다 → 쿠버네티스의 최소 실행 단위
  • 파드는 하나의 목적을 위해서 생성된 컨테이너를 부품처럼 조합가능하도록 설계되었다
    1. 파드 내부의 컨테이너들은 파드의 IP와 포트번호를 공유한다
    2. 파드 내부의 컨테이너들은 반드시 동일한 노드에 할당되며 동일한 생명 주기를 갖는다
    3. 파드 내부의 컨테이너들은 localhost로 서로 통신이 가능하다
    4. 파드 내부의 컨테이너들은 System V 프로세스 통신이나 POSIX 공유메모리를 사용해 서로 통신 가능
    5. 파드 내부의 컨테이너들은 파드 볼륨을 마운트해서 파일 시스템을 공유 가능
    • 위의 기능은 같은 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가 계속 바뀜 - 클라이언트의 요청을 전달할 서비스가 필요

  • 서비스 디스커버리를 수행하는 도메인 이름 기반의 엔드포인트 제공

  • 동작

    1. 서비스는 로드발란서의 역할을 가지며, 클라이언트 요청을 받기 위한 대표 ip 주소를 획득
    2. 서비스가 만들어질 때 서비스 이름이 내부 DNS 등록된다
      따라서 클라이언트는 서비스 이름만으로 서비스의 ip를 획득할 수 있다
    3. 서비스는 selector에 지정된 label과 일치하는 파드중 하나에게 요청을 전달한다
    4. 파드는 기동될때 자신의 정보(label, ip등)를 마스터 노드의 etcd에 등록해놓았다
    5. 따라서 해당 프로세스 중에 selector의 라벨에 일치하는 파드를 etcd에 조회해서 전송할 파드의 ip를 취득한다
    6. 서비스가 만들어지고 나서 생성 파드의 컨테이너에는 서비스 정보가 담긴 환경변수가 자동으로 설정된다

서비스의 종류

  1. ClusterIP
  • 서비스 리소스의 가장 기본이 되는 타입, 타입 지정 없으면 기본값 선택

  • 쿠버네티스 클러스터 내부 IP에 서비스가 공개

  • 클러스터 내부에서만 접근 가능하며 외부에서 접근 불가

  • 존재이유

    1. 많은 경우 제한된 엔드 포인트 외에는 직접 트래픽을 전달 받지 않음(네트워크 보안 및 관리)
      대신 외부로 열린 엔드포인트로부터 트래픽을 전달받아 서비스를 제공
    2. 더 확장된 쿠버네티스 네트워킹을 위한 기본 빌딩 블럭
      ClusterIP를 기반으로 더 복잡한 네트워킹 수행 가능
  • 사용처 : 인가된 사용자(운영자), 내부 Dashboard, pod서비스상태 디버깅

  1. NodePort
  • ClusterIP를 만드는 점은 1번과 동일
  • 각 노드에서 서비스 포트로 접속하기 위한 글로벌 포트를 개방하는 점이 차이
  • 모든 Node에 똑같은 포트가 할당됨
    • k8s는 클러스터 시스템 → 특정 노드 가 아니라 모든 노드에 동일하게 적용됨
      • kube-proxy
        • 리눅스 커널의 netfilter를 이용해서 커널 레벨에서 특정 트래픽을
          중간에 가로채서 다른 곳으로 라우팅 해주는 역할을 수행
        • 이를 통해 Pod이 위치한 노드 뿐 아니라 모든 노드에서
          동일한 NodePort로 원하는 서비스에 접근 할 수 있게 제공
          (externalTrafficPolicy: Cluster인 경우)
  • 물리적인 로컬호스트의 ip를 통해서 pod 접근 가능
  • 사용처 : 클러스터 밖에 있지만 내부망 연결시 사용 ,일시적 데모
    why? 대부분 host ip는 보안적으로 내부망에서만 접근 가능하게 네트워크가 구성되어 있음
  1. LoadBalancer
  • 역시 NodePort를 만드는 점은 2번과 동일하다
    • 다만 이때 요청을 받은 노드 내에 있는 파드로만 전송하도록 설정할 수 있다((externalTrafficPolicy: local인 경우))
    • 노드들 앞에 LB가 있다면 매우 유용한 설정이다
  • 이후 외부ip를 가진 Loadbalancer가 각각node의 nodeport를 가르키게 됨
  • 퍼블릭 클라우드 플랫폼의 LB 지원 - GCP의 Cloud Load Balancing, AWS의 Elastic Load Balancing을 지원한다
  • 기본적으로는 사용이 안되며 로컬에서 사용하려면 metalLB등을 사용해야함
  • LB 사용 이유
    1. 보안성
    • 호스트 서버의 NodePort 대역(30000~23767)을 외부에 노출할 필요가 없음
    • LB만 외부 네트워크에 위치해서 endpoint 제공 - 네트워크 보안성 증가
    1. 디스커버리 편의성
    • 사용자가 master,worker를 직접 알 필요 없이 LB의 도메인이나 ip로 요청 가능
    • 실무에서는 Pod처럼 노드들도 생성및 삭제가 잦음 - 그떄마다 노드 ip 추적은 비효율적
    • ClusterIP 타입 서비스가 Pod레벨의 안정적 서비스 엔드포인트를 제공한다면
      LB 타입 서비스는 노드 레벨에서의 안정적인 서비스 엔드포인트를 제공한다
  1. 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

    • 사용 이유
    1. 위의 단점 : pod이 다른 노드에서 재생성시 문제
    2. 볼륨과 어플리케이션의 정의가 강하게 연관되서 분리할 수 없는 상황
    • 예) 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 에러 발생, 강제 중단

리미트레인지(LimitRange)

  • 각각의 pod의 최대크기 제한
  • 특정 pod 크기가 설정한 값보다 크면 들어올 수 없음

이해가 안되서 정리

리소스 quota 설정은 무엇을 위한 quota인가

  • Resource Limits, Resource Requests : Pod의 QOS에 영향을 준다

    • 어플리케이션 리소스 요구량 - 개발자 책임
    • request, limnit를 맞추면 우선 순위가 높은 Qos Guaranteed를 구할 수 있음
    • 즉 어플리케이션을 위한 제약 - 부정적이 아니라 긍정적으로 활용해야함
    • 관리자의 입장에서는 검토, 리소스 부족시 증설도 검토 필요
  • LimitRange, ResourceQuota : 클러스터를 위한 제약

    • 클러스터 전체에 영향을 주는 리소스 소비를 억제
    • 클러스터 이용자 전원을 보호하기 위한 제약
  • 이상적?

    • 정답은 없음, 현실적인 대안은?
    1. 우선 가이드라인을 만들고 프로젝트의 희망사항을 들으면서 상한 변경 하기
    2. 프로젝트 개별적으로 네임스페이스 상한을 완화 하기

Related POST

공유하기