본문 바로가기
CSP (Cloud Service Provider)/GCP

GKE Maintenance Alert to SLACK

by BTC_ryul 2023. 5. 12.

베하 ~~! 안녕하세요 엄..팀입니다. 

이번 포스팅 주제에서는 GKE Maintenance에 대한 이벤트를 Slack으로 알림을 보내는 구성을 실습합니다.

 

 

개요

GKE + Pub/Sub + Cloud Functions + (Cloud Build) 를 이용한 알림 설정 

  • GKE : Publisher
  • Slack Webhook : Subscriber

 

1. Create Slack Application

타사 서비스의 클러스터 알림 구성

Slack 알림을 설정하려면 Slack 애플리케이션을 만들고, 이 애플리케이션에 대한 수신 웹훅을 활성화한 다음 Slack 작업공간에 애플리케이션을 설치해야 합니다.

Slack 애플리케이션 만들기

  1. 이메일로 등록하거나 작업공간 관리자가 보낸 초대를 사용하여 Slack 작업공간에 가입합니다.
  2. 참고: Slack 작업공간 관리자가 아닌 경우 작업공간 관리자의 승인을 받아야 앱이 작업공간에 배포됩니다.
  3. 작업공간 이름과 Slack 계정 사용자 인증 정보를 사용하여 Slack에 로그인합니다.
  4. 새 Slack 앱을 만듭니다.
    1. Create an app(앱 만들기) 대화상자에서 From scratch(처음부터)를 클릭합니다.
    2. App Name(앱 이름)을 지정하고 Slack 작업공간을 선택합니다.
    3. Create App을 클릭합니다.
    4. Add features and functionality(특징 및 기능 추가)에서 Incoming Webhooks(수신 웹훅)를 클릭합니다.
    5. Activate Incoming Webhooks(수신 웹훅 활성화) 전환 버튼을 클릭합니다.
    6. Webhook URLs for Your Workspace(작업공간의 웹훅 URL) 섹션에서 Add New Webhook to Workspace(작업공간에 새 웹훅 추가)를 클릭합니다.
    7. 승인 페이지가 열리면 알림을 수신할 채널을 선택합니다.
    8. 허용을 클릭합니다.
    9. Slack 애플리케이션의 웹훅이 Webhook URLs for Your Workspace(작업공간의 웹훅 URL) 섹션에 표시됩니다. 나중을 위해 이 URL을 저장합니다.

2. 기존 클러스터에서 클러스터 알림 사용 설정

클러스터 알림 수신

SecurityBulletinEvent

GKE에서 클러스터 구성 또는 버전과 직접 연관되는 보안 게시판이 실행될 때 GKE는 SecurityBulletinEvent 알림을 전송하여, 취약점, 영향, 수행 가능한 조치에 대한 정보를 제공합니다.

UpgradeAvailableEvent

출시 채널에서 새 버전을 사용할 수 있게 되면 GKE는 해당 출시 채널의 클러스터에 UpgradeAvailableEvent 알림을 보내 새 버전을 사용할 수 있음을 클러스터에 알립니다.

UpgradeEvent

용자 또는 GKE가 업그레이드를 시작하면 GKE가 UpgradeEvent 알림을 전송하여 업그레이드가 시작되었음을 알립니다. 

# example
gcloud container clusters update CLUSTER_NAME \\
--region=COMPUTE_REGION \\
--notification-config=pubsub=ENABLED,pubsub-topic=projects/PROJECT_ID/topics/TOPIC_NAME,filter=NOTIFICATION_TYPE

# actually executed
gcloud container clusters update bespin-d-service-gke-service-ans3-001 \\
--region=asia-northeast3 \\
--notification-config=pubsub=ENABLED,pubsub-topic=projects/bespin-service/topics/bespin-d-service-pst-noti,filter=UpgradeAvailableEvent|UpgradeEvent|SecurityBulletinEvent

 

3. 코드 작성

타사 서비스의 클러스터 알림 구성

  • 소스 코드는 수정할 부분이 없습니다.
  • Cloud Functions 배포시에 전달하는 환경변수 값(slack webhook url)을 코드에서 읽기 때문입니다.

- 환경구성

mkdir ~/gke_slack && cd $_

- index.js

const { IncomingWebhook } = require('@slack/webhook');
const url = process.env.SLACK_WEBHOOK;

const webhook = new IncomingWebhook(url);

// Optionally filter what notification types to forward to Slack.
// If empty, all types will be allowed.
const allowedTypeURLs = [];

// slackNotifier is the main function called by Cloud Functions
module.exports.slackNotifier = (pubSubEvent, context) => {
  const data = decode(pubSubEvent.data);

  // Send message to Slack.
  if (isAllowedType(pubSubEvent.attributes)) {
    const message = createSlackMessage(data, pubSubEvent.attributes);
    webhook.send(message);
  }
};

// decode decodes a pubsub event message from base64.
const decode = (data) => {
  return Buffer.from(data, 'base64').toString();
}

// isAllowedType can be used to filter out messages that don't match the
// allowed type URLs. If allowedTypeURLs is empty, it allows all types.
const isAllowedType = (attributes) => {
  if (allowedTypeURLs.length == 0) {
    return true;
  }
  for (var x in allowedTypeURLs) {
    if (attributes['type_url'] == allowedTypeURLs[x]) {
      return true;
    }
  }
  return false;
}

// createSlackMessage creates a message from a data object.
const createSlackMessage = (data, attributes) => {
  // Write the message data and attributes.
  text = `${data}`
  for (var key in attributes) {
    if (attributes.hasOwnProperty(key)) {
      text = text + `\\n\\t\\`${key}: ${attributes[key]}\\``
    }
  }
  const message = {
    text: text,
    mrkdwn: true,
  };
  return message;
}

- Package.json

{
  "name": "gke-slack",
  "version": "0.0.1",
  "description": "Slack integration for GKE, using Cloud Functions",
  "main": "index.js",
  "dependencies": {
    "@slack/webhook": "5.0.1"
  }
}

 

4. Cloud Functions Deploy

gcloud functions deploy

- 해당 소스코드가 있는 위치에서 실행합니다 

# sample (nodejs10 will be deprecated)
gcloud functions deploy slackNotifier \\
  --trigger-topic=TOPIC_NAME \\
  --runtime=nodejs10 \\
  --set-env-vars="SLACK_WEBHOOK=WEBHOOK_URL"

# actually executed 
gcloud functions deploy bespin-d-service-func-noti-an3 \\
--trigger-topic=bespin-d-service-pst-noti \\
--runtime=nodejs10 \\
--set-env-vars="SLACK_WEBHOOK=https://hooks.slack.com/services/~~~" \\
--entry-point=slackNotifier \\
--region=asia-northeast3 \\
--project=bespin-service

 

5. Test

Topic에 메시지 게시

# example
gcloud pubsub topics publish TOPIC_ID \\
--message=MESSAGE_DATA \\
[--attribute=KEY="VALUE",...]

# actually executed
gcloud pubsub topics publish bespin-d-service-pst-noti \\
--message=test
--attribute=KEY=VALUE
--project bespin-service

 

6. 확인

 

 

TroubleShooting

Cloud Functions 문제 해결 - 잘못 지정된 진입점으로 인해 함수 배포 실패

—-entry-point 옵션으로 해당 소스 코드내의 함수 이름을 따로 설정하지 않으면, 배포 시 설정한 function이름(bespin-d-service-func-noti)으로 —entry-point 가 생성됩니다. bespin-d-service-func-noti라는 함수가 없기 때문에 아래와 같은 에러를 뱉습니다.

Deployment failure: Function failed on loading user code. Error message:
Error: please examine your function logs to see the error cause:
<https://cloud.google.com/functions/docs/monitoring/logging#viewing_logs>

 

 

References

https://cloud.google.com/kubernetes-engine/docs/concepts/cluster-notifications?hl=ko#filtering

https://cloud.google.com/kubernetes-engine/docs/tutorials/cluster-notifications-slack?hl=ko#deploying_the 

 

 

 

댓글