Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions docs/2025-12-13-k8s-gateway-api/gabiacloud.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Gabiacloud

- [로드 밸런서 사용하기](https://customer.gabia.com/manual/cloud/23381/24281)
- [nginx.yml](./nginx.yml)

`nginx.service`는 `clusterIp`로 기본적으로 노출되는 것이 아니라, `NodePort`로 control-plane에 노출됨.


## TODO

- [ ] gabiacloud TLS 인증서를 어떻게 연결하는지

```mermaid
sequenceDiagram
autonumber
actor Client as External Client
participant LB as nginx-service (Service: LoadBalancer, EXTERNAL-IP)
participant Nginx as NGINX Pods (nginx-deployment)
participant EGW as Envoy Gateway Proxy (Service: ClusterIP)
participant GWAPI as Gateway API (Gateway/HTTPRoute/GRPCRoute)
participant SVC as Backend Service (ClusterIP)
participant POD as Backend Pods

Client->>LB: 1) TCP 443 (or 80) to EXTERNAL-IP
LB->>Nginx: 2) L4 forward to targetPort (NGINX Pod)
Note over Nginx: TLS termination happens here\n(nginx has cert/key)

Nginx->>EGW: 3) HTTP request proxied to Envoy Proxy Service (ClusterIP:80)
Note over Nginx,EGW: Preserve Host header for HTTPRoute.hostnames\nAdd X-Forwarded-* headers

EGW->>GWAPI: 4) Match Gateway listener + Route rules\n(host/path/headers or gRPC methods)
GWAPI->>SVC: 5) Select backendRef (Service:port)
SVC->>POD: 6) Kube-proxy routes to one Pod endpoint

POD-->>SVC: 7) Response
SVC-->>EGW: 8) Response
EGW-->>Nginx: 9) Response (HTTP)
Nginx-->>LB: 10) Response (HTTPS re-encrypted to client)
LB-->>Client: 11) HTTPS response
```
40 changes: 40 additions & 0 deletions docs/2025-12-13-k8s-gateway-api/nginx.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---

apiVersion: v1
kind: Service
metadata:
name: nginx-service
annotations:
loadbalancer.openstack.org/flavor-id: adc12270-f56a-4ef1-bb00-429aad71ef6e
loadbalancer.openstack.org/availability-zone: KR1-Zone1-LB
loadbalancer.openstack.org/enable-health-monitor: "true"
service.beta.kubernetes.io/openstack-internal-load-balancer: "false"
# SSL 인증서 콘솔에서 등록이 필요함.
loadbalancer.openstack.org/default-tls-container-ref: "https://external.gabiacloud.com:9311/v1/secrets/88750a57-9a44-41d5-bc89-602ab2b131f8"
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- port: 443
protocol: TCP
targetPort: 80
12 changes: 12 additions & 0 deletions docs/2025-12-13-k8s-gateway-api/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# K8s Gateway API 적용

## 적용 대상

- gabiacloud managed k8s 환경
- local k8s

| 항목 | EKS | 직접 구성 | 로컬 |
|----|---------|-------|----|
| LB | AWS NLB | | |
| | | | |
| | | | |
13 changes: 13 additions & 0 deletions docs/2025-12-13-k8s-gateway-api/개념.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Gateway API

## GatewayClass (클러스터 공용)

클러스터에 어떤 **Gateway 컨트롤러**를 쓸 것인가?

## Gateway

외부 트래픽이 들어오는 **엔드포인트(주소/포트/TLS)** 를 어떻게 열 것인가?



## CRD
86 changes: 86 additions & 0 deletions docs/k8s/crd.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# CRD (Custom Resource Definition)

## 1. 무엇인가?

Kubernetes에 새로운 리소스 타입(API 오브젝트) 을 사용자 정의로 추가하는 메커니즘.

Pod, Service, Deployment 같은 기본 리소스처럼
`kubectl get xxx, kubectl apply -f`로 다룰 수 있는 나만의 리소스 종류를 만드는 방법.

한 줄로 요약하면, **CRD = Kubernetes API를 확장하는 공식적인 방법**

## 2. 목적

고수준 도메인 개념을 하나의 리소스로 표현하고 컨트롤러가 그 의미를 구현하도록 만듭니다.

- 고수준 도메인 개념: `이 앱은 외부 노출 + TLS + WAF`, `이 데이터베이스는 자동 백업 + 복제 정책이 필요함`

## 3. 구조: "정의"와 "인스턴스"의 분리

### 3.1 CRD(Definition)

- “이런 종류의 리소스가 있다”를 API 서버에 등록
- 스키마(OpenAPI), 버전(v1alpha1/v1beta1/v1) 포함

```yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: widgets.example.com
spec:
group: example.com
names:
kind: Widget
plural: widgets
scope: Namespaced
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
size:
type: string
```

→ 이 시점부터 K8s는 Widget 이라는 리소스를 알게 됨

### 3.2 CR(Instance)

CRD로 정의된 실제 객체, Pod/Service처럼 생성/삭제/조회 가능

```yaml
apiVersion: example.com/v1
kind: Widget
metadata:
name: my-widget
spec:
size: large
```

→ 하지만 이 자체로는 아무 일도 일어나지 않음

### 3.3 Controller

CRD는 “명세(계약)”일 뿐이고, 실제 동작은 Controller가 구현

특정 CR을 감시(watch)하다가 CR의 spec을 읽고 실제 K8s 리소스(Pod, Service, ConfigMap 등)를 생성/수정 및 현제 상태를 `status`에 반영

#### 흐름 요약

```text
CR 생성
API Server 저장
Controller가 감지
원하는 상태(spec)를 실제 리소스로 구현
결과를 status에 기록
```
Loading