Kubernetes jak zrobić wdrożenie, aby zaktualizować obraz

133

Mam wdrożenie z pojedynczym pod, z moim niestandardowym obrazem platformy Docker, takim jak:

containers:
  - name: mycontainer
    image: myimage:latest

Podczas programowania chcę wypchnąć nową najnowszą wersję i zaktualizować Wdrożenie. Nie mogę znaleźć, jak to zrobić, bez wyraźnego zdefiniowania tagu / wersji i inkrementowania go dla każdej kompilacji, i zrób

kubectl set image deployment/my-deployment mycontainer=myimage:1.9.1
powyżej
źródło

Odpowiedzi:

152

Możesz skonfigurować swój pod z okresem karencji (na przykład 30 sekund lub więcej, w zależności od czasu uruchamiania kontenera i rozmiaru obrazu) i ustawić "imagePullPolicy: "Always". I użyj kubectl delete pod pod_name. Zostanie utworzony nowy kontener, a najnowszy obraz zostanie automatycznie pobrany, a stary kontener zostanie zamknięty.

Przykład:

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

Obecnie używam Jenkinsa do automatycznych kompilacji i tagowania obrazów i wygląda to mniej więcej tak:

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

Inną sztuczką jest uruchomienie:

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

i wtedy:

kubectl set image deployment/my-deployment mycontainer=myimage

W rzeczywistości będzie wyzwalać aktualizację kroczącą, ale upewnij się, że również imagePullPolicy: "Always"ustawiłeś.

Aktualizacja:

Kolejną sztuczką, którą znalazłem, w której nie musisz zmieniać nazwy obrazu, jest zmiana wartości pola, które wyzwoli aktualizację kroczącą, na przykład terminationGracePeriodSeconds. Możesz to zrobić za pomocą kubectl edit deployment your_deploymentlub kubectl apply -f your_deployment.yamllub używając takiej łatki:

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

Upewnij się tylko, że zawsze zmieniasz wartość liczbową.

Camil
źródło
1
Właściwie to twoja sztuczka nie jest zła, biorąc pod uwagę myimage: lastet i myimage w zasadzie to samo, dzięki!
ranem
1
Ta sztuczka wygląda bardziej na błąd, nie jestem pewien, dlaczego musimy to dwukrotnie określić.
speedplane
2
Jeśli chcesz, aby wdrożenie kubernetes uruchamiało nowy pod przy użyciu tego samego obrazu (a ta sztuczka działa tylko z tagiem „najnowsze”), musisz określić je bez tagu. Następnym razem dodaj „najnowszy” tag, a to uruchomi aktualizację. Kolejność można odwrócić, to nie ma znaczenia. Nigdy nie używasz tagu „najnowszego” w środowisku produkcyjnym, ale czasami możesz z niego skorzystać w celach programistycznych.
Camil
2
Działa tylko dla najnowszych. Domyślnie, przynajmniej w docker hub, nie oznaczając obrazu, przyjmie tag „najnowszy”. Ale będzie też działać bez niego. Ten przykład nie jest czymś, czego będziesz chciał w środowisku produkcyjnym i nie ma wielu przypadków użycia, w których możesz z niego skorzystać również w fazie rozwoju. Istnieją lepsze metody automatycznej aktualizacji obrazu przy użyciu narzędzia CI / CD.
Camil
11
Za każdym razem, gdy zmienisz tag i uruchomisz kubectl set imagepolecenie, kubernetes wykona aktualizację kroczącą. Na przykład, powiedzmy, że wdrożyłeś „repo / myimage: latest”. W międzyczasie obraz został zmieniony i przesłany do repozytorium z tagiem „v0.2”. Możesz przeprowadzić aktualizację, uruchamiając. kubectl set image deployment/my-deployment mycontainer=myimage:v0.2Ten obraz będzie miał również tag „najnowszy”.
Camil
75

AKTUALIZACJA 24.06.2019

Na podstawie komentarza @Jodiug, jeśli masz 1.15wersję, możesz użyć polecenia:

kubectl rollout restart deployment/demo

Przeczytaj więcej na ten temat:

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


Cóż, jest ciekawa dyskusja na ten temat w projekcie kubernetes GitHub. Zobacz problem: https://github.com/kubernetes/kubernetes/issues/33664

Z opisanych tam rozwiązań sugerowałbym jedno z dwóch.

Pierwszy

1. Przygotuj wdrożenie

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. wdrożyć

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

Drugi (jedna wkładka):

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

Oczywiście imagePullPolicy: Alwaysjest to wymagane w obu przypadkach.

Przemek Nowak
źródło
Znalazłem inną powiązaną sztuczkę. Jeśli po prostu wykonasz „wdrożenie kubectl, zrestartuj wdrażanie” bez określenia konkretnej nazwy wdrożenia, zrobi to „wszystkie” z nich.
Lennart Rolland
22
kubectl rollout restart deployment myapp

Jest to obecny sposób wyzwalania aktualizacji kroczącej i pozostawienia starych zestawów replik na miejscu dla innych operacji zapewnianych przez kubectl rolloutpodobne wycofywanie zmian.

Martin Peter
źródło
@Prathameshdhanawade operacja poprawki nie ma undopolecenia ani odpowiednika.
Martin Peter
8

Używam Gitlab-CI do budowania obrazu, a następnie wdrażam go bezpośrednio do GCK. Jeśli użyjesz zgrabnej małej sztuczki, aby uzyskać aktualizację kroczącą bez zmiany jakichkolwiek rzeczywistych ustawień kontenera, czyli zmianę etykiety na bieżącą zatwierdzoną-krótką-sha.

Moje polecenie wygląda tak:

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

Gdzie możesz użyć dowolnej nazwy i dowolnej wartości dla etykiety, o ile zmienia się ona przy każdej kompilacji.

Baw się dobrze!

David Faber
źródło
6

Wygląda na to, że k8s oczekuje od nas dostarczenia innego tagu obrazu dla każdego wdrożenia. Domyślną strategią byłoby, aby system CI generować i przesunąć obrazy Döcker, znakowanie je z numerem kompilacji: xpmatteo/foobar:456.

W przypadku lokalnego rozwoju może być wygodne użycie skryptu lub pliku makefile, takiego jak ten:

# 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

sedKomenda zastępuje zastępczy w dokumencie rozmieszczania z rzeczywistego obrazu generowanego tagu.

xpmatteo
źródło
kubernetes nie wymaga aktualizowania wdrożenia nowym tagiem w celu pobrania najnowszej wersji dowolnego obrazu, przy czym „najnowszy” jest najczęstszym przykładem.
Dave White
1

Używam Azure DevOps do wdrażania aplikacji w kontenerach, łatwo mogę rozwiązać ten problem, używając identyfikatora kompilacji

Za każdym razem, gdy kompiluje i generuje nowy identyfikator kompilacji, używam tego identyfikatora kompilacji jako tagu dla obrazu dockera, na przykład

nazwa zdjęcia: buildID

po pomyślnym zbudowaniu obrazu (CI) w potoku CD w pliku yml wdrożenia mam nadać nazwę obrazu jako

nazwa zdjęcia: env: buildID

tutaj evn: buildid jest zmienną Azure Devops, która ma wartość identyfikatora kompilacji.

więc teraz za każdym razem, gdy mam nowe zmiany do kompilacji (CI) i wdrożenia (CD).

prosimy o komentarz, jeśli potrzebujesz definicji kompilacji dla CI / CD.

Noman Sadiq
źródło
Manifest jest częścią repozytorium. Nie rozumiem, jakie są najlepsze praktyki w tym zakresie. Jeśli zbuduję obraz w potoku, czy powinienem naciskać, aby opanować zaktualizowany manifest? czy też powinienem utworzyć zaktualizowany manifest dla artefaktów (a zatem manifest w repozytorium byłby tylko szablonem bez rzeczywistego otagowanego obrazu)?
pablete