Zaawansowane polityki w API Management – use case deployment slot

Do napisania tego posta zainspirowało mnie zmiana statusu na GA Azure Functions Deployment Slots, oraz próba jego użycia w aplikacji którą się zajmuję.

W skrócie do czego można wykorzystać „Deployment Slots”? Możemy je użyć do separacji środowisk pre-prod/prod lub też do testów jakiś wybranych funkcjonalności. Są one mocno powiązane z koncepcją Canary Releases lub też Blue-Green Deployment. O co chodzi z obiema koncepcjami zapraszam do podlinkowanych artykułów z blog Martin Fowler.

A teraz po kolei:

Konfiguracja Deployment Slot

WAŻNE: W odróżnieniu od App Service dla Function App możemy utworzyć tylko jeden Deployment Slot który będzie się skalował zależnie od użytego planu np. Consumption. Nie mamy również takich funkcjonalności jak przekierowanie np. 5% ruchu do naszego Slot.

Zakładam, że nasz Deployment Slot jest już utworzony. Przechodzimy do sekcji Manage naszej funkcji gdzie dodajemy Host Key.

Deployment Slot Host key

Gdy dodaliśmy dla naszej Function App API Gateway w postaci API Management to usługa ta utworzyła również swój Host Key w slot „Production”.

APIM Host Key

Konfiguracja instancji API Management

Przejdźmy teraz do naszego API Management i głównego punktu tego artykułu, czyli pisania zaawansowanych polityk.

Całość rozwiązania jest pomyślana w ten sposób aby nasze funkcje/HTTP endpoint-y były „ukryte” za tzw. API Gateway w tym wypadku jest to usługa API Management. Problemem jaki chciałem rozwiązać było przepuszczenie ruchu aplikacji do naszego Deployment Slot w celu testowania nowych funkcjonalności na wybranej grupie użytkowników.

  1. Z uwagi na fakt, że korzystam z APIM w wersji Consumption nie mam adresu IP usługi i nie mogę ustawić Function App na Anonymous, oraz na akceptację tylko lokalnego ruchu (https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook#secure-an-http-endpoint-in-production).
  2. Z uwagi na powyższe w celu „autoryzacji” muszę wykorzystać Function/Host Keys.

Problem ten rozwiązałem tworząc politykę w API Management która na podstawie przekazanego nagłówka kieruje ruch do odpowiedniego endpoint.

WAŻNE: Usługa API Management po utworzeniu z poziomu Function App lub też stworzeniu „link” do Function App identyfikuje usługę po tzw. backend-id.

Nagłówek

Nagłówek w żądaniu HTTP który ma informować o kierowaniu ruchu do naszego Deployment Slot to Canary ustawiony na true. Za tą część odpowiada polityka utworzona w Inbound.

<choose>
<when condition="@(context.Request.Headers.GetValueOrDefault("Canary") == "true")">
    <set-variable name="IsCanaryRelease" value="true" />
</when>
<otherwise>
    <set-variable name="IsCanaryRelease" value="false" />
</otherwise>
</choose>

Polityka ta sprawdza czy w nagłówku jest przekazany odpowiedni parametr i ustawia zmienną „IsCanaryRelease”.

Backend service

Kolejnym krokiem jest skierowanie ruchu do odpowiedniego url lub usługi. Gdy połączenie naszej Function App z API Management zostało wykonane za pomocą „link”. Poprzez dodanie Function App z poziomu APIM 👇.

API Management dodanie Function App

Można też podobny efekt osiągnąć poprzez utworzenie „link” z poziomu Function App 👇.

Function App dodanie API Management

W takiej konfiguracji API Management jest powiązane z naszym backend za pomocą backend-id. Jest on skonfigurowany za pomocą poniższej polityki na poziomie konkretnych HTTP endpoint.

<set-backend-service backend-id="whereismypackage-func" />

Żeby ustawić odpowiednio ruch należy ze wszystkich HTTP endpoint usunąć powyższą politykę, oraz w All operations dodać nową w sekcji Backend.

<choose>
<when condition="@(bool.Parse((string)context.Variables["IsCanaryRelease"]))">
  <set-backend-service base-url="https://whereismypackage-func-staging.azurewebsites.net/api" />
  <set-query-parameter name="code" exists-action="skip">
     <value>{{staging-key}}</value>
  </set-query-parameter>
  <forward-request />
</when>
<otherwise>
  <set-backend-service backend-id="whereismypackage-func" />
  <forward-request />
</otherwise>
</choose>

Polityka choose odpowiada za sprawdzenie wartości zmiennej „IsCanaryRelease” zależnie od jej wartości kierujemy ruch do naszego Deployment Slot (staging) lub też do production slot. Ze względu na „link” pomiędzy APIM i Function App ruch kierowany do production slot jest rozwiązywany za pomocą backend-id z tego też względu nie muszę przekazywać Function/Host key ponieważ usługa robi to za mnie.

WAŻNE: W tym kroku jest przekazywany APIM Host Key.

Bardziej skomplikowana jest polityka służąca za kierowanie ruchu do staging slot ponieważ musimy dodatkowo do URL przekazać w query string parametr z naszym Host Key (staging) który skonfigurowaliśmy na poziomie naszej Function App w Deployment Slot.

<set-backend-service base-url="https://whereismypackage-func-staging.azurewebsites.net/api" />
<set-query-parameter name="code" exists-action="skip">
   <value>{{staging-key}}</value>
</set-query-parameter>

Ostatnią polityką która nam została jest

<forward-request />

Odpowiada ona za wysłanie ruchu do naszego backend.

Podsumowanie

Największą trudnością na jaką trafiłem tworząc to rozwiązanie jest zrozumienie jak to wszystko działa, oraz przestawienie się trochę z C# na ten XML-owy format. Dzięki wykorzystaniu APIM oraz polityk możemy tworzyć bardziej rozbudowane mechanizmy np. skierować tylko 5% ruchu do naszego testowego backend. Co mi da użycie Deployment Slots, oraz APIM na pewno większą pewność co do poprawności działania nowych funkcjonalności dzięki możliwości szybkiego przestawienia ruchu na inne „środowisko” (Swap). Kolejny plus to możliwość stworzenia bardziej bezpiecznego rozwiązania dzięki politykom odpowiadającym za autoryzację.

Share