Membuat aplikasi kontainer Service Fabric pertama Anda di Linux

Menjalankan aplikasi yang ada di kontainer Windows pada klaster Service Fabric tidak memerlukan perubahan apa pun pada aplikasi Anda. Artikel ini memandu Anda membuat gambar Docker yang berisi aplikasi web Python Flask dan menyebarkannya ke klaster Azure Service Fabric. Anda juga akan membagikan aplikasi kontainer Anda melalui Azure Container Registry. Artikel ini mengasumsikan pemahaman dasar tentang Docker. Anda dapat mempelajari tentang Docker dengan membaca Gambaran umum Docker.

Catatan

Artikel ini berlaku untuk lingkungan pengembangan Linux. Runtime klaster Service Fabric dan runtime Docker harus berjalan pada OS yang sama. Anda tidak dapat menjalankan kontainer Linux pada klaster Windows.

Prasyarat

Tentukan kontainer Docker

Bangun gambar berdasarkan gambar Python yang terletak di Docker Hub.

Tentukan kontainer Docker Anda di Dockerfile. Dockerfile terdiri dari instruksi untuk mengatur lingkungan di dalam kontainer Anda, memuat aplikasi yang ingin Anda jalankan, dan memetakan port. Dockerfile adalah input ke perintah docker build, yang membuat gambar.

Buat direktori kosong dan buat file Dockerfile (tanpa ekstensi file). Tambahkan hal berikut ini ke Dockerfile dan simpan perubahan Anda:

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

Baca referensi Dockerfile untuk informasi selengkapnya.

Membuat aplikasi web dasar

Buat aplikasi web Flask mendengarkan di port 80 yang mengembalikan "Halo Dunia!". Dalam direktori yang sama, buat file requirements.txt. Tambahkan yang berikut ini dan simpan perubahan Anda:

Flask

Buat juga file app.py dan tambahkan cuplikan berikut:

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)

Masuk ke Docker dan membangun gambar

Selanjutnya kita akan membuat gambar yang menjalankan aplikasi web Anda. Saat menarik gambar publik dari Docker (seperti python:2.7-slim di Dockerfile kami), ini adalah praktik terbaik untuk mengautentikasi dengan akun Docker Hub Anda daripada membuat permintaan pull anonim.

Catatan

Saat sering membuat permintaan pull anonim, Anda mungkin melihat kesalahan Docker mirip dengan ERROR: toomanyrequests: Too Many Requests. atau You have reached your pull rate limit. Autentikasi ke Docker Hub untuk mencegah kesalahan ini. Lihat Mengelola konten publik dengan Azure Container Registry untuk informasi selengkapnya.

Buka jendela PowerShell dan navigasikan ke direktori yang berisi Dockerfile. Kemudian jalankan perintah berikut:

docker login
docker build -t helloworldapp .

Perintah ini membangun gambar baru menggunakan instruksi di Dockerfile Anda, penamaan (-t tagging) gambar helloworldapp. Untuk membangun gambar kontainer, gambar dasar pertama kali diunduh dari Docker Hub tempat aplikasi ditambahkan.

Setelah perintah bangun selesai, jalankan perintah docker images untuk melihat informasi pada gambar baru:

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

Menjalankan aplikasi secara lokal

Verifikasi bahwa aplikasi kontainer Anda berjalan secara lokal sebelum mendorongnya ke registri kontainer.

Jalankan aplikasi, memetakan port 4000 komputer Anda ke port kontainer yang terekspos 80:

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

nama memberikan nama pada kontainer yang sedang berjalan (bukan ID kontainer).

Sambungkan ke kontainer yang sedang berjalan. Buka browser web yang menunjuk ke alamat IP yang dikembalikan pada port 4000, misalnya "http://localhost:4000". Anda akan melihat tampilan judul "Halo Dunia!" di browser.

Hello World!

Untuk menghentikan kontainer Anda, jalankan:

docker stop my-web-site

Hapus kontainer dari komputer pengembangan Anda:

docker rm my-web-site

Mendorong gambar ke registri kontainer

Setelah Anda memverifikasi bahwa aplikasi berjalan di Docker, dorong gambar ke registri Anda di Azure Container Registry.

Jalankan docker login untuk masuk ke registri kontainer Anda dengan kredensial registri Anda.

Contoh berikut meneruskan ID dan kata sandi perwakilan layanan Microsoft Entra. Misalnya, Anda mungkin telah menetapkan prinsipal layanan ke registri Anda untuk skenario otomatisasi. Atau, Anda dapat masuk menggunakan nama pengguna dan kata sandi registri Anda.

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

Perintah berikut membuat tag, atau alias, gambar, dengan jalur yang sepenuhnya memenuhi syarat ke registri Anda. Contoh ini menempatkan gambar di namespace samples untuk menghindari clutter di akar registri.

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

Dorong gambar ke registri kontainer Anda:

docker push myregistry.azurecr.io/samples/helloworldapp

Membungkus gambar Docker dengan Yeoman

Service Fabric SDK untuk Linux menyertakan generator Yeoman yang memudahkan Anda membuat aplikasi dan menambahkan gambar kontainer. Mari kita gunakan Yeoman untuk membuat aplikasi dengan satu kontainer Docker yang disebut SimpleContainerApp.

Untuk membuat aplikasi kontainer Service Fabric, buka jendela terminal dan jalankan yo azuresfcontainer.

Beri nama aplikasi Anda (misalnya, mycontainer) dan beri nama layanan aplikasi (misalnya, myservice).

Untuk nama gambar, berikan URL untuk gambar kontainer dalam registri kontainer (misalnya, "myregistry.azurecr.io/samples/helloworldapp").

Karena citra ini memiliki titik entri beban kerja yang ditentukan, Anda tidak perlu secara eksplisit menentukan perintah input (perintah berjalan di dalam kontainer yang akan menjaga kontainer berjalan setelah startup).

Tentukan jumlah instans "1".

Tentukan pemetaan port dalam format yang sesuai. Untuk artikel ini, Anda perlu menyediakan 80:4000 sebagai pemetaan port. Dengan melakukan ini, Anda telah mengonfigurasi bahwa setiap permintaan masuk yang datang ke port 4000 pada mesin host dialihkan ke port 80 pada kontainer.

Service Fabric Yeoman generator for containers

Mengonfigurasi autentikasi repositori kontainer

Lihat Container Repository Authenticationuntuk mempelajari cara mengonfigurasi berbagai jenis autentikasi untuk mengunduh gambar kontainer.

Mengonfigurasi mode isolasi

Dengan rilis runtime 6.3, isolasi VM didukung untuk kontainer Linux, sehingga mendukung dua mode isolasi untuk kontainer: proses dan Hyper-V. Dengan mode isolasi Hyper-V, kernel diisolasi antara setiap kontainer Hyper-V dan host kontainer. Isolasi Hyper-V diterapkan menggunakan Clear Containers. Mode isolasi ditentukan di ServicePackageContainerPolicy elemen dalam file manifes aplikasi. Mode isolasi yang dapat ditentukan adalah process, hyperv, dan default. Defaultnya adalah mode isolasi proses. Cuplikan berikut menampilkan bagaimana mode isolasi ditentukan dalam file manifes aplikasi.

<ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="MyServicePkg" ServiceManifestVersion="1.0.0"/>
      <Policies>
        <ServicePackageContainerPolicy Hostname="votefront" Isolation="hyperv">
          <PortBinding ContainerPort="80" EndpointRef="myServiceTypeEndpoint"/>
        </ServicePackageContainerPolicy>
    </Policies>
  </ServiceManifestImport>

Mengonfigurasi tata kelola sumber daya

Tata kelola sumber daya membatasi sumber daya yang dapat digunakan kontainer pada host. Elemen ResourceGovernancePolicy, yang ditentukan dalam manifes aplikasi, digunakan untuk mendeklarasikan batas sumber daya untuk paket kode layanan. Batas sumber daya dapat diatur untuk sumber daya berikut: Memori, MemorySwap, CpuShares (berat relatif CPU), MemoryReservationInMB, BlkioWeight (Berat relatif BlockIO). Dalam contoh ini, paket layanan Guest1Pkg mendapatkan satu inti pada node klaster di mana paket layanan ditempatkan. Batas memori bersifat mutlak, sehingga paket kode terbatas pada memori 1024 MB (dan reservasi jaminan sementara yang sama). Paket kode (kontainer atau proses) tidak dapat mengalokasikan lebih banyak memori daripada batas ini, dan mencoba melakukannya sehingga menghasilkan pengecualian di luar memori. Agar penegakan batas sumber daya berfungsi, semua paket kode dalam paket layanan harus memiliki batas memori yang ditentukan.

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

Mengonfigurasi docker HEALTHCHECK

Mulai v6.1, Service Fabric secara otomatis mengintegrasikan aktivitas docker HEALTHCHECK dalam laporan kesehatan sistemnya. Ini berarti bahwa jika kontainer Anda telah mengaktifkan HEALTHCHECK, Service Fabric akan melaporkan kesehatan setiap kali status kesehatan kontainer berubah seperti yang dilaporkan oleh Docker. Laporan kesehatan OK akan muncul di Service Fabric Explorer ketika health_statussehat dan PERINGATAN akan muncul ketika health_statustidak sehat.

Dimulai dengan rilis refresh terbaru v6.4, Anda memiliki opsi untuk menentukan bahwa evaluasi HEALTHCHECK docker harus dilaporkan sebagai kesalahan. Jika opsi ini diaktifkan, laporan kesehatan OK akan muncul ketika health_statussehat dan KESALAHAN akan muncul ketika health_statustidak sehat.

Instruksi HEALTHCHECK yang menunjuk ke pemeriksaan aktual yang dilakukan untuk memantau kesehatan kontainer harus ada di Dockerfile yang digunakan ketika menghasilkan gambar kontainer.

Screenshot shows details of the Deployed Service Package NodeServicePackage.

HealthCheckUnhealthyApp

HealthCheckUnhealthyDsp

Anda dapat mengonfigurasi perilaku HEALTHCHECK untuk setiap kontainer dengan menetapkan opsi HealthConfig sebagai bagian dari ContainerHostPolicies di ApplicationManifest.

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

Secara default IncludeDockerHealthStatusInSystemHealthReport diatur ke true, RestartContainerOnUnhealthyDockerHealthStatus diatur ke false, dan TreatContainerUnhealthyStatusAsError diatur ke false.

Jika RestartContainerOnUnhealthyDockerHealthStatus diatur ke true, kontainer yang berulang kali melaporkan tidak sehat direstart (mungkin pada node lainnya).

Jika TreatContainerUnhealthyStatusAsError diatur ke true, laporan kesehatan KESALAHAN akan muncul ketika health_status kontainer tidak sehat.

Jika Anda ingin menonaktifkan integrasi HEALTHCHECK untuk seluruh klaster Service Fabric, Anda perlu mengatur EnableDockerHealthCheckIntegration ke false.

Menyebarkan aplikasi

Setelah aplikasi dibangun, Anda dapat menyebarkannya ke klaster lokal menggunakan Service Fabric CLI.

Sambungkan ke klaster Service Fabric lokal.

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

Jalankan skrip instal yang disediakan di templat https://github.com/Azure-Samples/service-fabric-containers/ untuk menyalin paket aplikasi ke penyimpanan klaster gambar, daftarkan jenis aplikasi, dan buat instans aplikasi.

./install.sh

Buka browser dan navigasikan ke Service Fabric Explorer di http://localhost:19080/Explorer (ganti localhost dengan IP privat VM jika menggunakan Vagrant di Mac OS X). Kemudian, perluas node Aplikasi dan perhatikan bahwa sekarang ada entri untuk jenis aplikasi Anda dan entri lain untuk instans pertama dari jenis itu.

Sambungkan ke kontainer yang sedang berjalan. Buka browser web yang menunjuk ke alamat IP yang dikembalikan pada port 4000, misalnya "http://localhost:4000". Anda akan melihat tampilan judul "Halo Dunia!" di browser.

Hello World!

Penghapusan

Gunakan skrip hapus instalan yang disediakan dalam templat untuk menghapus instans aplikasi dari klaster dan membatalkan registrasi jenis aplikasi.

./uninstall.sh

Setelah Anda memasukkan gambar ke registri kontainer, Anda dapat menghapus gambar lokal dari komputer pengembangan Anda:

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

Contoh lengkap manifes aplikasi dan layanan Service Fabric

Berikut adalah manifes layanan dan aplikasi yang lengkap yang digunakan dalam artikel ini.

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>

Menambahkan lebih banyak layanan ke aplikasi yang sudah ada

Untuk menambahkan layanan kontainer lain ke aplikasi yang sudah dibuat menggunakan Yeoman, lakukan langkah-langkah berikut:

  1. Ubah direktori ke akar aplikasi yang ada. Contohnya, cd ~/YeomanSamples/MyApplication, jika MyApplication adalah aplikasi yang dibuat oleh Yeoman.
  2. Jalankan yo azuresfcontainer:AddService

Mengonfigurasi interval waktu sebelum kontainer dihentikan paksa

Anda dapat mengonfigurasi interval waktu untuk runtime agar menunggu sebelum kontainer dihapus setelah penghapusan layanan (atau pindah ke node lainnya) telah dimulai. Mengonfigurasi interval waktu mengirimkan perintah docker stop <time in seconds> ke kontainer. Untuk lebih jelasnya, lihat pemberhentian docker. Interval waktu untuk menunggu ditentukan di bawah bagian Hosting. Cuplikan manifes klaster berikut menampilkan cara mengatur interval tunggu:

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

Interval waktu default diatur ke 10 detik. Karena konfigurasi ini dinamis, konfigurasi hanya meningkatkan klaster yang memperbarui waktu habis.

Mengonfigurasi runtime untuk menghapus gambar kontainer yang tidak digunakan

Anda dapat mengonfigurasi klaster Service Fabric untuk menghapus gambar kontainer yang tidak digunakan dari node. Konfigurasi ini memungkinkan ruang disk diambil kembali jika terlalu banyak citra kontainer ada pada node. Untuk mengaktifkan fitur ini, perbarui bagian Hosting dalam manifes klaster seperti yang ditunjukkan dalam cuplikan berikut:

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

Untuk citra yang tidak boleh dihapus, Anda dapat menentukannya di bawah parameter ContainerImagesToSkip.

Mengonfigurasi waktu pengunduhan gambar kontainer

Runtime Service Fabric mengalokasikan 20 menit untuk mengunduh dan mengekstrak gambar kontainer, yang berfungsi untuk sebagian besar gambar kontainer. Untuk citra yang besar atau ketika koneksi jaringan lambat, mungkin perlu untuk menambah waktu untuk menunggu sebelum membatalkan pengunduhan dan ekstraksi citra. Waktu habis ini diatur menggunakan atribut ContainerImageDownloadTimeout di bagian Hosting dari manifes klaster seperti yang ditunjukkan dalam cuplikan berikut:

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

Mengatur kebijakan penyimpanan kontainer

Untuk membantu mendiagnosis kegagalan startup kontainer, Service Fabric (versi 6.1 atau lebih tinggi) mendukung mempertahankan kontainer yang dihentikan atau gagal dimulai. Kebijakan ini dapat diatur dalam file ApplicationManifest.xml seperti yang ditunjukkan dalam cuplikan berikut:

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

Pengaturan ContainersRetentionCount menentukan jumlah kontainer yang akan dipertahankan ketika gagal. Jika nilai negatif ditentukan, semua kontainer yang gagal akan dipertahankan. Jika atribut ContainersRetentionCount tidak ditentukan, tidak ada kontainer yang akan dipertahankan. Atribut ContainersRetentionCount juga mendukung Parameter Aplikasi sehingga pengguna dapat menentukan nilai yang berbeda untuk kluster pengujian dan produksi. Gunakan batasan penempatan untuk menargetkan layanan kontainer ke node tertentu saat menggunakan fitur ini untuk mencegah layanan kontainer berpindah ke node lain. Setiap kontainer yang dipertahankan menggunakan fitur ini harus dihapus secara manual.

Mulai daemon Docker dengan argumen khusus

Dengan versi 6.2 dari runtime Service Fabric dan yang lebih besar, Anda dapat memulai daemon Docker dengan argumen khusus. Ketika argumen khusus ditentukan, Service Fabric tidak meneruskan argumen lain apa pun ke mesin docker kecuali argumen --pidfile. Oleh karena itu, --pidfile tidak boleh diteruskan sebagai argumen. Selain itu, argumen harus terus membuat daemon docker mendengarkan pipa nama default pada Windows (atau soket domain unix di Linux) agar Service Fabric berkomunikasi dengan daemon. Argumen kustom ditentukan dalam manifes klaster di bawah bagian Hosting di bawah ContainerServiceArguments. Contoh diperlihatkan dalam cuplikan berikut:

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

Langkah berikutnya