Статьи
Обучающие материалы
Интерактивные руководства
Использование флажков возможностей LaunchDarkly в конвейерах Bitbucket
Уоррен Марусяк
Старший технический эксперт
Развертывать новый код в рабочей среде всегда рискованно. Баги могут проникнуть в нее даже после модульного, интеграционного и системного тестирования кода в тестовой и промежуточной среде. Как правило, у разработчиков есть два варианта, когда баг попадает в рабочую версию и затрагивает пользователей. Можно откатить код с багом или исправить его в следующей версии. Оба этих решения требуют времени. Теперь разработчики могут включать или выключать возможности в среде одним нажатием кнопки, поместив соответствующие изменения кода во флажок возможности. Воздействие кода с багами на пользователей можно немедленно смягчить, а исправление — безопасно разработать и внедрить. В этой статье данный подход показан на примере конвейеров Bitbucket и флажков возможностей LaunchDarkly в демонстрационном приложении ImageLabeller.
Обязательные условия
Демонстрация флажков возможностей для ImageLabeller
ImageLabeller — это небольшое приложение, которое использует машинное обучение для маркировки изображений. ImageLabeller развертывается в пяти средах: Test, Staging, Production-us-west-2, Production-us-east-1 и Production-ca-central-1. В этой статье показано, как управлять изменениями в компоненте SubmitImage приложения ImageLabeller с помощью флажков возможностей. SubmitImage — это программа AWS Lambda, написанная на языке Go. Вы будете использовать LaunchDarkly для управления флажками возможностей, Bitbucket — для управления исходным кодом и Bitbucket Pipelines — для работы с функциями CI/CD.
Использование флажков возможностей LaunchDarkly с конвейерами Bitbucket
Попросите локального администратора LaunchDarkly создать проект и среду. На снимке экрана ниже представлен проект PMMimageLabellerDemo с пятью средами. Test и Staging — это тестовая и промежуточная среды, используемые перед рабочими средами. Обратите внимание на ключ SDK для каждой среды. В дальнейшем эти ключи SDK будут добавлены в качестве переменных репозитория в Bitbucket.
В этом примере конвейеры Bitbucket выполняют развертывание в этих средах при коммитах кода в функциональную ветку. Production-US-West-2, Production-US-East-1 и Production-CA-Central-1 — это рабочие среды, соответствующие средам AWS. Конвейеры Bitbucket выполняют развертывание в этих средах при слиянии кода в основной ветке с кодом из функциональной ветки с помощью запроса pull.
В LaunchDarkly создайте флажок возможности для проекта. Выберите тестовую среду и задайте настройки флажка возможности. На снимке экрана ниже флажок возможности по умолчанию возвращает значение true в тестовом регионе. Если запрос подает конкретный пользователь AtlassianTestUser@atlassian.com, флажок возможности вернет значение false. Таким образом, для пользователя с конкретным именем, например для тестовых пользователей в пакете системных тестов, код будет выполняться одним образом, а для обычных пользователей в той же среде — другим.
Это поведение можно настраивать отдельно для каждой среды. Флажки возможностей позволяют разработчику развертывать новый код во всех регионах, но при этом выполняться он будет только в определенных средах. Для этого демонстрационного приложения флажок возвращает значение false в среде Staging и во всех трех рабочих средах. Новый код будет выполняться только в тестовой среде.
Найдите ключи SDK для каждой среды в LaunchDarkly. Затем перейдите в Bitbucket и добавьте переменные репозитория в каждый репозиторий, который будет использовать этот флажок. На снимке экрана ниже добавлено пять переменных репозитория. ld_test_env содержит ключ SDK LaunchDarkly для тестовой среды. ld_staging_env содержит ключ SDK LaunchDarkly для промежуточной среды. В дальнейшем эти переменные будут использоваться в качестве ссылок в файле bitbucket-pipelines.yml для репозитория.
Значения ключей SDK могут использоваться как ссылки в файле bitbucket-pipeline.yml после добавления ключей SDK в качестве переменных репозитория. В приведенном ниже фрагменте в шаг развертывания для среды production-ca-central-1 добавлена переменная STACK_PARAMETERS. STACK_PARAMETERS отправляет значение соответствующего ключа SDK в файл AWS CloudFormation template.yml в виде параметра.
- pipe: atlassian/aws-sam-deploy:1.2.0
variables:
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
AWS_DEFAULT_REGION: 'ca-central-1'
STACK_NAME: 'OpenDevOpsSubmitImage'
CAPABILITIES: [ 'CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM', 'CAPABILITY_AUTO_EXPAND' ]
TEMPLATE: 'https://s3.amazonaws.com/open-devops-code-ca-central-1-${AWS_ACCOUNT_ID}/submit-image-packaged.yml'
WAIT: 'true'
DEBUG: 'true'
S3_BUCKET: 'open-devops-code-ca-central-1-${AWS_ACCOUNT_ID}'
SAM_TEMPLATE: 'build/template.yaml'
STACK_PARAMETERS: '[{
"ParameterKey": "LaunchDarklySDKKey",
"ParameterValue": "${ld_prod_cac1_env}"
}]'
Добавьте параметр LaunchDarklySDKKey типа String в раздел Parameters файла template.yml для репозитория. Он получает значение параметра STACK_PARAMETER для LaunchDarklySDKKey, заданного в файле bitbucket-pipelines.yml.
Parameters:
LaunchDarklySDKKey:
Type: String
Кроме того, обновите ресурс AWS Lambda для функции SubmitImageFunction в разделе Resources файла template.yml. Добавьте переменную среды LaunchDarklySDKKey в разделе Environment > Variables.
Resources:
SubmitImageFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: submitImage/
Handler: submit-image
Runtime: go1.x
Tracing: Active # https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html
Policies:
- AmazonDynamoDBFullAccess
- AmazonS3FullAccess
Events:
CatchAll:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /submit-image
Method: GET
Environment:
Variables:
LaunchDarklySDKKey:
Ref: LaunchDarklySDKKey
Переменную среды LaunchDarklySDKKey можно будет увидеть в консоли AWS Lambda после развертывания конвейерами BitBucket в среде. Значение этого ключа уникально для каждой среды. Например, переменная среды LaunchDarklySDKKey в среде Test будет отличаться от переменной в Production-us-west-2.
SubmitImage — это программа AWS Lambda, написанная на языке Go. Чтобы использовать LaunchDarkly в Go, импортируйте следующие зависимости.
"gopkg.in/launchdarkly/go-sdk-common.v2/lduser"
ld "gopkg.in/launchdarkly/go-server-sdk.v5"
Добавьте функцию для получения значения флажка возможности из LaunchDarkly во время выполнения.
func getLaunchDarklyFlags(username string) (bool, error) {
client, _ := ld.MakeClient(os.Getenv("LaunchDarklySDKKey"), 5 * time.Second)
flagKey := "SubmitImageDemoFeature"
userUuid, uuidErr := uuid.NewRandom()
if uuidErr != nil {
return false, uuidErr
}
var user lduser.User
if(username == "") {
user = lduser.NewAnonymousUser(userUuid.String())
} else {
user = lduser.NewUser(username)
}
showFeature, _ := client.BoolVariation(flagKey, user, false)
if showFeature {
return true, nil
} else {
return false, nil
}
}
Передайте функции пустую строку, чтобы получить значение флажка по умолчанию, или электронную почту пользователя, чтобы получить соответствующее значение. С приведенной выше конфигурацией для анонимного пользователя должно возвращаться значение true, а для пользователя AtlasianTestUser@atlassian.com — значение false.
flagVal, flagErr := getLaunchDarklyFlags("")
if flagErr != nil {
return "", flagErr
}
fmt.Println("DEMO flagVal for anonymous user: ", flagVal)
flagVal, flagErr = getLaunchDarklyFlags("AtlassianTestUser@atlassian.com")
if flagErr != nil {
return "", flagErr
}
fmt.Println("DEMO flagVal for AtlassianTestUser@atlassian.com: ", flagVal)
После выполнения кода перейдите в журналы AWS CloudWatch, чтобы убедиться, что для флажка возвращаются правильные значения.
Перейдите в раздел Admin settings (Настройки администратора), а затем выберите API keys (Ключи API), чтобы получить список ключей API для каждой среды. Эти ключи API отправляются обратно в Split во время вызовов API в коде, чтобы получить правильную версию Split. В этом руководстве для каждой среды используются ключи Server-side.
Перейдите в свой репозиторий Bitbucket, затем нажмите Repository settings (Настройки репозитория), после чего выберите Repository variables (Переменные репозитория) и добавьте переменные для каждого ключа API.
Отредактируйте файл bitbucket-pipelines.yml и добавьте переменную STACK_PARAMETERS в шаг развертывания AWS SAM. Это делается отдельно для каждой среды. В приведенном ниже фрагменте YAML показан этап развертывания в регионе для тестирования (в данном случае это AWS US-WEST-1). Поэтому в данном шаге указана ссылка на настроенную выше переменную репозитория split_test_env. Используйте соответствующую переменную репозитория для каждой среды.
- pipe: atlassian/aws-sam-deploy:1.2.0
variables:
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
AWS_DEFAULT_REGION: 'us-west-1'
STACK_NAME: 'OpenDevOpsSubmitImage'
CAPABILITIES: [ 'CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM', 'CAPABILITY_AUTO_EXPAND' ]
TEMPLATE: 'https://s3.amazonaws.com/open-devops-code-us-west-1-${AWS_ACCOUNT_ID}/submit-image-packaged.yml'
WAIT: 'true'
DEBUG: 'true'
S3_BUCKET: 'open-devops-code-us-west-1-${AWS_ACCOUNT_ID}'
SAM_TEMPLATE: 'build/template.yaml'
STACK_PARAMETERS: '[{
"ParameterKey": "SplitIOSDKKey",
"ParameterValue": "${split_test_env}"
}]'
Отредактируйте файл template.yml для AWS CloudFormation и добавьте раздел Parameters со ссылкой на ключ Split SDK.
Parameters:
SplitIOSDKKey:
Type: String
В файле template.yml добавьте раздел Environment для каждого ресурса AWS Lambda, которому требуется доступ к Split. В этом руководстве показано
Environment:
Variables:
SplitIOSDKKey:
Ref: SplitIOSDKKey
Импортируйте следующие зависимости в файл Go, в котором будет использоваться Split SDK.
"github.com/splitio/go-client/v6/splitio/client"
"github.com/splitio/go-client/v6/splitio/conf"
Эта функция создает клиент и извлекает значение флажка возможности для параметра SubmitImageDemoSplit, созданного в пользовательском интерфейсе Split. Она принимает один аргумент — имя пользователя.
func getSplitIOFlag(username string) (string, error) {
splitIOSDKKey := os.Getenv("SplitIOSDKKey")
cfg := conf.Default()
factory, err := client.NewSplitFactory(splitIOSDKKey, cfg)
if err != nil {
fmt.Printf("SDK init error: %s\n", err)
return "", err
}
splitClient := factory.Client()
err = splitClient.BlockUntilReady(10)
if err != nil {
fmt.Printf("SDK timeout: %s\n", err)
return "", err
}
treatment := splitClient.Treatment(username, "SubmitImageDemoSplit", nil)
fmt.Printf("SPLIT_DEMO treatment is %s, username is %s\n", treatment, username)
return treatment, nil
}
Вызовите функцию, передав ей адрес электронной почты. В этом случае для адреса someRandomUser@atlassian.com функция вернет значение по умолчанию, поскольку он не входит в список разрешенных адресов для флажка возможности. Для AtlassianTestUser@atlassian.com функция вернет значение из списка разрешенных адресов для этого флажка возможности.
Просмотрите выходные данные в журналах AWS CloudWatch после выполнения кода. Обратите внимание, что для флажка возможности указано off (отключено) при обращении с адресом someRandomUser@atlassian.com и on (включено) — при обращении с адресом AtlassianTestUser@atlassian.com.
Заключение
Флажки возможностей LaunchDarkly можно легко интегрировать в приложение, развертываемое с помощью конвейеров Bitbucket. Они позволяют разработчикам контролировать выполнение развернутого кода. Это может ускорить реагирование на баги при развертывании и снизить воздействие на пользователей. Потратьте немного времени, чтобы запустить экземпляр Bitbucket с LaunchDarkly и протестировать возможности для вашей команды.
Поделитесь этой статьей
Следующая тема
Рекомендуемые статьи
Добавьте эти ресурсы в закладки, чтобы изучить типы команд DevOps или получать регулярные обновления по DevOps в Atlassian.