目次

今回は、CachetをOpenShiftにデプロイして実行するまでの手順と運用していく上でハマったポイントなど。

はじめに

一応、私が運用しているものは以下になります。これはOpenShiftとMySQL, Cachetなどを使っています。

http://cachet-tapp.1d35.starter-us-east-1.openshiftapps.com/

OpenShift

まず、OpenShiftについてですが、これはRed Hatが開発するPaaS(IaaSに近い)基盤のようなもので、今回使ったものはOpenShift V3 Onlineの無料枠になります。

OpenShiftにも色々あり、基本的にはOpenShift Enterpriseを指すことが多いですが、これは、Dockerコンテナでアプリケーションを動作させるためのPaaS基盤です。GoogleのKubernetes(k8s)をベースに構築されています。

OpenShift Onlineでは、このOpenShift Enterpriseをサービスとして運用していて、分かりやすく言うとGCP(Google Cloud Platform)のGKE(Google Container Engile)のようなものです。

最終的にはPodという形でアプリがデプロイされ、Podというのは、Docker Containerの集まりみたいなもので、この間においては連携(共有)が可能となります。

Cachet

Cachetというのは、Webサイト監視ツールのようなもので、特徴としてはサービス運用を始めとしたメール購読などが可能です。

例えば、StatusCakeのようなWebサイトを自分で作れると言えば分かりやすいかもしれません。

実際の運用では、一部機能を無効にしたり、また、サインアップなども停止しています。OpenShiftの無料枠で運用しているため、負担を必要最小限に留めるようにしています。

openshift-cachet

https://github.com/cyril-dussert/Cachet-openshift

https://github.com/cyril-dussert/Cachet-openshift/blob/c6a3bd0cf75cffd625d3eb76213f1d62971c8c61/bootstrap/autoload.php

bootstrap/autoload.php

//L12 
//KERMIT MODIFICATION
ini_set('xdebug.max_nesting_level', 300);

OpenShiftの使い方

ocのインストール

様々なコマンドラインツールが用意されていますが、ここではocを使います。検索すると似たものにoadmというものがでてきますが、これはoc admを意味します。つまりocadmオプションで実現できるということです。よって、とりあえずocをインストールすればいいと思います。

https://docs.openshift.com/online/cli_reference/get_started_cli.html

ocの使い方

  • 基本的にはloginして使用します

  • 無料枠ではadm(権限)は使えません

  • localhostで使うことができます。この場合、admを使うことができます

localhost

まずはlocalhostで実行してみましょう。loginがlocalhostならdocer registryへのpingなどは通ります。

$ oc cluster up
$ oc login -u system:admin
# oc new-project myproject

$ oc get scc
$ oc adm policy add-scc-to-group anyuid system:authenticated

$ oc new-app https://github.com/openshift/sti-php.git --context-dir=5.5/test/test-app -l app=php --strategy=source
$ oc get all
$ oc build-logs sti-php-1
$ oc get all
	svc/sti-php 172.30.36.155 <none> 8080/TCP  
$ ping 172.30.36.155
$ curl 172.30.36.155:8080

ポイントとしては、oc get allで表示される出力の意味です。大体は以下の通りの意味になります。

pod, po

build

route

service, svc

buildconfig, bc

deploymentconfig, dc

replicationcontroller, rc

imagestream, is

persistentvolumeclaim, pvc

例えば、svc=serviceの意味であり、これが表示されるとサービスが公開されていることを意味します。svc/sti-php

po=podという意味でこの名前がappname-n-build, appname-n-deploy, appname-n-numberという順に立ち上がります。そして1/1 RunningになっていればそのPodが走っていることになります。つまり、最新版に更新されているということです。

少し分かりにくいかもしれませんが、何度か触っているうちにわかってくると思います。

oc get allの結果は個別に見ることもできます。

$ oc get service
svc/sti-php

$ oc get pod
po/sti-php-1-build 1/1 Running
po/sti-php-1-deploy 1/1 Running
po/sti-php-1-xxxxx 1/1 Running

なお、po/sti-php-1-build, deployは削除しても構いません。xxxxxを削除すると再度、deployが走ることになります。

$ oc delete po/sti-php-1-build po/sti-php-1-deploy
$ oc delete rc/sti-php-1
$ oc delete builds/sti-php

無料枠で運用する場合、Podが3つ以上になるとエラーが出やすいです。なので、頻繁にoc deleteは使うことになるでしょう。

login user (online)

次は、onlineのuserでloginしてみます。

$ oc login https://api.starter-us-east-1.openshift.com --token=xxxxxx
$ oc whoami
$ oc get project

$ oc new-project xxxxx

Deploying Cachet on Openshift

# まずはdb serverを立ち上げる、これはsvc/dbがdocker registry address(172.30.x.x)で公開されていればok
# DB_XXXXの変数は必要がないかもしれない
$ oc new-app mysql \
	-e MYSQL_USER=${user} \
	-e MYSQL_PASSWORD=${pass} \
	-e MYSQL_DATABASE=${base} \
	-l db=mysql \
	-e DB_USERNAME=${user} \
	-e DB_PASSWORD=${pass} \
	-e DB_DATABESE=${base} \
	-e DB_PORT=3306

$ oc get service
	copy : 172.30.xx.xx -> DB_HOST
$ oc get pod
	po/mysql-n-xxx 1/1 Running # deployされ有効なpodが存在してる確認

# 次にcachetをbuild, deploy
$ oc new-app php~https://github.com/CachetHQ/Cachet \
	-e DOCUMENTROOT=/public \
	-e DB_USERNAME=${user} \
	-e DB_PASSWORD=${pass} \
	-e DB_DATABESE=${base} \
	-e DB_HOST=172.30.xx.xx \
	-e DB_PORT=3306

$ oc get pod
	po/cachet-1-build
	po/cachet-1-deploy
	po/cachet-1-xxx

# コンテナにリモートアクセスする
$ oc rsh po/cachet-1-xxx

	$ cp .env.example .env
	$ vi .env
	$ php composer.phar install --no-dev -o
	$ php artisan app:install
	$ php artisan key:generate
	$ php artisan migrate 
	$ php artisan up
	$ exit

$ oc expose svc/cachet
$ oc get all
	routes/cachet ${appname}-${projectname}.xxx.starter-us-east-1.openshiftapps.com 8080-tcp

mysql:env:DB_XXXX

MySQLをbuild,deployする際にDB_XXXXの変数は必要がないかもしれないと書きましたが、これは、Cachetの.envに以下のような項目が書かれているからです。

DB_DRIVER=mysql

DB_USERNAME=xxxx
DB_PASSWORD=xxxx
...

最初にDB_DRIVERmysqlを指定しています。これによってDBにアクセスする際の環境変数が設定されるものと思われます。DBはmysqlの他、postgresqlなどにも対応しているようです。

しかし、Cachetでどれが対応しているのかわかりやすくするために書いておきました。

svc/cachet:ip address

172.30.xx.xxのアドレスはDocker Registry(k8s)のものですので、内部では共有できますが外部からのアクセスは不可能です。

これを外部に公開するには$ oc expose service $app-nameを実行します。これによってxxx.openshiftapp.comのアドレスが付与されます(通常は)。

# svc/cachet = service cachet
$ oc expose svc/cachet
$ oc expose service cachet --hostname=foo.example.com

$ oc get all
	routes/cachet ${appname}-${projectname}.xxx.starter-us-east-1.openshiftapps.com 8080-tcp
	routes/cachet foo.example.com

後は、routesで発行されたopenshiftapp.comのアドレスにアクセスして確認します。

私は、CloudFlareのDNSでCNAME foo xxx.openshiftapp.comを設定しました。これによって、routesで2つ目に作ったfoo.example.comからでもアクセスできるようになります。

# アップデートとか
$ oc start-build cachet --commit=xxxxxx

# k8s describe
$ oc describe po/cachet-n-xxx
$ oc describe po/mysql-n-xxx

OpenShiftに関しては参考情報を読んでみてください。

cachet:env:example

cachetコンテナ内のWORKDIRにある.envについてです。編集例を載せておきます。

$ oc get pod
$ oc rsh svc/cachet-n-xxx

.env

APP_ENV=production
APP_DEBUG=false
APP_URL=http://$appname-$projectname-xxx.openshiftapp.com
# APP_KEYは $ php artisan key:generate を実行すると自動で入る, 更新した際はmigrateを実行する必要
APP_KEY=xxxx

DB_DRIVER=mysql
# DB_HOSTは $ oc get svc/mysql で調べたip addressを入れる
DB_HOST=172.30.11.155
DB_DATABASE=${base}
DB_USERNAME=${user}
DB_PASSWORD=${pass}
DB_PORT=3306
DB_PREFIX=null

CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync

cachet:queue

$ php artisan queue:listen
$ php artisan queue:work --daemon
$ php artisan queue:work --delay=1 --sleep=1 --timeout=1800 --tries=3 --daemon

$ /usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf

cachet:mail

mail, 購読機能に関しては以下の情報を確認してください。

https://docs.cachethq.io/v1.0/docs/configuring-the-queue

https://docs.cachethq.io/v1.0/docs/configuring-mail

.env

MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=587
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ADDRESS=null
MAIL_NAME=null
MAIL_ENCRYPTION=tls
$ php artisan config:cache
$ rm -rf bootstrap/cache/*

cachet:client

https://docs.cachethq.io/v1.0/docs/client-libraries

main.go

package main

import (
	"fmt"
	"github.com/andygrunwald/cachet"
)

func main() {
	client, _ := cachet.NewClient("https://demo.cachethq.io/", nil)
	pong, resp, _ := client.General.Ping()

	fmt.Printf("Result: %s\n", pong)
	fmt.Printf("Status: %s\n", resp.Status)

	// Output: Result: Pong!
	// Status: 200 OK
}

cachet:addon

plugin(addon)に関しては以下を確認してください。

https://docs.cachethq.io/v1.0/docs/addons

Error

openshift:limit.cpu etc…

OpenShiftのocは非常に使いやすいです。Documentも充実しています。しかし、日本語情報が不足していますし、limit errorに関してscaleがあまりうまくいかずよく分かりませんでした。現在はpoを3つ以上貯めないようにしてエラーを回避しています。

exceeded quota: compute-resources, requested: limits.cpu=1,limits.memory=512Mi, used: limits.cpu=2,limits.memory=1Gi, limited: limits.cpu=2,limits.memory=1Gi

これらは$ oc describe po/xxxなどである程度調べられます。

$ oc get pod
$ oc describe po/cachet po/mysql

cachet:docker unable to validate against any security context constraint

CachetにはDocker Imageが用意されていますが、無料枠では実行できませんでした。

localhostで実行してみても600秒タイムエラーなどがでた記憶。

$ oc cluster up
$ oc login -u system:admin
$ oc adm policy add-scc-to-group anyuid system:authenticated
$ git clone https://github.com/CachetHQ/Docker cachet-docker
$ cd cachet-docker/openshift
$ oc create -f cachethd-dc.yaml

そして、$ oc get scc問題を解決するには$ oc adm権限が必要です。無料枠ではこの問題を解決できません。

Error creating: pods “cachet-1-” is forbidden: unable to validate against any security context constraint: [securityContext.runAsUser: Invalid value: 0: UID on container cachet does not match required range. Found 0, required min: 1000250000 max: 1000259999]

issue : https://github.com/CachetHQ/Docker/issues/175

cachet:CSRF token validation failed

Cachetにて/setupにアクセスした最初にCSRF token validation failedというエラーが出ていました。これは以下のコミットなどで修正されました。

commit : https://github.com/CachetHQ/Cachet/commit/e426eff98c18e60be9f659bb935df1a12193156e

issue : https://github.com/CachetHQ/Cachet/issues/2741

cachet:heroku deploy

現在、HerokuではCachetは動きません。

deploy : https://github.com/ProxyBite/Cachet

issue : https://github.com/cachethq/Cachet/issues/557

issue : https://github.com/CachetHQ/Cachet/issues/2391#issuecomment-283408062

Yeah, Cachet no longer officially supports Heroku.

Brian’s comment should help other directions though.

リポジトリの追加

$ oc new-build php~https://github.com/syui/Cachet --name cachet

cloudflare:ssl=full

SSLはflexiableでないとApplication is not availableがでてアクセスできませんね。

issue : https://github.com/cachethq/Cachet/issues/592

いつの間にかApplication is not availableが出るようになった

RoutesのSecurityにて”Allow”だと、https通信にならないことがあるので、”Redirect”が一番おすすめということのようです。

poがいきなりリセットされ、繋がらなくなるのは、一体どういうことなのか。もしかしたら待ってたら直るのかもしれません。相変わらずopenshiftはかなり不安定でbluemixと良い勝負です。herokuが一番安定しています。

一旦、Projectを削除して作り直すまで、うまくPodが生成されなかった。これは、設定の問題とかそういうことではなく、単なるバグだと思います。若しくは制限か。今まで何時間もデプロイに時間がかかっていましたが、一旦、Projectを削除して作り直すと、ほぼ問題ない時間で完了しました。

しかし、問題があって、Projectを削除するとStorageまで削除されてしまうということです。これは予めバックアップしておくことで対応しますが、面倒なことに変わりません。

Add Storage

Storageで作った1GのStorage(仮にsbaとします)をMySQLの/var/lib/mysql/dataに割り当てます。元からマウントされているストレージはremoveします。または、先にCachetのアプリを作ってしまったことが原因かもしれません。順番としてはMySQLのあとに作成します。

Application -> Deployments -> Cofiguration -> add storage

remove : default, volume-xxxxxx
add storage : sba, /var/lib/mysql/data
# このコマンドは必要ありません
$ php artisan migrate:reset
$ php artisan migrate

[Illuminate\Database\QueryException]

これは多分、MySQLの問題です。

issue : https://github.com/CachetHQ/Cachet/issues/2272

$ php artisan app:install
[Illuminate\Database\QueryException]

$ rm -rf bootstrap/cache/*
$ php artisan config:cache

$ php artisan app:install
[Illuminate\Database\QueryException]

issue : https://github.com/CachetHQ/Cachet/issues/1997#issuecomment-320103664

$ echo "" > database/database.sqlite
$ php artisan migrate
$ php artisan app:install

https://docs.cachethq.io/docs/installing-cachet

$ chmod -R 777 bootstrap/
$ chmod -R 777 storage
$ rm -rf bootstrap/cache/*

上記では全く解決せず、MySQLのPodを新しく作り直したら解決しました。

The route is not accepting traffic yet because it has not been admitted by a router

様々な問題がありました。問題の代表格はRoutesが作成できない問題であり、作成できたとしてもThe route is not accepting traffic yet because it has not been admitted by a routerが出ます。

以下、解決策若しくは原因と思われる事柄をまとめました。

  • build, deployが通らない -> アカウント削除して作り直し、プロジェクトを再度立ち上げて時間を置いた

  • oc expose svc/xxxxxが通らない -> issueを書いたら翌日何故か通るようになった

$ oc expose svc/xxxxx
The route is not accepting traffic yet because it has not been admitted by a router
  • routes/custom domainが作れない -> どうやらproのオプションだったらしく、最近制限が再適用されただとかなんとか

An error occurred creating the route

An error occurred creating the route. Reason: Route “xxxxx” is invalid: spec.host: Forbidden: you do not have permission to set the host field of the route

  • 4回くらいリロードしないとアプリエラーが出る -> issueを書いて、その翌日くらいで解消した

issue : https://github.com/openshift/openshift-docs/issues/6086

issue : https://github.com/openshift/origin/issues/17183

参考

https://github.com/nekop/openshift-sandbox/blob/master/docs/developer-handson.md