본문 바로가기

DevOps/DOIK (Database Operator in Kubernetes)

Kubernetes Basic

1. Kubernetes Components

쿠버네티스 클러스터는 Control Plane과 Node로 구성되어 있다.

Control plane = kube-apiserver + kube-controller-manager + kube-scheduler : 클러스터 리소스에 대한 관리 역할을 하는 노드 → 외부로부터 리소스에 대한 요청을 처리하고, 리소스의 desired state와 현재 state를 맞춤

  • kube-api-server :
    • 클러스터에 대한 리소스 제어 API 제공
    • 외부로부터 이러한 API가 호출되기 위해 클라이언트에 대한 보안 기능 제공
    • 노드 또는 파드에 접근할 수 있는 proxy 역할 수행
  • kube-controller-manager :
    • 쿠버네티스 리소스들에 대한 상태 관리
    • 리소스의 Desired State를 유지할 수 있도록 Actual State를 체크, 일치
  • kube-scheduler :
    • 쿠버네티스 리소스들에 대한 스케줄링 담당
    • 노드의 상태를 파악하고 요청 받은 리소스가 실행될 수 있는 곳에 리소스 배치
  • Etcd :
    • 쿠버네티스 서비스의 상태를 저장하는 스토리지 서비스 (key-value store)

Worker Node = kubelet + kube-proxy : Control Plane로부터 부여받은 컨테이너가 실행되는 노드

  • kuelet :
    • docker, containerd, cri-o 등 컨테이너런타임을 이용해 컨테이너를 수행 역할
  • kube-proxy : (daemonset)
    • 각각의 노드에서 실행되는 네트워크 proxy로, 노드의 네트워크 규칙 생성/관리
  • Container Runtime :
    • 실제 컨테이너를 실행하는 컨테이너 실행 환경

2. Kubernetes Storage

Container Volume...

컨테이너 내 디스크에 있는 파일은 임시적이다. 그에 따라 2가지 문제가 발생하는데..

  1. 컨테이너가 크래시될 때 파일이 손실됨 (Pod 내부의 데이터는 Pod가 정지되면 모두 삭제됨)
  2. 하나의 Pod에서 같이 실행되는 컨테이너들이 파일을 공유할 때 발생

쿠버네티스 볼륨 추상화는 이러한 문제를 해결한다.

Kubernetes Volume...

쿠버네티스는 다양한 유형의 볼륨을 지원한다.

[1] hostPath

hostPath 볼륨은 호스트 노드의 파일시시스템에 있는 파일이나 디렉터리를 파드에 마운트 한다.

 

[2] emptyDir

emptyDir 볼륨은 파드가 노드에 할당될 때 처음 생성되며, 해당 노드에서 파드가 실행되는 동안에만 존재.

(노드에서 파드가 제거되면 emptyDir의 데이터가 영구적으로 삭제됨. 컨테이너가 크래시 되는 것은 노드에서 파드를 제거하지 않기 때문에 emptyDir 볼륨의 데이터는 컨테이너 크래시로부터 안전함)

기본 emptyDir 볼륨은 디스크, SSD, 네트워크 스토리지와 같이 노드를 지원하는 모든 매체에 저장된다. emptyDir.medium 필드를 "Memory"로 설정하면, 쿠버네티스는 tmpfs(RAM 기반 파일시스템)를 대신 마운트한다.

 

[3] PV(persistentVolume) / PVC(persistentVolumeClaim)

PV는 정적 또는 동적으로 프로비저닝 한 클러스터의 스토리지이다.

PVC는 사용자의 스토리지에 대한 요청이다.

 

3. Kubernetes Network

참고자료: https://www.tkng.io

 

The Kubernetes Networking Guide :: The Kubernetes Networking Guide

The Kubernetes Networking Guide The purpose of this website is to provide an overview of various Kubernetes networking components with a specific focus on exactly how they implement the required functionality. The information here can be used for education

www.tkng.io

[1] Kubernetes CNI

Container Network Interface는 쿠버네티스 네트워크 환경을 구성

 

Kubernetes Calico CNI vs AWS VPC CNI 차이

Calico의 경우, 일반적으로 노드와 파드 네트워크 대역이 다르다. 반면 AWS VPC CNI는 노드와 파드의 네트워크 대역이 같다.

파드간 통신 시 일반적으로 쿠버네티스 CNI는 오버레이(VXLAN, IP-IP 등) 통신을 하고, AWS VPC CNI는 동일 대역으로 직접 통신한다.

[2] Kubernetes Service

파드 집합에서 실행 중인 애플리케이션을 네트워크 서비스로 노출하는 추상화 방법으로 다양한 타입을 지원한다.

 

ClusterIP 타입

클라이언트가 ClusterIP 접속 시 해당 노드의 iptables 룰 (랜덤 분산)에 의해 Destination IP에 대해 네트워크 변환 처리가 되어(일반적으로 목적지 IP와 목적지 port 변환) 목적지 파드와 통신

  • 클러스터 내부에서만 ClusterIP로 접근 가능 (외부 불가능)
  • ClusterIP 서비스를 생성하면, apiserver -> kube-proxy -> iptables에 rule 생성됨
  • 모든 노드(마스터 포함)에 iptables rule이 설정되므로, 파드에 접속 시 해당 노드에 존재하는 iptables rule에 의해 분산 접속 됨
    • sessionAffinity: ClusterIP 설정을 통해 클라이언트가 접속한 목적지(파드)에 고정적인 접속을 지원한다.
  • iptables는 파드에 대한 healthcheck 기능이 없어 문제 있는 파드에 연결될 수 있다
    • 파드에 Readiness Probe 설정을 통해 문제 있는 파드를 서비스 엔드포인트에 제거되게 설정할 수 있다.

NodePort 타입

외부 클라이언트가 NodePort 접속 시 해당 노드의 iptables 룰에 의해

  1. Source IP에 대해 네트워크 변환 처리(일반적으로 출발지 IP 변환)와
  2. Destination IP에 대해 네트워크 변환 처리가 되어(일반적으로 목적지 IP와 목적지 port 변환)

목적지 파드와 통신 후 리턴 트래픽은 최초 인입 노드를 경유해서 외부로 되돌아간다.

 

  • 외부에서 클러스터의 NodePort로 접근 가능
  • 모든 노드(마스터 포함)에 iptables rule이 설정되므로, 모든 노드에 NodePort로 접속 시 iptable rule에 의해 분산 접속됨
  • externalTrafficPolicy: Local 설정을 통해 NodePort 접속 시 해당 노드에 배치된 파드로만 접속할 수 있다.
    (위와 같은 경우, Source IP에 대해 네트워크 변환 처리(일반적으로 출발지 IP 변환)가 이루어지지 않아 외부 클라이언트 IP가 보존됨)
  • 외부에서 노드의 IP와 포트로 직접 접속이 필요함에 따라, 내부망이 외부에 공개되어 보안에 취약
    • LoadBalancer 서비스를 사용하여 외부 공개 최소화할 수 있다.
  • 클라이언트 IP 보존을 위해, externalTrafficPolicy: Local 사용 시 파드가 없는 노드 IP로 NodePort 접속 시 실패
    • LoadBalancer 서비스에서 healthcheck 기능으로 대비할 수 있다.

LoadBalancer 타입

외부 클라이언트가 LoadBalancer 접속 시 부하분산되어 노드 도달 후 iptables 룰로 목적지 파드와 통신한다.

  • LoadBalancer를 통해 노드는 외부에 공개되지 않고 로드밸런서만 외부에 공개되어, 외부 클라이언트는 로그밸런서에 접속을 할 뿐 내부의 정보를 알 수 없다.
  • 로드밸런서가 부하분산하여 파드가 존재하는 노드들에게 전달
    (iptables 룰에서는 자신의 노드에 있는 파드만 연결한다. externalTrafficPolicy: Local)
  • Destination IP에 대한 네트워크 변환 처리가 2번 동작한다.
    1. 로드밸런서 접속 후 노드의 iptables로 나갈 때
    2. 노드의 iptables 룰에서 파드 IP 전달 시
  • 외부 클라이언트 IP를 보존할 수 있다.
    • AWS NLB는 target이 인스턴스일 경우 클라이언트 IP를 유지
    • iptables 룰 경우에도 externalTrafficPolicy로 클라이언트 IP를 보존
  • LoadBalancer 사용 시, 노드에 파드가 없을 경우 healthcheck가 실패하여 해당 노드로는 외부 요청 트래픽을 전달하지 않는다.
  • LoadBalancer 타입의 서비스를 생성할 때마다 로드밸런서가 생성되어 자원 활용이 비효율적이다.
    • HTTP 프로토콜 사용 시 Ingress를 통해 자원 활용 효율화 가능
  • LoadBalancer 타입의 서비스는 HTTP/HTTPS 처리에 일부 부족하다.(TLS 종료, 도메인 기반 라우팅 등)
    • Ingress를 통해 기능 동작 가능

Headless 타입

DNS만을 포함하는 가장 간단한 형태의 로드밸런싱. 로드밸런서 가상 IP가 할당되지 않지만, DNS쿼리는 모든 백엔드 파드에 대한 IP를 반환한다. 이에 대한 가장 일반적인 사례는 클라이언트가 안정적이고 예측 가능한 DNS 이름이 필요하고 연결 및 장애 조치의 손실을 스스로 처리할 수 있는 stateful workload인 경우이다.

  • Headless 서비스는 대상이 되는 개별 파드의 IP의 주소가 직접 반환되는 서비스
    • 기본은 DNS RR(Resource Record)로 파드의 IP 주소가 직접 반환, StatefulSet인 경우 추가로 파드명으로 이름 해석 가능
  • Headless 서비스 조건
    • 서비스 spec.type: ClusterIP
    • 서비스 spec.clusterIP: None
    • StatefulSet + Headless service 사용으로 StatefuleSet으로 생성된 파드명으로 이름 해석 시:
      • 서비스의 metadata.name 이 statefulset의 spec.serviceName과 같을 것

[3] Kubernetes Ingress

Ingress

클러스터 내부의 서비스(ClusterIP, NodePort, LoadBalancer)를 외부로 노출(HTTP/HTTPS) (Proxy역할)

기술적으로 NodePort 또는 LoadBalancer 서비스를 통해 내부 애플리케이션을 노출할 수 있지만, 이런 경우가 드물다.

1. Costs 비용

각 LoadBalancer 서비스는 단일 외부 주소와 연결되어 있어, 퍼블릭 클라우드 환경에서 실행할 때 많은 비용이 발생된다

2. Funcitonality 기능

서비스에서 제공하는 간단한 L4 로드밸런싱은 일반적으로 애플리케이션 proxy 또는 gateway와 관련된 많은 기능이 부족하다. (TLS management, Rate-limiting, Authentication, Traffic Routing 등)

 

LoadBalancer 서비스 유형과 비슷하게, Kubernetes는 Ingress API만 정의하고 클러스터 add-on에 의해 구현된다.(클라우드 환경의 경우 기존 애플리케이션 로드밸런서에 의해 구현)

 

Ingress Controller는 대부분 다음과 같은 구성 요소로 이루어져 있다.

  • Controller : API 서버와 통신하고 프록시를 성공적으로 프로비저닝 하는 데 필요한 모든 정보를 수집
  • Proxy : controller가 관리하는 데이터 플레인(sclae up/down 가능)

Ingress의 주요 기능은 다음과 같다.

  • Path(경로) 기반 라우팅 : Ingress는 들어오는 요청의 경로를 기준으로 적절한 내부 파드로 라우팅 한다.
  • 가상 호스트 기반 라우팅 : Ingress는 요청된 도메인 이름을 기준으로 가상 호스트를 설정하여 서로 다른 도메인 또는 서브도메인으로 접근하는 요청을 서비스로 전달할 수 있다.
  • SSL 인증서 관리 : Ingress는 HTTPS 프로토콜을 지원하며, SSL 인증서를 관리하여 암호화된 통신을 제공한다. Ingress Controller에서 인증서를 처리하고 Controller와 내부 파드 간 연결은 평문(http)으로 통신한다.
  • LoadBalancing : 백엔드 서비스 간에 트래픽을 균등하게 분배하거나, 특정 규칙에 따라 트래픽을 전달할 수 있다.

[4] CoreDNS

CoreDNS는 일반적으로 Kubernetes Cluster 내부에서 이용되는 DNS 서버이다. 주로 Kubernetes 클러스터 내부에서 도메인을 통해 Service나 Pod IP를 찾는 용도로 많이 이용된다.

CoreDNS는 일반적으로 Worker Node에서 Deployment로 배포되어 다수의 파드로 구동되는데, 다수의 CoreDNS의 파드들은 CoreDNS 서비스를 통해 가상 IP(ClusterIP)로 묶이게 된다.

쿠버네티스 클러스터의 파드들은 CoreDNS Service의 가상 IP를 통해 CoreDNS에 접근하게 되며, 다수의 CoreDNS 파드와 서비스를 사용하는 이유는 HA 때문이다.

 

[5] ExternalDNS

 

쿠버네티스는 외부에서 쿠버네티스의 resources, LoadBalancer Service, ingress, Gateway를 발견할 수 있는 방법을 제공해야 하며, 이를 위해 2가지 방법을 제공한다. (ExternalDNS cluster add-on, k8s_gateway)

 

ExternalDNS는 kubernetes dns(kube-dbs)와 상반되는 개념으로 내부 도메인 서버가 아닌 Public 한 도메인 서버를 사용하여 쿠버네티스 리소스를 쿼리 할 수 있게 해 준다. ExternalDNS를 사용하면 public 도메인 서버가 무엇이든 상관없이 쿠버네티스 리소스를 통해 DNS 레코드를 동적으로 관리할 수 있다.

 

K8s Service/Ingress 생성 시 도메인을 설정하면, AWS(Route53), Azure(DNS), GCP(Cloud DNS)에 레코드 자동 생성/삭제

(Ingress 생성과 동시에 Route53 - ALB - Node - Pod 트랙픽이 단번에 라우팅)