Вступление
В микросервисной архитектуре непрерывная интеграция и непрерывная доставка (CI / CD) имеют решающее значение для создания гибкой среды для внесения постепенных изменений в вашу систему. Это требует немедленного создания, тестирования и развертывания каждого изменения кода, которое вы вносите в свой репозиторий, в свою инфраструктуру. Есть много технологий, которые помогают сделать это, и часто требуется, чтобы вы установили сложные части программного обеспечения для достижения цели.
Вам также может понравиться: Полная коллекция CI / CD
Недавно GitHub Actions вышел из бета-версии и доступен для общего пользования. Действия GitHub предоставляют удобный механизм для реализации конвейеров CI / CD с использованием их концепции рабочих процессов, прямо из наших репозиториев GitHub. Вместо того, чтобы устанавливать собственное программное обеспечение, оно доступно как облачный сервис для всех.
В этой статье мы проверим, как GitHub Actions дополняет использование языка Ballerina , платформы, которая специализируется на разработке и развертывании микросервисов. С помощью действия Ballerina GitHub , которое доступно на GitHub Marketplace, мы можем создать среду разработки Ballerina со встроенным CI / CD с помощью GitHub. Мы специально рассмотрим три сценария развития с использованием Ballerina.
- Развертывание микросервисов балерины с Kubernetes.
- Развертывание балерины без сервера с помощью AWS Lambda.
- Развертывание модуля «Балерина» до Центра Балерины.
Балерина Микросервис Развертывание с Kubernetes
Балерина содержит богатую поддержку для развертывания микросервисов в среде Kubernetes. Просто добавив соответствующие аннотации к нашим сервисам, компилятор автоматически сгенерирует образ Docker и артефакты Kubernetes для вас. Затем, в качестве последнего шага, вы можете просто использовать инструмент kubectl для развертывания приложения в целевом кластере Kubernetes. Проверьте эту Балерину на Примере по Развертыванию Kubernetes для получения дополнительной информации.
Давайте создадим простой сервис Ballerina, чтобы продемонстрировать эту функциональность. Эта служба просто принимает полезную нагрузку двоичного запроса, которая передает содержимое в соединитель Azure Computer Vision , который затем связывается с облачной службой и выполняет преобразование изображения в текст. Здесь мы требуем, чтобы приложение создавалось, тестировалось и развертывалось в нашем кластере Kubernetes каждый раз, когда мы выполняем обновление кода для нашего сервиса. Это можно сделать, определив рабочий процесс GitHub Actions для нашего репозитория. Основные шаги для этого следующие:
- Извлеките код проекта Ballerina в рабочее пространство.
- Постройте код и запустите модульные тесты.
- Передайте ключи API как секреты.
- Создайте уникальный образ Docker для каждой сборки и разверните его в DockerHub.
- Укажите имя пользователя / пароль DockerHub в качестве секрета.
- Выполните kubectl для развертывания встроенного приложения в кластер Kubernetes.
Вышеуказанные шаги должны быть определены в нашем рабочем процессе. Для начала давайте посмотрим на исходный код службы Ballerina, который показан в листинге 1.
Джава
1
import ballerina/http;
2
import ballerina/kubernetes;
3
import ballerina/system;
4
import wso2/azurecv;
5
azurecv:Configuration conf = {
7
key: system:getEnv("CV_KEY"),
8
region: "eastus"
9
};
10
azurecv:Client cvClient = new(conf);
12
Service { :
14
serviceType: "LoadBalancer",
15
port: 80
16
}
17
Deployment { :
18
image: "$env{docker_username}/ballerina-k8s-actions-sample-$env{GITHUB_SHA}",
19
push: true,
20
username: "$env{docker_username}",
21
password: "$env{docker_password}",
22
imagePullPolicy: "Always",
23
env: { "CV_KEY": "$env{CV_KEY}" }
24
}
25
ServiceConfig { :
26
basePath: "/image2Text"
27
}
28
service Image2Text on new http:Listener(8080) {
29
ResourceConfig { :
31
path: "/"
32
}
33
resource function process(http:Caller caller, http:Request request) returns error? {
34
byte[] payload = check request.getBinaryPayload();
35
string result = check cvClient->ocr(<> payload);
36
check caller->respond(<> result);
37
}
38
}
Листинг 1 - image2Text.bal
В приведенном выше исходном коде мы видим, что нам нужны некоторые дополнительные параметры во время сборки и во время выполнения. Во время сборки нам нужна пара имя пользователя / пароль DockerHub для загрузки образа Docker приложения в DockerHub (или любой другой реестр Docker).
Поскольку наше приложение теперь встроено в среду GitHub, мы можем установить переменные среды в нашем рабочем процессе GitHub Actions, которые будут считываться сборкой Ballerina. Кроме того, любая конфиденциальная информация может быть установлена в качестве секретов в настройках вашего репозитория GitHub, как показано на рисунке 1. Они также предоставляются в качестве переменных среды при выполнении нашей сборки.
Во время выполнения нам нужен ключ API для службы компьютерного зрения Azure , чтобы использовать соединитель. Для этого сначала необходимо предоставить ключ API для среды сборки GitHub, задав его в качестве секрета («CV_KEY») и передав его в качестве переменной среды через рабочий процесс. Теперь, во время сборки, мы получаем доступ к этому значению как к переменной среды и устанавливаем его в артефактах развертывания Kubernetes, используя атрибут «env» аннотаций @kubernetes: Deployment.
Для этого требуется карта пар ключ / значение для переменных среды, которые необходимо установить в целевом контейнере. Используя этот шаблон, мы можем передать секретное значение из среды сборки GitHub в среду выполнения целевого кластера Kubernetes, которая будет использоваться в наших приложениях.
Также обратите внимание, что мы добавили суффикс «$ env {GITHUB_SHA}» к атрибуту «image» аннотации «@kubernetes: Deployment» («GITHUB_SHA» - это переменная среды, автоматически заполняемая GitHub Actions, которая содержит значение SHA последнего Git commit, который запустил рабочий процесс). Это делается для того, чтобы создать уникальное имя изображения для повторных развертываний. Таким образом, Kubernetes будет подбирать обновленный образ каждый раз, когда развертывание будет выполнено.
Давайте теперь посмотрим на рабочий процесс GitHub Actions, который мы определили для выполнения необходимых шагов.
YAML
xxxxxxxxxx
1
name Deploy to K8s
2
on push
4
jobs
6
build
7
runs-on ubuntu-latest
9
steps
11
name Checkout
12
uses actions/checkout@v1
13
14
name Ballerina Build
15
uses ballerina-platform/ballerina-action/@1.1.1
16
with
17
args
18
build image2Text.bal
19
env
20
docker_username $
21
docker_password $
22
CV_KEY $
23
24
name Kubectl
25
uses danielr1996/kubectl-action@1.0.0
26
with
27
args apply -f $GITHUB_WORKSPACE/kubernetes/
28
kubeconfig $
Листинг 2 - Определение рабочего процесса развертывания Ballerina Service Kubernetes
Рабочие процессы определяются в вашем репозитории GitHub путем добавления файла YAML в каталог «/.github/workflows/». В листинге 2 показано определение рабочего процесса: как он запускается при каждом нажатии кода и где он начинается с извлечения исходного кода. Затем он выполняет действие Ballerina, чтобы выполнить команду «Ballerina build» для нашего исходного кода Ballerina.
После сборки образ Docker будет загружен в реестр, и сгенерированные артефакты Kubernetes будут доступны в рабочей области. В рабочем процессе после сборки Ballerina мы выполняем действие kubectl, чтобы использовать сгенерированные артефакты Kubernetes и развернуть приложение в целевом кластере.
В моем примере я использовал службу Azure Kubernetes (AKS) для создания кластера Kubernetes в облаке. После этого я заполнил свой локальный kubeconfig информацией о кластере AKS Kubernetes, используя следующую команду Azure CLI.
Оболочка
xxxxxxxxxx
1
az aks get-credentials --resource-group connector --name k8s-1
Чтобы выполнить команду kubectl в среде GitHub Actions, нам нужно предоставить kubeconfig, чтобы найти целевой кластер. Это делается путем установки переменной среды «kubeconfig» для действия kubectl, которая содержит кодированный в 64-битном формате текст данных kubeconfig. Например, наш локальный kubeconfig может быть извлечен в этом формате с помощью следующей команды оболочки.
Оболочка
xxxxxxxxxx
1
cat ~/.kube/config | base64
В моих настройках репозитория GitHub я установил вышеуказанное содержимое kubeconfig, используя секрет «KUBE_CONFIG_DATA», как показано на рисунке 1, который, в свою очередь, используется в рабочем процессе для установки переменной среды «kubeconfig» для действия kubectl.
Теперь, имея рабочий процесс GitHub Actions, давайте посмотрим, какие операции происходят, когда мы выполняем передачу кода в наше хранилище кода.
На рисунке 2 показана вкладка «Действия» в репозитории GitHub, а также порядок выполнения рабочего процесса. После проверки кода он выполняет сборку Ballerina и выполняет действие kubectl для развертывания нашего сервиса в кластере Kubernetes в AKS.
После выполнения рабочего процесса мы можем локально выполнить команду kubectl, чтобы отслеживать наше развернутое приложение и, в частности, чтобы определить внешний IP-адрес, по которому будет доступна служба.
Оболочка
xxxxxxxxxx
1
$ kubectl get svc
2
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
4
image2text-svc LoadBalancer 10.0.254.92 52.138.123.109 80:30435/TCP 23s
6
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 96m
Мы видим, что наш сервис развернут по определенному внешнему IP-адресу, и мы можем отправлять запросы на эту конечную точку.
Оболочка
xxxxxxxxxx
1
$ curl --data-binary "@input.jpeg" http://52.138.123.109/image2Text
2
NOTHING
3
EXISTS
4
EXCEPT
5
ATOMS
6
AND EMPTY
7
SPACE.
8
Everything else
9
is opinion.
Полный источник этого образца и рабочий процесс, используемый для этого, можно найти здесь: https://github.com/lafernando/ballerina-k8s-actions-sample .
Балерина без сервера развертывания с AWS Lambda
Балерина имеет встроенную поддержку написания лямбда-функций AWS. Это делается путем написания функции Ballerina в соответствии с определенной сигнатурой и добавления к ней аннотации «@awslambda: Function».
Пример лямбда-функции в Ballerina показан в листинге 3.
Джава
xxxxxxxxxx
1
import ballerinax/awslambda;
2
Function :
4
public function hello(awslambda:Context ctx, json input) returns json|error {
5
return "Hello, World!";
6
}
Листинг 3: hello.bal
Здесь мы просто возвращаем постоянное строковое значение из лямбда-функции. Это может быть любое значение JSON, которое мы возвращаем.
Мы можем собрать приведенный выше код с помощью команды «ballerina build», и это приведет к аналогичному выводу, как показано ниже.
Оболочка
xxxxxxxxxx
1
$ ballerina build hello.bal
2
Compiling source
3
hello.bal
4
Generating executables
5
hello.jar
6
@awslambda:Function: hello
7
Run the following commands to deploy each Ballerina AWS Lambda function:
9
aws lambda create-function --function-name <FUNCTION_NAME> --zip-file fileb://aws-ballerina-lambda-functions.zip --handler hello.<FUNCTION_NAME> --runtime provided --role <LAMBDA_ROLE_ARN> --timeout 10 --memory-size 1024
11
aws lambda update-function-configuration --function-name <FUNCTION_NAME> --layers arn:aws:lambda:<REGION_ID>:141896495686:layer:ballerina:2
13
Run the following command to re-deploy an updated Ballerina AWS Lambda function:
15
aws lambda update-function-code --function-name <FUNCTION_NAME> --zip-file fileb://aws-ballerina-lambda-functions.zip
В результате генерируется лямбда-zip-файл («aws-ballerina-lambda-functions.zip»), который упакован в формате, требуемом AWS Lambda. Это также выводит на экран команды CLI AWS, необходимые для развертывания функции. Мы можем выполнить начальное развертывание функции с помощью команды, аналогичной следующей.
Оболочка
xxxxxxxxxx
1
$ aws lambda create-function --function-name hello --zip-file fileb://aws-ballerina-lambda-functions.zip --handler hello.hello --runtime provided --role arn:aws:iam::908363916138:role/lambda-role --layers arn:aws:lambda:us-west-1:141896495686:layer:ballerina:2
2
{
4
"FunctionName": "hello",
6
"FunctionArn": "arn:aws:lambda:us-west-1:908363916138:function:hello",
8
"Runtime": "provided",
10
"Role": "arn:aws:iam::908363916138:role/lambda-role",
12
"Handler": "hello.hello",
14
"CodeSize": 20951578,
16
"Description": "",
18
"Timeout": 3,
20
"MemorySize": 128,
22
"LastModified": "2020-02-08T09:44:07.804+0000",
24
"CodeSha256": "+NlTLe0SDUPbkwNNrnlg+Bwj6yCIaZeFDzZEnrwLa9c=",
26
"Version": "$LATEST",
28
"TracingConfig": {
30
"Mode": "PassThrough"
32
},
34
"RevisionId": "7df9f305-22ea-44cf-aee2-396df4df021e",
36
"Layers": [
38
{
40
"Arn": "arn:aws:lambda:us-west-1:141896495686:layer:ballerina:2",
42
"CodeSize": 697
44
}
46
]
48
}
После того, как начальное развертывание выполнено, каждый раз, когда вы делаете изменение кода, мы можем повторно развертывать код, используя следующую команду.
Простой текст
xxxxxxxxxx
1
$ aws lambda update-function-code --function-name hello --zip-file fileb://aws-ballerina-lambda-functions.zip
Давайте автоматизируем наше развертывание обновленной функции Lambda, используя рабочий процесс GitHub Actions. Давайте начнем с определения, которое мы использовали для достижения этой цели, как показано в листинге 4.
YAML
xxxxxxxxxx
1
name AWS Lambda Deploy
2
on push
4
jobs
6
build
7
runs-on ubuntu-latest
9
steps
11
uses actions/checkout@v2
12
name Ballerina Build
13
uses ballerina-platform/ballerina-action/@1.1.1
14
with
15
args
16
build hello.bal
17
name AWS CLI
18
uses ItsKarma/aws-cli@v1.70.0
19
with
20
args
21
lambda update-function-code --function-name hello --zip-file fileb://aws-ballerina-lambda-functions.zip
22
env
23
AWS_DEFAULT_REGION us-west-1
24
AWS_SECRET_ACCESS_KEY $
25
AWS_ACCESS_KEY_ID $
Листинг 4: Определение рабочего процесса AWS Lambda Deployment
Здесь, аналогично нашему рабочему процессу развертывания в Kubernetes, мы сначала начнем с проверки кода и создания исходного кода Ballerina. После этого мы выполняем действие, которое запускает CLI AWS. В этом действии используются три переменные среды: «AWS_DEFAULT_REGION», «AWS_SECRET_ACCESS_KEY» и «AWS_ACCESS_KEY_ID». Последние два считываются как секреты из настроек репозитория GitHub. Значения доступа / секрета можно найти в вашей учетной записи AWS.
Теперь каждый раз, когда в репозиторий выполняется передача кода, рабочий процесс будет выполняться и повторно развертывать лямбда-функцию в AWS. Шаги, видимые в рабочем процессе, будут аналогичны рисунку 3.
Мы можем проверить развертывание, вызвав лямбда-функцию следующим образом.
Оболочка
xxxxxxxxxx
1
$ aws lambda invoke --function-name hello out.json
2
{
4
"StatusCode": 200,
5
"ExecutedVersion": "$LATEST"
6
}
7
$ cat out.json
9
"Hello, World!"
Полный источник этого образца и рабочий процесс, используемый для этого, можно найти здесь: https://github.com/lafernando/lambda-actions-example .
Балерина Модуль Развертывание в Балерина Центральная
У Ballerina есть собственный публичный репозиторий модулей, известный как Ballerina Central . Всякий раз, когда у нас есть модуль Ballerina, который можно использовать повторно и которым нужно поделиться с другими, мы отправляем модуль в Ballerina Central.
Как правило, после того, как мы разработали некоторые улучшения модуля, мы делали релиз репозитория GitHub, чтобы пометить его, а затем собирали и передавали модуль в Ballerina Central. Более ранние ручные операции по созданию, запуску тестов и развертыванию модуля теперь можно автоматизировать с помощью действий GitHub. Давайте посмотрим пример модуля, где мы это сделали.
Модуль CV Azure , который используется в нашем первом сценарии, разработан и выпущен используя действия GitHub рабочего процесса. Здесь мы используем два отдельных рабочих процесса для наших операций непрерывной интеграции (CI), которые создают и запускают тесты для каждого push-кода. Другой рабочий процесс специально предназначен для развертывания в Ballerina Central, который запускается по завершении выпуска модуля.
Давайте посмотрим на рабочий процесс CI, который мы имеем в листинге 5 ниже.
YAML
xxxxxxxxxx
1
name CI
2
on push
4
jobs
6
build
7
runs-on ubuntu-latest
9
steps
11
uses actions/checkout@v2
12
name Ballerina Build
13
uses ballerina-platform/ballerina-action/@1.1.1
14
with
15
args
16
build -a -c
17
env
18
AZURE_CV_KEY $
Листинг 5 - Определение рабочего процесса CI Ballerina Azure CV Module
Здесь мы просто проверяем код и делаем сборку Ballerina для запуска тестов, чтобы посмотреть, все ли работает правильно с нашим новым изменением. Также мы передаем секретное значение репозитория GitHub «AZURE_CV_KEY» в качестве переменной среды, которая используется в тестах в качестве ключа API соединителя.
В следующем рабочем процессе мы выполняем дополнительные команды, чтобы отправить модуль в Ballerina Central. Это показано в листинге 6 ниже.
YAML
xxxxxxxxxx
1
name Deployment
2
on release
4
jobs
6
build
7
runs-on ubuntu-latest
9
steps
11
uses actions/checkout@v2
12
name Ballerina Build
13
uses ballerina-platform/ballerina-action/@1.1.1
14
with
15
args
16
build -a -c
17
env
18
AZURE_CV_KEY $
19
name Ballerina Push
20
uses ballerina-platform/ballerina-action/@1.1.1
21
with
22
args
23
push -a
24
env
25
BALLERINA_CENTRAL_ACCESS_TOKEN $
Листинг 6 - Определение рабочего процесса развертывания модуля CV Ballerina Azure
Вы можете заметить, что вышеуказанный рабочий процесс запускается с событием «release», а не с «push» событием, которое мы использовали ранее. Кроме того, после того, как мы выполним проверку кода, создадим код и запустим тесты, мы, наконец, делаем «толчок балерины», чтобы загрузить встроенный модуль Ballerina в Ballerina Central.
Для этого нам нужно предоставить токен доступа Ballerina Central в качестве переменной среды («BALLERINA_CENTRAL_ACCESS_TOKEN»). Чтобы узнать значение токена доступа Ballerina Central, войдите в Ballerina Central и перейдите по адресу https://central.ballerina.io/dashboard .
Два рабочих процесса в действии можно увидеть на рисунках 4 и 5 для определения CI и выпуска соответственно.
Резюме
В этой статье мы увидели, как можно создать эффективный конвейер CI / CD с использованием языка программирования Ballerina, который специализируется на разработке микросервисов, в сочетании с GitHub Actions, который предоставляет чистый облачный сервис для определения наших собственных рабочих процессов выполнения. Таким образом, нам больше не нужно создавать собственную инфраструктуру для операций CI / CD, а мы можем определить необходимые нам функции непосредственно из наших репозиториев GitHub.
Дальнейшее чтение
DZone Refcard: Начало работы с балериной