こんにちは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-authとgoogle-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などを応用して使えば自動起動や自動停止なども簡単にできそうですね。こちらの記事とか参考になると思います。
上記ができれば無駄な稼働時時間をなくすことができるのでお財布に優しいはず!
現場からは以上です!
株式会社grasys(グラシス)は、技術が好きで一緒に夢中になれる仲間を募集しています。
grasysは、大規模・高負荷・高集積・高密度なシステムを多く扱っているITインフラの会社です。Google Cloud (GCP)、Amazon Web Services (AWS)、Microsoft Azureの最先端技術を活用してクラウドインフラやデータ分析基盤など、ITシステムの重要な基盤を設計・構築し、改善を続けながら運用しています。
お客様の課題解決をしながら技術を広げたい方、攻めのインフラ技術を習得したい方、とことん技術を追求したい方にとって素晴らしい環境が、grasysにはあります。
お気軽にご連絡ください。