📙
Daeun's devlogs
  • First page
  • Docker
    • 이미지, 레이어
    • 컨테이너 생성하기
    • Dockerfile로 이미지 생성하기
    • 이미지를 dockerhub repo에 push하기
  • Python
  • Algorithm Study
  • 방향없는 그래프(undirected graph)
  • 방향있는 그래프(directed graph)
  • 위상 정렬(topological sort)
  • BFS(Breadth-First Search)
  • 다익스트라(Dijkstra)
  • 벨만-포드(Bellman-Ford) 알고리즘
  • 최소신장트리(Minimum Spanning Tree)
  • 크루스칼(Kruskal) 알고리즘
  • Algorithm quiz
    • quizzes & solutions
    • graph에서 cycle 유무 확인하기
    • bipartite(이분그래프) 확인하기
    • Dijkstra 알고리즘으로 모든 정점으로의 최단 경로 구하기
  • operating system
  • 스루풋 & 레이턴시
  • Cloud Computing
    • cloud computing 의 종류
    • CloudFormation으로 EC2 & ElasticIP 생성하기
  • Network
    • DataLink 계층
    • Network 계층
    • subnetting & CIDR
    • Domain Name System
    • Transport 계층
  • Unix
    • dig 커맨드로 DNS서버에 질의하기
    • APT(Advanced Package Tool)로 젠킨스 설치하기
    • usermod 로 그룹에 유저 추가하기
    • sysctl 로 커널 변수 조회하기
  • Django
    • 마이그레이션 실행여부 확인하기
    • 마이그레이션 DDL 쿼리 확인하기
  • Kubernetes
  • 쿠버네티스(Kubernetes) 개념
  • k8s 클러스터에 애플리케이션 서버 실행하기
  • kops로 AWS에 k8s 클러스터 생성하기
  • k8s 클러스터에 replicaset 생성하기
  • Nginx & WSGI pod를 service로 노출하기
  • Helm으로 쿠버네티스 리소스 배포하기
Powered by GitBook
On this page
  • 1. WSGI pod의 service 생성하기
  • 2. Nginx pod의 service 생성하기

Was this helpful?

Nginx & WSGI pod를 service로 노출하기

Previousk8s 클러스터에 replicaset 생성하기NextHelm으로 쿠버네티스 리소스 배포하기

Last updated 5 years ago

Was this helpful?

최초작성일 [2020.03.18]

아래와 같은 구조로 쿠버네티스의 service를 생성하려고 한다. (replicaset 또는 deployment를 미리 생성해야 한다.)

1. WSGI pod의 service 생성하기

WSGI 프로세스는 아래의 configuration으로 작동한다. 포트번호 9090을 통해 트래픽을 받아 flask 애플리케이션으로 전달한다.

[uwsgi]
wsgi-file=app/app.py
# flask app's name
callable=flask_app

# bind to the specified UNIX/TCP socket using default protocol
socket=:9090
# set internal http socket timeout
http-timeout=5

# enable master process
master = 1
# spawn the specified number of workers/processes
processes = 4

enable-threads=true

# serialize accept(), AKA Thundering Herd
# https://uwsgi-docs.readthedocs.io/en/latest/articles/SerializingAccept.html
thunder-lock=true

WSGI는 nginx를 통해 들어오는 트래픽만을 허용하므로 service 타입은 ClusterIP로 선택한다. ClusterIP 타입은 pod를 클러스터 내부에 한정하여 노출하려고 할 때 사용한다.

apiVersion: v1

kind: Service

metadata:
  name: service-flask-wsgi

spec:
  type: ClusterIP
  selector:
    app: flask-wsgi
  ports:
    - name: port-flask-wsgi
      port: 9090
      targetPort: 9090

attribute

usage

selector

ports.port

서비스가 생성되면 서비스는 클러스터 내부에서만 사용할 수 있는 고유한 IP를 가지게 된다. 서비스의 IP에 접근할 때 ports.port에 해당하는 값을 포트번호로 쓴다.

ports.targetPort

selector에 정의된 라벨에 해당하는 pod들이 사용하는 포트번호. replicaset 템플릿에서 지정한containerPort의 값과 같아야 한다.

위에서 작성한 템플릿 service-app.yml 을 클러스터에 적용한다.

$ kubectl apply -f service-app.yml
service/service-flask-wsgi created

$ kubectl get service
NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes           ClusterIP   100.64.0.1       <none>        443/TCP          4d23h
service-flask-wsgi   ClusterIP   100.66.110.185   <none>        9090/TCP         121m

metadata.name의 값에 맞게 service-flask-wsgi라는 서비스가 생성되었다. CLUSTER-IP 필드의 IP주소는 클러스터 내부에서 해당 서비스에 접근하는 용도로 쓰인다. 즉, 클러스터 외부에서는 CLUSTER-IP필드의 주소로 접근할 수 없다.

kubernetes라는 서비스가 이미 있는 것을 볼 수 있다. kubernetes서비스는 pod 내부에서 쿠버네티스의 API에 접근하기 위한 용도로 쓰인다.

2. Nginx pod의 service 생성하기

nginx.conf는 아래와 같다. Nginx가 업스트리밍하는 서버의 주소가 위에서 생성한 서비스의 이름에 해당하 service-flask-wsgi인 것을 알 수 있다. 쿠버네티스 애플리케이션에는 service나 pod와 같은 리소스를 쉽게 찾을 수 있도록 리소스의 이름을 레코드로 관리하는 내부 DNS가 있다. 그리고 pod들은 이 DNS에 주소를 질의하기 때문에 service의 이름을 주소로 사용할 수 있다.

user nginx;
worker_processes auto;
...
http {
    ...
    upstream flask_server {
        server service-flask-wsgi:9090;
        keepalive 512;
        keepalive_timeout 5;
    }
    server {
        listen 80;
        server_name service-flask-wsgi;

        location / {
            include /etc/nginx/uwsgi_params;
            uwsgi_pass flask_server;
        }
    }
}

Nginx pod를 클러스터 외부에 노출하기 위해 아래와 같은 템플릿을 작성한다. NodePort 타입은 모든 노드의 특정 포트를 개방하여 외부에서 서비스에 접근하도록 허용한다. 아래의 service는 모든 노드에 포트번호 80번을 개방한다.

apiVersion: v1

kind: Service

metadata:
  name: service-my-nginx

spec:
  type: NodePort
  selector:
    app: my-nginx
  ports:
    - name: port-my-nginx
      port: 8080
      targetPort: 80

위에서 작성한 템플릿 service-nginx.yml을 클러스터에 생성한다.

$ kubectl apply -f service-nginx.yml
service/service-my-nginx created

$ kubectl get services
NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes           ClusterIP   100.64.0.1       <none>        443/TCP          4d22h
service-flask-wsgi   ClusterIP   100.66.110.185   <none>        9090/TCP         60m
service-my-nginx     NodePort    100.68.131.17    <none>        8080:31085/TCP   4s

service-my-nginx라는 이름으로 service가 생성된 것을 확인할 수 있다. service 타입이 NodePort였음에도 CLUSTER-IP가 만들어진 것을 볼 수 있는데, NodePort 타입의 service가 ClusterIP 타입의 기능을 포함하기 때문이다. 따라서 NodePort 타입으로 생성한 서비스는

  • 클러스터 내부에서 CLUSTER-IP 또는 service 이름을 통해 접근할 수 있고

  • 클러스터 외부에서 노드의 IP를 통해 접근할 수 있다.

PORT(S)의 값은 <클러스터 내부에서 접근할 때 쓰는 포트번호>:<클러스터 외부에서 접근할 때 쓰는 포트번호>로 되어있다.

클러스터 내부에서 service-my-nginx 에 접근해보자. 클러스터 내부의 워커 노드 중 하나에 접속하여 curl을 실행했다. IP주소는 CLUSTER-IP에 해당하는 100.68.131.17이고 포트번호 8080으로 접근한다.

admin@ip-172-20-40-1:~$ curl 100.68.131.17:8080
Hello, This is DaEun Kim.

이번에는 클러스터 외부에서 service-my-nginx에 접근한다. 워커 노드의 퍼블릭IP주소와 함께 포트번호는 31085으로 접근한다. 내/외부 IP주소를 포함한 노드의 정보를 조회하고 싶다면 아래의 커맨드를 실행한다.

$ kubectl get nodes -o wide  

위 커맨드에서 조회한 노드의 퍼블릭 IP주소로 curl을 실행한다.

$ curl 13.125.164.232:31085
Hello, This is DaEun Kim. 

참고

외부로 노출시키려는 pod의 라벨을 식별한다. ( 참고.)

Nginx Upstream 성능최적화
Nginx config 정리
Nginx full example
시작하세요! 도커/쿠버네티스
label selector