본문 바로가기
Kubernetes

[Project] 온프레미스 중간 프로젝트

by Nirah 2023. 2. 17.

 

 

 

docker login

docker tag backend:flask hkang4628/was:1

docker push hkang4628/web:1

 

WEB 설정

 

프론트엔드 개발자를 위한 Docker로 React 개발 및 배포하기

리액트 앱을 도커 컨테이너에 쉽게 띄워보자! 이 포스트는 Youtube의 Sanjeev Thiyagarajan라는 분이 올려주신 Docker + ReactJS tutorial 영상을 따라 쉽게 도커를 이해할 수 있도록 정리한 내용이다.

velog.io

# delete.html

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <link
    rel="stylesheet"
    href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"
    integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l"
    crossorigin="anonymous"
  />
  <script
    src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"
    integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p"
    crossorigin="anonymous"
  ></script>
  <script
    src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js"
    integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF"
    crossorigin="anonymous"
  ></script>
  <style>
    * {
      margin: 10px;
    }
  </style>
</head>
<form
  action="http://192.168.108.201:5000/delete"
  method="POST"
  target="iframe1"
>
  <input type="text" name="id" />
  <input type="submit" value="삭 제" /><br />
</form>
<iframe id="iframe1" name="iframe1"></iframe>
# default.conf

server {
    listen       80;
    server_name  _;
    location /test {
        add_header 'Content-Type' 'text/plain';
        return 200 "Host=$host  Path=$request_uri  From=$hostname  ClientIP=$remote_addr  XFF=$http_x_forwarded_for\n";
    }
    location / {
        root    /usr/share/nginx/html;
        index   index.html;
    }
}

 

kubernetes 설정

  • # web.yml
    
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: web
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: web
      template:
        metadata:
          labels:
            app: web
        spec:
          containers:
          - name: web
            image: hkang4628/web:1
            ports:
            - containerPort: 80
              protocol: TCP
            livenessProbe:
              httpGet:
                path: /index.html
                port: 80
                scheme: HTTP
              initialDelaySeconds: 5
              periodSeconds: 5
              timeoutSeconds: 1
              successThreshold: 1
              failureThreshold: 2
            volumeMounts:
            - mountPath: /usr/share/nginx/html
              name: pvc-volume-web
              subPath: src
            - mountPath: /etc/nginx/http.d
              name: pvc-volume-web
              subPath: config
          volumes:
          - name: pvc-volume-web
            persistentVolumeClaim:
              claimName: pv-claim-web
    

 

service

# web_service.yml

apiVersion: v1
kind: Service
metadata:
  name: web-service
  labels:
    app: web
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    app: web

 

 

 

WAS 설정

  • python 도커 파일 설정
  •  
#Dockerfile

FROM python

WORKDIR /usr/src/app

COPY app.py ./
#COPY requirements.txt ./
#RUN pip install --no-cache-dir -r requirements.txt
RUN pip install flask pymysql flask_cors


CMD [ "python", "./app.py" ]

EXPOSE  5000/tcp
# app.py
from flask import Flask, redirect, request, jsonify, url_for
import pymysql
from flask_cors import CORS

app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False
CORS(app)

@app.route('/')
def board():
    try:
        with pymysql.connect(host='192.168.108.10', user='root', password='Test12#$', db='students') as con:
            cur = con.cursor()
            cur.execute("select * from users")
            rows = cur.fetchall()
    except Exception as e:
        print(e)
        return "board error"
    print(rows)
    return jsonify(rows)

@app.route('/search', methods=['POST'])
def search():
    if request.method == 'POST':
        result = request.form['search']
        print(result)
        try:
            with pymysql.connect(host='192.168.108.10', user='root', password='Test12#$', db='students') as con:
                cur = con.cursor()
                cur.execute(f"select * from users WHERE name='{result}'")
                rows = cur.fetchall()
        except Exception as e:
            print(e)
            return "search error"
        print(rows)
        return jsonify(rows)

@app.route('/add', methods=['GET', 'POST'])
def add():
    if request.method == 'POST':
        try:
            id = request.form['id']
            name = request.form['name']
            phone = request.form['phone']
            address = request.form['address']
            with pymysql.connect(host='192.168.108.10', user='root', password='Test12#$', db='students') as con:
                cur = con.cursor()
                cur.execute(
                    f"INSERT INTO users (id, name, phone, address) VALUES('{id}', '{name}', '{phone}', '{address}')")
                con.commit()
        except Exception as e:
            print(e)
            return "add error"
    return "add success"

@app.route('/delete', methods=['GET', 'POST'])
def delete():
    if request.method == 'POST':
        id = request.form['id']
        print(id)
        try:
            with pymysql.connect(host='192.168.108.10', user='root', password='Test12#$', db='students') as con:
                cur = con.cursor()
                cur.execute(f"DELETE FROM users WHERE id='{id}'")
                con.commit()
        except Exception as e:
            print(e)
            return "delete error"
        return "delete success"

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

 

 

  • kubernetes
# was.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: was
spec:
  replicas: 3
  selector:
    matchLabels:
      app: was
  template:
    metadata:
      labels:
        app: was
    spec:
      containers:
      - name: was
        image: hkang4628/was:1
        ports:
        - containerPort: 5000
          protocol: TCP
        readinessProbe:
          httpGet:
            path: /
            port: 80
            scheme: HTTP
          initialDelaySeconds: 5
          periodSeconds: 5
          timeoutSeconds: 1
          successThreshold: 2
          failureThreshold: 2
        volumeMounts:
        - mountPath: /usr/src/app
          name: pvc-volume-was
          subPath: src

      volumes:
      - name: pvc-volume-was
        persistentVolumeClaim:
          claimName: pv-claim-was
# was_service.yml

apiVersion: v1
kind: Service
metadata:
  name: was-service
  labels:
    app: was
spec:
  type: ClusterIP
  ports:
    - port: 5000
      targetPort: 5000
      protocol: TCP
  selector:
    app: was

 

  • flask 연동

pip install flask

pip install pymysql

pip install flask_cors

 

DB 설정

 

linux 설정

  • yum install -y mariadb-server
  • mysql_secure_installation
  • firewall-cmd --add-port=3306/tcp --per
  • systemctl enable mariadb —now
  • 192.168.108.10
  •  
  •  
  • DB 설정
  • show variables like 'c%';
  • 한글 설정
# my.cnf

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mariadb according to the
# instructions in http://fedoraproject.org/wiki/Systemd
init_connect = "SET collation_connection = utf8_general_ci"
init_connect = "SET NAMES utf8"
character-set-server = utf8
collation-server = utf8_general_ci

[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid

#
# include all files from the config directory
#
!includedir /etc/my.cnf.d
[mysql]
default-character-set = utf8

CREATE DATABASE students;

CREATE TABLE students.users(
    no INT NOT NULL AUTO_INCREMENT, # AUTO_INCREMENT: 해당 칼럼의 값이 자동으로 1씩 증가된다.
    id VARCHAR(255) NOT NULL,
    name VARCHAR(255) NOT NULL,
    phone VARCHAR(255) NOT NULL,
    address VARCHAR(255) NOT NULL,
    PRIMARY KEY (no) # 고유키로 설정할 컬럼
);

grant all privileges on . to 'root'@'%' identified by 'Test12#$';

FLUSH PRIVILEGES;

 

DNS 설정

alpine 에 dns 설정

#Dockerfile for dns

FROM	alpine:3.17

RUN		  apk upgrade
RUN     apk add bind

COPY    named.conf.authoritative /etc/bind
COPY    sazo.com.zone   /var/bind

CMD     ["/usr/sbin/named", "-c", "/etc/bind/named.conf.authoritative", "-g"]

EXPOSE  53/udp
EXPOSE  53/tcp
#named.conf.authoritative
// Copy this file to /etc/bind/named.conf if you want to run bind as an
// authoritative nameserver. If you want to run a recursive DNS resolver
// instead, see /etc/bind/named.conf.recursive.
//
// BIND supports using the same daemon as both authoritative nameserver and
// recursive resolver; it supports this because it is the oldest and original
// nameserver and so was designed before it was realized that combining these
// functions is inadvisable.
//
// In actual fact, combining these functions is a very bad idea. It is thus
// recommended that you run a given instance of BIND as either an authoritative
// nameserver or recursive resolver, not both. The example configuration herein
// provides a secure starting point for running an authoritative nameserver.

options {
        directory "/var/bind";

        // Configure the IPs to listen on here.
        listen-on { any; };
        listen-on-v6 { none; };

        // If you want to allow only specific hosts to use the DNS server:
        //allow-query {
        //      127.0.0.1;
        //};

        // Specify a list of IPs/masks to allow zone transfers to here.
        //
        // You can override this on a per-zone basis by specifying this inside a zone
        // block.
        //
        // Warning: Removing this block will cause BIND to revert to its default
        //          behaviour of allowing zone transfers to any host (!).
        allow-transfer {
                none;
        };

        // If you have problems and are behind a firewall:
        //query-source address * port 53;

        pid-file "/var/run/named/named.pid";

        // Changing this is NOT RECOMMENDED; see the notes above and in
        // named.conf.recursive.
        allow-recursion { none; };
        recursion no;
};

// Example of how to configure a zone for which this server is the master:
//zone "example.com" IN {
//      type master;
//      file "/etc/bind/master/example.com";
//};

// You can include files:
//include "/etc/bind/example.conf";

zone "sazo.com" IN {
        type master;
        file "sazo.com.zone";
        allow-update { none; };
};
#sazo.com.zone

$TTL 1D
@       IN SOA  ns1.sazo.com. web.sazo.com. (
                                        0       ; serial
                                        1D      ; refresh
                                        1H      ; retry
                                        1W      ; expire
                                        3H )    ; minimum
        NS      ns1.sazo.com.
        MX 10   mx1.sazo.com.

@       A       192.168.108.200
ns1     A       192.168.108.200

www     A       192.168.108.201
mx1     A       172.17.0.10

 

  • kubernetes 설정

deployment

# dns.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: dns
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dns
  template:
    metadata:
      labels:
        app: dns
    spec:
      containers:
      - name: dns
        image: hkang4628/dns:1
        ports:
        - containerPort: 53
          protocol: TCP
        - containerPort: 53
          protocol: UDP

 

service

apiVersion: v1
kind: Service
metadata:
  name: dns-service
  labels:
    app: dns
spec:
  type: LoadBalancer
  ports:
    - port: 53
      targetPort: 53
      protocol: UDP
  selector:
    app: dns

 

NFS 설정

  • nfs 설정mkdir /web /was
  • vi /etc/exports
  • yum install -y nfs-utils
/web   192.168.108.0/24(rw,sync,no_subtree_check,no_root_squash)
/was   192.168.108.0/24(rw,sync,no_subtree_check,no_root_squash)

systemctl enable nfs —now

 

 

 

pv, pvc 설정

# pv.yml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv-web
  labels:
    data: web
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  storageClassName: manual
  persistentVolumeReclaimPolicy: Delete
  nfs:
   server: 192.168.108.20
   path: /web
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv-was
  labels:
    data: was
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  storageClassName: manual
  persistentVolumeReclaimPolicy: Delete
  nfs:
   server: 192.168.108.20
   path: /was
# pvc.yml

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pv-claim-web
  labels:
    app: web
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi
  storageClassName: manual
  selector:
    matchLabels:
      data: web
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pv-claim-was
  labels:
    app: was
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi
  storageClassName: manual
  selector:
    matchLabels:
      data: was

 

 

 

 

Health check

liveness probe 설정 화면