[Yandex Cloud documentation](../../index.md) > [Yandex API Gateway](../index.md) > [Tutorials](index.md) > Serverless-based backend > Canary release of a function in Cloud Functions

# Canary release of a function in Cloud Functions


Create a canary release of a function in Cloud Functions using API Gateway.

To create a canary release:
1. [Get your cloud ready](#before-begin).
1. [Create a service account](#create-account).
1. [Create a function in Cloud Functions](#create-functions).
1. [Add tags](#add-tag).
1. [Create an API gateway](#create-api-gw).
1. [Test your application](#test).

If you no longer need the resources you created, [delete them](#clear-out).

## Getting started {#before-begin}

Sign up for Yandex Cloud and create a [billing account](../../billing/concepts/billing-account.md):
1. Navigate to the [management console](https://console.yandex.cloud) and log in to Yandex Cloud or create a new account.
1. On the **[Yandex Cloud Billing](https://center.yandex.cloud/billing/accounts)** page, make sure you have a billing account linked and it has the `ACTIVE` or `TRIAL_ACTIVE` [status](../../billing/concepts/billing-account-statuses.md). If you do not have a billing account, [create one](../../billing/quickstart/index.md) and [link](../../billing/operations/pin-cloud.md) a cloud to it.

If you have an active billing account, you can create or select a [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) for your infrastructure on the [cloud page](https://console.yandex.cloud/cloud).

[Learn more about clouds and folders here](../../resource-manager/concepts/resources-hierarchy.md).

### Required paid resources {#paid-resources}

The web application support cost includes:
* Fee for the number of requests to the API gateway and outgoing traffic (see [Yandex API Gateway pricing](../pricing.md)).
* Fee for the number of function calls, computing resources allocated for the function, and outgoing traffic (see [Yandex Cloud Functions pricing](../../functions/pricing.md)).

## Create a service account {#create-account}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you want to create a service account.
  1. Navigate to **Identity and Access Management**.
  1. Click **Create service account**.
  1. Enter a name for the service account: `canary-sa`.
  1. Click ![image](../../_assets/console-icons/plus.svg) **Add role** and select `editor`.
  1. Click **Create**.

- CLI {#cli}

  If you do not have the Yandex Cloud CLI yet, [install and initialize it](../../cli/quickstart.md#install).

  The folder used by default is the one specified when [creating](../../cli/operations/profile/profile-create.md) the CLI profile. To change the default folder, use the `yc config set folder-id <folder_ID>` command. You can also specify a different folder for any command using `--folder-name` or `--folder-id`. If you access a resource by its name, the search will be limited to the default folder. If you access a resource by its ID, the search will be global, i.e., through all folders based on access permissions.

  1. Create a service account named `canary-sa`:

      ```bash
      yc iam service-account create --name canary-sa
      ```

      Result:

      ```
      id: nfersamh4sjq********
      folder_id: b1gc1t4cb638********
      created_at: "2023-09-21T10:36:29.726397755Z"
      name: canary-sa
      ```

      Save the ID of the `canary-sa` service account (`id`) and the ID of the folder where you created it (`folder_id`).

  1. Assign the `editor` role for the folder to the service account:

      ```bash
      yc resource-manager folder add-access-binding <folder_ID> \
        --role editor \
        --subject serviceAccount:<service_account_ID>
      ```

      Result:

      ```
      done (1s)
      ```

- Terraform {#tf}

  
  If you do not have Terraform yet, [install it and configure the Yandex Cloud provider](../../tutorials/infrastructure-management/terraform-quickstart.md#install-terraform).


  1. In the configuration file, define the service account properties:

      ```hcl
      resource "yandex_iam_service_account" "canary-sa" {
        name        = "canary-sa"
        folder_id   = "<folder_ID>"
      }

      resource "yandex_resourcemanager_folder_iam_member" "editor" {
        folder_id = "<folder_ID>"
        role      = "editor"
        member    = "serviceAccount:${yandex_iam_service_account.canary-sa id}"
      }
      ```

      Where:

      * `name`: Service account name. This is a required setting.
      * `folder_id`: [Folder ID](../../resource-manager/operations/folder/get-id.md). This is an optional setting. It defaults to the value specified in the provider settings.
      * `role`: Role being assigned.

      For more information about `yandex_iam_service_account` properties in Terraform, see [this provider guide](../../terraform/resources/iam_service_account.md).

  1. Make sure the configuration files are correct.

      1. In the terminal, navigate to the directory where you created your configuration file.
      1. Run a check using this command:

         ```bash
         terraform plan
         ```

      If the configuration is correct, the terminal will display information about the service account. Otherwise, Terraform will show any detected errors.

  1. Deploy the cloud resources.

      1. If the configuration is correct, run this command:

           ```bash
           terraform apply
           ```

      1. Confirm creating the service account by typing `yes` in the terminal and pressing **Enter**.

           This will create the service account. You can check it using the [management console](https://console.yandex.cloud) or this [CLI](../../cli/quickstart.md) command:

           ```bash
           yc iam service-account list
           ```

- API {#api}

  To create a service account, use the [create](../../iam/api-ref/ServiceAccount/create.md) REST API method for the [ServiceAccount](../../iam/api-ref/ServiceAccount/index.md) resource or the [ServiceAccountService/Create](../../iam/api-ref/grpc/ServiceAccount/create.md) gRPC API call.

  To assign the `editor` role for a folder to a service account, use the [setAccessBindings](../../iam/api-ref/ServiceAccount/setAccessBindings.md) method for the [ServiceAccount](../../iam/api-ref/ServiceAccount/index.md) resource or the [ServiceAccountService/SetAccessBindings](../../iam/api-ref/grpc/ServiceAccount/setAccessBindings.md) gRPC API call.

{% endlist %}

## Create a function in Cloud Functions {#create-functions}

[Create two function versions](../../functions/operations/index.md#create-function):
* Current release version.
* Canary release version to test on a certain percentage of requests.

You can use a custom function or create [any function from the list](../../functions/quickstart/create-function/index.md).

## Add tags {#add-tag}

Tag the first function version as `stable` and the second one as `canary`.

{% list tabs group=instructions %}

- CLI {#cli}

    To tag a version, run this command:

    ```
    yc serverless function version set-tag --id <version_ID> --tag <tag>
    ```

    Result:

    ```
    id: b09ch6pmpohf********
    function_id: b097d9ous3ge********
    created_at: "2023-08-22T09:12:38.464Z"
    runtime: python311
    entrypoint: test.handler
    resources:
      memory: "134217728"
    execution_timeout: 5s
    image_size: "4096"
    status: ACTIVE
    tags:
      - $latest
      - stable
    ```

- Terraform {#tf}

    To add a version tag:

    1. In the configuration file, add the `tags` section for the `yandex_function` resource and list the tags you want to add in the following format: `tags = ["<tag_name>"]`.

       Example of a function description in the Terraform configuration:
      
        ```
        resource "yandex_function" "test-function" {
            name               = "canary-function"
            user_hash          = "canary-function"
            runtime            = "python311"
            entrypoint         = "main"
            memory             = "128"
            execution_timeout  = "10"
            service_account_id = "<service_account_ID>"
            tags               = ["my_tag"]
            content {
                zip_filename = "<path_to_ZIP_archive>"
            }
        }
        ``` 

        For more information about `yandex_function` properties, see [this provider guide](../../terraform/resources/function.md).

    1. Validate your configuration using this command:
        
       ```
       terraform validate
       ```

       If the configuration is valid, you will get this message:
        
       ```
       Success! The configuration is valid.
       ```

    1. Run this command:

       ```
       terraform plan
       ```
        
       You will see a list of resources and their properties. No changes will be made at this step. Terraform will show any errors in the configuration. 
         
    1. Apply the configuration changes:

       ```
       terraform apply
       ```
    1. Type `yes` and press **Enter** to confirm the changes.
      
    You can check the new tags using the [management console](https://console.yandex.cloud) or this [CLI](../../cli/quickstart.md) command:

    ```
    yc serverless function version list --function-name <function_name>
    ```

- API {#api}

    To add a function version tag, use the [setTag](../../functions/functions/api-ref/Function/setTag.md) REST API method for the [Function](../../functions/functions/api-ref/Function/index.md) resource or the [FunctionService/SetTag](../../functions/functions/api-ref/grpc/Function/setTag.md) gRPC API call.

{% endlist %}

## Create an API gateway {#create-api-gw}

{% list tabs group=instructions %}

- Management console {#console}

    1. In the [management console](https://console.yandex.cloud), select the folder where you want to create an API gateway.
    1. Navigate to **API Gateway**.
    1. Click **Create API gateway**.
    1. In the **Name** field, enter `canary`.
    1. Under **Specification**, add the following specification:
    
        ```yaml
        openapi: 3.0.0
        info:
          title: Sample API
          version: 1.0.0

        x-yc-apigateway:
          variables:
            function.tag:
              default: "stable"
              enum:
                - "stable"
                - "canary"

        paths:
          /:
            get:
              x-yc-apigateway-integration:
                type: cloud_functions
                function_id: <function_ID>
                tag: "${var.function.tag}"
                service_account_id: <service_account_ID>
        ```
    1. Under **Variable settings**, enable the **Canary release** toggle.
    1. In the **Share of requests in canary release** field, specify `50`.
    1. In the **Variables for canary release** field, specify `function.tag`=`canary`.
    1. Click **Create**.
    
- CLI {#cli}

    1. Save the following specification to `spec.yaml`:
        
        ```yaml
        openapi: 3.0.0
        info:
          title: Sample API
          version: 1.0.0

        x-yc-apigateway:
          variables:
            function.tag:
              default: "stable"
              enum:
                - "stable"
                - "canary"

        paths:
          /:
            get:
              x-yc-apigateway-integration:
                type: cloud_functions
                function_id: <function_ID>
                tag: "${var.function.tag}"
                service_account_id: <service_account_ID>
        ```
    1. Run this command:

        ```bash
        yc serverless api-gateway create --name canary --spec=spec.yaml --canary-weight=50 --canary-variables function.tag=canary
        ```

        Where:
       
        * `--name`: API gateway name.
        * `--spec`: Specification file.
        * `--canary-weight`: Percentage of requests in the canary release.
        * `--canary-variables`: Variables for the canary release.

        Result:

        ```text
        done (5s)
        id: d5d1ud9bli1e********
        folder_id: b1gc1t4cb638********
        created_at: "2023-09-25T16:01:48.926Z"
        name: canary
        status: ACTIVE
        domain: d5dm1lba80md********.i9******.apigw.yandexcloud.net
        log_group_id: ckgefpleo5eg********
        connectivity: {}
        log_options:
          folder_id: b1gc1t4cb638********
        canary:
          weight: "50"
          variables:
            function.tag:
              string_value: canary
        ```

- Terraform {#tf}

  To create an API gateway:

  1. Specify the `yandex_api_gateway` properties in the configuration file:

     ```hcl
     resource "yandex_api_gateway" "canary-api-gateway" {
       name        = "canary"
       canary {
         weight    = 50
         variables = {
           function.tag = "canary"
         }
       }
       spec = <<-EOT
         openapi: 3.0.0
          info:
            title: Sample API
            version: 1.0.0

          x-yc-apigateway:
            variables:
              function.tag:
                default: "stable"
                enum:
                  - "stable"
                  - "canary"

          paths:
            /:
              get:
                x-yc-apigateway-integration:
                  type: cloud_functions
                  function_id: <function_ID>
                  tag: "${var.function.tag}"
                  service_account_id: <service_account_ID>
       EOT
     }
     ```

     Where:
     * `name`: API gateway name. The name format is as follows:

        * Length: between 3 and 63 characters.
        * It can only contain lowercase Latin letters, numbers, and hyphens.
        * It must start with a letter and cannot end with a hyphen.

     * `canary.0.weight`: Percentage of requests in the canary release.
     * `canary.0.variables`: Variables for the canary release.
     * `spec`: API gateway specification.

     For more information about resource properties in Terraform, see [this provider guide](../../terraform/resources/api_gateway.md).

  1. Make sure the configuration files are correct.

     1. In the terminal, navigate to the directory where you created your configuration file.
     1. Run a check using this command:

        ```
        terraform plan
        ```

     If the configuration is correct, the terminal will display a list of the resources and their settings. Otherwise, Terraform will show any detected errors. 

  1. Deploy the cloud resources.

     1. If the configuration is correct, run this command:

        ```
        terraform apply
        ```

     1. Confirm creating the resources by typing `yes` and pressing **Enter**.

        This will create all the resources you need in the specified folder. You can check the new resources and their settings using the [management console](https://console.yandex.cloud) or these [CLI](../../cli/quickstart.md) commands:

        ```
        yc serverless api-gateway get <API_gateway_name>
        ```

- API {#api}

  To create an API gateway, use the [create](../apigateway/api-ref/ApiGateway/create.md) REST API method for the [ApiGateway](../apigateway/api-ref/ApiGateway/index.md) resource or the [ApiGatewayService/Create](../apigateway/api-ref/grpc/ApiGateway/create.md) gRPC API call.

{% endlist %}

## Test the application {#test}

Send several requests to the created API gateway. The function version tagged `canary` should handle about half of your requests.

## How to delete the resources you created {#clear-out}

To stop paying for the resources you created:
1. [Delete the API gateway](../operations/api-gw-delete.md).
1. [Delete the function](../../functions/operations/function/function-delete.md).