[Kubernetes] Nginx - Gunicorn - Mysql 3계층 연동하기 (Pod/ConfigMap/Service)

안녕 ¡∇¡ !!
오늘은 ~ K8S Dashboard 의 Pod / ConfigMap / Service 를 이용해
Nginx(front) - Gunicorn(back) - MySQL(db) 3계층을 연동해보자 !
♡ 순서 ♡
1. MySQL - Service, ConfigMap, Pod 작성
2. 장고 프로젝트 준비
3. Gunicorn 이미지 도커에 업로드
4. Gunicorn - Service, ConfigMap, Pod 작성
5. 리액트 프로젝트 준비
6. Nginx 이미지 도커에 업로드
7. Nginx - Service, ConfigMap, Pod 작성
8. 확인해보기 (푸티 / 웹 브라우저)
¡ Dashboard 에 생성할 것 ¡
> Service : nginx-svc, django-svc, mysql-svc
> ConfigMap : nginx-dev, django-dev, mysql-dev
> Pod : nginx-pod, gunicorn-pod, mysql-pod
[ MySQL ]
● Service
# mysql-svc
apiVersion: v1
kind: Service
metadata:
name: mysql-svc
spec:
selector:
app: mysql-pod # Pod 랑 맞춰줘야 하는 값
ports:
- port: 3306
targetPort: 3306
● ConfigMap
# mysql-dev
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-dev
data:
MYSQL_ROOT_PASSWORD: "qwer1234" # 패스워드 설정
● Pod
# mysql-pod
apiVersion: v1
kind: Pod
metadata:
name: mysql-pod
labels:
app: mysql-pod # Service 랑 맞춰줘야 하는 값
spec:
containers:
- name: container
image: mysql:8.0.32-debian
envFrom:
- configMapRef:
name: mysql-dev # ConfigMap 지정
● mysql-pod 쉘에서 데이터베이스 만들어주기
> mysql -u root -p
> create database web;
[ Gunicorn ]
● 도커 허브에 이미지 업로드
》 장고 프로젝트 준비
미리 Pycharm을 이용해 Django 프로젝트를 대충 만들어놨어 !
# urls.py
urlpatterns = [
path('dev/data', web.views.read)
]
# web - views.py
def read(request):
datas = Data.objects.all().values()
data_list = []
for data in datas:
print(data)
data_list.append(data)
context = {"result": data_list}
return JsonResponse(context)
# web - models.py
class Data(models.Model):
value = models.CharField(max_length=100)
# config - settings.py
import os
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': os.environ['DBNAME'], # ConfigMap 에서 정의
'USER': os.environ['DBUSER'],
'PASSWORD': os.environ['DBPASS'],
'HOST': os.environ['DBHOST'],
'PORT': os.environ['DBPORT'],
'OPTIONS': {
'init_command': 'SET sql_mode="STRICT_TRANS_TABLES"'
}
}
}
프로젝트를 압축해서 FileZilla 를 통해 도커가 설치된 리눅스 가상머신으로 옮겨주자 !
》 Dockerfile
FROM python:3.9
ENV PYTHONUNBUFFERED 1
WORKDIR /app
COPY requirements.txt /app/requirements.txt
RUN pip3 install --upgrade pip
RUN pip install -r requirements.txt
COPY . /app
》 requirements.txt
# 장고 프로젝트에서 pip freeze > requirements.txt 로 생성 가능
asgiref==3.6.0
Django==4.2
django-cors-headers==3.14.0
gunicorn==20.1.0
mysqlclient==2.1.1
sqlparse==0.4.4
tzdata==2023.3
》 이미지 빌드 & 도커 업로드
# 이미지 빌드
# docker build --tag [docker hub id]/[directory]:[version] .
docker build --tag nuy0307/back:1.0 . # docker hub 에 미리 directory 만들어 놔야 함
# 도커에 이미지 올리기
# docker push [docker hub id]/[directory]:[version]
docker push nuy0307/back:1.0
● Service
# django-svc
apiVersion: v1
kind: Service
metadata:
name: django-svc
spec:
selector:
app: django-pod
ports:
- port: 8000
targetPort: 8000
● ConfigMap
# django-dev
apiVersion: v1
kind: ConfigMap
metadata:
name: django-dev
data:
DBNAME: "web"
DBUSER: "root"
DBPASS: "qwer1234"
DBHOST: "mysql-svc"
DBPORT: "3306"
● Pod
# gunicorn-pod
apiVersion: v1
kind: Pod
metadata:
name: gunicorn-pod
labels:
app: django-pod # Service 랑 맞춰주기
spec:
containers:
- name: container
image: nuy0307/back:1.0
command: ["/bin/sh", "-ec", "python manage.py migrate && gunicorn config.wsgi --bind 0.0.0.0:8000"]
envFrom:
- configMapRef:
name: django-dev # ConfigMap 이랑 맞춰주기
[ Nginx ]
● 도커 허브에 이미지 업로드
》 React 프로젝트 준비
# App.js
import React from 'react';
import './App.css';
function App() {
const [datas, setDatas] = React.useState([]);
React.useEffect(() => {
fetch("http://200.200.200.135:31897/dev/data", { # 외부에서 접속할 ip:[nginx nodeport]
method: "GET",
})
.then(res => {
return res.json();
})
.then(res => {
setDatas(res.result);
});
}, []);
return (
<div className="App">
{datas.map((data) => {
return <div key={data.id}>{data.value}</div>
})}
</div>
);
}
export default App;
> npm run build
프로젝트를 압축해서 FileZilla 를 통해 도커가 설치된 리눅스 가상머신으로 옮겨주자 !
필요한 건 build 파일과 default.conf 파일!
》 Dockerfile
FROM nginx:latest
RUN rm -rf /usr/share/nginx/html/index.html
ADD build /usr/share/nginx/html/
RUN rm -rf /etc/nginx/conf.d/default.conf
ADD default.conf.template /etc/nginx/conf.d/default.conf.template
》 default.conf.template
server {
listen 80 default_server;
listen [::]:80 default_server;
root /usr/share/nginx/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
location /dev {
proxy_set_header Host $http_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_pass http://${DJANGO_IP}:8000; # ConfigMap 에서 지정
}
}
》 이미지 빌드 & 도커 업로드
# 이미지 빌드
docker build --tag nuy0307/front:1.2 .
# 도커에 이미지 업로드
docker push nuy0307/front:1.2
● Service
# nginx-svc
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
selector:
app: nginx-pod
ports:
- port: 80
targetPort: 80
type: NodePort # 외부에서 접속 가능한 포트 번호 할당 (default : Cluster IP - 내부 접속)
● ConfigMap
# nginx-dev
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-dev
data:
DJANGO_IP: "django-svc"
● Pod
# nginx-pod
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx-pod
spec:
containers:
- name: container
image: nuy0307/front:1.2
command: ["/bin/sh", "-ec", "envsubst '$DJANGO_IP' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"]
envFrom:
- configMapRef:
name: nginx-dev
[ 확인해보기 ]
● PuTTy 에서 확인
# master node
curl [nginx-svc ip]:80 # html 출력
curl [nginx-svc ip]:80/dev/data # django project 출력
● 웹 브라우저에서 확인
》 http://[master/node1/node2 ip]:[nginx port]/dev/data 로 접속