Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Today
Total
관리 메뉴

쟝이의 세상

웹 게시판 소스코드를 POD로 Deployment 본문

자료

웹 게시판 소스코드를 POD로 Deployment

zyangee 2024. 10. 15. 18:10
📎 리눅스 웹 DB 연동했던 소스코드를 POD로 디플로이먼트(replicas=5) 하기
환경: Rocky Linux 9.3 (rhel centos fedora)

<< 진행 순서 >>
1) 웹 DB 연동에 필요한 프로그램 설치 및 확인
2) Dockerfile 생성
3) Dockerfile + index.php 이미지 빌드
4) 이미지 태깅
5) 도커허브에 업로드
6) MySQL) PV → PVC → Deployment 생성
7) POD에 user 생성 및 권한 부여
8) MySQL) Service 생성
9) Board) Deployment → Service 생성
10) Cluster IP / POD IP / NodePort / External IP 로 홈페이지 접속

<< Kubernetes 서비스 구성도 >>

 

 

📌 httpd 설치 및 방화벽 열어주기

yum update

#웹 서버 설치
yum install httpd -y

systemctl start httpd
systemctl enable httpd
systemctl status httpd

#웹 방화벽 열어주기
systemctl start firewalld
systemctl enable firewalld
systemctl status firewalld

firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload

 

✔️ index.html 파일 생성하여 curl 명령어로 열리는지 확인

- index.html 생성

cd /var/www/html
echo "<h2>웹페이지 테스트</h2>" | sudo tee /var/www/html/index.html

 

- curl 명령어로 확인

curl http://192.168.56.100

 

📌 mysql 설치

#mysql 설치
yum install mysql-server -y

#mysql 서비스 실행
systemctl start mysqld
systemctl enable mysqld
systemctl status mysqld

 

✔️ 확인작업

mysql -u root

 

📌 php 설치

dnf install php php-mysqlnd php-pdo -y
systemctl restart httpd

 

✔️ info.php 생성

echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/info.php

 

📌 Database 생성

#mysql root로 로그인
mysql -u root

#database 생성
create database board;
use board;

#user생성
create user 'boarduser'@'localhost' identified by 'Boarduser!@';
grant all privileges on board.* to 'boarduser'@'localhost';
flush privileges;

 

✔️ index.php 파일 생성 및 접속

(위치: /var/www/html/board/index.php)

👇🏻 index.php 코드 보기

더보기
<?php
$servername = "localhost";
$username = "boarduser";
$password = "Boarduser!@";
$dbname = "board";

try {
    // PDO 인스턴스 생성
    $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
    // 에러 모드 설정
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // 테이블 생성
    $sql = "CREATE TABLE IF NOT EXISTS test (
        id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
        title VARCHAR(30) NOT NULL,
        content TEXT NOT NULL,
        reg_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
    )";
    $conn->exec($sql);
    echo "Table test created successfully";

    // POST 요청 처리
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $title = $_POST['title'];
        $content = $_POST['content'];

        // Prepared statement 사용
        $stmt = $conn->prepare("INSERT INTO test (title, content) VALUES (:title, :content)");
        $stmt->bindParam(':title', $title);
        $stmt->bindParam(':content', $content);

        if ($stmt->execute()) {
            echo "New record created successfully";
        } else {
            echo "Error: Unable to create record.";
        }
    }

    // 데이터 조회
    $sql = "SELECT id, title, content, reg_date FROM test";
    $stmt = $conn->query($sql);

    if ($stmt->rowCount() > 0) {
        echo "<h2>Posts</h2>";
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            echo "<div>";
            echo "<h3>" . htmlspecialchars($row['title']) . "</h3>";
            echo "<p>" . htmlspecialchars($row['content']) . "</p>";
            echo "<small>Posted on " . $row['reg_date'] . "</small>";
            echo "</div><hr>";
        }
    } else {
        echo "0 results";
    }
} catch (PDOException $e) {
    echo "Connection failed: " . $e->getMessage();
}

// 연결 종료
$conn = null;
?>

<h2>Create Post</h2>
<form method="post" action="">
    Title: <input type="text" name="title" required><br>
    Content: <textarea name="content" required></textarea><br>
    <input type="submit">
</form>

 

✔️ Docker Image 생성을 위해 꼭 옮겨주기

mv /var/www/html/board ~/mission/app

 

→ 디렉토리 이동 후 ~/mission/app/index.php 파일 수정

<?php
$servername = "mysql";
...(생략)

 

📌 Dockerfile 생성 및 yaml 파일 생성

✔️ Dockerfile과 index.php 및 deployment 파일 위치

~/mission
│
├── Dockerfile
│
├── app
|     └── index.php
├── mysql-deployment.yaml
|
└── php-deployment.yaml

 

✔️ Dockerfile 생성

vi ~/mission/Dockerfile

👇🏻 Dockerfile 코드

더보기
FROM php:8.0-apache
COPY ./app /var/www/html/
RUN docker-php-ext-install pdo pdo_mysql
# 포트 노출
EXPOSE 80

 

✔️ deployment 파일 생성

(위치: ~/board_workspace/board-deployment.yaml)

더보기
apiVersion: apps/v1
kind: Deployment
metadata:
  name: board
spec:
  replicas: 3
  selector:
    matchLabels:
      app: board
  template:
    metadata:
      labels:
        app: board
    spec:
      containers:
      - name: board
        image: zyange/board:1.0
        ports:
        - containerPort: 80
        env:
        - name: DB_HOST
          value: mysql
        - name: DB_USER
          value: boarduser
        - name: DB_PASSWORD
          value: Boarduser!@
        - name: DB_NAME
          value: board
---
apiVersion: v1
kind: Service
metadata:
  name: board
spec:
  type: LoadBalancer
  ports:
    - port: 80
  selector:
    app: board

 

✔️ MySQL Deployment 파일 생성

(위치: ~/board_workspace/mysql-deployment.yaml)

더보기
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /var/lib/mysql  # 호스트에서 데이터가 저장될 경로
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:8.0
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: P@ssw0rd
            - name: MYSQL_DATABASE
              value: board
            - name: MYSQL_USER
              value: boarduser
            - name: MYSQL_PASSWORD
              value: Boarduser!@
          ports:
            - containerPort: 3306
          volumeMounts:
            - name: mysql-storage
              mountPath: /var/lib/mysql  # 로컬의 이 위치에 폴더를 생성
          resources:
            requests:
              memory: "1Gi"
            limits:
              memory: "2Gi"
      volumes:
        - name: mysql-storage
          persistentVolumeClaim:
            claimName: mysql-pvc

 

✔️ MySQL Service 파일 생성

(위치: ~/board_workspace/mysql-service.yaml)

더보기
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  type: ClusterIP
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: mysql

 

✔️ image build

docker build -t board:1.0 .

 

✔️ image tag

docker tag board:1.0 zyange/board:1.0

 

✔️ image push

docker login
docker push zyange/board:1.0
‼️중요
쿠버네티스에서 image를 사용하는 Deployment를 정의할 때,
기본적으로 컨테이너 이미지는 이미 push된 레지스트리(Docker Hub)에서 가져오기 때문에
내가 만든 이미지를 push 해줘야 한다.
(mysql의 경우엔 이미 push되어 있는 image를 가져옴)

 

(master node에 pod를 올리고 싶다면?) k8smaster Taint 제거

kubectl describe node k8smaster | grep Taint
kubectl taint nodes k8smaster node-role.kubernetes.io/control-plane:NoSchedule-

 

deployment와 service 생성하기 전에 mysql, http는 stop 또는 remove 해주기!!

 

📌 mysql deployment, service 생성

💡 순서 중요
- MySQL의 DeploymentPVC는 데이터베이스의 내부 상태와 스토리지에 관련된 중요한 자원이다.
반면, Service는 데이터베이스에 네트워크로 접근할 수 있는 엔드포인트를 정의한다.

- Service를 나중에 생성해야 내부 Pod가 제대로 준비된 상태에서 연결이 원활하게 이루어진다.
만약, 내부 Pod가 준비해되지 않은 상태에서 Service를 먼저 배포하면 네트워크 연결이 실패되거나 CrashLoopBackOff와 같은 문제가 발생할 수 있다.

하나의 yaml 파일로 작성할 때는 **코드 작성 순서** 가 중요하다.
yaml 파일 작성 순서 1) PersistentVolume (PV)
PVC가 바인딩되기 위해 PV가 먼저 생성되어야 한다.
2) PersistentVolumeClain(PVC)
Deployment가 스토리지를 사용하려면 PVC가 먼저 바인딩되어야 한다.
3) Deployment
Pod가 PVC로부터 스토리지를 바인딩해 사용한다.
4) Service
Pod가 준비된 후 Service를 통해 외부에서 접근할 수 있게 된다.
왜 순서가 중요한지??
- PVC가 생성되기 전에 Deployment가 실행되면 스토리지를 찾을 수 없다.
- Deployment가 생성되기 전에 PV와 PVC가 준비되어야 정상적으로 바인딩된다.
- Service는 Pod가 준비된 후에 작동해야 의미가 있으므로 마지막에 생성하는 것이 좋다.

** PV - PVC - Deployment - Service ** 순서로 작성!!

 

✔️ yaml 파일을 통해 먼저 mysql-deployment 생성

kubectl apply -f mysql-deployment.yaml

 

✔️ pod로 들어가서 user 생성

k exec -it mysql-7c9f5d75d9-c5b59 -- bash

mysql -u root -p
Enter password: [아무것도 없이 Enter]

mysql> alter user 'root'@'localhost' identified by 'P@ssw0rd';
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| board              |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
mysql> create user 'boarduser'@'%' identified by 'Boarduser!@';
Query OK, 0 rows affected (0.01 sec)

mysql> grant all privileges on board.* to 'boarduser'@'%';
Query OK, 0 rows affected (0.01 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> exit

 

✔️ yaml 파일을 통해 mysql-service 생성

kubectl apply -f mysql-service.yaml

 

📌 board deployment, service 생성

kubectl apply -f board-deployment.yaml

 

✔️ curl 명령을 통해 board 서비스에 접속 시도

curl http://10.108.1.163

→ successfully로 데이터베이스에 연결된 것을 확인할 수 있음

👇🏻 cluster IP로 접속해서 데이터베이스 삽입

더보기

📎 결과 화면

📎 삽입한 데이터 확인해보기

k exec -it mysql-7587466cbf-qltcj -- bash
mysql -u root -p

mysql> use board;
Database changed

mysql> show tables from board;
+-----------------+
| Tables_in_board |
+-----------------+
| test            |
+-----------------+
1 row in set (0.00 sec)

mysql> select * from test;
+----+---------+---------+---------------------+
| id | title   | content | reg_date            |
+----+---------+---------+---------------------+
|  1 | zyangee | today   | 2024-10-16 06:14:20 |
+----+---------+---------+---------------------+
1 row in set (0.00 sec)

 

✔️ pod의 IP와 service의 IP로 접속 / nodePort로 접속

 

✔️ external IP로 접속

 

'자료' 카테고리의 다른 글

BeEF를 활용하여 모의해킹  (0) 2024.10.21
AWS에서 EC2 인스턴스 배포 과정  (0) 2024.10.17
SQLMap을 활용하여 모의해킹  (0) 2024.10.15
Nikto를 활용하여 취약점 진단  (0) 2024.10.11
Nmap을 활용하여 취약점 진단  (0) 2024.10.11