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?