Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Запуск существующего приложения в контейнере Linux в кластере Service Fabric не требует каких-либо изменений в приложении. В этой статье описывается создание образа Docker, содержащего веб-приложение Python Flask и развертывание его в кластере Service Fabric. Вы также предоставите общий доступ к контейнеризованному приложению через реестр контейнеров Azure. В этой статье предполагается базовое понимание Docker. Вы можете узнать о Docker, прочитав обзор Docker.
Примечание.
Эта статья относится к среде разработки Linux. Среда выполнения кластера Service Fabric и среда выполнения Docker должны работать в той же ОС. Вы не можете запускать контейнеры Linux в кластере Windows.
Предпосылки
Компьютер для разработки, работающий на:
Кластер Linux с тремя или более узлами.
Реестр контейнеров Azure— создание реестра контейнеров в подписке Azure.
Определение контейнера 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-slim
# 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 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-slim в нашем Dockerfile) рекомендуется проходить аутентификацию с помощью учетной записи Docker Hub вместо анонимной загрузки.
Примечание.
При частом выполнении анонимных pull-запросов могут возникать ошибки 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, и присваивает образу тег (-t) helloworldapp. Чтобы создать образ контейнера, базовый образ сначала скачан из Docker Hub, в который добавляется приложение.
После завершения команды сборки выполните docker images команду, чтобы просмотреть сведения о новом образе:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
helloworldapp latest 86838648aab6 2 minutes ago 194 MB
Локальное запуск приложения
Убедитесь, что контейнерное приложение выполняется локально, прежде чем отправлять его в реестр контейнеров.
Запустите приложение, сопоставив порт компьютера 4000 с предоставленным портом контейнера 80:
docker run -d -p 4000:80 --name my-web-site helloworldapp
Имя присваивает запущенным контейнеру имя (вместо идентификатора контейнера).
Подключитесь к работающему контейнеру. Откройте веб-браузер, указывающий на IP-адрес, возвращенный через порт 4000, например "http://localhost:4000". В браузере появится заголовок Hello World!
Чтобы остановить контейнер, выполните следующую команду:
docker stop my-web-site
Удалите контейнер с компьютера разработки:
docker rm my-web-site
Отправьте образ в реестр контейнеров
После того как вы убедитесь, что приложение работает в Docker, отправьте образ в реестр Azure Container Registry.
Выполните 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
Упаковка образа Docker с помощью Yeoman
Пакет SDK Service Fabric для Linux включает генератор Yeoman , который упрощает создание приложения и добавление образа контейнера. Давайте будем использовать Yeoman для создания приложения с одним контейнером Docker с именем SimpleContainerApp.
Чтобы создать контейнерное приложение Service Fabric, откройте окно терминала и выполните команду yo azuresfcontainer.
Присвойте приложению имя (например, mycontainer) и назовите службу приложений (например, myservice).
В качестве имени образа укажите URL-адрес образа контейнера в реестре контейнеров (например, "myregistry.azurecr.io/samples/helloworldapp").
Так как в этом образе определена входная точка рабочей нагрузки, вам не нужно явно указывать входные команды (они выполняются внутри контейнера и поддерживают его работу после запуска).
Укажите число экземпляров "1".
Укажите сопоставление портов в соответствующем формате. Для этой статьи необходимо указать 80:4000 сопоставление портов. При этом вы настроили, что все входящие запросы, поступающие на порт 4000 на хост-компьютере, перенаправляются на порт 80 в контейнере.
Настройка проверки подлинности репозитория контейнеров
Ознакомьтесь с проверкой подлинности репозитория контейнеров, чтобы узнать, как настроить различные типы проверки подлинности для скачивания образа контейнера.
Настройка режима изоляции
В выпуске среды выполнения 6.3 изоляция виртуальных машин поддерживается для контейнеров Linux, тем самым поддерживая два режима изоляции для контейнеров: процесс и Hyper-V. При использовании режима изоляции Hyper-V ядра изолированы между каждым контейнером и узлом контейнера. Изоляция Hyper-V реализуется с помощью Clear Containers. Режим изоляции указан для кластеров Linux в элементе ServicePackageContainerPolicy в файле манифеста приложения. Режимы изоляции, которые можно указать, это process, hyperv и default. По умолчанию используется режим изоляции процесса. В следующем фрагменте кода показано, как режим изоляции указан в файле манифеста приложения.
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="MyServicePkg" ServiceManifestVersion="1.0.0"/>
<Policies>
<ServicePackageContainerPolicy Hostname="votefront" Isolation="hyperv">
<PortBinding ContainerPort="80" EndpointRef="myServiceTypeEndpoint"/>
</ServicePackageContainerPolicy>
</Policies>
</ServiceManifestImport>
Настройка управления ресурсами
Управление ресурсами ограничивает ресурсы, которые контейнер может использовать на узле. Элемент ResourceGovernancePolicy , указанный в манифесте приложения, используется для объявления ограничений ресурсов для пакета кода службы. Ограничения ресурсов можно задать для следующих ресурсов: memory, MemorySwap, CpuShares (относительный вес ЦП), MemoryReservationInMB, BlkioWeight (BlockIO относительный вес). В этом примере пакет службы Guest1Pkg получает одно ядро на узлах кластера, где он размещен. Ограничения памяти являются абсолютными, поэтому пакет кода ограничен 1024 МБ памяти (и мягким гарантированным резервированием такого же объёма). Пакеты кода (контейнеры или процессы) не могут выделить больше памяти, чем это ограничение, и попытка сделать это приводит к исключению из памяти. Для обеспечения работы ограничения ресурсов все пакеты кода в пакете службы должны иметь ограничения памяти.
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="MyServicePKg" ServiceManifestVersion="1.0.0" />
<Policies>
<ServicePackageResourceGovernancePolicy CpuCores="1"/>
<ResourceGovernancePolicy CodePackageRef="Code" MemoryInMB="1024" />
</Policies>
</ServiceManifestImport>
Настройка docker HEALTHCHECK
Начиная с версии 6.1 Service Fabric автоматически интегрирует события docker HEALTHCHECK в отчет о работоспособности системы. Это означает, что если в контейнере включена функция HEALTHCHECK , Service Fabric сообщает о работоспособности всякий раз, когда состояние работоспособности контейнера изменяется, как сообщает Docker. Отчет о работоспособности OK отображается в Service Fabric Explorer , когда health_statusработоспособен , и предупреждение будет отображаться, когда health_statusнеработоспособен.
Начиная с последнего обновления версии 6.4, можно указать, что результаты проверки docker HEALTHCHECK должны восприниматься как ошибка. Если этот параметр включен, отчет о состоянии здоровья ОК будет отображаться, когда health_statusздоровое состояние, а ОШИБКА будет отображаться, когда health_statusнездоровое состояние.
Инструкция HEALTHCHECK , указывающая на фактическую проверку работоспособности контейнера, должна присутствовать в Dockerfile, используемой при создании образа контейнера.
Вы можете настроить поведение HEALTHCHECK для каждого контейнера, указав параметры HealthConfig в составе ContainerHostPolicies в ApplicationManifest.
<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, отчеты о работоспособности ERROR будут отображаться, когда health_status контейнера неработоспособен.
Если вы хотите отключить интеграцию HEALTHCHECK для всего кластера Service Fabric, необходимо задать для параметра EnableDockerHealthCheckIntegrationзначение false.
Развертывание приложения
После создания приложения его можно развернуть в локальном кластере с помощью интерфейса командной строки Service Fabric.
Подключитесь к удаленному кластеру Service Fabric.
sfctl cluster select --endpoint http://localhost:19080
Используйте скрипт установки, предоставленный в шаблонах, чтобы скопировать пакет приложения в хранилище образов https://github.com/Azure-Samples/service-fabric-containers/ кластера, зарегистрировать тип приложения и создать экземпляр приложения.
./install.sh
Откройте браузер и перейдите в Service Fabric Explorer http://localhost:19080/Explorer по адресу (замените localhost частным IP-адресом виртуальной машины при использовании Vagrant в Mac OS X). Разверните узел "Приложения" и заметьте, что теперь есть запись для вашего типа приложения и еще одна для первого экземпляра этого типа.
Подключитесь к работающему контейнеру. Откройте веб-браузер, указывающий на IP-адрес, возвращенный через порт 4000, например "http://localhost:4000". В браузере появится заголовок Hello World!
Очистка
Используйте скрипт удаления, предоставленный в шаблоне, чтобы удалить экземпляр приложения из локального кластера разработки и отменить регистрацию типа приложения.
./uninstall.sh
После отправки образа в реестр контейнеров можно удалить локальный образ с компьютера разработки:
docker rmi helloworldapp
docker rmi myregistry.azurecr.io/samples/helloworldapp
Полный пример манифестов приложений и служб Service Fabric
Ниже приведены полные манифесты службы и приложения, используемые в этой статье.
ServiceManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="myservicePkg"
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="myserviceType" 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 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="VariableName" Value="VariableValue"/>
-->
</EnvironmentVariables>
</CodePackage>
<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="myServiceTypeEndpoint" UriScheme="http" Port="4000" Protocol="http"/>
</Endpoints>
</Resources>
</ServiceManifest>
ApplicationManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest ApplicationTypeName="mycontainerType"
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">
<!-- 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="myservicePkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
<Policies>
<ContainerHostPolicies CodePackageRef="Code">
<RepositoryCredentials AccountName="myregistry" Password="=P==/==/=8=/=+u4lyOB=+=nWzEeRfF=" PasswordEncrypted="false"/>
<PortBinding ContainerPort="80" EndpointRef="myServiceTypeEndpoint"/>
</ContainerHostPolicies>
</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="myservice">
<!-- On a local development cluster, set InstanceCount to 1. On a multi-node production
cluster, set InstanceCount to -1 for the container service to run on every node in
the cluster.
-->
<StatelessService ServiceTypeName="myserviceType" InstanceCount="1">
<SingletonPartition />
</StatelessService>
</Service>
</DefaultServices>
</ApplicationManifest>
Добавление дополнительных служб в существующее приложение
Чтобы добавить другую службу контейнеров в приложение, уже созданное с помощью yeoman, выполните следующие действия:
- Перейдите в корневой каталог существующего приложения. Например,
cd ~/YeomanSamples/MyApplication, еслиMyApplicationявляется приложением, созданным с помощью Yeoman. - Запуск
yo azuresfcontainer:AddService
Настройте интервал времени перед принудительным завершением контейнера
Можно настроить интервал времени для среды выполнения до удаления контейнера после удаления службы (или перехода на другой узел). При настройке интервала времени команда docker stop <time in seconds> отправляется в контейнер. Дополнительные сведения см. в разделе docker stop. Интервал времени ожидания указывается в разделе Hosting . В следующем фрагменте манифеста кластера показано, как задать интервал ожидания:
{
"name": "Hosting",
"parameters": [
{
"name": "ContainerDeactivationTimeout",
"value" : "10"
},
...
]
}
Интервал времени по умолчанию — 10 секунд. Поскольку эта конфигурация динамическая, обновление только конфигурации в кластере изменяет время ожидания.
Настройка среды выполнения для удаления неиспользуемых образов контейнеров
Кластер Service Fabric можно настроить для удаления неиспользуемых образов контейнеров из узла. Эта конфигурация позволяет восстановить место на диске, если на узле присутствует слишком много образов контейнеров. Чтобы включить эту функцию, обновите Hosting раздел в манифесте кластера, как показано в следующем фрагменте кода:
{
"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 в разделе "Размещение " манифеста кластера, как показано в следующем фрагменте кода:
{
"name": "Hosting",
"parameters": [
{
"name": "ContainerImageDownloadTimeout",
"value": "1200"
}
]
}
Настройка политики хранения контейнера
Чтобы помочь в диагностике сбоев запуска контейнера, Service Fabric (версия 6.1 или более поздней) поддерживает сохранение контейнеров, которые завершили работу или не удалось запустить. Эту политику можно настроить в файле ApplicationManifest.xml, как показано в следующем фрагменте кода:
<ContainerHostPolicies CodePackageRef="NodeService.Code" Isolation="process" ContainersRetentionCount="2" RunInteractive="true">
В атрибуте ContainersRetentionCount указывается число контейнеров, которые следует сохранить после сбоя. Если указано отрицательное значение, все неудачные контейнеры сохраняются. Если атрибут ContainerRetentionCount не указан, контейнеры не будут храниться. Атрибут ContainersRetentionCount также поддерживает параметры приложения, поэтому пользователи могут указывать разные значения для тестовых и рабочих кластеров. Чтобы предотвратить перемещение службы контейнеров на другие узлы, при использовании этих функций используйте ограничения на размещение, указав для службы контейнеров конкретный узел. Удаление всех контейнеров, сохраненных с помощью этой функции, выполняется вручную.
Запуск демона Docker с пользовательскими аргументами
Начиная с версии 6.2 среды выполнения Service Fabric и выше, можно запустить демон Docker с пользовательскими аргументами. При указании пользовательских аргументов Service Fabric не передает ни один другой аргумент в подсистему Docker, кроме аргумента --pidfile . Поэтому --pidfile не следует передавать в качестве аргумента. Кроме того, демон Docker должен продолжать прослушивать стандартный именованный канал в Windows (или сокет домена Unix в Linux), чтобы Service Fabric мог взаимодействовать с ним. Настраиваемые аргументы указываются в манифесте кластера в разделе Размещение под АргументыContainerService. Пример показан в следующем фрагменте кода:
{
"name": "Hosting",
"parameters": [
{
"name": "ContainerServiceArguments",
"value": "-H localhost:1234 -H unix:///var/run/docker.sock"
}
]
}
Дальнейшие действия
- Узнайте больше о запуске контейнеров в Service Fabric.
- Ознакомьтесь с руководством по развертыванию приложения .NET в контейнере .
- Узнайте о жизненном цикле приложения Service Fabric.
- Ознакомьтесь с примерами кода контейнера Service Fabric на GitHub.