Search in sources :

Example 1 with KafkaUpgradeException

use of io.strimzi.operator.cluster.KafkaUpgradeException in project strimzi by strimzi.

the class VersionChangeCreator method detectToAndFromVersions.

/**
 * Detects the current and desired Kafka versions based on the information collected from Kubernetes
 *
 * @return  Future which completes when the "to" and "from" versions are collected
 */
private Future<Void> detectToAndFromVersions(List<Pod> pods) {
    String lowestKafkaVersion = versionFromControllerResource;
    String highestKafkaVersion = versionFromControllerResource;
    for (Pod pod : pods) {
        // Collect the different annotations from the pods
        String currentVersion = Annotations.stringAnnotation(pod, ANNO_STRIMZI_IO_KAFKA_VERSION, null);
        String currentMessageFormat = Annotations.stringAnnotation(pod, KafkaCluster.ANNO_STRIMZI_IO_LOG_MESSAGE_FORMAT_VERSION, null);
        String currentIbp = Annotations.stringAnnotation(pod, KafkaCluster.ANNO_STRIMZI_IO_INTER_BROKER_PROTOCOL_VERSION, null);
        // downgrades which failed in the middle and continue with them.
        if (currentVersion != null) {
            if (highestKafkaVersion == null) {
                highestKafkaVersion = currentVersion;
            } else if (compareDottedVersions(highestKafkaVersion, currentVersion) < 0) {
                highestKafkaVersion = currentVersion;
            }
            if (lowestKafkaVersion == null) {
                lowestKafkaVersion = currentVersion;
            } else if (compareDottedVersions(lowestKafkaVersion, currentVersion) > 0) {
                lowestKafkaVersion = currentVersion;
            }
        }
        // upgrades or downgrades.
        if (currentMessageFormat != null) {
            if (highestLogMessageFormatVersionFromPods == null) {
                highestLogMessageFormatVersionFromPods = currentMessageFormat;
            } else if (compareDottedIVVersions(highestLogMessageFormatVersionFromPods, currentMessageFormat) < 0) {
                highestLogMessageFormatVersionFromPods = currentMessageFormat;
            }
        }
        // upgrades or downgrades.
        if (currentIbp != null) {
            if (highestInterBrokerProtocolVersionFromPods == null) {
                highestInterBrokerProtocolVersionFromPods = currentIbp;
            } else if (compareDottedIVVersions(highestInterBrokerProtocolVersionFromPods, currentIbp) < 0) {
                highestInterBrokerProtocolVersionFromPods = currentIbp;
            }
        }
    }
    // describing the situation.
    if (lowestKafkaVersion == null) {
        if (freshDeployment && pods.isEmpty()) {
            // No version found in Pods or StatefulSet because they do not exist => This means we
            // are dealing with a brand new Kafka cluster or a Kafka cluster with deleted
            // StatefulSet and Pods. New cluster does not need an upgrade. Cluster without
            // StatefulSet / Pods cannot be rolled. So we can just deploy a new one with the desired
            // version. So we can use the desired version and set the version change to noop.
            versionFrom = versionFromCr;
            versionTo = versionFromCr;
        } else {
            // Either Pods or StatefulSet already exist. However, none of them contains the version
            // annotation. This suggests they are not created by the current versions of Strimzi.
            // Without the annotation, we cannot detect the Kafka version and decide on upgrade.
            LOGGER.warnCr(reconciliation, "Kafka Pods or StatefulSet exist, but do not contain the {} annotation to detect their version. Kafka upgrade cannot be detected.", ANNO_STRIMZI_IO_KAFKA_VERSION);
            throw new KafkaUpgradeException("Kafka Pods or StatefulSet exist, but do not contain the " + ANNO_STRIMZI_IO_KAFKA_VERSION + " annotation to detect their version. Kafka upgrade cannot be detected.");
        }
    } else if (lowestKafkaVersion.equals(highestKafkaVersion)) {
        // All brokers have the same version. We can use it as the current version.
        versionFrom = versions.version(lowestKafkaVersion);
        versionTo = versionFromCr;
    } else if (compareDottedVersions(highestKafkaVersion, versionFromCr.version()) > 0) {
        // Highest Kafka version used by the brokers is higher than desired => suspected downgrade
        versionFrom = versions.version(highestKafkaVersion);
        versionTo = versionFromCr;
    } else {
        // Highest Kafka version used by the brokers is equal or lower than desired => suspected upgrade
        versionFrom = versions.version(lowestKafkaVersion);
        versionTo = versionFromCr;
    }
    return Future.succeededFuture();
}
Also used : Pod(io.fabric8.kubernetes.api.model.Pod) KafkaUpgradeException(io.strimzi.operator.cluster.KafkaUpgradeException)

Example 2 with KafkaUpgradeException

use of io.strimzi.operator.cluster.KafkaUpgradeException in project strimzi-kafka-operator by strimzi.

the class VersionChangeCreator method prepareVersionChange.

/**
 * Plans the version change and creates a KafkaVersionChange object which contains the main versions as well as the
 * inter.broker.protocol.version and log.message.format.version.
 *
 * @return  Future with the KafkaVersionChange instance describing the Kafka version changes
 */
@SuppressWarnings("checkstyle:CyclomaticComplexity")
private Future<KafkaVersionChange> prepareVersionChange() {
    if (versionFrom.compareTo(versionTo) == 0) {
        // => no version change
        LOGGER.debugCr(reconciliation, "{}: No Kafka version change", reconciliation);
        if (interBrokerProtocolVersionFromCr == null) {
            // When inter.broker.protocol.version is not set, we set it to current Kafka version
            interBrokerProtocolVersion = versionFromCr.protocolVersion();
            if (highestInterBrokerProtocolVersionFromPods != null && !versionFromCr.protocolVersion().equals(highestInterBrokerProtocolVersionFromPods)) {
                LOGGER.infoCr(reconciliation, "Upgrading Kafka inter.broker.protocol.version from {} to {}", highestInterBrokerProtocolVersionFromPods, versionFromCr.protocolVersion());
                if (compareDottedIVVersions(versionFromCr.protocolVersion(), "3.0") >= 0) {
                    // From Kafka 3.0.0, the log.message.format.version is ignored when inter.broker.protocol.version is set to 3.0 or higher
                    // We set the log.message.format.version immediately to the same version as inter.broker.protocol.version to avoid unnecessary rolling update
                    logMessageFormatVersion = versionFromCr.messageVersion();
                } else if (logMessageFormatVersionFromCr == null && highestLogMessageFormatVersionFromPods != null) {
                    // For Kafka versions older than 3.0.0, inter.broker.protocol.version and log.message.format.version should not change in the same rolling
                    // update. When this rolling update is going to change the inter.broker.protocol.version, we keep the old log.message.format.version
                    logMessageFormatVersion = highestLogMessageFormatVersionFromPods;
                }
            }
        }
        if (logMessageFormatVersionFromCr == null) {
            // When log.message.format.version is not set, we set it to current Kafka version
            logMessageFormatVersion = versionFromCr.messageVersion();
            if (highestLogMessageFormatVersionFromPods != null && !versionFromCr.messageVersion().equals(highestLogMessageFormatVersionFromPods)) {
                LOGGER.infoCr(reconciliation, "Upgrading Kafka log.message.format.version from {} to {}", highestLogMessageFormatVersionFromPods, versionFromCr.messageVersion());
            }
        }
    } else {
        if (versionFrom.compareTo(versionTo) < 0) {
            // => is upgrade
            LOGGER.infoCr(reconciliation, "Kafka is upgrading from {} to {}", versionFrom.version(), versionTo.version());
            // used by any of the brokers is not higher than the broker version we upgrade from.
            if ((highestLogMessageFormatVersionFromPods != null && compareDottedIVVersions(versionFrom.messageVersion(), highestLogMessageFormatVersionFromPods) < 0) || (highestInterBrokerProtocolVersionFromPods != null && compareDottedIVVersions(versionFrom.protocolVersion(), highestInterBrokerProtocolVersionFromPods) < 0)) {
                LOGGER.warnCr(reconciliation, "log.message.format.version ({}) and inter.broker.protocol.version ({}) used by the brokers have to be lower or equal to the Kafka broker version we upgrade from ({})", highestInterBrokerProtocolVersionFromPods, highestInterBrokerProtocolVersionFromPods, versionFrom.version());
                throw new KafkaUpgradeException("log.message.format.version (" + highestLogMessageFormatVersionFromPods + ") and inter.broker.protocol.version (" + highestInterBrokerProtocolVersionFromPods + ") used by the brokers have to be lower or equal to the Kafka broker version we upgrade from (" + versionFrom.version() + ")");
            }
            String desiredLogMessageFormat = logMessageFormatVersionFromCr;
            String desiredInterBrokerProtocol = interBrokerProtocolVersionFromCr;
            // upgrading from. If it is not set, we set it to the version we are upgrading from.
            if (desiredLogMessageFormat == null || compareDottedIVVersions(versionFrom.messageVersion(), desiredLogMessageFormat) < 0) {
                logMessageFormatVersion = versionFrom.messageVersion();
            }
            // are upgrading from. If it is not set, we set it to the version we are upgrading from.
            if (desiredInterBrokerProtocol == null || compareDottedIVVersions(versionFrom.protocolVersion(), desiredInterBrokerProtocol) < 0) {
                interBrokerProtocolVersion = versionFrom.protocolVersion();
            }
        } else {
            // Has to be a downgrade
            LOGGER.infoCr(reconciliation, "Kafka is downgrading from {} to {}", versionFrom.version(), versionTo.version());
            // reconciliation as well.
            if (highestLogMessageFormatVersionFromPods == null || compareDottedIVVersions(versionTo.messageVersion(), highestLogMessageFormatVersionFromPods) < 0 || highestInterBrokerProtocolVersionFromPods == null || compareDottedIVVersions(versionTo.protocolVersion(), highestInterBrokerProtocolVersionFromPods) < 0) {
                LOGGER.warnCr(reconciliation, "log.message.format.version ({}) and inter.broker.protocol.version ({}) used by the brokers have to be set and be lower or equal to the Kafka broker version we downgrade to ({})", highestLogMessageFormatVersionFromPods, highestInterBrokerProtocolVersionFromPods, versionTo.version());
                throw new KafkaUpgradeException("log.message.format.version (" + highestLogMessageFormatVersionFromPods + ") and inter.broker.protocol.version (" + highestInterBrokerProtocolVersionFromPods + ") used by the brokers have to be set and be lower or equal to the Kafka broker version we downgrade to (" + versionTo.version() + ")");
            }
            String desiredLogMessageFormat = logMessageFormatVersionFromCr;
            String desiredInterBrokerProtocol = interBrokerProtocolVersionFromCr;
            // If log.message.format.version is not set, we set it to the version we are downgrading to.
            if (desiredLogMessageFormat == null) {
                desiredLogMessageFormat = versionTo.messageVersion();
                logMessageFormatVersion = versionTo.messageVersion();
            }
            // If inter.broker.protocol.version is not set, we set it to the version we are downgrading to.
            if (desiredInterBrokerProtocol == null) {
                desiredInterBrokerProtocol = versionTo.protocolVersion();
                interBrokerProtocolVersion = versionTo.protocolVersion();
            }
            // validation. However, we still double-check it as safety.
            if (compareDottedIVVersions(versionTo.messageVersion(), desiredLogMessageFormat) < 0 || compareDottedIVVersions(versionTo.protocolVersion(), desiredInterBrokerProtocol) < 0) {
                LOGGER.warnCr(reconciliation, "log.message.format.version ({}) and inter.broker.protocol.version ({}) used in the Kafka CR have to be set and be lower or equal to the Kafka broker version we downgrade to ({})", highestLogMessageFormatVersionFromPods, highestInterBrokerProtocolVersionFromPods, versionTo.version());
                throw new KafkaUpgradeException("log.message.format.version and inter.broker.protocol.version used in the Kafka CR have to be set and be lower or equal to the Kafka broker version we downgrade to");
            }
        }
    }
    return Future.succeededFuture(new KafkaVersionChange(versionFrom, versionTo, interBrokerProtocolVersion, logMessageFormatVersion));
}
Also used : KafkaVersionChange(io.strimzi.operator.cluster.model.KafkaVersionChange) KafkaUpgradeException(io.strimzi.operator.cluster.KafkaUpgradeException)

Example 3 with KafkaUpgradeException

use of io.strimzi.operator.cluster.KafkaUpgradeException in project strimzi-kafka-operator by strimzi.

the class VersionChangeCreator method detectToAndFromVersions.

/**
 * Detects the current and desired Kafka versions based on the information collected from Kubernetes
 *
 * @return  Future which completes when the "to" and "from" versions are collected
 */
private Future<Void> detectToAndFromVersions(List<Pod> pods) {
    String lowestKafkaVersion = versionFromControllerResource;
    String highestKafkaVersion = versionFromControllerResource;
    for (Pod pod : pods) {
        // Collect the different annotations from the pods
        String currentVersion = Annotations.stringAnnotation(pod, ANNO_STRIMZI_IO_KAFKA_VERSION, null);
        String currentMessageFormat = Annotations.stringAnnotation(pod, KafkaCluster.ANNO_STRIMZI_IO_LOG_MESSAGE_FORMAT_VERSION, null);
        String currentIbp = Annotations.stringAnnotation(pod, KafkaCluster.ANNO_STRIMZI_IO_INTER_BROKER_PROTOCOL_VERSION, null);
        // downgrades which failed in the middle and continue with them.
        if (currentVersion != null) {
            if (highestKafkaVersion == null) {
                highestKafkaVersion = currentVersion;
            } else if (compareDottedVersions(highestKafkaVersion, currentVersion) < 0) {
                highestKafkaVersion = currentVersion;
            }
            if (lowestKafkaVersion == null) {
                lowestKafkaVersion = currentVersion;
            } else if (compareDottedVersions(lowestKafkaVersion, currentVersion) > 0) {
                lowestKafkaVersion = currentVersion;
            }
        }
        // upgrades or downgrades.
        if (currentMessageFormat != null) {
            if (highestLogMessageFormatVersionFromPods == null) {
                highestLogMessageFormatVersionFromPods = currentMessageFormat;
            } else if (compareDottedIVVersions(highestLogMessageFormatVersionFromPods, currentMessageFormat) < 0) {
                highestLogMessageFormatVersionFromPods = currentMessageFormat;
            }
        }
        // upgrades or downgrades.
        if (currentIbp != null) {
            if (highestInterBrokerProtocolVersionFromPods == null) {
                highestInterBrokerProtocolVersionFromPods = currentIbp;
            } else if (compareDottedIVVersions(highestInterBrokerProtocolVersionFromPods, currentIbp) < 0) {
                highestInterBrokerProtocolVersionFromPods = currentIbp;
            }
        }
    }
    // describing the situation.
    if (lowestKafkaVersion == null) {
        if (freshDeployment && pods.isEmpty()) {
            // No version found in Pods or StatefulSet because they do not exist => This means we
            // are dealing with a brand new Kafka cluster or a Kafka cluster with deleted
            // StatefulSet and Pods. New cluster does not need an upgrade. Cluster without
            // StatefulSet / Pods cannot be rolled. So we can just deploy a new one with the desired
            // version. So we can use the desired version and set the version change to noop.
            versionFrom = versionFromCr;
            versionTo = versionFromCr;
        } else {
            // Either Pods or StatefulSet already exist. However, none of them contains the version
            // annotation. This suggests they are not created by the current versions of Strimzi.
            // Without the annotation, we cannot detect the Kafka version and decide on upgrade.
            LOGGER.warnCr(reconciliation, "Kafka Pods or StatefulSet exist, but do not contain the {} annotation to detect their version. Kafka upgrade cannot be detected.", ANNO_STRIMZI_IO_KAFKA_VERSION);
            throw new KafkaUpgradeException("Kafka Pods or StatefulSet exist, but do not contain the " + ANNO_STRIMZI_IO_KAFKA_VERSION + " annotation to detect their version. Kafka upgrade cannot be detected.");
        }
    } else if (lowestKafkaVersion.equals(highestKafkaVersion)) {
        // All brokers have the same version. We can use it as the current version.
        versionFrom = versions.version(lowestKafkaVersion);
        versionTo = versionFromCr;
    } else if (compareDottedVersions(highestKafkaVersion, versionFromCr.version()) > 0) {
        // Highest Kafka version used by the brokers is higher than desired => suspected downgrade
        versionFrom = versions.version(highestKafkaVersion);
        versionTo = versionFromCr;
    } else {
        // Highest Kafka version used by the brokers is equal or lower than desired => suspected upgrade
        versionFrom = versions.version(lowestKafkaVersion);
        versionTo = versionFromCr;
    }
    return Future.succeededFuture();
}
Also used : Pod(io.fabric8.kubernetes.api.model.Pod) KafkaUpgradeException(io.strimzi.operator.cluster.KafkaUpgradeException)

Example 4 with KafkaUpgradeException

use of io.strimzi.operator.cluster.KafkaUpgradeException in project strimzi by strimzi.

the class VersionChangeCreator method prepareVersionChange.

/**
 * Plans the version change and creates a KafkaVersionChange object which contains the main versions as well as the
 * inter.broker.protocol.version and log.message.format.version.
 *
 * @return  Future with the KafkaVersionChange instance describing the Kafka version changes
 */
@SuppressWarnings("checkstyle:CyclomaticComplexity")
private Future<KafkaVersionChange> prepareVersionChange() {
    if (versionFrom.compareTo(versionTo) == 0) {
        // => no version change
        LOGGER.debugCr(reconciliation, "{}: No Kafka version change", reconciliation);
        if (interBrokerProtocolVersionFromCr == null) {
            // When inter.broker.protocol.version is not set, we set it to current Kafka version
            interBrokerProtocolVersion = versionFromCr.protocolVersion();
            if (highestInterBrokerProtocolVersionFromPods != null && !versionFromCr.protocolVersion().equals(highestInterBrokerProtocolVersionFromPods)) {
                LOGGER.infoCr(reconciliation, "Upgrading Kafka inter.broker.protocol.version from {} to {}", highestInterBrokerProtocolVersionFromPods, versionFromCr.protocolVersion());
                if (compareDottedIVVersions(versionFromCr.protocolVersion(), "3.0") >= 0) {
                    // From Kafka 3.0.0, the log.message.format.version is ignored when inter.broker.protocol.version is set to 3.0 or higher
                    // We set the log.message.format.version immediately to the same version as inter.broker.protocol.version to avoid unnecessary rolling update
                    logMessageFormatVersion = versionFromCr.messageVersion();
                } else if (logMessageFormatVersionFromCr == null && highestLogMessageFormatVersionFromPods != null) {
                    // For Kafka versions older than 3.0.0, inter.broker.protocol.version and log.message.format.version should not change in the same rolling
                    // update. When this rolling update is going to change the inter.broker.protocol.version, we keep the old log.message.format.version
                    logMessageFormatVersion = highestLogMessageFormatVersionFromPods;
                }
            }
        }
        if (logMessageFormatVersionFromCr == null) {
            // When log.message.format.version is not set, we set it to current Kafka version
            logMessageFormatVersion = versionFromCr.messageVersion();
            if (highestLogMessageFormatVersionFromPods != null && !versionFromCr.messageVersion().equals(highestLogMessageFormatVersionFromPods)) {
                LOGGER.infoCr(reconciliation, "Upgrading Kafka log.message.format.version from {} to {}", highestLogMessageFormatVersionFromPods, versionFromCr.messageVersion());
            }
        }
    } else {
        if (versionFrom.compareTo(versionTo) < 0) {
            // => is upgrade
            LOGGER.infoCr(reconciliation, "Kafka is upgrading from {} to {}", versionFrom.version(), versionTo.version());
            // used by any of the brokers is not higher than the broker version we upgrade from.
            if ((highestLogMessageFormatVersionFromPods != null && compareDottedIVVersions(versionFrom.messageVersion(), highestLogMessageFormatVersionFromPods) < 0) || (highestInterBrokerProtocolVersionFromPods != null && compareDottedIVVersions(versionFrom.protocolVersion(), highestInterBrokerProtocolVersionFromPods) < 0)) {
                LOGGER.warnCr(reconciliation, "log.message.format.version ({}) and inter.broker.protocol.version ({}) used by the brokers have to be lower or equal to the Kafka broker version we upgrade from ({})", highestInterBrokerProtocolVersionFromPods, highestInterBrokerProtocolVersionFromPods, versionFrom.version());
                throw new KafkaUpgradeException("log.message.format.version (" + highestLogMessageFormatVersionFromPods + ") and inter.broker.protocol.version (" + highestInterBrokerProtocolVersionFromPods + ") used by the brokers have to be lower or equal to the Kafka broker version we upgrade from (" + versionFrom.version() + ")");
            }
            String desiredLogMessageFormat = logMessageFormatVersionFromCr;
            String desiredInterBrokerProtocol = interBrokerProtocolVersionFromCr;
            // upgrading from. If it is not set, we set it to the version we are upgrading from.
            if (desiredLogMessageFormat == null || compareDottedIVVersions(versionFrom.messageVersion(), desiredLogMessageFormat) < 0) {
                logMessageFormatVersion = versionFrom.messageVersion();
            }
            // are upgrading from. If it is not set, we set it to the version we are upgrading from.
            if (desiredInterBrokerProtocol == null || compareDottedIVVersions(versionFrom.protocolVersion(), desiredInterBrokerProtocol) < 0) {
                interBrokerProtocolVersion = versionFrom.protocolVersion();
            }
        } else {
            // Has to be a downgrade
            LOGGER.infoCr(reconciliation, "Kafka is downgrading from {} to {}", versionFrom.version(), versionTo.version());
            // reconciliation as well.
            if (highestLogMessageFormatVersionFromPods == null || compareDottedIVVersions(versionTo.messageVersion(), highestLogMessageFormatVersionFromPods) < 0 || highestInterBrokerProtocolVersionFromPods == null || compareDottedIVVersions(versionTo.protocolVersion(), highestInterBrokerProtocolVersionFromPods) < 0) {
                LOGGER.warnCr(reconciliation, "log.message.format.version ({}) and inter.broker.protocol.version ({}) used by the brokers have to be set and be lower or equal to the Kafka broker version we downgrade to ({})", highestLogMessageFormatVersionFromPods, highestInterBrokerProtocolVersionFromPods, versionTo.version());
                throw new KafkaUpgradeException("log.message.format.version (" + highestLogMessageFormatVersionFromPods + ") and inter.broker.protocol.version (" + highestInterBrokerProtocolVersionFromPods + ") used by the brokers have to be set and be lower or equal to the Kafka broker version we downgrade to (" + versionTo.version() + ")");
            }
            String desiredLogMessageFormat = logMessageFormatVersionFromCr;
            String desiredInterBrokerProtocol = interBrokerProtocolVersionFromCr;
            // If log.message.format.version is not set, we set it to the version we are downgrading to.
            if (desiredLogMessageFormat == null) {
                desiredLogMessageFormat = versionTo.messageVersion();
                logMessageFormatVersion = versionTo.messageVersion();
            }
            // If inter.broker.protocol.version is not set, we set it to the version we are downgrading to.
            if (desiredInterBrokerProtocol == null) {
                desiredInterBrokerProtocol = versionTo.protocolVersion();
                interBrokerProtocolVersion = versionTo.protocolVersion();
            }
            // validation. However, we still double-check it as safety.
            if (compareDottedIVVersions(versionTo.messageVersion(), desiredLogMessageFormat) < 0 || compareDottedIVVersions(versionTo.protocolVersion(), desiredInterBrokerProtocol) < 0) {
                LOGGER.warnCr(reconciliation, "log.message.format.version ({}) and inter.broker.protocol.version ({}) used in the Kafka CR have to be set and be lower or equal to the Kafka broker version we downgrade to ({})", highestLogMessageFormatVersionFromPods, highestInterBrokerProtocolVersionFromPods, versionTo.version());
                throw new KafkaUpgradeException("log.message.format.version and inter.broker.protocol.version used in the Kafka CR have to be set and be lower or equal to the Kafka broker version we downgrade to");
            }
        }
    }
    return Future.succeededFuture(new KafkaVersionChange(versionFrom, versionTo, interBrokerProtocolVersion, logMessageFormatVersion));
}
Also used : KafkaVersionChange(io.strimzi.operator.cluster.model.KafkaVersionChange) KafkaUpgradeException(io.strimzi.operator.cluster.KafkaUpgradeException)

Aggregations

KafkaUpgradeException (io.strimzi.operator.cluster.KafkaUpgradeException)4 Pod (io.fabric8.kubernetes.api.model.Pod)2 KafkaVersionChange (io.strimzi.operator.cluster.model.KafkaVersionChange)2