[JAVA] Exécutons un lot dans un conteneur à l'aide d'Azure Batch

introduction

J'ai utilisé AWS Batch, qui peut confiner la logique dans un conteneur et l'exécuter sur n'importe quelle instance, de manière pratique, mais comme le projet actuel était Azure, j'ai essayé d'utiliser Azure Batch. Le concept est le même qu'AWS. Comme d'habitude, il n'y a pas beaucoup d'articles dans les documents et Qiita, donc j'espère que vous le trouverez utile.

À propos, cette fois, il est implémenté avec Java SDK, mais si vous définissez un lot à partir de l'écran ou utilisez le SDK d'une autre langue, vous pouvez le déplacer en définissant la même valeur de paramètre, donc je pense que ce sera utile.

Azure Batch

Azure Batch est un service qui vous permet d'exécuter n'importe quel programme (y compris Shell) sur une instance d'une taille spécifiée. Il est possible d'exécuter des programmes dans des conteneurs comme AWS Batch. À propos, AWS (*) a utilisé CloudWatch Events pour planifier, mais Azure Batch a une fonction de planification intégrée.

Préparation

Le programme qui s'exécute dans le conteneur ressemble à ceci. Mettons des informations telles que le système d'exploitation pour vérifier s'il s'exécute correctement sur l'instance spécifiée.

À propos, https://github.com/oshi/oshi est pratique pour obtenir des informations sur le système d'exploitation en Java.

public class BatchMain {

    public static void main(String[] args) {

        System.out.println("execute main method.");

        System.out.println("Environment Variables");
        System.getenv().forEach((k,v) -> System.out.println(k + ":" + v));

        var si = new SystemInfo();
        System.out.println("OS: " + si.getOperatingSystem());

        var hardware = si.getHardware();
        System.out.println("Processor: " + hardware.getProcessor());

        var memory = hardware.getMemory();
        System.out.println("Memory: " + memory.getAvailable() + " / " + memory.getTotal());

        System.exit(0);
    }
}

Nous allons maintenant pousser cela vers Azure Container Registry. Poussez avec la flèche comme d'habitude. N'oubliez pas d'écrire USERNAME et PASSWORD dans gradle.properties.

jib {
    to {
        image = 'xxxxx.azurecr.io/batch:0.0.1-SNAPSHOT'
        auth {
            username = "${USERNAME}"
            password = "${PASSWORD}"
        }
    }
}
gradlew jib

Créer un compte Azure Batch

Sélectionnez les comptes de lots.

image.png

Créez un compte de lot.

image.png

Faites une copie du compte de lot, de l'URL et de la clé d'accès principale. Ceci est utilisé lors de sa spécification par programme.

image.png

Faire une piscine

Dans Azure Batch, l'environnement d'exécution est défini dans Pool. Il n'est pas nécessaire de créer un paramètre de pool pour chaque travail, et si l'environnement ne change pas, c'est bien. Dans AWS, il s'agit d'un environnement informatique.

Les images de machine virtuelle prises en charge (Linux) sont répertoriées ici [https://docs.microsoft.com/en-us/azure/batch/batch-docker-container-workloads) mais uniquement pour centos ou ubuntu Devenir. Bien sûr, vous pouvez préparer le vôtre.

Il serait plus facile de trouver la valeur que vous spécifiez à partir de la console d'administration Azure

image.png


public class Pool {

    public static final String POOL_ID = "pool_1";

    public static void main(String[] args) throws IOException {
        BatchClient client = BatchClient.open(new BatchSharedKeyCredentials(
                "https://xxxxx.japaneast.batch.azure.com",
                "xxxx",
                "xxxxxx"));

        ContainerRegistry containerRegistry = new ContainerRegistry()
                .withRegistryServer("xxxxxx.azurecr.io")
                .withUserName("xxxxxx")
                .withPassword("xxxxxxxxx");

        ContainerConfiguration containerConfiguration = new ContainerConfiguration();
        containerConfiguration.withContainerRegistries(Arrays.asList(containerRegistry));
        containerConfiguration.withContainerImageNames(Arrays.asList("xxxx.azurecr.io/batch:0.0.1-SNAPSHOT"));

        ImageReference imageReference = new ImageReference();
        imageReference.withPublisher("microsoft-azure-batch");
        imageReference.withOffer("ubuntu-server-container");
        imageReference.withSku("16-04-lts");
        imageReference.withVersion("latest");

        // VM Configuration
        VirtualMachineConfiguration virtualMachineConfiguration = new VirtualMachineConfiguration();
        virtualMachineConfiguration.withImageReference(imageReference);
        virtualMachineConfiguration.withContainerConfiguration(containerConfiguration);
        virtualMachineConfiguration.withNodeAgentSKUId("batch.node.ubuntu 16.04");

        // Create Pool
        client.poolOperations().createPool(POOL_ID, "standard_d1_v2", virtualMachineConfiguration, 1);
    }

}

Bougez simplement

Déplaçons JOB et Task en fonction des informations définies dans Pool. Commencez par créer un JOB.


public class SimpleJob {

    public static final String POOL_ID = "pool_1";

    public static final String JOB_ID = "job_1";

    public static void main(String[] args) throws IOException {
        BatchClient client = BatchClient.open(new BatchSharedKeyCredentials(
                "https://xxxxx.japaneast.batch.azure.com",
                "xxxx",
                "xxxxxx"));

        PoolInformation poolInformation = new PoolInformation();
        poolInformation.withPoolId(POOL_ID);

        // CreateJob
        client.jobOperations().createJob(JOB_ID, poolInformation);
    }
}

Exécutez la tâche dans le JOB.

public class SimpleTask {

    public static void main(String[] args) throws IOException, InterruptedException {

        BatchClient client = BatchClient.open(new BatchSharedKeyCredentials(
                "https://xxxxx.japaneast.batch.azure.com",
                "xxxx",
                "xxxxxx"));

        TaskAddParameter parameter = new TaskAddParameter();
        parameter.withId("task1")
                .withUserIdentity(new UserIdentity().withAutoUser(new AutoUserSpecification().withElevationLevel(ElevationLevel.ADMIN).withScope(AutoUserScope.TASK)))
                .withContainerSettings(new TaskContainerSettings().withImageName("xxxx.azurecr.io/batch:0.0.1-SNAPSHOT")
                        .withContainerRunOptions("--rm"))
                .withConstraints(new TaskConstraints().withMaxTaskRetryCount(-1)).withCommandLine("");
        client.taskOperations().createTask(ScheduleJob.JOB_ID, parameter);

        long timeout = 300 * 1000;
        long startTime = System.currentTimeMillis();

        while (System.currentTimeMillis() - startTime <= timeout) {
            CloudTask task = client.taskOperations().getTask(ScheduleJob.JOB_ID, parameter.id());

            if (task.state() != TaskState.COMPLETED) {
                Thread.sleep(1000);
            }
        }
    }
}

Si vous faites cela, vous pouvez le voir sur l'écran d'administration Azure.

image.png

Lorsque vous cliquez sur le JOB déplacé, l'écran Tâche s'affiche et vous pouvez voir le contenu de sortie à partir de l'écran.

Exécuter JOB à l'heure spécifiée

Spécifiez l'heure du JOB avec withDoNotRunUntil. Il définit également les tâches qui se déplacent lorsque le JOB est exécuté.


public class ScheduleJob {

    public static final String POOL_ID = "pool_1";

    public static final String JOB_ID = "job_5";

    public static void main(String[] args) throws IOException {
        BatchClient client = BatchClient.open(new BatchSharedKeyCredentials(
                "https://xxxxx.japaneast.batch.azure.com",
                "xxxx",
                "xxxxxx"));

        // Create Schedule SimpleJob
        DateTime scheduleDateTime = new DateTime(2019,8,22,4,30, DateTimeZone.UTC);
        Schedule schedule = new Schedule().withDoNotRunUntil(scheduleDateTime);

        // pool
        PoolInformation poolInformation = new PoolInformation();
        poolInformation.withPoolId(POOL_ID);

        // container
        JobManagerTask task = new JobManagerTask();
        task.withId("scheduletask")
                .withUserIdentity(new UserIdentity().withAutoUser(new AutoUserSpecification().withElevationLevel(ElevationLevel.ADMIN).withScope(AutoUserScope.TASK)))
                .withContainerSettings(new TaskContainerSettings().withImageName("xxxxx.azurecr.io/batch:0.0.1-SNAPSHOT")
                        .withContainerRunOptions("--rm"))
                .withCommandLine("");

        JobSpecification jobSpecification = new JobSpecification().withPoolInfo(poolInformation).withJobManagerTask(task);

        client.jobScheduleOperations().createJobSchedule(JOB_ID,schedule, jobSpecification);
    }
}

Déplacer à plusieurs reprises à partir de l'heure spécifiée (Cron)

Spécifiez l'heure de déplacement pour la première fois avec DoNotRunUntil et spécifiez l'heure de déplacement répété avec RecurrenceInterval. Si vous ne spécifiez pas DoNotRunUntil, le JOB sera exécuté à plusieurs reprises à partir de l'heure définie.

public class CronScheduleJob {

    public static final String POOL_ID = "pool_1";

    public static final String JOB_ID = "job_7";

    public static void main(String[] args) throws IOException {
        BatchClient client = BatchClient.open(new BatchSharedKeyCredentials(
                "https://xxxxx.japaneast.batch.azure.com",
                "xxxx",
                "xxxxxx"));

        // Create Schedule SimpleJob
        DateTime startDateTime = new DateTime(2019,8,22,4,45, DateTimeZone.UTC);
        Period period = new Period(0,1,0,0);
        Schedule schedule = new Schedule().withRecurrenceInterval(period).withDoNotRunUntil(startDateTime);

        // pool
        PoolInformation poolInformation = new PoolInformation();
        poolInformation.withPoolId(POOL_ID);

        // container
        JobManagerTask task = new JobManagerTask();
        task.withId("cronscheduletask")
                .withUserIdentity(new UserIdentity().withAutoUser(new AutoUserSpecification().withElevationLevel(ElevationLevel.ADMIN).withScope(AutoUserScope.TASK)))
                .withContainerSettings(new TaskContainerSettings().withImageName("xxxxx.azurecr.io/batch:0.0.1-SNAPSHOT")
                        .withContainerRunOptions("--rm"))
                .withCommandLine("");

        JobSpecification jobSpecification = new JobSpecification().withPoolInfo(poolInformation).withJobManagerTask(task);

        client.jobScheduleOperations().createJobSchedule(JOB_ID,schedule, jobSpecification);
    }
}

référence

Recommended Posts

Exécutons un lot dans un conteneur à l'aide d'Azure Batch
Exécuter des applications Java dans Azure Batch
Implémentation par lots dans l'environnement RubyOnRails à l'aide de Digdag
[Rails] Exécutez LINE Bot dans un environnement local à l'aide de ngrok
Si vous souhaitez simplement exécuter vos conteneurs dans le cloud, Azure Container Instances est facile