Рубрики
Uncategorized

От нуля до сервера

Введение в переход от низкоуровневых развертываний к использованию без серверных функций. Tagged с DevOps, Server, AWS, Lambda.

Впервые я был подвержен функциям Lambda на работе, когда команде необходимо было реализовать службу API, которая будет получать запросы от других услуг, разрабатывать данные, а затем отправляет эти данные в Kafka. Теперь эта услуга обрабатывает около 1 м запроса каждый месяц 🎉🎉

Я был очень смущен тем, с чего начать или как сделать это для работы в области разработки, тестирования и производственных сред. Я видел Без сервера Framework , Кнайт и Kubeless в Интернете и потребовалось много времени, чтобы решить, что выбрать, так как мы используем K8s в наших средах.

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

Структура каталога

Лучше абстрагировать каждую функцию в отдельном каталоге с его компонентами. Вы также увидите Dockerfile а также .docker каталог, который используется в среде разработки. Вы также увидите, что мы используем Jenkins в нашем конвейере CI/CD. Язык программирования, который мы использовали, это Nodejs . Мы поговорим о каждой настройке среды.

Код обработчика функции всегда внутри Handler.js . Мы создаем столько файлов внутри lib/ по мере необходимости. Соответствующие тесты для всего этого кода находятся под тесты/ .

Serverless.yml

Позвольте мне начать с того, что поделитесь нашими «простой» serverless.yml 😅, а затем я начну комментировать его и объясню, как мы используем этот файл для всех наших сред:

service: api-service
provider:
  name: aws
  runtime: nodejs12.x
  memorySize: 512
  stage: ${opt:stage, 'dev'}
  logRetentionInDays: ${self:custom.logRetention.${self:provider.stage}, self:custom.logRetention.other}
  vpc:
    subnetIds:
      - ${self:custom.subnetIds.${self:provider.stage}, self:custom.subnetIds.other}
    securityGroupIds:
      - ${self:custom.securityGroupIds.${self:provider.stage}, self:custom.securityGroupIds.other}
  deploymentBucket:
    name: api-service

Во -первых, вам придется указать имя службы, на которое вы хотите назвать Сервис. В части провайдера вам нужно будет назвать своего облачного провайдера, которого вы собираетесь использовать. Я AWS, как показано выше, но если вы используете GCP, это будет Google . Вы можете увидеть пример для GCP здесь . Затем время выполнения, которое будет использовать ваше приложение без сервера. Не забудьте установить версию, подобную той, которую вы используете в среде разработчика.

Одним из важных вариантов в блоке поставщика является добавление объем памяти ценность. Значение по умолчанию составляет 1024, но иногда ваша функция не будет использовать эту большую часть памяти, поэтому хорошо сэкономить немного денег здесь. Далее Стадия Вариант, вы можете установить его с помощью аргумента SLS во время развертывания или использовать значение для отступления, как указано выше, Dev в нашем случае.

Далее следует устанавливать политику удержания для вашей функции ( logretentionIndys ). Некоторые люди забывают использовать эту опцию, но это хороший способ избавиться от старых журналов и сэкономить деньги от уменьшения тонн журналов, хранящихся в CloudWatch. Мы устанавливаем другое значение в тестировании, кроме производства, поскольку нам нужно, чтобы производственные журналы были дольше. Значения здесь установлены значениями в пользовательском разделе. Мы устанавливаем значение в зависимости от этапа, на которую мы развертываем. Мы используем этот подход в большинстве наших областей. Хорошо написать общий Serverless.yml Файл, который может обрабатывать несколько этапов/сред. Так что, если вы используете Stage Prod, он получит значение от Custom.Logretention.Prod . Это пойдет и посмотрит, если у нас есть Custom.Logretention.prod уже определен. Если нет, это установит значение с Custom.Logretention.other который мы используем для всех средств тестирования.

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

Будьте осторожны, как только вы подключите свою функцию с VPC, функция больше не может получить доступ к Интернету, даже если вы выбираете публичную подсети с маршрутом к интернет -шлюзу для вашей функции (см. Для функций Lambda Чтобы узнать больше). Таким образом, вы не можете иметь и то, и другое: доступ к ресурсам в вашем VPC и через Интернет.

Чтобы получить доступ к вашему VPC, а также в Интернете, вам нужно раскрутить Nat Gateway. Или в некоторых случаях вы можете сойти с рук с конечной точкой VPC.

Последняя часть здесь, добавляет ваш DeploymentBucket . Важно поместить все ваши развертывания в одно ведро. У вас будет каждый этап, функционирование и развертывание в организованных каталогах с временными метками. Если вы собираетесь пропустить это, это создаст случайное ведро для каждого развертывания.

package:
  include:
    - functions/api-service/.env.defaults
    - functions/api-service/app.js
    - functions/api-service/handler.js
    - functions/api-service/lib/**
    - functions/api-service/node_modules/**

Пакет Опция используется для включения, а также исключить файлы и каталоги из ваших функций, а также может помочь вам в уменьшении размера вашего приложения, который будет загружаться каждое развертывание на S3.

functions:
  api-service:
    handler: functions/api-service/handler.api-service
    description: this function will receive data from multiple services
    environment:
      KAFKA_TOPIC: api.service
      KAFKA_BROKERS: ${self:custom.KAFKA_BROKERS.${self:provider.stage}, self:custom.KAFKA_BROKERS.other}
    events:
      - http:
          path: api-service
          method: post
          cors:
            origins:
              - https://*.example.com
            headers:
              - Content-Type
              - X-Amz-Date
              - Authorization
              - X-Api-Key
              - X-Amz-Security-Token
              - X-Amz-User-Agent
            allowCredentials: true

Самая интересная часть — определение ваших функций массива. В нашем случае мы используем только одну функцию, но вы можете добавить столько, сколько вам нужно в зависимости от трубопровода, над которым вы работаете, или вы как бы не ботаник и используете функции шага 🤓. Я рекомендую искать здесь Если вы заинтересованы в поиске с шагами функциями.

Назовите свою функцию и добавьте ее вместе с его Описание и обработчик Анкет Убедитесь, что вы пишете функцию правого обработчика, а не имя файла. Тогда вы можете использовать среда Возможность экспортировать некоторые переменные среды для использования во время работы вашей функции. Вы поймете, что мы используем один и тот же подход при обработке одной и той же переменной среды с несколькими этапами, такими как в $ {Self: Custom. Kafka_brokers. $ {Self: provider.stage}, self: custom. Kafka_brokers.other}

В События Раздел, это зависит от того, что запускает вашу функцию: API Gateway, WebSocket, Kinesis & DynamoDB, S3 и т. Д. Смотри Здесь Больше подробностей.

Мы используем шлюз API с HTTP Endpoint Rading только для просьбы POST на /api-service Анкет Вы также можете добавить некоторые конфигурации CORS в вашу функцию, как мы видим выше.

plugins:
  - serverless-domain-manager
  - serverless-offline

Хорошая вещь, которая обеспечивает вам плагины без сервера, это плагины. Мы используем Сервер без официального линии Для запуска нашей настройки локально в среде разработки и Без сервера-домен-менеджер плагин для обработки конфигурации шлюза API.

custom:
  customDomain:
    domainName: ${self:custom.subDomain.${self:provider.stage}, self:custom.subDomain.other}.${self:custom.domain.${self:provider.stage}, self:custom.domain.other}
    certificateName: "*.${self:custom.domain.${self:provider.stage}, self:custom.domain.other}"
    basePath: "${self:custom.basePath.${self:provider.stage}, self:custom.basePath.other}"
    stage: ${self:provider.stage}
    createRoute53Record: true
  domain:
    prod: example-prod.com
    other: example.com
  subDomain:
    prod: api-service
    other: api-service
  basePath:
    prod: 
    other: ${self:provider.stage}
  subnetIds:
    prod: subnet-xxxxxxx
    other: subnet-yyyyyyy
  securityGroupIds:
    prod: 'sg-xxxxxxx'
    other: 'sg-yyyyyyy'
  KAFKA_BROKERS:
    prod: kafka-prod.example.com
    other: kafka-${self:provider.stage}.example.com
  logRetention:
    prod: 14
    other: 7

В обычай Раздел, это как объявление переменных. Переменные позволяют динамически заменять значения конфигурации в Serverless.yml конфигурация Мы объявляем один для продлевать и Другое чтобы задержать, когда сцена не продлевает. Как когда мы использовали $ {self: custom.subnetids. $ {self: provider.stage}, self: custom.subnetids.other} Анкет

Customdomain Переменная используется здесь для определения конфигурации шлюза API. Итак, мы настраиваем доменное имя , Сертификат , Базепат Что очень полезно, если используемый вами сертификат не обрабатывает альтернативные доменные имена (CNAME). Здесь Для получения дополнительной информации и Стадия поле. Вы также можете установить Createroute53record с Верно Чтобы фреймворк создал для вас, Route53 Records для использования в других ваших внешних службах.

Настройка среды разработки

Для среды разработки я предпочел запустить функцию без сервера с помощью Docker, чтобы лучше справиться с зависимостями. Так вот как выглядят Dockerfile и The Entrypoint:

FROM node:12.15.0-stretch

COPY ./.docker/startup.sh /etc/
RUN chmod +x /etc/startup.sh
CMD /etc/startup.sh
#!/bin/bash

cd /var/www/app
npm install -g serverless
npm install
sls offline -o api-service

Вы выше вы увидите, насколько просто настройка в среде разработки. Мы просто запускаем SLS командовать с Сервер без официального линии плагин. Это позволит локальному шлюзу API работать на порту 3000 Внутри контейнера и запускает функцию, как только мы ее нажимаем.

Наши параметры хранятся в функции/API-Service/.env.Defaults Анкет Мы будем обрабатывать наши параметры по -другому в других средах.

Чтобы запустить эту настройку локально, вы можете использовать только команду Docker, либо вы также можете использовать Docker-Compose.

Команда Docker:

$ docker build -t api-service .
$ docker run --name api-service -d -p 80:3000 -v ${PWD}:/var/www/app api-service

докер-состав:

version: '3.7'
services:
  # api service
  api:
    build:
      context: .
    ports:
      - "80:3000"
    volumes:
      - .:/var/www/app
$ docker-compose up -d

Настройка тестирования и производственной среды

К счастью, потому что мы написали очень крутой и общий Serverless.yml файл. У нас не так много шагов в этих средах. Вам просто нужно запустить:

sls deploy -s [stage] -v

Этот шаг создаст .serverless каталог, который будет иметь сгенерированный шаблон облачной информации, Serverless-State и zip-файл, который будет загружен в ковш S3. Мне также нравится -v возможность увидеть каждый созданный ресурс, и каждый шаг без сервера делает 👀

Автоматизация развертывания производства

Если вы хотите шагнуть выше со своим трубопроводом и добавить некоторую автоматизацию, вы можете использовать Дженкинс Чтобы автоматизировать ваш трубопровод CI/CD или автоматически развернуть ваше приложение при объединении ваших изменений в мастер.

Примером Jenkinsfile является как ниже:

pipeline {
  agent {
    kubernetes {
      label 'api-service'
      defaultContainer 'jnlp'
      yaml """
apiVersion: v1
kind: Pod
metadata:
labels:
  component: ci
spec:
  # Use service account that can deploy to all namespaces
  containers:
  - name: node
    image: node:12.15.0-stretch
    command:
    - cat
    tty: true
  - name: awscli
    image: organs/awscli
    command:
    - cat
    tty: true

"""
}
  }
  stages {
    stage('build') {
      environment {
          BRANCH_NAME = sh ( script: "echo ${env.GIT_BRANCH}|  rev  | cut -f1 -d '/' | rev | sed 's/ *//g'", returnStdout: true ).trim()
      }
      steps {
        container('node') {
            sh """
               npm install
               """
        }
        container('awscli') {
            sh """
               # deploy to prod stage if branch is master
               if [ "${env.BRANCH_NAME}" == "master" ]; then
                 sls deploy -s prod -v
               fi
               """
        }
      }
    }
  }
}

Закрытие

Serverless — это удивительная технология или мышление, если хотите. Это важный шаг к делегированию проблем инфраструктуры для компаний, которые гораздо лучше связаны с ними. Независимо от того, насколько хорошо вы становитесь в DevOps, вам иногда нужны эти компании, чтобы обрабатывать и управлять своими приложениями, с которыми вы не хотите беспокоиться. И главное, что здесь — строить вашу архитектуру, не тратя эпохи, налаживая ее самостоятельно и не экономя тонны денег, размещая ее.

Я буду продолжать писать о различных темах без серверов и сценариях корпусов, с которыми я столкнулся, что я также вижу это интересным и сложным.

Цените ваши комментарии и отзывы 😊

Оригинал: «https://dev.to/mohamedmahmoud97/from-zero-to-serverless-20g1»