Совместимость версий контейнеров Windows

Область применения: Windows Server 2022, Windows Server 2019, Windows Server 2016

Windows Server 2016 и юбилейное обновление Windows 10 (версии 14393) стали первыми выпусками Windows, которые могли выполнять сборку и запускать контейнеры Windows Server. Контейнеры, созданные с помощью этих версий, можно запускать в более поздних выпусках, но перед этим необходимо изучить некоторые подробности.

Архитектура Windows существенно отличается от архитектуры Linux. В Linux есть монолитное ядро, в то время как в Windows режимы пользователя и ядра более тесно связаны. До реализации контейнеров режимы пользователя и ядра в Windows предоставлялись синхронно, что приводило к необходимости удовлетворять требования к совместимости контейнеров в Windows, что отличается от конфигурации в Linux.

Разделение режимов пользователя и ядра в Windows — это монументальная и весьма нетривиальная задача, но мы прилагаем все усилия, чтобы стабилизировать эту границу во всех ОС Windows, чтобы наши клиенты могли гибко запускать контейнеры прежних версий. Начиная с Windows 11 и Windows Server 2022, мы предоставляем возможность запуска изолированных от процессов контейнеров WS2022 на узлах Windows 11. Мы сделали все возможное, чтобы зафиксировать области, которые нарушают эту границу, но теперь хотим открыть эту возможность для разработчиков Windows 11 для обратной связи. Поэтому сообщите нам, если у вас возникнут проблемы.

Для любого другого сценария, когда возможно несоответствие между версиями Windows узлов и гостевых систем между режимами пользователя и ядра, но это не гарантируется, следовательно, запуск образа контейнера на узле невозможен. Для любой несоответствующей версии процессы с изоляцией Hyper-V предоставляют контейнеру набор соответствующих двоичных файлов ядра и не зависят от версии узла. Подробные сведения о матрице совместимости см. в таблицах ниже.

Совместимость ОС узла Windows Server

Версия ОС базового образа контейнера Поддержка изоляции Hyper-V Поддержка изоляции процессов
Windows Server 2022
Windows Server 2019
Windows Server 2016

Совместимость ОС узла клиента Windows

Версия ОС базового образа контейнера Поддержка изоляции Hyper-V Поддержка изоляции процессов
Windows Server 2022 ✔ (предварительная версия)
Windows Server 2019
Windows Server 2016

Примечание.

Windows 10 версии 1809 и Windows Server 2019 имели одинаковый номер сборки в настоящее время. С тех пор они получили независимые обновления, что приводит к несоответствию номера сборки. Изоляция процессов в клиенте Windows доступна в предварительной версии для Windows 11 с образами Windows Server 2022 с несоответствием номера сборки. Если у вас есть требование запустить изолированные контейнеры обработки в Windows 10, сообщите нам о проблемах с GitHub.

Сопоставление версии узла контейнера с версиями образа контейнера

Контейнеры Windows Server

Номер сборки (новая версия Windows)

Операционная система Windows имеет четыре уровня указания версии: основной номер, дополнительный номер, номер сборки и номер редакции. Например, версия 10.0.14393.103 будет иметь основную версию 10, дополнительную версию 0, номер сборки 14393 и номер редакции 103. Номер сборки меняется только при публикации новых версий ОС. Номер редакции обновляется по мере установки обновлений Windows.

Кроме случаев использования WS2022 + Windows 11, контейнеры Windows Server не будут запускаться, если номера сборки узла контейнера и образа контейнера отличаются. Например, если узел контейнера имеет версию 10.0.14393.* (Windows Server 2016) и пытаетесь запустить контейнер с изображением версии 10.0.16299.* (Windows Server, версия 1709) служба вычислений ОС вернет ошибку несовместимости версий.

Ограничения для Windows Server 2016

Контейнеры на базе Windows Server 2016 не будут выполняться в системе, если номера редакции узла контейнера и образа контейнера отличаются. Например, если узел контейнера имеет версию 10.0.14393.1914 (Windows Server 2016 с исправлением KB4051033), а образ контейнера версию 10.0.14393.1944 (Windows Server 2016 с исправлением KB4053579), то образ может не запуститься.

Для узлов или образов с помощью Windows Server версии 1809 и более поздних версий это правило не применяется. Образ узла и контейнера не нуждаются в совпадающих редакциях.

Примечание.

Для обеспечения безопасности и совместимости настоятельно рекомендуется устанавливать последние исправления и обновления для узла и контейнеров. Важные рекомендации по обновлению контейнеров Windows см. в этой статье.

Практическое применение

Пример 1. Узел контейнера работает под управлением Windows Server 2016 с исправлением KB4041691. Все контейнеры Windows Server, развернутые на этом узле, должны быть основаны на образах контейнера версии 10.0.14393.1770. Если вы применяете обновление KB4053579 к контейнеру узла, необходимо также обновить образы, чтобы убедиться, что контейнер узла их поддерживает.

Пример 2. Узел контейнера работает под управлением Windows Server версии 1809 с применением KB4534273. Все контейнеры Windows Server, развернутые на этом узле, должны быть основаны на базовом образе контейнера Windows Server версии 1809 (10.0.17763), но не обязаны соответствовать KB узла. Если обновление KB4534273 применено к узлу, образы контейнеров по-прежнему будут поддерживаться, но рекомендуется обновить их для устранения всех потенциальных проблем безопасности.

Запрос версии

Метод 1. Введенная в версии 1709, команда cmd и ver теперь возвращают сведения о редакции.

Microsoft Windows [Version 10.0.16299.125]
(c) 2017 Microsoft Corporation. All rights reserved.

C:\>ver

Microsoft Windows [Version 10.0.16299.125]

Метод 2. Запросите следующий раздел реестра: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion

Например:

C:\>reg query "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion" /v BuildLabEx
Windows PowerShell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS C:\Users\Administrator> (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\').BuildLabEx
14393.321.amd64fre.rs1_release_inmarket.161004-2338

Чтобы узнать версию используемого базового образа, просмотрите теги в Docker Hub или хэш-таблицу образа в описании образа. Информацию о датах выпуска всех сборок и редакций можно найти на странице журнала обновлений Windows 10.

Изоляция Hyper-V для контейнеров

Контейнеры Windows можно запускать с изоляцией Hyper-V и без нее. Изоляция Hyper-V создает безопасную границу вокруг контейнера с оптимизированной виртуальной машиной. В отличие от стандартных контейнеров Windows, где для контейнеров и узла используется одно ядро, каждый изолированный контейнер Hyper-V использует собственный экземпляр ядра Windows. Это означает, что в узле контейнера и образе могут быть разные версии ОС (для дополнительных сведений см. матрицу совместимости ниже).

Чтобы запустить контейнер с изоляцией Hyper-V, просто добавьте тег --isolation=hyperv в команду docker run.

Ошибки из несовпадных версий

При попытке использования неподдерживаемого сочетания возникает следующая ошибка:

docker: Error response from daemon: container b81ed896222eb87906ccab1c3dd2fc49324eafa798438f7979b87b210906f839 encountered an error during CreateContainer: failure in a Windows system call: The operating system of the container does not match the operating system of the host. (0xc0370101) extra info: {"SystemType":"Container","Name":"b81ed896222eb87906ccab1c3dd2fc49324eafa798438f7979b87b210906f839","Owner":"docker","IsDummy":false,"VolumePath":"\\\\?\\Volume{2443d38a-1379-4bcf-a4b7-fc6ad4cd7b65}","IgnoreFlushesDuringBoot":true,"LayerFolderPath":"C:\\ProgramData\\docker\\windowsfilter\\b81ed896222eb87906ccab1c3dd2fc49324eafa798438f7979b87b210906f839","Layers":[{"ID":"1532b584-8431-5b5a-8735-5e1b4fe9c2a9","Path":"C:\\ProgramData\\docker\\windowsfilter\\b2b88bc2a47abcc682e422507abbba9c9b6d826d34e67b9e4e3144cc125a1f80"},{"ID":"a64b8da5-cd6e-5540-bc73-d81acae6da54","Path":"C:\\ProgramData\\docker\\windowsfilter\\5caaedbced1f546bccd01c9d31ea6eea4d30701ebba7b95ee8faa8c098a6845a"}],"HostName":"b81ed896222e","MappedDirectories":[],"HvPartition":false,"EndpointList":["002a0d9e-13b7-42c0-89b2-c1e80d9af243"],"Servicing":false,"AllowUnqualifiedDNSQuery":true}.

Устранить эту ошибку можно тремя способами:

  • Заново создайте контейнер на основе правильной версии mcr.microsoft.com/microsoft-windows-nanoserver или mcr.microsoft.com/windows/servercore.
  • Если узел более новый, выполните docker run --isolation=hyperv ...
  • Запустите контейнер на другом узле с такой же версией Windows.

Выбор версии ОС контейнера для использования

Примечание.

По состоянию на 16 апреля 2019 г. тег "последний" больше не публикуется или не поддерживается для образов контейнеров ОС Windows Server, Windows Server Core и Nano Server . При извлечении или ссылке изображений из этих репозиториев необходимо объявить определенный тег.

Необходимо знать, какую версию необходимо использовать для контейнера. Например, если вы хотите использовать Windows Server версии 1809 в качестве ОС контейнера и получить последние исправления для нее, используйте тег 1809, когда будете указывать базовую версию ОС образов контейнера. Например:

FROM mcr.microsoft.com/windows/nanoserver:1809
...

Тем не менее, если вам требуется определенное исправление Windows Server версии 1809, вы можете указать номер статьи базы знаний в теге. Например, чтобы получить базовый образ контейнера с ОС Nano Server из Windows Server версии 1809 с примененным исправлением KB4493509, укажите следующие данные:

FROM mcr.microsoft.com/windows/nanoserver:1809-KB4493509
...

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

FROM mcr.microsoft.com/windows/nanoserver:10.0.17763.437
...

Базовые образы Server Core, основанные на Windows Server 2022 и Windows Server 2019, являются выпусками канала Long-Term Servicing Channel (LTSC). Если для экземпляра требуется, чтобы ОС Windows Server 2019 использовалась в качестве ОС контейнера образа Server Core и для нее нужно установить последние исправления, вы можете указать выпуски LTSC следующим образом:

FROM mcr.microsoft.com/windows/servercore:ltsc2019
...

Сопоставление версий с помощью Docker Swarm

В настоящее время в Docker Swarm не предусмотрен встроенный способ сопоставления версии Windows контейнера с узлом, в котором используется та же версия ОС. Если служба обновляется для использования нового контейнера, она будет успешно запущена.

Если необходимо запустить несколько версий Windows в течение длительного периода времени, то для этого существует два возможных способа: настроить узлы Windows так, чтобы они всегда использовали изоляцию Hyper-V или ограничения меток.

Поиск службы, которая не запустится

Если служба не запускается, элемент MODE будет указан как replicated, но значение REPLICAS будет равно 0. Чтобы проверить, вызвана ли проблема версией ОС, выполните следующие команды:

Выполните команду docker service ls, чтобы найти имя службы:

ID                  NAME                MODE                REPLICAS            IMAGE                                             PORTS
xh6mwbdq2uil        angry_liskov        replicated          0/1                 windows/servercore/iis

Выполните команду docker service ps (имя службы), чтобы получить состояние и последние попытки:

C:\Program Files\Docker>docker service ps angry_liskov
ID                  NAME                 IMAGE                                             NODE                DESIRED STATE       CURRENT STATE               ERROR                              PORTS
klkbhn742lv0        angry_liskov.1       windows/servercore/iis   WIN-BSTMQDRQC2E     Ready               Ready 3 seconds ago
y5blbdum70zo         \_ angry_liskov.1   windows/servercore/iis   WIN-BSTMQDRQC2E     Shutdown            Failed 24 seconds ago       "starting container failed: co…"
yjq6zwzqj8kt         \_ angry_liskov.1   windows/servercore/iis   WIN-BSTMQDRQC2E     Shutdown            Failed 31 seconds ago       "starting container failed: co…"

ytnnv80p03xx         \_ angry_liskov.1   windows/servercore/iis   WIN-BSTMQDRQC2E     Shutdown            Failed about a minute ago   "starting container failed: co…"
xeqkxbsao57w         \_ angry_liskov.1   windows/servercore/iis   WIN-BSTMQDRQC2E     Shutdown            Failed about a minute ago   "starting container failed: co…"

Если вы видите сообщение starting container failed: ..., чтобы просмотреть полное описание ошибки, выполните команду docker service ps --no-trunc (имя контейнера):

C:\Program Files\Docker>docker service ps --no-trunc angry_liskov
ID                          NAME                 IMAGE                                                                                                                     NODE                DESIRED STATE       CURRENT STATE                     ERROR                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          PORTS
dwsd6sjlwsgic5vrglhtxu178   angry_liskov.1       windows/servercore/iis@sha256:868bca7e89e1743792e15f78edb5a73070ef44eae6807dc3f05f9b94c23943d5   WIN-BSTMQDRQC2E     Running             Starting less than a second ago
y5blbdum70zoh1f6uhx5nxsfv    \_ angry_liskov.1   windows/servercore/iis@sha256:868bca7e89e1743792e15f78edb5a73070ef44eae6807dc3f05f9b94c23943d5   WIN-BSTMQDRQC2E     Shutdown            Failed 39 seconds ago             "starting container failed: container e7b5d3adba7e510569c18d8e55f7c689d7cb92be40a516c91b363e27f84604d0 encountered an error during CreateContainer: failure in a Windows system call: The operating system of the container does not match the operating system of the host. (0xc0370101) extra info: {"SystemType":"Container","Name":"e7b5d3adba7e510569c18d8e55f7c689d7cb92be40a516c91b363e27f84604d0","Owner":"docker","VolumePath":"\\\\?\\Volume{2443d38a-1379-4bcf-a4b7-fc6ad4cd7b65}","IgnoreFlushesDuringBoot":true,"LayerFolderPath":"C:\\ProgramData\\docker\\windowsfilter\\e7b5d3adba7e510569c18d8e55f7c689d7cb92be40a516c91b363e27f84604d0","Layers":[{"ID":"bcf2630f-ea95-529b-b33c-e5cdab0afdb4","Path":"C:\\ProgramData\\docker\\windowsfilter\\200235127f92416724ae1d53ed3fdc86d78767132d019bdda1e1192ee4cf3ae4"},{"ID":"e3ea10a8-4c2f-5b93-b2aa-720982f116f6","Path":"C:\\ProgramData\\docker\\windowsfilter\\0ccc9fa71a9f4c5f6f3bc8134fe3533e454e09f453de662cf99ab5d2106abbdc"},{"ID":"cff5391f-e481-593c-aff7-12e080c653ab","Path":"C:\\ProgramData\\docker\\windowsfilter\\a49576b24cd6ec4a26202871c36c0a2083d507394a3072186133131a72601a31"},{"ID":"499cb51e-b891-549a-b1f4-8a25a4665fbd","Path":"C:\\ProgramData\\docker\\windowsfilter\\fdf2f52c4323c62f7ff9b031c0bc3af42cf5fba91098d51089d039fb3e834c08"},{"ID":"1532b584-8431-5b5a-8735-5e1b4fe9c2a9","Path":"C:\\ProgramData\\docker\\windowsfilter\\b2b88bc2a47abcc682e422507abbba9c9b6d826d34e67b9e4e3144cc125a1f80"},{"ID":"a64b8da5-cd6e-5540-bc73-d81acae6da54","Path":"C:\\ProgramData\\docker\\windowsfilter\\5caaedbced1f546bccd01c9d31ea6eea4d30701ebba7b95ee8faa8c098a6845a"}],"HostName":"e7b5d3adba7e","HvPartition":false,"EndpointList":["298bb656-8800-4948-a41c-1b0500f3d94c"],"AllowUnqualifiedDNSQuery":true}"

Это та же ошибка, что и CreateContainer: failure in a Windows system call: The operating system of the container does not match the operating system of the host. (0xc0370101).

Исправление. Обновление службы для использования соответствующей версии

Существует два соображения для Docker Swarm. Если у вас есть файл Compose, содержащий службу, которая использует образ, созданный не вами, необходимо изменить ссылку соответствующим образом. Например:

version: '3'

services:
  YourServiceName:
    image: windows/servercore:1709
...

Вторая ситуация — образ, на который вы ссылаетесь, создан вами (например, contoso/myimage):

version: '3'

services:
  YourServiceName:
    image: contoso/myimage
...

В этом случае вы можете использовать метод, описанный в разделе Ошибки из-за несовпадения версий, для изменения этого файла dockerfile вместо строки docker-compose.

Устранение рисков. Использование изоляции Hyper-V с Docker Swarm

Контейнеры Windows поддерживают использование изоляции Hyper-V на каждом отдельном контейнере, что требует изменения конфигурации Docker и последующего перезапуска модуля Docker.

  1. Измените C:\ProgramData\docker\config\daemon.json.

  2. Добавьте строку с "exec-opts":["isolation=hyperv"].

    Примечание.

    Файл daemon.json по умолчанию не существует. Если вы обнаружите, что это происходит при просмотре каталога, необходимо создать файл. Затем скопируйте в него следующее содержимое:

    {
        "exec-opts":["isolation=hyperv"]
    }
    
  3. Закройте и сохраните файл, а затем перезапустите подсистему Docker, выполнив следующие командлеты в PowerShell:

    Stop-Service docker
    Start-Service docker
    
  4. После перезапуска службы запустите контейнеры. Затем вы можете проверить уровень изоляции контейнера, изучив его с помощью следующего командлета:

    docker inspect --format='{{json .HostConfig.Isolation}}' $instanceNameOrId
    

Он возвращает значение "process" или "hyperv". Если вы изменили и задали daemon.json, как описано выше, он должен отобразить последний.

Устранение рисков. Использование меток и ограничений

Ниже показано, как использовать метки и ограничения для сопоставления версий:

  1. Добавьте метки для каждого узла.

    На каждом узле добавьте две метки: OS и OsVersion. Это предполагает локальное выполнение, но может быть изменено, чтобы задать их на удаленном узле.

    docker node update --label-add OS="windows" $ENV:COMPUTERNAME
    docker node update --label-add OsVersion="$((Get-ComputerInfo).OsVersion)" $ENV:COMPUTERNAME
    

    Затем вы можете проверить их, выполнив команду docker node inspect, которая должна показать недавно добавленные метки:

           "Spec": {
                "Labels": {
                   "OS": "windows",
                   "OsVersion": "10.0.16296"
               },
                "Role": "manager",
                "Availability": "active"
            }
    
  2. Добавьте ограничение службы.

    Теперь, когда вы добавили метки для каждого узла, можно обновить ограничения, которые определяют размещение служб. В примере ниже замените contoso_service на имя вашей службы:

    docker service update \
        --constraint-add "node.labels.OS == windows" \
        --constraint-add "node.labels.OsVersion == $((Get-ComputerInfo).OsVersion)" \
        contoso_service
    

    Это применяет и ограничивает выполнение узла.

Дополнительные сведения об использовании ограничений службы см. в справочнике по команде service create.

Сопоставление версий с помощью Kubernetes

Та же проблема, описанная в разделе Сопоставление версий с помощью Docker Swarm, может возникнуть, если модули pod запланированы для выполнения в Kubernetes. Эту проблему можно избежать с помощью аналогичных методов.

  • Заново создайте контейнера на основе той же версии ОС в среде разработки и производственной среде. Дополнительные сведения см. в разделе Выбор версии ОС контейнера для использования.
  • Используйте метки узла и NodeSelector, чтобы назначить модули pod совместимым узлам, если узлы Windows Server 2016 и Windows Server 1709 версии находятся в одном кластере.
  • Использование отдельных кластеров на основе версии ОС

Сбой поиска модулей pod в несоответствии ОС

В этом случае развертывание содержит модуль pod, который был назначен узлу с несовпадающей версией ОС и без изоляции Hyper-V.

Эта же ошибка отображается в событиях, перечисленных с kubectl describe pod <podname>. После нескольких попыток модуль pod, вероятно, будет в состоянии CrashLoopBackOff.

$ kubectl -n plang describe pod fabrikamfiber.web-789699744-rqv6p

Name:           fabrikamfiber.web-789699744-rqv6p
Namespace:      plang
Node:           38519acs9011/10.240.0.6
Start Time:     Mon, 09 Oct 2017 19:40:30 +0000
Labels:         io.kompose.service=fabrikamfiber.web
                pod-template-hash=789699744
Annotations:    kubernetes.io/created-by={"kind":"SerializedReference","apiVersion":"v1","reference":{"kind":"ReplicaSet","namespace":"plang","name":"fabrikamfiber.web-789699744","uid":"b5062a08-ad29-11e7-b16e-000d3a...
Status:         Running
IP:             10.244.3.169
Created By:     ReplicaSet/fabrikamfiber.web-789699744
Controlled By:  ReplicaSet/fabrikamfiber.web-789699744
Containers:
  fabrikamfiberweb:
    Container ID:       docker://eab0151378308315ed6c31adf4ad9e31e6d65fd300e56e742757004a969a803a
    Image:              patricklang/fabrikamfiber.web:latest
    Image ID:           docker-pullable://patricklang/fabrikamfiber.web@sha256:562741016ce7d9a232a389449a4fd0a0a55aab178cf324144404812887250ead
    Port:               80/TCP
    State:              Waiting
      Reason:           CrashLoopBackOff
    Last State:         Terminated
      Reason:           ContainerCannotRun
      Message:          container eab0151378308315ed6c31adf4ad9e31e6d65fd300e56e742757004a969a803a encountered an error during CreateContainer: failure in a Windows system call: The operating system of the container does not match the operating system of the host. (0xc0370101) extra info: {"SystemType":"Container","Name":"eab0151378308315ed6c31adf4ad9e31e6d65fd300e56e742757004a969a803a","Owner":"docker","IsDummy":false,"VolumePath":"\\\\?\\Volume{037b6606-bc9c-461f-ae02-829c28410798}","IgnoreFlushesDuringBoot":true,"LayerFolderPath":"C:\\ProgramData\\docker\\windowsfilter\\eab0151378308315ed6c31adf4ad9e31e6d65fd300e56e742757004a969a803a","Layers":[{"ID":"f8bc427f-7aa3-59c6-b271-7331713e9451","Path":"C:\\ProgramData\\docker\\windowsfilter\\e206d2514a6265a76645b9d6b3dc6a78777c34dbf5da9fa2d564651645685881"},{"ID":"a6f35e41-a86c-5e4d-a19a-a6c2464bfb47","Path":"C:\\ProgramData\\docker\\windowsfilter\\0f21f1e28ef13030bbf0d87cbc97d1bc75f82ea53c842e9a3250a2156ced12d5"},{"ID":"4f624ca7-2c6d-5c42-b73f-be6e6baf2530","Path":"C:\\ProgramData\\docker\\windowsfilter\\4d9e2ad969fbd74fd58c98b5ab61e55a523087910da5200920e2b6f641d00c67"},{"ID":"88e360ff-32af-521d-9a3f-3760c12b35e2","Path":"C:\\ProgramData\\docker\\windowsfilter\\9e16a3d53d3e9b33344a6f0d4ed34c8a46448ee7636b672b61718225b8165e6e"},{"ID":"20f1a4e0-a6f3-5db3-9bf2-01fd3e9e855a","Path":"C:\\ProgramData\\docker\\windowsfilter\\7eec7f59f9adce38cc0a6755da58a3589287d920d37414b5b21b5b543d910461"},{"ID":"c2b3d728-4879-5343-a92a-b735752a4724","Path":"C:\\ProgramData\\docker\\windowsfilter\\8ed04b60acc0f65f541292a9e598d5f73019c8db425f8d49ea5819eab16a42f3"},{"ID":"2973e760-dc59-5800-a3de-ab9d93be81e5","Path":"C:\\ProgramData\\docker\\windowsfilter\\cc71305d45f09ce377ef497f28c3a74ee027c27f20657d2c4a5f157d2457cc75"},{"ID":"454a7d36-038c-5364-8a25-fa84091869d6","Path":"C:\\ProgramData\\docker\\windowsfilter\\9e8cde1ce8f5de861a5f22841f1ab9bc53d5f606d06efeacf5177f340e8d54d0"},{"ID":"9b748c8c-69eb-55fb-a1c1-5688cac4efd8","Path":"C:\\ProgramData\\docker\\windowsfilter\\8e02bf5404057055a71d542780a2bb2731be4b3707c01918ba969fb4d83b98ec"},{"ID":"bfde5c26-b33f-5424-9405-9d69c2fea4d0","Path":"C:\\ProgramData\\docker\\windowsfilter\\77483cedfb0964008c33d92d306734e1fab3b5e1ebb27e898f58ccfd108108f2"},{"ID":"bdabfbf5-80d1-57f1-86f3-448ce97e2d05","Path":"C:\\ProgramData\\docker\\windowsfilter\\aed2ebbb31ad24b38ee8521dd17744319f83d267bf7f360bc177e27ae9a006cf"},{"ID":"ad9b34f2-dcee-59ea-8962-b30704ae6331","Path":"C:\\ProgramData\\docker\\windowsfilter\\d44d3a675fec1070b61d6ea9bacef4ac12513caf16bd6453f043eed2792f75d8"}],"HostName":"fabrikamfiber.web-789699744-rqv6p","MappedDirectories":[{"HostPath":"c:\\var\\lib\\kubelet\\pods\\b50f0027-ad29-11e7-b16e-000d3afd2878\\volumes\\kubernetes.io~secret\\default-token-rw9dn","ContainerPath":"c:\\var\\run\\secrets\\kubernetes.io\\serviceaccount","ReadOnly":true,"BandwidthMaximum":0,"IOPSMaximum":0}],"HvPartition":false,"EndpointList":null,"NetworkSharedContainerName":"586870f5833279678773cb700db3c175afc81d557a75867bf39b43f985133d13","Servicing":false,"AllowUnqualifiedDNSQuery":false}
      Exit Code:        128
      Started:          Mon, 09 Oct 2017 20:27:08 +0000
      Finished:         Mon, 09 Oct 2017 20:27:08 +0000
    Ready:              False
    Restart Count:      10
    Environment:        <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-rw9dn (ro)
Conditions:
  Type          Status
  Initialized   True
  Ready         False
  PodScheduled  True
Volumes:
  default-token-rw9dn:
    Type:       Secret (a volume populated by a Secret)
    SecretName: default-token-rw9dn
    Optional:   false
QoS Class:      BestEffort
Node-Selectors: beta.kubernetes.io/os=windows
Tolerations:    <none>
Events:
  FirstSeen     LastSeen        Count   From                    SubObjectPath                           Type            Reason                  Message
  ---------     --------        -----   ----                    -------------                           --------        ------                  -------
  49m           49m             1       default-scheduler                                               Normal          Scheduled               Successfully assigned fabrikamfiber.web-789699744-rqv6p to 38519acs9011
  49m           49m             1       kubelet, 38519acs9011                                           Normal          SuccessfulMountVolume   MountVolume.SetUp succeeded for volume "default-token-rw9dn"
  29m           29m             1       kubelet, 38519acs9011   spec.containers{fabrikamfiberweb}       Warning         Failed                  Failed to pull image "patricklang/fabrikamfiber.web:latest": rpc error: code = 2 desc = Error response from daemon: {"message":"Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io: no such host"}
  49m           3m              12      kubelet, 38519acs9011   spec.containers{fabrikamfiberweb}       Normal          Pulling                 pulling image "patricklang/fabrikamfiber.web:latest"
  33m           3m              11      kubelet, 38519acs9011   spec.containers{fabrikamfiberweb}       Normal          Pulled                  Successfully pulled image "patricklang/fabrikamfiber.web:latest"
  33m           3m              11      kubelet, 38519acs9011   spec.containers{fabrikamfiberweb}       Normal          Created                 Created container
  33m           2m              11      kubelet, 38519acs9011   spec.containers{fabrikamfiberweb}       Warning         Failed                  Error: failed to start container "fabrikamfiberweb": Error response from daemon: {"message":"container fabrikamfiberweb encountered an error during CreateContainer: failure in a Windows system call: The operating system of the container does not match the operating system of the host. (0xc0370101) extra info: {\"SystemType\":\"Container\",\"Name\":\"fabrikamfiberweb\",\"Owner\":\"docker\",\"IsDummy\":false,\"VolumePath\":\"\\\\\\\\?\\\\Volume{037b6606-bc9c-461f-ae02-829c28410798}\",\"IgnoreFlushesDuringBoot\":true,\"LayerFolderPath\":\"C:\\\\ProgramData\\\\docker\\\\windowsfilter\\\\fabrikamfiberweb\",\"Layers\":[{\"ID\":\"f8bc427f-7aa3-59c6-b271-7331713e9451\",\"Path\":\"C:\\\\ProgramData\\\\docker\\\\windowsfilter\\\\e206d2514a6265a76645b9d6b3dc6a78777c34dbf5da9fa2d564651645685881\"},{\"ID\":\"a6f35e41-a86c-5e4d-a19a-a6c2464bfb47\",\"Path\":\"C:\\\\ProgramData\\\\docker\\\\windowsfilter\\\\0f21f1e28ef13030bbf0d87cbc97d1bc75f82ea53c842e9a3250a2156ced12d5\"},{\"ID\":\"4f624ca7-2c6d-5c42-b73f-be6e6baf2530\",\"Path\":\"C:\\\\ProgramData\\\\docker\\\\windowsfilter\\\\4d9e2ad969fbd74fd58c98b5ab61e55a523087910da5200920e2b6f641d00c67\"},{\"ID\":\"88e360ff-32af-521d-9a3f-3760c12b35e2\",\"Path\":\"C:\\\\ProgramData\\\\docker\\\\windowsfilter\\\\9e16a3d53d3e9b33344a6f0d4ed34c8a46448ee7636b672b61718225b8165e6e\"},{\"ID\":\"20f1a4e0-a6f3-5db3-9bf2-01fd3e9e855a\",\"Path\":\"C:\\\\ProgramData\\\\docker\\\\windowsfilter\\\\7eec7f59f9adce38cc0a6755da58a3589287d920d37414b5b21b5b543d910461\"},{\"ID\":\"c2b3d728-4879-5343-a92a-b735752a4724\",\"Path\":\"C:\\\\ProgramData\\\\docker\\\\windowsfilter\\\\8ed04b60acc0f65f541292a9e598d5f73019c8db425f8d49ea5819eab16a42f3\"},{\"ID\":\"2973e760-dc59-5800-a3de-ab9d93be81e5\",\"Path\":\"C:\\\\ProgramData\\\\docker\\\\windowsfilter\\\\cc71305d45f09ce377ef497f28c3a74ee027c27f20657d2c4a5f157d2457cc75\"},{\"ID\":\"454a7d36-038c-5364-8a25-fa84091869d6\",\"Path\":\"C:\\\\ProgramData\\\\docker\\\\windowsfilter\\\\9e8cde1ce8f5de861a5f22841f1ab9bc53d5f606d06efeacf5177f340e8d54d0\"},{\"ID\":\"9b748c8c-69eb-55fb-a1c1-5688cac4efd8\",\"Path\":\"C:\\\\ProgramData\\\\docker\\\\windowsfilter\\\\8e02bf5404057055a71d542780a2bb2731be4b3707c01918ba969fb4d83b98ec\"},{\"ID\":\"bfde5c26-b33f-5424-9405-9d69c2fea4d0\",\"Path\":\"C:\\\\ProgramData\\\\docker\\\\windowsfilter\\\\77483cedfb0964008c33d92d306734e1fab3b5e1ebb27e898f58ccfd108108f2\"},{\"ID\":\"bdabfbf5-80d1-57f1-86f3-448ce97e2d05\",\"Path\":\"C:\\\\ProgramData\\\\docker\\\\windowsfilter\\\\aed2ebbb31ad24b38ee8521dd17744319f83d267bf7f360bc177e27ae9a006cf\"},{\"ID\":\"ad9b34f2-dcee-59ea-8962-b30704ae6331\",\"Path\":\"C:\\\\ProgramData\\\\docker\\\\windowsfilter\\\\d44d3a675fec1070b61d6ea9bacef4ac12513caf16bd6453f043eed2792f75d8\"}],\"HostName\":\"fabrikamfiber.web-789699744-rqv6p\",\"MappedDirectories\":[{\"HostPath\":\"c:\\\\var\\\\lib\\\\kubelet\\\\pods\\\\b50f0027-ad29-11e7-b16e-000d3afd2878\\\\volumes\\\\kubernetes.io~secret\\\\default-token-rw9dn\",\"ContainerPath\":\"c:\\\\var\\\\run\\\\secrets\\\\kubernetes.io\\\\serviceaccount\",\"ReadOnly\":true,\"BandwidthMaximum\":0,\"IOPSMaximum\":0}],\"HvPartition\":false,\"EndpointList\":null,\"NetworkSharedContainerName\":\"586870f5833279678773cb700db3c175afc81d557a75867bf39b43f985133d13\",\"Servicing\":false,\"AllowUnqualifiedDNSQuery\":false}"}
  33m           11s             151     kubelet, 38519acs9011                                           Warning         FailedSync              Error syncing pod
  32m           11s             139     kubelet, 38519acs9011   spec.containers{fabrikamfiberweb}       Warning         BackOff                 Back-off restarting failed container

Решение: использование меток узлов и NodeSelector

Чтобы получить список всех узлов, выполните команду kubectl get node. После этого можно выполнить команду kubectl describe node (имя узла), чтобы получить дополнительные сведения.

В следующем примере существуют два узла Windows под управлением различных версий:

$ kubectl get node

NAME                        STATUS    AGE       VERSION
38519acs9010                Ready     21h       v1.7.7-7+e79c96c8ff2d8e
38519acs9011                Ready     4h        v1.7.7-25+bc3094f1d650a2
k8s-linuxpool1-38519084-0   Ready     21h       v1.7.7
k8s-master-38519084-0       Ready     21h       v1.7.7

$ kubectl describe node 38519acs9010

Name:                   38519acs9010
Role:
Labels:                 beta.kubernetes.io/arch=amd64
                        beta.kubernetes.io/instance-type=Standard_D2_v2
                        beta.kubernetes.io/os=windows
                        failure-domain.beta.kubernetes.io/region=westus2
                        failure-domain.beta.kubernetes.io/zone=0
                        kubernetes.io/hostname=38519acs9010
Annotations:            node.alpha.kubernetes.io/ttl=0
                        volumes.kubernetes.io/controller-managed-attach-detach=true
Taints:                 <none>
CreationTimestamp:      Fri, 06 Oct 2017 01:41:02 +0000

...

System Info:
 Machine ID:                    38519acs9010
 System UUID:
 Boot ID:
 Kernel Version:                10.0 14393 (14393.1715.amd64fre.rs1_release_inmarket.170906-1810)
 OS Image:
 Operating System:              windows
 Architecture:                  amd64
 ...

$ kubectl describe node 38519acs9011
Name:                   38519acs9011
Role:
Labels:                 beta.kubernetes.io/arch=amd64
                        beta.kubernetes.io/instance-type=Standard_DS1_v2
                        beta.kubernetes.io/os=windows
                        failure-domain.beta.kubernetes.io/region=westus2
                        failure-domain.beta.kubernetes.io/zone=0
                        kubernetes.io/hostname=38519acs9011
Annotations:            node.alpha.kubernetes.io/ttl=0
                        volumes.kubernetes.io/controller-managed-attach-detach=true
Taints:                 <none>
CreationTimestamp:      Fri, 06 Oct 2017 18:13:25 +0000
Conditions:
...

System Info:
 Machine ID:                    38519acs9011
 System UUID:
 Boot ID:
 Kernel Version:                10.0 16299 (16299.0.amd64fre.rs3_release.170922-1354)
 OS Image:
 Operating System:              windows
 Architecture:                  amd64
...

Давайте рассмотрим этот пример, чтобы продемонстрировать, как сопоставить версии:

  1. Запомните имя каждого узла и Kernel Version из сведений о системе.

    В нашем примере информация будет иметь следующий вид:

    Имя. Версия
    38519acs9010 14393.1715.amd64fre.rs1_release_inmarket.170906-1810
    38519acs9011 16299.0.amd64fre.rs3_release.170922-1354
  2. Добавьте метку к каждому узлу beta.kubernetes.io/osbuild. Для Windows Server 2016 требуется поддержка основной и дополнительной версии (в этом примере 14393.1715) без изоляции Hyper-V. В Windows Server версии 1709 для сопоставления требуется только основная версия (в этом примере 16299).

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

    $ kubectl label node 38519acs9010 beta.kubernetes.io/osbuild=14393.1715
    
    
    node "38519acs9010" labeled
    $ kubectl label node 38519acs9011 beta.kubernetes.io/osbuild=16299
    
    node "38519acs9011" labeled
    
    
  3. Убедитесь в существовании меток, выполнив команду kubectl get nodes --show-labels.

    В этом примере результат будет выглядеть так:

    $ kubectl get nodes --show-labels
    
    NAME                        STATUS                     AGE       VERSION                    LABELS
    38519acs9010                Ready,SchedulingDisabled   3d        v1.7.7-7+e79c96c8ff2d8e    beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=Standard_D2_v2,beta.kubernetes.io/os=windows,beta.kubernetes.io/osbuild=14393.1715,failure-domain.beta.kubernetes.io/region=westus2,failure-domain.beta.kubernetes.io/zone=0,kubernetes.io/hostname=38519acs9010
    38519acs9011                Ready                      3d        v1.7.7-25+bc3094f1d650a2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=Standard_DS1_v2,beta.kubernetes.io/os=windows,beta.kubernetes.io/osbuild=16299,failure-domain.beta.kubernetes.io/region=westus2,failure-domain.beta.kubernetes.io/zone=0,kubernetes.io/hostname=38519acs9011
    k8s-linuxpool1-38519084-0   Ready                      3d        v1.7.7                     agentpool=linuxpool1,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=Standard_D2_v2,beta.kubernetes.io/os=linux,failure-domain.beta.kubernetes.io/region=westus2,failure-domain.beta.kubernetes.io/zone=0,kubernetes.io/hostname=k8s-linuxpool1-38519084-0,kubernetes.io/role=agent
    k8s-master-38519084-0       Ready                      3d        v1.7.7                     beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=Standard_D2_v2,beta.kubernetes.io/os=linux,failure-domain.beta.kubernetes.io/region=westus2,failure-domain.beta.kubernetes.io/zone=0,kubernetes.io/hostname=k8s-master-38519084-0,kubernetes.io/role=master
    
  4. Добавьте селекторы узла в развертывания. В этом примере мы добавим nodeSelector в спецификации контейнера, используя beta.kubernetes.io/os = windows и beta.kubernetes.io/osbuild = 14393.* или 16299 в соответствии с базовой ОС, используемой контейнером.

    Ниже приведен полный пример запуска контейнера, созданного для Windows Server 2016:

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      annotations:
        kompose.cmd: kompose convert -f docker-compose-combined.yml
        kompose.version: 1.2.0 (99f88ef)
      creationTimestamp: null
      labels:
        io.kompose.service: fabrikamfiber.web
      name: fabrikamfiber.web
    spec:
      replicas: 1
      strategy: {}
      template:
        metadata:
          creationTimestamp: null
          labels:
            io.kompose.service: fabrikamfiber.web
        spec:
          containers:
          - image: patricklang/fabrikamfiber.web:latest
            name: fabrikamfiberweb
            ports:
            - containerPort: 80
            resources: {}
          restartPolicy: Always
          nodeSelector:
            "beta.kubernetes.io/os": windows
            "beta.kubernetes.io/osbuild": "14393.1715"
    status: {}
    

    Теперь модуль pod может начинаться с обновленного развертывания. Селекторы узла также отображаются в kubectl describe pod <podname>, поэтому можно выполнить эту команду, чтобы проверить их добавление.

    В нашем примере результат будет выглядеть так:

    $ kubectl -n plang describe po fa
    
    Name:           fabrikamfiber.web-1780117715-5c8vw
    Namespace:      plang
    Node:           38519acs9010/10.240.0.4
    Start Time:     Tue, 10 Oct 2017 01:43:28 +0000
    Labels:         io.kompose.service=fabrikamfiber.web
                    pod-template-hash=1780117715
    Annotations:    kubernetes.io/created-by={"kind":"SerializedReference","apiVersion":"v1","reference":{"kind":"ReplicaSet","namespace":"plang","name":"fabrikamfiber.web-1780117715","uid":"6a07aaf3-ad5c-11e7-b16e-000d3...
    Status:         Running
    IP:             10.244.1.84
    Created By:     ReplicaSet/fabrikamfiber.web-1780117715
    Controlled By:  ReplicaSet/fabrikamfiber.web-1780117715
    Containers:
      fabrikamfiberweb:
        Container ID:       docker://c94594fb53161f3821cf050d9af7546991aaafbeab41d333d9f64291327fae13
        Image:              patricklang/fabrikamfiber.web:latest
        Image ID:           docker-pullable://patricklang/fabrikamfiber.web@sha256:562741016ce7d9a232a389449a4fd0a0a55aab178cf324144404812887250ead
        Port:               80/TCP
        State:              Running
          Started:          Tue, 10 Oct 2017 01:43:42 +0000
        Ready:              True
        Restart Count:      0
        Environment:        <none>
        Mounts:
          /var/run/secrets/kubernetes.io/serviceaccount from default-token-rw9dn (ro)
    Conditions:
      Type          Status
      Initialized   True
      Ready         True
      PodScheduled  True
    Volumes:
      default-token-rw9dn:
        Type:       Secret (a volume populated by a Secret)
        SecretName: default-token-rw9dn
        Optional:   false
    QoS Class:      BestEffort
    Node-Selectors: beta.kubernetes.io/os=windows
                    beta.kubernetes.io/osbuild=14393.1715
    Tolerations:    <none>
    Events:
      FirstSeen     LastSeen        Count   From                    SubObjectPath                           Type            Reason                  Message
      ---------     --------        -----   ----                    -------------                           --------        ------                  -------
      5m            5m              1       default-scheduler                                               Normal          Scheduled               Successfully assigned fabrikamfiber.web-1780117715-5c8vw to 38519acs9010
      5m            5m              1       kubelet, 38519acs9010                                           Normal          SuccessfulMountVolume   MountVolume.SetUp succeeded for volume "default-token-rw9dn"
      5m            5m              1       kubelet, 38519acs9010   spec.containers{fabrikamfiberweb}       Normal          Pulling                 pulling image "patricklang/fabrikamfiber.web:latest"
      5m            5m              1       kubelet, 38519acs9010   spec.containers{fabrikamfiberweb}       Normal          Pulled                  Successfully pulled image "patricklang/fabrikamfiber.web:latest"
      5m            5m              1       kubelet, 38519acs9010   spec.containers{fabrikamfiberweb}       Normal          Created                 Created container
      5m            5m              1       kubelet, 38519acs9010   spec.containers{fabrikamfiberweb}       Normal          Started                 Started container