콘텐츠 대표 이미지 - Knative: 쿠버네티스 위에서 서버리스 워크로드를 힙하게 관리하는 법

Knative: 쿠버네티스 위에서 서버리스 워크로드를 힙하게 관리하는 법

개발자라면 한 번쯤 들어봤을 '서버리스'.
서버 걱정 없이 코드만 짜면 된다니, 이거 완전 개발자의 유토피아 아니야?
하지만 현실은? 쿠버네티스라는 거대한 산이 떡하니 버티고 있지.
오늘, 이 둘을 환상적으로 이어주는 'Knative(네이티브)'에 대해 제대로 파헤쳐 보자고!

안녕, 개발자 친구들! 👋 서버리스와 쿠버네티스 사이에서 길을 잃었니?

요즘 개발 씬에서 가장 핫한 단어 두 개를 꼽으라면 단연 '서버리스(Serverless)'와 '쿠버네티스(Kubernetes)'일 거야. 한쪽에서는 "서버 관리는 이제 그만! 코드에만 집중해!"라며 달콤한 유혹을 속삭이고, 다른 한쪽에서는 "컨테이너 오케스트레이션의 표준은 나야 나!"라며 막강한 영향력을 과시하고 있지.

근데 여기서 문제가 발생해. 서버리스의 편리함을 누리고 싶지만, 우리 회사 인프라는 이미 쿠버네티스가 점령했는걸? AWS 람다나 구글 클라우드 펑션 같은 특정 클라우드 제공업체(CSP)의 서비스에 종속되기는 싫고, 그렇다고 쿠버네티스의 강력한 생태계를 포기할 수도 없고... 이거 완전 딜레마잖아?

이런 고민을 하는 너를 위해 구글 신께서 내려주신 선물이 있으니, 바로 **Knative(케이네이티브)**야. Knative는 쿠버네티스라는 튼튼한 기반 위에 서버리스라는 날개를 달아주는, 말 그대로 '게임 체인저'라고 할 수 있어. 복잡한 인프라 설정은 쿠버네티스에게 맡기고, 개발자는 오롯이 비즈니스 로직에만 집중할 수 있게 해주는 마법 같은 도구지.

잠깐, Knative를 왜 '케이네이티브'라고 읽어?
Knative는 Kubernetes-native의 줄임말이야. 그래서 '크네이티브'나 '나티브'가 아니라 쿠버네티스의 'K'를 살려서 '케이네이티브'라고 읽는 게 국룰이지. 이제부터 우리도 힙하게 '케이네이티브'라고 부르자고!

이 글을 끝까지 읽고 나면, 너는 더 이상 서버리스와 쿠버네티스 사이에서 방황하지 않게 될 거야. Knative가 어떻게 너의 개발 라이프를 윤택하게 만들어 주는지, 그 핵심 개념부터 실제 적용 사례까지! 친구에게 설명해주듯 쉽고 재미있게 알려줄게. 준비됐어? 그럼, 출발!


1. Knative, 넌 대체 누구니? (정의와 아키텍처)

Knative를 한마디로 정의하면 **"쿠버네티스 위에서 서버리스 애플리케이션을 빌드, 배포, 관리하기 위한 오픈소스 빌딩 블록 세트"**야. 말이 좀 어렵지? 쉽게 풀어보자.

쿠버네티스가 '클라우드 시대의 운영체제(OS)'라면, Knative는 그 OS 위에서 돌아가는 '서버리스 프레임워크' 같은 거야. 우리가 윈도우나 맥OS 위에서 포토샵이나 VS Code 같은 프로그램을 돌리는 것처럼, 쿠버네티스 위에서 Knative를 이용해 서버리스 워크로드를 돌리는 거지.

중요한 건 Knative가 쿠버네티스를 대체하는 게 아니라는 점이야. 오히려 쿠버네티스의 복잡한 부분을 살짝 가려주고, 개발자가 더 쓰기 편하게 만들어주는 '확장 프로그램'에 가까워. 쿠버네티스의 기본 오브젝트인 `Deployment`, `Service`, `Ingress` 등을 직접 다루는 대신, Knative가 제공하는 `Service`, `Route` 같은 더 높은 수준의 추상화된 개념을 사용하게 되는 거지.

Knative의 핵심 철학 엿보기

  • 개발자 중심: 인프라 걱정 없이 코드에만 집중하게 만들자!
  • 느슨한 결합(Loosely Coupled): 필요한 기능만 쏙쏙 골라 쓸 수 있게 하자!
  • 이식성(Portability): 한번 만들면 어디서든 돌아가게 하자! (AWS, GCP, Azure, 온프레미스 등)
  • 오픈소스: 모두가 함께 발전시키는 생태계를 만들자!

Knative의 아키텍처를 이해하려면, 먼저 얘가 혼자 일하는 게 아니라는 걸 알아야 해. Knative는 보통 '서비스 메시(Service Mesh)'라는 친구와 함께 일하는데, 대표적인 서비스 메시가 바로 **Istio(이스티오)**야. Istio는 컨테이너 간의 네트워크 통신을 제어하고 모니터링하는 역할을 해. Knative는 Istio의 이런 능력을 빌려서 트래픽을 나누거나(트래픽 스플리팅), 요청에 따라 컨테이너를 깨우는 등의 마법을 부리는 거지. (최근에는 Istio 외에 Kourier, Contour 등 더 가벼운 네트워킹 레이어도 많이 사용돼!)

아래 그림을 보면 Knative가 어떤 위치에 있는지 한눈에 이해될 거야.

Knative 아키텍처 개요 Kubernetes Cluster (기반 인프라) Worker Node 1 Worker Node 2 Worker Node 3 Service Mesh (네트워킹 계층) (Istio, Kourier, Contour 등) Knative (서버리스 빌딩 블록) Serving Eventing 의존 의존 개발자 (Code Push) 사용자 (HTTP Request)

결국 Knative는 쿠버네티스라는 든든한 형님과 Istio라는 똑똑한 동생 사이에서, 개발자가 편하게 서버리스의 꿀을 빨 수 있도록 도와주는 중간 관리자 역할이라고 생각하면 돼. 아주 頼もしい(타노모시이, 듬직한) 친구지!


2. Knative를 지탱하는 세 개의 기둥 (핵심 컴포넌트)

Knative는 크게 세 가지 핵심 컴포넌트로 구성되어 있었어. 바로 **Serving**, **Eventing**, 그리고 **Build**야. 여기서 '있었어'라고 과거형을 쓴 이유가 있는데, 그건 잠시 후에 설명해줄게. 일단 이 세 친구가 각각 무슨 일을 하는지 알아보자. 이 세 가지만 이해하면 Knative의 80%는 마스터하는 셈이야.

2.1. Knative Serving: 똑똑한 서빙 담당

Serving은 Knative의 가장 핵심적인 기능이야. 이름 그대로 **컨테이너를 실행하고, 네트워크를 통해 요청을 받아 처리(서빙)하는 역할**을 해. 근데 그냥 서빙만 하는 게 아니라, 아주 똑똑하게 일을 처리하지.

Knative Serving의 가장 큰 특징이자 존재 이유는 바로 **'Scale to Zero(스케일 투 제로)'**야. 이게 뭐냐면, 평소에 아무도 찾지 않는 서비스(컨테이너)는 아예 꺼버려서 리소스를 0으로 만들어. 그러다가 누군가 그 서비스를 호출하는 첫 번째 요청이 딱 들어오면, 그제서야 잠자고 있던 컨테이너를 번개처럼 깨워서 요청을 처리하는 거지. 그리고 또 한동안 요청이 없으면 다시 잠재워 버려. 이거 완전 자린고비 정신 아니냐고! 덕분에 우리는 유휴 리소스에 대한 비용을 획기적으로 줄일 수 있어.

Scale to Zero가 왜 그렇게 중요해?
생각해봐. 우리가 수십, 수백 개의 마이크로서비스를 운영하는데, 모든 서비스가 24시간 내내 바쁜 건 아니잖아. 어떤 서비스는 특정 시간에만 사용되고, 어떤 건 가끔씩만 호출되지. 기존 방식대로라면 이 모든 서비스에 최소한의 리소스(CPU, Memory)를 항상 할당해둬야 했어. 이건 엄청난 낭비지. 하지만 Scale to Zero 덕분에 우리는 딱 사용한 만큼만 비용을 지불하는, 진정한 의미의 'Pay-per-use' 모델을 구현할 수 있게 된 거야. 서버 비용 아껴서 팀원들 커피 사줄 수 있다 이 말이지!

Serving은 이 마법 같은 일을 해내기 위해 몇 가지 중요한 개념(오브젝트)을 사용해. 처음 보면 좀 헷갈릴 수 있지만, 관계를 생각하면서 보면 금방 이해될 거야.

  • **Service (서비스):** Knative Serving의 최상위 리소스야. 우리가 다룰 가장 중요한 오브젝트지. 하나의 `Service`는 애플리케이션의 전체 라이프사이클을 관리해. `Service`를 하나 만들면, Knative가 알아서 아래에 설명할 `Route`와 `Configuration`을 만들어주고 관리해줘. (주의! 쿠버네티스의 기본 `Service`와는 이름만 같고 역할은 완전히 다른 친구야!)
  • **Route (라우트):** 네트워크 트래픽을 어디로 보낼지 결정하는 교통 경찰이야. 특정 URL로 들어온 요청을 어떤 `Revision`으로 보낼지 매핑해줘. 이 친구 덕분에 우리는 **트래픽 스플리팅(Traffic Splitting)**이라는 고급 기술을 쓸 수 있어. 예를 들어, 새 버전(v2)에 10%의 트래픽만 보내고, 기존 버전(v1)에 90%를 보내는 '카나리 배포(Canary Deployment)'나, 두 버전을 동시에 띄워놓고 비교하는 'A/B 테스팅'을 아주 쉽게 할 수 있지.
  • **Configuration (컨피그레이션):** 서비스의 '원하는 상태(desired state)'를 정의하는 설계도야. 어떤 컨테이너 이미지를 쓸 건지, 환경 변수는 뭘로 할 건지 같은 설정을 담고 있어. 이 `Configuration`이 변경될 때마다, Knative는 새로운 `Revision`을 만들어내.
  • **Revision (리비전):** 코드와 설정의 '특정 시점 스냅샷'이야. 한번 만들어지면 절대 변하지 않는 **불변(Immutable)**의 특징을 가져. `Configuration`이 업데이트되면 새로운 `Revision`이 생성되고, 이전 `Revision`은 그대로 남아있어. 덕분에 문제가 생겼을 때 이전 버전으로 아주 빠르고 안전하게 롤백하는 게 가능해져.

이들의 관계를 그림으로 보면 훨씬 이해하기 쉬울 거야.

Knative Serving 컴포넌트 관계도 개발자 kubectl apply Knative Service: "helloworld-go" Configuration "어떤 컨테이너를 쓸까?" spec.template... Route "트래픽은 어디로?" URL: helloworld-go.default.example.com 생성 및 관리 변경 시 생성 Revision 1 (v1) image: gcr.io/hello:v1 (Immutable Snapshot) Pod Revision 2 (v2) image: gcr.io/hello:v2 (Immutable Snapshot) Pod 10% 90%

자, 그럼 실제로 Knative Service는 어떻게 생겼는지 YAML 코드를 한번 볼까? 백문이 불여일견이니까.


apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld-go
namespace: default
spec:
template:
spec:
containers:
- image: gcr.io/knative-samples/helloworld-go
env:
- name: TARGET
value: "Knative"

어때? 쿠버네티스 `Deployment` YAML 파일에 익숙하다면 "어? 생각보다 간단한데?" 싶을 거야. 이게 바로 Knative의 매력이지. 저 간단한 YAML 파일 안에 엄청난 기능이 숨어있어. 하나씩 뜯어보자.

  • apiVersion: serving.knative.dev/v1: "이 YAML은 Knative Serving API의 v1 버전을 사용할 거야"라고 알려주는 부분.
  • kind: Service: 이 리소스의 종류가 Knative의 `Service`임을 명시.
  • metadata: 이름(`name`)이나 네임스페이스(`namespace`) 같은 기본적인 정보를 담는 곳.
  • spec.template.spec.containers: 이 부분이 핵심! 바로 여기에 우리가 실행하고 싶은 컨테이너의 정보를 적어주면 돼.
    • image: 사용할 컨테이너 이미지 주소.
    • env: 컨테이너에 전달할 환경 변수.

우리가 저 YAML 파일을 `kubectl apply -f` 명령어로 쿠버네티스 클러스터에 적용하면, Knative Serving 컨트롤러가 이걸 딱 보고는 알아서 `Configuration`, `Route`를 만들고, 첫 번째 `Revision`을 생성한 뒤, Pod를 띄워서 서비스를 실행시켜. 그리고 외부에서 접근할 수 있는 URL까지 만들어주지. 우리는 복잡한 `Deployment`, `Service`, `Ingress` 설정을 할 필요가 전혀 없어. 완전 편하지 않아?

2.2. Knative Eventing: 이벤트 기반 아키텍처의 해결사

두 번째 기둥은 **Eventing**이야. 현대적인 애플리케이션은 '이벤트 기반(Event-Driven)'으로 동작하는 경우가 많아. 예를 들면, '사용자가 회원가입을 하면(이벤트 발생) -> 환영 이메일을 보낸다(처리)' 같은 흐름이지. Knative Eventing은 바로 이런 **이벤트 기반 아키텍처를 쿠버네티스 위에서 쉽게 구축할 수 있도록 도와주는 컴포넌트**야.

Eventing의 핵심 철학은 **'생산자(Producer)와 소비자(Consumer)의 분리(Decoupling)'**야. 이벤트를 만드는 놈(생산자)과 이벤트를 받아서 처리하는 놈(소비자)이 서로를 몰라도 되게 만드는 거지. 이게 왜 중요하냐면, 시스템이 훨씬 유연해지고 확장성이 좋아지기 때문이야.

예를 들어, '주문 생성'이라는 이벤트가 발생했다고 치자. 처음에는 '재고 관리 서비스'만 이 이벤트를 받아서 처리했어. 그런데 나중에 '배송 시작 서비스'와 '추천 상품 분석 서비스'도 이 이벤트가 필요해졌네? 생산자와 소비자가 꽉 묶여있다면(Tightly Coupled), 주문 시스템 코드를 수정해서 새로운 서비스들에게도 이벤트를 보내도록 만들어야 해. 이건 완전 악몽이지.

하지만 Knative Eventing을 쓰면? '주문 생성' 이벤트를 중앙 허브에 그냥 던져놓기만 하면 돼. 그러면 필요한 서비스들이 각자 알아서 그 허브에서 이벤트를 구독해서 가져가는 거야. 생산자는 누가 이벤트를 가져가는지 전혀 신경 쓸 필요가 없어. 이게 바로 느슨한 결합(Loosely Coupled)의 힘이지!

이벤트 기반 아키텍처, 어디에 써먹을까?

  • 파일 처리: 스토리지에 이미지가 업로드되면(이벤트), 자동으로 리사이징하고 워터마크를 박는 서비스(소비자)를 실행.
  • 데이터 파이프라인: 데이터베이스에 새로운 데이터가 삽입되면(이벤트), 데이터를 분석하고 대시보드를 업데이트하는 서비스(소비자)를 실행.
  • CI/CD 자동화: GitHub에 코드가 푸시되면(이벤트), 자동으로 테스트하고 배포하는 파이프라인(소비자)을 실행.
  • IoT: 수많은 센서에서 데이터가 들어오면(이벤트), 이상 징후를 감지하고 알림을 보내는 서비스(소비자)를 실행.

Knative Eventing도 Serving처럼 몇 가지 중요한 개념들로 이루어져 있어.

  • **Event Source (이벤트 소스):** 말 그대로 이벤트가 시작되는 곳이야. 이벤트를 만들어내는 주체지. GitHub, Kafka, RabbitMQ, GCP Pub/Sub, 심지어 특정 시간마다 이벤트를 발생시키는 CronJob까지 아주 다양한 종류의 `Event Source`가 있어.
  • **Broker (브로커):** 이벤트의 중앙 허브, 즉 우체국 같은 역할을 해. 모든 `Event Source`는 이벤트를 `Broker`에게 보내. `Broker`는 받은 이벤트를 잠시 보관하고 있다가, 이 이벤트를 받기 원하는 `Trigger`에게 전달해주는 역할을 하지.
  • **Trigger (트리거):** `Broker`와 `Consumer`(이벤트를 최종적으로 처리하는 서비스)를 연결하는 다리야. `Trigger`에는 **필터(Filter)** 기능이 있어서, `Broker`에 들어온 수많은 이벤트 중에서 자기가 원하는 조건의 이벤트만 쏙 골라서 `Consumer`에게 전달할 수 있어. 예를 들어, "HTTP 헤더의 `type`이 `com.github.pull_request`인 이벤트만 줘!" 와 같이 필터링할 수 있지.
  • **Sink (싱크):** 이벤트의 최종 목적지. 즉, 이벤트를 소비하는 `Consumer`를 의미해. 보통은 Knative `Service`가 `Sink` 역할을 많이 해.

이벤트가 흘러가는 과정을 그림으로 한번 보자. 훨씬 직관적으로 와닿을 거야.

Knative Eventing 이벤트 흐름도 Event Sources (생산자) GitHub Source Kafka Source CronJob Source Broker (이벤트 허브) Event Ingress Event 1 (Push) Event 2 (Order) Event 3 (Tick) Sinks (소비자) CI/CD Service (Knative Service) Inventory Service (Knative Service) Notification Service (Knative Service) Trigger 1: type=github.push Trigger 2: type=new.order Trigger 3: source=cronjob

YAML 코드를 보면 더 명확해질 거야. 여기 `Broker`와 `Trigger`를 정의하는 예시가 있어.


# 1. 이벤트를 담을 Broker 생성
apiVersion: eventing.knative.dev/v1
kind: Broker
metadata:
name: default
namespace: my-event-namespace

---

# 2. 특정 이벤트를 필터링해서 서비스로 전달할 Trigger 생성
apiVersion: eventing.knative.dev/v1
kind: Trigger
metadata:
name: new-order-trigger
namespace: my-event-namespace
spec:
broker: default
filter:
attributes:
type: "com.example.new.order"
source: "order-service"
subscriber:
ref:
kind: Service
name: inventory-manager
apiVersion: serving.knative.dev/v1

이 YAML은 두 부분으로 나뉘어 있어.

  1. Broker 정의: `default`라는 이름의 `Broker`를 `my-event-namespace`에 만들어. 이제 이 네임스페이스로 들어오는 이벤트들은 이 `Broker`가 받게 돼.
  2. Trigger 정의: `new-order-trigger`라는 이름의 `Trigger`를 만들어.
    • spec.broker: default: 이 `Trigger`는 'default' 브로커에 연결될 거야.
    • spec.filter.attributes: **이 부분이 바로 필터!** `source`가 `order-service`이고 `type`이 `com.example.new.order`인 이벤트만 골라내겠다는 의미야.
    • spec.subscriber.ref: 필터링된 이벤트를 누구에게 보낼지, 즉 `Sink`를 정의하는 부분. 여기서는 `inventory-manager`라는 Knative `Service`로 보내도록 설정했어.

이렇게 `Broker`와 `Trigger`를 사용하면, 우리는 아주 복잡한 이벤트 라우팅 규칙도 선언적인 YAML 파일 하나로 깔끔하게 관리할 수 있게 돼. 코드를 한 줄도 바꾸지 않고 새로운 이벤트 소비자를 추가하거나, 라우팅 규칙을 바꾸는 게 가능해지는 거지. 이게 바로 Knative Eventing이 주는 강력함이야.

2.3. Knative Build: 그리고 Tekton으로의 진화

마지막 세 번째 기둥은 **Build**였어. 이름에서 알 수 있듯이, **소스 코드를 컨테이너 이미지로 빌드하는 역할**을 담당했지. 개발자가 소스 코드만 Git에 푸시하면, Knative Build가 알아서 코드를 가져오고, Dockerfile을 이용해 이미지를 빌드한 다음, 컨테이너 레지스트리(Docker Hub, GCR 등)에 푸시해주는 'Source-to-Image' 워크플로우를 자동화해주는 멋진 친구였어.

그런데 왜 자꾸 과거형으로 말하냐고? Knative 프로젝트가 발전하면서, 이 'Build' 기능이 비단 서버리스 워크플로우뿐만 아니라 일반적인 CI/CD(지속적 통합/지속적 배포) 파이프라인에서도 매우 유용하다는 걸 깨닫게 된 거야. 그래서 Knative 팀은 이 Build 컴포넌트를 **'Tekton(텍톤)'**이라는 별도의 독립적인 프로젝트로 분리해서 더 크게 키우기로 결정했어.

Tekton: 쿠버네티스 네이티브 CI/CD 프레임워크
Tekton은 이제 Knative의 일부가 아니라, 그 자체로 강력한 CI/CD 솔루션이야. 쿠버네티스 위에서 CI/CD 파이프라인을 표준화되고, 재사용 가능하며, 선언적인 방식으로 구축할 수 있게 해줘. `Task`(작업의 최소 단위), `Pipeline`(Task들의 묶음), `TaskRun`, `PipelineRun` 같은 개념을 사용해서 복잡한 빌드, 테스트, 배포 과정을 자동화할 수 있지. Knative 환경에서 소스 코드를 이미지로 만드는 과정은 이제 대부분 Tekton이 담당하고 있어.

그래서 현재 Knative의 공식 컴포넌트는 **Serving**과 **Eventing** 두 가지라고 보는 게 맞아. 하지만 Knative의 시작과 철학을 이해하려면, 소스 코드를 자동으로 컨테이너로 만들어주려 했던 Build의 역할과 그것이 Tekton으로 진화한 역사를 함께 알아두는 것이 중요해. 이 세 가지(Serving, Eventing, Tekton)가 함께 어우러질 때, 우리는 비로소 `git push` 한 번으로 빌드부터 배포, 서빙까지 이어지는 환상적인 개발 경험을 완성할 수 있으니까!


3. 그래서 Knative를 왜 써야 하는데? (핵심 장점)

지금까지 Knative의 핵심 컴포넌트들에 대해 알아봤어. "오, 기능은 좋아 보이는데... 그래서 이걸 쓰면 구체적으로 나한테 뭐가 좋은데?"라고 묻는다면, 지금부터 눈을 크게 뜨고 보길 바라. Knative가 너의 개발 라이프를 어떻게 바꿔줄 수 있는지, 킬링 포인트만 쏙쏙 뽑아서 알려줄게.

🚀 개발자 경험(DX)의 수직 상승

Knative의 가장 큰 미덕은 개발자를 인프라의 고통에서 해방시켜 준다는 거야. 더 이상 `Deployment`, `Service`, `Ingress`, `HPA(HorizontalPodAutoscaler)` 같은 복잡한 쿠버네티스 리소스들을 일일이 설정하고 관리하느라 머리 싸맬 필요가 없어. 그냥 내 애플리케이션 로직이 담긴 컨테이너 이미지 주소만 알려주면, Knative가 나머지는 다 알아서 해주니까. 개발자는 오롯이 **'What(무엇을 만들까)'**에만 집중하고, **'How(어떻게 배포하고 운영할까)'**에 대한 고민은 Knative에게 맡길 수 있게 돼. 이건 정말 혁명적인 변화야.

🌐 진정한 이식성, 클라우드 종속성 탈출!

AWS 람다, 애저 펑션... 편리하긴 하지만 한번 쓰기 시작하면 그 클라우드 생태계에 발이 묶이는 '벤더 종속(Vendor Lock-in)' 문제가 항상 마음에 걸렸지? Knative는 이 문제에 대한 완벽한 해답을 제시해. Knative는 쿠버네티스가 돌아가는 곳이라면 어디든 설치할 수 있어. GCP(GKE), AWS(EKS), Azure(AKS) 같은 퍼블릭 클라우드는 물론이고, 회사 데이터센터의 온프레미스(On-premise) 환경에서도 동일하게 동작해. 즉, Knative `Service`로 작성된 내 애플리케이션은 **코드를 한 줄도 바꾸지 않고** 이 모든 환경을 자유롭게 오고 갈 수 있다는 거야. 이건 비즈니스 유연성 측면에서 엄청난 장점이지.

💰 비용 절감의 끝판왕, Scale-to-Zero

앞에서도 강조했지만, 이건 정말 Knative의 치트키야. 요청이 없을 때 Pod를 0개로 줄여서 리소스를 아예 사용하지 않는 능력. 특히 수많은 마이크로서비스를 운영하거나, 사용량이 들쭉날쭉한 서비스를 다룰 때 그 효과는 극대화돼. 개발/스테이징 환경처럼 항상 켜 둘 필요가 없는 환경에서도 비용을 획기적으로 절약할 수 있어. "서버 비용이 반으로 줄었어요" 같은 간증이 괜히 나오는 게 아니라고. 물론 첫 요청에 대한 응답이 살짝 느려지는 '콜드 스타트(Cold Start)'라는 단점이 있지만, 이건 Knative의 설정을 통해 최소 실행 인스턴스 수를 조절하는 식으로 완화할 수 있어.

🚦 전문가급 트래픽 관리 기능 기본 탑재

새로운 버전을 배포할 때마다 심장이 쫄깃했던 경험, 다들 있지? Knative Serving의 `Route`는 이런 걱정을 덜어줘. 복잡한 설정 없이 YAML 파일 몇 줄만 수정하면 **카나리 배포, 블루/그린 배포, A/B 테스팅** 같은 고급 배포 전략을 손쉽게 구현할 수 있어. "새 버전에 트래픽 1%만 보내서 테스트해보고, 문제없으면 10%, 50%, 100%로 점진적으로 늘려나가자" 같은 시나리오가 아주 간단해지는 거야. 이건 DevOps 엔지니어들이 사랑에 빠질 수밖에 없는 기능이지.

🧩 강력한 클라우드 네이티브 생태계와의 연동

Knative는 혼자가 아니야. CNCF(Cloud Native Computing Foundation) 생태계의 수많은 강력한 도구들과 찰떡궁합을 자랑해. 서비스 메시인 **Istio**, 모니터링의 표준인 **Prometheus**, 시각화 도구인 **Grafana**, 로그 수집기인 **Fluentd**, 분산 추적 시스템인 **Jaeger** 등과 아주 자연스럽게 통합돼. 덕분에 우리는 서버리스 애플리케이션의 상태를 아주 상세하게 관찰하고(Observability), 문제가 생겼을 때 빠르게 원인을 파악하고 대응할 수 있어.

이 정도면 Knative를 써야 할 이유, 충분히 납득되지? Knative는 단순히 '편리한 도구'를 넘어서, 개발 문화와 비즈니스 전략까지 긍정적으로 바꿀 수 있는 잠재력을 가진 플랫폼이야.


4. Knative vs 다른 애들 (간단 비교)

"Knative 좋은 건 알겠는데, 비슷한 다른 서비스들이랑은 뭐가 다른 거야?" 라는 궁금증이 생길 수 있어. 특히 대표적인 FaaS(Function-as-a-Service)와 다른 쿠버네티스 기반 서버리스 프레임워크와 비교해보자.

4.1. Knative vs AWS Lambda, Google Cloud Functions (FaaS)

FaaS는 서버리스의 원조 격이지. 개발자가 함수 코드만 올리면 알아서 실행해주니 정말 편리해. 하지만 Knative와는 몇 가지 근본적인 차이가 있어.

구분 Knative FaaS (e.g., AWS Lambda)
운영 주체 사용자 (Self-hosted)
쿠버네티스 클러스터는 직접 관리해야 함.
클라우드 제공업체 (Managed)
인프라에 전혀 신경 쓸 필요 없음.
이식성 매우 높음
모든 쿠버네티스 환경에서 동작. 벤더 종속 없음.
낮음
특정 클라우드 플랫폼에 강하게 종속됨.
워크로드 단위 컨테이너 (Container)
어떤 언어, 프레임워크, 라이브러리든 컨테이너로 만들 수만 있으면 OK.
함수 (Function)
제공업체가 지원하는 특정 런타임과 코드 구조를 따라야 함.
유연성/제어 높음
네트워킹, 스케일링 등 세부 설정을 직접 제어 가능.
낮음
제공업체가 정해준 규칙과 제약사항(실행 시간, 메모리 등)을 따라야 함.
누구에게 좋을까? 이미 쿠버네티스를 사용 중이고, 벤더 종속을 피하면서 더 많은 제어권을 원하는 팀. 인프라 관리에 전혀 신경 쓰고 싶지 않고, 빠르게 프로토타입을 만들거나 간단한 기능을 구현하고 싶은 팀.

결론적으로, **"최고의 편리함"**을 원한다면 FaaS가, **"최고의 유연성과 이식성"**을 원한다면 Knative가 더 나은 선택일 수 있어. 이건 정답이 있는 문제가 아니라, 우리 팀의 상황과 요구사항에 맞는 도구를 선택하는 트레이드오프의 문제야.

4.2. Knative vs OpenFaaS, Kubeless

Knative 외에도 쿠버네티스 위에서 서버리스를 구현하려는 프로젝트는 여럿 있었어. OpenFaaS나 Kubeless 같은 친구들이 대표적이지. 이들과 Knative의 가장 큰 차이점은 '철학'에 있어.

  • OpenFaaS/Kubeless: 이름에서 알 수 있듯이 'FaaS(Function-as-a-Service)'를 쿠버네티스 위에 구현하는 데 더 초점을 맞췄어. 개발자에게 함수 중심의 경험을 제공하는 것을 목표로 해.
  • Knative: 함수뿐만 아니라, 일반적인 웹 애플리케이션, API 서버 등 **모든 종류의 컨테이너**를 서버리스 방식으로 실행하는 '서버리스 컨테이너 플랫폼'을 지향해. 즉, 더 범용적이고 넓은 범위를 커버하지. 또한, Serving, Eventing 같은 기능들을 독립적인 '빌딩 블록'으로 제공해서, 사용자가 필요한 것만 골라 쓸 수 있도록 설계된 점이 달라.

현재 클라우드 네이티브 생태계에서는 구글, 레드햇 등 거대 기업들의 전폭적인 지지를 받는 Knative가 사실상의 표준(de facto standard)으로 자리 잡아가고 있는 분위기야.


5. 직접 만져보자! Knative 퀵스타트

이론은 충분히 배웠으니, 이제 직접 손맛을 볼 차례지? 내 로컬 PC에 Knative를 설치하고 'Hello World' 서비스를 띄워보는 과정을 간단하게 따라 해 보자. 여기서는 가장 간단한 방법으로 진행할 거야. 로컬 쿠버네티스 환경으로는 **Minikube**를 사용한다고 가정할게.

⚠️ 잠깐! 시작하기 전에
이 가이드는 개념 이해를 돕기 위한 최소한의 과정이야. 실제 운영 환경(Production)에 적용하려면 보안, 리소스, DNS 설정 등 훨씬 더 많은 것들을 고려해야 해. 만약 실제 프로젝트에 Knative 도입이 필요하다면, **재능넷** 같은 플랫폼에서 쿠버네티스 및 DevOps 전문가의 도움을 받는 것을 강력히 추천해. 전문가의 경험은 수많은 삽질의 시간을 아껴주거든!

1단계: Minikube 시작하기

먼저 넉넉한 리소스로 Minikube를 시작해야 해. Knative 컴포넌트들이 생각보다 메모리를 좀 먹거든.

minikube start --memory=8192 --cpus=4

2단계: Knative Operator 설치하기

Knative의 각 컴포넌트를 쉽게 설치하고 관리해주는 'Operator'를 먼저 설치할 거야.


# Operator 설치
kubectl apply -f https://github.com/knative/operator/releases/download/knative-v1.13.1/operator.yaml

3단계: Knative Serving 컴포넌트 설치하기

이제 Operator를 통해 Serving 컴포넌트를 설치하자. 아래와 같은 YAML 파일을 작성해. (`knative-serving.yaml`)


apiVersion: v1
kind: Namespace
metadata:
name: knative-serving
---
apiVersion: operator.knative.dev/v1beta1
kind: KnativeServing
metadata:
name: knative-serving
namespace: knative-serving

그리고 이 파일을 클러스터에 적용!

kubectl apply -f knative-serving.yaml

설치가 완료될 때까지 몇 분 정도 걸릴 수 있어. 아래 명령어로 설치 진행 상황을 확인할 수 있어.


kubectl get knativeserving.operator.knative.dev/knative-serving -n knative-serving --watch

4단계: 네트워킹 레이어(Kourier) 설치하기

Knative가 외부 트래픽을 받으려면 네트워킹 레이어가 필요해. 여기서는 Istio보다 가볍고 빠른 **Kourier**를 설치할 거야. Knative Operator 설정을 수정해서 Kourier를 활성화하자.


# KnativeServing 리소스를 편집 모드로 열기
kubectl edit knativeserving.operator.knative.dev/knative-serving -n knative-serving

# spec: 아래에 다음 내용을 추가하고 저장
# ...
spec:
ingress:
kourier:
enabled: true
# ...

5단계: DNS 설정하기 (Magic DNS: sslip.io)

원래는 실제 도메인을 설정해야 하지만, 로컬 테스트를 위해 외부 IP 주소를 도메인 이름으로 변환해주는 고마운 서비스인 `sslip.io`를 사용할 거야. 먼저 Kourier 서비스의 외부 IP를 확인하자.


# Kourier 서비스의 EXTERNAL-IP를 확인 (Pending 상태라면 잠시 기다리거나 minikube tunnel을 실행)
kubectl --namespace kourier-system get service kourier

# 만약 EXTERNAL-IP가 이면, 새 터미널을 열고 아래 명령 실행
minikube tunnel

이제 알아낸 IP 주소를 사용해서 Knative가 `sslip.io` 도메인을 사용하도록 설정하자.


# YOUR_EXTERNAL_IP 부분에 위에서 확인한 IP 주소를 넣으세요.
IP_ADDRESS=$(kubectl -n kourier-system get service kourier -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

# Knative의 기본 도메인 설정을 담은 ConfigMap을 수정
kubectl patch configmap/config-domain \
-n knative-serving \
--type merge \
-p '{"data":{"'${IP_ADDRESS}'.sslip.io":""}}'

6. 드디어! 첫 Knative 서비스 배포하기

모든 준비가 끝났어. 이제 맨 처음에 봤던 'helloworld-go' 서비스를 배포해보자. 아래 내용으로 `hello.yaml` 파일을 만들어.


apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld-go
spec:
template:
spec:
containers:
- image: gcr.io/knative-samples/helloworld-go
env:
- name: TARGET
value: "Knative on My Laptop!"

그리고 대망의 배포!

kubectl apply -f hello.yaml

서비스가 준비될 때까지 잠시 기다린 후, 서비스 정보를 확인해보자.

kubectl get kservice helloworld-go

출력 결과에 `URL` 항목이 보일 거야. 그게 바로 네 서비스의 주소야! 이제 `curl` 명령어로 호출해보자.


# 출력된 URL로 요청 보내기
curl $(kubectl get kservice helloworld-go -o jsonpath='{.status.url}')

# 예상 출력:
# Hello Knative on My Laptop!

축하해! 너는 방금 너의 로컬 PC에서 Knative를 이용해 서버리스 애플리케이션을 성공적으로 배포했어. 이제 몇 분 정도 아무 요청도 보내지 말고 기다려봐. 그리고 `kubectl get pod` 명령어로 Pod 상태를 확인하면, `helloworld-go` 서비스의 Pod가 사라진 것을 볼 수 있을 거야. 이게 바로 **Scale to Zero**! 다시 `curl`로 호출하면 Pod가 순식간에 다시 생겨나는 마법도 경험할 수 있지.


6. Knative, 실전에서는 어떻게 쓸까? (리얼 월드 유스케이스)

Knative는 단순한 장난감이 아니야. 이미 수많은 기업에서 핵심적인 워크로드를 처리하는 데 사용되고 있어. Knative가 빛을 발하는 몇 가지 대표적인 시나리오를 살펴보자.

시나리오 1: 확장성 있는 API 백엔드 서버

가장 일반적이면서도 강력한 사용 사례야. 우리가 만드는 대부분의 웹 서비스나 모바일 앱은 API 백엔드를 필요로 해. 이 API 서버를 Knative `Service`로 배포하는 거지.

  • 평소: 사용량이 적을 때는 최소한의 Pod만 유지하거나 아예 0으로 줄여서 비용을 아낀다.
  • 피크 타임: 갑자기 사용자가 몰리면(예: 마케팅 이벤트, TV 광고) Knative가 자동으로 Pod 수를 수십, 수백 개로 늘려서(Scale-out) 트래픽을 감당해낸다.
  • 배포: 새로운 API 버전을 배포할 때는 카나리 배포를 통해 1%의 사용자에게만 먼저 공개해서 안정성을 검증하고, 점진적으로 전체 사용자에게 확대한다.

시나리오 2: 비동기 이미지 처리 파이프라인

유저가 이미지를 업로드하는 서비스를 만든다고 상상해보자. 원본 이미지를 그대로 저장하면 용량도 크고, 썸네일도 필요하고, 워터마크도 박아야 해. 이 모든 작업을 동기적으로 처리하면 유저는 한참을 기다려야 할 거야. 이럴 때 Knative Eventing이 딱이지!

  1. (이벤트 발생) 유저가 웹서버를 통해 이미지를 S3 같은 스토리지에 업로드한다. S3는 '새 파일이 생성됨' 이벤트를 발생시킨다.
  2. (이벤트 수신) Knative의 `AWSS3Source`가 이 이벤트를 감지해서 `Broker`로 전달한다.
  3. (이벤트 분배) `Broker`는 이벤트를 여러 `Trigger`에게 보낸다.
    • `Trigger 1` (썸네일 생성용): 이벤트를 'thumbnail-generator' Knative `Service`로 보낸다.
    • `Trigger 2` (워터마크 삽입용): 이벤트를 'watermark-inserter' Knative `Service`로 보낸다.
    • `Trigger 3` (이미지 분석용): 이벤트를 'image-analyzer' Knative `Service`로 보낸다.
  4. (작업 처리) 각각의 Knative `Service`들은 필요할 때만 깨어나서(Scale from Zero) 각자의 작업을 처리하고 다시 잠든다.

이런 구조 덕분에 각 기능은 서로에게 전혀 영향을 주지 않고 독립적으로 개발, 배포, 확장될 수 있어. 정말 아름다운 아키텍처지?

시나리오 3: GitHub Webhook을 이용한 CI/CD 자동화

개발자가 `main` 브랜치에 코드를 푸시할 때마다 자동으로 테스트를 돌리고, 성공하면 스테이징 환경에 배포하는 파이프라인을 만들어보자. 이것도 Knative Eventing과 Tekton을 조합하면 환상적으로 구현할 수 있어.

  1. (이벤트 발생) 개발자가 `git push`를 하면 GitHub이 설정된 Webhook URL로 `push` 이벤트를 보낸다.
  2. (이벤트 수신) Knative의 `GitHubSource`가 이 이벤트를 받아서 `Broker`로 전달한다.
  3. (파이프라인 실행) `Trigger`가 `main` 브랜치에 대한 `push` 이벤트만 필터링해서, 이벤트를 Tekton 파이프라인을 실행시키는 `Sink`로 보낸다.
  4. (빌드/테스트/배포) Tekton `PipelineRun`이 생성되고, 정의된 `Task`들에 따라 소스 코드를 체크아웃하고, 빌드하고, 유닛 테스트를 실행하고, 모든 게 성공하면 최종적으로 Knative `Service`를 업데이트해서 새로운 버전을 배포한다.

이 모든 과정이 완전 자동으로 일어나! 개발자는 그냥 코드 짜고 푸시만 하면 되는 거야. 이런 환경에서 일하면 개발 효율이 얼마나 올라갈지 상상만 해도 즐겁지 않아?

물론 이런 복잡한 파이프라인을 처음부터 혼자 구축하는 것은 쉽지 않을 수 있어. 그럴 땐 주저하지 말고 도움을 구하는 게 현명해. 예를 들어 **재능넷**과 같은 플랫폼에는 이런 클라우드 네이티브 기술에 능숙한 프리랜서 전문가들이 많이 활동하고 있으니, 프로젝트의 필요에 따라 기술 자문을 받거나 구축을 의뢰하는 것도 좋은 방법이야.


7. 미래를 향하여: Knative의 다음 스텝과 우리의 자세

Knative는 이제 막 걸음마를 뗀 프로젝트가 아니야. 2022년에 CNCF 인큐베이팅 프로젝트로 선정되었고, 수많은 실제 운영 환경에서 검증을 거치며 꾸준히 성숙해왔어. Knative의 미래는 더욱 밝아 보여.

특히 최근에는 **Knative Functions**라는 프로젝트가 주목받고 있어. 이건 개발자 경험을 한 단계 더 끌어올리기 위한 노력의 일환이야. `kn func`라는 CLI 도구를 통해, 개발자는 Dockerfile이나 YAML 파일을 직접 작성할 필요 없이, 특정 언어로 된 함수 코드만 작성하면 바로 Knative 서비스로 빌드하고 배포할 수 있게 돼. AWS 람다 같은 FaaS의 간결한 개발 경험과 Knative의 유연성 및 이식성을 모두 잡으려는 시도지.

서버리스의 패러다임은 'FaaS'에서 출발해, 이제 Knative가 이끄는 **'서버리스 컨테이너'**의 시대로 넘어가고 있어. 기존의 모든 애플리케이션을 함수 단위로 쪼개는 건 현실적으로 어렵지만, 컨테이너 단위로 패키징하는 것은 훨씬 쉽고 자연스럽기 때문이야. Knative는 바로 이 '서버리스 컨테이너'라는, 가장 현실적이면서도 강력한 서버리스 모델의 중심에 서 있어.

오늘 우리는 Knative라는 아주 매력적인 기술에 대해 깊이 있게 알아봤어. 쿠버네티스의 복잡함에 가려져 있던 서버리스의 진정한 잠재력을 깨워주는 열쇠가 바로 Knative라는 걸 느꼈을 거야. 물론 Knative가 모든 문제의 해결책인 '만병통치약'은 아니야. 하지만 쿠버네티스 기반의 현대적인 클라우드 네이티브 환경을 구축하려는 개발자나 조직에게 Knative는 분명히 고려해볼 가치가 있는, 아니 반드시 알아야 할 필수 교양과목이 되었어.

그러니 망설이지 마. 오늘 배운 내용을 바탕으로 너의 로컬 환경에서 Knative를 직접 만져보고, 작은 토이 프로젝트부터 시작해봐. 그렇게 한 걸음씩 나아가다 보면, 어느새 너는 쿠버네티스 위에서 서버리스를 자유자재로 다루는 '힙한' 개발자가 되어 있을 거야. 자, 이제 너의 코딩에 서버리스라는 날개를 달아줄 시간이야!

댓글 작성

이 글에 대한 여러분의 생각을 들려주세요

댓글 0