티스토리 뷰
[Kubernetes] 쿠버네티스와 도커를 활용하여 웹서비스 배포하기 프로젝트 2주차 : 진행 상황 및 에러 슈팅 | 502 Bad Gateway | DB 초기 설정 오류
YouJungJang 2023. 12. 4. 04:00
1. Database를 구성하는 StatefulSet
프론트, 백엔드, 데이터 베이스 각각의 모든 오브젝트 매니페스트 파일을 만들고 실행 한 뒤 파드 로그를 띄웠을 때
백엔드 서버 파드가 가동되자마자 죽는 CrashLoopBackOff 에러가 발생했다.
또한 인그레스와 서비스가 잘 연결됐는지 확인하는 명령어를 실행했을 때 아래와 같이 백엔드 서비스가 빈칸으로 비워져 있었다.
당연히 인그레스의 External IP로 접속하면 오류가 나왔다.
나는 위에서 언급한 이유들로 인해 현재 오류가 백엔드 파드에서 발생했다고 생각했다.
백엔드 파드에서 오류가 발생하는 여러 원인을 생각해 봤는데, 우리가 구성한 백엔드 파드는 DB 파드가 제대로 동작하지 않으면 절대 작동할 수 없다. 또한 백엔드의 디플로이먼트와 서비스 yaml 파일은 단순하기 때문에 백엔드를 구성하는 오브젝트 자체에서는 큰 오류를 찾지 못했다.
그래서 DB를 구성하는 오브젝트 특히 'Statefulset.yaml'파일을 뜯어고치기로 했다.
[1] db_init.sql 실행 안 되는 이슈
Statefulset 매니페스트 파일을 생성하고 적용한 뒤 생성된 파드에 직접 접근해 보자
kubectl exec -it [DB 파드 명] -- bash
아래 명령어로 접근하면 DB 파드의 bash로 접근할 수 있다.
그럼 이제 mysql client server를 실행하면 되는데 우리 DB는 mariadb를 사용하므로 아래 명령어를 사용했다.
mariadb -uroot -p
그리고 생성된 DB를 확인했더니 웬걸, 생성된 DB가 없었다. Docker 컨테이너에 같이 마운트 해준 db_init.sql 이 실행되지 않은 것이다.
그래서 db_init.sql 파일을 확인해 보니 데이터베이스 초기 설정문에서 '데이터 베이스 생성부'와 '사용 선언부'가 빠져있고 Create Table 구문만 있었다. 애초에 데이터 베이스를 생성하지도 않고 테이블을 생성하려고 하니 초기 설정이 하나도 이뤄지지 않은 것 같아서 이를 해결하기 위한 몇 가지 방법을 생각했다.
1) Config Map 작성해서 적용하기
apiVersion: v1
kind: ConfigMap
metadata:
name: mariadb-initdb-config
data:
init.sql: |
CREATE DATABASE IF NOT EXISTS sc_db;
use sc_db;
CREATE TABLE `User` (
`user_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_name` varchar(45) NOT NULL,
`user_pwd` varchar(60) NOT NULL,
`user_email` varchar(45) NOT NULL,
PRIMARY KEY (`user_id`),
UNIQUE KEY `user_id_UNIQUE` (`user_id`),
UNIQUE KEY `user_email_UNIQUE` (`user_email`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
#(..중략..)
아래와 같이 컨피그 맵을 작성하고 create 해준 뒤 스테이트풀셋 매니페스트 파일에 마운트 하려고 했는데 결론적으로 이 방법은 실패했다. 아래 태그를 어떤 자리에 둬도 apply 할 때 오류가 나거나 정상적으로 셋이 생성돼도 pod는 생성되지 않는 원인 모를 에러가 났다. 그래서 다음 방법을 사용하기로 했다.
volumes:
- name: sc-pv
configMap:
name: mariadb-initdb-config # configMap 설정
2) db_init.sql 수정 후 Docker image 새로 빌드하기
기존 테이블 생성문만 있던 db_init.sql 파일에 DB 생성과 USE 문을 추가하고 새로운 도커 이미지를 만들어 Docker Hub에 Push 해줬다. 기존 youjung819/sc_database:1.0에서 youjung819/sc_database:2.0으로 바뀐 것이다. StatefulSet 매니페스트 파일에서 컨테이너 이미지 부분 태그를 2.0으로 수정해 주고, 컨테이너 'VolumeMount' 부분에 'mountPath: /docker-entrypoint-initdb.d'를 추가해서 해당 폴더에 .sql 파일이 존재할 때 Container 생성 시 실행하도록 했다.
volumeMounts: ## 특징③ 컨테이너상의 마운트 경로 설정
- name: pvc
mountPath: /docker-entrypoint-initdb.d # 해당 폴더에 .sql 파일 존재 시 Container 생성 시 실행
그런데 결론적으로 이번에도 역시 init 파일이 실행되지 않았다.
🙀🙀
내가 생각하는 원인은 아래와 같이 mountPath 두 개가 있어서 인 것 같은데,
위에 있는 것은 내가 추가한 것, 아래 것은 원래 있던 것이다. (매니페스트 파일.. 너무 비직관적이고 불친절해서 정말 어렵다)두 개를 어떻게 둘지 몰라 아래와 같이 뒀는데 아마 여기 부분에서 뭔가 혼선이 생긴 것 아닐까 추측해 본다.
그래서 결국 컨테이너에 들어가 init 파일을 직접 실행시켰다.
명령어는 아래와 같다.
mariadb -u root -p < db_init.sql
그 결과 DB는 올바르게 생성되었고 테이블도 잘 만들어져 있는 것을 확인했다.
[2] Secret이 적용되지 않는 이슈
맨 처음 statefulset을 실행할 때는 실습했던 데로 아래와 같이 DB의 root 계정 비밀번호를 그대로 노출시킨 채로 작성했다.
하지만 보안을 위해 secret 파일을 아래와 같이 새로 작성했다.
apiVersion: v1
kind: Secret
metadata:
name: scdb-secret
data:
password: c2NjaGF0dGluZw==
그리고는 해당 시크릿을 statefulset.yml 파일의 env 태그에 적용시켜 줬는데
DB 컨테이너 bash에서 mariadb -uroot -p 명령어로 DB에 접근하려고 할 때 비밀 번호를 아무리 입력해도 틀렸다고 했다. 설마 하고 예전 비밀번호 'qwerty'를 입력했더니 접속되었다.
분명 Statefulset을 없애고 다시 apply 했는데 왜 적용이 안돼있을까 PV라서 그런 걸까? 그럼 아예 PV 마운트를 지웠다가 다시 설정해야 하는 걸까? 좀 더 공부가 필요한 부분이다.
2. 502 Bad Gateway 에러
'kubectl describe ing' 명령어를 사용해서 인그레스 정보를 띄웠을 때 프론트 엔드 서비스와 백엔드 서비스의 포트 번호가 올바르게 뜨는 것을 확인하고 (원래는 백엔드에 아무런 정보도 뜨지 않았다)
인그레스의 ExternalIP로 접속하려고 하자 502 Bad Gateway 에러 화면이 나온다.
해당 에러는 게이트웨어, 즉 서로 다른 프로토콜을 연결해 주는 장치가 잘못된 프로토콜을 연결하거나 어느 쪽 프로토콜에 문제가 있어 통신이 제대로 되지 않을 때 출력되는 코드라고 한다.
아마 내 생각에는 기존 서비스의 백엔드와 프론트 엔드 소스 코드에서 api를 사용해 통신하는 것을 클러스터에 제대로 반영하지 않아서 생긴 오류인 것 같다.
그래도 비어있던 백엔드 서비스에 포트번호를 확인할 수 있다는 것만으로도 큰 발전이라고 생각한다. 아직 일주일 더 남았으니 남은 시간 동안 꼭 해결해 보겠다!