Обновление на местесловосередина,"обновление"Не сложно понять,Это экземпляр приложения Воля из версии, замененной старой версией на новую версию. Так как знал Kubernetes А как насчет окружающей среды, чтобы понять «на месте»?
Давайте сначала посмотрим, как высвобождается собственная рабочая нагрузка K8. Здесь предполагается, что нам нужно развернуть приложение, включающее в себя два контейнера foo и bar в поде. Среди них версия образа, использованная при первом развертывании контейнера foo, была v1. Нам нужно обновить его до образа версии v2. Как это сделать?
image
Во время процесса обновления исходный объект Pod удаляется и создается новый объект Pod. Новый под назначается другому узлу, ему назначается новый IP-адрес, два контейнера foo и bar повторно извлекаются на этом узле, и контейнеры запускаются.
image
Стоит отметить, что хотя старый и новый поды называются pod-0, на самом деле это два совершенно разных объекта пода (uid также изменился). StatefulSet ждет, пока исходный объект pod-0 не будет полностью удален из кластера Kubernetes, прежде чем приступить к созданию нового объекта pod-0. Этот новый под также будет перепланирован, ему будет присвоен IP-адрес, получен образ и запущен контейнер.
-Так называемый режим обновления на месте позволяет избежать удаления или создания новых объектов Pod в процессе обновления приложения, а обновить версию образа одного или нескольких контейнеров на основе исходных объектов Pod:
В процессе обновления на месте мы только обновили поле изображения контейнера foo в исходном объекте Pod, чтобы инициировать обновление контейнера foo до новой версии. Независимо от того, изменились ли объект Pod, Node или IP, даже контейнер bar все еще работает во время обновления контейнера foo.
Подвести Итог: Это только обновления Pod одну или несколько версий контейнера, не затрагивая всю Pod Метод обновления объектов и других контейнеров называется Kubernetes Обновление на месте в .
Итак, почему мы представляем эту концепцию и дизайн обновления на месте в Kubernetes?
Прежде всего, такая модель обновления на месте значительно повышает эффективность выпуска приложений. Согласно неполной статистике, обновление на месте в среде Alibaba повышает скорость выпуска как минимум на 80% по сравнению с полной пересборкой и обновлением. На самом деле это легко понять. Обновление на месте обеспечивает следующие моменты оптимизации для повышения эффективности выпуска:
Во-вторых, когда мы обновляем некоторые дополнительные контейнеры в поде (например, сбор логов, мониторинг и т. д.), мы фактически не хотим вмешиваться в работу бизнес-контейнеров. Однако в этом сценарии обновление Deployment или StatefulSet приведет к перестройке всего пода, что неизбежно окажет определенное влияние на бизнес. Объем изменений при обновлении на месте на уровне контейнера легко контролируется. Пересозданы будут только те контейнеры, которые необходимо обновить, а другие контейнеры, включая сетевые и монтируемые диски, не будут затронуты.
Наконец, обновление на месте также обеспечивает стабильность и уверенность кластера. Когда большое количество приложений в кластере Kubernetes запускает перестроение обновлений подов, это может вызвать крупномасштабное смещение подов и повторную упреждающую миграцию некоторых подов с низким приоритетом задач на узле. Эти крупномасштабные реконструкции Pod сами по себе окажут большую нагрузку на центральные компоненты, такие как API-сервер, планировщик, распределение сети/диска и т. д., а задержки в этих компонентах также создадут порочный круг для реконструкции Pod. При обновлении на месте весь процесс обновления включает только обновление контроллером объекта Pod и перестройку kubelet соответствующего контейнера.
В Alibaba большинство приложений электронной коммерции выпускаются с использованием обновлений на месте в собственной облачной среде, и этот набор контроллеров, поддерживающих обновления на месте, находится в проекте с открытым исходным кодом OpenKruise.
Другими словами, все внутренние облачные приложения Alibaba используют расширенную рабочую нагрузку OpenKruise для развертывания и управления и не используют собственный Deployment/StatefulSet и т. д.
Так OpenKruise Как получить Обновление на местеспособностьиз Шерстяная ткань?существоватьпредставлять Обновление на месте Принцип Прежде чем приступить к реализации, давайте взглянем на некоторые обновления. на функция места зависит от из Родной Kubernetes Функция:
Kubelet на каждом узле рассчитает хэш-значение для каждого контейнера во всех контейнерах Pod.spec.containers на локальном компьютере и запишет его в фактически созданный контейнер.
Если мы изменим поле изображения контейнера в Pod, kubelet обнаружит, что хэш контейнера изменился и не соответствует хешу контейнера, созданному ранее на компьютере. Затем kubelet остановит старый контейнер и затем будет использовать его. в соответствии с последней спецификацией контейнера Pod, чтобы создать новый контейнер.
Эта функция на самом деле является основным принципом обновления на месте для одного модуля.
В собственном kube-apiserver запросы на обновление объектов Pod имеют строгую логику проверки:
// validate updateable fields:
// 1. spec.containers[*].image
// 2. spec.initContainers[*].image
// 3. spec.activeDeadlineSeconds
Проще говоря, для созданного пода в спецификации пода разрешено изменять только поле изображения в контейнерах/initContainers и поле activeDeadlineSeconds. Обновления всех остальных полей в спецификации Pod будут отклонены kube-apiserver.
kubelet сообщит о состоянии контейнера в файле pod.status, что соответствует фактическому статусу работы всех контейнеров в поде:
apiVersion: v1
kind: Pod
spec:
containers:
- name: nginx
image: nginx:latest
status:
containerStatuses:
- name: nginx
image: nginx:mainline
imageID: docker-pullable://nginx@sha256:2f68b99bc0d6d25d0c56876b924ec20418544ff28e1fb89a4c27679a40da811b
В большинстве случаев два изображения spec.containers[x].image и status.containerStatuses[x].image совпадают.
Однако бывают ситуации, подобные приведенной выше, когда изображение, сообщаемое kubelet, не соответствует изображению в спецификации (в спецификации указано nginx:latest, а в статусе — nginx:mainline).
Это потому что кубелет сообщил image На самом деле из CRI Имя изображения, соответствующее контейнеру, полученному в интерфейсе. И если Node На машине имеется несколько изображений, соответствующих одному imageID,Так Отчетиз可能да其серединалюбой:
$ docker images | grep nginx
nginx latest 2622e6cca7eb 2 days ago 132MB
nginx mainline 2622e6cca7eb 2 days ago
Следовательно, если поля изображения спецификации и статуса в поде несовместимы, это не означает, что версия образа, запускаемая контейнером на хосте, несовместима с ожидаемой.
существовать Kubernetes 1.12 предыдущая версия, Pod будь то в Ready статус просто kubelet Определите на основе состояния контейнера: если Pod Все средние контейнеры ready,Так Pod Просто в Ready состояние.
Но на самом деле во многих случаях оператору или пользователю верхнего уровня требуется возможность контролировать готовность модуля. Поэтому Kubernetes версии 1.12 и более поздних версий предоставляет функцию ReadinessGates для реализации этого сценария. следующее:
apiVersion: v1
kind: Pod
spec:
readinessGates:
- conditionType: MyDemo
status:
conditions:
- type: MyDemo
status: "True"
- type: ContainersReady
status: "True"
- type: Ready
status: "True"
В настоящее время существует два обязательных условия для того, чтобы kubelet мог определить готовность пода:
Только при выполнении двух вышеуказанных предварительных условий kubelet сообщит о состоянии готовности как True.
После понимания четырех вышеупомянутых предпосылок, давайте проанализируем OpenKruise дакаксуществовать Kubernetes Принцип реализации обновления на месте.
Как видно из «Фоны 1», на самом деле, если мы изменим поля в spec.containers[x] существующего пода, kubelet почувствует, что хэш этого контейнера изменился, и тогда он остановит соответствующий старый контейнер и используйте новый контейнер для извлечения изображений, создания и запуска новых контейнеров.
Как видно из «Фон 2», текущие изменения, которые мы вносим в spec.containers[x] существующего пода, ограничены полем изображения.
Отсюда следует, что первый Принцип реализация: **верно к существующему из Pod Объект, мы можем и можем только его модифицировать spec.containers[x].image поле для запуска Pod Обновите соответствующий контейнер до нового. image。
Следующий вопрос: после того как мы изменим поле spec.containers[x].image в Pod, как определить, что kubelet успешно пересобрал контейнер?
По "Фон. 3" видно, сравните spec и status в image Поле ненадежно, потому что очень возможно status Тот, о котором сообщалось в Node Сохранить существованиеиз другого имени зеркала (того же imageID)。
поэтому,Получите второй Принцип реализации:суждение Pod Обновление на сели успешны, условно говоря, более надежным методом является существование Обновление на местевперед Первый генерал status.containerStatuses[x].imageID Запишите это. существование обновлено spec После зеркалирования, если оно наблюдается Pod из status.containerStatuses[x].imageID изменений, мы считаем, что обновление на месте перестроило контейнер.
Но таким образом,насверно Обновление на местеиз image Также есть требование: его нельзя использовать image Имена (теги) разные, но на самом деле соответствуют одному и тому же imageID иззеркало Приди и сделай это Обновление на месте, иначе могло быть суждениедля и обновление не удалось (из-за status середина imageID не изменится).
Конечно, мы можем продолжить оптимизацию в будущем. Опен Круиз То есть воля с открытым исходным кодом зеркала с подогревом из возможности, пройдет DaemonSet существоватькаждый Node Разверните один на NodeImage Под. проходить NodeImage Сообщите об этом и мы узнаем pod spec в image Местоверноотвечатьиз imageID, затем и pod status в imageID Сравнение позволяет точно определить, является ли обновление на месте успешным.
существовать Kubernetes середина,один Pod ли Ready Это означает, что он может предоставлять услуги. Итак, как Service Этот вид въезда будет проходить через суждение. Pod Ready Приходи и выбирай, может ли Воля это Pod присоединиться endpoints 端点середина。
По "Фон. 4" видно из Kubernetes 1.12+ После этого оператор/контролер Эти компоненты также можно настроить через readinessGates èОбновить pod.status.conditions в Настроить type статус для контроля Pod ли доступен.
поэтому,Получите третий принцип реализации:Можетсуществовать pod.spec.readinessGates середина определяет человека по имени InPlaceUpdateReady из conditionType。
существовать Обновление на местечас:
После завершения обновления на месте InPlaceUpdateReady condition установлен на «Правда» делает Pod вернуться в Ready состояние.
кроме тогосуществовать Обновление на местоиз двух шагов середина, первый шаг Воля Pod Изменить на NotReady После этого компонент потока становится асинхронным. watch Изменение и удаление конечной точки может занять некоторое время. Поэтому мы также предлагаем элегантное Обновление. на размещаемость, то есть gracePeriodSeconds Конфигурациясуществовать修改 NotReady статус и реальное обновление image курок Обновление на место изтихо период времени между двумя шагами.
Обновление на местеи Pod Подобно пересборке и обновлению, его можно выполнять в сочетании с различными стратегиями выпуска:
Как упоминалось выше,OpenKruise объединить Kubernetes Роднойпоставлятьиз kubelet Управление версиями контейнеров, готовностьGates и другие функции,реализованные для Pod из Обновление на местеспособность。
и Обновление на Место также для выпуска приложений приносит значительные улучшения в эффективности и стабильности. Стоит обратить внимание Однако по мере увеличения масштаба кластеров и приложений это улучшение будет становиться все более очевидным. Это Обновление на Возможности площадки, существовавшие в последние два года, помогли Alibaba плавно перейти на сверхкрупномасштабные контейнеры приложений Alibaba. Kubernetes изоблако Роднойсреда,и Родной Deployment/StatefulSet Совершенно невозможно распространять и использовать его в среде такого размера.
Источник (авторские права принадлежат оригинальному автору): https://developer.aliyun.com/article/765421