Niedawno przestawiliśmy nasze środowisko produkcyjne na Kubernetes. Chciałbym wymusić ograniczenia procesorów dla kontenerów. Dostaję sprzeczne miary procesora, które nie pasują do siebie. Oto moja konfiguracja:
- Agenci DataDog działający jako
Daemonset
- Istniejące aplikacje działające bez limitów procesora
- Kontenery, o których mowa, to wielowątkowe aplikacje Ruby
- Dwie metryki:
kubernetes.cpu.usage.{avg,max}
idocker.cpu.usage
c4.xlarge
węzły klastra (4 vCPU lub 4000 m w kategoriach Kubernetes)
kubernetes.cpu.usage.max
zgłasza ~ 600m dla danych kontenerów. docker.cpu.usage
zgłasza ~ 60%. Wynika z tego, że limit 1000m procesora byłby większy niż wystarczająca pojemność podczas normalnej pracy.
Ustawiłem limit na 1000m. Potem docker.container.throttles
znacząco wzrasta kubernetes.cpu.usage.max
i docker.cpu.usage
pozostaje taki sam. W tym czasie cały system upadł na kolana. To nie ma dla mnie sensu.
Zbadałem statystyki Dockera. Wydaje się, że docker stats
(i podstawowy API) normalizują obciążenie zgodnie z rdzeniami procesora. Tak więc w moim przypadku docker.cpu.usage
60% to (4000m * 0,60) do 2400m w kategoriach Kubernetes. Nie ma to jednak związku z żadnymi liczbami Kubernetes. Zrobiłem kolejny eksperyment, aby sprawdzić moją hipotezę, że liczby Kubernetesa są nieprawidłowe. Ustawiłem limit na 2600 m (dla dodatkowego miejsca nad głową). Nie spowodowało to żadnych przepustnic. Jednak Kubernetes zauważył, że użycie procesora się nie zmieniło. To mnie dezorientuje.
Więc moje pytania to:
- Czy to wygląda jak błąd w Kubernetes (czy coś w stosie?)
- Czy moje rozumowanie jest prawidłowe?
Moje dalsze pytanie dotyczy tego, jak poprawnie określić procesor dla aplikacji Ruby. Jeden pojemnik wykorzystuje Pumę. Jest to wielowątkowy serwer WWW z konfigurowalną liczbą wątków. Żądania HTTP są obsługiwane przez jeden z wątków. Druga aplikacja to serwer oszczędnościowy korzystający z serwera wątkowego. Każde przychodzące połączenie TCP jest obsługiwane przez własny wątek. Wątek kończy się, gdy połączenie zostanie zamknięte. Ruby jako GIL (Global Interpreter Lock), więc tylko jeden wątek może wykonywać kod Ruby jednocześnie. To pozwala na wiele wątków wykonujących operacje we / wy i takie tam.
Myślę, że najlepszym rozwiązaniem jest ograniczenie liczby wątków działających w każdej aplikacji i przybliżenie limitów procesora Kubernetes na podstawie liczby wątków. Procesy nie rozwidlają się, więc trudniej jest przewidzieć całkowite użycie procesora.
Pytanie brzmi: jak właściwie przewidzieć wykorzystanie procesora i ograniczenia dla tych aplikacji?
źródło
Odpowiedzi:
Wiele rzeczy tutaj:
Jesteś na AWS ec2, dlatego cokolwiek robisz na instancji w celu pomiaru procesora, oblicza procesor na poziomie hiperwizora, a nie na poziomie instancji. W tym celu uruchom dowolny test obciążenia i sprawdź iostat -ct 1 oraz użycie procesora w chmurze. Zużycie procesora w chmurze jest zawsze o 10-20% większe niż to, co zgłosi iostat, a to dlatego, że iostat da użycie procesora na poziomie hiperwizora.
Jako okno dokowane, aby zobaczyć, jak porównywane są kubernetes i metryki dokowania, sugeruję uruchomienie kontenerów z opcją --cpuset = 1 lub dowolną liczbą, aby umożliwić wszystkim kontenerom używanie tylko jednego vCPU.
Również w AWS 1 CPU = 2vcpu. Jest hipertekstowany do 2. Możesz to wziąć pod uwagę podczas obliczania.
Wreszcie najlepszą miarą do wykorzystania użycia procesora dla konkretnej aplikacji jest użycie htopa i korelacja z parametrami cloudwatch.
Zauważyłem też czasami, że demon dokujący przyczepia się do jednego z wirtualnych procesorów, a zatem, gdy redukujesz go do 1000 m, być może cała konfiguracja zwalnia, ponieważ redukcja odbywa się na jednym z vpcus. Możesz użyć mpstat, aby uzyskać szczegółowe informacje na ten temat.
Wreszcie na poziomie hosta możesz przypiąć dokerkę do jednego procesora i obserwować więcej.
Mam nadzieję, że zbliży cię to nieco. Zaktualizuj mnie, jeśli już znalazłeś rozwiązanie.
źródło