몇 개월 전에 쿠버네티스에 MariaDB를 설치하면서 시놀로지 NAS를 NFS서버로 구성하여 Persistent Volume을 생성한 다음 MariaDB Pod에 연결하는 작업을 진행했다.
처음 진행해보는 이 작업은 정말 까다롭고 어려웠던 것으로 기억된다. 단순하게 MariaDB를 설치하는 것이면 그다지 어렵지 않았겠지만 시놀로지 NAS를 NFS로 연결하여 Persistent Volume으로 사용할 수 있도록 설정하는 과정이 쉽지는 않았다. 어쨌든 그 작업은 성공했고 아래 화면처럼 POD에 Shell로 연결하여 df 명령을 실행하면 시놀로지 NAS의 NFS 디렉토리가 컨테이너의 /var/lib/mysql 디렉토리에 마운트되어 Database 경로로 사용되고 있음을 알 수 있다.

이제 MariaDB 컨테이너에 연결하여 동작하는 워드프레스를 쿠버네티스 클러스터에 설치하는 과정을 포스팅한다.
MariaDB에 워드프레스 데이터베이스 생성하고 사용자 계정 만들기
워드프레스를 설치하기 위해서는 먼저 워드프레스가 사용할 데이터베이스와 사용자 계정을 MariaDB에 생성해야 한다. DBeaver를 사용해 생성하거나 MariaDB의 컨테이너(POD)에 쉘 접속하여 mysql 또는 mariadb 명령어로 MariaDB DBMS에 접속하여 다음의 SQL문을 실행해야 한다.
CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER 'taeho'@'%' IDENTIFIED VIA mysql_native_password USING PASSWORD('1qaz2wsx');
GRANT ALL PRIVILEGES ON wordpress.* TO 'taeho'@'%';
FLUSH PRIVILEGES;
이 SQL문에서 데이터베이스 이름은 wordpress와 계정명인 taeho 그리고 비밀번호는 잘 기억해두어야 한다. 아래에서 생성할 WordPress 디플로이먼트 파일(yaml)에서 사용되기 때문이다.
워드프레스 디플로이먼트 구성하고 배포하기
쿠버네티스에는 POD(포드 또는 파드 라고 읽음)라는 컨테이너 관리 단위가 있다. POD는 최소 1개의 컨테이너를 포함하는 쿠버네티스의 최하위 응용프로그램 관리 단위로서 POD내의 컨테이너들은 동일한 네트워크와 스토리지를 공유할 수 있다. 그리고 보다 큰 단위인 디플로이먼트(Deployment)가 있다. 디플로이먼트는 파드를 포함하는데 리플리카(Replica)라는 개념을 도입해 동일한 POD를 몇 개를 유지할지를 정할 수 있다. 특정 파드가 실행 중 오류로 인해 종료될 경우 지정된 개수를 채우기 위해 POD를 추가로 실행하게 된다.
어쨌든 여기서는 디플로이먼트를 정의하고 배포하는 YAML 파일을 작성하여 워드프레스를 설치하고 배포하기로 한다.
디플로이먼트를 통한 설치 및 배포 작업은 kubectl 명령을 쿠버네티스 클러스터에 실행할 수 있다면 장소를 가리지 않는다. PC에 kubectl 을 설치하고 클러스터에 연결하여 실행할 수도 있고 마스터 노드에 SSH 접속하여 실행할 수도 있다. 여기서는 마스터 노드에 접속하여 실행하도록 한다.
워드프레스 디플로이먼트 YAML 작성하고 배포(Deploy)하기
워드프레스를 배포하기 위한 YAML 파일을 다음과 같이 작성한다. 여기서는 이미 작성된 YAML 파일을 cat 명령으로 보는 것으로 대체한다.
taeho@k8s-master-a:~$ cat wordpress-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress-deployment
spec:
replicas: 1
selector:
matchLabels:
app: wordpress
template:
metadata:
labels:
app: wordpress
spec:
containers:
- name: wordpress
image: wordpress:latest
ports:
- containerPort: 80
env:
- name: WORDPRESS_DB_HOST
value: mariadb-svc:3306
- name: WORDPRESS_DB_NAME
value: wordpress
- name: WORDPRESS_DB_USER
value: taeho
- name: WORDPRESS_DB_PASSWORD
value: 1qaz2wsx
volumeMounts:
- name: wordpress-storage
mountPath: /var/www/html
volumes:
- name: wordpress-storage
emptyDir: {}
taeho@k8s-master-a:~$
replicas는 1로 정의하여 워드프레스 디플로이먼트에서는 POD를 1개만 실행하는 것으로 한다. replicas를 2로 하여 배포하면 워드프레스 POD가 2개가 실행된다.
containers: 의 image: 에서는 컨테이너 레지스트리(여기서는 기본값인 dockerhub를 의미함)에서 wordpress의 가장 최신(latest) 이미지를 가져와 POD로 빌드하도록 정의한다. 웹 서비스 포트는 80을 사용한다.
환경변수에서는 DB HOST를 먼저 설치해 둔 mariadb-svc에서 정의한 컨테이너의 3306 포트에 MariaDB가 있음을 정의하고 DB이름과 계정 그리고 패스워드를 지정해준다. 그리고 컨테이너가 종료되었을 때 워드프레스가 실행되는 동안 변경된 값들이 사라지지 않도록 /var/www/html을 비어있는 공간을 지정하고 그 공간에 임시로 저장하도록 한다. 다만 POD나 디플로이먼트를 삭제하면 변경된 값들은 함께 삭제된다. 테스트용으로 적합한 방법이다.
이 yaml 파일을 사용해 쿠버네티스에 워드프레스 POD를 디플로이(배포)한다. kubectl 명령으로 다음과 같이 실행한다.
$ kubectl create -f wordpress-deployment.yaml
이 명령을 실행하면 도커허브에서 wordpress 최신 이미지를 내려받아 yaml 파일에서 정의한 설정을 적용하여 쿠버네티스의 클러스터에 배포(Deploy)한다. 그리고 배포한 POD는 다음 명령으로 확인할 수 있다.
taeho@k8s-master-a:~$
taeho@k8s-master-a:~$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
mariadb-deployment 1/1 1 1 120d
wordpress-deployment 1/1 1 1 5h40m
taeho@k8s-master-a:~$
taeho@k8s-master-a:~$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mariadb-deployment-78448bf7db-tvj56 1/1 Running 2 (4h27m ago) 6h30m 10.0.1.111 k8s-worker-a <none> <none>
wordpress-deployment-6fdcd5dbc6-5mskz 1/1 Running 1 (4h27m ago) 5h40m 10.0.1.173 k8s-worker-b <none> <none>
taeho@k8s-master-a:~$
두개의 디플로이먼트가 배포되어 있다. 먼저 배포한 mariadb-deployment가 있고 조금 전 배포한 wordpress-deployment가 있다. 그리고 각각의 디플로이먼트에 의해 배포된 POD 2개가 kubectl get pods 명령에 의해 조회되었다.
mariadb POD는 k8s-worker-a 노드에서 10.0.1.111 IP를 할당받아 실행중이고 wordpress POD는 k8s-worker-b 노드에서 10.0.1.173 IP를 할당받아 실행되고 있다. 이 IP는 POD를 재실행하거나 쿠버네티스 워커 노드를 재실행하면 수시로 변경된다.
다음은 실행된 POD에 외부에서 접속할 수 있도록 서비스를 생성하여 워커 노드를 통해 컨테이너에 접속할 수 있도록 해주어야 한다.
워드프레스 서비스 YAML 작성하고 워커 노드와 연결하기
쿠버네티스에서 서비스(Service)는 엔드포인트(endpoint)인 컨테이너에 할당된 IP/Port에 연결된 워커 노드 포트( Port)의 정의 라고 할 수 있다. 다음과 같이 워드프레스 서비스 파일을 작성한다.
taeho@k8s-master-a:~$ cat wordpress-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: wordpress-svc
spec:
type: NodePort
selector:
app: wordpress
ports:
- port: 80
targetPort: 80
nodePort: 30800 # 원하는 외부 노출 포트
taeho@k8s-master-a:~$
이 서비스를 적용할 앱의 이름은 wordpress다. wordpress-deployment.yaml 에서 정의한 APP의 이름과 동일하게 정의한다.
유형은 NodePort다. 즉 워드프레스 컨테이너의 서비스는 워커 노드의 Port를 할당받아 연결한다는 의미다. 즉 워커 노드의 30080 포트를 워드프레스 컨테이너의 80 번 포트에 연결한다는 의미다.
이 파일을 저장한 후 다음의 명령으로 컨테이너의 포트와 워커 노드의 포트를 연결해준다. 일종의 포트 포워딩인 셈이다.
$ kubectl create -f wordpress-svc.yaml
연결된 서비스는 다음과 같이 확인할 수 있다.
taeho@k8s-master-a:~$
taeho@k8s-master-a:~$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 243d
mariadb-svc NodePort 10.105.135.39 <none> 3306:30006/TCP 120d
wordpress-svc NodePort 10.106.153.199 <none> 80:30800/TCP 5h52m
taeho@k8s-master-a:~$
PORT(S)에 보면 mariadb 컨테이너의 3306 포트가 워커 노드의 30006 포트와 연결되어 있음을 알 수 있고 worpress 역시 컨테이너의 80 포트가 워커노드의 30800 포트로 연결되어 있다는 것을 알 수 있다.
설치 실패 시 로그 확인
워드프레스의 설치에 실패했든 성공했든 로그를 확인하는 것이 좋다. 배포된 워드프레스가 처음 실행될 때 발생하는 로그는 다음의 명령으로 확인할 수 있다.
$ kubectl logs wordpress-deployment-6fdcd5dbc6-725bd
wordpress-deployment-6fdcd5dbc6-725bd는 각자 배포된 컨테이너의 이름이다. 즉 kubectl get pods 명령에서 보이는 컨테이너의 이름이다.
워드프레스 초기 설치 화면
정상적으로 워드프레스의 디플로이먼트 배포가 완료되었다면 워커노드의 IP를 기준으로 다음과 같이 접속할 수 있다. 192.168.219.11 IP는 워커노드의 IP다. 여기에서는 워커 노드가 2개 인데 두 워커 노드 중 아무 워커 노드의 IP 뒤에 30800 포트 번호만 지정해주면 접속이 된다.
http://192.168.219.11:30800

언어를 선택하고 Continue 버튼을 누르고 기본 설정을 마치면 설치가 완료된다.

추가로 필요한 작업
기본적인 설치는 완료되었지만 로드밸런서의 적용, HTTPS의 적용, POD의 접근통제를 위한 Network Policy 적용 등 할일이 넘쳐나지만 개념적으로 가장 이해하기 어렵고 생소한 작업단계는 여기까지였던 것 같다. 이 단계까지의 작업 내용을 완벽하게 이해한다면 쿠버네티스라는 오르기 어려운 산의 주 능선까지 오른 것은 아닐까 생각된다.
쿠버네티스를 사용해 정보시스템을 구축하는 이유
이쯤에서 쿠버네티스를 왜 사용하는지를 생각해볼 필요가 있다. 여러 이유가 있겠지만 그 중 하나는 가용성을 높이기 위함이다.
이 테스트 환경은 아래 화면에서 처럼 2대의 물리서버(prxmx, prxmx2)로 구성된 Proxmox 클러스터 위에 쿠버네티스를 설치한 3개의 하이퍼바이저 타입 1의 가상 서버가 실행중인 구성이다. 가상서버 1대는 쿠버네티스 마스터 노드이고 가상서버 2대는 워커 노드다.

그리고 앞의 설치 과정에서 볼 수 있듯 mariadb는 워커노드 중 k8s-worker-a 에서 실행되도록 쿠버네티스에 의해 스케줄링 되었고 wordpress는 워커 노드 중 k8s-worker-b에서 실행되도록 스케줄링 되었다.
이 때 k8s-worker-b 노드가 불시에 장애가 생겨 리눅스 노드 자체가 다운되었다면 이 노드에서 실행되던 워드프레스 컨테이너도 함께 다운될 것이다. 당연히 워드프레스는 접속이 되지 않을 것이다.
이때 쿠버네티스의 진가가 발휘된다. 다음은 k8s-worker-b를 강제로 다운시켰을 때 노드의 상태다.
taeho@k8s-master-a:~$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master-a Ready control-plane 243d v1.29.15
k8s-worker-a Ready worker 243d v1.29.15
k8s-worker-b NotReady worker 243d v1.29.15
taeho@k8s-master-a:~$
k8s-worker-b 노드를 강제로 셧다운 했을 때 해당 노드가 NotReady 상태가 된 것을 확인할 수 있다. 이 상태가 일정시간 계속되고 장애가 발생한 노드가 복구되지 않으면 쿠버네티스는 wordpress 컨테이너를 다른 워커노드 즉 k8s-worker-a에서 재실행하게 된다. 다음이 바로 k8s-worker-a 노드에서 wordpress 컨테이너가 실행된 화면이다.
taeho@k8s-master-a:~$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mariadb-deployment-78448bf7db-tvj56 1/1 Running 2 (5h32m ago) 7h35m 10.0.1.111 k8s-worker-a <none> <none>
wordpress-deployment-6fdcd5dbc6-5mskz 1/1 Terminating 1 (5h32m ago) 6h45m 10.0.1.173 k8s-worker-b <none> <none>
wordpress-deployment-6fdcd5dbc6-djt6z 1/1 Running 0 45s 10.0.1.112 k8s-worker-a <none> <none>
taeho@k8s-master-a:~$
k8s-worker-b 에서 실행되던 wordpress POD는 Terminating 상태로 표시되고 그 아래에 k8s-worker-a에서 wordpress POD가 실행되어 Running 상태인 것을 볼 수 있다.
당연히 웹 브라우저를 통해 접속하면 워드프레스에 접속이 가능하다. 쿠버네티스를 통해 가용성을 획기적으로 높일 수 있는 이유라고 하겠다.
#쿠버네티스 #워드프레스설치 #디플로이먼트
신기한 기술을 간접으로 나마 볼 수 있도록 해주셔서 감사합니다.
귀한 댓글을 남겨주시다니 저야말로 감사합니다. ^^ 즐거운 주말 보내세요~