কম্পিউটার টিউটোরিয়াল

GCE, Cloud Storage, এবং Pub/Sub ব্যবহার করে Ruby-তে একটি विश्वস্ত আপটাইম মনিটরিং সিস্টেম বিল্ড করুন

আপটাইম মনিটরিং জড়িত ওয়েবসাইট, API, এবং সার্ভারের উপলব্ধতা যাচাই করা। মনিটর একটি নির্দিষ্ট अन्तরালে একটি প্রদত্ত এন্ডপয়েন্ট প্রোব করে এটি উপলব্ধ কিনা নির্ধারণ করতে। লক্ষ্য হলো কন্ট্রাক্ট করা উপলব্ধতার লেভেল অর্জন করা, যেমন সিস্টেমের SLA-তে নির্দিষ্ট, এবং পার্থক্য নির্ধারণ করা যখন কন্ট্রাক্ট মেট হয় না।

এই আর্টিকেলে, আমরা Prometheus blackbox_exporter বেজড একটি আপটাইম মনিটরিং সিস্টেম বিল্ড করব। কাস্টম HTTP মনিটরিং সিস্টেম বিল্ড করা তुच্ছ হলেও, এক্সপোর্টারের চারপাশে একটি র‍্যাপার বিল্ড করা আমাদের অন্য অনেক প্রোব টেকনিক এক্সেস করতে এবং আমাদের সিস্টেমের অন্যান্য এলিমেন্ট দ্রুত মনিটর করতে সক্ষম করে।

এই আর্টিকেলে বেশ কিছু টেকনোলজি ব্যবহৃত হয়েছে, এবং আমি প্রতিটি কম্পোনেন্ট বর্ণনা করব আপটাইম সিস্টেমের ডিটেইলসে যাওয়ার আগে।

Google Compute Engine (GCE) কী?

Compute Engine হলো Google-এর ক্লাউড কম্পিউটিং সার্ভিস AWS-এর EC2 কম্পিউট অফারিং-এর সমান। GCE সিকিউর এবং কাস্টমাইজেবল যথেষ্ট যাতে বিভিন্ন ওয়ার্কলোড ফিট করে ছোট মেশিন (৩২ vCPUs এবং ১২৮ GB মেমরি সাপোর্ট করে) থেকে স্ট্যান্ডার্ড মেশিন (২২৪ vCPUs এবং ৮৯৬ GB মেমরি সাপোর্ট করে) এবং ইন্টেনসিভ ওয়ার্কলোডের জন্য অন্যান্য হাই-এন্ড মেশিন। এটি কম্পিউট অন-ডিমান্ড ব্যবহার করে আপনার প্রয়োজন অনুযায়ী স্কেল করতে।

GCE অ্যাপ ডেপ্লয়মেন্টের জন্য বিভিন্ন ডেপ্লয়মেন্ট মেকানিজম সাপোর্ট করে, কন্টেইনার, ইনস্ট্যান্স টেমপ্লেট, এবং ম্যানেজড ইনস্ট্যান্স গ্রুপস সহ। এই আর্টিকেলের উদ্দেশ্যে, আমরা আমাদের Ruby আপটাইম মনিটরকে একটি ডকার কন্টেইনারে বান্ডেল করব ডেপ্লয়মেন্টের জন্য।

Cloud Storage কী?

Google Cloud Storage হলো একটি হাইলি অবেলেবল অবজেক্ট-স্টোরেজ সার্ভিস AWS-এর S3 সার্ভিসের সমান। Cloud Storage অনেক স্টোরেজ ফিচার প্রদান করে যা আধুনিক অ্যাপসের জন্য বেশ কিছু ইউজ-কেস সক্ষম করে। Ruby-তে Cloud Storage-এ শুরু করতে, আমরা google-cloud-storage জেম ব্যবহার করব অথেনটিকেট, আপলোড, এবং ডাউনলোড ফাইলস করার জন্য Cloud Storage- থেকে:

require 'google/cloud/storage'
def upload_file bucket_name:, file_path:, file_name: nil
  storage = Google::Cloud::Storage.new
  bucket = storage.bucket bucket_name
  file = bucket.create_file file_path, file_name
end

def download_file bucket_name:, file_path:, file_name: nil
  storage = Google::Cloud::Storage.new
  bucket = storage.bucket bucket_name
  file = bucket.file file_name
  file.download file_path
end

নোট: আপনাকে আপনার এনভায়রনমেন্টে GOOGLE_APPLICATION_CREDENTIALS সেট আপ করতে হবে যাতে সেটি সঠিক সার্ভিস একাউন্ট কী-এ পয়েন্ট করে। সব Google ক্লায়েন্ট জেম এই এনভায়রনমেন্ট ভেরিয়েবল সার্চ করে অথোরাইজেশনের জন্য; অন্যথায়, আপনাকে অথ স্পেসিফিক প্যারামিটার পাস করতে হবে Google::Cloud::Storage.new-এ। যদি আপনার অ্যাপ একটি GCE VM-এ রান করে, তবে, এটি ইতিমধ্যে এনভায়রনমেন্টে সেট আপড আছে।

Cloud PubSub কী?

Cloud PubSub হলো Google Cloud দ্বারা প্রদত্ত একটি পাবলিশ/সাবস্ক্রাইব মেসেজিং সার্ভিস। কমিউনিকেশনের এই ফর্মটি অ্যাসিনক্রোনাস সার্ভিস-টু-সার্ভিস কমিউনিকেশন ফ্যাসিলিটেট করতে ব্যবহৃত হয়, AWS-এর SNS-এর সমান। অ্যাসিনক্রোনাস কমিউনিকেশন সহ সিস্টেম বিল্ড করা আমাদের সিস্টেমের পারফরম্যান্স, স্কেলেবিলিটি, এবং রিলায়াবিলিটি উন্নত করতে সাহায্য করতে পারে। Ruby-তে Cloud PubSub-এ শুরু করতে, আমরা google-cloud-pubsub জেম ব্যবহার করব অথেনটিকেট, পাবলিশ, এবং ইভেন্টে লিসেন করতে:

require 'google/cloud/pubsub'
def publish_message topic_id:, message: nil
  pubsub = Google::Cloud::Pubsub.new
  topic = pubsub.topic topic_id
  topic.publish_async message do |result|
    raise "Failed to publish message" unless result.succeeded?
    puts "Message published asynchronously"
  end
  topic.async_publisher.stop.wait!
rescue StandardError => e
  puts "Received error while publishing: #{e.message}"
end

def receive_message subscription_id: nil, wait_time: 200.seconds
  pubsub = Google::Cloud::Pubsub.new
  subscription = pubsub.subscription subscription_id
  subscriber = subscription.listen do |received_message|
    puts "Received message: #{received_message.data}"
    received_message.acknowledge!
  end
  subscriber.start
  sleep wait_time
end

নোট: Cloud Storage-র জন্য বর্ণিত অথেনটিকেশন এখানেও প্রযোজ্য।

Cloud Storage এবং PubSub লিভারেজ করলে, আমরা খুব আকর্ষণীয় সমাধান বিল্ড করতে পারি। প্রায়শই, আমরা একটি অবজেক্ট আপলোড করতে চাই এবং এর আপডেট ট্র্যাক করতে - এর লাইফ-সাইকেল - ক্রিয়েট, আপডেট, ডিলিট, এবং নির্দিষ্ট ইভেন্টের বেজে স্পেসifik অ্যাকশন নেওয়া। যদি এটি এখনো অবস্ট্রাক্ট लगे, আসুন দুটি ইউজ-কেস এক্সপ্লোর করি:

  • Image Service: একটি ইমেজ সার্ভিস বিল্ড করা। ধরুন আমরা Cloudinary-এর মত কিছু তৈরি করতে চাই যা ইমেজ এবং ভিডিও স্টোরেজ প্রদান করে, সেইসাথে এই ডেটার ওপর ট্রান্সফরমেশন পারফর্ম করে। Cloud Storage ডেটা স্টোর এবং ভার্সন করতে সাহায্য করলেও, PubSub-এ আমরা একটি বাকেট থেকে ইভেন্টের জন্য লিসেন করতে পারি এবং ডেটার ওপর নির্দিষ্ট টাইপের প্রি-প্রসেসিং পারফর্ম করতে পারি, এমনকি কাস্টমার একটি প্রি-প্রসেসড ভার্সন রিকোয়েস্ট করার আগে।
  • Distribute Configuration Files: ইনফ্রাস্ট্রাকচার ইঞ্জিনিয়ারিং-এ একটি সাধারণ সমস্যা হলো কনফিগারেশন ফাইল রোল আউট করা кільটি সার্ভারে এবং সহজ রোলব্যাক প্রদান করা। ধরুন আমরা একটি সেন্ট্রাল সার্ভার চাই যা সার্ভার কনফিগারেশনের জন্য দায়বদ্ধ, এবং আমরা একবার কনফিগারেশন আপডেট করতে চাই এবং কনফিগারেশন ডিস্ট্রিবিউট করতে চাই আমাদের সার্ভার ফ्लीটে। Cloud Storage এবং Cloud PubSub ব্যবহার করে, আমরা আমাদের সার্ভারগুলোর ওপর এজেন্ট বিল্ড করতে পারি যা PubSub-এ লিসেন করে অবজেক্ট নোটিফিকেশন পেতে এবং এই ইভেন্টের বেজে অ্যাকশন নেওয়া। আরও, যদি এটি একটি ব্যাড চেঞ্জ হয় (ভুল কনফিগারেশন চেঞ্জ ডাউনটাইমের একটি সাধারণ কারণ 😩), আমরা অবজেক্ট ভার্সনিং দিয়ে একটি রোলব্যাক পারফর্ম করতে পারি।

এই আর্টিকেলে, আমরা Blackbox Exporter-এর জন্য একটি Ruby র‍্যাপার বিল্ড করব উপরের বর্ণিত দ্বিতীয় ইউজ-কেস ব্যবহার করে। র‍্যাপারটি এক্সপোর্টারটি একটি প্রসেসে রান করবে এবং অন্য একটি প্রসেস চালাবে GCP-এ একটি বাকেট থেকে কনফিগারেশন চেঞ্জের জন্য واয়াচ করতে, এবং তারপর লাইভ রিলোড করবে এক্সপোর্টার। আপনি প্রস্তুত? আসুন মজা করি!

Blackbox Exporter কী?

Blackbox Exporter হলো Prometheus টিম দ্বারা বিল্ট একটি ওপেন-সোর্স টুল যা এন্ডপয়েন্ট প্রোব করে HTTP, HTTPS, DNS, TCP, এবং ICMP ওভার। এক্সপোর্টারটি একটি Grafana এবং Prometheus ডেপ্লয়মেন্টের পাশে ডেপ্লয় করা উচিত। কমপ্লিট সেটআপ এরকম দেখে:

GCE, Cloud Storage, এবং Pub/Sub ব্যবহার করে Ruby-তে একটি विश्वস্ত আপটাইম মনিটরিং সিস্টেম বিল্ড করুন

Blackbox wrapper কনফিগার করা সব এন্ডপয়েন্ট প্রোব করে, এবং Prometheus এক্সপোর্টারটি স্ক্রেপ করে অন্য যেকোনো টার্গেটের মত। তারপর, Grafana Prometheus থেকে ডেটা রিট্রিভ করে গ্রাফ করার জন্য। আমরা এক্সপোর্টার বাইনারি রান করি যেন blackbox_exporter --config.file blackbox.yml। Blackbox Exporter আমাদের লাইভ রিলোড করার অনুমতিও দেয় এক্সপোর্টারকে একটি নতুন কনফিগারেশনসহ বাইনারি শাট ডাউন এবং রিস্টার্ট ছাড়া। এটি খুব উপকারী হতে পারে সেকেন্ডসে মাপা ইন্টারভাল সহ এন্ডপয়েন্ট স্ক্রেপ করার সময়।

BlackboxWrapper সার্ভিস স্পেকস

কোডে গভীরে যাওয়ার আগে, সার্ভিস স্পেকস হাইলাইট করি:

  • BlackboxWrapper সার্ভিস দুটি প্রসেস রান করবে।
    • প্রথম প্রসেস blackbox_exporter বাইনারি রান করবে।
    • দ্বিতীয় প্রসেস GCP-র বাকেট চেঞ্জের জন্য লিসেন করবে এবং প্রথম প্রসেস রিস্টার্ট করবে।
  • সার্ভিসটি একটি ডকার ইমেজ হিসেবে ডেপ্লয় হবে, যা আমাদের সক্ষম করবে সার্ভিসকে blackbox_exporter বাইনারির সাথে প্যাকেজ করতে।

GCE, Cloud Storage, এবং Pub/Sub ব্যবহার করে Ruby-তে একটি विश्वস্ত আপটাইম মনিটরিং সিস্টেম বিল্ড করুন

চলুন বিল্ড শুরু করি

প্রথম, একটি অ্যাপ ডিরেক্টরি তৈরি করুন এবং তারপর ডিরেক্টরিতে প্রবেশ করুন।

mkdir blackbox-wrapper && cd blackbox-wrapper

আমাদের স্ট্যান্ডার্ড Ruby অ্যাপ্লিকেশনের মত, আমরা bundler ব্যবহার করব আমাদের র‍্যাপারের ডিপেন্ডেন্সি ম্যানেজ করতে। একটি Gemfile তৈরি করুন:

source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
ruby '2.7.2'
gem 'google-cloud-storage'
gem 'google-cloud-pubsub'
gem 'rake'
gem 'pry'

তারপর bundle install রান করুন।

এখন আমরা একটি ফাইল তৈরি করব আমাদের কোড ধারণ করার জন্য: app.rb।

এই ফাইলটি আমাদের সার্ভিসের এন্ট্রি পয়েন্ট হিসেবে কাজ করবে। যেহেতু আমরা আমাদের অ্যাপটি একটি কন্টেইনারে ডেপ্লয় করব, এই ফাইলটি Dockerfile-এ CMD কমান্ডে স্পেসিফাই করা হবে পরে।

touch app.rb

Dockerfile তৈরি করা

যদিও এই ফাইল থেকে কিছু আইটেম উদ্দেশ্যপূর্বক ওমিট করা হয়েছে। নিচের কোডটি এই আর্টিকেলের জন্য ক্রিটিক্যাল কম্পোনেন্টগুলো হাইলাইট করে:

FROM ruby:2.7.2
RUN mkdir /app
WORKDIR /app
COPY . .
# Install other dependencies ...
# Download & Install blackbox exporter
RUN curl -SL \
  https://github.com/prometheus/blackbox_exporter/releases/download/v0.18.0/blackbox_exporter-0.18.0.linux-386.tar.gz | \
  tar xvz -C /tmp && \
  mv /tmp/blackbox_exporter-0.18.0.linux-386/blackbox_exporter /usr/local/bin && \
  mkdir /etc/blackbox && \
  mv /tmp/blackbox_exporter-0.18.0.linux-386/blackbox.yml /etc/blackbox/
# Specify entry point.
CMD ["bundle", "exec", "ruby", "app.rb" ]

উপর থেকে, আমাদের নিচের বিষয়গুলো নোট করা উচিত:

  • আমরা একটি Ruby ইমেজ - ruby:2.7.2 - বেস ইমেজ হিসেবে ব্যবহার করেছি Ruby ইনস্টলডসহ।
  • আমরা blackbox_exporter বাইনারি ইনস্টল করেছি এবং এটি একটি ডিরেক্টরিতে মুভ করেছি যা আমাদের PATH-এ থেকে অ্যাক্সেসযোগ্য।
  • আমরা কন্টেইনারের এন্ট্রিপয়েন্ট স্পেসিফাই করেছি app.rb রান করার জন্য কন্টেইনার স্টার্ট আপে।

র‍্যাপার সার্ভিস বিল্ড করা

এটি আমাদের Ruby সার্ভিস যা সব কিছু একসাথে যুগ্ল করে। main.rb-এ, নিচের কন্টেন্ট রাখুন:

require 'rubygems'
require 'bundler/setup'
require "google/cloud/pubsub"
require "google/cloud/storage"

CONFIG_BUCKET = ENV['BUCKET_NAME']
TOPIC = ENV['PUBSUB_TOPIC']
TOPIC_SUBSCRIPTION = ENV['TOPIC_SUBSCRIPTION']

class ProcessNotification
  def initialize(file, attr, blackbox_exporter)
    @file = file
    @attr = attr
    @blackbox_exporter = blackbox_exporter
  end

  def call
    return if @attr['eventType'] == 'OBJECT_DELETE'
    @blackbox_exporter.write @file
    @blackbox_exporter.reload
  end
end

class BlackBoxExporter
  CONFIG_FILE = '/etc/blackbox/blackbox.yml'

  def initialize
    @blackbox_pid = nil
  end

  def start
    return unless @blackbox_pid.nil?
    @blackbox_pid = fork do
      exec('blackbox_exporter', '--config.file', CONFIG_FILE)
    end
  end

  def write(file)
    file.download CONFIG_FILE
  end

  def reload
    # Send SIGHUP signal
    Process.kill('HUP', @blackbox_pid)
  end

  def shutdown
    Process.kill('KILL', @blackbox_pid)
  end
end

class Subscriber
  class NotificationConfigError < StandardError
  end

  SUPPORTED_FILE_TYPES = ['blackbox.yml']

  def initialize(blackbox_exporter)
    @pubsub = Google::Cloud::Pubsub.new
    @storage = Google::Cloud::Storage.new
    @subscription_name = ENV['TOPIC_SUBSCRIPTION']
    # Retrieve a subscription
    @bucket = @storage.bucket CONFIG_BUCKET
    @subscription = @pubsub.subscription @subscription_name
    @blackbox_exporter = blackbox_exporter
  end

  def listen
    create_notification_config
    puts "Starting subscriber"
    @subscriber = @subscription.listen do |received_message|
      process_notification(received_message)
    end
    @subscriber.on_error do |exception|
      process_exception(exception)
    end
    @subscriber.start
  end

  def process_notification(received_message)
    data = received_message.message.data
    published_at = received_message.message.published_at
    attributes = received_message.message.attributes
    puts "Data: #{data}, published at #{published_at}, Attr: #{attributes}"
    received_message.acknowledge!
    parsed_data = JSON.parse(data)
    file_name = parsed_data['name']
    return unless SUPPORTED_FILE_TYPES.include?(file_name)
    file = @bucket.file file_name
    process_notification = ProcessNotification.new(file, attributes, @blackbox_exporter)
    process_notification.call
  end

  def process_exception(exception)
    puts "Exception: #{exception.class} #{exception.message}"
  end

  def shutdown
    @subscriber.stop!(10)
  end

  def create_notification_config
    topic = @pubsub.topic TOPIC
    notification_exists = @bucket.notifications.count == 1
    unless notification_exists
      @bucket.notifications.each do |notification|
        notification.delete
      end
    end
    @bucket.create_notification topic.name
  rescue StandardError => e
    raise NotificationConfigError, e.message
  end
end

class BlackboxWrapper
  def initialize
    @blackbox_exporter = BlackBoxExporter.new
    @subscriber = Subscriber.new(@blackbox_exporter)
  end

  def start
    @blackbox_exporter.start
    @subscriber.listen
    at_exit do
      @blackbox_exporter.shutdown
      @subscriber.shutdown
    end
    # Block, letting processing threads continue in the background
    sleep
  end
end

blackbox_wrapper = BlackboxWrapper.new
blackbox_wrapper.start

যদিও উপরের কোডটি অনেক, আসুন এটিকে ব্রেক ডাউন করার চেষ্টা করি নিচ থেকে শুরু করে:

  • BlackboxWrapper: এই ক্লাসটি আমাদের সার্ভিসের এন্ট্রিপয়েন্ট। - .start মেথডটি নিচের কাজগুলো করে:
    • blackbox_exporter বাইনারি একটি ভিন্ন প্রসেসে শুরু করে এন্ডপয়েন্ট প্রোব করতে।
    • subscriber একটি অন্য প্রসেসে শুরু করে বাকেট চেঞ্জের জন্য লিসেন করতে।
    • তারপর এটি মেইন প্রসেসে sleep কল করে যাতে অ্যাপ ইনফিনিটলি চলে।
  • BlackboxExporter কীভাবে কাজ করে?
    • .start মেথডটি exec কার্নেল মেথড ব্যবহার করে blackbox_exporter বাইনারি একটি অন্য প্রসেসে রান করে।
    • .reload মেথডটি SIGHUP সিগন্যাল পাঠায় লাইভ রিলোড করতে blackbox_exporter বাইনারিকে নতুন কনফিগারেশনসহ। যেমন আপনি ProcessNotification ক্লাস থেকে নোট করেছেন, একটি নতুন কনফিগারেশন ফাইল কনফিগারেশন ফাইল লোকেশনে লিখা হয় এক্সপোর্টার রিলোড করার আগে।
  • Subscriber কীভাবে কাজ করে?
    • .listen মেথডটি একটি NotificationConfiguration তৈরি করার সাথে শুরু হয়। একটি NotificationConfiguration হলো একটি রুল যা তিনটি জিনিস স্পেসিফাই করে:
      • Pub/Sub-এ একটি টপিক নোটিফিকেশন রিসিভ করতে।
      • ইভেন্ট যেটি নোটিফিকেশন পাঠাতে ট্রিগার করে। এখানে ক্লিক করে বিভিন্ন ইভেন্ট টাইপ দেখুন যেগুলো নোটিফিকেশন ট্রিগার করতে পারে।
      • নোটিফিকেশনের ভিতরে থাকা ইনফরমেশন।
    • #create_notification_config মেথডটি নিশ্চিত করে যে শুধু একটি NotificationConfiguration আছে; অন্যথায়, এটি সব ডিলিট করে এবং একটি তৈরি করে। এটি নিশ্চিত করে যে নোটিফিকেশন শুধু একবার পাঠানো হয়।
    • .listen মেথডটি @subscription.listen কল করে বাকেটে নোটিফিকেশন চেঞ্জের জন্য লিসেন শুরু করতে যেটি আমরা সাবস্ক্রাইবড আছি। নোট করুন যে এটি অন্য একটি প্রসেসে ইনফিনিটলি রান করে, যেমন ব্যাখ্যা করা হয়েছে।
    • #process_notification মেথডটি প্রতিটি নোটিফিকেশন আপডেট পাঠানো হলে কল হয়। নোট করুন যে আমাদের SUPPORTED_FILE_TYPES আছে, যা আমরা ব্যবহার করি বাকেটে আমাদের যত ফাইল আছে সেগুলো আইডেন্টিফাই করতে এবং বাকিগুলোর জন্য কিছুই করব না।
  • ProcessNotification: এটি নোটিফিকেশন প্রসেস করার জন্য দায়বদ্ধ, আপডেট করা কনফিগারেশন ডাউনলোড করা, এটি একটি ফাইলে লেখা, এবং blackbox_exporter বাইনারি রিলোড করা।

সার্ভিসটি লোকালি রান করা

সার্ভিসটি লোকালি রান এবং টেস্ট করতে, অ্যাপ ডিরেক্টরির রুটে নিচের কমান্ডগুলো রান করুন:

export BUCKET_NAME='{insert-bucket-name}'
export PUBSUB_TOPIC='{insert-pubsub-topic}'
export TOPIC_SUBSCRIPTION='{insert-subscription-name}'
export GOOGLE_APPLICATION_CREDENTIALS='{insert-path-to-service-key-json}'
bundle exec ruby app.rb

আমাদের সার্ভিস Google Compute Engine-এ ডেপ্লয় করা

ক্লাউডের অনেক দিকের মত, একই রেজাল্ট অর্জন করার অনেক উপায় আছে, কিন্তু মডার্ন সফ্টওয়্যার ইঞ্জিনিয়ারিং বেশ কিছু ভালো কারণের জন্য CI/CD প্রসেস এনকourage করে। তাই, আমরা ফোকাস করব GitHub Actions ব্যবহার করে setup-gcloud দিয়ে আমাদের সার্ভিস GitHub থেকে ডেপ্লয় করার ওপর।

আমাদের ডেপ্লয়মেন্ট ফাইল সেট আপ করি (.github/workflows/deploy.yml)।

name: Build and Deploy to Google Compute Engine
on:
  push:
    branches:
      - main
env:
  PROJECT_ID: ${{ secrets.GCE_PROJECT }}
  GCE_INSTANCE: ${{ secrets.GCE_INSTANCE }}
  GCE_INSTANCE_ZONE: us-central1-a
  BUCKET_NAME: demo-configurations
  PUBSUB_TOPIC: demo-configurations-bucket-notifications
  TOPIC_SUBSCRIPTION: demo-bucket-changes-subscription
jobs:
  setup-build-publish-deploy:
    name: Setup, Build, Publish, and Deploy
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      # Setup gcloud CLI
      - uses: google-github-actions/setup-gcloud@master
        with:
          version: '290.0.1'
          service_account_key: ${{ secrets.GCE_SA_KEY }}
          project_id: ${{ secrets.GCE_PROJECT }}
      # Configure Docker to use the gcloud command-line tool as a credential
      # helper for authentication
      - run: |- 
          gcloud --quiet auth configure-docker
      # Build the Docker image
      - name: Build
        run: |- 
          docker build --tag "gcr.io/$PROJECT_ID/$GCE_INSTANCE-image:$GITHUB_SHA" .
      # Push the Docker image to Google Container Registry
      - name: Publish
        run: |- 
          docker push "gcr.io/$PROJECT_ID/$GCE_INSTANCE-image:$GITHUB_SHA"
      - name: Deploy
        run: |- 
          gcloud compute instances update-container "$GCE_INSTANCE" \
            --zone "$GCE_INSTANCE_ZONE" \
            --container-image "gcr.io/$PROJECT_ID/$GCE_INSTANCE-image:$GITHUB_SHA" \
            --container-env "BUCKET_NAME=$BUCKET_NAME,PUBSUB_TOPIC=$PUBSUB_TOPIC,TOPIC_SUBSCRIPTION=$TOPIC_SUBSCRIPTION"

নোট করুন যে --container-env ফ্ল্যাগ ডেপ্লয় ফেজে সেট করা হয়েছে, যা নিশ্চিত করে যে আমরা GitHub Actions secrets থেকে প্রয়োজনীয় এনভায়রনমেন্ট ভেরিয়েবলস কন্টেইনারে সিকিউর ফ্যাশনে পাস করছি।

Secrets & এনভায়রনমেন্ট ভেরিয়েবলস

এরপর, আমরা GitHub Actions-এ সিক্রেটস সেট আপ করব।

GCE, Cloud Storage, এবং Pub/Sub ব্যবহার করে Ruby-তে একটি विश्वস্ত আপটাইম মনিটরিং সিস্টেম বিল্ড করুন

আমরা আমাদের কন্টেইনারের জন্য এনভায়রনমেন্ট ভেরিয়েবলস সেট করি --container-env ফ্ল্যাগ দিয়ে। যেহেতু আমরা এটি GitHub Actions থেকে সেট করছি, আমরা είথার সিক্রেটস ব্যবহার করতে পারি সেনসিটিভ ডেটার জন্য অথবা env ভেরিয়েবলস নন-সেনসিটিভ ডেটার জন্য।

GCP রিসোর্স তৈরি করা

GCP কনসোলে একটি বাকেট তৈরি করুন।

GCE, Cloud Storage, এবং Pub/Sub ব্যবহার করে Ruby-তে একটি विश्वস্ত আপটাইম মনিটরিং সিস্টেম বিল্ড করুন

আমরা GCP কনসোলে একটি PubSub টপিকও তৈরি করব।

GCE, Cloud Storage, এবং Pub/Sub ব্যবহার করে Ruby-তে একটি विश्वস্ত আপটাইম মনিটরিং সিস্টেম বিল্ড করুন

ক্লাউড স্টোরেজ বাকেটের সার্ভিস এজেন্ট সেট আপ করুন - IAM রোল - pubsub.publisher কনসোলে। প্রতিটি প্রজেক্টের একটি অ্যাসোসিয়েটেড Cloud Storage সার্ভিস একাউন্ট থাকে যা কিছু ব্যাকগ্রাউন্ড অ্যাকশনের জন্য দায়বদ্ধ, PubSub নোটিফিকেশনসহ। এখানে ক্লিক করুন কীভাবে খুঁজে বের করতে হয় শিখতে।

GCE, Cloud Storage, এবং Pub/Sub ব্যবহার করে Ruby-তে একটি विश्वস্ত আপটাইম মনিটরিং সিস্টেম বিল্ড করুন

শেষে, আমরা GCP কনসোলে একটি সাবস্ক্রিপশন তৈরি করব।

GCE, Cloud Storage, এবং Pub/Sub ব্যবহার করে Ruby-তে একটি विश्वস্ত আপটাইম মনিটরিং সিস্টেম বিল্ড করুন

Voila! 🎉 আমাদের ক্লাউড ফাংশন সফলভাবে ডেপ্লয় হয়েছে।

উপসংহার

আপনি যদি এতদুর আসেন, আপনি একটি কুকি ডিজার্ভ করেন 🍪। আমি মনে করি এটি একটি পটেনশিয়ালি গ্রেট সমাধানের ফার্স্ট ভার্সন যেখানে একাধিক অপ্টিমাইজেশন অর্জন করা যাবে। উদাহরণস্বরূপ, আমরা অর্জন করতে পারি:

  • Blackbox_exporter কে একটি সার্ভারলেস ফাংশন হিসেবে ডেপ্লয় করা একাধিক রিজন সাপোর্ট করার জন্য, যা আপটাইম মনিটরিং-এ আইডিয়াল, এবং একটি মাস্টার সার্ভার ডেপ্লয় করা যা বাকেট কনফিগারেশন আপডেট করবে Cloud Storage-এ।
  • পূর্বের পয়েন্ট থেকে, আমরা সম্ভবত এটি একটি অ্যাপে অ্যাবস্ট্রাক্ট করতে পারি যা পপুলার ক্লাউড প্রোভাইডারসের সাথে ইন্টিগ্রেট করে একই ফাংশনালিটি অর্জন করার জন্য, তাই এটি ক্লাউড-অগনস্টিক হবে। P.S: পপুলার ক্লাউড প্রোভাইডারস (GCP, AWS, & Azure) একই ফাংশনালিটি সার্ভিস জুড়ে প্রদান করে।
  • পরবর্তী আর্টিকেলে, আমরা এই সমাধানের ওপর বিল্ড করব রোলব্যাক প্রদান করার জন্য cloud-storage অবজেক্ট ভার্সনিং দিয়ে, যা আমাদের রিকভার করতে সক্ষম করবে ইনকরেক্ট আপডেটসহ কনফিগারেশন আপডেট করার পর থেকে।

  • Docker দিয়ে ডেপ্লয় করা শুধু প্যাকেজিং সমস্যাটি সমাধান করে আমাদের জন্য, কিন্তু আপনি যেন ইতিমধ্যে জানেন, সার্ভিস প্যাকেজ করার বিভিন্ন উপায় আছে। আমি এই আর্টিকেলে Docker বেছে নেওয়া সিম্পলিসিটির জন্য।

Glossary

  • Prometheus হলো একটি ওপেন-সোর্স সিস্টেম মনিটরিং এবং অ্যালার্টিং টুলকিট। এতে একটি সার্ভার থাকে যা স্ক্রেপ এবং স্টোর করে টাইম-সিরিজ ডেটা, অ্যাপ্লিকেশন কোড ইনস্ট্রুমেন্ট করার জন্য ক্লায়েন্ট লাইব্রেরি, এবং অ্যালার্ট হ্যান্ডল করার জন্য একটি অ্যালার্ট ম্যানেজার।
  • Grafana হলো একটি ভিজ্যুয়ালাইজেশন সিস্টেম যা আপনাকে কোয়েরি, ভিজ্যুয়ালাইজ, অ্যালার্ট, এবং আপনার মেট্রিক্স বুঝতে দেয়, যেগুলো যেকোনো জায়গা স্টোরড থাকে।
  • Blackbox Exporter হলো Prometheus টিম দ্বারা বিল্ট একটি ওপেন-সোর্স টুল যা এন্ডপয়েন্ট প্রোব করে HTTP, HTTPS, DNS, TCP, এবং ICMP ওভার।
  1. রুবি পার্সিং মास্টার: স্ক্র্যাচ থেকে নিজস্ব পার্সার বানান

  2. SwiftUI দিয়ে একটি রবাস্ট ডিজাইন সিস্টেম বানান: একটি পূর্ণ গাইড

  3. Cloud Tuneup Pro দিয়ে ইন্টারনেট কুকি এবং সিস্টেম রেজিস্ট্রি স্ক্যান করুন শীর্ষ পারফরম্যান্সের জন্য

  4. ক্লাউড স্টোরেজ: সিকিউর ডেটা স্টোরেজ ও ট্রান্সফারের জন্য পনivationওয়েরিং ইনোভেশন