GCP (Google Cloud Platform) の GKE で WordPress を構築

スポンサーリンク

はじめに

自分でサーバーを借りてブログを立ち上げるなら、まず思いつくのは WordPress かと思います。

しかし、サーバーを借りて、サーバーに OS をインストールして、PHP をインストールして、データベースをインストールして、Web サーバーをインストールして、WordPress をインストールして、リバースプロキシの設定をして・・・、と考えるとちょっと躊躇してしまうかもしれません。

そして近年は Web サイトの HTTPS 化が当然のように求められており、そうなってくると、自分でサーバーを借りてブログを立ち上げる場合にも独自ドメインが必要になってきます。

ちなみに、Google Domains で独自ドメインを取得する手順については以前に投稿しています。

Google Domains で独自ドメインを取得
はじめに 自分でサーバーを借りて WordPress でブログを立ち上げるなら、独自ドメインが欲しくなるところです。独自ドメインを取得して管理できるサービスはたくさんありますが、Google も Google Domains として提...

なるべく手間を掛けずに WordPress を立ち上げたい場合、Google Cloud Platform、略して GCP のいくつかのサービスで WordPress の構築をサポートしているようです。GCP では無料トライアルも提供されています。これを機に GCP で WordPress を立ててみます。

ちなみに、無料トライアルが終わった後も GCP で WordPress を立ち上げ続けると、構成によってはそれなりの料金が発生するかと思われます。ご利用は計画的に、です。

文末に、1 ヶ月あたりの費用も書いています。

準備するもの

  • Google Cloud Platform、略して GCP を使うことができる Google アカウント
  • Cloud SDK
  • Git

GCP を無料トライアルで始め、Cloud SDK をインストールする手順については以前にポストしています。

Google Cloud Platform を無料トライアルで使い始める
はじめに Google が提供するクラウドサービスである Google Cloud Platform, 略して GCP でクラウドコンピューティングに触れてみます。12 ヶ月の無料トライアルで、お得に使い始めることができます。また、無...

Gitは、macOS、Linux にはデフォルトでインストールされています。Windows の場合は、Git for Windows をインストールします。

Git for Windows
We bring the awesome Git VCS to Windows

大まかな手順

構築手段の決定

GCP では WordPress を構築するにあたり、主に 3 種類の手段が提供されています。

WordPress Cloud Hosting | Google Cloud
https://cloud.google.com/wordpress/

  • GCP Marketplace で WordPress の単一インスタンスをデプロイ
  • Kubernetes Engine に WordPress をデプロイ
  • App Engine に WordPress をデプロイ

ここでは Kubernetes Engine、Google Kubernetes Engine、略してGKEを使用します。この 3 つの中では一番柔軟性はありますが、一番面倒なやつですね。

個人的な見解ですが、Kubernetes、略して k8s は、現代の Web エンジニア、インフラエンジニアにとって、一度は触っておいて損は無い知識だと思います。

チュートリアルの確認

下記のチュートリアルに沿って行います。

Kubernetes Engine Tutorials > Using Persistent Disks with WordPress and MySQL
https://cloud.google.com/kubernetes-engine/docs/tutorials/persistent-disk

注意点としては、同じチュートリアルの URL でも英語表示と日本語表示とでは微妙に内容が異なります。

Google Cloud のページは日本語表示でも提供されていますが、基本は英語で、日本語訳は遅れて行われるようです。最新の情報を得るために、まずは英語表示の情報を確認することをお勧めします。

表示言語は、Google Cloud のページの左下で切り換えることができます。

英語が苦手?そういう場合はGoogle 翻訳を使いましょう。

Google 翻訳
Google の無料サービスなら、単語、フレーズ、ウェブページを英語から 100 以上の他言語にすぐに翻訳できます。

Kubernetes Engineの有効化

まず、Web ブラウザで GCP のコンソールにアクセスします。

Google Cloud Platform
Google Cloud Platform では、Google と同じインフラストラクチャでアプリケーション、ウェブサイト、サービスを構築、導入、拡大することができます。

画面左側メニューの Kubernetes Engine をクリックし、機能を有効化します。

kubectl のインストール

ここからは Cloud SDK を使ってコマンドで GCP を操作していきます。macOS や Linux の場合はターミナル、Windows の場合はコマンドプロンプトから行います。

ここからは macOS で行った場合について書いていきます。

なお、macOS に Cloud SDK をインストールする手順については以前に投稿しています。

Google Cloud Platform を無料トライアルで使い始める
はじめに Google が提供するクラウドサービスである Google Cloud Platform, 略して GCP でクラウドコンピューティングに触れてみます。12 ヶ月の無料トライアルで、お得に使い始めることができます。また、無...

macOS でターミナルを起動し、下記のコマンドを実行します。

gcloud components install kubectl

これで、Cloud SDK を使用して GKE を操作することができるようになります。

GKE クラスタの作成

ターミナルで Cloud SDK を使用して作成します。

gcloud container clusters create examplecluster \
  --num-nodes=3 \
  --machine-type=g1-small \
  --disk-size=10 \
  --preemptible

マシンタイプは g1-small にしました。最も低スペックな f1-micro だと自分の体感では WordPress を動かすにはちょっと不安が。

ノードは 3 にしました。3 未満にすると、下記のようなエラーでクラスタを作成できませんでした。

ERROR: (gcloud.container.clusters.create) ResponseError: code=400, message=Clusters of f1-micro instances must contain at least 3 nodes. Please make the cluster larger or use a different machine type.

ディスクサイズは何も設定しないとデフォルトで 200GB も作成されてしまいますが、ディスク使用量は高額になりますし、データ永続用のディスクは別途準備するため、ここでは 10GB としました。

また、費用を抑えるために、プリエンプティブとしました。プリエンプティブと設定すると、仮想マシンがいつシャットダウンされるか分からないものの、その代わり使用料が割安になるものです。今回ノード数を 3 にしているため、同時に 3 つシャットダウンされることは (恐らく) ないでしょうし。

Preemptible VM Instances  |  Compute Engine Documentation  |  Google Cloud
Learn about Google Compute Engine's Preemptible virtual machine (VM) instances

そして、クラスタ作成コマンドの実行結果は下記の通りです。

WARNING: Starting in 1.12, new clusters will have basic authentication disabled by default. Basic authentication can be enabled (or disabled) manually using the `--[no-]enable-basic-auth` flag.
WARNING: Starting in 1.12, new clusters will not have a client certificate issued. You can manually enable (or disable) the issuance of the client certificate using the `--[no-]issue-client-certificate` flag.
WARNING: Currently VPC-native is not the default mode during cluster creation. In the future, this will become the default mode and can be disabled using `--no-enable-ip-alias` flag. Use `--[no-]enable-ip-alias` flag to suppress this warning.
WARNING: Starting in 1.12, default node pools in new clusters will have their legacy Compute Engine instance metadata endpoints disabled by default. To create a cluster with legacy instance metadata endpoints disabled in the default node pool, run `clusters create` with the flag `--metadata disable-legacy-endpoints=true`.
This will enable the autorepair feature for nodes. Please see https://cloud.google.com/kubernetes-engine/docs/node-auto-repair for more information on node autorepairs.
WARNING: Starting in Kubernetes v1.10, new clusters will no longer get compute-rw and storage-ro scopes added to what is specified in --scopes (though the latter will remain included in the default --scopes). To use these scopes, add them explicitly to --scopes. To use the new behavior, set container/new_scopes_behavior property (gcloud config set container/new_scopes_behavior true).
Creating cluster examplecluster in asia-east1-b...done.                                                                
Created [ttps://container.googleapis.com/v1/projects/my-project-123456789/zones/asia-east1-b/clusters/examplecluster].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/asia-east1-b/examplecluster?project=project-01234567
kubeconfig entry generated for examplecluster.
NAME       LOCATION      MASTER_VERSION  MASTER_IP       MACHINE_TYPE  NODE_VERSION  NUM_NODES  STATUS
examplecluster  asia-east1-b  1.9.7-gke.7     aaa.bbb.ccc.ddd  g1-small      1.9.7-gke.7   3          RUNNING

MySQLパスワードの作成

MySQL のパスワードを格納するシークレットを作成します。ここではデータベースのパスワードを mypassword と設定しています。

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

実行結果

secret "mysql" created

YAML ファイルの入手

GKE は、kubectl と YAML ファイルを使用して制御します。GCP で GKE を使用して WordPress を構築するための YAML ファイルのサンプルを Google が提供しています。それを Git でクローンしておきましょう。

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

以降、wordpress-persistent-disks フォルダ下にあるサンプルファイルを編集していきます。

データ永続化用ストレージの作成

まず、MySQL用のmysql-volumeclaim.yamlです。ストレージのサイズは10GBとしました。

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

次に、WordPress 用 の wordpress-volumeclaim.yaml です。こちらもストレージのサイズは 10GB としました。

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

kubectl を使用して GKE へ設定を行います。まずは MySQL 用の設定です。

kubectl apply -f mysql-volumeclaim.yaml

実行結果

persistentvolumeclaim "mysql-volumeclaim" created

続いてWordPress用の設定です。

kubectl apply -f wordpress-volumeclaim.yaml

実行結果

persistentvolumeclaim "wordpress-volumeclaim" created

確認してみます。

kubectl get pvc

実際に、10GBのストレージが確保されています。

NAME                    STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mysql-volumeclaim       Bound     pvc-xxxxxxxx-0000-0000-0000-000000000000   10Gi       RWO            standard       36s
wordpress-volumeclaim   Bound     pvc-yyyyyyyy-0000-0000-0000-000000000000   10Gi       RWO            standard       13s

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

デプロイします。

kubectl create -f mysql.yaml

実行結果

deployment.apps "mysql" created

確認してみます。

kubectl get po

実行結果

NAME                    READY     STATUS    RESTARTS   AGE
mysql-000000000-00000   1/1       Running   0          52s

MySQLサービスの作成

mysql-service.yaml ファイルの内容は下記の通りです。サンプルそのままです。

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

作成します。

kubectl create -f mysql-service.yaml

実行結果

service "mysql" created

確認してみます。

kubectl get service mysql

実行結果

NAME      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
mysql     ClusterIP   10.aaa.bbb.ccc           3306/TCP   5m

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
          readinessProbe:
            httpGet:
              path: /wp-admin/install.php
              port: 80
          volumeMounts:
            - name: wordpress-persistent-storage
              mountPath: /var/www/html
      volumes:
        - name: wordpress-persistent-storage
          persistentVolumeClaim:
            claimName: wordpress-volumeclaim

デプロイします。

kubectl create -f wordpress.yaml

実行結果

deployment.apps "wordpress" created

確認してみます。

kubectl get po

実行結果

NAME                         READY     STATUS    RESTARTS   AGE
mysql-0000000000-00000        1/1       Running   0          11m
wordpress-0000000000-00000   1/1       Running   0          3m

静的IPアドレスの取得

WordPress はインターネットに公開されます。しかし、何もしなければ、GKE のクラスタを再起動する度にグローバル IP アドレスが変更されます。そうならないように、WordPress 用に静的 IP アドレス (固定 IP アドレス、Static IP アドレス) を取得しておきます。

gcloud compute addresses create example --global --ip-version=IPV4

実行結果

Created https://www.googleapis.com/compute/v1/projects/my-project-0123456789/global/addresses/example.

確認してみます。

gcloud compute addresses describe example --global

確認結果

address: x.x.x.x
creationTimestamp: '2018-11-xxT04:13:16.153-08:00'
description: ''
id: 'xxxxxxxxxxxxxxxxxxx'
ipVersion: IPV4
kind: compute#address
name: exmaple
networkTier: PREMIUM
selfLink: https://www.googleapis.com/compute/v1/projects/my-project-01234567/global/addresses/example
status: RESERVED
https://cloud.google.com/kubernetes-engine/docs/tutorials/configuring-domain-name-static-ip

WordPressサービスとイングレスの作成

wordpress-ingress.yaml を作成します。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: wordpress-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: example
spec:
  backend:
    serviceName: wordpress
    servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  type: NodePort
  selector:
    app: wordpress
  ports:
  - port: 80
    targetPort: 80

設定を適用させます。

kubectl apply -f wordpress-ingress.yaml

実行結果

ingress.extensions "wordpress" created
service "wordpress" created

確認してみます。

kubectl get ingress

確認結果

NAME        HOSTS     ADDRESS        PORTS     AGE
wordpress   *         x.x.x.x   80        7m

WordPress へのアクセス

http://静的IPアドレス/wp-admin/install.php にアクセスすると、WordPress の初期設定画面になります。

費用

この投稿の設定で 2 ヶ月ずっと WordPress を稼働してみたところ、7,700 円くらいでした。1 ヶ月あたり 4,000 円くらいかなと思います。

次は

静的 IP アドレスに Google Domains で取得した独自ドメインを設定してみます。

長くなったので、次の投稿にて。