Skip to content
malak.cloud
  • Kontakt
  • O mnie
  • Search Icon

malak.cloud

Cloud Native na co dzień

Kubernetes, canary deployment i Istio

Kubernetes, canary deployment i Istio

25 maja 2020

Nie ważne czy wdrażasz aplikacje monolityczne czy mikroserwisy. Na pewno przed wypuszczeniem nowej wersji chciałbyś ją przetestować na jakiejś próbce swoich użytkowników. Powiedzmy na 10 procentach. Na czystym Kubernetesie będzie ciężko. Możesz zarządzać liczbą podów w konkretnym deploymencie. Pody podpinasz pod serwis. I to chyba tyle. Pokażę jak zrobić canary deployment w Kubernetes za pomocą Istio.

Deployment

W przykładzie będę używał swojego obrazu dockerowego. Serwis w nim zawarty potrafi między innymi zwracać tekst zdefiniowany w zmiennej środowiskowej RETURN_TEXT. W ten sposób będę mógł łatwo rozróżnić „wersję” aplikacji. Pierwsza z nich będzie zwracała tekst service-1a

Stworzę dwa deploymenty z dwoma wersjami serwisu. Drugi będzie zwracał tekst service-1b

Na początek wrzucimy na klaster nasze zasoby. Dodatkowo tworzymy namespace, które oznaczamy labelką istio-injection: enabled.

apiVersion: v1
kind: Namespace
metadata:
  name: srv
  labels:
    istio-injection: enabled

To spowoduje, że do wszystkich podów deployowanych w tej przestrzeni będą automatycznie wstrzykiwane komponenty Istio.

Pierwszy deployment wygląda następująco:

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: srv
  labels:
    app: mt1
  name: mt1
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mt1
      ver: "1"
  template:
    metadata:
      labels:
        app: mt1
        ver: "1"
    spec:
      containers:
      - image: przemekmalak/multitool
        name: multitool
        env:
          - name: RETURN_TEXT
            value: service-1a

W drugim zmienimy tylko wartość RETURN_TEXT na service-1b oraz labelkę opisującą wersję na 2

 selector:
    matchLabels:
      app: mt1
      ver: "2"
  template:
    metadata:
      labels:
        app: mt1
        ver: "2"

Serwis

Serwis będzie szukał wszystkich podów spełniających warunek:

  selector:
    app: mt1

W ten sposób, oba deploymenty „ubierzemy” w jeden serwis. Ruch będzie rozrzucany pomiędzy obie wersje.

Cały plik yaml z definicją serwisu wygląda tak:

apiVersion: v1
kind: Service
metadata:
  namespace: srv
  labels:
    app: mt1
  name: mt1
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: mt1

Testy

Jeżeli wszystko już mamy w naszym klastrze gotowe możemy przetestować jak wygląda dystrybucja ruchu. W tym celu uruchomię nowego poda, w którym będę miał curla.

kubectl run test --image=przemekmalak/tools --rm -it -- sh

i z wewnątrz tego poda spróbuję kilka razy podłączyć się do naszego serwisu:

for i in `seq 1 10`
do
	curl -m 3 mt1.srv:8080
done

Jak zapewnie zauważyliście ruch został rozłożony po wszystkich podach z obu deploymentów. Ale, tak jak pisałem, ilość requestów przekazywanych do poszczególnych wersji możemy regulować za pomocą ilości podów w poszczególnych deploymentach.

Istio

Zakładam, że samo Istio masz zainstalowane. Jeżeli nie to popatrz tutaj jak to zrobić. To naprawdę tylko kilka kroków. Zainstaluj z profilem demo. To pozwoli potem na zabawę z kilkoma innymi usługami.

Istio dodaje do klastra kilka własnych obiektów, które pozwalają na zarządzanie ruchem. Jednym z kich jest DestinationRule. Za pomocą tego obiektu zdefiniujemy sobie tak zwane subsety. Dwa. Po jednym dla każdej wersji naszej aplikacji. Znowu skorzystamy z labelek w poszczególnych deploymentach.

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  namespace: srv
  name: mt1
spec:
  host: mt1.srv.svc.cluster.local
  subsets:
  - name: mt1
    labels:
      app: mt1
      ver: "1"
  - name: mt2
    labels:
      app: mt1
      ver: "2"

W Destination rule definiujemy między innymi to, co ma się stać z ruchem, który zostanie skierowany w konkretne miejsce. A w te miejsca ruch będzie kierował kolejny obiekt Istio, czyli Virtual Service. To właśnie tutaj zdefiniujemy zasady routingu. Nasze nie są zbyt skomplikowane, mamy tylko jedną ścieżkę. Ale za jego pomocą możemy także zdefiniować jaka część ruchu ma być przesyłana do poszczególnych wersji. W naszym przypadku, prześlemy 80% ruchu do wersji pierwszej i 20% do wersji drugiej.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: mt1
  namespace: srv
spec:
  hosts:
  - mt1.srv.svc.cluster.local
  http:
  - match:
    - uri:
        prefix: /
    route:
      - destination:
          host: mt1.srv.svc.cluster.local
          subset: mt1
          port:
            number: 8080
        weight: 80
      - destination:
          host: mt1.srv.svc.cluster.local
          subset: mt2
          port:
            number: 8080
        weight: 20

Dodajemy oba obiekty do klastra i spróbujmy ponownie sprawdzić jak kierowany jest ruch. Tym razem już przez Istio. Ponownie tworzymy dodatkowego poda kubectl run test --image=przemekmalak/tools --rm -it -n srv -- sh

Zwróćcie uwagę, że tworzę go w przestrzeni nazw srv. I ponownie, wewnątrz poda wykonujemy:

for i in `seq 1 10`
do
	curl -m 3 mt1.srv.svc.cluster.local
done

I w efekcie powinniśmy dostać coś zbliżonego do

20% ruchu poszło do wersji 2, a 80% do wersji pierwszej.

Dla leniwych

Dołączam dwa pliki, które możecie wykorzystać. Po rozpakowaniu wystarczy wykonać dwa polecenia: kubectl apply -f 1_services.yaml oraz kubectl apply -f 2_virtual_services.yaml

Po chwili na klastrze powinniście mieć nasze serwisy i dodatkowy pod o nazwie debug , z którego możecie sprawdzić jak rozrzucany jest ruch.


DEV, Istio, k8s
Dev, Docker, k8s, mesh

Post navigation

PREVIOUS
Certified Kubernetes Application Developer
NEXT
etcdctl w kontenerze
Comments are closed.
Cześć. Nazywam się Przemek Malak. Dzięki za wizytę. Mam nadzieję, że to o czym piszę Cię zainteresowało. Jeżeli chcesz ze mną pogadać, najłatwiej będzie przez LinkedIn.

Losowe wpisy

  • Dane w plikach CSV, JSON i SQL? Tak. AWS Athena

    22 września 2017
  • Jak za pomocą funkcji Lambda włączyć i wyłączyć serwer EC2 w AWS

    25 października 2017
  • Step Functions i obsługa błędów

    22 października 2022
  • AWS Lambda i idempotentność

    21 marca 2022
  • AWS Step Functions

    13 lutego 2018
  • Apps
  • AWS
  • CloudNative
  • Cookbook
  • Data
  • DEV
  • GCP
  • IoT
  • Istio
  • k8s
  • Security
  • Social
  • GitHub
  • LinkedIn
© 2023   All Rights Reserved.