Поделиться через


Create your first Service Fabric container application on Linux

Running an existing application in a Linux container on a Service Fabric cluster doesn't require any changes to your application. This article walks you through creating a Docker image containing a Python Flask web application and deploying it to a Service Fabric cluster. You will also share your containerized application through Azure Container Registry. В этой статье предполагается базовое понимание Docker. Вы можете узнать о Docker, прочитав обзор Docker.

Примечание.

This article applies to a Linux development environment. Среда выполнения кластера Service Fabric и среда выполнения Docker должны работать в той же ОС. You cannot run Linux containers on a Windows cluster.

Предпосылки

Определение контейнера 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 .

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

Create a Flask web application listening on port 80 that returns "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 и создание образа

Далее мы создадим образ, который запускает веб-приложение. When pulling public images from Docker (like python:2.7-slim in our Dockerfile), it's a best practice to authenticate with your Docker Hub account instead of making an anonymous pull request.

Примечание.

При частом выполнении анонимных 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 .

This command builds the new image using the instructions in your Dockerfile, naming (-t tagging) the image helloworldapp. Чтобы создать образ контейнера, базовый образ сначала скачан из Docker Hub, в который добавляется приложение.

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

$ docker images
    
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
helloworldapp                 latest              86838648aab6        2 minutes ago       194 MB

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

Verify that your containerized application runs locally before pushing it the container registry.

Run the application, mapping your computer's port 4000 to the container's exposed port 80:

docker run -d -p 4000:80 --name my-web-site helloworldapp

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

Подключитесь к работающему контейнеру. Open a web browser pointing to the IP address returned on port 4000, for example "http://localhost:4000". В браузере появится заголовок Hello World!

Hello World!

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

docker stop my-web-site

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

docker rm my-web-site

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

After you verify that the application runs in Docker, push the image to your registry in Azure Container Registry.

Run docker login to sign in to your container registry with your registry credentials.

В следующем примере передается идентификатор и пароль сервисного принципала Microsoft Entra. For example, you might have assigned a service principal to your registry for an automation scenario. Кроме того, вы можете войти с помощью имени пользователя и пароля реестра.

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

The following command creates a tag, or alias, of the image, with a fully qualified path to your registry. В этом примере изображение помещается в пространство имен samples, чтобы избежать захламлённости в корневой части реестра.

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

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

docker push myregistry.azurecr.io/samples/helloworldapp

Package the Docker image with Yeoman

The Service Fabric SDK for Linux includes a Yeoman generator that makes it easy to create your application and add a container image. Let's use Yeoman to create an application with a single Docker container called SimpleContainerApp.

To create a Service Fabric container application, open a terminal window and run yo azuresfcontainer.

Name your application (for example, mycontainer) and name the application service (for example, myservice).

For the image name, provide the URL for the container image in a container registry (for example, "myregistry.azurecr.io/samples/helloworldapp").

Since this image has a workload entry-point defined, you don't need to explicitly specify input commands (commands run inside the container, which will keep the container running after startup).

Specify an instance count of "1".

Specify the port mapping in the appropriate format. For this article, you need to provide 80:4000 as the port mapping. By doing this you have configured that any incoming requests coming to port 4000 on the host machine are redirected to port 80 on the container.

Service Fabric Yeoman generator for containers

Настройка проверки подлинности репозитория контейнеров

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

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

With the 6.3 runtime release, VM isolation is supported for Linux containers, thereby supporting two isolation modes for containers: process and Hyper-V. With the Hyper-V isolation mode, the kernels are isolated between each container and the container host. The Hyper-V isolation is implemented using Clear Containers. The isolation mode is specified for Linux clusters in the ServicePackageContainerPolicy element in the application manifest file. Режимы изоляции, которые можно указать, это process, hyperv и default. The default is process isolation mode. В следующем фрагменте кода показано, как режим изоляции указан в файле манифеста приложения.

<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 относительный вес). In this example, service package Guest1Pkg gets one core on the cluster nodes where it is placed. Ограничения памяти являются абсолютными, поэтому пакет кода ограничен 1024 МБ памяти (и мягким гарантированным резервированием такого же объёма). Code packages (containers or processes) are not able to allocate more memory than this limit, and attempting to do so results in an out-of-memory exception. Для обеспечения работы ограничения ресурсов все пакеты кода в пакете службы должны иметь ограничения памяти.

<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, используемой при создании образа контейнера.

Снимок экрана показывает сведения о развернутом пакете службы NodeServicePackage.

HealthCheckUnhealthyApp

HealthCheckUnhealthyDsp

Вы можете настроить поведение 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 контейнера неработоспособен.

If you want to the disable the HEALTHCHECK integration for the entire Service Fabric cluster, you will need to set EnableDockerHealthCheckIntegration to false.

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

Once the application is built, you can deploy it to the local cluster using the Service Fabric CLI.

Подключитесь к удаленному кластеру Service Fabric.

sfctl cluster select --endpoint http://localhost:19080

Use the install script provided in the templates at https://github.com/Azure-Samples/service-fabric-containers/ to copy the application package to the cluster's image store, register the application type, and create an instance of the application.

./install.sh

Open a browser and navigate to Service Fabric Explorer at http://localhost:19080/Explorer (replace localhost with the private IP of the VM if using Vagrant on Mac OS X). Expand the Applications node and note that there is now an entry for your application type and another for the first instance of that type.

Подключитесь к работающему контейнеру. Open a web browser pointing to the IP address returned on port 4000, for example "http://localhost:4000". В браузере появится заголовок Hello World!

Hello World!

Очистка

Use the uninstall script provided in the template to delete the application instance from the local development cluster and unregister the application type.

./uninstall.sh

After you push the image to the container registry you can delete the local image from your development computer:

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>

Добавление дополнительных служб в существующее приложение

To add another container service to an application already created using yeoman, perform the following steps:

  1. Перейдите в корневой каталог существующего приложения. Например, cd ~/YeomanSamples/MyApplication, если MyApplication является приложением, созданным с помощью Yeoman.
  2. Run yo azuresfcontainer:AddService

Configure time interval before container is force terminated

You can configure a time interval for the runtime to wait before the container is removed after the service deletion (or a move to another node) has started. При настройке интервала времени команда docker stop <time in seconds> отправляется в контейнер. Дополнительные сведения см. в разделе docker stop. Интервал времени ожидания указывается в разделе Hosting . В следующем фрагменте манифеста кластера показано, как задать интервал ожидания:

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

Интервал времени по умолчанию — 10 секунд. Since this configuration is dynamic, a config only upgrade on the cluster updates the timeout.

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

Кластер Service Fabric можно настроить для удаления неиспользуемых образов контейнеров из узла. Эта конфигурация позволяет восстановить место на диске, если на узле присутствует слишком много образов контейнеров. To enable this feature, update the Hosting section in the cluster manifest as shown in the following snippet:

{
        "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 .

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

The Service Fabric runtime allocates 20 minutes to download and extract container images, which works for the majority of container images. Для больших образов или при медленном подключении к сети может потребоваться увеличить время ожидания, прежде чем прерывать скачивание и извлечение образа. This timeout is set using the ContainerImageDownloadTimeout attribute in the Hosting section of the cluster manifest as shown in the following snippet:

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

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

To assist with diagnosing container startup failures, Service Fabric (version 6.1 or higher) supports retaining containers that terminated or failed to start. Эту политику можно настроить в файле ApplicationManifest.xml, как показано в следующем фрагменте кода:

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

В атрибуте ContainersRetentionCount указывается число контейнеров, которые следует сохранить после сбоя. If a negative value is specified, all failing containers will be retained. When the ContainersRetentionCount attribute is not specified, no containers will be retained. Атрибут ContainersRetentionCount также поддерживает параметры приложения, поэтому пользователи могут указывать разные значения для тестовых и рабочих кластеров. Чтобы предотвратить перемещение службы контейнеров на другие узлы, при использовании этих функций используйте ограничения на размещение, указав для службы контейнеров конкретный узел. Удаление всех контейнеров, сохраненных с помощью этой функции, выполняется вручную.

Запуск демона Docker с пользовательскими аргументами

Начиная с версии 6.2 среды выполнения Service Fabric и выше, можно запустить демон Docker с пользовательскими аргументами. When custom arguments are specified, Service Fabric does not pass any other argument to docker engine except the --pidfile argument. Поэтому --pidfile не следует передавать в качестве аргумента. Additionally, the argument should continue to have the docker daemon listen on the default name pipe on Windows (or unix domain socket on Linux) for Service Fabric to communicate with the daemon. The custom arguments are specified in the cluster manifest under the Hosting section under ContainerServiceArguments. An example is shown in the following snippet:

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

Дальнейшие действия