ISTIO, Service Mesh Architecture

Jeonghak Cho·2025년 3월 2일

Istio

목록 보기
6/6

아키텍처

서비스 메시 아키텍처 설계

이스티오 인젝션

이스티오 프록시 컨테이너 인젝션 대상 네임스페이스 지정

kubectl label ns myistio istio-injection-
kubectl label ns myistio istio-injection=enabled

아키텍처 참여 컴포넌트

백엔드 서비스

REST API 서버를 배포한다. FastAPI는 Python 기반의 웹 프레임워크로, API 개발을 빠르고 효율적으로 할 수 있도록 설계되었다. 성능이 뛰어나고, 타입 힌트를 적극적으로 활용하여 코드의 안정성과 가독성을 높일 수 있다. 버전을 v1, v2 로 나누어 정책에 따라 트래픽이 라우팅되게 구성하였다.

K8S Gateway API on ISTIO

Kubernetes Gateway API는 Kubernetes 클러스터 내에서 L4 및 L7 트래픽 라우팅을 관리하기 위한 공식 프로젝트로, 기존 Ingress API의 한계를 보완하고자 설계되었다.
ingress 보다 아래 기능이 향상된다.

  • 표현력 향상: Gateway API는 헤더 기반 라우팅, 트래픽 분할 등 고급 트래픽 관리 기능을 기본으로 지원
  • 역할 기반 리소스 분리: 플랫폼 팀, DevOps, 개발자 등 각 역할에 맞는 리소스를 제공하여, 역할별 책임 분리가 가능
  • 벤더 중립성: 표준화된 API를 통해 다양한 컨트롤러 간의 이식성과 호환성을 보장

이곳 아키텍처에서는 로드 밸런서를 대신하고 API Gateway가 관리하기 어려운 동서 트래픽(서비스 대 서비스 트래픽)을 관리하기 위해 사용하였다.

BFF

Backend for Frontend(BFF) 는 특정 프론트엔드(웹, 모바일 앱 등)의 요구사항에 맞게 백엔드를 커스텀하여 제공하는 아키텍처 패턴이다.
일반적인 API Gateway는 모든 클라이언트(웹, 모바일, 데스크톱 등)에 대해 동일한 API를 제공하지만, BFF는 각 클라이언트별 맞춤형 API를 제공하는 것이 특징이다.

웹서버

NGINX는 가볍고 빠른 웹 서버이자 리버스 프록시, 로드 밸런서, API 게이트웨이 역할을 수행하는 오픈소스 소프트웨어이다. 높은 동시 연결 처리 성능과 비동기 이벤트 기반 아키텍처를 통해 트래픽이 많은 환경에서도 안정적인 서비스를 제공한다.
리버스 프록시를 설정하여 BFF 서비스를 호출한다.

클라이언트

쿠버네티스 네트워크 연결 확인을 위한 BASH 콘솔 실행을 위한 이미지로 사용하였다. 웹서버의 URL을 지속적으로 호출하여 트래픽을 발생시킨다.

아키텍처 구축

주요 파일 내용을 참조가능하도록 노출하였으며, 세부 단계는 생략하였다.

백엔드 API 서버

파이썬 소스 (main.py)

main.py

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def base():
    return {"message": "Hello, FastAPI!"}

@app.get("/health")
async def base():
    return {"message": "Hello, FastAPI!"}    

@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
    return {"item_id": item_id, "query": q}

라이브러리 목록 파일

vagrant@slave1:~/myistio$ cat requirements.txt
fastapi>=0.68.0,<0.69.0
pydantic>=1.8.0,<2.0.0
uvicorn>=0.15.0,<0.16.0

도커 파일

Docerfile.backend-dev

FROM python:3.11-alpine

LABEL maintainer="chojeonghak@gmail.com"
LABEL version="1.0"
LABEL description="backend"

WORKDIR /app

USER root

RUN apk update && \
    apk add --no-cache curl vim bash

COPY ./requirements.txt /app

RUN pip install -r requirements.txt

COPY ./main.py /app

EXPOSE 5000

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "5000"]

쿠버네티스 메니페스터

backend.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-v1
  namespace: myistio
spec:
  selector:
    matchLabels:
      app: backend
      version: v1
  replicas: 1
  template:
    metadata:
      labels:
        app: backend
        version: v1
    spec:
      containers:
      - name: backend
        image: 저장소/backend:0.2
        ports:
        - containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
  name: backend-v1
  namespace: myistio
  labels:
    app: backend
    version: v1
spec:
  ports:
  - port: 5000
    protocol: TCP
  selector:
    app: backend
    version: v1
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-v2
  namespace: myistio
spec:
  selector:
    matchLabels:
      app: backend
      version: v2
  replicas: 1
  template:
    metadata:
      labels:
        app: dbackend
        version: v2
    spec:
      containers:
      - name: backend
        image: 저장소/backend:0.2
        ports:
        - containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
  name: backend-v2
  namespace: myistio
  labels:
    app: backend
    version: v2
spec:
  ports:
  - port: 5000
    protocol: TCP
  selector:
    app: backend
    version: v2
  type: ClusterIP  

K8S Gateway API on ISTIO

게이트웨이

mygateway.yml

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: mygateway
  namespace: myistio
  labels:
    app: mygateway
spec:
  gatewayClassName: istio
  listeners:
    - protocol: HTTP
      port: 80
      name: http

HTTPROUTE

myroute.yml

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: myroute
  namespace: myistio
spec:
  parentRefs:
    - name: mygateway
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: "/"
      backendRefs:
        - name: backend-v1
          port: 5000
          weight: 50
        - name: backend-v2
          port: 5000
          weight: 50

BFF 생성

소스 생성

import requests
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/', methods=['GET'])
def web_home():
    return jsonify({
        "title": "Welcome to Web",
        "content": "This is web-specific content."
    })

@app.get("/health")
async def base():
    return {"message": "Hello, FastAPI!"}    

@app.route('/bff')
def call_bff():
    print("CALLED backend for frontend!")
    response = requests.get("http://mygateway-istio")
    return f"BFF RESPONSE: {response.text}"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=3000)

도커파일

FROM python:3.11-slim
LABEL maintainer="chojeonghak@gmail.com"
LABEL version="1.0"
LABEL description="BFF"
USER root
WORKDIR /app
RUN apt-get update && \
    apt-get install -y curl vim && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

RUN pip install flask
RUN pip install requests
COPY ./bff.py /app

EXPOSE 3000

CMD ["python3", "bff.py"]

쿠버네티스 메니페스터 작성

bff.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: bff
spec:
  selector:
    matchLabels:
      app: bff
  replicas: 1
  template:
    metadata:
      labels:
        app: bff
    spec:
      containers:
      - name: bff
        image: 저장소/bff:0.2
        ports:
        - containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
  name: bff
  namespace: myistio
  labels:
    app: bff
spec:
  ports:
  - port: 3000
    protocol: TCP
  selector:
    app: bff        

쿠버네티스 배포

bff.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: bff
  namespace: myistio
spec:
  selector:
    matchLabels:
      app: bff
  replicas: 1
  template:
    metadata:
      labels:
        app: bff
    spec:
      containers:
      - name: bff
        image: 저장소/bff:0.1
        ports:
        - containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
  name: bff
  namespace: myistio
  labels:
    app: bff
spec:
  ports:
  - port: 3000
    protocol: TCP
  selector:
    app: bff        

웹서버 ( frontend )

메니페스트

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  selector:
    matchLabels:
      app: frontend
  replicas: 1
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: frontend
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: shared-data
          mountPath: /usr/share/nginx/html
        - mountPath: /etc/nginx/nginx.conf
          readOnly: true
          name: config
          subPath: nginx.conf
      volumes:
      - name: shared-data
        persistentVolumeClaim:
          claimName: mypvc
      - name: config
        configMap:
          name: nginx
          items:
            - key: nginx.conf
              path: nginx.conf
      - name: logs
        emptyDir: {}
---        
apiVersion: v1
kind: Service
metadata:
  name: frontend
  labels:
    app: frontend
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    app: frontend  
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx
data:
  nginx.conf: |
    user nginx;
    worker_processes  3;
    error_log  /var/log/nginx/error.log;
    events {
      worker_connections  10240;
    }
    http {
      access_log        /var/log/nginx/access.log main;
      server {
          listen       80;
          server_name  _;
          location / {
              root   /usr/share/nginx/html;
              index  index.html index.htm;
          }

          location /bff {
              proxy_pass http://bff.myistio.svc.cluster.local:3000/bff;
              proxy_http_version 1.1;
              proxy_set_header Host $host;
              proxy_set_header X-Real-IP $remote_addr;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
              proxy_set_header X-Forwarded-Proto $scheme;
              proxy_set_header Connection "";
              proxy_set_header Upgrade $http_upgrade;
              proxy_cache_bypass $http_upgrade;

              proxy_connect_timeout 10s;
              proxy_send_timeout 15s;
              proxy_read_timeout 15s;
          }
      }

    }              

클라이언트

  • 트래픽 생성
while true; do curl "http://frontend.myistio.svc.cluster.local/bff";sleep 1; done

0개의 댓글