SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

KubernetesによるスケーラブルなWebアプリ環境の構築

Google Stackdriverにおける、アラートの設定とアプリケーションのログの設定

KubernetesによるスケーラブルなWebアプリ環境の構築 第6回

  • X ポスト
  • このエントリーをはてなブックマークに追加

エラーログが発生した時のアラートの設定

 次に、エラーログが発生した際のアラートの設定をしていましょう。エラーログのアラート通知は以下のフローです。

  1. アプリケーションでログレベルがエラー以上のログが発生
  2. Stackdriverのロギングにエラーログが送られる
  3. 「Stackdriverロギングの指標」の機能でエラーログが検出される

 この処理フローを実現するためには以下の手順が必要です。​

  1. Stackdriverロギングの形式になったログフォーマット(JSON)でログレベルを出力するように、アプリケーション側の変更を行う。
  2. ログレベルがエラー以上のログを検出する指標を作成する。
  3. 先ほど作成した指標のCondition(状態)を条件にしたアラートを作成する。

Stackdriverロギング

 手順の説明に入る前に、Stackdriverロギングについて簡単に説明します。Stackdriverロギングは主にログの収集と分析を行うことができるサービスです。GKEはStackdriverロギングと連携する機能があり、機能を有効にしているとGKEのコンテナで出力されたログは自動的にStackdriverに収集、保存されます。

 Stackdriverロギングにはブラウザから見られるログのビューア機能もあり、ログレベルや特定の文字列をフィルタにしてログを表示することができます。他にもログベースの指標の機能を使って、特定の条件に合致したログエントリの数を記録する指標を作ることができます。

1.Stackdriverロギングの形式になったログフォーマット(JSON)でログレベルを出力するように、アプリケーション側の変更を行う。

 GKEのコンテナで出力したログは、基本的には標準出力であればログレベルがINFO、標準エラー出力であればERRORになります。しかしログをJSON形式した上で、severityというキーにINFOやERRORといった値を指定して出力することで、その値に応じたログレベルを持ったログに変更できます。今回は検証用にseverityでログレベルを指定し、ログを出力するアプリケーションを作成します。

 検証に使うアプリケーションは、どんなものでも構いません。今回はGo言語を使ったものを紹介します。エディタを開き、リスト2の内容をコピーして「server.go」のファイル名で保存してください。

リスト2 server.go
package main

import (
	"os"
	"fmt"
	"net/http"
)

func stdoutHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "stdout")
	fmt.Print("stdout")
}

func stderrHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "stderr")
	os.Stderr.WriteString("stderr")
}

func infoHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Println(`{"severity": "INFO", "message":"info"}`)
	fmt.Fprintf(w, "info")
}

func warningHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Println(`{"severity": "WARNING", "message":"warning"}`)
	fmt.Fprintf(w, "warning")
}

func errorHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Println(`{"severity": "ERROR", "message":"error"}`)
	fmt.Fprintf(w, "error")
}

func criticalHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Println(`{"severity": "CRITICAL", "message":"critical"}`)
	fmt.Fprintf(w, "critical")
}

func main() {
	http.HandleFunc("/stdout/", stdoutHandler)
	http.HandleFunc("/stderr/", stderrHandler)
	http.HandleFunc("/info/", infoHandler)
	http.HandleFunc("/warning/", warningHandler)
	http.HandleFunc("/error/", errorHandler)
	http.HandleFunc("/critical/", criticalHandler)
	http.ListenAndServe(":80", nil)
}

 このアプリケーションは、エンドポイントのパスに応じたログレベルのログを出力するように作ってあります。例えば「/info/」であればログレベルがINFO、「/error/」であればログレベルがERRORといった具合です。今回は検証ということで、INFO、WARNING、ERROR、CRITICALのログレベルのログを出力します。その他のStackdriverで使えるログレベルを確認したい方は、公式サイトのLogSevertiyのEnumsの項目をご覧ください。

 また、検証において標準出力と標準エラー出力の場合、ログレベルがどうなるかを確認するため、それらのログを出力する「/stdout/」と「/stderr/」のパスを持ったエンドポイントも作ってあります。

 次は、このアプリケーションのDockerコンテナイメージを作成するDockerfileを作っていきましょう。エディタを開き、リスト3の内容をコピーして「Dockerfile」のファイル名で保存してください。

リスト3 Dockerfile
FROM golang:1.9.2-alpine3.6

ADD ./server.go ./
RUN go build -o server
CMD ["/go/server"]

 このDockerfileはgo buildで先ほどのGoのファイルをビルドし、コンテナ起動時にビルドしたアプリケーションを起動するように設定したものです。

 それでは、このDockerfileをbuildしてContainer Registryにpushしましょう。

$ docker build -t gcr.io/{プロジェクト名}/my-api:logtest .
$ gcloud docker -- push gcr.io/{プロジェクト名}/my-api:logtest

 次に、このアプリケーションをGKEにデプロイしましょう。エディタを開き、リスト4の内容をコピーして「my-api-logtest.yaml」のファイル名で保存してください。

リスト4 my-api-logtest.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-api-logtest
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: my-api
        version: logtest
    spec:
      containers:
      - name: my-api-logtest
        image: gcr.io/{プロジェクト名}/my-api:logtest #先ほどpushしたイメージを指定(1)
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: my-api-logtest
spec:
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    name: http
  selector:
    app: my-api
    version: logtest

 コンテナのイメージを指定している(1)の箇所は先ほどpushしたイメージに合わせて変更してください。

 それではデプロイしていきましょう。

$kubectl apply -f my-api-logtest.yaml

 デプロイが完了したら、curlコマンドでアプリケーションをたたいてみましょう。

$curl --resolve dev.app.io:80:{ingress-ip} http://dev.app.io/versions/logtest/info/

 これで、INFOのログレベルを持ったログが出力されました。

 では実際にStackdriverのLoggingのページに行って、INFOのログレベルのログが出力されたかを確認しましょう。手順は以下の通りです。

 最初にGCPのコンソールからStackdriver Loggingのページにアクセスします。次にログのページに移動して、ログビューアのプルダウンメニューから[GKEコンテナ>{クラスタ名}>{default(ネームスペース)}]を選択してください。

[GKEコンテナ>{クラスタ名}>{default(ネームスペース)}]を選択
[GKEコンテナ>{クラスタ名}>{default(ネームスペース)}]を選択

 次にすべてのログのプルダウンメニューから「my-api-logtest」を選択して[OK]を押してください。

プルダウンメニューから「my-api-logtest」を選択
プルダウンメニューから「my-api-logtest」を選択

 これで、先ほどデプロイしたアプリケーションのログが確認できるはずです。

ログ画面
ログ画面

 この画像を見ると、ログのメッセージが「info」でseverityが「INFO」になっていることが確認できると思います。他にも以下のcurlコマンドでアプリケーションのエンドポイントをたたくと、それに応じたログが出力されログビューアで確認ができるので試してみてください。ちなみにログがStackdriverに反映されるまでに多少ラグがあるので注意してください。

$curl --resolve dev.app.io:80:{ingress-ip} http://dev.app.io/versions/logtest/warning/
$curl --resolve dev.app.io:80:{ingress-ip} http://dev.app.io/versions/logtest/error/
$curl --resolve dev.app.io:80:{ingress-ip} http://dev.app.io/versions/logtest/critical/
$curl --resolve dev.app.io:80:{ingress-ip} http://dev.app.io/versions/logtest/stdout/
$curl --resolve dev.app.io:80:{ingress-ip} http://dev.app.io/versions/logtest/stderr/

 warning、error、criticalはエンドポイントのパスと同じログレベルのログを出力されるはずです。stdout(標準出力)とstderr(標準エラー出力)はseverity(ログレベル)の指定はしてませんが、stdoutの方はINFOで、stderrはERRORのログレベルになります。

2.ログレベルがエラー以上のログを検出する指標を作成する。

 次に指標を作成していましょう。指標は先ほどのログビューアのページから作成することができます。プルダウンメニューからログのレベルを「エラー」に変更し、左上の[指標を作成]をクリックしてください。

指標を作成
指標を作成

 指標エディタが開くので、適当な名前を入れ[指標を作成]を押せば完了です。

指標エディタ
指標エディタ

 指標を作成すると「ログベースの指標」のページに遷移します。このまま続けて、この指標を元にしたアラートを作成していきましょう。

 先ほど作成した指標が[ユーザー定義の指標]の下に表示されているので、その右端の丸が3つ縦に並んでいるアイコンをクリックすると[指標に基づいて通知を作成する]という項目が出てきます。それをクリックをすると「Add Metric Threshold Condition」のページに遷移するので、「Configuration」の下の構成を変更していきましょう。まず「CONDITION」を「above」に「THRESHOLD」を「0.001」に「FOR」を「1 minute」にします。これは「1分間以上、0.001以上のエラーログが発生した場合」という条件になります。

 次に「RESOURCE」を「gke_container」に変更してください。正しい設定ができてエラーログがあれば、下の画像のように発生したエラーログによって山ができたグラフが確認できるはずです。

Add Metric Threshold Conditionの画面
Add Metric Threshold Conditionの画面

Note

 もし、エラーログがグラフに反映されていなければ、グラフの[TIME]を変更するかcurlコマンドでエラーのエンドポイントをたたいてエラーログを出力してみてください。StackDriverのロギングはログが発生してから実際に反映されるまで多少ラグがあります。そのため、エラーログが検出されない場合は少し間を開けてください。

 確認ができたら[Save Condition]を押して保存しましょう。保存すると「Create new alerting policy」というアラートポリシーの画面に遷移するので、このまま[Save Policy]を押してアラートを保存しましょう。

Save Policy後のPolicies Overview
Save Policy後のPolicies Overview

 右に表示されている「OPEN」が現在発生しているアラート、「ACKNOWLEDGED」が確認済みのアラート、「RESOLVED」が解決済みのアラートです。

 最後に、実際にアラートが発生した時の挙動を確認しましょう。アラートポリシーの条件に引っかかるように、curlコマンドを間隔を開けて2回たたきます。

$curl --resolve dev.app.io:80:{ingress-ip} http://dev.app.io/versions/logtest/error/ && sleep 55 s && curl --resolve dev.app.io:80:{ingress-ip} http://dev.app.io/versions/logtest/error/

 しばらくしてからアラートポリシーの一覧画面にアクセスすると、OPENが1以上になっていることが確認できると思います。

 ちなみにAlertingから「Incident」のメニューを選択することで、OPENになっているアラートを一覧で確認できるようになっています。

Incidentのページ
Incidentのページ

 OPENになったアラートはアラートポリシーの条件を満たさなくなると、自動的にRESOLVEDになります。

最後に

 今回はアラートの設定とアプリケーションのログの設定ついて解説をしました。アラートの設定はアプリケーションを運用していく上で欠かせないものです。ぜひ試してください。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
KubernetesによるスケーラブルなWebアプリ環境の構築連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 吉海 将太(ヨシカイ ショウタ)

 株式会社カブクのサーバーサイドエンジニアです。APIの開発(Python,GO,AppEngine)とKubernetesによるインフラ環境の構築を担当しています。好きな獣はチベットスナギツネです。 Twitter: @yoshikai_ FacebookWINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト)

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/10703 2018/03/23 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング