grasys blog

Cloud Functionsを使ってCompute Engineを制御するという話

文●fukushima/grasys 編集● ASCII

  • この記事をはてなブックマークに追加
  • 本文印刷

本記事はgrasys が提供する「grasys blog」に掲載されたCloud Functionsを使ってCompute Engineを制御するという話」を再編集したものです。

 こんにちはgrasysの福嶌です。 そろそろ競輪祭の時期ですね。それが終わればグランプリなので1年はあっという間だなと言う感じしかしません。

はじめに

 grasysでは検証環境があります、ただ気軽に使えるのではなく金額を気にして使わないと怒られてしまいます。

 そのためインスタンスタイプを低くして使うことが多いのですが今回は非力ゆえにスペックの低いGCEインスタンスで起きた事象(CPUが100%に貼り付いてインスタンスにsshすらできなくなる)の解決策(その場しのぎの対応)について書いていこうかと思います。

事象

 検証で同僚[1]のインスタンスを間借りしようとしたらsshができなく確認したらCPUが100%に貼り付いている事象が発生していました。
 

 プロセスを確認するとGCEの以下のディレクトリのログが出力されており以下のディレクトリに出力されてました。


/.config/gcloud/logs/

 ドキュメントを見ると以下のような記載

ログファイルには、gcloud compute ツールを使用して送信されたすべてのリクエストとそのレスポンスに関する情報が含まれています。
https://cloud.google.com/compute/docs/troubleshooting/general-tips?hl=ja#viewlogs

 結局インスタンスタイプが低すぎて当該のプロセスが原因でCPUが100%に貼り付いてしまいインスタンスのリセットを行なうと事象は解決しましたが定期的に発生し都度リセットを行なうと言う作業をしていました。

解決方法

今回のゴールとして以下を設定しました。 CPUが100%になり貼り付いたらそれをトリガーとしてCloud Functions経由でインスタンスの制御を行なう

構成

 今回は以下のような構成で作っていこうと思います。

Cloud Pub/Sub

 アラートを飛ばす先のPub/Subの設定をします。アラート通知にPub/Subを設定は作ったPub/Subトピックにモニタリングに向けて権限設定を設定する必要があります。 ドキュメントを参考に以下のコマンドを実施


$ gcloud pubsub topics add-iam-policy-binding projects/{{プロジェクト名}}/topics/{{pub/subトピックID}} --role=roles/pubsub.publisher --member=serviceAccount:xxxxx@gcp-sa-monitoring-notification.iam.gserviceaccount.com

Cloud Monitoring

 アラートは以下のように設定


対象インスタンス:自分の検証に利用しているインスタンス
Condition: is above
Threshold: 99.9
For: 5 minutes

 99.9%以上の高負荷が5分続いた場合アラートを発砲するようにしました。

 通知先は念のためメールとPub/Subにします。

Cloud Functions

 制御するコードは以下のようなコードを作成しました。今回はgoogle-authgoogle-api-python-clientを利用してAPIを叩きます。


#!/usr/bin/python
#coding:utf-8

import sys
import json
import base64

import google.auth
import googleapiclient.discovery

class Variables:
    name = {{インスタンス名}}
    zone = {{ゾーン名}}}

def reset_instances(compute, project, zone):
    # 対象のVMをリセット
    try:
        compute.instances().reset(project=project, zone=zone, instance=Variables.name).execute()
    except Exception as e:
        print(e)
        sys.exit(1)

    return "success"

def alert2pubsubFunc(event, context):
    if 'data' in event:
        req = base64.b64decode(event['data']).decode('utf-8')
        staus = json.loads(req)['incident']['state']
    else:
        sys.exit(2)

    compute = googleapiclient.discovery.build('compute', 'v1')
    project = google.auth.default()[1]

    # Alert open
    if staus == "open":
        print(reset_instances(compute, project, Variables.zone))

 また、Cloud FunctionsのランタイムはPython3.9を利用します。デプロイは以下のコマンドで実施


$ gcloud functions deploy alert2pubsubFunc --trigger-topic {{pub/subトピックID}} --runtime python39 --region asia-northeast1

 デプロイエラーが出ると思ったら、Pyparsingが最新で3.0.6ためCloud Functionsでデプロイエラーを起こしてしまうようです。stackoverflowで探したら解決としてはバージョンを2.4.7に指定し解決しました。

テスト

 そしたら早速テストをしてみましょう!

 発報するためにアラートの閾値を低めに設定しアラートを飛ばしやすく調整を行ない。サーバー内で以下のコマンドを実行してCPU負荷を高くしてみます。


$ yes > /dev/null

 アラートが12:50に発報され…

 モニタリングの方で確認したらインスタンスがリセットされた!

 うまく動いてますね!

まとめ

 今回はアラートをpub/subに送ってCloud FunctionsのトリガーとしてCompute Engineを制御しました。

 またCloud FunctionsをHTTPリクエストにしてアラートではなくCloud Schedulerなどを応用して使えば自動起動や自動停止なども簡単にできそうですね。こちらの記事とか参考になると思います。

 上記ができれば無駄な稼働時時間をなくすことができるのでお財布に優しいはず!

 現場からは以上です!

■関連サイト

この記事の編集者は以下の記事もオススメしています

過去記事アーカイブ

2023年
01月
03月
2022年
01月
02月
03月
04月
05月
06月
07月
08月
12月
2021年
03月
04月
05月
06月
07月
08月
09月
10月
11月
12月
2020年
04月
05月
08月
09月
10月
11月
12月
2018年
09月
2017年
06月
2014年
07月