ã¿ã¤ãã«ã®éããGoogle Cloud monitoringã®ã¢ã©ã¼ããGitHub Issueã«éç¥ããã·ã¹ãã ã®æ§ç¯æ¹æ³ãç´¹ä»ãã¾ãã
terrafromã使ã£ã¦ä½æãã¾ãã
ã³ã¼ãã¯GitHubãªãã¸ããªã«ã¾ã¨ã¾ã£ã¦ãã¾ãã
ãã®ã³ã¼ããapplyãããã¨ã§ãWebãµã¼ãã¹(EasyBuggy)ãç£è¦ãã¢ã©ã¼ããIssueã«æã£ã¦ãããã¤ãã©ã¤ã³ããããã¤ããã¾ãã
ã·ã¹ãã å³
ãã®ãããªæ§æãã¨ã£ã¦ãã¾ãã
main.tf
æ©éã³ã¼ããç´¹ä»ãã¦ããã¾ãããã®ãã¡ã¤ã«ã§ã¯ãEasyBuggyã¨ããèå¼±ãªWebãµã¼ãã¹ãGCEã«ãããã¤ãã¾ãã
terraform { required_providers { google = { source = "hashicorp/google" version = "5.39.0" } } } provider "google" { credentials = var.credential_file project = var.project region = var.region } resource "google_compute_instance" "easybuggy" { name = "easybuggy-instance" machine_type = "n1-standard-1" zone = var.zone boot_disk { initialize_params { image = "debian-cloud/debian-11" } } network_interface { network = "default" access_config {} } metadata = { "enable-osconfig" = "true" } metadata_startup_script = <<EOF #!/bin/bash sudo apt-get update for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done sudo apt-get install -y ca-certificates curl git sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo git clone https://github.com/k-tamura/easybuggy.git cd easybuggy sudo docker build . -t easybuggy:local sudo docker run -p 8080:8080 easybuggy:local EOF } resource "google_compute_firewall" "allow-home-ip" { name = "allow-home-ip" network = "default" allow { protocol = "tcp" ports = ["8080"] } source_ranges = [var.my_ip] } output "instance_ip" { value = google_compute_instance.easybuggy.network_interface[0].access_config[0].nat_ip }
monitoring.tf
ãã¡ãã®ãã¡ã¤ã«ã§ã¯ç£è¦ãã¢ã©ã¼ããIssueã«æã£ã¦ãããã¤ãã©ã¤ã³ããããã¤ãã¾ããmain.tfã§ãããã¤ããã¤ã³ã¹ã¿ã³ã¹ã®CPU使ç¨çã80%ãè¶ ããã¨ã¢ã©ã¼ããçºçãã¾ãã
resource "google_pubsub_topic" "alerts_topic" { name = "alerts-topic" } resource "google_pubsub_subscription" "alerts_subscription" { name = "alerts-subscription" topic = google_pubsub_topic.alerts_topic.name } resource "google_monitoring_notification_channel" "pubsub_channel" { display_name = "Pub/Sub to Cloud Function" type = "pubsub" labels = { "topic" = google_pubsub_topic.alerts_topic.id } } resource "google_pubsub_topic_iam_binding" "alerts_topic_publisher" { topic = google_pubsub_topic.alerts_topic.name role = "roles/pubsub.publisher" members = [ "serviceAccount:service-${var.project_id}@gcp-sa-monitoring-notification.iam.gserviceaccount.com" ] } resource "google_storage_bucket" "easybuggy_monitoring_function_bucket" { name = "easybubby_monitoring-functions-bucket" location = "ASIA-NORTHEAST1" force_destroy = true } resource "google_storage_bucket_object" "function_source_object" { name = "function-source.zip" bucket = google_storage_bucket.easybuggy_monitoring_function_bucket.name source = "function-source.zip" } resource "google_cloudfunctions_function" "issue_creator_function" { name = "issue-creator-function" description = "Receive Pub/Sub message from Google Cloud Monitoring and create a GitHub issue" runtime = "python39" source_archive_bucket = google_storage_bucket.easybuggy_monitoring_function_bucket.name source_archive_object = google_storage_bucket_object.function_source_object.name entry_point = "main" region = var.region environment_variables = { "GITHUB_API_TOKEN" = var.github_api_token "GITHUB_REPO" = var.github_repo "GITHUB_OWNER" = var.github_owner } event_trigger { event_type = "providers/cloud.pubsub/eventTypes/topic.publish" resource = google_pubsub_topic.alerts_topic.id } } resource "google_monitoring_alert_policy" "cpu_usage_policy" { display_name = "High CPU Utilization Alert" combiner = "OR" conditions { display_name = "CPU usage over 80%" condition_threshold { filter = "metric.type=\"compute.googleapis.com/instance/cpu/utilization\" AND resource.type=\"gce_instance\"" duration = "60s" comparison = "COMPARISON_GT" threshold_value = 0.8 } } enabled = true notification_channels = [google_monitoring_notification_channel.pubsub_channel.id] }
main.py
functionsã§å®è¡ãããã³ã¼ãã§ããpub/subããåãåã£ããã¼ã¿ããã¢ã©ã¼ãã®titleã¨bodyãæãåºãã¦Github Issueã«ãã¹ããã¾ãã
import base64 import json import os import logging import requests from flask import Flask, request app = Flask(__name__) GITHUB_API_TOKEN = os.environ.get('GITHUB_API_TOKEN') GITHUB_REPO = os.environ.get('GITHUB_REPO') GITHUB_OWNER = os.environ.get('GITHUB_OWNER') logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) def create_github_issue(data): issue_title = f"Alert: {data['incident']['incident_id']}" issue_body = data['incident']['summary'] logger.info(f"Creating issue with title: {issue_title} body: {issue_body}") response = requests.post( f"https://api.github.com/repos/{GITHUB_OWNER}/{GITHUB_REPO}/issues", headers={ "Authorization": f"token {GITHUB_API_TOKEN}", "Accept": "application/vnd.github.v3+json", }, json={ "title": issue_title, "body": issue_body, }, ) if response.status_code == 201: logger.info("Issue created successfully") return "Issue created successfully", 201 else: logger.error(f"Failed to create issue: {response.content}") return f"Failed to create issue: {response.content}", response.status_code @app.route('/', methods=['POST']) def main(d, context): #Need to receive arguments envelope = request.get_json() if not envelope: logger.error("No envelope received") return "Bad Request", 400 logger.info(f"envelope: {envelope}") pubsub_data = envelope.get('data', {}) logger.info(f"pub_sub_data") if not pubsub_data: logger.error(f"No outside data received: ") return "Bad Request", 400 try: data_base64 = pubsub_data.get('data', '') if not data_base64: raise ValueError("No data field in outside data") data = base64.b64decode(data_base64.encode('utf-8')).decode('utf-8') logger.info(f"Decoded data: {data}") data = json.loads(data) logger.info(f"Received data: {data}") except Exception as e: logger.error(f"Error processing message: {e}") return "Bad Request", 400 return create_github_issue(data) if __name__ == "__main__": app.run()
ãããã¤
å
容ãç解ãããterraform apply
ãã¾ããããã¢ãã©ã¤ãæåãããã¤ã³ã¹ã¿ã³ã¹IPã表示ããã¾ãã
åä½ç¢ºèª
http://instance_ip:8080
ã«ãã©ã¦ã¶ã§ã¢ã¯ã»ã¹ããã¨ãã®ãããªç»é¢ã«ãªãã¾ãã
ãç¡éã«ã¼ããã®ãªã³ã¯ãæ¼ããç¡éã«ã¼ããçºçããã¾ãããã
CPU使ç¨çã80%ãè¶ ãããã¨ã確èªãã
GitHub Issueã確èªããã¨ãã¢ã©ã¼ããéç¥ããã¦ãã¾ãã
以ä¸ãGoogle Cloud monitoringã®ã¢ã©ã¼ããGitHub Issueã«éç¥ããæµãã¨ãªãã¾ãã