Kubernetes: Existe uma maneira de gerar arquivos yml que produzirão o cluster existente?

Criado em 27 abr. 2016  ·  24Comentários  ·  Fonte: kubernetes/kubernetes

Dado um cluster Kubernetes que está executando um certo número de pods, serviços, implantações, etc, gostaria de gerar um ou mais arquivos (formato yml de preferência) que reproduziria a configuração atual, quando aplicado a um novo cluster.

Meu caso de uso é um sistema de promoção. Eu tenho meus 'arquivos de pilha' como arquivos yml em um repositório git, mas preciso permitir que humanos aprovem as alterações antes de serem aplicadas ao cluster.

Uma maneira de fazer isso é usar um sistema de 'circuito aberto'. Posso usar tags ou outros mecanismos para determinar quais versões foram aplicadas ao cluster e, em seguida, comparar a versão mais recente disponível com a versão mais recente implantada.

O problema com o sistema de loop aberto é que ele não considera que as alterações poderiam ter sido feitas fora dos arquivos, ou que as alterações aplicadas poderiam ter tido problemas, etc.

Se eu pudesse extrair os arquivos 'equivalentes' de um cluster em execução, poderia compará-los com os que estão prestes a ser aplicados. Este é um sistema de 'loop fechado' muito mais forte - é capaz de entender corretamente o que acontecerá quando as alterações forem aplicadas, mesmo que tenhamos perdido o controle do estado real do alvo.

se existisse algo como kubectl apply -f--dry-run, que lista apenas as mudanças que serão feitas, ao invés de realmente fazer as mudanças, isso também funcionaria. Isso já está sendo discutido na questão https://github.com/kubernetes/kubernetes/issues/11488

Alguém tem alguma opinião sobre isso? Somos novos no kubernetes, mas criamos a funcionalidade que estou descrevendo acima para nossas implantações baseadas em rpm do RedHat / Satellite, então quero recriá-lo no K8s. Claro, no k8s, temos a complexidade de que a própria infraestrutura pode mudar, não apenas as versões dos pacotes instalados!

Comentários muito úteis

kubectl get po, deployment, rc, rs, ds, no, job -o yaml?

Todos 24 comentários

kubectl get po, deployment, rc, rs, ds, no, job -o yaml?

Ah sim, claro! Isso funciona, mas não é o que eu estava procurando. Ele responde à minha pergunta, mas não me dá os arquivos que correspondem aos que usei.

Aprendi que a resposta a essa pergunta é ler a anotação 'last-apply-configuration' adicionada pelo kubectl. isso fornecerá os arquivos que foram usados ​​para produzir a configuração.

@dcowden também veja kubectl get --export

ah isso é ainda melhor! obrigado!

Combinando outras respostas, é isso que eu inventei para o bash:

for n in $(kubectl get -o=name pvc,configmap,serviceaccount,secret,ingress,service,deployment,statefulset,hpa,job,cronjob)
do
    mkdir -p $(dirname $n)
    kubectl get -o=yaml --export $n > $n.yaml
done

k8s 1.8

kubectl get all --export=true -o yaml

Para as pessoas que vêm do Google, na minha instância de teste, o último comentário all não parece incluir ingress , e também você tem que dizer --all-namespaces para fazê-lo descartar outros namespaces.

Relacionado: https://github.com/kubernetes/kubernetes/issues/42885 e https://github.com/kubernetes/kubernetes/pull/42954#issuecomment -285949856 etc.

Uma variação da solução fornecida por @alahijani

for n in $(kubectl get -o=name pvc,configmap,ingress,service,secret,deployment,statefulset,hpa,job,cronjob | grep -v 'secret/default-token')
do
    kubectl get -o=yaml --export $n > $(dirname $n)_$(basename $n).yaml
done

Isso é para ter todos os arquivos yaml em um único diretório por um kubectl apply -f fácil. Também exclui o segredo da conta de serviço padrão, que não pode ser exportado.

Outra versão: Exportando todos os yamls de todos os namespaces. Para cada namespace, um diretório é criado.

  • incluindo volumes persistentes!
i=$((0))
for n in $(kubectl get -o=custom-columns=NAMESPACE:.metadata.namespace,KIND:.kind,NAME:.metadata.name pv,pvc,configmap,ingress,service,secret,deployment,statefulset,hpa,job,cronjob --all-namespaces | grep -v 'secrets/default-token')
do
    if (( $i < 1 )); then
        namespace=$n
        i=$(($i+1))
        if [[ "$namespace" == "PersistentVolume" ]]; then
            kind=$n
            i=$(($i+1))
        fi
    elif (( $i < 2 )); then
        kind=$n
        i=$(($i+1))
    elif (( $i < 3 )); then
        name=$n
        i=$((0))
        echo "saving ${namespace} ${kind} ${name}"
        if [[ "$namespace" != "NAMESPACE" ]]; then
            mkdir -p $namespace
            kubectl get $kind -o=yaml --export $name -n $namespace > $namespace/$kind.$name.yaml
        fi
    fi
done

e para importar novamente:

path=$(pwd)
for n in $(ls -d */)
do
    echo "Creating namespace ${n:0:-1}"
    kubectl create namespace ${n:0:-1}

    for yaml in $(ls $path/$n)
    do
        echo -e "\t Importing $yaml"
        kubectl apply -f $path/$n$yaml -n ${n:0:-1}
    done

done

Outro pequeno ajuste para excluir tokens de conta de serviço:

#!/bin/env bash

## https://github.com/kubernetes/kubernetes/issues/24873#issuecomment-416189335

i=$((0))
for n in $(kubectl get -o=custom-columns=NAMESPACE:.metadata.namespace,KIND:.kind,NAME:.metadata.name pv,pvc,configmap,ingress,service,secret,deployment,statefulset,hpa,job,cronjob --all-namespaces | grep -v 'secrets/default-token')
do
    if (( $i < 1 )); then
        namespace=$n
        i=$(($i+1))
        if [[ "$namespace" == "PersistentVolume" ]]; then
            kind=$n
            i=$(($i+1))
        fi
    elif (( $i < 2 )); then
        kind=$n
        i=$(($i+1))
    elif (( $i < 3 )); then
        name=$n
        i=$((0))
        if [[ "$namespace" != "NAMESPACE" ]]; then
            mkdir -p $namespace

            yaml=$((kubectl get $kind -o=yaml $name -n $namespace ) 2>/dev/null)
            if [[ $kind != 'Secret' || $yaml != *"type: kubernetes.io/service-account-token"* ]]; then
                echo "Saving ${namespace}/${kind}.${name}.yaml"
                kubectl get $kind -o=yaml --export $name -n $namespace > $namespace/$kind.$name.yaml
            fi
        fi
    fi
done

Para quem trabalha no Windows Powershell, aqui está um one-liner:
Foreach ($i in $(kubectl get -o=name pvc,configmap,ingress,service,secret,deployment,statefulset,hpa,job,cronjob)) {If($i -notmatch "default-token") {kubectl get -o=yaml --export $i | Out-File -filepath $($i.Replace("/", "-") + ".yaml")}}

@mrwulf @acondrat
Acho que grep -v 'secrets/default-token' deve ser alterado para grep -v 'secret/default-token'
secrets não funcionou comigo.

Estou usando as seguintes versões do cluster kubectl e k8s

Client Version: version.Info{Major:"1", Minor:"12", GitVersion:"v1.12.2", GitCommit:"17c77c7898218073f14c8d573582e8d2313dc740", GitTreeState:"clean", BuildDate:"2018-10-24T06:54:59Z", GoVersion:"go1.10.4", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.5", GitCommit:"32ac1c9073b132b8ba18aa830f46b77dcceb0723", GitTreeState:"clean", BuildDate:"2018-06-21T11:34:22Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}

@ 4m3ndy você está certo! Obrigado!

Ei, pessoal, acabamos de fazer esta imagem do docker para exportar os arquivos yaml necessários para cada componente por namespace. esses backups são exportados e criptografados com uma senha e carregados no S3 Bucket.

Se alguém quiser fazer alguma alteração ou compartilhar algum comentário, você é mais que bem-vindo: +1:
ambient-innovation / k8s-backup

exemplo: gerar pv yaml.

kubectl get pv -o yaml --export | sed -e '/resourceVersion: "[0-9]\+"/d' -e '/uid: [a-z0-9-]\+/d' -e '/selfLink: [a-z0-9A-Z/]\+/d' -e '/status:/d' -e '/phase:/d' -e '/creationTimestamp:/d' > pvList.yaml

@ xiaoping378
https://github.com/ambient-innovation/k8s-backup/blob/01c1bfe750136648fd91e14dd691ba39bb05f282/k8s-backup.sh#L38

Este script deve gerar todos os pvc para cada namespace e então exportar o arquivo yaml para cada pv, dê uma olhada

Crie uma pasta $ {HOME} / clusterstate / e execute:
kubectl cluster-info dump --all-namespaces --output-directory=${HOME}/clusterstate/ -o yaml
Todas as suas entidades estarão em estruturas de pastas separadas, correspondendo aos namespaces.
As extensões .json, ou seja, deployments.json, são enganosas, pois o sinalizador -o yaml criará exportações yaml.

Crie uma pasta $ {HOME} / clusterstate / e execute:
kubectl cluster-info dump --all-namespaces --output-directory=${HOME}/clusterstate/ -o yaml
Todas as suas entidades estarão em estruturas de pastas separadas, correspondendo aos namespaces.
As extensões .json, ou seja, deployments.json, são enganosas, pois o sinalizador -o yaml criará exportações yaml.

Para sua informação, isso parece precisar de uma quantidade decente de RAM para grandes implantações, meu jumpbox VM de 2 GB de RAM CLI não consegue lidar com isso (provavelmente precisa de 4 ou 8, imagino):

fatal error: runtime: out of memory

runtime stack:
runtime.throw(0x1ab7c29, 0x16)
        /usr/local/go/src/runtime/panic.go:774 +0x72
runtime.sysMap(0xc068000000, 0x10000000, 0x2da7238)
        /usr/local/go/src/runtime/mem_linux.go:169 +0xc5
runtime.(*mheap).sysAlloc(0x2d8e9a0, 0x10000000, 0x0, 0x0)
        /usr/local/go/src/runtime/malloc.go:701 +0x1cd
runtime.(*mheap).grow(0x2d8e9a0, 0x8000, 0xffffffff)
        /usr/local/go/src/runtime/mheap.go:1255 +0xa3
runtime.(*mheap).allocSpanLocked(0x2d8e9a0, 0x8000, 0x2da7248, 0x42c7bc)
        /usr/local/go/src/runtime/mheap.go:1170 +0x266
runtime.(*mheap).alloc_m(0x2d8e9a0, 0x8000, 0x101, 0xc000103f18)
        /usr/local/go/src/runtime/mheap.go:1022 +0xc2

Eu fiz uma nova varredura na minha área de trabalho e rastreei o uso de memória do processo kubectl, que atingiu o pico em cerca de 4 GB, então são 8 GB!

Aparentemente, isso corresponde ao tamanho de saída total do dump, que inclui logs e alguns de nossos pods (90 deles) estão emitindo logs de mais de 100 MB. Isso indicaria para mim que o comando dump está armazenando tudo na RAM, mesmo enquanto está gravando no disco, provavelmente poderia ser otimizado para limpar a RAM quando os logs terminarem de gravar.

Alguém pode me dizer o comando ou script que fará o backup do cluster (inclui ns, implantação, svc, segredos, arquivos pv pvc, cm yaml apenas) com todas as informações e restaurá-lo em um novo cluster.
Eu tentei com o comando --export, mas no serviço yaml o nome do arquivo de serviço está faltando e se eu fizer backup sem --export, ele inclui clusterIP IP , porta nodePort ,
Kubernetes cluster versão 1.14 em diante 1.15 / 16/17 (tentando fazer backup / restauração no GCP gke ou AWS eks).

Graças a kubectl api-resources ! Consegui obter manifestos (arquivos yaml) de todos os recursos em todos os namespaces em k8s usando o seguinte script bash:

#!/usr/bin/env bash

while read -r line
do
    output=$(kubectl get "$line" --all-namespaces -o yaml 2>/dev/null | grep '^items:')
    if ! grep -q "\[\]" <<< $output; then
        echo -e "\n======== "$line" manifests ========\n"
        kubectl get "$line" --all-namespaces -o yaml
    fi
done < <(kubectl api-resources | awk '{print $1}' | grep -v '^NAME')

O script bash acima foi testado com:

  • k8s v1.16.3
  • Ubuntu Bionic 18.04.3 OS
  • versão bash versão 4.4.20(1)-release (x86_64-pc-linux-gnu)

@vhosakot Pequena simplificação em seu script.

Você pode substituir: kubectl api-resources | awk '{print $1}' | grep -v '^NAME'
Com: kubectl api-resources -o name

#!/usr/bin/env bash

while read -r namespace
do
    echo "scanning namespace '${namespace}'"
    mkdir -p "${HOME}/cluster-backup/${namespace}"
    while read -r resource
    do
        echo "  scanning resource '${resource}'"
        mkdir -p "${HOME}/cluster-backup/${namespace}/${resource}"
        while read -r item
        do
            echo "    exporting item '${item}'"
            kubectl get "$resource" -n "$namespace" "$item" -o yaml > "${HOME}/cluster-backup/${namespace}/${resource}/$item.yaml"
        done < <(kubectl get "$resource" -n "$namespace" 2>&1 | tail -n +2 | awk '{print $1}')
    done < <(kubectl api-resources --namespaced=true 2>/dev/null | tail -n +2 | awk '{print $1}')
done < <(kubectl get namespaces | tail -n +2 | awk '{print $1}')

Eu estendi o script acima um pouco (e o retardei). isso carrega todos os namespaces, carrega todos os recursos em todos os namespaces e, em seguida, carrega cada configuração como um único arquivo em cada recurso em cada namespace. é prolixo e mostra alguns erros, mas o resultado final (o despejo) deve ser limpo.

#!/usr/bin/env bash
ROOT=${HOME}/clusterstate

while read -r resource
do
    echo "  scanning resource '${resource}'"
    while read -r namespace item x
    do
        mkdir -p "${ROOT}/${namespace}/${resource}"        
        echo "    exporting item '${namespace} ${item}'"
        kubectl get "$resource" -n "$namespace" "$item" -o yaml > "${ROOT}/${namespace}/${resource}/$item.yaml" &
    done < <(kubectl get "$resource" --all-namespaces 2>&1 | tail -n +2)
done < <(kubectl api-resources --namespaced=true 2>/dev/null | tail -n +2 | awk '{print $1}')

wait

Inspirado em @scones, mas é executado um pouco mais rápido por causa da bifurcação do processo e do aninhamento de loop reduzido, o que é útil se você tiver muitas definições de recursos personalizados!

O mesmo que @ nathan-c
Removi events da lista de recursos para corrigir erros

#!/usr/bin/env bash
ROOT=${HOME}/clusterstate
while read -r resource
do
    echo "  scanning resource '${resource}'"
    while read -r namespace item x
    do
        mkdir -p "${ROOT}/${namespace}/${resource}"        
        echo "    exporting item '${namespace} ${item}'"
        kubectl get "$resource" -n "$namespace" "$item" -o yaml > "${ROOT}/${namespace}/${resource}/$item.yaml" &
    done < <(kubectl get "$resource" --all-namespaces 2>&1  | tail -n +2)
done < <(kubectl api-resources --namespaced=true 2>/dev/null | grep -v "events" | tail -n +2 | awk '{print $1}')

wait
Esta página foi útil?
0 / 5 - 0 avaliações