μλΉμ€ λ©μκ° ν΅ν©λ Python API κ²μ΄νΈμ¨μ΄ κ°λ°μ νꡬν©λλ€. λ§μ΄ν¬λ‘μλΉμ€, λΌμ°ν , μΈμ¦, κ΄μ°° κ°λ₯μ±μ λν΄ μ λ°μ μΈ κ΄μ μμ νμ΅νμΈμ.
Python API Gateway: νλ μν€ν μ²λ₯Ό μν μλΉμ€ λ©μ ꡬν
μ€λλ λΉ λ₯΄κ² λ°μ νλ λμ§νΈ νκ²½μμ λ§μ΄ν¬λ‘μλΉμ€ μν€ν μ²λ νμ₯ κ°λ₯νκ³ λ³΅μλ ₯μ΄ λ°μ΄λλ©° μ μ§ κ΄λ¦¬ κ°λ₯ν μ ν리μΌμ΄μ μ ꡬμΆνλ νμ€μ΄ λμμ΅λλ€. μ΄λ¬ν μν€ν μ²μ ν΅μ¬μ μλΉμ€ κ°μ ν¨μ¨μ μ΄κ³ μμ ν ν΅μ μ λν νμμ±μ λλ€. λ°λ‘ μ΄ μ§μ μμ API κ²μ΄νΈμ¨μ΄μ μλΉμ€ λ©μκ° μ€μν μν μ ν©λλ€. μ΄ κΈμμλ Python κΈ°λ° API κ²μ΄νΈμ¨μ΄λ₯Ό ꡬμΆνκ³ μ΄λ₯Ό μλΉμ€ λ©μμ ν΅ν©νμ¬ μ μΈκ³μ μΈ λ§₯λ½μμ λ§μ΄ν¬λ‘μλΉμ€ ν΅μ μ κ΄λ¦¬νκΈ° μν κ°λ ₯ν μ루μ μ μ 곡νλ λ°©λ²μ μ΄ν΄λ΄ λλ€.
API κ²μ΄νΈμ¨μ΄ λ° μλΉμ€ λ©μ μ΄ν΄
API κ²μ΄νΈμ¨μ΄λ 무μμΈκ°μ?
API κ²μ΄νΈμ¨μ΄λ λ§μ΄ν¬λ‘μλΉμ€ λ°±μλμ λν λͺ¨λ ν΄λΌμ΄μΈνΈ μμ²μ λ¨μΌ μ§μ μ μν μ ν©λλ€. λ€μκ³Ό κ°μ μμ μ μ²λ¦¬ν©λλ€:
- λΌμ°ν : μμ²μ μ μ ν λ§μ΄ν¬λ‘μλΉμ€λ‘ μ λ¬ν©λλ€.
- μΈμ¦ λ° κΆν λΆμ¬: ν΄λΌμ΄μΈνΈμ μ μμ νμΈνκ³ νμν κΆνμ΄ μλμ§ νμΈν©λλ€.
- μλ μ ν: μ€μ©μ λ°©μ§νκ³ μλΉμ€μ 곡μ ν μ¬μ©μ 보μ₯ν©λλ€.
- μμ² λ³ν: λ°±μλλ‘ λ³΄λ΄κΈ° μ μ μμ²μ μμ ν©λλ€.
- μλ΅ μ§κ³: μ¬λ¬ λ§μ΄ν¬λ‘μλΉμ€μ μλ΅μ λ¨μΌ μλ΅μΌλ‘ κ²°ν©ν©λλ€.
- μΊμ±: λκΈ° μκ°μ μ€μ΄κ³ μ±λ₯μ ν₯μμν΅λλ€.
μ΄λ₯Ό μ ν리μΌμ΄μ μ μ κ΅ν μ μμμ΄λΌκ³ μκ°ν΄λ³΄μΈμ. λͺ¨λ λ€μ΄μ€λ νΈλν½μ μ²λ¦¬νκ³ μμ νκ³ ν¨μ¨μ μΌλ‘ μ¬λ°λ₯Έ λͺ©μ μ§μ λλ¬νλλ‘ λ³΄μ₯ν©λλ€. μλ₯Ό λ€μ΄, νΈμ£Όμ μλ λͺ¨λ°μΌ μ ν리μΌμ΄μ μ΄ API κ²μ΄νΈμ¨μ΄λ‘ μμ²μ 보λ΄λ©΄, κ²μ΄νΈμ¨μ΄λ μ΄λ₯Ό μ±κ°ν¬λ₯΄μ μλ κ°κ²© μ± μ μλΉμ€μ λ μΌμ μλ μ¬κ³ μλΉμ€λ‘ λΌμ°ν νκ³ , κ·Έ κ²°κ³Όλ₯Ό μ§κ³νμ¬ μ¬μ©μμκ² λ°νν©λλ€.
μλΉμ€ λ©μλ 무μμΈκ°μ?
μλΉμ€ λ©μλ λ§μ΄ν¬λ‘μλΉμ€ μν€ν μ² λ΄μμ μλΉμ€ κ° ν΅μ μ μ²λ¦¬νλ μΈνλΌ κ³μΈ΅μ λλ€. λ€μκ³Ό κ°μ κΈ°λ₯μ μ 곡ν©λλ€:
- μλΉμ€ λμ€μ»€λ²λ¦¬: μλΉμ€μ μ¬μ© κ°λ₯ν μΈμ€ν΄μ€λ₯Ό μλμΌλ‘ μ°Ύμ΅λλ€.
- νΈλν½ κ΄λ¦¬: λ‘λ λ°Έλ°μ±, λΌμ°ν λ° μν· λΈλ μ΄νΉμ ν¬ν¨νμ¬ μλΉμ€ κ°μ νΈλν½ νλ¦μ μ μ΄ν©λλ€.
- κ΄μ°° κ°λ₯μ±: μλΉμ€μ μ±λ₯ λ° μνμ λν ν΅μ°°λ ₯μ μ 곡ν©λλ€.
- 보μ: μλΉμ€ κ° ν΅μ μ μνΈννκ³ λ³΄μ μ μ± μ μ μ©ν©λλ€.
μλΉμ€ λ©μλ μΌλ°μ μΌλ‘ μ μ΄ νλ μΈ(μ: Istio)κ³Ό λ°μ΄ν° νλ μΈ(μ: Envoy)μΌλ‘ ꡬμ±λ©λλ€. λ°μ΄ν° νλ μΈμ λͺ¨λ μλΉμ€ κ° ν΅μ μ κ°λ‘μ±κ³ μ μ΄ νλ μΈμ μν΄ μ μλ μ μ± μ μ μ©ν©λλ€. λͺ¨λ λ΄λΆ ν΅μ μ μ²λ¦¬νμ¬ λ©μκ° μμ νκ³ μμ μ μ΄λ©° ν¨μ¨μ μΌλ‘ μ λ¬λλλ‘ νλ 보μ΄μ§ μλ νλ°° λ€νΈμν¬λ₯Ό μμν΄ λ³΄μΈμ. μλΉμ€ λ©μλ κΈ°λ³Έμ μΌλ‘ μ λ‘ νΈλ¬μ€νΈ λ€νΈμνΉμ κ°λ₯νκ² ν©λλ€. μ¦, λͺ¨λ μλΉμ€λ μμΉμ κ΄κ³μμ΄ λ€λ₯Έ λͺ¨λ μλΉμ€λ₯Ό μΈμ¦ν©λλ€. μ΄λ μ¬λ¬ μ§μμ μλΉμ€κ° λΆμ°λ λ€κ΅μ κΈ°μ μμ νΉν μ€μν©λλ€.
API κ²μ΄νΈμ¨μ΄μ μλΉμ€ λ©μλ₯Ό κ²°ν©νλ μ΄μ
API κ²μ΄νΈμ¨μ΄μ μλΉμ€ λ©μ λͺ¨λ λ§μ΄ν¬λ‘μλΉμ€ ν΅μ μ μ²λ¦¬νμ§λ§, μλ‘ λ€λ₯Έ κ³μΈ΅μμ μλνλ©° λ€λ₯Έ λ¬Έμ λ₯Ό ν΄κ²°ν©λλ€. API κ²μ΄νΈμ¨μ΄λ μΈλΆ νΈλν½ κ΄λ¦¬μ μ€μ μ λλ λ°λ©΄, μλΉμ€ λ©μλ λ΄λΆ νΈλν½ κ΄λ¦¬μ μ€μ μ λ‘λλ€. μ΄ λμ κ²°ν©νλ©΄ ν΄λ¬μ€ν° λ΄λΆμ μΈλΆ λͺ¨λμμ λ§μ΄ν¬λ‘μλΉμ€ ν΅μ μ 보νΈ, κ΄λ¦¬ λ° κ΄μ°°νκΈ° μν ν¬κ΄μ μΈ μ루μ μ μ 곡ν©λλ€.
μλ₯Ό λ€μ΄, μ μ μκ±°λ νλ«νΌμ μκ°ν΄ λ΄ μλ€. API κ²μ΄νΈμ¨μ΄λ μΉ λ° λͺ¨λ°μΌ μ ν리μΌμ΄μ μ μμ²μ μ²λ¦¬νκ³ , μ¬μ©μλ₯Ό μΈμ¦νκ³ , μλ μ νμ μ μ©νλ©°, μ μ ν λ°±μλ μλΉμ€λ‘ μμ²μ λΌμ°ν ν©λλ€. μλΉμ€ λ©μλ λ°±μλ μλΉμ€ κ°μ ν΅μ μ κ΄λ¦¬νμ¬ μ ν μΉ΄νλ‘κ·Έ, μ£Όλ¬Έ κ΄λ¦¬ λ° κ²°μ μ²λ¦¬ μλΉμ€ κ°μ μμ νκ³ μ λ’°ν μ μλ ν΅μ μ 보μ₯ν©λλ€. API κ²μ΄νΈμ¨μ΄λ Okta λλ Auth0κ³Ό κ°μ μΈλΆ μΈμ¦ μλΉμ€λ₯Ό μ¬μ©ν μ μμΌλ©°, μλΉμ€ λ©μλ μνΈ TLS(mTLS)λ₯Ό μ¬μ©νμ¬ λ΄λΆ μλΉμ€ κ°μ μμ ν ν΅μ μ 보μ₯ν©λλ€.
Python API κ²μ΄νΈμ¨μ΄ ꡬμΆ
νλΆν λΌμ΄λΈλ¬λ¦¬ λ° νλ μμν¬ μνκ³λ₯Ό κ°μΆ Pythonμ API κ²μ΄νΈμ¨μ΄λ₯Ό ꡬμΆνλ λ° νμν μ νμ λλ€. νμ₯ κ°λ₯νκ³ μ μ§ κ΄λ¦¬ κ°λ₯ν κ²μ΄νΈμ¨μ΄λ₯Ό λ§λ€κΈ° μν΄ μ¬λ¬ νλ μμν¬λ₯Ό μ‘°ν©νμ¬ μ¬μ©ν κ²μ λλ€.
νλ μμν¬ μ ν
- FastAPI: API ꡬμΆμ μν νλμ μ΄κ³ κ³ μ±λ₯ μΉ νλ μμν¬μ λλ€. FastAPIλ μλ λ°μ΄ν° μ ν¨μ± κ²μ¬, μ§λ ¬ν λ° λ¬Έμ μμ±μ μ 곡ν©λλ€.
- Uvicorn: λΉλκΈ° Python μ ν리μΌμ΄μ μ€νμ μν ASGI μλ²μ λλ€.
- Requests: λ°±μλ μλΉμ€μ HTTP μμ²μ 보λ΄κΈ° μν λΌμ΄λΈλ¬λ¦¬μ λλ€. λ 볡μ‘ν μλ리μ€μ κ²½μ° λΉλκΈ° μ§μμ μ 곡νλ `httpx` μ¬μ©μ κ³ λ €νμμμ€.
- PyJWT: μΈμ¦μ μν JSON μΉ ν ν°(JWT) μμ μ μν λΌμ΄λΈλ¬λ¦¬μ λλ€.
νλ‘μ νΈ κ΅¬μ‘°
api_gateway/ βββ main.py # λ©μΈ μ ν리μΌμ΄μ νμΌ βββ config.py # κ΅¬μ± μ€μ βββ routes.py # API λΌμ°ν μ μ βββ auth.py # μΈμ¦ λ‘μ§ βββ utils.py # μ νΈλ¦¬ν° ν¨μ βββ requirements.txt # νλ‘μ νΈ μ’ μμ±
μμ μ½λ: main.py
from fastapi import FastAPI, Depends, HTTPException, Request
from fastapi.responses import JSONResponse
import uvicorn
import requests
import jwt
from config import settings
from auth import verify_jwt
from routes import router
app = FastAPI()
app.include_router(router)
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
response = await call_next(request)
return response
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
μμ μ½λ: routes.py
from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.responses import JSONResponse
import requests
import jwt
from config import settings
from auth import verify_jwt
router = APIRouter()
@router.get("/products/{product_id}")
async def get_product(product_id: int, request: Request, is_authenticated: bool = Depends(verify_jwt)):
# μ ν μλΉμ€λ‘ μμ² μ λ¬
product_service_url = f"{settings.product_service_url}/products/{product_id}"
try:
response = requests.get(product_service_url)
response.raise_for_status() # 4xx λλ 5xx μ€λ₯ μλ΅μ λν΄ HTTPError λ°μ
return response.json()
except requests.exceptions.RequestException as e:
raise HTTPException(status_code=500, detail=f"μ ν μλΉμ€μ ν΅μ μ€ μ€λ₯ λ°μ: {e}")
@router.post("/orders")
async def create_order(request: Request, is_authenticated: bool = Depends(verify_jwt)):
# μ£Όλ¬Έ μλΉμ€λ‘ μμ² μ λ¬
order_service_url = f"{settings.order_service_url}/orders"
body = await request.json()
try:
response = requests.post(order_service_url, json=body)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
raise HTTPException(status_code=500, detail=f"μ£Όλ¬Έ μλΉμ€μ ν΅μ μ€ μ€λ₯ λ°μ: {e}")
μμ μ½λ: auth.py
from fastapi import HTTPException, Depends, Header
import jwt
from config import settings
from typing import Optional
async def verify_jwt(authorization: Optional[str] = Header(None)) -> bool:
if not authorization:
raise HTTPException(status_code=401, detail="Authorization headerκ° νμν©λλ€")
try:
token = authorization.split(" ")[1]
jwt.decode(token, settings.jwt_secret, algorithms=[settings.jwt_algorithm])
return True
except jwt.ExpiredSignatureError:
raise HTTPException(status_code=401, detail="ν ν°μ΄ λ§λ£λμμ΅λλ€")
except jwt.InvalidTokenError:
raise HTTPException(status_code=401, detail="μ ν¨νμ§ μμ ν ν°μ
λλ€")
μμ μ½λ: config.py
import os
from typing import Optional
from pydantic import BaseSettings
class Settings(BaseSettings):
product_service_url: str = os.getenv("PRODUCT_SERVICE_URL", "http://localhost:8001")
order_service_url: str = os.getenv("ORDER_SERVICE_URL", "http://localhost:8002")
jwt_secret: str = os.getenv("JWT_SECRET", "secret")
jwt_algorithm: str = os.getenv("JWT_ALGORITHM", "HS256")
settings = Settings()
ꡬμ±
λ°±μλ μλΉμ€ URL λ° μΈμ¦ ν€μ κ°μ κ΅¬μ± μ€μ μ λ³λμ κ΅¬μ± νμΌ(μ: `config.py`)μ μ μ₯ν©λλ€. νκ²½ λ³μλ₯Ό μ¬μ©νμ¬ κ°λ°, μ€ν μ΄μ§, νλ‘λμ λ± λ€μν νκ²½μ ꡬμ±ν©λλ€.
μΈμ¦
JWTλ₯Ό μ¬μ©νμ¬ μΈμ¦μ ꡬνν©λλ€. API κ²μ΄νΈμ¨μ΄λ μμ²μ λ°±μλ μλΉμ€λ‘ μ λ¬νκΈ° μ μ JWTλ₯Ό νμΈν©λλ€. μ΄ μ κ·Ό λ°©μμ 보μ λ° λΆμ°νλ₯Ό μ΄μ§ν©λλ€. λκ·λͺ¨ μ‘°μ§μ κ²½μ° Keycloak λλ Azure ADμ κ°μ ID 곡κΈμμμ ν΅ν©μ κ³ λ €νμμμ€. μ΄λ₯Ό ν΅ν΄ μΈμ¦ λ° κΆν λΆμ¬ μ μ± μ μ€μ μ§μ€νν μ μμ΅λλ€.
λΌμ°ν
λ³λμ νμΌ(μ: `routes.py`)μ κ²½λ‘λ₯Ό μ μν©λλ€. FastAPIμ λΌμ°ν° κΈ°λ₯μ μ¬μ©νμ¬ λ€μ΄μ€λ μμ²μ μ μ ν λ°±μλ μλΉμ€μ λ§€νν©λλ€. μμ² κ²½λ‘, HTTP λ©μλ λ° ν€λλ₯Ό κΈ°λ°μΌλ‘ λΌμ°ν μ ꡬνν©λλ€.
μμ : API κ²μ΄νΈμ¨μ΄ λ컀ν
API κ²μ΄νΈμ¨μ΄λ₯Ό 컨ν μ΄λλ‘ ν¨ν€μ§νκΈ° μν΄ `Dockerfile`μ μμ±ν©λλ€.
FROM python:3.9-slim-buster WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
μλΉμ€ λ©μ ν΅ν©
Python API κ²μ΄νΈμ¨μ΄λ₯Ό Istioμ κ°μ μλΉμ€ λ©μμ ν΅ν©νλ©΄ 보μ, κ΄μ°° κ°λ₯μ± λ° νΈλν½ κ΄λ¦¬κ° ν₯μλ©λλ€. API κ²μ΄νΈμ¨μ΄λ₯Ό ν΅ν΄ νλ₯΄λ νΈλν½μ κ΄λ¦¬νλλ‘ Istioλ₯Ό ꡬμ±νλ λ°©λ²μ μ€μ μ λ κ²μ λλ€.
Istio μ€μΉ
μ§ννκΈ° μ μ Kubernetes ν΄λ¬μ€ν°μ Istioκ° μ€μΉλμ΄ μλμ§ νμΈνμμμ€. μ€μΉ μ§μΉ¨μ 곡μ Istio λ¬Έμλ₯Ό μ°Έμ‘°νμμμ€. AWS, Google Cloud λ° Azureμ κ°μ λ§μ ν΄λΌμ°λ μ 곡μ 체λ λ°°ν¬ λ° κ΄λ¦¬λ₯Ό λ¨μννλ κ΄λ¦¬ν Istio μλΉμ€λ₯Ό μ 곡ν©λλ€.
μ¬μ΄λμΉ΄ μ£Όμ
Istioλ μ¬μ΄λμΉ΄ νλ‘μ(Envoy)λ₯Ό μ¬μ©νμ¬ μλΉμ€λ‘ λ€μ΄μ€κ³ λκ°λ λͺ¨λ νΈλν½μ κ°λ‘μ±λλ€. API κ²μ΄νΈμ¨μ΄μ Istioλ₯Ό μ¬μ©νλ €λ©΄ API κ²μ΄νΈμ¨μ΄μ νλμ μ¬μ΄λμΉ΄ νλ‘μλ₯Ό μ£Όμ ν΄μΌ ν©λλ€. μ΄λ μΌλ°μ μΌλ‘ νλ λ°°ν¬μ μ΄λ Έν μ΄μ μ μΆκ°νμ¬ μνλ©λλ€:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-gateway
labels:
app: api-gateway
spec:
replicas: 1
selector:
matchLabels:
app: api-gateway
template:
metadata:
labels:
app: api-gateway
annotations:
sidecar.istio.io/inject: "true" # Istio μ¬μ΄λμΉ΄ μ£Όμ
νμ±ν
spec:
containers:
- name: api-gateway
image: your-api-gateway-image:latest
ports:
- containerPort: 8000
κ°μ μλΉμ€ λ° κ²μ΄νΈμ¨μ΄
Istioλ νΈλν½ λΌμ°ν μ κ΄λ¦¬νκΈ° μν΄ κ°μ μλΉμ€μ κ²μ΄νΈμ¨μ΄λ₯Ό μ¬μ©ν©λλ€. κ²μ΄νΈμ¨μ΄λ λ©μλ‘ λ€μ΄μ€λ νΈλν½μ μ§μ μ μ μ μνκ³ , κ°μ μλΉμ€λ λ©μ λ΄μ μλΉμ€λ‘ νΈλν½μ΄ λΌμ°ν λλ λ°©μμ μ μν©λλ€.
Istio κ²μ΄νΈμ¨μ΄ μμ±
API κ²μ΄νΈμ¨μ΄λ₯Ό μΈλΆ νΈλν½μ λ ΈμΆνκΈ° μν΄ Istio κ²μ΄νΈμ¨μ΄λ₯Ό μ μν©λλ€.
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: api-gateway-gateway
spec:
selector:
istio: ingressgateway # Istioμ κΈ°λ³Έ μΈκ·Έλ μ€ κ²μ΄νΈμ¨μ΄ μ¬μ©
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*" # λλ©μΈμΌλ‘ κ΅μ²΄
κ°μ μλΉμ€ μμ±
κ²μ΄νΈμ¨μ΄μμ API κ²μ΄νΈμ¨μ΄ μλΉμ€λ‘ νΈλν½μ λΌμ°ν νκΈ° μν κ°μ μλΉμ€λ₯Ό μ μν©λλ€.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: api-gateway-virtualservice
spec:
hosts:
- "*" # λλ©μΈμΌλ‘ κ΅μ²΄
gateways:
- api-gateway-gateway
http:
- route:
- destination:
host: api-gateway # Kubernetesμ μλΉμ€ μ΄λ¦
port:
number: 8000 # API κ²μ΄νΈμ¨μ΄κ° μμ λκΈ°νλ ν¬νΈ
Istioλ₯Ό μ¬μ©ν νΈλν½ κ΄λ¦¬
Istioλ λ€μκ³Ό κ°μ κ°λ ₯ν νΈλν½ κ΄λ¦¬ κΈ°λ₯μ μ 곡ν©λλ€:
- λ‘λ λ°Έλ°μ±: μλΉμ€μ μ¬λ¬ μΈμ€ν΄μ€μ νΈλν½μ λΆμ°ν©λλ€. Istioλ λΌμ΄λ λ‘λΉ, μ΅μ μ°κ²° λ° μΌκ΄λ ν΄μ±μ ν¬ν¨ν λ€μν λ‘λ λ°Έλ°μ± μκ³ λ¦¬μ¦μ μ§μν©λλ€.
- νΈλν½ λΆν (μΉ΄λ리 λ°°ν¬): μ λ²μ μ μλΉμ€μ μλμ νΈλν½μ 보λ΄μ΄ μ μ§μ μΌλ‘ μ λ²μ μ λ‘€μμν©λλ€. μ΄λ₯Ό ν΅ν΄ λͺ¨λ μ¬μ©μμκ² μν₯μ μ£Όμ§ μκ³ νλ‘λμ μμ μ κΈ°λ₯μ ν μ€νΈν μ μμ΅λλ€.
- μν· λΈλ μ΄νΉ: λΉμ μμ μΈ μλΉμ€λ‘μ νΈλν½μ μλμΌλ‘ μ€μ§νμ¬ μ°μ μ€ν¨λ₯Ό λ°©μ§ν©λλ€.
- κ²°ν¨ μ£Όμ : μ ν리μΌμ΄μ μ 볡μλ ₯μ ν μ€νΈνκΈ° μν΄ νΈλν½μ μ§μ° λλ μ€λ₯λ₯Ό μ£Όμ ν©λλ€.
μμ : Istioλ₯Ό μ¬μ©ν μΉ΄λ리 λ°°ν¬
μΉ΄λ리 λ°°ν¬λ₯Ό μννλ €λ©΄ Istioλ₯Ό ꡬμ±νμ¬ API κ²μ΄νΈμ¨μ΄μ μ λ²μ μ μλμ νΈλν½(μ: 10%)μ λ³΄λΌ μ μμ΅λλ€.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: api-gateway-virtualservice
spec:
hosts:
- "*" # λλ©μΈμΌλ‘ κ΅μ²΄
gateways:
- api-gateway-gateway
http:
- route:
- destination:
host: api-gateway # λ²μ 1
port:
number: 8000
weight: 90
- destination:
host: api-gateway-v2 # λ²μ 2 (μΉ΄λ리)
port:
number: 8000
weight: 10
κ΄μ°° κ°λ₯μ±
λͺ¨λν°λ§ λ° λ‘κΉ μ API κ²μ΄νΈμ¨μ΄ λ° λ°±μλ μλΉμ€μ μ±λ₯κ³Ό μνλ₯Ό μ΄ν΄νλ λ° μ€μν©λλ€. λ€μκ³Ό κ°μ λꡬλ₯Ό μ¬μ©νμ¬ ν¬κ΄μ μΈ κ΄μ°° κ°λ₯μ±μ ꡬννμμμ€:
- Prometheus: λ©νΈλ¦μ μμ§νκ³ μ μ₯νλ λͺ¨λν°λ§ μμ€ν μ λλ€. Istioλ Prometheusμ ν΅ν©λμ΄ μλΉμ€ νΈλν½, μ§μ° μκ° λ° μ€λ₯μ λν λ©νΈλ¦μ μ 곡ν©λλ€.
- Grafana: μ ν리μΌμ΄μ μ λͺ¨λν°λ§νκΈ° μν λμ보λλ₯Ό μμ±νλ λ°μ΄ν° μκ°ν λꡬμ λλ€.
- Jaeger: λ§μ΄ν¬λ‘μλΉμ€λ₯Ό ν΅ν΄ νλ₯΄λ μμ²μ μΆμ νκΈ° μν λΆμ° μΆμ μμ€ν μ λλ€. Istioλ λͺ¨λ μλΉμ€ κ° ν΅μ μ λν μΆμ μ μλμΌλ‘ μμ±ν μ μμ΅λλ€.
- Fluentd/Elasticsearch/Kibana (EFK μ€ν): λ‘κ·Έλ₯Ό μμ§, μ μ₯ λ° λΆμνκΈ° μν λ‘κΉ μ€νμ λλ€.
Istio ν λ λ©νΈλ¦¬
Istioλ λ©νΈλ¦, λ‘κ·Έ λ° μΆμ μ ν¬ν¨νμ¬ μλΉμ€ νΈλν½μ λν ν λ λ©νΈλ¦¬ λ°μ΄ν°λ₯Ό μλμΌλ‘ μμ§ν©λλ€. μ΄ λ°μ΄ν°λ₯Ό μ¬μ©νμ¬ API κ²μ΄νΈμ¨μ΄ λ° λ°±μλ μλΉμ€μ μ±λ₯κ³Ό μνλ₯Ό λͺ¨λν°λ§ν μ μμ΅λλ€. Istioλ₯Ό ꡬμ±νμ¬ ν λ λ©νΈλ¦¬ λ°μ΄ν°λ₯Ό Prometheus, Grafana λ° Jaegerλ‘ λ΄λ³΄λ λλ€.
API κ²μ΄νΈμ¨μ΄ νΉμ λ©νΈλ¦
Istioμ ν λ λ©νΈλ¦¬ λ°μ΄ν° μΈμλ λ€μκ³Ό κ°μ API κ²μ΄νΈμ¨μ΄ νΉμ λ©νΈλ¦μ μμ§ν΄μΌ ν©λλ€:
- μμ²λ₯ : μ΄λΉ μμ² μμ λλ€.
- μλ΅ μκ°: μμ²μ μ²λ¦¬νλ λ° κ±Έλ¦¬λ νκ· μκ°μ λλ€.
- μ€λ₯μ¨: μ€λ₯κ° λ°μνλ μμ²μ λΉμ¨μ λλ€.
- μΈμ¦ μ±κ³΅/μ€ν¨μ¨: μ±κ³΅ λ° μ€ν¨ν μΈμ¦ μλ νμμ λλ€.
- μΊμ μ μ€λ₯ : μΊμμμ μ 곡λλ μμ²μ λΉμ¨μ λλ€.
보μ κ³ λ € μ¬ν
API κ²μ΄νΈμ¨μ΄λ₯Ό ꡬμΆν λ 보μμ κ°μ₯ μ€μν©λλ€. λ€μ 보μ μ‘°μΉλ₯Ό κ³ λ €νμμμ€:
- μΈμ¦ λ° κΆν λΆμ¬: λ°±μλ μλΉμ€λ₯Ό 보νΈνκΈ° μν΄ κ°λ ₯ν μΈμ¦ λ° κΆν λΆμ¬ λ©μ»€λμ¦μ ꡬνν©λλ€. JWT, OAuth 2.0 λλ κΈ°ν μ°μ νμ€ νλ‘ν μ½μ μ¬μ©νμμμ€.
- μ λ ₯ μ ν¨μ± κ²μ¬: μ£Όμ 곡격μ λ°©μ§νκΈ° μν΄ λͺ¨λ μμ μμ²μ μ ν¨μ±μ κ²μ¬ν©λλ€.
- μλ μ ν: μ€μ© λ° μλΉμ€ κ±°λΆ κ³΅κ²©μ λ°©μ§νκΈ° μν΄ μλ μ νμ ꡬνν©λλ€.
- TLS μνΈν: TLSλ₯Ό μ¬μ©νμ¬ API κ²μ΄νΈμ¨μ΄μ λ°±μλ μλΉμ€ κ°μ λͺ¨λ ν΅μ μ μνΈνν©λλ€. Istioλ μνΈ TLS(mTLS)λ₯Ό μ¬μ©νμ¬ μλ TLS μνΈνλ₯Ό μ 곡ν©λλ€.
- μΉ μ ν리μΌμ΄μ λ°©νλ²½ (WAF): SQL μ£Όμ λ° κ΅μ°¨ μ¬μ΄νΈ μ€ν¬λ¦½ν (XSS)κ³Ό κ°μ μΌλ°μ μΈ μΉ μ ν리μΌμ΄μ 곡격μΌλ‘λΆν° 보νΈνκΈ° μν΄ WAFλ₯Ό μ¬μ©ν©λλ€.
- μ κΈ°μ μΈ λ³΄μ κ°μ¬: μ·¨μ½μ μ μλ³νκ³ ν΄κ²°νκΈ° μν΄ μ κΈ°μ μΈ λ³΄μ κ°μ¬λ₯Ό μνν©λλ€.
Istioλ₯Ό μ¬μ©ν μνΈ TLS (mTLS)
Istioλ λͺ¨λ μλΉμ€ κ° ν΅μ μ λν΄ mTLSλ₯Ό μλμΌλ‘ μ μ©νμ¬ λͺ¨λ ν΅μ μ΄ μνΈνλκ³ μΈμ¦λλλ‘ λ³΄μ₯ν μ μμ΅λλ€. μ΄λ λμ² λ° λ³μ‘°μ λν κ°λ ₯ν 보μ κ³μΈ΅μ μ 곡ν©λλ€.
κ³ κΈ μ£Όμ
GraphQL κ²μ΄νΈμ¨μ΄
REST API λμ GraphQLμ μ¬μ©νμ¬ λ ν¨μ¨μ μΈ λ°μ΄ν° κ°μ Έμ€κΈ°λ₯Ό κ³ λ €νμμμ€. Graphene λ° Ariadneμ κ°μ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ GraphQL κ²μ΄νΈμ¨μ΄λ₯Ό ꡬνν©λλ€. GraphQLμ ν΄λΌμ΄μΈνΈκ° νμν λ°μ΄ν°λ§ μμ²ν μ μλλ‘ νμ¬ κ³Όλν λ°μ΄ν° κ°μ Έμ€κΈ°λ₯Ό μ€μ΄κ³ μ±λ₯μ ν₯μμν΅λλ€.
gRPC κ²μ΄νΈμ¨μ΄
μλΉμ€ κ°μ κ³ μ±λ₯ ν΅μ μ μν΄ gRPC μ¬μ©μ κ³ λ €νμμμ€. μΈλΆ ν΄λΌμ΄μΈνΈμ gRPC μλΉμ€λ₯Ό λ ΈμΆνκΈ° μν΄ gRPC κ²μ΄νΈμ¨μ΄λ₯Ό ꡬνν©λλ€. grpc-gatewayμ κ°μ λꡬλ₯Ό μ¬μ©νμ¬ gRPC μ μμμ RESTful APIλ₯Ό μμ±ν©λλ€.
μλ²λ¦¬μ€ API κ²μ΄νΈμ¨μ΄
AWS Lambda, Google Cloud Functions λλ Azure Functionsμ κ°μ νλ«νΌμ μ¬μ©νμ¬ API κ²μ΄νΈμ¨μ΄λ₯Ό μλ²λ¦¬μ€ ν¨μλ‘ λ°°ν¬νμμμ€. μλ²λ¦¬μ€ API κ²μ΄νΈμ¨μ΄λ νμ₯μ±, λΉμ© ν¨μ¨μ± λ° μ΄μ μ€λ²ν€λ κ°μλ₯Ό μ 곡ν©λλ€. μλ₯Ό λ€μ΄, API κ²μ΄νΈμ¨μ΄λ PythonμΌλ‘ μμ±λ AWS Lambda ν¨μμ ν΅ν©λμ΄ μμ²μ μ²λ¦¬ν μ μμ΅λλ€. μ΄ μλ²λ¦¬μ€ μ κ·Ό λ°©μμ μΈνλΌ λΉμ©μ ν¬κ² μ€μΌ μ μμ΅λλ€.
κ²°λ‘
μλΉμ€ λ©μ ν΅ν©μ ν΅ν Python API κ²μ΄νΈμ¨μ΄ ꡬμΆμ λ§μ΄ν¬λ‘μλΉμ€ ν΅μ κ΄λ¦¬λ₯Ό μν κ°λ ₯νκ³ νμ₯ κ°λ₯ν μ루μ μ μ 곡ν©λλ€. API κ²μ΄νΈμ¨μ΄μ μλΉμ€ λ©μμ κ°μ μ κ²°ν©νμ¬ ν₯μλ 보μ, κ΄μ°° κ°λ₯μ± λ° νΈλν½ κ΄λ¦¬λ₯Ό λ¬μ±ν μ μμ΅λλ€. μ΄ μν€ν μ²λ κ³ κ°μ©μ±, νμ₯μ± λ° λ³΄μμ μꡬνλ νλμ μΈ ν΄λΌμ°λ λ€μ΄ν°λΈ μ ν리μΌμ΄μ μ λ§€μ° μ ν©ν©λλ€. νΉμ μꡬ μ¬νμ κ³ λ €νκ³ νμμ κ°μ₯ μ ν©ν λꡬμ κΈ°μ μ μ νν΄μΌ ν©λλ€. μλ₯Ό λ€μ΄, μκ·λͺ¨ νμ¬λ μλμ μΌλ‘ μ¬μ©νκΈ° μ¬μ΄ Kongμ API κ²μ΄νΈμ¨μ΄λ‘, Linkerdλ₯Ό μλΉμ€ λ©μλ‘ μ νΈν μ μμ§λ§, λκΈ°μ μ μν€ν μ²μ λͺ¨λ μΈ‘λ©΄μ μΈλ°νκ² μ μ΄νκΈ° μν΄ Istioμ λ§μΆ€ν Python API κ²μ΄νΈμ¨μ΄λ₯Ό μ νν μ μμ΅λλ€. μ¬λ°λ₯Έ λꡬλ₯Ό μ ννκ³ μμμ μΈκΈν 보μ κ³ λ € μ¬νμ μ μ€νκ² κ΅¬ννλ κ²μ΄ μ±κ³΅μ κ°μ₯ μ€μν©λλ€. λν, λμμμ΄ μ§ννλ κΈ°μ νκ²½μμ κ°λ ₯νκ³ μμ ν API κ²μ΄νΈμ¨μ΄λ₯Ό μ μ§νλ €λ©΄ μ§μμ μΈ λͺ¨λν°λ§κ³Ό μ μμ΄ νμμ μ λλ€.