CPU steal time na VPS: vizinho ruidoso ou sobrecarga?
Entenda o CPU steal time, leia a coluna st do vmstat e diferencie um vizinho ruidoso de sobrecarga real na sua VPS, sem confundir espera de CPU com I/O.
O que o CPU steal time mede realmente
O CPU steal time é a parcela de tempo em que a sua CPU virtual estava pronta para executar, sem nada pendente, enquanto o hypervisor atribuía o core físico a outro guest. O trabalho estava em fila. O core estava a executar noutro guest. O Linux contabiliza esses ciclos separadamente e apresenta-os como st. Assim, é possível distinguir entre “o meu servidor está ocupado” e “o meu servidor está à espera da sua vez”.
Essa diferença é precisamente a razão pela qual este contador existe. O tempo que os seus próprios processos passam na CPU é apresentado como us (user) ou sy (system). O tempo que uma tarefa passa bloqueada à espera de armazenamento é apresentado como wa (I/O wait). Uma vCPU (CPU virtual) que está executável, na run queue, sem operações de I/O pendentes e ainda assim não está a executar é apresentada como st. Nada dentro do seu servidor pode eliminar esse estado, porque a decisão de escalonamento é tomada uma camada abaixo, no host.
Isto resulta diretamente de como uma VPS partilha uma máquina física entre vários guests. A causa habitual é um vizinho: outro guest no mesmo node está a usar intensivamente a CPU, por isso o host divide os cores entre os guests. Existe uma segunda causa que muitas vezes passa despercebida. Muitos providers limitam uma vCPU partilhada a uma fração de um core físico e, em vários hypervisors, esse limite imposto é contabilizado como steal dentro do guest. Portanto, uma leitura elevada de st indica que o core não lhe foi atribuído. Não indica sempre quem o estava a utilizar.
De onde vem o valor de steal
O seu kernel não consegue medir steal sozinho, porque não consegue ver o host. O hypervisor fornece esse valor. No KVM, o host escreve um contador por vCPU numa página partilhada com o guest, e o guest soma-o quando o kernel é compilado com CONFIG_PARAVIRT_TIME_ACCOUNTING, como acontece com todos os kernels das distribuições. O Xen comunica o mesmo através da sua área de estado de execução. O total chega ao userspace num único local:
head -1 /proc/statEssa linha cpu contém dez contadores, em ticks de USER_HZ desde o arranque, pela seguinte ordem: user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice. Steal é o oitavo valor depois do rótulo. Todas as ferramentas abaixo, vmstat, top, mpstat e qualquer exporter do Prometheus, leem esse mesmo campo e transformam duas amostras numa percentagem.
Uma consequência é mais importante do que as restantes. Se o hypervisor nunca exportar o contador, o campo permanece sempre a zero, e todas as ferramentas baseadas nele indicam um 0.0 tranquilo enquanto o host está sobrecarregado. O KVM e o Xen exportam esse valor. Os guests em VMware e Hyper-V normalmente apresentam um zero constante. Verifique a plataforma antes de confiar num zero:
systemd-detect-virtEste comando apresenta o nome da plataforma, como kvm, xen, vmware ou microsoft, e none em bare metal. Dentro de um container, apresenta o runtime em vez disso, como lxc, docker ou podman, o que fornece informação sobre o container, não sobre a máquina subjacente. Em kvm, um zero é uma evidência real de que o host está a disponibilizar recursos adequados. Numa plataforma que nunca preenche esse campo, um zero não é evidência de nada, e a contenção tem de ser avaliada medindo o tempo de execução de trabalho real.
Como verificar o tempo de CPU steal numa VPS?
vmstat vem do pacote procps. Está presente em quase todas as imagens de VPS Ubuntu e Debian, mas pode faltar em algumas imagens mínimas de contentores. Instale-o antes de depender dele.
sudo apt-get update
sudo apt-get install -y procps
vmstat --version
vmstat 1 5vmstat --version apresenta uma linha como vmstat from procps-ng 4.0.4. Se essa linha for apresentada, a ferramenta está instalada e está a ler contadores reais do kernel. vmstat 1 5 recolhe depois uma amostra por segundo, cinco vezes.
procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu-------
r b swpd free buff cache si so bi bo in cs us sy id wa st gu
1 0 0 3216484 98304 1284360 0 0 4 18 62 110 3 1 96 0 0 0
2 0 0 3216232 98304 1284360 0 0 0 0 248 431 6 2 84 0 8 0Procure a coluna st no bloco cpu, à direita. As versões atuais do procps-ng apresentam uma coluna gu depois dela para o tempo do guest KVM. Por isso, st é a segunda coluna a contar da direita, e não a última. Leia a coluna pelo nome do cabeçalho, porque essa posição mudou entre versões.
Duas práticas mantêm a leitura correta. A primeira linha de dados é a média desde o arranque, por isso ignore-a e leia as linhas seguintes. Uma única amostra também não é uma medição, porque o steal ocorre em rajadas. Execute vmstat 1 60 e monitorize um minuto completo antes de tirar conclusões.
top apresenta o mesmo valor na linha de resumo %Cpu(s), no campo identificado por st:
%Cpu(s): 6.2 us, 2.1 sy, 0.0 ni, 83.9 id, 0.0 wa, 0.0 hi, 0.3 si, 7.5 stPara obter detalhes por núcleo, adicione sysstat:
sudo apt-get install -y sysstat
mpstat -P ALL 1 5mpstat apresenta uma linha por CPU com uma coluna %steal. Essa coluna mostra se todas as vCPU são afetadas ou apenas uma. Para obter o histórico necessário num pedido de suporte, guarde as amostras em vez de as ler no ecrã:
date -u | tee -a ~/steal.log
mpstat -P ALL 1 5 | tee -a ~/steal.logExecute esse comando a partir do cron durante as horas em que suspeita do problema. O ficheiro permite substituir a afirmação "esteve lento ontem à noite" pelos dez minutos exatos do problema.
O que significam os valores de steal?
- Um
0.0estável. O estado é saudável ou a plataforma não comunica qualquer steal. Confirme comsystemd-detect-virtantes de tirar conclusões. - Picos de alguns por cento durante alguns segundos. É normal em qualquer nó partilhado. Uma compilação de outro cliente começa ou o host executa as cópias de segurança.
- De 1 a 5 por cento de forma sustentada num plano partilhado. É esperado. O preço reflete a CPU partilhada.
- De 5 a 10 por cento de forma sustentada. É uma redução de desempenho mensurável. Comece a recolher evidências e compare as mesmas horas ao longo de vários dias.
- Acima de 10 por cento durante várias horas seguidas. O nó está sobrecarregado para a sua carga de trabalho. Este é o nível que justifica abrir um pedido de suporte ou mudar de nó.
Use estes intervalos como orientação, não como uma especificação, porque nenhum fornecedor publica uma garantia de steal num plano partilhado. Avalie-os em função do que executa. Um trabalho em lote noturno pode absorver 15 por cento de steal sem que alguém note. Um serviço sensível à latência apresenta o efeito no p99 muito antes de a média parecer preocupante. Por isso, cargas de trabalho sensíveis à latência, como bots de negociação devem usar cores dedicados.
Quanto custa o steal time?
A aritmética é curta. Se uma fração s do seu tempo de CPU for ocupada por outros processos, uma tarefa que precisa de uma quantidade fixa de CPU demora 1 / (1 - s) vezes mais tempo de relógio. Para uma tarefa que precisa de 60 segundos de CPU:
The data behind this chart
[
{
"steal_percent": 0,
"wall_clock_seconds": "60.0"
},
{
"steal_percent": 3,
"wall_clock_seconds": "61.9"
},
{
"steal_percent": 8,
"wall_clock_seconds": "65.2"
},
{
"steal_percent": 15,
"wall_clock_seconds": "70.6"
},
{
"steal_percent": 25,
"wall_clock_seconds": "80.0"
},
{
"steal_percent": 40,
"wall_clock_seconds": "100.0"
}
]A 3 por cento, um valor normal num plano partilhado, essa tarefa demora 61.9 segundos em vez de 60.0. Ninguém abre um ticket por causa disso. A 8 por cento, demora 65.2 segundos. A 40 por cento, a mesma tarefa precisa de 100.0 segundos, e uma fila que antes era processada começa a crescer.
Estes são valores calculados, não medições. O modelo assume uma única thread executável e que o steal é distribuído uniformemente pelo intervalo. Os serviços reais muitas vezes têm um desempenho pior do que a curva indica, porque um intervalo de CPU roubado ocorre a meio de um pedido e o atraso é depois suportado novamente por tudo o que está à espera desse pedido. Para obter o seu próprio valor em vez de usar uma fórmula, faça um benchmark da VPS durante uma hora tranquila e novamente durante uma hora movimentada, registando st nas duas janelas.
É steal ou é outra coisa?
É fácil confundir steal com outros sintomas. Leia os contadores em conjunto, na mesma linha vmstat.
stalto, enquantoreuspermanecem baixos: o host não lhe está a disponibilizar o core. Isso é steal.rbem acima do número de vCPUs, comusalto estpróximo de zero: está a executar mais trabalho do que os seus próprios CPUs conseguem processar. Comparercom o resultado denproc. Isto é oversubscription da sua própria carga, não de um vizinho.waalto, comstpróximo de zero: as tarefas estão bloqueadas no armazenamento. É um problema diferente, com uma correção diferente.- Load average alto, enquanto
steusestão ambos baixos: o valor de load também contabiliza tarefas não interrompíveis. Isto normalmente aponta para um dispositivo bloqueado ou uma montagem de rede bloqueada, e não para a CPU.
Os planos burstable merecem uma nota própria. Fornecem um saldo de créditos que aumenta enquanto está inativo e diminui enquanto está ocupado. Quando o saldo termina, o fornecedor limita a instância a uma taxa base. Em algumas plataformas, esse throttling é reportado como steal. Noutras, é invisível a partir do sistema e simplesmente obtém menos ciclos por segundo. Leia a descrição do plano antes de concluir que a causa é um vizinho.
Por que um container não apresenta steal time
Steal é uma propriedade da máquina virtual, não de um container executado dentro dela. Um container Docker no seu próprio VPS partilha o /proc do host, portanto o valor de st lido dentro dele corresponde ao steal do VPS, que é o valor pretendido. A virtualização baseada em containers, comercializada como VPS, funciona de forma diferente. Com o lxcfs em uso, o valor de /proc/stat dentro do container é sintetizado a partir da contabilização do cgroup, e o steal é zero por definição. Uma stack de monitorização que recolhe métricas apenas a partir do interior pode apresentar um zero estável e aparentemente normal enquanto a máquina física subjacente está sem capacidade de CPU.
Dentro de um container, o contador com significado equivalente é o throttling da quota de CPU. No cgroup v2:
cat /sys/fs/cgroup/cpu.statnr_throttled contabiliza os períodos de imposição em que o grupo atingiu a sua quota de CPU, e throttled_usec totaliza o tempo durante o qual ficou congelado. Um nr_throttled crescente significa que o processo estava pronto para executar, mas não estava a executar. A experiência é a mesma do steal, mas é causada por um limite definido por si. Verifique os seus próprios limites antes de culpar o host, sobretudo se executar os seus serviços em Docker num VPS com limites de CPU no ficheiro compose. A virtualização em camadas acrescenta outro ponto onde o tempo pode desaparecer, porque uma VM dentro do seu VPS acumula o steal do VPS e o seu próprio atraso de agendamento. Tenha isto em conta se utilizar virtualização aninhada num VPS.
O que fazer em caso de steal persistente
Nenhuma definição dentro do guest corrige o steal, porque o scheduler que toma essa decisão é executado fora do guest. Há quatro medidas eficazes.
Recolha primeiro as evidências. Registe os timestamps em UTC, a duração de cada episódio, a frequência com que se repete e se mpstat mostra uma vCPU afetada ou todas. Uma semana de amostras registadas vale mais do que uma captura de ecrã.
Abra um ticket com esses dados. Faça duas perguntas diretas: este node está oversubscribed durante estas janelas e a minha instance pode ser movida? Cole o output de vmstat e as horas exatas. Os providers atuam com base numa janela reproduzível, e um ticket que apenas diga que o servidor está lento recebe como resposta um pedido desses dados. A quantidade deste trabalho que pode transferir para o provider é uma das diferenças práticas entre um VPS gerido e um VPS não gerido.
Peça uma migração. Mover um guest para um node menos carregado é uma operação habitual para um provider e normalmente implica apenas um reboot curto. Esta é a correção que não tem custo e resolve o caso comum, em que um node fica com vários vizinhos pesados ao mesmo tempo.
Compre uma configuração sem contention. Um plano com vCPU dedicada reserva cores físicos para a sua instance, pelo que o contador fica em zero e permanece assim. O custo mensal é superior, mas esta é a resposta adequada para uma carga de trabalho que não pode absorver esta variação. Se isso ainda não for suficiente, ou se também quiser reservar a largura de banda da memória, o passo seguinte é um servidor dedicado em vez de um VPS.
Enquanto espera por uma destas medidas, reduza o impacto do steal. Execute menos worker threads do que o número de vCPUs disponíveis, porque as threads que não conseguem obter um core apenas acrescentam context switches. Mova o trabalho batch para as horas em que o node está menos ocupado, conforme o seu próprio log agora indica. Depois, faça novas medições com o mesmo comando durante as mesmas horas, para poder determinar se a alteração funcionou em vez de adivinhar.
FAQ
Qual é um valor normal de CPU steal time numa VPS?
Num plano partilhado, picos breves e um valor sustentado inferior a cerca de 5 por cento são normais, porque uma CPU partilhada significa que o host divide os cores físicos entre os guests. Valores de dois dígitos sustentados durante várias horas não são normais e justificam a abertura de um ticket. Num plano com vCPU dedicada, o valor esperado é 0.0, pelo que qualquer outro valor deve ser reportado como uma falha. Avalie o número em função da sua própria carga de trabalho: um job batch noturno tolera steal time que uma API sensível à latência não tolera.
Um plano maior resolve um steal time elevado?
Não por si só. Mais vCPUs no mesmo nó partilhado significam mais CPUs virtuais a competir pelos mesmos cores físicos congestionados, e a percentagem pode manter-se exatamente igual. O que elimina o steal time é uma alocação de CPU dedicada ou a migração para um nó menos carregado. Uma quota maior numa máquina ocupada continua a ser uma quota numa máquina ocupada.
Porque é que a minha VPS mostra 0 de steal time quando está claramente lenta?
Existem duas razões comuns. O hypervisor pode não exportar o contador, o que é habitual em plataformas VMware e Hyper-V, pelo que o campo permanece a zero independentemente do que acontece no host. Execute systemd-detect-virt para ver qual é a plataforma utilizada. Caso contrário, o congestionamento está noutro componente: consulte wa para verificar esperas de armazenamento, compare r com nproc para avaliar a sua própria sobrecarga e leia /sys/fs/cgroup/cpu.stat dentro dos contentores para verificar a limitação por quota.
Posso reduzir o steal time a partir do meu servidor?
Não pode alterar o agendamento do host a partir do guest. Só pode reduzir o impacto. Execute menos threads de trabalho do que o número de vCPUs disponíveis, para que haja menos trabalho na run queue à espera de um core que não está disponível. Mova os jobs batch para as horas em que o nó está menos ocupado. Faça cache dos resultados para que menos pedidos precisem de CPU. As alterações que eliminam efetivamente o steal time, como a migração para outro nó ou a utilização de cores dedicados, dependem do provider.