Kubernetes как сделать развертывание для обновления образа

134

У меня есть развертывание с одним модулем с моим настраиваемым образом докера, например:

containers:
  - name: mycontainer
    image: myimage:latest

Во время разработки я хочу выпустить новую последнюю версию и обновить развертывание. Не могу найти, как это сделать, без явного определения тега / версии и увеличения его для каждой сборки, и выполните

kubectl set image deployment/my-deployment mycontainer=myimage:1.9.1
abovesun
источник

Ответы:

152

Вы можете настроить свой модуль с периодом отсрочки (например, 30 секунд или более, в зависимости от времени запуска контейнера и размера образа) и установить "imagePullPolicy: "Always". И пользуйся kubectl delete pod pod_name. Будет создан новый контейнер и автоматически загружен последний образ, после чего старый контейнер будет остановлен.

Пример:

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

В настоящее время я использую Jenkins для автоматизированных сборок и тегов изображений, и это выглядит примерно так:

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

Еще один трюк - запустить:

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

а потом:

kubectl set image deployment/my-deployment mycontainer=myimage

Фактически это будет запускать скользящее обновление, но убедитесь, что вы также imagePullPolicy: "Always"установили.

Обновить:

Еще один трюк, который я обнаружил, когда вам не нужно изменять имя изображения, - это изменить значение поля, которое будет запускать скользящее обновление, например terminationGracePeriodSeconds. Вы можете сделать это с помощью kubectl edit deployment your_deploymentили kubectl apply -f your_deployment.yamlили используя такой патч:

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

Просто убедитесь, что вы всегда меняете числовое значение.

Камил
источник
1
Вообще-то это ваш трюк неплох, учитывая myimage: lastet и myimage в основном одно и то же, спасибо!
выше,
1
Этот трюк больше похож на ошибку, не знаю, почему нам нужно указывать его дважды.
Speedplane
2
Если вы хотите, чтобы развертывание Kubernetes запускало новый модуль с тем же образом (а этот трюк работает только с тегом «latest»), вы должны указать его без тега. В следующий раз добавьте тег «последний», и он запустит обновление. Порядок может быть изменен, это не имеет значения. Вы никогда не используете «последний» тег в продакшене, но в целях разработки иногда можете извлечь из него пользу.
Camil
2
Это работает только для последних. По умолчанию, по крайней мере, в docker hub, если изображение не помечается, он принимает «последний» тег. Но работать и без него будет. Этот пример не то, что вам нужно в производственной среде, и не так много случаев использования, где вы могли бы извлечь из него пользу и при разработке. Есть лучшие методы для автоматического обновления образа с помощью инструмента CI / CD.
Камил
11
Каждый раз, когда вы меняете тег и запускаете kubectl set imageкоманду, кубернетес будет выполнять скользящее обновление. Например, допустим, вы развернули «repo / myimage: latest». Тем временем ваше изображение было изменено и отправлено в репо с тегом «v0.2». Вы можете выполнить обновление, запустив. kubectl set image deployment/my-deployment mycontainer=myimage:v0.2Этот образ также будет иметь тег «последний».
Камил
75

ОБНОВЛЕНИЕ 2019-06-24

Основываясь на комментарии @Jodiug, если у вас есть 1.15версия, вы можете использовать команду:

kubectl rollout restart deployment/demo

Подробнее по теме:

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


Что ж, есть интересная дискуссия на эту тему в проекте kubernetes GitHub. См. Проблему: https://github.com/kubernetes/kubernetes/issues/33664

Из описанных там решений я бы предложил одно из двух.

Первый

1. подготовить развертывание

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.Deploy

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

Второй (один лайнер):

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

Конечно, в imagePullPolicy: Alwaysобоих случаях требуется.

Пшемек Новак
источник
Нашел еще одну похожую уловку. Если вы просто выполните команду «kubectl rollout restart deployment» без указания какого-либо конкретного имени развертывания, он выполнит «все» из них.
Леннарт Роллан
22
kubectl rollout restart deployment myapp

Это текущий способ запустить непрерывное обновление и оставить старые наборы реплик на месте для других операций, обеспечиваемых kubectl rolloutаналогичными откатами.

Мартин Питер
источник
@Prathameshdhanawade операция исправления не имеет undoкоманды или эквивалента.
Мартин Питер
8

Я использую Gitlab-CI для создания образа, а затем развертываю его непосредственно в GCK. Если использовать небольшой аккуратный трюк для достижения непрерывного обновления без изменения каких-либо реальных настроек контейнера, который меняет метку на текущий commit-short-sha.

Моя команда выглядит так:

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

Где вы можете использовать любое имя и любое значение для метки, если она меняется с каждой сборкой.

Радоваться, веселиться!

Дэвид Фабер
источник
6

Похоже, что k8s ожидает от нас предоставления разных тегов изображения для каждого развертывания. Моя стратегия по умолчанию - заставить систему CI генерировать и отправлять образы докеров, помечая их номером сборки:xpmatteo/foobar:456 .

Для локальной разработки может быть удобно использовать скрипт или make-файл, например:

# 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

Команда sedзаменяет заполнитель в документе развертывания фактически созданным тегом изображения.

xpmatteo
источник
kubernetes не требует, чтобы вы обновляли развертывание с помощью нового тега, чтобы получить самую последнюю версию любого образа, наиболее распространенным примером является «последняя».
Дэйв Уайт
1

Я использую Azure DevOps для развертывания контейнерных приложений, мне легко удается решить эту проблему с помощью идентификатора сборки.

Каждый раз, когда он строит и генерирует новый идентификатор сборки, я использую этот идентификатор сборки в качестве тега для изображения докера, вот пример

ImageName: buildID

как только ваш образ будет успешно построен (CI), в конвейере компакт-диска в файле развертывания yml я дал имя изображения как

ImageName: окр: buildID

здесь evn: buildid - это переменная azure DevOps, имеющая значение идентификатора сборки.

так что теперь каждый раз у меня есть новые изменения для сборки (CI) и развертывания (CD).

прокомментируйте, если вам нужно определение сборки для CI / CD.

Номан Садик
источник
Манифест является частью репо. Я не понимаю, как лучше всего это делать. Если я создаю образ в конвейере, должен ли я нажимать, чтобы освоить обновленный манифест? или я должен создать обновленный манифест для артефактов (и, таким образом, манифест в репозитории будет просто шаблоном без фактического изображения с тегами)?
паблете