kusanagiでWordPress運用環境構築、CircleCI/githubで自動デプロイ

kusanagiWordPressThemeCircleCI
kusanagiWordPressThemeCircleCI

kusanagiでWordPressのCD/CI環境構築を行いました。本番環境、ステージング環境、開発環境の3環境です。リモートとしては本番サーバー(本番環境https://hogehoge.com)と開発サーバー(ステージング環境https://hogehoge.com、開発環境https://dev01.hogehoge.com)の2サーバーです。リモート2サーバー、3環境という構成です。リポジトリのノンベア・ベアについては管理がめんどくさいので採用していません。ftpやsftpで本番のリポジトリのmasterブランチを書き換えてgit addもgit commitもせず、やったぜオーラを出す様な人は居ない(笑)としておきます。

git pull の部分はgit fetch / git merge とブランチ設定を含めて、改良していく予定です。

本番サーバーの本番環境のみgit/github管理という作戦もある

開発サーバー側はgit管理しない、git管理は本番サーバーの本番環境のみという作戦もある様です。メインリポジトリのgithubと本番環境のgitの2つだけ管理すればいいのでgit/github本番環境へのファイナルマージ兼環境全体マネージャの負担は大きく減りますね。

kusanagiを使うメリット

開発者のローカルも含めて全環境のインフラをDockerでも、Virtualboxでも、AWSでも、Azureでも、さくらVPSでも、ConohaVPSでも、kusanagiで統一できるためです。環境差を最小限に抑えやすいです。また、本番サーバーの本番環境と開発サーバーのステージング環境で独自ドメインを同一にしたため、WordPressのDB同期が可能となり、developブランチの開発環境https://dev01.hogehoge.comをmasterブランチの本番環境https://hogehoge.comにマージしたら、本番環境で問題が起きる!!F○ck!!などのケースをreleaseブランチのステージング環境https://hogehoge.comで事前に検証できます。本番再現性の高いステージング環境をはさむことで本番環境でトラブルが起きる確率を最小限に減らすことが出来ます。

前提条件

  • テンプレートであるテーマだけを既にgithub上でプライベートメインリポジトリとして管理している
  • 「本番環境」と「ステージング環境/開発環境」を別サーバーで管理している。ステージング環境は、本番環境をコピーしてSSL証明書は本番と同じものを使い独自ドメインも同じにしています。開発環境は独自ドメインを変更して普通にSSL証明証を新規設定して構築しています。
  • kusanagiで本番サーバーに本番環境 https://hogehoge.com、ステージ/開発サーバーにステージング環境https://hogehoge.com(hostsファイルで見る)と開発環境https://dev01.hogehoge.com(Basic認証をかける)を別プロファイルで全部作ってある
  • 各テーマディレクトリをgitリポジトリ化してある
  • Linuxのkusanagiユーザーは全環境でパスフレーズ発行をしている
  • Linuxのsshのパスワード認証無効化、ssh鍵認証有効化、他の一般Linuxユーザーをwheelグループ追加によってroot昇格出来るようにしてある、Linuxのrootユーザーのssh接続禁止、それぞれが既に完了している
  • .cirleci/config.ymlに変数のハードコーディングをしない。フィンガープリントを含めて変数はCircleCIのEnvironment Variablesを使う

rsyncではなく、全てgitでデプロイ

rsyncを使うと環境個別の設定値の管理をやりにくくなるということもあり、githubメインリポジトリからリモートリポジトリへのpushやpullをCircleCIでトリガーとして、本番/ステージ/開発環境のシェルスクリプトのgit pullをCircleCIでキックしてすべてgitでデプロイします。

permission deniedが頻発する!

kusanagiはLinuxユーザー設計がセキュアでパーミッションまでしっかり作りこまれています。環境構築中はpermission denied が頻発します。LinuxユーザーやLinuxグループ、パーミッション、各種ssh接続環境の構築、githubリポジトリとリモート/ローカルホストのgitの連携構築、ブランチの使い分け、などを把握していないと結構大変です。インフラエンジニアやセキュリティエンジニアの方のほうがとっつきやすいかもしれません。

ステージング/開発サーバーでCiecleCI専用ユーザーを作る

まずは、Linuxのrootユーザーやkusanagiユーザーではない、CircleCI用のLinuxユーザーをステージング/開発サーバーで作ります。CircleCIで使うため、パスフレーズ無しの鍵認証となります。日頃からパスフレーズ有りを徹底している場合、セキュリティ的に違和感があると思いますが、どうしようもないです。

CircleCI用のLinuxユーザー追加

rootユーザーで行ってください

useradd ユーザー名

ユーザー名は開発サーバーのCircleCIユーザーとしてcircleusdevとしました。CircleCIのドキュメントなどでcircleやcircleciなどの命名ケースがあるので命名の重複を避けました。本番サーバーのCircleCIユーザーはcircleusprodとなります。

useradd circleusdev

Linuxユーザーパスワード設定

rootユーザーで行ってください

passwd ユーザー名

ユーザー名はcircleusdev

passwd circleusdev

Linuxユーザー一覧確認

rootユーザーで行ってください

cat /etc/passwd

ファイル中身の見方としては、横に1行単位で以下の様に並んでいます。基本的に、パスワードは暗号化されて見られないです。

ユーザー名 : パスワード(x) : ユーザーID : グループID : 任意コメント(何も記載されてないことが多い) : ユーザーホームディレクトリ : ユーザーが使用するシェル

ユーザーの所属しているグループを確認

groups ユーザー名

ユーザー名はcircleusdev

groups circleusdev

ユーザーが所属するグループを追加

rootユーザーで行ってください

usermod -aG グループ名 ユーザー名

グループはkusanagi、ユーザーはcircleusdevとします。kusanagiユーザーが所属するkusanagiグループとwwwグループの両グループをcircleusdevユーザーに追加します。wwwは不要かもしれませんが念の為に追加します。

usermod -aG kusanagi circleusdev
usermod -aG www circleusdev

kusanagiグループを追加してもcircleusdevユーザーでcd /home/kusanagiがpermission denied

circleusdevユーザーでは、cd /home/kusanagiでpermission deniedが発生します。rootユーザーになり、permission denied が発生する/home/kusanagiディレクトリにて「グループ」のパーミッションの数値を調整します。

rootユーザーからcircleusdevユーザに変更

su - circleusdev

パーミッションでrwxの7を使いたくないですが、/home/kusnagi ディレクトリは701なので、グループをrwxとして771に変えます。751では同kusanagiグループのcircleusdevユーザーは書き込み出来ない(読みと実行のみ)ので気をつけてください。

chmod 771 /home/kusanagi

/home/kusanagi/.ssh(700➞770)を行うと鍵認証できなくなるのでくれぐれも気をつけてください。

手元のローカルマシンからリモートのステージ/開発サーバーにcircleusdevユーザーでssh接続

kusanagi 立ち上げ直後にやっておきたいLinuxユーザー設定の基本 でLinux一般ユーザーを作ってssh接続するまでの手順を確認出来ます。パスフレーズ無しでcircleusdevユーザーで同じ様に設定してください。

リモートのステージ/開発サーバーからgithubメインリポジトリにcircleusdevユーザーでssh接続

VPS(Linux)からgithubに接続でも手順を確認できますが、CircleCIで使う場合、以下の手順を推奨します。必ず、/home/circleusdev/.sshにてcircleusdevユーザーでパスフレーズ無しでssh-keygenコマンドで設定を行ってください。

ssh-keygen -t rsa -b 4096 -C "メールアドレス" -f id_rsa_github

id_rsa_github.pubはgithubのGUIでPersonal settings(Settings)➞SSH and GPG keys➞New SSH keyに登録してください。そして、/home/circleusdev/.ssh/configファイルを以下のように作り、接続先Hostをステージ/開発サーバに事前登録して、ssh github.comなどでgithubにssh接続出来るようにしてください。パスフレーズ無しでssh接続を出来る事によってシェルスクリプトによる自動化が可能となります。*今回は、Hostの接続名自体をgithub.comにしています。


  Host github.com
    HostName github.com
    IdentityFile /home/circleusdev/.ssh/id_rsa_github
    User git

/home/circleusdev/.ssh/config のパーミッションを600に変える

rootユーザーで行ってください

chmod 600 /home/circleusdev/.ssh/config

ステージ/開発サーバーのステージング環境https://hogehoge.comにdeploy_stage.shを作る

ステージ/開発サーバーのcircleusdevユーザーで

vi /home/kusanagi/hogehoge_html/deploy_stage.sh

を作ります。

deploy_stage.shの中身は以下の通りです。git pullコマンドのブランチ運用については少しずつ追記更新します。

#! /bin/bash
cd /home/kusanagi/hogehoge_html/DocumentRoot/wp-content/themes/something
git pull
echo "git pull !"

念のため

chown circleusdev:circleusdev  /home/kusanagi/hogehoge_html/deploy_stage.sh

も行い、ユーザー:グループを circleusdev:circleusdevにしておきます。

さらにrootユーザーで

chmod 775 /home/kusanagi/hogehoge_html/DocumentRoot/wp-content
chmod 775 /home/kusanagi/hogehoge_html/DocumentRoot/wp-content/themes
chown -R circleusdev /home/kusanagi/hogehoge_html/DocumentRoot/wp-content/themes/something/.git/

も行います。

最後に.circleci/config.ymlです。version: 2.1 のOrbsは使っていません。Environment variablesは適宜CircleCIで設定してください。

# Environment variables
# - HOST_NAME_STAGEDEV
# - USER_NAME_STAGEDEV
# - HOST_NAME_PROD
# - USER_NAME_PROD
version: 2
jobs:
  build:
    docker:
      - image: circleci/php:latest
    steps:
      - checkout
      #- run:
          #name: "Check Composer Version"
          #command: composer --version
      - add_ssh_keys:
          fingerprints:
            - "フィンガープリント"
      - run:
          name: Start ssh-keyscan
          command: |
            ssh-keyscan ${HOST_NAME_DEV} >> ~/.ssh/known_hosts
            echo ${CIRCLE_BRANCH}
      #- run: whoami
      - deploy:
          name: Start develop deploy
          command: |
            if [ "${CIRCLE_BRANCH}" == "master" ]; then
             ssh -o "StrictHostKeyChecking=no" ${USER_NAME_PROD}@${HOST_NAME_PROD} "/home/kusanagi/hogehoge_html/deploy_prod.sh"
            elif [ "${CIRCLE_BRANCH}" == "release" ]; then
             ssh -o "StrictHostKeyChecking=no" ${USER_NAME_STAGEDEV}@${HOST_NAME_STAGEDEV} "/home/kusanagi/hogehoge_html/deploy_stage.sh"
            elif [ "${CIRCLE_BRANCH}" == "develop" ]; then
             ssh -o "StrictHostKeyChecking=no" ${USER_NAME_STAGEDEV}@${HOST_NAME_STAGEDEV} "/home/kusanagi/dev01hogehoge_html/deploy_dev.sh"
            else
             echo "Not pull req"
            fi

本番環境、ステージング環境、開発環境からgithubへgit pullを行うdeploy_prod.sh、deploy_stage.sh、deploy_dev.shをそれぞれの環境のプロファイルディレクトリに配置、ローカル開発環境からgithubの中央リポジトリにfeatureなどの特定のブランチを指定してpullリクエスト、もしくはgithub上のフォークリポジトリから中央リポジトリへfeatureなどの特定のブランチを指定してpullリクエストを行い、masterブランチ / developブランチ / releaseブランチへのpushやmerge pull requestをトリガーとしてCircleCIで各ホストにssh接続してデプロイ向けシェルスクリプトの各ファイルをキックします。

今後やりたいこと

本番環境、ステージング環境、開発環境、それぞれの違いをわかりやすくするため環境別のホストIPや各種独自ドメインをDBに登録して、ブラウザで見ている環境が本番、ステージング、開発のどれであるか?簡単にわかるような環境判別プラグインを作りたい。

パーミッションは環境構築をしたインフラエンジニア以外、触ってはいけない

DevOpsチーム全体で、chmodやchownなどのパーミッション変更は、環境構築を行ったインフラエンジニア以外、勝手にやらないことをチーム内で徹底啓蒙する必要があります。本番デプロイで問題が起きる原因の1つとして、環境毎のパーミッション不揃い問題があります。インフラエンジニアの仕事は、トラブル原因Linuxユーザー(開発エンジニア)を特定しやすい管理、トラブルが起きないLinuxパーミッション管理、updatableでセキュア、デプロイがやりやすい、テストコードが上手で、速い軽い安定したサーバー、を維持しつつ、突然のヤフー砲に負けないサーバーを構築/維持することです。