Google Cloud Platform - бессерверные контейнеры

Опубликовано: 2 Марта, 2022

Разработчики любят бессерверные. Они предпочитают сосредоточиться на коде, развертывании и позволить платформе позаботиться обо всем остальном. Cloud Run позволяет запускать любой контейнер без сохранения состояния без сервера. С Cloud Run вы можете забыть об инфраструктуре. Он ориентирован на быстрое автоматическое масштабирование с учетом запросов, поэтому вы можете масштабировать его до нуля и платить только тогда, когда оно используется.

Чтобы объяснить эту концепцию, давайте рассмотрим пример. Здесь мы собираемся развернуть бессерверный микросервис, который преобразует документы Word в файлы PDF. Для выполнения этого преобразования нам понадобится OpenOffice . Мы собираемся просто добавить OpenOffice в наш контейнер, а затем запустить его в бессерверной среде.

Давайте начнем с этого. На консоли перейдите в Cloud Run и откройте страницу развертывания.

Выберите или вставьте URL-адрес изображения контейнера и нажмите « Создать» .

Это все, что нам нужно для создания бессерверного контейнера. Нет инфраструктуры, которую нужно подготовить заранее, нет файла YAML и нет серверов.

Cloud Run импортировал наш образ, убедитесь, что он запущен и собрал стабильную и безопасную конечную точку HTTPS.

Мы только что развернули масштабируемый микросервис, который преобразует документ в PDF. Давайте посмотрим, как это работает, предоставив ему документ для преобразования, загрузив его в работающий микросервис.

OpenOffice - это не совсем современная программа. Речь идет о двоичном файле 15-летней давности, размером около 200 мегабайт. И мы просто взяли этот двоичный файл и развернули его как бессерверную рабочую нагрузку с Cloud Run, потому что Cloud Run поддерживает контейнеры Docker. Это означает, что вы можете запускать любой язык программирования или любое программное обеспечение без сервера.

Посмотрим на код. У нас есть небольшой фрагмент кода Python, который прослушивает входящие HTTP-запросы и вызывает OpenOffice для преобразования нашего документа.

Python3

# python program to convert
# docs into pdf
  
import os
import shutil
import requests
import tempfile
  
from gevent.pywsgi import WSGIServer
from flask import Flask, after_this_request, render_template, request, send_file
from subprocess import call
  
UPLOAD_FOLDER = "/tmp"
ALLOWED_EXTENSIONS = set(["doc", "docx", "xls", "xlsx"])
  
app = Flask(__name__)
  
  
# Convert using Libre Office
def convert_file(output_dir, input_file):
    call("libreoffice --headless --convert-to pdf --outdir %s %s " %
         (output_dir, input_file), shell=True)
  
  
def allowed_file(filename):
    return "." in filename and
           filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS
  
  
@app.route("/", methods=["GET", "POST"])
def api():
    work_dir = tempfile.TemporaryDirectory()
    file_name = "document"
    input_file_path = os.path.join(work_dir.name, file_name)
    # Libreoffice is creating files with the same name but .pdf extension
    output_file_path = os.path.join(work_dir.name, file_name + ".pdf")
  
    if request.method == "POST":
        # check if the post request has the file part
        if "file" not in request.files:
            return "No file provided"
        file = request.files["file"]
        if file.filename == "":
            return "No file provided"
        if file and allowed_file(file.filename):
            file.save(input_file_path)
  
    if request.method == "GET":
        url = request.args.get("url", type=str)
        if not url:
            return render_template("index.html")
        # Download from URL
        response = requests.get(url, stream=True)
        with open(input_file_path, "wb") as file:
            shutil.copyfileobj(response.raw, file)
        del response
  
    convert_file(work_dir.name, input_file_path)
  
    @after_this_request
    def cleanup(response):
        work_dir.cleanup()
        return response
   
    return send_file(output_file_path, mimetype="application/pdf")
  
  
if __name__ == "__main__":
    http_server = WSGIServer(("", int(os.environ.get("PORT", 8080))), app)
    http_server.serve_forever()

А еще у нас есть очень маленький файл Docker . Он начинается с определения нашего базового изображения.

 ОТ питона: 3-альпийский
ENV APP_HOME / app
WORKDIR $ APP_HOME
ЗАПУСТИТЬ apk добавить libreoffice 
    строить базу  
    # Установить шрифты
    msttcorefonts-установщик fontconfig && 
    обновление-мс-шрифты && 
    fc-cache -f
ЗАПУСК apk add --no-cache build-base libffi libffi-dev && pip install cffi
RUN pip install Flask запрашивает gevent
КОПИРОВАТЬ. $ APP_HOME
# запретить libreoffice запрашивать :: 1 (ipv6 :: 1 отклоняется до istio 1.1)
ЗАПУСТИТЬ mkdir -p / etc / cups && echo "ServerName 127.0.0.1"> /etc/cups/client.conf
CMD ["питон", "to-pdf.py"]

В нашем случае это официальный образ на Python. Позже мы установили OpenOffice и указали нашу команду запуска. Затем мы упаковали все это в образ контейнера с помощью Cloud Build и развернули его в Cloud Run. В Cloud Run наш микросервис можно автоматически масштабировать до тысяч контейнеров или экземпляров всего за несколько секунд. Мы просто взяли устаревшее приложение и развернули его в среде микросервисов без каких-либо изменений в коде.

Но иногда вам может потребоваться немного больше контроля. Например, больший размер ЦП, доступ к графическим процессорам, больший объем памяти или, возможно, его работа в кластере Kubernetes Engine. В Cloud Run на GKE используется точно такой же интерфейс. Мы собираемся развернуть точно такой же образ контейнера, на этот раз в GKE.

И вместо полностью управляемого региона мы теперь выбираем наш кластер GKE. Мы получаем тот же опыт разработчика Cloud Run, что и раньше. Мы получаем стабильную и безопасную конечную точку, которая автоматически масштабирует наш микросервис.

За кулисами Cloud Run и Cloud Run на GKE работают на Knative, проекте с открытым исходным кодом для выполнения бессерверных рабочих нагрузок, который был запущен в прошлом году. Это означает, что мы можем фактически развернуть один и тот же микросервис в любом кластере Kubernetes, работающем на Knative. Давайте взглянем.

Мы экспортировали микросервис в файл service.yaml . Затем, используя приведенную ниже команду, мы развернем его на управляемом Knative у другого облачного провайдера.

 kubectl apply - f service.yaml

Мы введем приведенную ниже команду, чтобы получить конечную точку URL.

 kubectl получить ksvc

Теперь о другом облачном провайдере. Давайте посмотрим на запущенную службу, введя следующую команду:

 Службы запуска бета-версии gcloud описывают службу PDF

Если вы знакомы с Kubernetes, эти версии и поля API могут показаться вам знакомыми.

В этом случае мы не используем Kubernetes. Но поскольку Cloud Run реализует Knative API, расширение Kubernetes, это объект API, который выглядит как Kubernetes. Knative позволяет переносить службы между средами без привязки к поставщику. Cloud Run дает вам все, что вам нравится в бессерверном режиме. Нет серверов, которыми нужно управлять, вы можете оставаться в коде, и есть быстрое масштабирование и, что более важно, масштабирование до нуля. Вы ничего не платите, если нет циклов. Используйте любой двоичный файл или язык, потому что это зависит от гибкости контейнеров. И это дает вам доступ к экосистеме Google Cloud и API. И вы получите единообразную работу в любом месте - в полностью управляемой среде или в GKE.