kubectl apply vs set: Escolhendo o Comando Certo para Atualizações de Recursos

Entenda quando usar kubectl apply, set e edit sem criar divergência entre objetos Kubernetes ativos e o Git.

kubectl apply vs set: Escolhendo o Comando Certo para Atualizações de Recursos

A diferença entre kubectl apply e kubectl set não é apenas sintaxe. É a diferença entre gerenciar Kubernetes a partir de uma fonte de verdade declarada e alterar objetos ativos diretamente. Ambos são úteis. Ambos podem prejudicá-lo se usados no lugar errado.

Use kubectl apply quando a alteração deve se tornar o estado desejado do sistema. Use kubectl set quando você precisa de uma alteração ativa focada, geralmente temporária ou urgente. Use kubectl edit quando precisar inspecionar e corrigir um objeto ativo interativamente, mas entenda que é a maneira mais fácil de criar divergência do Git.

Um objeto Kubernetes tem um estado desejado armazenado no servidor da API. Um Deployment diz quantas réplicas devem existir, qual imagem deve ser executada, quais labels identificam os pods, quais recursos são solicitados e muito mais. Os controladores trabalham para fazer a realidade corresponder a esse estado desejado. Seu comando de atualização altera o estado desejado; os controladores fazem o resto.

Com kubectl apply, você mantém esse estado desejado em arquivos YAML ou JSON. O arquivo é a coisa que você revisa, confirma, promove e reverte. Um comando típico é simples:

kubectl apply -f deployment.yaml

Se o objeto não existir, o Kubernetes o cria. Se existir, o Kubernetes o atualiza para corresponder ao manifesto. Aplicar o mesmo arquivo novamente não deve causar uma nova mudança comportamental. Essa idempotência é uma das razões pelas quais apply funciona bem em fluxos de trabalho CI/CD e GitOps.

O kubectl apply do lado do cliente historicamente usava uma anotação de última aplicação para calcular alterações. O apply do lado do servidor, habilitado com --server-side, rastreia a propriedade do campo através de campos gerenciados no servidor da API. Os detalhes diferem, mas a ideia operacional é a mesma: uma configuração declarada possui o estado desejado.

Aqui está um pequeno manifesto de Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80

Se você alterar a imagem no arquivo e executar kubectl apply -f deployment.yaml, o Deployment é atualizado. Se o arquivo estiver no Git, a alteração pode ser revisada. Se o rollout quebrar, você pode reverter o commit ou usar o histórico de rollout do Kubernetes, dependendo de como seu processo de implantação registra as revisões.

kubectl set funciona de forma diferente. Ele altera um campo específico em um objeto ativo. O exemplo comum é alterar uma imagem de contêiner:

kubectl set image deployment/web nginx=nginx:1.26

Esse comando é rápido e legível. Durante um incidente, a velocidade importa. Se a imagem atual está quebrada e você precisa mover um Deployment para uma imagem conhecidamente boa, kubectl set image pode ser o caminho mais rápido. O perigo é o que acontece depois. Se deployment.yaml ainda diz nginx:1.25, o próximo kubectl apply -f deployment.yaml pode mover a carga de trabalho de volta para 1.25.

Essa incompatibilidade é divergência de configuração. O cluster ativo diz uma coisa. O arquivo de origem diz outra. A divergência nem sempre é catastrófica, mas torna a depuração mais difícil porque as pessoas param de confiar no repositório. Alguém pergunta: "O que está rodando em produção?" e a resposta honesta se torna: "Deixe-me verificar o cluster."

kubectl set tem vários subcomandos úteis:

kubectl set image deployment/web nginx=nginx:1.26
kubectl set env deployment/web FEATURE_FLAG=true
kubectl set resources deployment/web -c=nginx --requests=cpu=200m,memory=256Mi --limits=cpu=500m,memory=512Mi

Estes são práticos para clusters de desenvolvimento, demonstrações, testes de curta duração e mudanças de emergência em produção com um commit de acompanhamento. Eles não substituem manifestos mantidos.

kubectl edit busca o objeto ativo, abre no seu editor e envia o objeto alterado de volta ao servidor da API quando você salva:

kubectl edit deployment/web

É conveniente porque você pode ver o YAML ativo completo, incluindo campos adicionados pelos controladores. Também é arriscado porque objetos ativos contêm muitos campos que você não deve gerenciar manualmente, como status, metadados gerados, versões de recursos e campos gerenciados. O Kubernetes ignorará ou rejeitará algumas edições inválidas, mas nem toda edição ruim é sintaticamente inválida.

Um uso seguro comum de kubectl edit é um experimento rápido de não produção: aumentar réplicas, alterar uma anotação ou testar um valor de sonda. Um uso inseguro comum é editar manualmente Deployments de produção toda semana e nunca atualizar os manifestos. Isso cria um cluster que ninguém pode reconstruir com confiança.

A regra prática é esta: se você quer que a alteração sobreviva à próxima implantação, coloque-a no manifesto e use apply. Se você só precisa cutucar o objeto ativo, use set ou edit, depois reverta a alteração ou faça o backport para o Git.

Há alguns casos em que comandos imperativos não são apenas aceitáveis, mas úteis. Durante a depuração, você pode adicionar temporariamente uma variável de ambiente que aumenta a verbosidade do log:

kubectl set env deployment/api LOG_LEVEL=debug

Depois de coletar logs, remova-a:

kubectl set env deployment/api LOG_LEVEL-

Se a configuração de depuração deve se tornar permanente, faça o commit no manifesto. Não confie na memória.

Outro caso é o rollback de emergência. Se seu pipeline de implantação está travado e os clientes estão afetados, definir a imagem diretamente pode ser razoável:

kubectl set image deployment/api api=registry.example.com/api:2026-05-23-good
kubectl rollout status deployment/api

O acompanhamento deve acontecer imediatamente: abra um pull request ou commit que faça o manifesto declarado corresponder ao estado de emergência, ou execute o processo de rollback normal assim que o pipeline estiver saudável. A correção ao vivo ganha tempo; não deve se tornar o novo método de implantação não documentado.

kubectl apply também tem armadilhas. Se você misturar várias ferramentas que gerenciam os mesmos campos, pode obter conflitos ou sobrescritas surpreendentes. Por exemplo, um controlador GitOps, Helm e um humano executando kubectl apply contra o mesmo Deployment podem todos acreditar que possuem parte do objeto. Escolha uma propriedade clara. Se o Helm gerencia o recurso, atualize os valores do Helm e execute o processo de release do Helm. Se Argo CD ou Flux o gerencia, mude o Git e deixe o controlador reconciliar.

Para secrets e config, seja especialmente cuidadoso. kubectl set env pode colocar mudanças rápidas em um Deployment, mas pode expor valores no histórico do shell ou logs de auditoria. Para valores sensíveis, atualize o Secret através do seu processo normal de gerenciamento de secrets. Não cole credenciais de produção em um comando ad hoc a menos que sua equipe tenha aceitado explicitamente esse fluxo de trabalho.

Antes de alterar um objeto ativo, inspecione-o:

kubectl get deployment web -o yaml
kubectl diff -f deployment.yaml

kubectl diff é subutilizado. Ele mostra o que apply mudaria antes de você fazer a alteração. Em produção, essa pré-visualização pode pegar erros como remover acidentalmente um seletor de label, eliminar um limite de recurso ou aplicar o manifesto do ambiente errado.

Para apply do lado do servidor, o comando se parece com isso:

kubectl apply --server-side -f deployment.yaml

O apply do lado do servidor pode ser útil quando vários atores gerenciam campos diferentes, mas não remove a necessidade de disciplina de propriedade. Se dois gerentes tentarem possuir o mesmo campo, o Kubernetes pode relatar um conflito. Isso é um recurso; está dizendo que o fluxo de trabalho é ambíguo.

Aqui está um guia de decisão simples que uso em clusters reais. Novo lançamento de aplicação? Altere o manifesto e use apply através do pipeline. Aumentar réplicas para um teste de carga em staging? kubectl scale ou kubectl set é aceitável se você reverter. Corrigir uma imagem quebrada em produção? kubectl set image pode ser aceitável, mas crie a alteração da fonte de verdade imediatamente. Ajustar solicitações de CPU permanentemente? Atualize o manifesto. Explorar quais campos existem em um recurso? Use kubectl get -o yaml antes de recorrer ao edit.

Quando as equipes acertam isso, o Kubernetes se torna mais fácil de raciocinar. O repositório conta a história. O cluster corresponde ao repositório na maioria das vezes. Mudanças temporárias ao vivo são rotuladas como temporárias e limpas. Incidentes ainda são estressantes, mas a configuração não se torna um segundo mistério.

O comando em si não é o ponto. O ponto é se você pode reconstruir o estado do cluster amanhã a partir de arquivos confiáveis. kubectl apply suporta esse hábito. kubectl set e kubectl edit são ferramentas afiadas para momentos em que a ação direta é útil. Mantenha esse limite claro e você evitará muita confusão evitável do Kubernetes.

Há outro comando que as pessoas colocam no mesmo balde mental: kubectl patch. Também é imperativo, mas é melhor para mudanças precisas e scriptadas do que edit. Por exemplo, você pode corrigir uma anotação de Deployment para acionar uma reinicialização ou atualizar um campo pequeno na automação. A mesma regra de divergência se aplica. Se o campo corrigido representa o estado desejado de longo prazo, atualize o manifesto de origem também.

kubectl patch deployment web   -p '{"spec":{"template":{"metadata":{"annotations":{"restartedAt":"2026-05-24T10:00:00Z"}}}}}'

Para reinicializações, prefira o comando específico:

kubectl rollout restart deployment/web

Esse comando ainda altera o objeto ativo, mas sua intenção é clara: iniciar um novo rollout a partir do modelo de pod atual. Não substitui a alteração da configuração no Git.

Em ambientes GitOps, o limite é ainda mais rigoroso. Se Argo CD ou Flux possui um objeto, um kubectl set image manual pode ser revertido automaticamente porque o controlador vê divergência e reconcilia de volta ao Git. Isso pode ser surpreendente durante um incidente. Antes de fazer uma mudança manual em produção, saiba se um controlador GitOps vai lutar contra você. Às vezes, a ação de emergência correta é pausar a reconciliação para essa aplicação, fazer a correção, depois fazer o commit da mudança correspondente no Git e retomar a reconciliação.

Você também deve saber como capturar uma diferença ao vivo sem commitar cegamente campos gerados. kubectl get deployment web -o yaml inclui status, versões de recursos, campos gerenciados e outros dados que não devem ir para um manifesto limpo. Se você precisar fazer backport de uma correção rápida, edite o manifesto de origem manualmente ou use uma ferramenta como Kustomize ou valores do Helm, depois execute kubectl diff para verificar a mudança pretendida. Não substitua seu arquivo de origem pelo YAML ativo bruto a menos que você o limpe cuidadosamente.

Para equipes, a política mais saudável é geralmente curta e explícita. Mudanças de produção passam pelo Git. Mudanças ao vivo de emergência são permitidas quando necessário, mas exigem uma mudança de origem ou rollback de acompanhamento. Clusters de desenvolvimento são mais flexíveis, mas qualquer coisa promovida além do desenvolvimento deve ser declarada. Essa política é mais fácil de seguir do que uma longa lista de comandos proibidos.

Há também um lado humano nisso. Durante uma interrupção, a pessoa com acesso ao cluster pode fazer a correção mais rápida possível. Isso é aceitável quando a equipe trata como uma exceção de emergência. Torna-se perigoso quando essas exceções se tornam operações normais. Se a produção é rotineiramente corrigida manualmente, o processo de implantação é muito lento, muito frágil ou não confiável. Corrija esse processo em vez de ensinar a todos mais truques de edição ao vivo.

O RBAC pode reforçar o fluxo de trabalho. Muitas equipes permitem amplo acesso kubectl em desenvolvimento, mas restringem gravações em produção a sistemas CI/CD, controladores GitOps ou um pequeno grupo de plantão. Isso não é burocracia por si só. Reduz o número de caminhos que podem alterar o estado desejado. Quando algo muda, os logs de auditoria e o histórico do Git são mais fáceis de seguir.

Para aprendizado, ainda vale a pena praticar todos os três comandos em um namespace descartável. Crie um Deployment com apply, altere sua imagem com set, inspecione a divergência com kubectl diff, depois atualize o manifesto e aplique novamente. Ver a divergência acontecer uma vez em um ambiente seguro torna a regra de produção muito mais fácil de lembrar.