Skip to main content
  • »
  • KUBERNETES »
  • Autoskalowanie oparte na żądaniach HTTP na K8S przy użyciu Prometheus i Keda na NSIS

Autoskalowanie oparte na żądaniach HTTP na K8S przy użyciu Prometheus i Keda na NSIS

Autoskaler podów Kubernetes (HPA) natywnie wykorzystuje metryki CPU i RAM jako domyślne wyzwalacze dla zwiększania lub zmniejszania liczby podów. Chociaż często jest to wystarczające, mogą istnieć przypadki użycia, w których preferowane jest skalowanie na podstawie niestandardowych metryk.

KEDA to narzędzie do automatycznego skalowania w oparciu o zdarzenia/metryki dostarczane z popularnych źródeł/technologii, takich jak Prometheus, Kafka, Postgres i wiele innych.

W tym artykule wdrożymy przykładową aplikację w chmurze NSIS. Będziemy zbierać żądania HTTP z NGINX Ingress na naszym klastrze Kubernetes i, używając Keda ze skalerem Prometheus, zastosujemy niestandardowe skalowanie oparte na żądaniach HTTP.

Informacja

Użyjemy NGINX web server do zademonstrowania aplikacji i NGINX ingress do jej wdrożenia i zbierania metryk. Należy pamiętać, że NGINX web server i NGINX ingress to dwa oddzielne elementy oprogramowania, mające dwa różne cele.

Co będziemy omawiać

  • Zainstaluj NGINX ingress na klastrze Magnum

  • Zainstaluj Prometheus

  • Zainstaluj Keda

  • Wdrożenie przykładowej aplikacji

  • Wdrożenie naszej aplikacji ingress

  • Dostęp do pulpitu Prometheus

  • Wdrożenie KEDA ScaledObject

  • Test z Locust

Wymagania wstępne

Nr 1 Konto

Potrzebne jest konto hostingowe NSIS z dostępem do interfejsu Horizon: https://horizon.cloudferro.com.

Nr 2 Utwórz nowy klaster Kubernetes bez preinstalowanego Magnum NGINX z Horizon UI.

Domyślny ingress NGINX wdrożony z Magnum z Horizon UI nie implementuje jeszcze eksportu metryk Prometheus. Zamiast próbować skonfigurować ingress Magnum dla tego przypadku użycia, raczej zainstalujemy nowy ingress NGINX. Aby uniknąć konfliktów, najlepiej postępować zgodnie z poniższą instrukcją na klastrze Kubernetes bez Magnum NGINX preinstalowanego z Horizon UI.

Nr 3 kubectl wskazał klaster Kubernetes

Poniższy artykuł zawiera opcje tworzenia nowego klastra i aktywacji polecenia kubectl:

Jak uzyskać dostęp do klastra Kubernetes po wdrożeniu przy użyciu Kubectl na NSIS OpenStack Magnum?.

Jak wspomniano, utwórz klaster bez instalowania opcji NGINX ingress.

Nr 4 Znajomość obsługi wykresów Helm

W tym artykule przedstawiono wykresy Helm na platformie Kubernetes:

Wdrażanie Helm Charts na klastrach Magnum Kubernetes w chmurze NSIS Cloud

Zainstaluj NGINX ingress na klastrze Magnum

Wpisz następujące polecenia, aby pobrać repozytorium Helm ingress-nginx, a następnie zainstaluj wykres. Należy pamiętać, że używamy niestandardowej przestrzeni nazw ingress-nginx, a także ustawiamy opcje, aby włączyć metryki Prometheus.

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

kubectl create namespace ingress-nginx

helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--set controller.metrics.enabled=true \
--set-string controller.podAnnotations."prometheus\.io/scrape"="true" \
--set-string controller.podAnnotations."prometheus\.io/port"="10254"

Teraz uruchom następujące polecenie, aby uzyskać zewnętrzny adres IP kontrolera ingress, który będzie używany przez zasoby ingress utworzone w dalszych krokach tego artykułu.

$ kubectl get services -n ingress-nginx
NAME                      TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                      AGE
ingress-nginx-controller  LoadBalancer   10.254.118.18    64.225.135.67   80:31573/TCP,443:30786/TCP   26h

Otrzymamy 64.225.135.67. Zamiast tej wartości użyj wartości EXTERNAL-IP, którą otrzymasz w terminalu po uruchomieniu powyższego polecenia.

Zainstaluj Prometheus

Aby zainstalować Prometheus, należy wykonać następujące polecenie na klastrze:

kubectl apply --kustomize github.com/kubernetes/ingress-nginx/deploy/prometheus/

Należy pamiętać, że jest to instalacja Prometheus dostosowana do NGINX Ingress i już domyślnie instaluje się w przestrzeni nazw ingress-nginx, więc nie ma potrzeby podawania flagi przestrzeni nazw ani jej tworzenia.

Zainstaluj Keda

Wykonując poniższe kroki, utwórz oddzielną przestrzeń nazw dla artefaktów Keda, pobierz repozytorium i zainstaluj wykres Keda-Core:

kubectl create namespace keda

helm repo add kedacore https://kedacore.github.io/charts
helm repo update

helm install keda kedacore/keda --version 2.3.0 --namespace keda

Wdrożenie przykładowej aplikacji

Po wykonaniu powyższych kroków możemy wdrożyć prostą aplikację. Będzie to serwer WWW NGINX, obsługujący prostą stronę „Welcome to nginx!”. Uwaga, tworzymy wdrożenie, a następnie udostępniamy je jako usługę typu ClusterIP. Utwórz plik app-deployment.yaml w swoim ulubionym edytorze:

app-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  type: ClusterIP
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

Następnie zastosuj poniższe polecenie:

kubectl apply -f app-deployment.yaml -n ingress-nginx

Wdrażamy tę aplikację w przestrzeni nazw ingress-nginx, w której hostowana jest również instalacja ingress i Prometheus. W przypadku scenariuszy produkcyjnych możesz chcieć mieć lepszą izolację aplikacji od infrastruktury, jednak wykracza to poza zakres tego artykułu.

Wdrożenie naszej aplikacji ingress

Nasza aplikacja jest już uruchomiona i udostępniona w naszym klastrze, ale chcemy również udostępnić ją publicznie. W tym celu użyjemy NGINX ingress, który będzie również działał jako proxy do rejestrowania metryk żądań. Utwórz plik app-ingress.yaml z następującą zawartością:

app-ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: "64.225.135.67.nip.io"
    http:
      paths:
      - backend:
          service:
            name: nginx
            port:
              number: 80
        path: /app
        pathType: Prefix

Następnie zastosuj:

kubectl apply -f app-ingress.yaml -n ingress-nginx

Po chwili można uzyskać publiczny adres IP, pod którym aplikacja jest dostępna:

$ kubectl get ingress -n ingress-nginx
NAME           CLASS   HOSTS                  ADDRESS         PORTS   AGE
app-ingress    nginx   64.225.135.67.nip.io   64.225.135.67   80      18h

Po wpisaniu adresu IP z prefiksem (zastąp własnym pływającym adresem IP z sufiksem /app), możemy zobaczyć odsłoniętą aplikację. Używamy usługi nip.io, która działa jako resolver DNS, więc nie ma potrzeby konfigurowania rekordów DNS do celów demonstracyjnych.

../_images/welcome_nginx.png

Dostęp do pulpitu Prometheus

Aby uzyskać dostęp do pulpitu Prometheus, możemy przekierować port działającego serwera prometheus na nasz localhost. Może to być przydatne do rozwiązywania problemów. Mamy prometheus-server działający jako usługa NodePort, co można zweryfikować poniżej:

$ kubectl get services -n ingress-nginx
NAME                                 TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.254.3.172     64.225.135.67   80:30881/TCP,443:30942/TCP   26h
ingress-nginx-controller-admission   ClusterIP      10.254.51.201    <none>          443/TCP                      26h
ingress-nginx-controller-metrics     ClusterIP      10.254.15.196    <none>          10254/TCP                    26h
nginx                                ClusterIP      10.254.160.207   <none>          80/TCP                       25h
prometheus-server                    NodePort       10.254.24.85     <none>          9090:32051/TCP               26h

W poniższym poleceniu przekierujemy port do lokalnego hosta:

kubectl port-forward deployment/prometheus-server 9090:9090 -n ingress-nginx

Następnie wpisz localhost:9090 w przeglądarce, a zobaczysz pulpit nawigacyjny Prometheus. W tym widoku będziemy mogli zobaczyć różne metryki udostępniane przez nginx-ingress. Można to zweryfikować, wpisując „nginx-ingress” w pasku wyszukiwania, a następnie zaczną pojawiać się różne powiązane metryki.

../_images/prometheus-dashboard_9090.png

Wdrożenie KEDA ScaledObject

Keda ScaledObject to niestandardowy zasób, który umożliwi skalowanie naszej aplikacji w oparciu o niestandardowe metryki. W manifeście YAML definiujemy, co będzie skalowane (wdrożenie nginx), jakie są warunki skalowania oraz definicję i konfigurację wyzwalacza, w tym przypadku Prometheus. Przygotuj plik scaled-object.yaml z następującą zawartością:

scaled-object.yaml

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: prometheus-scaledobject
  namespace: ingress-nginx
  labels:
    deploymentName: nginx
spec:
  scaleTargetRef:
    kind: Deployment
    name: nginx # name of the deployment, must be in the same namespace as ScaledObject
  minReplicaCount: 1
  pollingInterval: 15
  triggers:
  - type: prometheus
    metadata:
      serverAddress: http://prometheus-server.ingress-nginx.svc.cluster.local:9090
      metricName: nginx_ingress_controller_requests
      threshold: '100'
      query: sum(rate(nginx_ingress_controller_requests[1m]))

Szczegółowa definicja ScaledObject znajduje się w dokumentacji Keda. W tym przykładzie pomijamy wiele ustawień domyślnych, z których najbardziej godnym uwagi jest coolDownPeriod. Ponieważ nie ma ona wyraźnie przypisanej wartości, jej domyślna wartość 300 sekund będzie obowiązywać, jednak zobacz poniżej, jak możesz zmienić tę wartość na coś innego.

Używamy tutaj metryki nginx-ingress-controller-requests do skalowania. Ta metryka pojawi się na pulpicie nawigacyjnym Prometheus dopiero wtedy, gdy żądania zaczną trafiać do naszej usługi aplikacji. Ustawiamy próg na 100 i czas na 1 minutę, więc w przypadku większej liczby żądań niż 100 na kapsułę w ciągu minuty, spowoduje to zwiększenie skali.

kubectl apply -f scaled-object.yaml -n ingress-nginx

Test z Locust

Możemy teraz przetestować, czy skalowanie działa zgodnie z oczekiwaniami. Wykorzystamy do tego Locust, który jest narzędziem do testowania obciążenia. Aby szybko wdrożyć Locust jako typ usługi LoadBalancer, wprowadź następujące polecenia:

kubectl create deployment locust --image paultur/locustproject:latest
kubectl expose deployment locust --type LoadBalancer --port 80 --target-port 8089

Po kilku minutach LoadBalancer zostaje utworzony, a Locust zostaje odsłonięty:

$ kubectl get services
NAME         TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)        AGE
kubernetes   ClusterIP      10.254.0.1     <none>           443/TCP        28h
locust       LoadBalancer   10.254.88.89   64.225.132.243   80:31287/TCP   4m19s

Wejdź do Locust UI w przeglądarce używając EXTERNAL-IP. Może to być tylko 64.225.132.243 lub 64.225.132.243.nip.io, jedna z tych wartości na pewno zadziała. Następnie naciśnij „Start Swarming”, aby zainicjować mock requesty na publicznym punkcie końcowym naszej aplikacji:

../_images/locust_test.png

Przy domyślnych ustawieniach i nawet jednym użytkowniku, Locust natychmiast zacznie roić się od setek żądań. Dostrajanie Locusta nie wchodzi w zakres tego artykułu, ale możemy szybko zobaczyć efekt. Generowane są dodatkowe repliki podów:

$ kubectl get pods -n ingress-nginx
NAME                                        READY   STATUS              RESTARTS   AGE
ingress-nginx-controller-557bf68967-h9zf5   1/1     Running             0          27h
nginx-85b98978db-2kjx6                      1/1     Running             0          30s
nginx-85b98978db-2kxzz                      1/1     Running             0          61s
nginx-85b98978db-2t42c                      1/1     Running             0          31s
nginx-85b98978db-2xdzw                      0/1     ContainerCreating   0          16s
nginx-85b98978db-2zdjm                      1/1     Running             0          30s
nginx-85b98978db-4btfm                      1/1     Running             0          30s
nginx-85b98978db-4mmlz                      0/1     ContainerCreating   0          16s
nginx-85b98978db-4n5bk                      1/1     Running             0          46s
nginx-85b98978db-525mq                      1/1     Running             0          30s
nginx-85b98978db-5czdf                      1/1     Running             0          46s
nginx-85b98978db-5kkgq                      0/1     ContainerCreating   0          16s
nginx-85b98978db-5rt54                      1/1     Running             0          30s
nginx-85b98978db-5wmdk                      1/1     Running             0          46s
nginx-85b98978db-6tc6p                      1/1     Running             0          77s
nginx-85b98978db-6zcdw                      1/1     Running             0          61s
...

Chłodzenie

Po naciśnięciu „Stop” w Locust, strąki będą skalowane w dół do jednej repliki, zgodnie z wartością parametru coolDownPeriod, który jest zdefiniowany w Keda ScaledObject. Jego domyślna wartość to 300 sekund. Jeśli chcesz ją zmienić, użyj polecenia

kubectl edit scaledobject prometheus-scaledobject -n ingress-nginx