Kubernetes como fazer a implantação para atualizar a imagem

130

Tenho implantação com pod único, com minha imagem de janela de encaixe personalizada, como:

containers:
  - name: mycontainer
    image: myimage:latest

Durante o desenvolvimento, quero enviar a nova versão mais recente e atualizar o Deployment. Não é possível encontrar como fazer isso, sem definir explicitamente a tag / versão e incrementá-la para cada build, e faça

kubectl set image deployment/my-deployment mycontainer=myimage:1.9.1
abovesun
fonte

Respostas:

151

Você pode configurar seu pod com um período de carência (por exemplo, 30 segundos ou mais, dependendo do tempo de inicialização do contêiner e do tamanho da imagem) e definir "imagePullPolicy: "Always". E use kubectl delete pod pod_name. Um novo contêiner será criado e a imagem mais recente será baixada automaticamente e o contêiner antigo será encerrado.

Exemplo:

spec:
  terminationGracePeriodSeconds: 30
  containers:
  - name: my_container
    image: my_image:latest
    imagePullPolicy: "Always"

Atualmente, estou usando o Jenkins para compilações automatizadas e marcação de imagens e é algo como isto:

kubectl --user="kube-user" --server="https://kubemaster.example.com"  --token=$ACCESS_TOKEN set image deployment/my-deployment mycontainer=myimage:"$BUILD_NUMBER-$SHORT_GIT_COMMIT"

Outro truque é executar inicialmente:

kubectl set image deployment/my-deployment mycontainer=myimage:latest

e depois:

kubectl set image deployment/my-deployment mycontainer=myimage

Na verdade, ele estará acionando a atualização sem interrupção, mas verifique se você também imagePullPolicy: "Always"definiu.

Atualizar:

outro truque que encontrei, onde você não precisa alterar o nome da imagem, é alterar o valor de um campo que acionará uma atualização contínua, como terminationGracePeriodSeconds. Você pode fazer isso usando kubectl edit deployment your_deploymentou kubectl apply -f your_deployment.yamlou usando um patch assim:

kubectl patch deployment your_deployment -p \
  '{"spec":{"template":{"spec":{"terminationGracePeriodSeconds":31}}}}'

Apenas certifique-se de sempre alterar o valor numérico.

Camil
fonte
1
Na verdade, seu truque não é ruim, considerando myimage: lastet e myimage basicamente a mesma coisa, obrigado!
Abovesun
1
Esse truque parece mais um bug, não sei por que precisamos especificá-lo duas vezes.
speedplane 29/06
2
Se você deseja que uma implantação do kubernetes inicie um novo pod usando a mesma imagem (e esse truque funciona apenas com a tag "mais recente"), você deve especificá-lo sem uma tag. Da próxima vez, adicione a tag "latest" e ela acionará a atualização. A ordem pode ser revertida, não importa. Você nunca usa a tag "mais recente" na produção, mas, para fins de desenvolvimento, pode se beneficiar dela algumas vezes.
Camil
2
Funciona apenas para as últimas. Por padrão, pelo menos no hub docker, ao não marcar uma imagem, ela assumirá a tag "mais recente". Mas também funcionará sem ele. Este exemplo não é algo que você desejará em um ambiente de produção e não há muitos casos de uso em que você também possa se beneficiar dele no desenvolvimento. Existem métodos melhores para atualizar uma imagem automaticamente, usando uma ferramenta de CI / CD.
Camil
11
Sempre que você alterar a tag e executar o kubectl set imagecomando, o kubernetes executará uma atualização contínua. Por exemplo, digamos que você implantou "repo / myimage: latest". Enquanto isso, sua imagem foi alterada e enviada ao repositório com a tag "v0.2". Você pode executar uma atualização executando kubectl set image deployment/my-deployment mycontainer=myimage:v0.2Esta imagem também terá a tag "mais recente".
Camil
73

ATUALIZAÇÃO 24/06/2019

Com base no comentário @Jodiug, se você tiver uma 1.15versão, poderá usar o comando:

kubectl rollout restart deployment/demo

Leia mais sobre o assunto:

https://github.com/kubernetes/kubernetes/issues/13488


Bem, há uma discussão interessante sobre esse assunto no projeto kubernetes GitHub. Veja o problema: https://github.com/kubernetes/kubernetes/issues/33664

Das soluções descritas lá, eu sugeriria uma de duas.

Primeiro

1.Prepare a implantação

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: demo
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: demo
        image: registry.example.com/apps/demo:master
        imagePullPolicy: Always
        env:
        - name: FOR_GODS_SAKE_PLEASE_REDEPLOY
          value: 'THIS_STRING_IS_REPLACED_DURING_BUILD'

2. implantar

sed -ie "s/THIS_STRING_IS_REPLACED_DURING_BUILD/$(date)/g" deployment.yml
kubectl apply -f deployment.yml

Segundo (um revestimento):

kubectl patch deployment web -p \
  "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"`date +'%s'`\"}}}}}"

Obviamente, isso imagePullPolicy: Alwaysé necessário nos dois casos.

Przemek Nowak
fonte
Encontrei outro truque relacionado. Se você apenas fizer o "kubectl rollout restart deploy" sem especificar nenhum nome de implantação específico, ele fará "todos".
Lennart Rolland
20
kubectl rollout restart deployment myapp

Essa é a maneira atual de acionar uma atualização sem interrupção e deixar os conjuntos de réplicas antigos em vigor para outras operações fornecidas por kubectl rolloutreversões semelhantes.

Martin Peter
fonte
@Prathameshdhanawade a operação do patch não tem undocomando ou equivalente.
Martin Peter
7

Eu uso o Gitlab-CI para criar a imagem e depois implantá-la diretamente no GCK. Se você usar um pequeno truque para obter uma atualização sem interrupção, sem alterar as configurações reais do contêiner, o que está alterando um rótulo para o commit-short-sha atual.

Meu comando é assim:

kubectl patch deployment my-deployment -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"build\":\"$CI_COMMIT_SHORT_SHA\"}}}}}}"

Onde você pode usar qualquer nome e valor para o rótulo, desde que ele seja alterado a cada construção.

Diverta-se!

David Faber
fonte
6

Parece que o k8s espera que forneçamos uma tag de imagem diferente para cada implantação. Minha estratégia padrão seria fazer o sistema CI gerar e empurrar as imagens Estivador, marcá-los com o número de compilação: xpmatteo/foobar:456.

Para o desenvolvimento local, pode ser conveniente usar um script ou um makefile, como este:

# create a unique tag    
VERSION:=$(shell date +%Y%m%d%H%M%S)
TAG=xpmatteo/foobar:$(VERSION)

deploy:
    npm run-script build
    docker build -t $(TAG) . 
    docker push $(TAG)
    sed s%IMAGE_TAG_PLACEHOLDER%$(TAG)% foobar-deployment.yaml | kubectl apply -f - --record

O sedcomando substitui um espaço reservado no documento de implantação pela tag de imagem gerada real.

xpmatteo
fonte
O kubernetes não exige que você atualize a implantação com uma nova tag para obter a versão mais recente de qualquer imagem, sendo "mais recente" o exemplo mais comum.
Dave White
1

Estou usando o Azure DevOps para implantar os aplicativos em contêiner, consigo gerenciar facilmente esse problema usando o ID da compilação

Toda vez que ela cria e gera o novo ID da compilação, eu uso essa identificação como tag para a imagem do docker, aqui está um exemplo

imagename: buildID

uma vez que sua imagem é compilada (CI) com êxito, no pipeline do CD no arquivo yml de implantação, eu nomeei

imagename: env: buildID

aqui evn: buildid é a variável azure devops que possui o valor do ID da construção.

agora, toda vez que tenho novas alterações para criar (CI) e implantar (CD).

comente se você precisa criar uma definição para CI / CD.

Noman Sadiq
fonte
O manifesto faz parte do repositório. Não entendo quais são as melhores práticas para isso. Se eu criar a imagem no pipeline, devo pressionar para dominar o manifesto atualizado? ou devo produzir um manifesto atualizado para os artefatos (e, portanto, o manifesto no repositório seria apenas um modelo sem a imagem marcada real)?
pablete 17/02