쿠버네티스

컨테이너 오케스트레이션

  • 여러 개의 컨테이너를 관리하는 애플리케이션이나 프레임워크

장점

  • 고가용성: 여러 개의 애플리케이션 인스턴스를 실행해서 실패한 애플리케이션의 인스턴스를 자동으로 새로운 인스턴스로 교체 가능
  • 규모 확장성

오케스트레이션 도구

  • Docker Swarm: 도커 컨테이너 엔진을 개발한 팀에서 개발을 했는데 설정이나 실행은 쉽지만 유연성이 부족
  • Apache Methos
    • 데이터 센터와 클라우드 환경 모두에서 컴퓨팅, 메모리 및 스토리지를 관리하는 Low Level 오케스트레이션 도구
    • 기본적으로 컨테이너를 관리하지는 않지만 메소스 위에서 실행되는 마라톤은 완전하게 확장된 컨테이너 오케스트레이션 도구가 되고 쿠버네티스도 메소스 위에서 실행 가능
  • 쿠버네티스
    • k8s라는 이름으로도 불리는 구글이 개발한 오픈소스 컨테이너 오케스트레이션 도구
    • 오픈소스가 된 후에는 엔터프라이즈 환경에서 컨테이너를 실행하고 오케스트레이션 하는 사실상의 표준
    • 매우 큰 커뮤니티를 가진 성숙도 높은 제품
    • 아파치 메소스보다 조작이 간단하고 도커 스웜보다는 유연성이 뛰어남

쿠버네티스 아키텍쳐

노드 유형

  • 노드는 VM, 베어메탈 호스트, 라즈베리 파이 등 다양
    • Master Node: Control Plane Application 실행을 담당
    • Worker Node: 쿠버네티스에 배포되는 애플리케이션 실행을 담당

Control Plane

  • 마스터 노드에서 실행되는 애플리케이션과 서비스의 집합
  • 고도로 특화된 서비스
    • kube-apiserver: 쿠버네티스에 전송된 커맨드를 처리
    • kube-scheduler: 워크 로드를 배치할 노드를 결정하며 이는 상당히 복잡한 과정일 때도 있음
    • kube-controller-manager: 클러스터와 클러스터에서 실행 중인 애플리케이션이 원하는 설정대로 구성되도록 고수준의 제어 루프를 제공
    • etcd: 클러스터 설정을 포함하는 분산 키-값 저장소
  • 이 컴포넌트들은 모든 마스터 노드에서 실행되는 시스템 서비스 형태로 되어 있는데 클러스터 전체를 수동으로 실행 및 생성할 수 있지만 클러스터 생성 라이브러리나 클라우드 벤더가 제공하는 서비스(EKS)를 사용하면 프로덕션 환경에서 자동으로 시작할 수 있음

쿠버네티스 API Server

  • 일반적으로 443 포트를 사용해 HTTPS 요청을 받는 컴포넌트
  • 쿠버네티스 API 서버에 구성 요청시 etcd에서 현재 클러스터 설정 정보를 확인하고 필요 시 변경함
  • 쿠버네티스 API는 RESTful API
  • 쿼리 경로로 API 버전과 각 쿠버네티스 리소스 유형에 대한 엔드포인트로 구성
  • 쿠버네티스를 확장할 때 API 그룹을 기반으로 동적 엔드포인트 세트를 가진 API를 이용해서 커스텀 리소스를 동일한 수준의 RESTful API로 노출할 수 있음
쿠버네티스 동작 과정
                                                         ___________클러스터_____________________________________
사용자 인증 -> 명령어 인증 -> API Server ->-------------->| kubelet -> Docker, containerd가 pod 생성              |
    |                           ||                      | kubelet  -> 스케쥴러(파드가 생성 워커 파드를 찾아서 조정)|
파드 생성 알림, etcd 저장<--------|                       |------------------------------------------------------|
(실제로 생성됐는지는 확인해야)    etcd  

etcd

  • API Server는 파드를 만든다는 사실을 etcd에 알리고 사용자가에게 파드가 생성되었음을 알리는 기능을 수행
  • etcd는 클러스터의 상태를 저장하는 컴포넌트
  • key-value 형태로 저장

스케쥴러

  • 파드를 위치시킬 적당한 워커 노드를 확인하는 컴포넌트
  • 워커 노드가 확인되면 API Server에게 알리고 그러면 etcd에 파드가 생성될 것이라고 저장

kubelet

  • API Server로부터 생성될 워커 노드에 있는 kubelet에게 파드 생성 정보를 전달하고 kubelet은 이 정보를 기반으로 파드를 생성
  • 파드가 생성되면 kubelet은 API Server에 생성되었다는 사실을 알려주고 그 정보를 etcd에 업데이트(어떤 워커 노드에 어떤 파드가 생성되었는지 저장)

Controller Manager

  • 컴포넌트의 상태를 지속적으로 모니터링하는 동시에 실행 상태를 유지하는 역할을 수행
  • 특정 노드 와 통신이 불가능하다고 판단되면 해당 노드에 할당된 파드를 제거하고 다른 워커 노드에서 파드를 생성해 서비스가 계속되도록 함

Proxy

  • 클러스터의 모든 노드에서 실행되는 네트워크 프록시
  • 노드에 대한 네트워크 규칙을 관리
  • 클러스터 내부와 외부에 대한 통신을 담당

Container Runtime

  • 컨테이너 런타임은 컨테이너 실행을 담당

  • 여러 종류의 런타임을 지원하는데 최신 버전에서는 도커는 지원 중단되고 컨테이너디와 크라이오 등을 사용

  • etcd, API Server, Controller Manager, Scheduler는 Master Node에 존재하고 Proxy, Kubelet, Container Runtime은 워커 노드에 존재

|======================Cluster=====================================|
||==master node========|            |-----worker node---------|    |
||etcd <- API server<--|------------|----Proxy(통신)           |    |
||           ^      <--|------------|-----kubelet(명령실행)    |    |
||           |         |            |       |                 |     |
||Controller Manager / |            |  Container Runtime      |     |
||       스케쥴러       |            |                         |     |
||=====================|            |-------------------------|     |
|===================================================================|

쿠버네티스 컨트롤러

Deployment -> Replica Set ->
Daemon Set ---------------->
Stateful Set -------------->   POD
Cron Job -> Job ----------->
Application Controller ---->
  • 파드를 관리하는 역할을 수행하는 객체

Deployment

  • 쿠버네티스에서 상태가 없는 애플리케이션을 배포할 때 사용하는 가장 기본적인 컨트롤러
  • 레플리카 셋의 상위 개념이면서 파드를 배포할 때 사용
  • 파드를 배포할 때는 Deployment나 서비스를 이용
  • yaml 파일 기본 구조
apiVersion: apps/v1
kind: Deployment
metadata:
 name: 이름
 labels:
   app: 레이블 설정

spec:
 replicas: 레플리카 개수
 selector:
 
 metadata: 파드 실행 설정

ReplicaSet

  • 몇 개의 파드를 유지할지 결정하는 컨트롤러
  • ReplicaSet과 ReplicaController는 다름
  • ReplicaSet은 집합 기반으로 in, not in, exists 같은 연산자를 지원하지만 ReplicationController는 등호 기반이라서 =, !=를 지원
  • ReplicaSet은 롤링 업데이트를 사용할려면 Deployment를 사용해야 하지만 ReplicationController는 롤링 업데이트 옵션을 지원

Job

  • 하나 이상의 파드를 지정하고 지정된 수의 파드가 성공적으로 실행되도록 해주는 컨트롤러
  • 노드의 하드웨어 장애나 재부팅 등으로 파드가 비정삭적으로 작동하면 다른 노드에서 파드를 시작해 서비스가 지속되도록 함
  • manifest
apiVersion: batch/v1
kind: job
spec:
metadata:
  name: 잡이름
spec:
  template:
    metadata:
      name: 하나의 템플릿 이름
    spec:
      containers:
        - name: 컨테이너이름
          image: 이미지이름
          command: [명령어]
      restartPolicy: 정책

CronJob

  • 잡의 일종으로 특정 시간에 특정 파드를 실행시키는 것 과 같이 지정한 일정에 따라서 잡을 실행시킬 때 사용
  • 주로 애플리케이션 프로그램의 실행이나 데이터베이스의 경우 백업 등의 작업을 설정
  • manifest
apiVersion: batch/v1
kind: CronJob
metadata:
  name: 잡이름
spec:
  schedule: "* * * * *" # linux의 cron 작업과 동일
  jobTemplate:
    spec:
      template:
      metadata:
        name: 하나의 템플릿 이름
      spec:
        containers:
          - name: 컨테이너이름
            image: 이미지이름
            args:
              - /bin/sh
              - -c
              - date; echo Hello this is Cron test
        restartPolicy: 정책

DaemonSet

  • Deployment 처럼 파드를 생성하고 관리
  • Deployment는 파드의 개수와 배포 전략을 설정하지만 데몬 셋은 특정 노드 또는 모든 노드에 파드를 배포하고 관리
  • 노드마다 배치되어야 하는 성능 수집 및 로그 수집 같은 작업에 사용
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: 이름
  labels:
    app: 레이블 # 데몬셋을 식별할 수 있는 레이블을 설정
spec:
  selector:
    matchLabels:
      app: 앱의 레이블
  template:
    metadata:
      labels:
        app: 앱의 레이블 # 파드의 레이블
    spec:
      tolerations:
      - key: node-role/master
        effect: NoSchedule
  • taint와 tolerations
    • 쿠버네티스 클러스터를 운영하다 보면 특정 워커 노드에는 특정 성격의 파드만 배포하고자 하는 경우가 있음
    • GPU가 설치된 파드에는 GPU가 필요한 서비스만 배포하고자 하는 경우가 대표적
    • 테인트가 설정된 노드에는 일반적으로 사용되는 파드는 배포될 수 없으나 톨러레이션을 적용하면 배포할 수 있음
    • 테인트 설정 kubectl taint node [NODE_NAME] [KEY]=[VALUE]:[EFFECT]
    • EFFECT에는 3가지 옵션이 있음
      • NoSchedule: 톨러레이션이 완전치 일치하는 파드만 배포할 수 있음
      • NoExecute: 기존에 이미 배포된 파드를 다른 노드로 옮기고 새로운 파드는 배포하지 못하도록 하는 것
      • PreferNoSchedule: NoSchedule 과 유사하지만 지정된 노드에는 새로운 파드가 배포되지 않지만 리소스가 부족할 때는 배포할 수 있는 차이가 있음

쿠버네티스 서비스

K8S Cluster
└── Deployment
    └── ReplicaSet (2 replicas)
        ├── Pod (Node 1)
        ├── Pod (Node 2)
        └──     (Node 3)
  • 파드는 쿠버네티스 클러스터 안에서 옮겨다니는 특성이 있음
  • 각각의 파드는 별도의 IP를 할당받음
  • 동적으로 변하는 파드에 고정된 방법으로 접근하기 위해서 사용하는 것이 service
  • 서비스를 사용하면 파드가 클러스터 내의 어디에 떠 있든지 고정된 주소를 이용해서 접근할 수 있음
  • 클러스터 외부에서도 접근할 수 있음
alias, symbolic link 쓰는 이유 두가지:
  1 짧게 쓰기 위해
  2 이름이 바뀔 수 있기 때문
    ex Linux의 systemd -> init.d 로 바뀜
       Linux의 bash
      Node의 Pod이 다른 Node로 옮겨가도 IP는 바뀌지만 IP가리키는 이름은 바뀌지 않음
agile은 같이 일하는 것, 서비스를 분할하는 것이 아닌
  • 서비스의 종류
    • Cluster IP: 쿠버네티스 클러스터 내의 파드들은 기본적으로 외부에서 접근할 수 있는 IP를 할당받지 않지만 클러스터 내부에서는 파드들이 통신할 방법을 제공하는데 이것이 클러스터 IP 입니다. 클러스터 내의 모든 파드가 해당 클러스터 IP 주소로 접근할 수 있습니다.
    • NodePort: 서비스를 외부로 노출할 때 사용하는 것으로 노드포트로 서비스를 노출하기 위해 워커 노드의 IP 와 포트를 이용합니다. 워커 노드의 IP가 192.168.2.3 이고 30010 포트를 사용한다면 192.168.2.3:30010 포트로 외부에서 접근 가능
    • Load Balancer: 로드 밸런서는 주로 퍼블릭 클라우드에 존재하는 로드 밸런서에 연결하고자 할 때 사용하는데 이 경우는 Load Balancer의 외부 IP를 통해서 접근
Load Balancer
├── 서비스 1 (NodePort) (Public IP)
│   └── K8S Cluster 1 (Cluster IP)
│       └── Deployment
│           └── ReplicaSet (2 replicas)
│               ├── Pod (Node 1) (Private IP)
│               ├── Pod (Node 2) (Private IP)
│               └──     (Node 3)
└── 서비스 2 (NodePort) (Public IP)
    └── K8S Cluster 2 (Cluster IP)
        └── Deployment
            └── ReplicaSet (2 replicas)
                ├── Pod (Node 1) (Private IP)
                ├── Pod (Node 2) (Private IP)
                └──     (Node 3)
  • manifest
apiVersion: v1
kind: Service
metadata:
  name: t-service
spec:
  selector:
    app: webserver #워커 노드에 떠 있는 컨테이너 중 webserver를 선택
  ports:
    - protocol: TCP
      port: 80 # 서비스에서 컨테이너 애플리케이션과 매핑 시킬 포트 번호
      targetPort: 8080 # 컨테이너에서 구동 중인 애플리케이션 포트번호

쿠버네티스 통신

쿠버네티스 통신의 특징

  • 파드가 사용하는 네트워크와 호스트(노드)가 사용하는 네트워크는 다름
  • 노드 내의 파드들은 가상의 네트워크를 사용하고 호스트는 물리 네트워크를 사용
  • ipconfig 명령 시 실제 인터페이스는 무선LAN WIFI어댑터와 이더넷 어댑터 두개
    • 나머지는 가상 인터페이스
  • 같은 노드에 있는 파드끼리만 통신이 가능
    • 같은 노드에 떠 있는 파드끼리는 통신이 가능하지만 다른 노드의 파드 또는 외부와의 통신은 불가능
  • 다른 노드의 파드와 통신하려면 CNI 플러그인이 필요
    • CNI(Container Network Interface)는 컨테이너 간의 통신을 위한 네트워크 인터페이스
    • CNI Plugin은 컨테이너들의 네트워크 연결하거나 삭제하면 특히 삭제할 때는 할당된 자원을 제거
    • 쿠버네티스를 설치할 때 자동으로 구성되지 않으므로 별도로 설치해야 함

같은 파드에 포함된 컨테이너간 통신

  • 파드: docker-compose와 유사 (1개 이상의 컨테이너로 구성)
  • 같은 파드 내의 컨테이너가 통신은 직접(로컬호스트 통신) 통신이 가능
  • 하나의 파드에는 하나의 가상 네트워크가 만들어지고 그 파드 내에 존재하는 컨테이너들은 같은 가상 네트워크를 사용
  • 하나의 파드 내에 존재하는 컨테이너들은 모두 동일한 IP를 사용
  • 하나의 파드 안에 있는 컨테이너들은 포트 번호를 이용해서 구분
  • 하나의 파드가 만들어지면 가상의 네트워크가 만들어지고 브릿지가 존재하고 이 브릿지가 노드의 실제 NIC 와 연결됨
eth : Node
└── Bridge
    └── veth : Pod

단일 노드에서 파드간 통신

  • 단일 노드에 떠 있는 파드들은 같은 네트워크 대역(veth0: 172.10.0.2/24, vetho: 172.10.0.3/24)을 가지므로 브릿지를 이용해서 통신을 수행할 수 있음

다수의 노드에서 파드 간 통신

  • 각 노드에서는 노드 별로 가상의 네트워크를 생성하기 때문에 서로 다른 노드 간에 동일한 IP를 가질 수 있기 때문에 단순한 방식으로는 통신이 불가능함
  • 오버레이 네트워크를 이용해서 통신(NAT)
  • 오버레이 네트워크는 노드에서 사용하는 물리적인 네트워크 위에 가상의 네트워크를 구성하는 것
  • 오버레이 네트워크를 사용하면 클러스터로 묶인 모든 노드에 떠 있는 파드 간의 통신이 가능
  • 쿠버네티스에서는 기본적으로 kubenet이라는 기본적이고 간단한 네트워크 플러그인을 제공하는데 이 플러그인이 오버레이 네트워크를 구성함
오버레이 네트워크
Kubernetes Cluster
├── Node 1: eth0(public IP)
│   ├── Pod A (172.16.0.1)
│   └── Overlay Network
│       └── 10.0.0.2/24
└── Node 2: eth0(public IP)
    ├── Pod B (172.16.0.1)
    └── Overlay Network
        └── 10.0.0.3/24

파드와 서비스 간의 통신

  • 서비스의 특성
    • 서비스도 파드처럼 IP를 가짐
    • 파드와 서비스에서 사용하는 IP 대역은 다릅니다.
  • Client 파드가 네트워크를 통해서 다른 노드의 Web Server 파드에 http 요청을 하는 경우
    • Client 파드는 서비스 이름으로 http 요청을 보냄
    • 클러스터 DNS 서버는 서비스이름에 해당하는 서비스 IP를 Client 파드에게 전달
    • 서비스 IP를 전달받은 Client 파드는 해당 IP를 이용해서 http 요청을 보내는데 이 때 클라이언트 워커 노드는 라우팅 테이블에 서비스 IP가 있는지 검색하고 검색 결과 IP가 없으면 해당 요청을 라우터/게이트웨이 로 전달
    • 라우터 나 게이트웨이는 서비스 IP를 찾지 못할 수 있는데 이 경우 linux에 있는 netfilter 와 iptables 기능을 이용해서 찾아옴
    • netfilter는 주소변환, 규칙 기반의 패킷 처리 엔진으로 서비스 IP를 특정 IP로 변경할 수 규칙을 저장하고 변환하는 역할을 함
    • 이런 이유로 netfilter를 프록시라고 함
    • 이 정보를 저장하고 있는 것이 iptables

외부 와 서비스 간의 통신

  • NodePort: 노드 포트란 노드 IP에 포트를 붙여서 외부에 노출시키는 것
  • Load Balancer: 로드 밸런서는 로드밸런서 IP를 이용해서 클러스터 외부에서 파드에 접근할 수 있도록 해주는 기능
  • Ingress: 클러스터 외부에서 내부로 접근하는 요청을 어떻게 처리할 것인지에 관한 규칙의 모음이고 실제로 동작시키는 것은 Ingress Controller
  • 서비스를 넓게 이야기 할 때는 위의 3개를 포함하는 것으로 이야기 하고 좁게 이야기 할 때는 클러스터 내부에서 다른 노드에 접근할 수 있도록 해주는 것만 서비스라고 하기도 함