Creare la prima applicazione contenitore di Service Fabric in Windows

Per eseguire un'applicazione esistente in un contenitore Windows in un cluster di Service Fabric non è necessario apportare modifiche all'applicazione. Questo articolo illustra come creare un'immagine Docker contenente un'applicazione Web Python Flask e distribuirla in un cluster di Azure Service Fabric. Si condividerà anche l'applicazione in contenitore tramite Registro Azure Container. L'articolo presuppone una conoscenza di base di Docker. Per informazioni su Docker, vedere Docker overview (Panoramica su Docker).

Nota

Questo articolo si applica a un ambiente di sviluppo Windows. Il runtime del cluster di Service Fabric e il runtime di Docker devono essere in esecuzione nello stesso sistema operativo. Non è possibile eseguire contenitori Windows su un cluster Linux.

Nota

È consigliabile usare il modulo Azure Az PowerShell per interagire con Azure. Per iniziare, vedere Installare Azure PowerShell. Per informazioni su come eseguire la migrazione al modulo AZ PowerShell, vedere Eseguire la migrazione di Azure PowerShell da AzureRM ad Az.

Prerequisiti

  • Un computer di sviluppo che esegue:

    • Visual Studio 2015 o Visual Studio 2019.
    • SDK e strumenti di Service Fabric.
    • Docker per Windows. Scaricare Docker CE per Windows (stabile). Dopo aver installato e avviato Docker, fare clic con il pulsante destro del mouse sull'icona nell'area di notifica e selezionare Switch to Windows containers (Passa ai contenitori Windows). Questo passaggio è necessario per eseguire le immagini Docker basate su Windows.
  • Un cluster Windows con tre o più nodi che esegue Windows Server con contenitori.

    Per questo articolo, la versione (build) di Windows Server con contenitori in esecuzione nei nodi del cluster deve corrispondere a quella nel computer di sviluppo. Questo è dovuto al fatto che l'immagine Docker viene compilata nel computer di sviluppo e sono presenti vincoli compatibilità tra le versioni del sistema operativo del contenitore e il sistema operativo host in cui è distribuito. Per altre informazioni, vedere Compatibilità tra il sistema operativo del contenitore di Windows Server e il sistema operativo dell'host.

    Per determinare la versione di Windows Server con contenitori necessari per il cluster, eseguire il ver comando da un prompt dei comandi di Windows nel computer di sviluppo. Prima di creare un cluster, fare riferimento alla compatibilitàdel sistema operativo contenitore di Windows Server e del sistema operativo host.

  • Un registro all'interno di Registro Azure Container. A questo scopo, creare un registro contenitori nella sottoscrizione di Azure.

Nota

La distribuzione di contenitori in un cluster di Service Fabric in esecuzione in Windows 10 è supportata. Vedere questo articolo per informazioni su come configurare Windows 10 per l'esecuzione di contenitori Windows.

Nota

Service Fabric versione 6.2 e successive supporta la distribuzione di contenitori in cluster in esecuzione in Windows Server versione 1709.

Definire il contenitore Docker

Compilare un'immagine in base all'immagine Python disponibile nell'hub Docker.

Specificare il contenitore Docker in un Dockerfile. Il Dockerfile è costituito da istruzioni per la configurazione dell'ambiente all'interno del contenitore, il caricamento dell'applicazione da eseguire e il mapping delle porte. Il file Dockerfile rappresenta l'input per il comando docker build che crea l'immagine.

Creare una directory vuota e il file Dockerfile (senza estensione file). Aggiungere quanto segue a Dockerfile e salvare le modifiche:

# 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"]

Per altre informazioni, vedere Dockerfile reference (Informazioni di riferimento su Dockerfile).

Creare un'applicazione Web di base

Creare un'applicazione Web Flask in ascolto sulla porta 80 che restituisce Hello World!. Nella stessa directory creare il file requirements.txt. Aggiungere quanto segue e salvare le modifiche:

Flask

Creare anche il file app.py e aggiungere il frammento di codice seguente:

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)

Accedere a Docker e compilare l'immagine

Verrà quindi creata l'immagine che esegue l'applicazione Web. Quando si estraggono immagini pubbliche da Docker (ad esempio python:2.7-windowsservercore nel Dockerfile), è consigliabile eseguire l'autenticazione con l'account dell'hub Docker anziché effettuare una richiesta pull anonima.

Nota

Quando si effettuano frequenti richieste pull anonime, è possibile che vengano visualizzati errori Docker simili a o You have reached your pull rate limit. Autenticati nell'hub ERROR: toomanyrequests: Too Many Requests. Docker per evitare questi errori. Per altre informazioni, vedi Gestire il contenuto pubblico con Registro Azure Container.

Aprire una finestra di PowerShell e passare alla directory contenente il Dockerfile. Eseguire quindi i comandi seguenti:

docker login
docker build -t helloworldapp .

Questo comando crea la nuova immagine usando le istruzioni contenute nel Dockerfile e denomina l'immagine helloworldapp, ovvero le assegna un tag -t. Per creare un'immagine del contenitore, l'immagine di base viene prima scaricata dall'hub Docker nel quale viene aggiunta l'applicazione.

Al termine dell'esecuzione del comando di compilazione, eseguire il comando docker images per visualizzare le informazioni sulla nuova immagine:

$ docker images

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

Eseguire l'applicazione in locale

Verifica l'immagine in locale prima di effettuarne il push nel registro contenitori.

Eseguire l'applicazione:

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

name assegna un nome al contenitore in esecuzione, anziché l'ID contenitore.

Dopo aver avviato il contenitore, trovare il relativo indirizzo IP per consentire la connessione al contenitore in esecuzione da un browser:

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

Se il comando non restituisce alcun elemento, eseguire il comando seguente ed esaminare l'elemento Network Impostazioni-Networks> per l'indirizzo IP:

docker inspect my-web-site

Connettersi al contenitore in esecuzione. Aprire un Web browser che punta all'indirizzo IP restituito, ad esempio "http://172.31.194.61". Nel browser dovrebbe essere visualizzata l'intestazione "Hello World!".

Per arrestare il contenitore, eseguire:

docker stop my-web-site

Per eliminare il contenitore dal computer di sviluppo, eseguire:

docker rm my-web-site

Effettuare il push dell'immagine nel registro contenitori

Dopo aver verificato l'esecuzione del contenitore nel computer di sviluppo, effettuare il push dell'immagine nel registro all'interno di Registro Azure Container.

Eseguire docker login per accedere al registro contenitori con le credenziali del registro.

L'esempio seguente passa l'ID e la password di un'entità servizio Microsoft Entra. Ad esempio, è possibile che sia stata assegnata un'entità servizio al registro per uno scenario di automazione. In alternativa, è possibile accedere usando il nome utente e la password del Registro di sistema.

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

Il comando seguente crea un tag, o alias, dell'immagine, con un percorso completo del registro. Questo esempio inserisce l'immagine dello spazio dei nomi samples per evitare confusione nella radice del registro.

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

Effettuare il push dell'immagine nel registro contenitori:

docker push myregistry.azurecr.io/samples/helloworldapp

Creare il servizio in contenitori in Visual Studio

L'SDK e gli strumenti di Service Fabric offrono un modello di servizio che consente di creare un'applicazione in contenitori.

  1. Avviare Visual Studio. Selezionare File>New (Nuovo) >Project (Progetto).
  2. Selezionare l'applicazione di Service Fabric, denominarla "MyFirstContainer" e fare clic su OK.
  3. Scegliere Contenitore dall'elenco dei modelli di servizio.
  4. In Nome immagine immettere "myregistry.azurecr.io/samples/helloworldapp", vale a dire l'immagine di cui è stato effettuato il push nel repository dei contenitori.
  5. Assegnare un nome al servizio e fare clic su OK.

Configurare la comunicazione

Il servizio in contenitori richiede un endpoint per la comunicazione. Aggiungere un elemento Endpoint con il protocollo, la porta e il tipo al file ServiceManifest.xml. In questo esempio viene usata una porta fissa 8081. Se non vengono specificate porte, verrà scelta una porta casuale dall'intervallo di porte dell'applicazione.

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

Nota

È possibile aggiungere altri endpoint per un servizio dichiarando elementi EndPoint aggiuntivi con valori della proprietà applicabili. Ogni porta può dichiarare un solo valore di protocollo.

Definendo un endpoint, Service Fabric pubblica l'endpoint nel servizio Naming. Altri servizi in esecuzione nel cluster possono risolvere questo contenitore. È anche possibile eseguire la comunicazione da contenitore a contenitore usando il proxy inverso. La comunicazione avviene specificando la porta di ascolto HTTP del proxy inverso e il nome dei servizi con cui si vuole comunicare come variabili di ambiente.

Il servizio è in ascolto su una porta specifica, 8081 in questo esempio. Quando l'applicazione viene distribuita in un cluster in Azure, sia il cluster che l'applicazione vengono eseguiti dietro un servizio di bilanciamento del carico di Azure. La porta dell'applicazione deve essere aperta nel servizio di bilanciamento del carico di Azure in modo che il traffico in entrata possa raggiungere il servizio. È possibile aprire questa porta nel servizio di bilanciamento carico di Azure usando uno script di PowerShell o il portale di Azure.

Configurare e impostare variabili di ambiente

È possibile specificare variabili di ambiente per ogni pacchetto di codice nel manifesto del servizio. Questa funzionalità è disponibile per tutti i servizi, siano essi distribuiti come contenitori, processi o eseguibili guest. È possibile sostituire i valori delle variabili di ambiente nel manifesto dell'applicazione oppure specificarli durante la distribuzione come parametri dell'applicazione.

Il frammento XML del manifesto del servizio seguente offre un esempio di come specificare le variabili di ambiente per un pacchetto di codice:

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

È possibile eseguire l'override di queste variabili di ambiente nel manifesto dell'applicazione:

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

Configurare il mapping tra porta del contenitore e porta dell'host e l'individuazione da contenitore a contenitore

Configurare una porta dell'host per la comunicazione con il contenitore. Il binding di porta esegue il mapping tra la porta su cui il servizio è in ascolto nel contenitore e una porta nell'host. Aggiungere un elemento PortBinding nell'elemento ContainerHostPolicies del file ApplicationManifest.xml. Per questo articolo, il valore di ContainerPort è 80, vale a dire che il contenitore espone la porta 80, come specificato nel Dockerfile, e il valore di EndpointRef è "Guest1TypeEndpoint", ovvero l'endpoint definito in precedenza nel manifesto del servizio. Per le richieste in ingresso per il servizio sulla porta 8081 viene eseguito il mapping alla porta 80 del contenitore.

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

Nota

È possibile aggiungere altri PortBinding per un servizio dichiarando elementi PortBinding aggiuntivi con valori della proprietà applicabili.

Configurare l'autenticazione del repository di contenitori

Vedere Autenticazionedel repository contenitori per informazioni su come configurare diversi tipi di autenticazione per il download di immagini del contenitore.

Configurare la modalità di isolamento

Windows supporta due modalità di isolamento per i contenitori: la modalità processo e la modalità Hyper-V. Nella modalità di isolamento del processo tutti i contenitori in esecuzione nello stesso computer host condividono il kernel con l'host. Nella modalità di isolamento Hyper-V i kernel sono isolati tra i singoli contenitori Hyper-V e il contenitore host. La modalità di isolamento è specificata nell'elemento ContainerHostPolicies nel file manifesto dell'applicazione. Le modalità di isolamento specificabili sono process, hyperv e default. L'impostazione predefinita è la modalità di isolamento dei processi negli host Windows Server. Negli host Windows 10 è supportata solo la modalità di isolamento Hyper-V, pertanto il contenitore verrà eseguito in modalità di isolamento Hyper-V indipendentemente dalla modalità di isolamento impostata. Il frammento seguente indica come è specificata la modalità di isolamento nel file manifesto dell'applicazione.

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

Nota

La modalità di isolamento Hyper-V è disponibile negli SKU di Azure Ev3 e Dv3 che hanno il supporto per la virtualizzazione annidato.

Configurare la governance delle risorse

La governance delle risorse limita le risorse che possono essere usate dal contenitore nell'host. L'elemento ResourceGovernancePolicy, specificato nel manifesto dell'applicazione, viene usato per dichiarare limiti di risorse per il pacchetto di codice di un servizio. È possibile impostare limiti per le risorse seguenti: Memory, MemorySwap, CpuShares (peso relativo CPU), MemoryReservationInMB, BlkioWeight (peso relativo BlockIO). In questo esempio, il pacchetto del servizio Guest1Pkg ottiene un core nei nodi del cluster in cui è posizionato. I limiti di memoria sono assoluti, quindi i pacchetti di codice sono limitati a 1024 MB di memoria, con prenotazione a garanzia flessibile. I pacchetti di codice (contenitori o pacchetti) non sono in grado di allocare una quantità di memoria superiore a questo limite. Un'operazione di questo tipo genererebbe un'eccezione di memoria esaurita. Perché l'imposizione di un limite di risorse funzioni, è necessario che tutti i pacchetti di codice inclusi in un pacchetto del servizio abbiano limiti di memoria specificati.

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

Configurare docker HEALTHCHECK

A partire dalla versione 6.1, Service Fabric integra automaticamente gli eventi di docker HEALTHCHECK nel report relativo all'integrità del sistema. Se HEALTHCHECK è stato abilitato nel contenitore, Service Fabric fornirà informazioni sull'integrità ogni volta che lo stato dell'integrità del contenitore subisce modifiche, in base a quanto segnalato da Docker. Un report sull'integrità di tipo OK verrà visualizzato in Service Fabric Explorer quando il valore health_status è healthy e un report di tipo AVVISO verrà visualizzato quando il valore health_status è unhealthy.

A partire dalla versione di aggiornamento più recente di v6.4, è possibile specificare che le valutazioni docker HEALTHCHECK devono essere segnalate come errore. Se questa opzione è abilitata, verrà visualizzato un report di integrità OK quando health_status è integro e verrà visualizzato l'errore quando health_status non è integro.

L'istruzione HEALTHCHECK che fa riferimento alla verifica effettiva eseguita per il monitoraggio dell'integrità dei contenitori deve essere presente nel Dockerfile usato durante la generazione dell'immagine del contenitore.

Screenshot shows details of the Deployed Service Package NodeServicePackage.

HealthCheckUnhealthyApp

HealthCheckUnhealthyDsp

È possibile configurare il comportamento di HEALTHCHECK per ogni contenitore specificando le opzioni di HealthConfig come parte di ContainerHostPolicies in ApplicationManifest.

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

Per impostazione predefinita IncludeDockerHealthStatusInSystemHealthReport è impostato su true, RestartContainerOnUnhealthyDockerHealthStatus è impostato su false e TreatContainerUnhealthyStatusAsError è impostato su false.

Se l'opzione RestartContainerOnUnhealthyDockerHealthStatus è impostata su true, un contenitore che segnala ripetutamente uno stato non integro viene riavviato, possibilmente su altri nodi.

Se TreatContainerUnhealthyStatusAsError è impostato su true, i report sull'integrità degli errori verranno visualizzati quando il health_status del contenitore non è integro.

Se si vuole disabilitare l'integrazione di HEALTHCHECK per l'intero cluster di Service Fabric, sarà necessario impostare EnableDockerHealthCheckIntegration su false.

Distribuire l'applicazione del contenitore

Salvare tutte le modifiche e compilare l'applicazione. Per pubblicare l'applicazione, fare clic con il pulsante destro del mouse su MyFirstContainer in Esplora soluzioni e scegliere Pubblica.

In Endpoint connessione immettere l'endpoint di gestione per il cluster, Ad esempio, containercluster.westus2.cloudapp.azure.com:19000. L'endpoint di connessione del client è disponibile nella scheda Panoramica del cluster nel portale di Azure.

Fare clic su Pubblica.

Service Fabric Explorer è uno strumento basato sul Web che permette di analizzare e gestire applicazioni e nodi in un cluster di Service Fabric. Aprire un browser Web e passare a http://containercluster.westus2.cloudapp.azure.com:19080/Explorer/ per seguire la distribuzione dell'applicazione. L'applicazione viene distribuita ma è in uno stato di errore fino a quando l'immagine non viene scaricata nei nodi del cluster (che può richiedere del tempo, a seconda delle dimensioni dell'immagine): Error

L'applicazione è pronta quando è in Ready stato: Ready

Aprire un browser e passare a http://containercluster.westus2.cloudapp.azure.com:8081. Nel browser dovrebbe essere visualizzata l'intestazione "Hello World!".

Eseguire la pulizia

Mentre il cluster è in esecuzione, continuano a essere addebitati i relativi costi. È quindi consigliabile eliminare il cluster.

Dopo aver effettuato il push dell'immagine nel registro contenitori, è possibile eliminare l'immagine locale dal computer di sviluppo:

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

Compatibilità tra il sistema operativo del contenitore di Windows Server e il sistema operativo dell'host

I contenitori di Windows Server non sono compatibili con tutte le versioni del sistema operativo host. Ad esempio:

  • I contenitori di Windows Server creati tramite Windows Server versione 1709 non funzionano in un host che esegue Windows Server 2016.
  • I contenitori di Windows Server creati con Windows Server 2016 funzionano in modalità di isolamento Hyper-V solo in un host che esegue Windows Server versione 1709.
  • Con i contenitori di Windows Server creati tramite Windows Server 2016, potrebbe essere necessario assicurarsi che la revisione del sistema operativo del contenitore e del sistema operativo host corrispondano durante l'esecuzione in modalità di isolamento dei processi in un host che esegue Windows Server 2016.

Per altre informazioni, vedere Compatibilità delle versioni dei contenitori di Windows.

Considerare la compatibilità del sistema operativo host e del sistema operativo del contenitore durante la creazione e la distribuzione dei contenitori nel cluster di Service Fabric. Ad esempio:

  • Assicurarsi di distribuire i contenitori con un sistema operativo compatibile con il sistema operativo nei nodi del cluster.
  • Assicurarsi che la modalità di isolamento specificata per l'applicazione contenitore sia coerente con il supporto per il sistema operativo contenitore nel nodo in cui viene distribuita.
  • Valutare in che modo gli aggiornamenti del sistema operativo nei nodi del cluster o nei contenitori possono influenzarne la compatibilità.

È consigliabile attenersi alle seguenti procedure per assicurarsi che i contenitori siano distribuiti correttamente nel cluster di Service Fabric:

  • Usare l'assegnazione di tag espliciti con le immagini Docker per specificare la versione del sistema operativo Windows Server da cui è stato creato un contenitore.
  • Usare l'assegnazione di tag del sistema operativo nel file manifesto dell'applicazione per assicurarsi che l'applicazione sia compatibile con le diverse versioni e gli aggiornamenti di Windows Server.

Nota

Con Service Fabric 6.2 e versioni successive, è possibile distribuire i contenitori basati su Windows Server 2016 in locale su un host Windows 10. In Windows 10, i contenitori vengono eseguiti in modalità di isolamento Hyper-V, indipendentemente dalla modalità di isolamento impostata nel manifesto dell'applicazione. Per altre informazioni, vedere Configurare la modalità di isolamento.

Specificare immagini del contenitore specifiche per la build del sistema operativo

I contenitori di Windows Server potrebbero non essere compatibili nelle diverse versioni del sistema operativo. Ad esempio, i contenitori di Windows Server creati tramite Windows Server 2016 non funzionano in Windows Server versione 1709 in modalità di isolamento dei processi. Se i nodi del cluster vengono aggiornati alla versione più recente, è quindi possibile che si verifichino errori nei servizi contenitori creati usando le versioni precedenti del sistema operativo. Per aggirare questo problema con la versione 6.1 del runtime e con le versioni successive, Service Fabric supporta la possibilità di specificare più immagini del sistema operativo per ogni contenitore e di contrassegnarle con le versioni della build del sistema operativo nel manifesto dell'applicazione. È possibile ottenere la versione della build del sistema operativo eseguendo winver al prompt dei comandi di Windows. Aggiornare i manifesti dell'applicazione e specificare gli override delle immagini per ogni versione del sistema operativo prima di aggiornare il sistema operativo nei nodi. Il frammento di codice seguente mostra come specificare più immagini del contenitore nel manifesto dell'applicazione, 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> 

La versione di build per Windows Server 2016 è 14393 e la versione di build per Windows Server versione 1709 è 16299. Il manifesto del servizio continua a specificare solo un'immagine per ogni servizio contenitore, come mostrato di seguito:

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

Nota

Le funzionalità di contrassegno delle versioni della build del sistema operativo sono disponibili solo per Service Fabric su Windows

Se la build del sistema operativo sottostante sulla VM è 16299 (versione 1709), Service Fabric seleziona l'immagine del contenitore corrispondente a tale versione di Windows Server. Se nel manifesto dell'applicazione viene fornita anche un'immagine del contenitore non contrassegnata insieme alle immagini del contenitore contrassegnate, Service Fabric considera l'immagine non contrassegnata come quella in grado di funzionare in tutte le versioni. Contrassegnare le immagini del contenitore in modo esplicito per evitare problemi durante gli aggiornamenti.

L'immagine del contenitore non contrassegnata eseguirà l'override dell'immagine specificata nel file ServiceManifest. L'immagine "myregistry.azurecr.io/samples/helloworldappDefault" eseguirà quindi l'override del nome immagine "myregistry.azurecr.io/samples/helloworldapp" nel file ServiceManifest.

Manifesti di esempio completi del servizio e dell'applicazione di Service Fabric

Di seguito sono riportati i manifesti completi del servizio e dell'applicazione usati in questo articolo.

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>

Configurare l'intervallo di tempo prima della terminazione forzata del contenitore

È possibile configurare un intervallo di tempo di attesa del runtime prima che il contenitore venga rimosso dopo l'avvio dell'eliminazione del servizio (o di un passaggio a un altro nodo). Configurando l'intervallo di tempo, viene inviato il comando docker stop <time in seconds> al contenitore. Per altri dettagli, vedere docker stop. L'intervallo di tempo per l'attesa viene specificato nella sezione Hosting. La Hosting sezione può essere aggiunta al momento della creazione del cluster o successiva in un aggiornamento della configurazione. Il frammento di manifesto del cluster seguente illustra come impostare l'intervallo di attesa:

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

L'intervallo di tempo predefinito è impostato su 10 secondi. Poiché questa configurazione è dinamica, un aggiornamento della sola configurazione nel cluster aggiorna il timeout.

Configurare il runtime per rimuovere le immagini del contenitore non usate

È possibile configurate il cluster di Service Fabric per rimuovere le immagini del contenitore non usate dal nodo. Questa configurazione consente di riacquisire spazio su disco se nel nodo sono presenti troppe immagini del contenitore. Per abilitare questa funzionalità, aggiornare la sezione Hosting nel manifesto del cluster, come illustrato nel frammento di codice seguente:

"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|..."
          }
          ...
          }
        ]
	} 
]

Le immagini che non devono essere eliminate possono essere specificate nel parametro ContainerImagesToSkip.

Configurare il tempo di download delle immagini del contenitore

Il runtime di Service Fabric alloca 20 minuti per il download e l'estrazione delle immagini del contenitore, perché tale limite è appropriato per la maggior parte delle immagini del contenitore. Per immagini di grandi dimensioni o in caso di connessione di rete lenta potrebbe essere necessario aumentare il tempo di attesa prima dell'interruzione del download e dell'estrazione dell'immagine. Questo timeout viene configurato tramite l'attributo ContainerImageDownloadTimeout nella sezione Hosting del manifesto del cluster, come mostrato nel frammento di codice seguente:

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

Configurare i criteri di conservazione dei contenitori

Per semplificare la diagnosi degli errori di avvio dei contenitori, Service Fabric (versione 6.1 o versioni successive) supporta la conservazione di contenitori terminati o il cui avvio non è riuscito. Questo criterio può essere configurato nel file ApplicationManifest.xml, come mostrato nel frammento di codice seguente:

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

L'impostazione ContainersRetentionCount specifica il numero di contenitori da conservare in caso di errore. Se viene specificato un valore negativo, verranno conservati tutti i contenitori con errori. Quando l'attributo ContainersRetentionCount non viene specificato, non verrà conservato alcun contenitore. L'attributo ContainersRetentionCount supporta anche i parametri dell'applicazione, quindi gli utenti possono specificare valori diversi per cluster di test e di produzione. Usare vincoli di posizionamento per specificare come destinazione un nodo specifico per il servizio contenitore quando si usa questa funzionalità, per evitare che il servizio contenitore passi ad altri nodi. Eventuali contenitori conservati tramite questa funzionalità devono essere rimossi manualmente.

Avviare il daemon Docker con argomenti personalizzati

A partire dalla versione 6.2 del runtime di Service Fabric è possibile avviare il daemon Docker con argomenti personalizzati. Quando vengono specificati argomenti personalizzati, Service Fabric non passa altri argomenti al motore Docker, ad eccezione dell'argomento --pidfile. Di conseguenza, --pidfile non deve essere passato come argomento. L'argomento deve continuare ad avere il daemon Docker in ascolto sulla named pipe predefinita in Windows (o sul socket di dominio Unix in Linux) perché Service Fabric possa comunicare con il daemon. Gli argomenti personalizzati vengono passati nel manifesto del cluster nella sezione Hosting in ContainerServiceArguments, come mostrato nel frammento di codice seguente:

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

EntryPoint Override

Con la versione 8.2 di ServiceFabric Runtime, è possibile eseguire l'override del punto di ingresso per il pacchetto di codice host exe e contenitore. Questa operazione può essere usata nei casi in cui tutti gli elementi manifesto rimangano invariati, ma è necessario modificare l'immagine del contenitore, quindi il provisioning di una versione diversa del tipo di app non è più necessario oppure è necessario passare argomenti diversi in base allo scenario di test o di produzione e il punto di ingresso rimane invariato.

Di seguito è riportato un esempio su come eseguire l'override del punto di ingresso del contenitore:

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>

Dopo aver specificato le sostituzioni nel manifesto dell'applicazione, verrà avviato il contenitore con nome immagine myregistry.azurecr.io/samples/helloworldapp, comandi di comandoOverride, sourceOverride di origine e entryPoint EntryPointOverride.

Analogamente, di seguito è riportato un esempio su come eseguire l'override di ExeHost:

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

Nota

L'override del punto di ingresso non è supportato per SetupEntryPoint.

Passaggi successivi