Managed Service Column <システム運用コラム>

Kubernetes

Category: 実践編

2020.05.17

はじめに

インフラ側の準備が整ったので、いよいよ Kubernetes 上に WordPress を構築します。
公式の Docker イメージを利用して、WordPress の初期設定画面を表示させるところまでを行います。

Kubectl の使い方

Kubernetes の API を実行してくれるコマンド、kubectl を使ってオブジェクトを作成していきます。使い方は、これだけです。

$ kubectl apply -f <マニフェスト.yaml>

簡単に説明しておきます。

  • マニュフェスト (yaml) からオブジェクトを作成します。
  • “apply” はオブジェクトの状態によって、新規作成、更新、削除を判断して実行してくれます。

あとは、作った後に kubectl get を使って、ちゃんと出来たか確認します。問題がある場合は、kubectl describe で詳細を確認します。
このあとは基本的に、「マニフェストファイルを作成する」「kubectl apply を実行して、オブジェクトを作成する」をひらすら繰り返していきます。この流れを覚えてください。

$ kubectl get <オブジェクトの種類> <オブジェクト名>
$ kubectl describe <オブジェクトの種類> <オブジェクト名>

kubectl の実行環境は、AKS に接続できる環境であればどこでも構いません。
今回は、ローカル環境に kubectl をインストールするのが面倒なので、Azure Cloud Shell (bash) を使います。

どこからでもいいので、Azure ポータルの画面右側にある Shell アイコンをクリックします。
クリックすると、自動でストレージアカウントが作成され、Shell の実行環境にログインできます。(初回は結構、時間がかかります。)
この環境には、Azure CLI など一通りのコマンドが用意されています。

Azure Cloud Shell にログインできたら、以下のコマンドを実行して、AKS のクラスタに接続するための認証を行ってください。

$ az aks get-credentials --resource-group <myResourceGroup> --name <myAKSCluster>

Azure Files のマウントポイントについて

WordPress をデプロイする前に、Azure Files のマウントポイントについて補足しておきます。
(Kubernetes とは関係ないため、読み飛ばしても構いません。)

通常、WordPress の冗長化を行う場合は、外部ストレージのマウントポイントとしてドキュメントルートを指定します。
これにより、WordPress に関連するファイルを一式、サーバ間で共有することができます。
しかし、NFS のようなネットワークファイル共有を利用する場合、パフォーマンスの低下が発生します。
ユーザがアクセスするたびに、ネットワーク越しに php が実行されるわけですが、どうしてもこの部分でディスク I/O がボトルネックになってしまうためです。
(特に、Azure Files は SMB プロトコルをマウントしているため、NFS よりもパフォーマンスは低下してしまうようです。)

これの回避策として、今回はマウントポイントをドキュメントルート配下の wp-content に限定することにします。
これにより、プラグインや画像などのコンテンツは Azure Files 上に保存されます。代わりに、コアファイルの修正・アップデートを行う際は、Docker イメージの中に含めなくてはなりません。

Kubernetes への WordPress デプロイ

認証情報・接続情報

データベースのパスワード情報を設定します。
パスワードなので、Key, Value の組を暗号化してストアするオブジェクト、”secret” を利用することにします。

まずは、マニフェストファイルを作成します。
vim などを利用して yaml ファイルに以下を書き込み、保存します。
“WORDPRESS_DB_PASSWORD” は wordpress イメージ内で定義されている環境変数です。その下の “WORDPRESS_AUTH_KEY” から “WORDPRESS_NONCE_SALT” はシークレットキーとソルトと呼ばれるもので、管理画面へのログイン時に利用する Cookie を生成するものです。通常は自動で生成されて wp-config.php に書き込まれるのですが、今回は wp-config.php を Azure Files 上に配置しないため、全てのコンテナで同じ値を取れるよう、ここで指定します。(コンテナごとにこの値がバラバラだと、セッション維持ができなくなったしまいます。)また、格納するパスワードは Base64 でエンコードする必要があります。

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  WORDPRESS_DB_PASSWORD: bzRlNzF5byFrYXNoaQ==
  WORDPRESS_AUTH_KEY: Q01HYiBid21JUS1aYGZCTFBEZ1hRZVYxPCEoKW58WF0+Vy1UVjFRb1pvOzRyNGhld0xZUWYt
  WORDPRESS_SECURE_AUTH_KEY: Q01HYiBid21JUS1aYGZCTFBEZ1hRZVYxPCEoKW58WF0+Vy1UVjFRb1pvOzRyNGhld0xZUWYt
  WORDPRESS_LOGGED_IN_KEY: Q01HYiBid21JUS1aYGZCTFBEZ1hRZVYxPCEoKW58WF0+Vy1UVjFRb1pvOzRyNGhld0xZUWYt
  WORDPRESS_NONCE_KEY: Q01HYiBid21JUS1aYGZCTFBEZ1hRZVYxPCEoKW58WF0+Vy1UVjFRb1pvOzRyNGhld0xZUWYt
  WORDPRESS_AUTH_SALT: Q01HYiBid21JUS1aYGZCTFBEZ1hRZVYxPCEoKW58WF0+Vy1UVjFRb1pvOzRyNGhld0xZUWYt
  WORDPRESS_SECURE_AUTH_SALT: Q01HYiBid21JUS1aYGZCTFBEZ1hRZVYxPCEoKW58WF0+Vy1UVjFRb1pvOzRyNGhld0xZUWYt
  WORDPRESS_LOGGED_IN_SALT: Q01HYiBid21JUS1aYGZCTFBEZ1hRZVYxPCEoKW58WF0+Vy1UVjFRb1pvOzRyNGhld0xZUWYt
  WORDPRESS_NONCE_SALT: Q01HYiBid21JUS1aYGZCTFBEZ1hRZVYxPCEoKW58WF0+Vy1UVjFRb1pvOzRyNGhld0xZUWYt

※ 参考 (Base64 でのエンコード)

$ echo -n 'mypassword' | base64

保存した yaml ファイルに対して、kubectl apply を実行し、オブジェクトを作成します。

rworks@Azure:~$ kubectl apply -f db-secret.yaml
secret/db-secret created

rworks@Azure:~$ kubectl get secret db-secret
NAME TYPE DATA AGE
db-secret Opaque 1 8s

次に、接続先の情報を作成します。
こちらは、暗号化する必要のない Key,Value の組なので、configmap オブジェクトを利用します。

wp-config.yaml を作成します。

apiVersion: v1
kind: ConfigMap
metadata:
  name: wp-configmap
data:
  WORDPRESS_DB_NAME: wordpress
  WORDPRESS_DB_USER: wpadmin@wordpress-db-rworks
  WORDPRESS_DB_HOST: wordpress-db-rworks.mysql.database.azure.com

オブジェクトを作成します。

rworks@Azure:~$ kubectl apply -f wp-config.yaml
configmap/wp-configmap created

rworks@Azure:~$ kubectl get configmap wp-configmap
NAME DATA AGE
wp-configmap 3 16s

ストレージ

まずは、Azure Files のパラメータを指定します。これは、”StorageClass” オブジェクトを利用します。(apiVersion がこれまでと異なります。マニフェストで指定する項目も異なることに注意してください。)

“azurefiles” という名前で、一番安い「標準のローカル冗長ストレージ」クラスを作成しましょう。azure-files-sc.yaml を作成します。
マウントする際の所有者を “www-data” にしておかないと、プラグインのアップロードができなくなるので、注意してください。また、パフォーマンス向上のため、キャッシュも有効にしておきます。

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: azurefiles
provisioner: kubernetes.io/azure-files
mountOptions:
  - dir_mode=0777
  - file_mode=0777
  - uid=33                  # ← apache の実行ユーザ (www-data)
  - gid=33
  - mfsymlinks
  - nobrl
  - cache=strict            # ← cache を有効に
parameters:
  skuName: Standard_LRS

オブジェクトを作成します。

rworks@Azure:~$ kubectl apply -f azure-files-sc.yaml
storageclass.storage.k8s.io/azurefiles created

rworks@Azure:~$ kubectl get storageclass azurefiles
NAME        PROVISIONER                AGE
azurefiles   kubernetes.io/azure-files   34d

次に、「PersistentVolumeClaim」と呼ばれる、外部ストレージを動的にプロビジョニングするためのオブジェクトを作成します。これにより、Azure Files から必要な分だけストレージを利用することができます。さきほど作成した “azurefiles” オブジェクトから 5GB 分をプロビジョニングする、という設定にしてみます。
azure-files-pvc.yaml を作成します。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: azurefiles
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: azurefiles
  resources:
    requests:
      storage: 5Gi

オブジェクトを作成します。

rworks@Azure:~$ kubectl apply -f azure-files-pvc.yaml
persistentvolumeclaim/azurefiles created

rworks@Azure:~$ kubectl get pvc azurefiles
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
azurefiles Bound pvc-937e9fd7-579e-11ea-b5a7-12252093dbe6 5Gi RWX azurefiles 48s

サービス

エンドユーザがアクセスするためのエンドポイントを作成します。
“Service” オブジェクトを利用して、Azure Load Balancer を使うように設定します。

service.yaml を作成します。

apiVersion: v1
kind: Service
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  ports:
    - port: 80
  selector:
    app: wordpress
    tier: frontend
  type: LoadBalancer
  loadBalancerIP: 20.44.xxx.xxx  # ← Azure で取得したグローバルアドレス

service オブジェクトを作成します。

rworks@Azure:~$ kubectl apply -f service.yaml
service/wordpress created

rworks@Azure:~$ kubectl get service wordpress
NAME        TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)        AGE
wordpress   LoadBalancer   10.0.143.24   20.44.xxx.xxx   80:31121/TCP   20m

ここで Azure Load Balancer へのグローバルアドレス割り当てが行われます。

Deployment

いよいよ、コンテナ本体を作成します。”Deployment” オブジェクトとして、以下のような設定を作成します。

  • ReplicaSet は2つ
  • イメージ “WordPress” を利用
  • wp-config, secret オブジェクトからデータベース接続情報、シークレットキーを読み込む
  • Azure Files を /var/www/html/wp-content にマウント
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  replicas: 2                                 # ← Pod の数
  selector:
    matchLabels:
      app: wordpress
      tier: frontend
  strategy:
    type: Recreate
  template:                                   # ← template となる Pod の定義
    metadata:
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
      - image: wordpress
        name: wordpress
        envFrom:                              # ← MySQL への接続情報と認証情報を全て読み込み
        - configMapRef:
            name: wp-configmap
        - secretRef:
            name: db-secret
        ports:
        - containerPort: 80
          name: wordpress
        volumeMounts:
        - name: wordpress-persistent-storage
          mountPath: /var/www/html/wp-content            # ← Azure Files のマウントポイント
      volumes:
      - name: wordpress-persistent-storage
        persistentVolumeClaim:
          claimName: azurefiles                # ← pvc の名前

オブジェクトを作成します。

works@Azure:~$ kubectl apply -f deployment.yaml
deployment.apps/wordpress created

WordPress サイトが無事にできたか、Azure Load Balancer のグローバルアドレスにアクセスしてみます。インストール画面が表示されたら、成功です。

以下の通り、Pod が2つ、動いていることが分かります。

rworks@Azure:~$ kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
wordpress-776f579889-6d859   1/1     Running   0          9m12s
wordpress-776f579889-vxjpf   1/1     Running   0          9m34s

まとめ

無事、Kubernetes で WordPress サイトを公開することができました。
次回は、運用する際のポイントについて解説します。
「Kubernetes で WordPress サイトを公開してみる (運用編)」を読む

Tag: コンテナ Kubernetes

Contactお問い合わせ

お見積もり・ご相談など、お気軽にお問い合わせください。

single.php