WordPress 및 MySQL에 Persistent Disk 사용

이 가이드에서는 클러스터에서 단일 복제본 WordPress 배포 및 단일 복제본 MySQL 데이터베이스를 설정하는 방법을 보여줍니다. 두 애플리케이션 모두 PersistentVolumes(PV) 및 PersistentVolumeClaims(PVC)를 사용하여 데이터를 저장합니다.

PersistentVolume은 관리자가 수동으로 프로비저닝했거나 Kubernetes가 StorageClass를 사용해서 동적으로 프로비저닝한 클러스터의 저장소를 나타냅니다. PersistentVolumeClaim은 PersistentVolume으로 충족될 수 있는 사용자의 저장소 요청입니다. PersistentVolume과 PersistentVolumeClaim은 포드 수명 주기와 별개이며, 포드 다시 시작, 일정 다시 잡기, 삭제를 통해 데이터를 보존합니다. 두 애플리케이션 모두 영구 디스크를 저장소로 사용해서 영구 볼륨을 지원합니다.

배경

WordPress는 MySQL을 데이터베이스로 사용해서 블로그 문서를 저장하고 로컬 파일 시스템을 사용하여 블로그 게시물의 사진과 같은 저작물 또는 확장 기능을 저장하는 블로그 도구입니다. 이 가이드에서는 Docker Hub의 공식 MySQLWordPress 컨테이너 이미지를 사용합니다.

일반적으로 컨테이너의 루트 파일 시스템은 영구 데이터를 저장하는 데 적합하지 않습니다. GKE에서 실행하는 컨테이너는 일반적으로 일회용 항목이며, 클러스터 관리자는 노드 오류 또는 기타 원인으로 인해 사용할 수 없게 된 모든 컨테이너를 삭제, 축출 또는 다시 예약해야 합니다. 이러한 경우 컨테이너의 루트 파일 시스템에 저장된 모든 데이터가 손실됩니다.

영구 디스크에서 지원되는 영구 볼륨을 사용하면 컨테이너 외부에 WordPress 및 MySQL 애플리케이션 데이터를 저장할 수 있습니다. 이렇게 하면 컨테이너가 삭제되더라도 데이터가 유지됩니다.

MySQL과 Wordpress 모두 데이터를 저장하려면 PersistentVolume이 필요합니다. 이 가이드에서는 영구 디스크를 동적으로 만들고 각 배포당 하나씩 2개의 PersistentVolumeClaim을 만드는 기본 저장소 클래스를 사용합니다.

그런 다음 MySQL과 WordPress에 하나씩 2개의 배포를 만듭니다. 이 두 배포는 모두 각 포드의 단일 복제본만 실행합니다.

그런 후 2개의 서비스를 만듭니다. 이러한 두 서비스는 각각 MySQL 컨테이너와 통신하기 위한 WordPress 컨테이너용 서비스와 부하 분산기로 외부 IP 주소에서 인터넷에 WordPress 배포를 노출하기 위한 서비스입니다.

시작하기 전에

다음 단계에 따라 Kubernetes Engine API를 사용 설정합니다.
  1. Google Cloud Platform 콘솔에서 Kubernetes Engine 페이지로 이동합니다.
  2. 프로젝트를 만들거나 선택합니다.
  3. API 및 관련 서비스가 사용 설정될 때까지 기다립니다. 몇 분 정도 걸릴 수 있습니다.
  4. 프로젝트에 결제가 사용 설정되어 있는지 확인하세요.

    결제 사용 설정 방법 알아보기

이 가이드에 사용된 다음 명령줄 도구를 설치합니다.

  • gcloud는 Kubernetes Engine 클러스터를 만들고 삭제하는 데 사용됩니다. gcloudGoogle Cloud SDK에 포함되어 있습니다.
  • kubectl은 Kubernetes Engine에서 사용되는 클러스터 조정 시스템인 Kubernetes를 관리하기 위해 사용됩니다. gcloud를 사용하여 kubectl을 설치할 수 있습니다.
    gcloud components install kubectl

gcloud 명령줄 도구의 기본값 설정

gcloud 명령줄 도구에서 프로젝트 IDCompute Engine 영역 옵션을 입력하는 시간을 절약하기 위해 기본값을 설정할 수 있습니다.
gcloud config set project [PROJECT_ID]
gcloud config set compute/zone us-central1-b

애플리케이션 매니페스트 다운로드

이 가이드에서는 YAML 형식으로 매니페스트 파일을 사용하여 필요한 Kubernetes 객체를 만듭니다.

이 접근 방식을 선언적 객체 관리라고 부릅니다. 이러한 파일은 사용자를 위해 제공됩니다. GitHub 저장소에서 매니페스트 파일을 다운로드하려면 터미널에서 다음 명령을 실행합니다.

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd kubernetes-engine-samples/wordpress-persistent-disks

(git가 시스템에 설치되지 않았으면 아래 링크에서 다운로드할 수 있습니다.)

1단계: GKE 클러스터 만들기

첫 번째 단계는 WordPress 및 MySQL 애플리케이션 컨테이너를 호스팅하기 위한 GKE 클러스터를 만드는 것입니다. 다음 명령은 3개 노드가 포함된 이름이 persistent-disk-tutorial인 클러스터를 만듭니다.

gcloud container clusters create persistent-disk-tutorial --num-nodes=3

2단계: PersistentVolume 및 PersistentVolumeClaim 만들기

MySQL 및 Wordpress에 필요한 저장소를 만들기 위한 첫 번째 단계는 PersistentVolumeClaim을 만드는 것입니다. PersistentVolumeClaim이 생성되면 결합할 기존 PersistentVolume이 없는 경우, StorageClass 구성에 따라 새로운 PersistentVolume이 동적으로 프로비저닝됩니다.

GKE에는 영구 디스크로 지원되는 PersistentVolume을 동적으로 프로비저닝할 수 있게 해주는 기본 StorageClass가 설치되어 있습니다. StorageClass가 PersistentVolumeClaim,에 지정되지 않았으면 클러스터의 기본 StorageClass가 대신 사용됩니다.

개발자는 mysql-volumeclaim.yamlwordpress-volumeclaim.yaml 파일을 사용하여 배포에 필요한 PersistentVolumeClaim을 만들 것입니다. mysql-volumeclaim.yaml 파일은 다음과 같습니다.

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: mysql-volumeclaim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 200Gi

그리고 wordpress-volumeclaim.yaml 파일은 다음과 같습니다.

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: wordpress-volumeclaim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 200Gi

이러한 매니페스트는 각각 파일 시스템으로 포맷된 200Gi의 저장소를 요청하는 PersistentVolumeClaim을 기술합니다. StorageClass는 지정되지 않았으므로 이러한 PersistentVolumeClaim은 영구 디스크로 지원되는 PersistentVolume을 프로비저닝하는 기본 StorageClass를 사용합니다.

이러한 매니페스트를 배포하려면 다음을 실행합니다.

kubectl apply -f mysql-volumeclaim.yaml
kubectl apply -f wordpress-volumeclaim.yaml

다음 명령어를 실행하여 클레임이 결합되는지 확인합니다. 영구 디스크로 지원되는 PersistentVolume을 프로비저닝하고 이를 PersistentVolumeClaim에 결합하려면 몇 초 정도 걸릴 수 있습니다.

kubectl get pvc
출력:
NAME                    STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mysql-volumeclaim       Bound     pvc-864bf3d6-3c44-11e8-80a6-42010a800002   200G       RWO            standard       11s
wordpress-volumeclaim   Bound     pvc-89d49350-3c44-11e8-80a6-42010a800002   200G       RWO            standard       5s

3단계: MySQL 설정

MySQL 배포

MySQL을 배포하는 첫 번째 단계는 데이터베이스의 비밀번호를 저장하기 위한 Kubernetes 보안 비밀을 만드는 것입니다. 이름이 mysql보안 비밀을 만들려면 다음 명령어를 실행하고 YOUR_PASSWORD를 선택한 암호로 바꿉니다.

kubectl create secret generic mysql --from-literal=password=YOUR_PASSWORD

그런 후 mysql.yaml 매니페스트 파일을 사용해서 포트 3306에서 실행되는 단일 인스턴스 MySQL 애플리케이션을 배포합니다. mysql.yaml 파일은 다음과 같습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - image: mysql:5.6
          name: mysql
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql
                  key: password
          ports:
            - containerPort: 3306
              name: mysql
          volumeMounts:
            - name: mysql-persistent-storage
              mountPath: /var/lib/mysql
      volumes:
        - name: mysql-persistent-storage
          persistentVolumeClaim:
            claimName: mysql-volumeclaim

이 매니페스트는 생성된 보안 비밀로부터 해당 값이 설정되는 MYSQL_ROOT_PASSWORD 환경 변수를 포함할 단일 인스턴스 MySQL 포드가 포함된 배포를 기술합니다. mysql 컨테이너는 PersistentVolumeClaim을 사용하여 컨테이너 내부의 /var/lib/mysql에 영구 디스크를 마운트합니다.

이 매니페스트 파일을 배포하려면 다음을 실행합니다.

kubectl create -f mysql.yaml

포드가 실행되는지 확인합니다. 컴퓨팅 노드에 영구 디스크를 연결하려면 잠시 시간이 걸리기 때문에 포드가 Running 상태로 전환되려면 몇 분 정도 걸릴 수 있습니다.

kubectl get pod -l app=mysql
출력:
NAME                 READY     STATUS    RESTARTS   AGE
mysql-259040-flmqh   1/1       Running   0          3m

MySQL 서비스 만들기

다음 단계에서는 MySQL 컨테이너를 노출하기 위한 서비스를 만들고, 개발자가 만들려는 wordpress 컨테이너에서 액세스할 수 있도록 합니다.

다음과 같이 mysql-service.yaml에 정의된 서비스 매니페스트를 사용합니다.

apiVersion: v1
kind: Service
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  type: ClusterIP
  ports:
    - port: 3306
  selector:
    app: mysql

이 매니페스트는 app: mysql 라벨과 일치하는 포드의 클러스터 IP를 포트 3306에서 만드는 서비스를 기술합니다. 이전 단계에서 배포된 mysql 컨테이너에 이 라벨이 포함됩니다. 이 경우에는 서비스에 type:ClusterIP를 사용합니다. 이 값은 클러스터 내에서만 서비스에 연결할 수 있게 해줍니다.

생성된 클러스터 IP는 클러스터의 모든 컴퓨팅 노드에서 MySQL 컨테이너로 트래픽 경로를 지정하며, 클러스터 외부의 클라이언트에 액세스할 수 없습니다. 서비스가 생성된 다음에는 동일한 컴퓨팅 노드에 있지 않아도 wordpress 컨테이너가 mysql 컨테이너의 DNS 이름을 사용하여 통신할 수 있습니다.

이 매니페스트 파일을 배포하려면 다음을 실행합니다.

kubectl create -f mysql-service.yaml

서비스가 생성되었는지 확인합니다.

kubectl get service mysql
출력:
NAME      CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
mysql     10.51.240.175   <none>        3306/TCP   4m

새 WordPress 블로그의 데이터베이스 설정이 완료되었습니다.

4단계: WordPress 설정

WordPress 배포

다음 단계에서는 WordPress 컨테이너를 컨테이너 클러스터에 배포합니다. wordpress.yaml 매니페스트 파일을 사용해서 단일 인스턴스 WordPress 컨테이너를 배포합니다.

wordpress.yaml은 다음과 같습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      containers:
        - image: wordpress
          name: wordpress
          env:
          - name: WORDPRESS_DB_HOST
            value: mysql:3306
          - name: WORDPRESS_DB_PASSWORD
            valueFrom:
              secretKeyRef:
                name: mysql
                key: password
          ports:
            - containerPort: 80
              name: wordpress
          volumeMounts:
            - name: wordpress-persistent-storage
              mountPath: /var/www/html
      volumes:
        - name: wordpress-persistent-storage
          persistentVolumeClaim:
            claimName: wordpress-volumeclaim

이 매니페스트는 단일 인스턴스 WordPress 포드가 포함된 배포를 기술합니다. 이 컨테이너는 개발자가 이전에 만든 데이터베이스 비밀번호 보안 비밀에서 WORDPRESS_DB_PASSWORD 환경 변수를 읽습니다.

이 매니페스트는 또한 호스트 주소 mysql:3306으로 MySQL과 통신하도록 WordPress 컨테이너를 구성합니다. 이 값은 WORDPRESS_DB_HOST 환경 변수에 설정됩니다. Kubernetes DNS는 포드가 해당 이름으로 서비스와 통신하도록 허용하므로 데이터베이스를 mysql이라고 부를 수 있습니다.

이 매니페스트 파일을 배포하려면 다음을 실행합니다.

kubectl create -f wordpress.yaml

포드가 실행되는지 확인합니다. 컴퓨팅 노드에 영구 디스크를 연결하려면 잠시 시간이 걸리기 때문에 포드가 Running 상태로 전환되려면 몇 분 정도 걸릴 수 있습니다.

kubectl get pod -l app=wordpress
출력:
NAME                     READY     STATUS    RESTARTS   AGE
wordpress-387015-02xxb   1/1       Running   0          9h

WordPress 서비스 노출

이전 단계에서는 외부 IP 주소가 없으므로 클러스터 외부에서는 현재 액세스할 수 없는 WordPress 컨테이너를 배포했습니다.

부하 분산기를 사용하여 인터넷 트래픽에 WordPress 애플리케이션을 노출하기 위해서는(비용 청구 대상), type:LoadBalancer서비스가 필요합니다.

wordpress-service.yaml 파일에 포함된 이 서비스의 매니페스트는 다음과 같습니다.

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

이 매니페스트 파일을 배포하려면 다음을 실행합니다.

kubectl create -f wordpress-service.yaml

이 매니페스트를 배포하면 부하 분산기가 생성되고, 이 작업은 몇 분 정도 걸릴 수 있습니다. 다음 명령어를 실행하여 블로그의 외부 IP 주소를 찾습니다.

kubectl get svc -l app=wordpress
출력:
NAME        CLUSTER-IP      EXTERNAL-IP    PORT(S)        AGE
wordpress   10.51.243.233   203.0.113.3    80:32418/TCP   1m

위 출력에서 EXTERNAL-IP 열은 블로그에 대해 생성된 공개 IP 주소를 보여줍니다. 다음 단계를 위해 이 IP 주소를 저장합니다.

이제 WordPress 블로그를 배포하고 노출하는 단계가 완료되었습니다.

5단계: 새로운 WordPress 블로그로 이동

블로그의 IP 주소를 찾은 후, 브라우저에서 이 IP 주소로 이동하면 다음과 같은 WordPress 설치 화면이 나타납니다.

Wordpress 설치 화면 스크린샷

WordPress 설정을 완료했으면 브라우저에서 WordPress 앱의 IP 주소를 입력하여 블로그를 다시 방문합니다. 모든 것이 예상대로 작동합니다.

6단계: (선택 사항) 오류 시 데이터 지속성 테스트

PersistentVolume을 사용하면 데이터가 애플리케이션 컨테이너 외부에 유지됩니다. 컨테이너를 사용할 수 없게 되고, Kubernetes에 의해 다른 컴퓨팅 인스턴스로 다시 예약되면, GKE가 포드 실행을 시작한 인스턴스에서 PersistentVolume을 사용할 수 있게 합니다.

kubectl get pods -o=wide
NAME                   ...  IP          NODE
mysql-259040-flmqh     ...  10.48.2.8   gke-persistent-disk-tutorial-default-pool-fe4fe9af-wcb4
wordpress-387483-02xxb ...  10.48.2.7   gke-persistent-disk-tutorial-default-pool-fe4fe9af-wcb4

이제 다음을 실행하여 mysql 포드를 삭제합니다.

kubectl delete pod -l app=mysql

mysql 포드가 삭제되면 배포 컨트롤러에서 포드가 누락된 것을 인식하고 포드를 다시 만듭니다. 새 mysql 포드는 이전에 실행된 것과 다른 노드에서 시작될 가능성이 높습니다.

다음 명령어를 다시 실행해서 mysql 포드가 이전과 다른 컴퓨팅 인스턴스에 예약된 것을 확인합니다. 그렇지 않으면 다른 위치에서 실행될 때까지 포드를 다시 삭제할 수 있습니다.

kubectl get pods -o=wide
출력:
NAME                   ...  IP          NODE
mysql-259040-flmqh     ...  10.48.2.8   gke-persistent-disk-tutorial-default-pool-fe4fe9af-vg56
wordpress-387483-02xxb ...  10.48.2.7   gke-persistent-disk-tutorial-default-pool-fe4fe9af-wcb4

블로그를 다시 방문하여 웹사이트가 올바르게 작동하는지 확인하고 포드를 삭제하더라도 데이터가 지속되고 포드가 클러스터의 다른 인스턴스에 예약되는지 확인합니다.

7단계: 애플리케이션 이미지 업데이트

배포된 소프트웨어를 최신 상태로 유지하는 것이 중요합니다. 예를 들어 업데이트가 필요한 WordPress에서는 취약성이 보고될 수 있습니다. WordPress 컨테이너 이미지를 업데이트하려면 Docker Hub에서 최신 이미지 버전을 찾고 wordpress.yaml 파일에서 이미지 값을 업데이트합니다. 업데이트를 적용하려면 다음을 실행하세요.

kubectl apply -f wordpress.yaml

삭제

이 가이드에서 사용한 리소스 비용이 Google Cloud Platform 계정에 청구되지 않도록 하는 방법은 다음과 같습니다.

이 가이드를 완료한 후에는 다음 단계에 따라 자신의 계정에 원치 않는 비용이 발생하지 않도록 다음 리소스를 삭제합니다.

  1. 서비스 삭제: 이 단계를 수행하면 해당 wordpress 서비스에 대해 생성된 Cloud 부하 분산기가 할당 해제됩니다.
kubectl delete service wordpress
  1. wordpress 서비스를 위해 프로비저닝된 부하 분산기가 삭제될 때까지 대기: kubectl delete를 실행하면 부하 분산기가 백그라운드에서 비동기식으로 삭제됩니다. 다음 명령어 출력을 확인하여 부하 분산기가 삭제될 때까지 기다립니다.

    gcloud compute forwarding-rules list
  2. MySQL 및 WordPress를 위한 PersistentVolumeClaim 삭제: 이 작업을 수행하면 동적으로 프로비저닝된 PersistentVolume과 이러한 PersistentVolumeClaim과 연결된 영구 디스크의 삭제 작업이 자동으로 트리거됩니다.

kubectl delete pvc wordpress-volumeclaim
kubectl delete pvc mysql-volumeclaim
  1. 컨테이너 클러스터 삭제: 이 단계에서는 컴퓨팅 인스턴스, 디스크, 네트워크 리소스와 같이 컨테이너 클러스터를 구성하는 리소스를 삭제합니다.

    gcloud container clusters delete persistent-disk-tutorial

다음 단계

이 페이지가 도움이 되었나요? 평가를 부탁드립니다.

다음에 대한 의견 보내기...

Kubernetes Engine 가이드