[쿠버네티스] 3계층 배포

최동혁·2023년 4월 25일
0

쿠버네티스

목록 보기
2/7

쿠버네티스

MySQL 서비스

apiVersion: v1
kind: Service
metadata:
  name: db-svc
spec:
  selector:
    type: db
  ports:
  - port: 3306
    targetPort: 3306

MySQL configmap

apiVersion: v1
kind: ConfigMap
metadata:
  name: db-cm
data:
  MYSQL_ROOT_PASSWORD: "qwer1234"

MySQL 파드

apiVersion: v1
kind: Pod
metadata:
  name: db-pod
  labels:
    type: db
spec:
  containers:
  - name: container
    image: mysql:8.0.32-debian
    envFrom:
    - configMapRef:
        name: db-cm

  • mysql -u root -p 로 올라온 파드에 잘 생성되었나 확인
  • 그리고 CREATE DATABASE web;
  • web이라는 이름으로 데이터 베이스 생성 (백엔드에서 접속할 데이터베이스 이름으로 해줘야함)

gunicon 서비스

apiVersion: v1
kind: Service
metadata:
  name: backend-svc
spec:
  selector:
    type: backend
  ports:
  - port: 8000
    targetPort: 8000

gunicorn configmap

apiVersion: v1
kind: ConfigMap
metadata:
  name: backend-cm
data:
  DBNAME: "web"
  DBUSER: "root"
  DBPASS: "qwer1234"
  DBHOST: "db-svc"
  DBPORT: "3306"

gunicorn 파드

이미지 생성

  • docker는 방화벽이 실행되고 있어야 컨테이너 생성가능

폴더 생성

  • 격리할 컨테이너의 디렉토리를 생성
  • mkdir gunicorn

Dockerfile

FROM python:3.9
ENV PYTHONUNBUFFERED 1
WORKDIR /app
COPY r.txt /app/r.txt
COPY . /app
RUN pip install -r r.txt

파일 옮기기

  • django 프로젝트 파일과, requirements.txt(r.txt) 파일을 옮겨놓는다.
  • 필자는 Filezilla를 이용해 가상환경으로 파일을 옮겼다.

settings.py

  • 데이터베이스 환경변수 값을 불러올 수 있게 설정
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': os.environ["DBNAME"],
        '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"'
        }
    }
}

이미지 생성해서 hub에 올리기

  • docker login 명령어로 login 해놓기
  • docker hub에 namespace의 레포지토리 생성

  • docker build --tag (namespace)/(repository):(tag) .
    • 만약 이 명령어를 쳤는데 RUN pip install 쪽에서 막힌다? 방화벽 꺼져있는거임.
    • systemctl restart firewalld 를 이용해 방화벽을 켜줘야한다.

  • docker push (namespace)/(repository):(tag)

  • docker hub 의 레포지토리에 들어가서 확인하면 위의 그림처럼 이미지가 업로드 되어 있다.

파드 생성

apiVersion: v1
kind: Pod
metadata:
  name: backend-pod
  labels:
    type: backend
spec:
  containers:
  - name: container
    image: cis07385/back:1.0
    command: ["/bin/sh", "-ec", "python manage.py migrate && gunicorn config.wsgi --bind 0.0.0.0:8000"]
    envFrom:
    - configMapRef:
        name: backend-cm
  • 여기서 image를 자신이 위에서 생성한 이미지 파일을 docker hub에서 긁어오는 것이다. 자신이 올린 것을 써줘야한다.

  • 그 후, log를 확인하면 잘 실행되고 있는것을 확인할 수 있다.

nginx 서비스

apiVersion: v1
kind: Service
metadata:
  name: frontend-svc
spec:
  selector:
    type: frontend
  ports:
  - port: 80
    targetPort: 80

nginx configmap

apiVersion: v1
kind: ConfigMap
metadata:
  name: frontend-cm
data:
  BACKEND_SVC_NAME: "backend-svc"

nginx 파드

폴더 생성

  • mkdir nginx

이미지 생성

  • docker는 방화벽이 실행되고 있어야 컨테이너 생성가능

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

  • vi default.conf.template
server {
    listen       80;
    server_name  localhost;

    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://${BACKEND_SVC_NAME}:8000;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
  • envsubst는 특정 값을 특정 파일의 변수에 저장해라 명령어임.
  • service 이름이 바뀌게 될 수 있기 때문에, 환경 변수로 설정해서 configmap에서 다룰 것임.
  • 그래서 configmap의 특정 service의 이름을 읽어들여서 적용시키는 것임.
  • 그런데 이런 바뀌는 변수들은 Dockerfile에 작성해놓기 보다는, 파드 생성할 때 command로 해놓는게 좋다.
  • 여기서 변수로 잡은 BACKEND_SVC_NAME은 nginx configmap 설정에
  • 아 물론 여기서 location /dev는 back쪽 url을 따로 설정해놓은 것이다.
  • 해당 url의 /dev로 통신하면 back과 통신하게 해주는 것이다.
  • 물론 back 쪽에서도 모든 통신 api의 url에 dev를 붙여줘야한다!!!!!!!!!!!!!
data:
  BACKEND_SVC_NAME: "backend-svc"
  • 이런식으로 설정해놓았다.
  • 그래서 나중에 backend 서비스 이름이 바뀌더라도 configmap만 손보면 된다.

파일 옮기기

  • front build 파일을 옮겨야한다.
  • 필자는 react여서 npm run build 명령어를 이용해 build 파일을 만들었다.
  • 여기서 back의 url은 일단 아직 서비스가 생성되지 않은 상태이기 때문에 아무거나 넣어놓고 build 하자.

이미지 생성해서 hub에 올리기

  • docker login 명령어로 login 해놓기

  • docker hub에 namespace에 레포지토리 생성

  • docker build --tag (namespace)/(repository):(tag) .

    • 만약 이 명령어를 쳤는데 RUN pip install 쪽에서 막힌다? 방화벽 꺼져있는거임.
    • systemctl restart firewalld 를 이용해 방화벽을 켜줘야한다.
  • docker push (namespace)/(repository):(tag)

  • docker hub 의 레포지토리에 들어가서 확인하면 위의 그림처럼 이미지가 업로드 되어 있다.

파드 생성

apiVersion: v1
kind: Pod
metadata:
  name: frontend-pod
  labels:
    type: frontend
spec:
  containers:
  - name: container
    image: cis07385/front:1.0
    command: ["/bin/sh", "-ec", "envsubst '$BACKEND_SVC_NAME' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"]
    envFrom:
    - configMapRef:
        name: frontend-cm
  • 물론 이것도 이미지는 자신이 올린 이미지를 사용해야한다.
  • 그리고 envsubst는 위에서 말한데로 변수를 집어넣어주는 명령어이다.
  • nginx를 실행하는 명령어는 docker hub에 들어가서 nginx tag쪽을 보면 된다.

  • 이렇게 하면 총 3개의 파드와 3개의 서비스, 3개의 configmap이 생성이 된다.

확인

  • curl (backend service의 ip):8000/dev/data
  • curl (frontend service의 ip):80/dev/data

  • 위의 명령어를 치면 master node에서 해당 서비스의 클러스터 ip에는 접근할 수 있기 때문에 db의 저장된 값을 볼 수 있다. 필자는 db에 아무것도 저장하지 않았기에 아무것도 뜨지 않는다.

  • client가 front의 ip로 접속했을 때에는 안 뜬다.

  • 왜냐면 이건 클러스터 내부에서만 쓸 수 있는 서비스이기 때문에 외부 ip에서는 접근이 불가하다.

  • 각 연결되어 있는 노드들끼리만 접속이 가능하다.

  • 나중에는 외부에 있는 사용자들이 쿠버네티스 안에 컨테이너로 만들어져있는 특정 프로그램에 연결되게 하려면, Nodeport 혹은 Loadbalance를 사용해야한다.

  • 우리가 만든 frontend service의 ip만 외부에서 접속할 수 있으면 된다.

  • frontend 서비스 설정에 들어가서 default로 cluster ip로 설정되어 있는 것을 type:NodePort로 바꾸어 주고 나와서 확인해보면?

  • 특정 주어지는 port로 외부에서 접속이 가능하게 해준다.

  • 그러면 front에 back url을 부여받은 port까지 작성해서 넣어주고, build 파일을 다시 master node에 올려서 이미지를 생성 후, 파드를 재 생성해야한다.

  • 접속은 master의 ip 혹은 node1, node2의 ip에 port로 접속하면 된다.

  • 이건 또 쿠버네티스의 구조와 연관이 있는데 다음시간에..

  • 그런데 사용자들이 30000번대의 port로 브라우저에 접속하지는 않는다.

  • 이건 데모 버전에서 테스트를 할 때에만 사용함. 80번이나 443번을 지정하지 못함.

profile
항상 성장하는 개발자 최동혁입니다.

0개의 댓글