Automatyczne skalowanie oparte na żądaniach HTTP na K8S przy użyciu Prometheus i Keda na NSIS Cloud
Autoskaler podów Kubernetes (HPA) wykorzystuje natywnie metryki użycia CPU i pamięci RAM jako domyślne parametry wyzwalające zwiększanie lub zmniejszania liczby podów. Chociaż często jest to wystarczające, mogą istnieć przypadki, w których preferowane jest skalowanie na podstawie niestandardowych metryk.
KEDA to narzędzie do automatycznego skalowania w oparciu o zdarzenia/metryki dostarczane przez popularne źródła/technologie, takie 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 w 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 oraz 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 zostanie omówione?
Instalacja NGINX ingress na klastrze Magnum
Instalacja aplikacji Prometheus
Instalacja aplikacji Keda
Wdrożenie przykładowej aplikacji
Wdrożenie naszej aplikacji ingress
Dostęp do pulpitu Prometheus
Wdrożenie KEDA ScaledObject
Test z użyciem Locust
Wymagania wstępne
- Nr 1 Konto
Jest wymagane konto hostingowe NSIS z dostępem do interfejsu Horizon: https://horizon.cloudferro.com.
Nr 2 Utworzenie nowego klastra Kubernetes bez preinstalowanego Magnum NGINX z poziomu Horizon UI.
Domyślne wdrożenie NGINX ingress z Magnum z poziomu Horizon UI nie implementuje jeszcze eksportowania metryk Prometheus. Zamiast próbować skonfigurować ingress Magnum dla tego przypadku, raczej zainstalujemy nową instancję NGINX ingress. 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 wskazujący na klaster Kubernetes
Poniższy artykuł przedstawia opcje tworzenia nowego klastra i wykonania 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 pakietów charm Helm
Poniższy artykuł wprowadza w zagadnienie pakietów chart Helm na platformie Kubernetes:
Wdrażanie Helm Charts na klastrach Magnum Kubernetes w chmurze NSIS
Instalacja NGINX ingress na klastrze Magnum
Wpisz następujące polecenia, aby pobrać repozytorium Helm ingress-nginx, a następnie zainstalować wykres Helm. 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 adres 64.225.135.67. Zamiast tej wartości użyj wartości EXTERNAL-IP, którą otrzymasz w terminalu po uruchomieniu powyższego polecenia.
Instalacja aplikacji Prometheus
Aby zainstalować aplikację 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 jest instalowana w przestrzeni nazw ingress-nginx, więc nie ma potrzeby podawania flagi przestrzeni nazw ani jej tworzenia.
Instalacja aplikacji 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ć uzyskać 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 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 wykonaj polecenie:
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 go własnym adresem floating IP z sufiksem /app), możemy zobaczyć, że aplikacja jest dostępna. 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.
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 sprawdzić 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 w przeglądarce localhost:9090, zostanie wyświetlony pulpit nawigacyjny Prometheus. W tym widoku będzie można 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.
Wdrożenie KEDA ScaledObject
Keda ScaledObject to niestandardowy zasób, który umożliwi skalowanie 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ę triggera, 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 ono wyraźnie przypisanej wartości, będzie obowiązywać jego domyślna wartość 300 sekund, jednak zobacz poniżej, jak możesz zmienić tę wartość.
Używamy tutaj do skalowania metryki nginx-ingress-controller-requests. 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 liczby żądań większej niż 100 na pod w ciągu minuty, spowoduje to zwiększenie skali.
kubectl apply -f scaled-object.yaml -n ingress-nginx
Test z użyciem 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 load balancer, 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 load balancer zostaje utworzony, a Locust zostaje udostępniony:
$ 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 interfejsu graficznego Locust 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 przycisk „Start Swarming”, aby zainicjować pozorowaneżądana na publicznym punkcie końcowym naszej aplikacji:
Przy domyślnych ustawieniach i nawet jednym użytkowniku, Locust natychmiast zacznie obsługiwać setki żądań. Dostrajanie aplikacji Locust 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
...
Redukcja
Po naciśnięciu przycisku „Stop” w Locust, pody 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