이전 시간에는 미니큐브에서 스프링 프로젝트와 MySQL을 실행하고, 포트포워딩을 사용하여 외부에서 접속하는 방법을 배웠습니다. 그러나 이 방법으로는 하나의 서비스만 접속할 수 있습니다. 만약 여러 개의 서비스를 운영하고 있다면, 파이썬 기반의 플라스크나 장고, 자바 기반의 스프링, 그리고 자바스크립트 기반의 노드제이에스 등을 함께 사용하는 경우 라우팅이 필요합니다. 이번 시간에는 쿠버네티스에서 라우팅할 수 있는 방법을 배우겠습니다.

domain.com/spring → spring project

domain.com/flask → flask project

1. 샘플 프로젝트 만들기

  1. 스프링의 경우, 이전 시간에 만들었던 것을 그대로 활용할 예정입니다.
  2. 파이썬 프로젝트를 만들기 싫다면, 스킵하고 아래 flask-deploment.yaml 에 명시된 샘플 이미지를 그대로 사용할 수 있습니다.
  3. 플라스크의 경우, 다음과 같이 코드를 작성합니다.
from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, Flask!'

if __name__ == '__main__':
    app.run(host="0.0.0.0",port=80, debug=True)

  1. Dockerfile 작성
# Use an official Python runtime as the base image
FROM python:3.9

WORKDIR /app

COPY . .

RUN pip install Flask

EXPOSE 80
# Run the app.py file
CMD ["python", "app.py"]

  1. 빌드 (ec2를 x86으로 생성해줬으니 맞춰서 이미지를 만들어줄것입니다. )
docker build -t lee01042000/flask-test --platform linux/amd64 .

  1. 실행
docker run -it -p 8080:80 lee01042000/flask-test

  1. 크롬에서 8080 포트로 테스트해보세요. 만약 "Hello, Flask!"가 잘 나오면 끝입니다!
  2. 쿠버네틱스가 이미지를 가져오게 하기 위해 도커 허브에 푸쉬합니다. 만약 로그인이 안되어 있다면 로그인을 하고 진행하시면 됩니다.
docker push lee01042000/flask-test

2. Python Deployment & Service 작성하기

이전 포스트에서 스프링 프로젝트를 실행한 것처럼, 서비스와 배포를 명시한 python-deploy.yaml을 작성할 것입니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask-deployment
  labels:
    app: flask
spec:
  replicas: 1
  selector:
    matchLabels:
      app: flask
  template:
    metadata:
      labels:
        app: flask
    spec:
      containers:
      - name: flask
        image: 'lee01042000/flask-test'
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: flask-service
spec:
  type: NodePort
  selector:
    app: flask
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 80
      nodePort: 30008

kubectl apply -f python-deploy.yaml 을 이용해 쿠버네틱스에 적용하면 배포와 서비스를 실행할 수 있습니다.

minikube ip 명령어를 사용하여 IP 주소를 찾은 다음, curl {minikubeip}:30008을 실행하여 "Hello, Flask!"가 출력되면 성공입니다.

2. Ingress로 라우팅 구현하기

쿠버네틱스에서는 ingress를 사용하여 서비스 라우팅이 가능합니다.

이렇게 ingress는 요청을 먼저 받아들여 적절한 서비스로 라우팅할 수 있습니다.

URL 디렉터리를 기반으로 하거나, 요청 헤더에 포함된 호스트명을 가지고도 라우팅이 가능합니다.

L7 스위치라고 생각하시면 이해하기 쉽습니다.

2.1 Nginx ingress controller 설치

ingress 룰을 적용하기 위해선 룰을 구현하는 ingress controller가 필요합니다. 공식 홈페이지에서는 다양한 ingress controller를 찾아볼 수 있지만, 이 문서에서는 nginx를 사용해보겠습니다.

https://kubernetes.io/ko/docs/tasks/access-application-cluster/ingress-minikube/

  1. NGINX 인그레스 컨트롤러를 활성화하기 위해 다음 명령어를 실행합니다.
  2. minikube addons enable ingress

2.2 ingress 룰 작성

참고로 nginx.ingress.kubernetes.io/rewrite-target 옵션을 설정하지 않으면 http://minikubeip/spring 으로 요청시 /spring이 url에 포함되서 포워딩이 되니 / 로 명시해야합니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /spring
        pathType: Prefix
        backend:
          service:
            name: spring-service
            port:
              number: 8080
      - path: /flask
        pathType: Prefix
        backend:
          service:
            name: flask-service
            port:
              number: 80

  1. kubectl apply -f ingress.yaml 명령어로 적용합니다.
  2. curl {minikubeip}/flask & curl {minikubeip}/spring을 쳤을 때 사이 좋게 나오면 성공입니다!

3. 외부 접속 연결하기

아직은 ec2 내부에서만 접속이 가능합니다. 즉, client → server — x → ingress → service → pod인 상태입니다.

그럼 이제 서버포트랑 미니큐브 사이만 연결해주면 됩니다.

이를 포트포워딩이라고 합니다.

가장 친숙한 방법은 nginx를 사용하는 것입니다.

3.1 EC2에 Nginx를 설치

sudo amaxon-linux-extras install nginx1

3.2 EC2에 라우팅 정책 설정

minikube ip 가 192.168.49.2 인 경우 아래와 같이 server.location을 설정합니다.

# For more information on configuration, see:
#   * Official English Documentation: <http://nginx.org/en/docs/>
#   * Official Russian Documentation: <http://nginx.org/ru/docs/>

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See <http://nginx.org/en/docs/ngx_core_module.html#include>
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }

	location / {
            proxy_pass         http://192.168.49.2/;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }

# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2;
#        listen       [::]:443 ssl http2;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers PROFILE=SYSTEM;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }

}

3.3 재설치 및 재실행

sudo systemctl restart nginx

4. 테스트

이제 EC2서버에 접속해보겠습니다.

아래와 같이 잘 출력되면 성공입니다!

+ Recent posts