Создание первого приложения-контейнера Service Fabric в Windows

Чтобы запустить существующее приложение в контейнере Windows кластера Service Fabric, не требуется вносить изменения в приложение. В этой статье описано создание образа Docker, содержащего веб-приложение Flask Python, и его развертывание в кластере Azure Service Fabric. Кроме того, вы предоставите общий доступ к контейнерному приложению через реестр контейнеров Azure. Для работы с этой статьей необходимо знание основных понятий Docker. Чтобы ознакомиться с Docker, см. этот обзор Docker.

Примечание.

Эта статья касается среды разработки Windows. Среда выполнения кластера Service Fabric и среда выполнения Docker должны работать под управлением одной операционной системы. Контейнеры Windows нельзя запускать в кластере Linux.

Примечание.

Мы рекомендуем использовать модуль Azure Az PowerShell для взаимодействия с Azure. Чтобы начать работу, см. статью Установка Azure PowerShell. Дополнительные сведения см. в статье Перенос Azure PowerShell с AzureRM на Az.

Необходимые компоненты

  • Компьютер для разработки, на котором установлено ПО, перечисленное ниже.

  • Кластер Windows с тремя или более узлами под управлением Windows Server с контейнерами.

    В этой статье версия (сборка) Windows Server с контейнерами, запущенная на узлах кластера, должна соответствовать версии на компьютере разработки. Это связано с тем, что вы создаете образ Docker на компьютере разработки и между версиями ОС контейнера и ОС узла, где он развертывается, есть ограничения совместимости. Дополнительные сведения см. в разделе Совместимость ОС контейнера Windows Server и ОС узла.

    Чтобы определить версию Windows Server с контейнерами, необходимую для кластера, запустите команду ver из командной строки Windows на компьютере разработки. Перед созданием кластера ознакомьтесь с разделом Совместимость ОС контейнера Windows Server и ОС узла.

  • Реестр контейнеров Azure. Создайте реестр контейнеров в своей подписке Azure.

Примечание.

Поддерживается развертывание контейнеров в кластере Service Fabric под управлением Windows 10. Сведения о настройке Windows 10 для запуска контейнеров Windows см.в этой статье.

Примечание.

Service Fabric 6.2 и более поздних версий поддерживает развертывание контейнеров в кластерах под управлением Windows Server версии 1709.

Определение образа контейнера Docker

Создайте образ на основе образа Python из репозитория Docker Hub.

Определите образ Docker в файле Dockerfile. Файл Dockerfile содержит инструкции по настройке среды внутри контейнера, загрузке приложения, которое необходимо выполнить, и сопоставлению портов. Dockerfile — это входные данные для команды docker build, которая создает образ.

Создайте пустой каталог и файл Dockerfile (без расширения файла). Добавьте следующий код в Dockerfile и сохраните изменения:

# Use an official Python runtime as a base image
FROM python:2.7-windowsservercore

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
ADD . /app

# Install any needed packages specified in requirements.txt
RUN pip install -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

Дополнительные сведения см. в справочнике по Dockerfile.

Создание базового веб-приложения

Создайте веб-приложение Flask, ожидающее передачи данных в порт 80 и возвращающее Hello World!. В том же каталоге создайте файл requirements.txt. Добавьте следующее и сохраните изменения:

Flask

Кроме того, создайте файл app.py и добавьте следующий фрагмент кода:

from flask import Flask

app = Flask(__name__)


@app.route("/")
def hello():

    return 'Hello World!'


if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)

Вхов в Docker и создание образа

Теперь создадим образ, который запускает нужное веб-приложение. При вытягивании общедоступных образов из Docker (например, python:2.7-windowsservercore в нашем Dockerfile) рекомендуется выполнять аутентификацию в учетной записи Docker Hub вместо выполнения анонимного запроса на вытягивание.

Примечание.

При частом выполнении анонимных запросов на вытягивание могут возникать ошибки Docker, аналогичные ERROR: toomanyrequests: Too Many Requests. или You have reached your pull rate limit. Чтобы предотвратить возникновение этих ошибок, выполняйте аутентификацию в Docker Hub. Дополнительные сведения см. в статье Управление общедоступным содержимым с помощью реестра контейнеров Azure.

Откройте окно PowerShell и перейдите в каталог, содержащий Dockerfile. Затем выполните следующие команды:

docker login
docker build -t helloworldapp .

Эта команда создает образ согласно инструкциям в Dockerfile, и присваивает образу имя helloworldapp (-t — добавление тега). Чтобы создать образ контейнера, необходимо скачать из Docker Hub базовый образ, к которому добавляется приложение.

После выполнения команды сборки выполните команду docker images, чтобы получить информацию о новом образе:

$ docker images

REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
helloworldapp                 latest              8ce25f5d6a79        2 minutes ago       10.4 GB

Локальный запуск приложения

Проверьте работу образа локально, прежде чем отправлять его в реестр контейнеров.

Запустите приложение:

docker run -d --name my-web-site helloworldapp

Параметр name присваивает имя запущенному контейнеру (вместо идентификатора контейнера).

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

docker inspect -f "{{ .NetworkSettings.Networks.nat.IPAddress }}" my-web-site

Если эта команда не возвращает результаты, выполните следующую команду и проверьте IP-адрес в элементе NetworkSettings->Networks:

docker inspect my-web-site

Подключитесь к запущенному контейнеру. Откройте в веб-браузере страницу по IP-адресу, который вы получили, например http://172.31.194.61". В браузере должен отобразиться заголовок "Hello World!"

Чтобы остановить контейнер, выполните следующую команду:

docker stop my-web-site

Удаление контейнера с компьютера для разработки:

docker rm my-web-site

Отправка образа в реестр контейнеров

Убедившись, что контейнер запускается на компьютере разработки, отправьте образ в реестр в реестре контейнеров Azure.

Выполните команду docker login, чтобы войти в реестр контейнеров с помощью учетных данных реестра.

В следующем примере передается идентификатор и пароль субъекта-службы Microsoft Entra. Например, назначение субъекта-службы для реестра позволяет автоматизировать некоторые сценарии. Или вы можете входить, используя имя и пароль реестра.

docker login myregistry.azurecr.io -u xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -p myPassword

Следующая команда создает тег (псевдоним) образа с полным путем к вашему реестру. Чтобы избежать беспорядка в корне реестра, эта команда помещает образ в пространство имен samples.

docker tag helloworldapp myregistry.azurecr.io/samples/helloworldapp

Отправьте образ в реестр контейнеров:

docker push myregistry.azurecr.io/samples/helloworldapp

Создание контейнерной службы в Visual Studio

Пакет SDK и средства для Service Fabric предоставляют шаблон службы для создания контейнерного приложения.

  1. Запустите среду Visual Studio. Выберите File>New>Project ( Файл > Создать > Проект).
  2. Выберите Приложение Service Fabric, назовите его MyFirstContainer и нажмите кнопку ОК.
  3. В списке шаблонов служб выберите значение Container (Контейнер).
  4. В поле Имя образа введите myregistry.azurecr.io/samples/helloworldapp — это образ, который вы отправили в репозиторий контейнера.
  5. Присвойте службе имя и нажмите кнопку ОК.

настройка обмена данными;

Контейнерной службе для обмена данными требуется конечная точка. В файле ServiceManifest.xml добавьте элемент Endpoint и укажите протокол, порт и тип. В этом примере используется фиксированный порт 8081. Если порт не указан, выбирается случайный порт из диапазона портов приложения.

<Resources>
  <Endpoints>
    <Endpoint Name="Guest1TypeEndpoint" UriScheme="http" Port="8081" Protocol="http"/>
  </Endpoints>
</Resources>

Примечание.

Дополнительные конечные точки для службы могут быть добавлены путем объявления дополнительных элементов EndPoint с соответствующими значениями свойств. Для каждого отдельного порта может быть объявлено только одно значение протокола.

При определении конечной точки Service Fabric публикует ее в службе именования. Другие службы, работающие в кластере, могут разрешать этот контейнер. Кроме того, возможен обмен данными между контейнерами с помощью обратного прокси-сервера. Для этого нужно указать в переменных среды HTTP-порт прослушивания обратного прокси-сервера и имена служб, с которыми будет выполняться обмен данными.

Служба ожидает передачи данных через определенный порт (в этом примере — 8081). Если приложение развертывается в кластере в Azure, то приложение и кластер запускаются под контролем Azure Load Balancer. Чтобы входящий трафик поступал в службу, необходимо открыть порт приложения в Azure Load Balancer. Этот порт можно открыть в Azure Load Balancer с помощью скрипта PowerShell или на портале Azure.

Настройка и установка переменных среды

Переменные среды можно указать для каждого пакета кода в манифесте служб. Эта функция доступна для всех служб, вне зависимости от того, как они развернуты: в качестве контейнеров, процессов или гостевых исполняемых файлов. Вы можете переопределить значения переменных среды в манифесте приложения или указать их в качестве параметров приложения во время развертывания.

Следующий фрагмент XML-кода из манифеста службы демонстрирует, как определить переменные среды для пакета кода.

<CodePackage Name="Code" Version="1.0.0">
  ...
  <EnvironmentVariables>
    <EnvironmentVariable Name="HttpGatewayPort" Value=""/>    
  </EnvironmentVariables>
</CodePackage>

Эти переменные среды можно переопределить в манифесте приложения:

<ServiceManifestImport>
  <ServiceManifestRef ServiceManifestName="Guest1Pkg" ServiceManifestVersion="1.0.0" />
  <EnvironmentOverrides CodePackageRef="FrontendService.Code">
    <EnvironmentVariable Name="HttpGatewayPort" Value="19080"/>
  </EnvironmentOverrides>
  ...
</ServiceManifestImport>

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

Настройте порт узла, который будет использоваться для обмена данными с контейнером. Привязка порта сопоставляет порт, на котором служба ожидает передачи данных в контейнере, с портом на узле. Добавьте элемент PortBinding в элемент ContainerHostPolicies в файле ApplicationManifest.xml. В этой статье у ContainerPort будет значение 80 (контейнер предоставляет порт 80, как указано в Dockerfile), а у EndpointRef — Guest1TypeEndpoint (конечная точка, определенная ранее в манифесте служб). Входящие запросы к службе через порт 8081 сопоставляются с портом 80 в контейнере.

<ServiceManifestImport>
    ...
    <Policies>
        <ContainerHostPolicies CodePackageRef="Code">
            <PortBinding ContainerPort="80" EndpointRef="Guest1TypeEndpoint"/>
        </ContainerHostPolicies>
    </Policies>
    ...
</ServiceManifestImport>

Примечание.

Дополнительные PortBindings для службы могут быть добавлены путем объявления дополнительных элементов PortBinding с соответствующими значениями свойств.

Настройка аутентификации в репозитории

Сведения о настройке различных типов аутентификации для загрузки образа контейнера см. в статье Проверка подлинности репозитория контейнеров.

Настройка режима изоляции

Windows поддерживает два режима изоляции для контейнеров: режим изоляции процессов и Hyper-V. В режиме изоляции процесса все контейнеры, запущенные на одном хост-компьютере, совместно используют ядро и узел. В режиме изоляции Hyper-V все контейнеры Hyper-V и узлы контейнера используют отдельные ядра. Режим изоляции указывается в элементе ContainerHostPolicies в файле манифеста приложения. Вы можете указать следующие режимы изоляции: process, hyperv и default. По умолчанию на узлах Windows Server используется режим изоляции процессов. На узлах Windows 10 поддерживается только режим изоляции Hyper-V, поэтому контейнер работает в этом режиме независимо от параметра режима изоляции. В указанном ниже фрагменте кода показано, как режим изоляции указывается в файле манифеста приложения.

<ContainerHostPolicies CodePackageRef="Code" Isolation="hyperv">

Примечание.

Режим изоляции Hyper-v доступен для номеров SKU Azure Ev3 и Dv3 с поддержкой вложенной виртуализации.

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

Управление ресурсами позволяет ограничить ресурсы, которые контейнер может использовать на узле. Элемент ResourceGovernancePolicy, определяемый в манифесте приложения, позволяет объявить ограничения для ресурсов, доступных из пакета кода службы. Ограничения можно задать для следующих ресурсов: Memory, MemorySwap, CpuShares (относительный вес ЦП), MemoryReservationInMB, BlkioWeight (относительный вес BlockIO). В этом примере пакет службы Guest1Pkg получает одно ядро на узлах кластера, где он размещается. Ограничения по памяти абсолютны, так что пакет кода получает только 1024 МБ (и имеет соответствующие мягкие гарантии резервирования). Пакеты кода (контейнеры или процессы) не могут выделить больше памяти, чем задано ограничением, а при попытке сделать это возникнет проблема нехватки памяти. Чтобы принудительное ограничение ресурсов работало, для всех пакетов кода в пакете службы должны быть указаны ограничения по памяти.

<ServiceManifestImport>
  <ServiceManifestRef ServiceManifestName="Guest1Pkg" ServiceManifestVersion="1.0.0" />
  <Policies>
    <ServicePackageResourceGovernancePolicy CpuCores="1"/>
    <ResourceGovernancePolicy CodePackageRef="Code" MemoryInMB="1024"  />
  </Policies>
</ServiceManifestImport>

Настройка инструкции HEALTHCHECK в Docker

Начиная с версии 6.1 Service Fabric автоматически интегрирует события Docker HEALTHCHECK в отчеты о работоспособности системы. Это означает, что если в вашем контейнере включена инструкция HEALTHCHECK, то Service Fabric будет отправлять отчет о работоспособности при каждом изменении состояния контейнера согласно сведениям Docker. В Service Fabric Explorer будет отображаться состояние работоспособности ОК, если значение health_status равно healthy. Если же значение health_status равно unhealthy, отобразится предупреждение.

Начиная с последнего выпуска версии 6.4, вы можете указать, что оценки HEALTHCHECK в Docker должны выводиться как ошибки. При включении этого параметра будет отображаться состояние работоспособности OK, если значение health_status равно healthy. Если же значение health_status равно unhealthy, отобразится ОШИБКА.

В файле Dockerfile, который используется при создании образа контейнера, должна содержаться инструкция HEALTHCHECK, указывающая на фактическую проверку для отслеживания работоспособности контейнера.

Screenshot shows details of the Deployed Service Package NodeServicePackage.

HealthCheckUnhealthyApp

HealthCheckUnhealthyDsp

Поведение инструкции HEALTHCHECK можно настроить для каждого контейнера, указав параметры HealthConfig в разделе ContainerHostPolicies в манифесте приложения.

<ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="ContainerServicePkg" ServiceManifestVersion="2.0.0" />
    <Policies>
      <ContainerHostPolicies CodePackageRef="Code">
        <HealthConfig IncludeDockerHealthStatusInSystemHealthReport="true"
		      RestartContainerOnUnhealthyDockerHealthStatus="false" 
		      TreatContainerUnhealthyStatusAsError="false" />
      </ContainerHostPolicies>
    </Policies>
</ServiceManifestImport>

По умолчанию для IncludeDockerHealthStatusInSystemHealthReport задано значение true, для RestartContainerOnUnhealthyDockerHealthStatus задано значение false, а для TreatContainerUnhealthyStatusAsError — false.

Если для RestartContainerOnUnhealthyDockerHealthStatus задано значение true, контейнер, для которого несколько раз отображалось неработоспособное состояние, перезапускается (возможно, на других узлах).

Если для TreatContainerUnhealthyStatusAsError задано значение true, то ОШИБКА в отчетах о работоспособности отобразится, если значение health_status контейнера равно unhealthy.

Если вы хотите отключить интеграцию с HEALTHCHECK во всем кластере Service Fabric, задайте для EnableDockerHealthCheckIntegration значение false.

Развертывание приложения-контейнера

Сохраните все изменения и скомпилируйте приложение. Чтобы опубликовать приложение, щелкните правой кнопкой мыши MyFirstContainer в обозревателе решений и выберите действие Опубликовать.

В поле Конечная точка подключения введите конечную точку управления для кластера. Например, containercluster.westus2.cloudapp.azure.com:19000. Конечную точку подключения к клиенту можно найти на вкладке "Обзор" кластера на портале Azure.

Нажмите кнопку Опубликовать.

Service Fabric Explorer — это веб-средство для проверки приложений и узлов в кластере Service Fabric и управления ими. Откройте браузер, перейдите по адресу http://containercluster.westus2.cloudapp.azure.com:19080/Explorer/ и разверните приложение. Приложение развертывается, но находится в состоянии ошибки, пока образ не будет загружен на узлы кластера (что может занять некоторое время в зависимости от размера изображения): Error

Приложение готово, когда оно находится в Ready состоянии: Ready

Откройте веб-браузер и перейдите по адресу http://containercluster.westus2.cloudapp.azure.com:8081. В браузере должен отобразиться заголовок "Hello World!"

Очистка

Пока кластер работает, с вас будет взиматься плата. Рекомендуем удалить кластер.

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

docker rmi helloworldapp
docker rmi myregistry.azurecr.io/samples/helloworldapp

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

Контейнеры Windows Server совместимы не со всеми версиями ОС узла. Например:

  • Контейнеры Windows Server, созданные с использованием Windows Server 1709, не работают на узле с ОС Windows Server версии 2016.
  • Контейнеры Windows Server, созданные с использованием Windows Server 2016, работают в режиме изоляции Hyper-V только на узле с ОС Windows Server версии 1709.
  • Для контейнеров Windows Server, созданных с использованием Windows Server 2016, может потребоваться убедиться, что номера редакции версии ОС контейнера и узла ОС совпадают при работе в режиме изоляции процессов на узле под управлением Windows Server 2016.

Дополнительные сведения см. в разделе Совместимость версий контейнеров Windows.

Учитывайте совместимость ОС узла и контейнера при создании и развертывании контейнеров в кластере Service Fabric. Например:

  • Развертывайте контейнеры с ОС, совместимой с ОС на узлах кластера.
  • Убедитесь, что режим изоляции, указанный для приложения-контейнера, совместим с ОС контейнера на том узле, где развертывается это приложение.
  • Рассмотрите, как обновления операционной системы на узлах кластера или контейнерах могут повлиять на их совместимость.

Ниже приведены рекомендации, которые помогут гарантировать правильное развертывание контейнеров в кластере Service Fabric.

  • Добавляйте к образам Docker явные теги, содержащие версию ОС Windows Server, на основе которой создан контейнер.
  • Укажите теги ОС в файле манифеста приложения, чтобы обеспечить совместимость приложения между различными версиями Windows Server и обновлениями.

Примечание.

В Service Fabric 6.2 и более поздних версий можно развернуть контейнеры, основанные на Windows Server 2016, локально на узле Windows 10. В Windows 10 контейнеры работают в режиме изоляции Hyper-V, независимо от режима изоляции, заданного в манифесте приложения. Дополнительные сведения см. в разделе о настройке режима изоляции.

Указание образов контейнеров для конкретной сборки ОС

Контейнеры Windows Server могут быть несовместимы в разных версиях ОС. Например, контейнеры Windows Server, созданные с помощью Windows Server 2016, не работают в Windows Server версии 1709 в режиме изоляции. Таким образом, если узлы кластера обновлены до последней версии, в службах контейнеров, созданных с использованием предыдущих версий операционной системы, может произойти сбой. Для решения этой проблемы в версии среды выполнения 6.1 и более поздних в Service Fabric поддерживается указание нескольких образов ОС для одного контейнера и добавление к ним тегов версии сборки ОС в манифесте приложения. Вы можете узнать версию сборки операционной системы, выполнив в командной строке Windows команду winver. Перед обновлением операционной системы на узлах обновите манифесты приложений и укажите переопределения образов для каждой версии ОС. В следующем фрагменте кода показано, как указать несколько образов контейнеров в манифесте приложения ApplicationManifest.xml:

      <ContainerHostPolicies> 
         <ImageOverrides> 
	       <Image Name="myregistry.azurecr.io/samples/helloworldappDefault" /> 
               <Image Name="myregistry.azurecr.io/samples/helloworldapp1701" Os="14393" /> 
               <Image Name="myregistry.azurecr.io/samples/helloworldapp1709" Os="16299" /> 
         </ImageOverrides> 
      </ContainerHostPolicies> 

Для Windows Server 2016 используется версия сборки 14393, а для Windows Server версии 1709 — версия сборки 16299. В манифесте службы по-прежнему указывается только один образ на службу контейнеров:

<ContainerHost>
    <ImageName>myregistry.azurecr.io/samples/helloworldapp</ImageName> 
</ContainerHost>

Примечание.

Функции добавления тегов версии сборки ОС доступны только в Service Fabric для Windows.

Если на виртуальной машине используется базовая ОС сборки 16299 (версия 1709), Service Fabric выбирает образ контейнера, который соответствует этой версии Windows Server. Если в манифесте приложения наряду с образами контейнеров с тегами также указывается образ контейнера без тегов, Service Fabric рассматривает образ без тегов как работающий в разных версиях. Явным образом отметьте тегами образы контейнеров, чтобы избежать проблем во время обновления.

Непомеченный образ контейнера будет работать как переопределение для указанного в ServiceManifest. Поэтому образ "myregistry.azurecr.io/samples/helloworldappDefault" переопределит ImageName "myregistry.azurecr.io/samples/helloworldapp" в ServiceManifest.

Полные примеры манифестов службы и приложения Service Fabric

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

ServiceManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="Guest1Pkg"
                 Version="1.0.0"
                 xmlns="http://schemas.microsoft.com/2011/01/fabric"
                 xmlns:xsd="https://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
  <ServiceTypes>
    <!-- This is the name of your ServiceType.
         The UseImplicitHost attribute indicates this is a guest service. -->
    <StatelessServiceType ServiceTypeName="Guest1Type" UseImplicitHost="true" />
  </ServiceTypes>

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <!-- Follow this link for more information about deploying Windows containers to Service Fabric: https://aka.ms/sfguestcontainers -->
      <ContainerHost>
        <ImageName>myregistry.azurecr.io/samples/helloworldapp</ImageName>
        <!-- Pass comma delimited commands to your container: dotnet, myproc.dll, 5" -->
        <!--Commands> dotnet, myproc.dll, 5 </Commands-->
        <Commands></Commands>
      </ContainerHost>
    </EntryPoint>
    <!-- Pass environment variables to your container: -->    
    <EnvironmentVariables>
      <EnvironmentVariable Name="HttpGatewayPort" Value=""/>
      <EnvironmentVariable Name="BackendServiceName" Value=""/>
    </EnvironmentVariables>

  </CodePackage>

  <!-- Config package is the contents of the Config directory under PackageRoot that contains an
       independently-updateable and versioned set of custom configuration settings for your service. -->
  <ConfigPackage Name="Config" Version="1.0.0" />

  <Resources>
    <Endpoints>
      <!-- This endpoint is used by the communication listener to obtain the port on which to
           listen. Please note that if your service is partitioned, this port is shared with
           replicas of different partitions that are placed in your code. -->
      <Endpoint Name="Guest1TypeEndpoint" UriScheme="http" Port="8081" Protocol="http"/>
    </Endpoints>
  </Resources>
</ServiceManifest>

ApplicationManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest ApplicationTypeName="MyFirstContainerType"
                     ApplicationTypeVersion="1.0.0"
                     xmlns="http://schemas.microsoft.com/2011/01/fabric"
                     xmlns:xsd="https://www.w3.org/2001/XMLSchema"
                     xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
  <Parameters>
    <Parameter Name="Guest1_InstanceCount" DefaultValue="-1" />
  </Parameters>
  <!-- Import the ServiceManifest from the ServicePackage. The ServiceManifestName and ServiceManifestVersion
       should match the Name and Version attributes of the ServiceManifest element defined in the
       ServiceManifest.xml file. -->
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="Guest1Pkg" ServiceManifestVersion="1.0.0" />
    <EnvironmentOverrides CodePackageRef="FrontendService.Code">
      <EnvironmentVariable Name="HttpGatewayPort" Value="19080"/>
    </EnvironmentOverrides>
    <ConfigOverrides />
    <Policies>
      <ContainerHostPolicies CodePackageRef="Code">
        <RepositoryCredentials AccountName="myregistry" Password="MIIB6QYJKoZIhvcNAQcDoIIB2jCCAdYCAQAxggFRMIIBTQIBADA1MCExHzAdBgNVBAMMFnJ5YW53aWRhdGFlbmNpcGhlcm1lbnQCEFfyjOX/17S6RIoSjA6UZ1QwDQYJKoZIhvcNAQEHMAAEg
gEAS7oqxvoz8i6+8zULhDzFpBpOTLU+c2mhBdqXpkLwVfcmWUNA82rEWG57Vl1jZXe7J9BkW9ly4xhU8BbARkZHLEuKqg0saTrTHsMBQ6KMQDotSdU8m8Y2BR5Y100wRjvVx3y5+iNYuy/JmM
gSrNyyMQ/45HfMuVb5B4rwnuP8PAkXNT9VLbPeqAfxsMkYg+vGCDEtd8m+bX/7Xgp/kfwxymOuUCrq/YmSwe9QTG3pBri7Hq1K3zEpX4FH/7W2Zb4o3fBAQ+FuxH4nFjFNoYG29inL0bKEcTX
yNZNKrvhdM3n1Uk/8W2Hr62FQ33HgeFR1yxQjLsUu800PrYcR5tLfyTB8BgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBBybgM5NUV8BeetUbMR8mJhgFBrVSUsnp9B8RyebmtgU36dZiSObDsI
NtTvlzhk11LIlae/5kjPv95r3lw6DHmV4kXLwiCNlcWPYIWBGIuspwyG+28EWSrHmN7Dt2WqEWqeNQ==" PasswordEncrypted="true"/>
        <PortBinding ContainerPort="80" EndpointRef="Guest1TypeEndpoint"/>
      </ContainerHostPolicies>
      <ServicePackageResourceGovernancePolicy CpuCores="1"/>
      <ResourceGovernancePolicy CodePackageRef="Code" MemoryInMB="1024"  />
    </Policies>
  </ServiceManifestImport>
  <DefaultServices>
    <!-- The section below creates instances of service types, when an instance of this
         application type is created. You can also create one or more instances of service type using the
         ServiceFabric PowerShell module.

         The attribute ServiceTypeName below must match the name defined in the imported ServiceManifest.xml file. -->
    <Service Name="Guest1">
      <StatelessService ServiceTypeName="Guest1Type" InstanceCount="[Guest1_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>
  </DefaultServices>
</ApplicationManifest>

Настройка интервала времени перед принудительным завершением контейнера

Вы можете настроить интервал времени для среды выполнения перед удалением контейнера после начала удаления службы (или перехода на другой узел). При настройке интервала времени в контейнер отправляется команда docker stop <time in seconds>. Дополнительные сведения см. в статье docker stop (Остановка docker). Интервал времени ожидания указывается в разделе Hosting. Раздел Hosting можно добавить при создании кластера или позднее, при обновлении конфигурации. В следующем фрагменте манифеста кластера показано, как задать интервал ожидания:

"fabricSettings": [
	...,
	{
        "name": "Hosting",
        "parameters": [
          {
                "name": "ContainerDeactivationTimeout",
                "value" : "10"
          },
	      ...
        ]
	}
]

Интервал времени по умолчанию установлен на 10 секунд. Так как эта конфигурация является динамической, файл конфигурации обновляет только кластер для которого обновляется время ожидания.

Настройка среды выполнения для удаления неиспользуемых образов контейнера

Можно настроить кластер Service Fabric для удаления неиспользуемых образов контейнера из узла. Эта конфигурация позволяет месту на диске перезаписываться, если на узле находится слишком много образов контейнера. Чтобы включить эту функцию, обновите раздел Hosting в манифесте кластера, как показано в следующем фрагменте кода:

"fabricSettings": [
	...,
	{
        "name": "Hosting",
        "parameters": [
          {
                "name": "PruneContainerImages",
                "value": "True"
          },
          {
                "name": "ContainerImagesToSkip",
                "value": "mcr.microsoft.com/windows/servercore|mcr.microsoft.com/windows/nanoserver|mcr.microsoft.com/dotnet/framework/aspnet|..."
          }
          ...
          }
        ]
	} 
]

Образы, которые не должны удаляться, можно указать в параметре ContainerImagesToSkip.

Настройка времени загрузки образа контейнера

Среда выполнения Service Fabric выделяет 20 минут для скачивания и извлечения образов контейнеров. Этого достаточно для большинства образов контейнеров. В случае с большими образами или при медленном сетевом подключении, возможно, потребуется увеличить время ожидания перед прерыванием загрузки и извлечения образа. Это значение можно задать с помощью атрибута ContainerImageDownloadTimeout в разделе Hosting манифеста кластера, как показано в следующем фрагменте кода:

"fabricSettings": [
	...,
	{
        "name": "Hosting",
        "parameters": [
          {
              "name": "ContainerImageDownloadTimeout",
              "value": "1200"
          }
        ]
	}
]

Настройка политики хранения контейнера

Для упрощения диагностики сбоев при запуске контейнеров Service Fabric (версии 6.1 и более поздних версий) поддерживает хранение контейнеров, работа которых завершилась или при запуске которых произошел сбой. Эту политику можно настроить в файле ApplicationManifest.xml, как показано в следующем фрагменте кода:

 <ContainerHostPolicies CodePackageRef="NodeService.Code" Isolation="process" ContainersRetentionCount="2"  RunInteractive="true"> 

В атрибуте ContainersRetentionCount указывается число контейнеров, которые следует сохранить после сбоя. Если указано отрицательное значение, будут сохраняться все контейнеры после сбоя. Если значение ContainersRetentionCount не указано, контейнеры не будут сохраняться. Атрибут ContainersRetentionCount также поддерживает параметры приложения, поэтому пользователи могут указывать разные значения для тестовых и рабочих кластеров. Чтобы предотвратить перемещение службы контейнеров на другие узлы, при использовании этих функций используйте ограничения на размещение, указав для службы контейнеров конкретный узел. Удаление всех контейнеров, сохраненных с помощью этой функции, выполняется вручную.

Запуск управляющей программы Docker с пользовательскими аргументами

Используя среду выполнения Service Fabric версии 6.2 и выше, можно запустить управляющую программу Docker с пользовательскими аргументами. Если пользовательские аргументы указаны, Service Fabric не передает никакие другие аргументы модулю Docker, кроме аргумента --pidfile. Таким образом, не нужно передавать --pidfile в качестве аргумента. Кроме того, аргумент должен поддерживать прослушивание модулем Docker стандартного конвейера имен Windows (или сокета домена Unix в Linux), обеспечивая обмен данными между Service Fabric и управляющей программой. Пользовательские аргументы передаются в манифесте кластера в блоке Размещение раздела ContainerServiceArguments, как показано в следующем фрагменте:

"fabricSettings": [
	...,
	{ 
        "name": "Hosting", 
        "parameters": [ 
          { 
            "name": "ContainerServiceArguments", 
            "value": "-H localhost:1234 -H unix:///var/run/docker.sock" 
          } 
        ] 
	} 
]

Переопределение EntryPoint

Если используется версия 8.2 среды выполнения ServiceFabric, точка входа для контейнера и пакета кода узла исполнения может быть переопределена. Это может быть удобно в тех случаях, когда все элементы манифеста остаются одинаковыми, но необходимо изменить образ контейнера. В этом сценарии больше не требуется подготовка версии приложения другого типа. Также это позволяет передавать разные аргументы для тестирования и рабочей среды, сохраняя одну общую точку входа.

Следующий пример демонстрирует, как переопределить точку входа в контейнер.

ApplicationManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest ApplicationTypeName="MyFirstContainerType"
                     ApplicationTypeVersion="1.0.0"
                     xmlns="http://schemas.microsoft.com/2011/01/fabric"
                     xmlns:xsd="https://www.w3.org/2001/XMLSchema"
                     xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
  <Parameters>
    <Parameter Name="ImageName" DefaultValue="myregistry.azurecr.io/samples/helloworldapp" />
    <Parameter Name="Commands" DefaultValue="commandsOverride" />
    <Parameter Name="FromSource" DefaultValue="sourceOverride" />
    <Parameter Name="EntryPoint" DefaultValue="entryPointOverride" />
  </Parameters>
  <!-- Import the ServiceManifest from the ServicePackage. The ServiceManifestName and ServiceManifestVersion
       should match the Name and Version attributes of the ServiceManifest element defined in the
       ServiceManifest.xml file. -->
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="Guest1Pkg" ServiceManifestVersion="1.0.0" />
    <ConfigOverrides />
    <Policies>
      <CodePackagePolicy CodePackageRef="Code">
        <EntryPointOverride>
         <ContainerHostOverride>
            <ImageOverrides>
              <Image Name="[ImageName]" />
            </ImageOverrides>
            <Commands>[Commands]</Commands>
            <FromSource>[Source]</FromSource>
            <EntryPoint>[EntryPoint]</EntryPoint>
          </ContainerHostOverride>
        </EntryPointOverride>
      </CodePackagePolicy>
    </Policies>
  </ServiceManifestImport>
</ApplicationManifest>

ServiceManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="Guest1Pkg"
                 Version="1.0.0"
                 xmlns="http://schemas.microsoft.com/2011/01/fabric"
                 xmlns:xsd="https://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
  <ServiceTypes>
    <!-- This is the name of your ServiceType.
         The UseImplicitHost attribute indicates this is a guest service. -->
    <StatelessServiceType ServiceTypeName="Guest1Type" UseImplicitHost="true" />
  </ServiceTypes>

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <!-- Follow this link for more information about deploying Windows containers to Service Fabric: https://aka.ms/sfguestcontainers -->
      <ContainerHost>
        <ImageName>default imagename</ImageName>
        <Commands>default cmd</Commands>
        <EntryPoint>default entrypoint</EntryPoint>
        <FromSource>default source</FromSource>
      </ContainerHost>
    </EntryPoint>
  </CodePackage>

  <ConfigPackage Name="Config" Version="1.0.0" />
</ServiceManifest>

Когда вы внесете эти переопределения в манифест приложения, контейнер будет открываться с именем образа myregistry.azurecr.io/samples/helloworldapp, командами commandsOverride, источником sourceOverride, и будут запущена точка входа entryPointOverride.

Аналогичным образом ниже переопределяется ExeHost:

<?xml version="1.0" encoding="utf-8"?>
<Policies>
  <CodePackagePolicy CodePackageRef="Code">
    <EntryPointOverride>
      <ExeHostOverride>
        <Program>[Program]</Program>
        <Arguments>[Entry]</Arguments>
      </ExeHostOverride>
    </EntryPointOverride>
  </CodePackagePolicy>
</Policies>

Примечание.

Переопределение точки входа не поддерживается для SetupEntryPoint.

Следующие шаги