[쿠버네티스] 1. 개념

rin·2021년 2월 10일
1
post-thumbnail
post-custom-banner

https://kubernetes.io/ko/docs/home/

개요

쿠버네티스란 무엇인가?

컨테이너화된 워크로드와 서비스를 관리하기 위한 이식성이 있고, 확장가능한 오픈소스 플랫폼

🤔 워크로드란? 비즈니스 가치를 창출하는 리소스 및 코드 모음

쿠버네티스가 유용해질 때 까지의 시장 변화를 알아보자.

  1. 전통적 배포 시대
    어플리케이션을 물리 서버에서 실행하였기에 리소스 할당 시 문제가 발생할 수 밖에 없었다.
    여러 어플리케이션이 하나의 물리 서버에서 실행되면 할당에 따라 성능 저하가 발생할 수 있었으며, 서로 다른 물리 서버를 사용하면 리소스 활용이 충분하지 못한 상황이 되었다.
  2. 가상화된 배포 시대
    이런 문제를 해결하기 위해 "물리 서버" 대신 "가상 서버"가 도입되었다.
    단일 물리 서버의 CPU에서 여러 가상 시스템 (VM)을 실행 시킨다. 기본적으로 VM간 어플리케이션이 격리되어 다른 어플리케이션의 정보를 자유롭게 액세스 할 수 없어 일정 수준의 보안 효과를 가져올 수 있다.
    각 VM은 가상화된 하드웨어 상에서 자체 운영체제를 포함하는 모든 구성 요소를 실행하는 하나의 완전한 머신이다.
  3. 컨테이너 개발 시대
    컨테이너는 VM과 유사하지만 어플리케이션 간에 운영체제를 공유한다. 그러므로 컨테이너는 가볍다고 여겨진다.

쿠버네티스는 전통적인 (모든 것이 포함된) PaaS(Platform as a Service)가 아니다. 이는 컨테이너 수준에서 운영되며 (PaaS가 일반적으로 제공하는) 배포, 스케일링, 로드 밸런싱과 같은 기능을 제공한다.

Monolithic이 아니므로 기본 솔루션은 선택적으로 추가/제거 할 수 있다. 즉, 사용자의 선택권과 유연성을 지켜준다.

쿠버네티스가 왜 필요하고 무엇을 할 수 있나

어플리케이션이 실행되고 있는 환경을 지속적으로 모니터링하고 문제 상황이 발생하면 (서버가 다운되는 등의) 이를 시스템이 자동으로 처리해준다면 참 편리할 것이다!

그리고 이를 가능하게 해주는 것이 쿠버네티스이다.

쿠버네티스는 분산 시스템을 탄력적으로 실행하기 위한 프레임 워크를 제공한다.

쿠버네티스가 제공하는 구체적인 기능은 다음과 같다.

  • 서비스 디스커버리(클라이언트나 API 게이트웨이가 호출할 서비스를 찾는 매커니즘)와 로드 밸런싱
    • DNS / 자체 IP 주소를 이용해 컨테이너를 노출한다.
    • 트레픽 과부하 시 네트워크 트래픽을 로드밸런싱함으로써 안정적으로 배포 할 수 있도록 한다.
  • 스토리지 오케스트레이션
    • 로컬 저장소, 공용 클라우드 공급자 등 원하는 저장 시스템을 자동으로 탑재 할 수 있다.
  • 자동화된 롤아웃과 롤백
    • 쿠버네티스를 사용해 배포된 컨테이너의 원하는 상태를 서술할 수 있으며 현재 상태를 원하는 상태로 설정한 속도에 따라 변경할 수 있다.
  • 자동화된 빈 패킹(bin packing)
    • 각 컨테이너가 필요로 하는 CPU와 메모리(RAM)를 지시한다.
    • 쿠버네티스는 컨테이너를 노드에 맞추어서 리소스를 가장 잘 사용할 수 있도록 해준다.
  • 자동화된 복구(self-healing)
    • 실패한 컨테이너의 재시작, 컨테이너 교체, 미응답 컨테이너 종료 등 클라이언트에게 과정을 노출하지 않고 자동으로 실행한다.
  • 시크릿과 구성 관리
    • 암호, OAuth 토큰, SSH key와 같은 중요한 정보를 저장, 관리 할 수 있다.
    • 컨테이너 이미지 재구성 없이 시크릿을 노출하지 않고 시크릿 및 어플리케이션 구성을 배포 및 업데이트 한다.

컴포넌트

❗️ 쿠버네티스 클러스터란 컨테이너화된 어플리케이션을 실행하는 "노드"라는 워커 머신의 집합이다. (모든 클러스트는 최소 한 개의 워커 노드를 가진다.)

컨테이너는 파드 내에 배치되고 노드에서 실행되는데, 이 때 노드는 클러스터에 따라 가상 또는 물리 머신 일 수 있다.

  • 파드(Pod) : 쿠버네티스에서 생성하고 관리할 수 있는 배포 가능한 가장 작은 컴퓨팅 단위. 하나 이상의 컨테이너 그룹을 의미한다.

컨트롤 플레인 컴포넌트

컨트롤 플레인은 워커 노드와 클러스터 내 파드를 관리한다.

  • 클러스터에 관한 전반적인 결정(스케줄링 등)을 수행
  • 클러스터 이벤트를 감지하고 반응

컨트롤 플레인을 구성하는 컴포넌트는 다음과 같다

  • kube-apiserver : 쿠버네티스 컨트롤 플레인의 프론트 엔드
  • etcd : 모든 클러스터 데이터를 담는 쿠버네티스 뒷단의 저장소. key-value 스토리지.
  • kube-scheduler : 아직 노드가 배정되지 않은 새로 생성된 파드를 감지한다. 실행할 노드를 선택한다.
  • kube-controller-manager : 컨트롤러를 구동하는 마스터 상의 컴포넌트.
    이 컨트롤러는 다음을 포함한다.
    • 노드 컨트롤러 - 노드가 다운되었을 때 통지와 대응에 관한 책임을 가진다.
    • 레플리케이션 컨트롤러 - 시스템의 모든 레플리케이션 컨트롤러 오브젝트에 대해 알맞은 수의 파드들을 유지시켜주는 책임을 가진다.
    • 엔드포인트 컨트롤러 - 엔드포인트 오브젝트를 채운다. (서비스와 파드를 연결시킨다.)
    • 서비스 어카운트 & 토큰 컨트롤러 - 새로운 네임스페이스에 대한 기본 계정과 API 접근 토큰을 생성한다.
  • cloud-controller-manager : 클러스터를 클라우드 공급자의 API에 연결하고 해당 클라우드 플랫폼과 상호 작용하는 컴포넌트를 클러스터와 상호 작용하는 컴포넌트와 분리할 수 있다.

쿠버네티스 API

쿠버네티스 컨트롤 플레인의 핵심은 API 서버이다.

API 서버는 최종 사용자, 클러스터의 다른 부분, 외부 컴포넌트가 서로 통신할 수 있도록 HTTP API를 제공한다.

  • API 서버를 사용해 쿠버네티스의 API 오브젝트(파드, 네임스터이스, 컨피그맵, 이벤트 등)를 질의(Query)하고 조작할 수 있다.
  • 대부분의 작업은 kubectl 커맨드 라인 인터페이스 또는 API를 사용하는 kubeadm과 같은 다른 커맨드 라인 도구를 통해 수행 할 수 있다.
    • REST 호출을 통한 API 직접 접근 또한 가능하다.
  • 이를 사용해 어플리케이션을 작성하는 경우, 클라이언트 라이브러리 중 하나를 사용하는 것이 좋다.

노드 컴포넌트

노드 컴포넌트는 동작 중인 파드를 유지시키고 쿠버네티스 런타임 환경을 제공하며, 모든 노드 상에서 동작한다.

  • kubelet : 파드에서 컨테이너가 확실하게 동작하도록 관리한다.
  • kube-proxy : 클러스터의 각 노드에서 실행되는 네트워크 프록시로써 노드의 네트워크 규칙을 유지 관리한다.
    즉, 내부 네트워크 세션이나 클러스터 바깥에서 피드로 네트워크 통신을 가능하게 해준다.
  • 컨테이너 런타임 : 컨테이너 실행을 담당하는 소프트웨어

애드온

애드온은 쿠버네티스 리소스(데몬셋, 디플로이먼트 등)를 이용해 클러스터 기능을 구현한다.

쿠버네티스 오브젝트로 작업하기

쿠버네티스 오브젝트 이해하기

쿠버네티스 오브젝트란 쿠버네티스 시스템에서 영속성을 가지는 오브젝트로써 클러스터의 상태를 나타내기 위해 이용한다.

  • 컨테이너화된 어플리케이션 중 어떤 것이 동작 중이며, 어느 노드에서 동작 중인지
  • 해당 어플리케이션이 이용 가능한 리소스
  • 해당 어플리케이션이 어떻게 재구동 정책, 업그레이드, 내고장성과 같은 것에 동작해야 하는지에 대한 정책

오브젝트를 생성함으로써, 클러스터의 워크로드를 어떤 형태로 보이고자 하는지 쿠버네티스 시스템에 효과적으로 전달 할 수 있다. 이것이 바로 의도한 상태가 되는 것이다.

오브젝트 명세(spec)와 상태(status)

쿠버네티스 오브젝트는 오브젝트의 구성을 결정해주는 두 개의 중첩된 오브젝트 필드를 포함하는데,

  • 오브젝트 명세 (spec) - 오브젝트 생성 시 리소스에 원하는 특징(의도한 상태)에 대한 설명을 제공
  • 오브젝트 상태 (status) - 제공되고 업데이트된 오브젝트의 현재 상태

이다.

❗️ 쿠버네티스 컨트롤 플레인은 모든 오브젝트의 실제 상태를 사용자가 의도한 상태와 일치시키기 위해 끊임없이 능동적으로 관리한다.

쿠버네티스 오브젝트 기술하기

쿠버네티스에서 오브젝트를 생성할 때는

  • (이름과 같은) 기본정보
  • 의도한 상태 (spec)

을 제시해줘야만 한다.

대부분의 경우 정보를 .yaml 파일로 kubectl에 제공하며 kubectl은 API 요청이 이루어질 때, JSON 형식으로 정보를 변환시켜 준다.

Example :

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
  • apiVersion : 이 오브젝트를 생성하기 위해 사용하고 있는 쿠버네티스 API 버전이 어떤 것인지
  • kind : 어떤 종류의 오브젝트를 생성하고자 하는지
  • metadata : name, UID, 선택적인 namaspace를 포함. 오브젝트를 유일하게 구분지어 줄 데이터
  • spec : 오브젝트에 대해 의도한 상태 (정확한 포맷은 쿠버네티스 오브젝트마다 다르며 중첩된 필드를 포함한다.)

오브젝트 이름과 ID

  • 해당 유형 리소스에 대해 고유한 이름
  • 전체 클러스터에 걸친 고유한 UID

예를 들어, 이름이 myapp-1234인 파드는 동일한 네임스페이스에서 하나만 존재할 수 있지만, 이름이 동일한 myapp-1234인 디플로이먼트는 각각 존재할 수 있다.

✔️ 이름
/api/v1/pods/some-name과 같이, 리소스 URL에서 오브젝트를 가리키는 클라이언트 제공 문자열.

✔️ UID
오브젝트를 중복없이 식별하기 위해 쿠버네티스 시스템이 생성하는 문자열.
쿠버네티스 클러스터가 구동되는 전체 시간에 걸쳐 생성되는 모든 오브젝트는 기록상 유사한 오브젝트의 출현을 서로 구분하기 위해 고유한 UID를 갖는다.

네임스페이스

쿠버네티스는 동일한 물리 클러스터를 기반으로 하는 여러 가상 클러스터를 지원하는데, 이런 가상 클러스터를 네임스페이스라고 한다.

여러 개의 네임스페이스를 사용하는 경우

네임스페이스는

  • 이름의 범위를 제공한다.
  • 서로 중첩될 수 없으며
  • 각 쿠버네티스 리소스는 하나의 네임스페이스에만 있을 수 있다.
  • 클러스터 자원을 (리소스 쿼터를 통해) 여러 사용자 사이에서 나누는 방법

❗️ NOTE 리소스쿼터
여러 사용자나 팀이 정해진 수의 노드로 클러스터를 공유할 때, 한 팀이 공정하게 분배된 리소스 이상의 리소스를 사용할 우려가 있다.
리소스 쿼터는 관리자가 이러한 문제를 해결하기 위해 제공되는 도구이다.
ref. https://kubernetes.io/ko/docs/concepts/policy/resource-quotas/

단, 모든 오브젝트가 네임스페이스에 속하는 것은 아니다.
대부분의 쿠버네티스 리소스는 네임스페이스에 속하나, 네임스페이스 리소스 자체는 이에 속하지 않는다. 노드나 persistence volume과 같은 저수준 리소스 또한 네임스페이스에 속하지 않는다.

레이블과 셀렉터

레이블은 파드와 같은 오브젝트에 첨부된 키값 쌍으로써 오브젝트의 특성을 식별하는데 사용된다. (코어 시스템에 직접적인 의미는 없다.)

레이블을 이용해 느슨한 결합도로 조직 구조와 시스템 오브젝트를 매핑할 수 있으며, 클라이언트에 매핑 정보를 저장할 필요가 없다.

레이블은 오브젝트 생성 시 or 생성 이후에 붙이거나 수정이 가능하며 오브젝트마다 키-값으로 레이블을 정의할 수 있는데, 오브젝트의 키는 고유한 값이어야한다.

Example :

"metadata": {
  "labels": {
    "key1" : "value1",
    "key2" : "value2"
  }
}

레이블 셀렉터

이름이나 UID와 다르게 레이블은 고유하지 않다. 일반적으로 많은 오브젝트는 같은 레이블을 가질 수 있다.

그럼 레이블을 통한 오브젝트 구분은 불가능한 것일까? 🤔 레이블 셀렉터를 사용하면 클라이언트와 사용자가 오브젝트를 식별할 수 있다.

API는 현재 두 종류의 셀렉터-일치성 기준, 집합성 기준-를 지원하는데, 이는 쉼표로 구분된 다양한 요구사항에 따라 만들 수 있다. (&& 연산자와 동일한 역할)

✔️ 일치성 기준 요건 : 일치성 기준 또는 불일치 기준의 요구사항으로 레이블의 키와 값의 필터링을 허용한다.

  • 일치하는 오브젝트는 추가 레이블을 가질 수 있지만 레이블의 명시된 제약 조건을 모두 만족해야한다.
  • =, ==, != 3가지 연산자만 허용한다.

Example :

1) environment = production
2) tier != frontend

1) 키가 environment 이고, 값이 production인 레이블을 포함하는 모든 리소스를 선택한다.
2) 키가 tier 이지만 값이 frontend아닌 레이블을 포함하는 모든 리소스를 선택한다. (공백 포함)

쉼표를 통해 한 문장으로 environment = production, tier != frontend 로 표현하면 두 조건을 한꺼번에 필터링 할 수 있다.

✔️ 집합성 기준 요건 : 집합성 기준 레이블 요건에 따라 값 집합을 키로 필터링 할 수 있다.

  • in, notin, exists(키 식별자만 해당) 3가지 연산자만 허용한다.

Example :

1) environment in (production, qa)
2) tier notin (frontend, backend)
3) partition
4) !partition

1) 키가 environment이고 값이 production 또는 qa인 모든 리소스를 선택한다.
2) 키가 tier이고 값이 frontend backend가 아닌 경우의 리소스를 선택한다. (공백 포함)
3) 값에 상관없이 키가 partition 인 레이블을 포함하는 모든 리소스를 선택한다.
4) 값에 상관없이 키가 partition 인 레이블을 포함하지 않는 모든 리소스를 선택한다.

어노테이션

임의의 비식별 메타데이터를 오브젝트에 첨부할 수 있으며, 도구 및 라이브라이와 같은 클라이언트에서 이 메타데이터를 검색할 수 있다.

오브젝트에 메타데이터 첨부

"metadata": {
  "annotations": {
    "key1" : "value1",
    "key2" : "value2"
  }
}

레이블을 사용해 오브젝트를 선택하고, 특정 조건을 만족하는 오브젝트 컬렉션을 찾을 수 있는 것과 달리 어노테이션은 오브젝트를 식별하고 선택하는데 사용되지 않는다. 따라서 어노테이션의 메타데이터는 느슨한 규약을 가지고 있다.

(단, 레이블과 같이 키-값 맵이다.)

필드 셀렉터

필드 셀렉터는 한 개 이상의 리소스 필드 값에 따라 쿠버네티스 리소스를 선택하기 위해 사용된다.

Example :

  • metadata.name=my-service
  • metadata.namespace!=default
  • status.phase=Pending

❗️ NOTE
필드 셀렉터는 본질적으로 리소스 필터이다. 기본적으로 적용되는 셀렉터나 필드는 없으며, 이는 명시된 종류의 모든 리소스가 선택됨을 암시한다.

예를 들어 kubectl get podskubectl get pods --field-selector ""와 동일하다.

권장 레이블

https://kubernetes.io/ko/docs/concepts/overview/working-with-objects/common-labels/

쿠버네티스는 플랫폼 서비스(PaaS)가 아니며 어플리케이션에 대해 공식적인 개념이 없거나 강요하지 않는다. 대신 어플리케이션은 비공식적이며 메타데이터로 설명된다. 어플리케이션에 포함된 정의는 유연하다.

메타데이터들은 권장되는 레이블이다. 어플리케이션을 보다 쉽게 관리할 수 있지만 코어 도구에는 사실상 필요하지 않은 요소이다.

profile
🌱 😈💻 🌱
post-custom-banner

0개의 댓글