Ghost 블로그를 쿠버네티스에 배포해보기(gke)
안녕하세요 😉
유유자적한 개발자 유로띠 입니다 😀
👏👏👏👏
이번에 사내에서 gke 스터디를 시작하게 되었습니다.
스터디를 시작하기 전에 gke에 대해서 전혀 모르기 때문에
찾아보다가 유튜브에서
Subicura님의 강의를
찾아서 보게 되었습니다.
초보자도 알기 쉽게 설명해 주셔서
너무 좋았습니다.
쿠버네티스를 이용한 배포 데모 편에서
ghost 블로그를 쿠버네티스에 올리는 시연을 보여주셔서
저도 궁금하여 직접 해보게 되었습니다!
이번 포스팅에서는
✅ 컨테이너 오케스트레이션
✅ 쿠퍼네티스 소개
✅ gke에 Ghost 블로그 배포
에 대해서 알아보겠습니다
컨테이너 오케스트레이션
✅ 서버를 관리한다는 것
💡 (하나하나 캡처를 해서) 문서화를 잘하자!
-> 업데이트가 안될 수 있고, 환경이 바뀌면? 버전이 바뀌면?
💡 서버를 관리하는 관리 도구를 사용하자!
🔴 서버 관리도구 자체를 배워야 한다.
🔴 복잡하게 관리하다 보면 그것에 맞게 관리 도구도 사용하기 복잡해진다.
💡 가상 머신을 사용하자! 머신에 프로그램을 설치하면 버전이나 환경에 따른 문제가 거의 없다.
🔴 클라우드 환경에 잘 맞지 않는다.
🔴 특정 벤더에 의존성이 생긴다.
💡 도커를 사용하자!
🟢 모든 실행환경을 컨테이너로!
🟢 어디서는 동작하기 쉽고 효율적이다!
✅ 도커의 등장
컨테이너의 특징
가상 머신과 비교하여 컨테이너 생성이 쉽고 cpu, 메모리 사용이 효율적입니다.
컨테이너 이미지를 이용한 배포와 롤백이 간단합니다.
언어나 프레임워크에 상관없이 애플리케이션을 동일한 방식으로 관리가 가능합니다.
개발, 테스팅, 운영 환경은 물론 로컬 PC와 클라우드까지 동일한 환경을 구축할 수 있습니다.
오픈소스이기 때문에 특정 클라우드 벤더에 종속적이지 않습니다.
컨테이너화 해서 사용하는 것을 containerization라 합니다.
보통 프로그램 개발 과정은 아래의 흐름을 가집니다.
이러한 방식으로 진행하면 어떠한 언어로 개발을 해도 도커 이미지만 만들면 배포는 쉬워지게 되었습니다.
서버 관리가 쉬워지게 됩니다.
그러나!
컨테이너가 수십 개, 수백 개, 수천 개가 생기게 되면서 많은 것을 관리하려면 여전히 손이 가게 됩니다. 🧐
✅ 컨테이너 오케스트레이션
복잡한 컨테이너 환경을 효과적으로 관리하기 위한 도구로 컨테이너 오케스트레이션이 등장합니다.
-> 서버 관리자가 하는 일들을 대신해주는 어떤 프로그램을 만듭니다.
컨테이너 오케스트레이션의 특징
🟢 클러스터(중앙제어)
🟢 상태 관리
🟢 스케쥴링(배포관리)
🟢 롤아웃/롤백(배포 버전 관리)
🟢 서비스 디스커버리 (서비스 등록 및 조회)
🟢 볼륨(볼륨 스토리지)
컨테이너 오케스트레이션은 개념이기 때문에 다양한 오케스트레이션 도구들이 등장합니다.
DEIS, RANCHER, NOMAD, Docker swarm 등 다양한 도구가 나왔지만쿠버네티스가 표준으로 자리를 잡았습니다.
쿠버네티스 소개
✅ 쿠버네티스 란
컨테이너를 쉽고 빠르게 배포/확장하고 관리를 자동화해주는 오픈소스 플랫폼
클라우드 3대장도 쿠버네티스 서비스를 제공합니다.
✅ 쿠버네티스 이름
The name “Kubernetes” stems from an ancient Greek word for “helmsman,”
(someone who steers a ship, like a container ship) which explains the ship wheel logo
쿠버네티스는 그리스어로 조타수에서 유래했습니다.
gke에 Ghost 블로그 배포
✅ Ghost 란?
Ghost는 강력한 성능, 유연성 및 성능이 필요한 팀을 위해 설계된 최신 Node.js 기술 스택을 기반으로 하는 오픈 소스 전문 출판 플랫폼입니다
✅ gke 만들기
gcp에서 > Kubernetes 클러스터로 이동 후 만들기를 선택합니다.
저는 standard를 선택하였습니다.
기본사항에 클러스터 이름과 영역을 선택해 줍니다.
이렇게만 설정하고 만들어도 충분하지만 요금이 비싸기 때문에 노드 수도 수정해 보겠습니다.
노드 풀에서 노드 수를 기본 3개에서 2개로 변경하였고 노드 탭에서 머신 유형을 가장 낮은 메모리(1GB)를 선택하였습니다.
시간이 얼마 지나지 않아 gke가 완성되었습니다. 🙌
그럼 cloud shell을 통해 접속해보겠습니다.
해당 쿠버네티스의 클러스터에서 연결을 통해 cloud shell에 접속합니다.
연결을 클릭하면 shell에 접속할 수 있는 명령어를 보여줍니다.
$ gcloud container clusters get-credentials ghost-cluster --zone asia-northeast3-a --project 'project-name'
원하는 설정대로 2개의 node가 생성되었는지 검색해보겠습니다.
// node 조회
$ kubectl get node
아직 아무것도 배포한 것이 없기 때문에 pod는 없다고 나옵니다.
// Pod 조회
$ kubectl get po
이제 Ghost 블로그를 배포해 보겠습니다. 👍
✅ gke에 ghost 배포
BITNAMI 패키지로 만든 ghost를 가져와 사용합니다.
Bitnami 애플리케이션을 Helm 차트로 배포하는 것은 Kubernetes에서 애플리케이션을 시작하는 가장 쉬운 방법입니다. 😉
bitnami repo를 등록하고 bitnami/ghost 패키지를 my-ghost란 이름으로 설치합니다.
$ helm repo add bitnami https://charts.bitnami.com/bitnami
$ helm install my-ghost bitnami/ghost
저 같은 경우는 bitnami repo가 이미 있다고 나옵니다.
$ helm repo add bitnami https://charts.bitnami.com/bitnami
"bitnami" already exists with the same configuration, skipping
$ helm install my-ghost bitnami/ghost
NAME: my-ghost
LAST DEPLOYED: Sun Jul 31 16:26:24 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: ghost
CHART VERSION: 19.0.12
APP VERSION: 5.5.0
** Please be patient while the chart is being deployed **###############################################################################
### ERROR: You did not provide an external host in your 'helm install' call ###
###############################################################################
This deployment will be incomplete until you configure Ghost with a resolvable
host. To configure Ghost with the URL of your service:
1. Get the Ghost URL by running:
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
Watch the status with: 'kubectl get svc --namespace default -w my-ghost'
export APP_HOST=$(kubectl get svc --namespace default my-ghost --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}")
export GHOST_PASSWORD=$(kubectl get secret --namespace "default" my-ghost -o jsonpath="{.data.ghost-password}" | base64 -d)
export MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace "default" my-ghost-mysql -o jsonpath="{.data.mysql-root-password}" | base64 -d)
export MYSQL_PASSWORD=$(kubectl get secret --namespace "default" my-ghost-mysql -o jsonpath="{.data.mysql-password}" | base64 -d)
2. Complete your Ghost deployment by running:
helm upgrade --namespace default my-ghost bitnami/ghost \
--set service.type=LoadBalancer,ghostHost=$APP_HOST,ghostPassword=$GHOST_PASSWORD,mysql.auth.rootPassword=$MYSQL_ROOT_PASSWORD,mysql.auth.password=$MYSQL_PASSWORD
ghost 블로그 설치가 완료되었습니다! 🙌
그럼 이번엔 get po 명령어를 통해 확인해보겠습니다.
$ kubectl get po
//조회 결과 포멧 변경
$ kubectl get po -o wide
// 다양한 포멧 변경
$ kubectl get po -o yaml
$ kubectl get po -o json
mysql이 설치되어 Running(기동 중) 상태입니다. 해당 mysql은 쿠버네티스가 2개의 노드 중 랜덤하게 1개의 노드에 설치를 하였습니다.
그다음으로 ghost server를 설치해야 합니다.
install시 나온 가이드대로 진행하도록 하겠습니다!
일단 APP_HOST를 설정하기 위해 host 정보를 가져와야 합니다.
아래의 명령어를 이용하여 host 정보를 가져옵니다.
$ kubectl get svc --namespace default my-ghost --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}"
가이드에서는 export하여 진행하지만 저는 다음 아래와 같이 yml 파일을 생성하여 진행하도록 하겠습니다.
다양한 옵션이 있지만 실행하기 위한 기본 옵션만 설정하였습니다.
ghost의 name, password와 mysql의 root-password, password 그리고 접속 계정의 email을 설정해 주시면 됩니다.
다양한 옵션은 ghost/values.yml을 참고하세요! 😉
📍 values.yml
service:
type: LoadBalancer
ghostHost: 'host정보'
ghostUsername: minseonyu@gmail.com
ghostPassword: qwer1234!!
ghostEmail: minseonyu@gmail.com
ghostBlogTitle: MS Blog
mysql:
auth:
rootPassword: qwer1234!!
password: qwer1234!!
설정한 정보를 이용하여 my-ghost에 업데이트를 진행해 줍니다.
$ helm upgrade --namespace default my-ghost bitnami/ghost --values values.yml
성공했다는 log와 함께 접속 URL과 정보를 보여줍니다.
$ helm upgrade --namespace default my-ghost bitnami/ghost --values values.yml
Release "my-ghost" has been upgraded. Happy Helming!
NAME: my-ghost
LAST DEPLOYED: Sun Jul 31 16:40:43 2022
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None
NOTES:
CHART NAME: ghost
CHART VERSION: 19.0.12
APP VERSION: 5.5.0
** Please be patient while the chart is being deployed **
1. Get the Ghost URL by running:
echo Blog URL : http://34.XX.XX.XXX/
echo Admin URL : http://34.XX.XX.XXX/ghost
2. Get your Ghost login credentials by running:
echo Email: minseonyu@gmail.com
echo Password: $(kubectl get secret --namespace default my-ghost -o jsonpath="{.data.ghost-password}" | base64 -d)
pod를 확인해 볼까요? 😄
쿠버네티스가 자동으로 pod에 배포하는데 다른 node에 service와 mysql이 있는 걸 확인할 수 있습니다.
READY 0/1 은 아직 준비 중이며 READY 1/1이 준비 완료 상태입니다.
$ kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-ghost-7dccbf86b8-9drbp 0/1 Running 0 3m6s 10.76.0.10 gke-ghost-cluster-default-pool-919c0b9d-lz3z <none> <none>
my-ghost-mysql-0 0/1 Running 0 4m52s 10.76.1.10 gke-ghost-cluster-default-pool-919c0b9d-lp5x <none> <none>
준비 완료를 확인 후 ghost 블로그에 접속해보도록 하겠습니다.
설정 파일에 입력한 email을 통해 관리자 로그인이 가능합니다.
관리자 화면입니다.
포스팅을 한번 해보고 블로그 메인에서 확인해보겠습니다.
성공입니다 🙌
컨테이너를 삭제해도 쿠버네티스가 자동으로 띄워 주는지 테스트해 보겠습니다.
컨테이너는 상태를 유지하려고 하기 때문에 새롭게 컨테이너를 생성하여 자동으로 띄워줍니다.
$ kubectl delete po/my-ghost-7dccbf86b8-9drbp
pod "my-ghost-7dccbf86b8-9drbp" deleted
$ kubectl get po
NAME READY STATUS RESTARTS AGE
my-ghost-5b46c8d49c-8pljn 0/1 ContainerCreating 0 1s
my-ghost-mysql-0 1/1 Running 0 2d10h
$ kubectl get po
NAME READY STATUS RESTARTS AGE
my-ghost-5b46c8d49c-8pljn 0/1 Running 0 30s
my-ghost-mysql-0 1/1 Running 0 2d10h
$ kubectl get po
NAME READY STATUS RESTARTS AGE
my-ghost-5b46c8d49c-8pljn 1/1 Running 0 77s
my-ghost-mysql-0 1/1 Running 0 2d10h
my-ghost-7dccbf86b8-9drbp를 삭제하니 쿠버네티스가 바로 새로운 컨테이너(my-ghost-5b46c8d49c-8pljn)를 시작합니다.
참고
초보를 위한 쿠버네티스 안내서 - 쿠버네티스를 이용한 배포 데모