Swarm Healthcheck переводит задачу в состояние завершения

Создали рой и запустили на нем простое приложение nodejs. Я хотел бы проверить, как проверка работоспособности работает в среде роя. Я установил блок проверки работоспособности в файле компоновки следующим образом:

 healthcheck:
        test:  ["CMD", "curl", "-f", "http://localhost:3000/healthcheck"]
        interval: 1m
        timeout: 10s
        retries: 1
        start_period: 20s

Источник nodejs прост:

const express = require("express");
const os = require("os");

var fs = require('fs');
const app=express();
let health = "ok";

app.get("/", (req, res) => {
    var hostname = fs.readFileSync('/host/etc/hostname', 'utf8');

    var body =    " Hello from SwarmDemo (V1.0)" + "<br>";
    body = body + " container name: " + os.hostname()+ "<br>";
    body = body + " host name: " + hostname;

    res.send(body);
});

app.get("/healthcheck", (req, res) => {
    if (health == "ok") {
        res.send("OK")
    } else {
        res.status(503);
        res.send("");
    }
});

app.get("/kill", (req, res) => {
    var hostname = fs.readFileSync('/host/etc/hostname', 'utf8');

    health = "killed";
    res.send("Host " + hostname + " was killed!")
});

app.listen(3000, () => {
    console.log("Server is running on port 3000");
});

Я ожидал, что рой остановит неработоспособный контейнер и запустит новый, но этого не произошло. Он останавливает контейнер, но только устанавливает состояние задачи для завершения и покидает ее, не запуская новую.

Если я проверяю остановленный контейнер, он говорит, что код выхода равен 0, что означает, насколько я знаю, он был остановлен успешно, но не из-за сбоя. Я вижу вызов Healthchek, который также вернул код ответа 503 HTTP:

        "State": {
            "Status": "exited",
            "Running": false,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 0,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2019-08-16T17:33:55.778937745Z",
            "FinishedAt": "2019-08-16T17:35:59.664281868Z",
            "Health": {
                "Status": "unhealthy",
                "FailingStreak": 1,
                "Log": [
                    {
                        "Start": "2019-08-16T19:34:55.779656075+02:00",
                        "End": "2019-08-16T19:34:56.648373763+02:00",
                        "ExitCode": 0,
                        "Output": "  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current\n                                 Dload  Upload   Total   Spent    Left  Speed\n\r  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0\r100     2  100     2    0     0     22      0 --:--:-- --:--:-- --:--:--    22\nOK"
                    },
                    {
                        "Start": "2019-08-16T19:35:56.658734507+02:00",
                        "End": "2019-08-16T19:35:57.549464299+02:00",
                        "ExitCode": 22,
                        "Output": "  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current\n                                 Dload  Upload   Total   Spent    Left  Speed\n\r  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0\r  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0\ncurl: (22) The requested URL returned error: 503 Service Unavailable\n"
                    }
                ]
            }
        },

Если я изменю политику перезапуска с при отказе на любую:

            restart_policy:
                condition: any
                delay: 5s
                max_attempts: 3
                window: 30s

оно работает. Он останавливает контейнер и запускает новый.

Мой вопрос: как я могу заставить рой запустить новый контейнер, когда проверка работоспособности не удалась. Должен ли я отправить что-то еще, кроме кода ответа HTTP 5xx?

Я видел статьи, в которых вызов HTTP был завернут в скрипт. Если HTTP-вызов возвращал что-либо кроме 200, он возвращал 1, в противном случае — 0.

Будет ли это единственным решением?


person user2833793    schedule 17.08.2019    source источник


Ответы (1)


Кажется, что если докер без проблем остановит контейнер, статус будет завершен. Это означает, что в данном случае ему все равно на состояние здоровья.

Если я остановлю процесс узла в методе kill:

app.get("/kill", (req, res) => {
 process.exit(1);
});

или в проверке здоровья:

app.get("/healthcheck", (req, res) => {
    if (health == "ok") {
        res.send("OK")
    } else {
        process.exit(1);
    }
});

оно работает. Статус будет неудачным.

person user2833793    schedule 21.08.2019