Search in sources :

Example 71 with Reconciliation

use of io.strimzi.operator.common.Reconciliation in project strimzi by strimzi.

the class KafkaReconciler method scaleDown.

/**
 * Scales down the Kafka cluster if needed. Kafka scale-down is done in one go.
 *
 * @return  Future which completes when the scale-down is finished
 */
protected Future<Void> scaleDown() {
    if (currentReplicas != 0 && currentReplicas > kafka.getReplicas()) {
        // The previous (current) number of replicas is bigger than desired => we should scale-down
        LOGGER.infoCr(reconciliation, "Scaling Kafka down from {} to {} replicas", currentReplicas, kafka.getReplicas());
        if (featureGates.useStrimziPodSetsEnabled()) {
            Set<String> desiredPodNames = new HashSet<>(kafka.getReplicas());
            for (int i = 0; i < kafka.getReplicas(); i++) {
                desiredPodNames.add(kafka.getPodName(i));
            }
            return strimziPodSetOperator.getAsync(reconciliation.namespace(), kafka.getName()).compose(podSet -> {
                if (podSet == null) {
                    return Future.succeededFuture();
                } else {
                    List<Map<String, Object>> desiredPods = podSet.getSpec().getPods().stream().filter(pod -> desiredPodNames.contains(PodSetUtils.mapToPod(pod).getMetadata().getName())).collect(Collectors.toList());
                    StrimziPodSet scaledDownPodSet = new StrimziPodSetBuilder(podSet).editSpec().withPods(desiredPods).endSpec().build();
                    return strimziPodSetOperator.reconcile(reconciliation, reconciliation.namespace(), kafka.getName(), scaledDownPodSet).map((Void) null);
                }
            });
        } else {
            return stsOperator.scaleDown(reconciliation, reconciliation.namespace(), kafka.getName(), kafka.getReplicas()).map((Void) null);
        }
    } else {
        // desired replicas => no need to scale-down
        return Future.succeededFuture();
    }
}
Also used : IngressV1Beta1Operator(io.strimzi.operator.common.operator.resource.IngressV1Beta1Operator) Storage(io.strimzi.api.kafka.model.storage.Storage) StrimziPodSetOperator(io.strimzi.operator.common.operator.resource.StrimziPodSetOperator) Date(java.util.Date) Annotations(io.strimzi.operator.common.Annotations) KafkaException(org.apache.kafka.common.KafkaException) PodDisruptionBudget(io.fabric8.kubernetes.api.model.policy.v1.PodDisruptionBudget) ClusterRoleBindingOperator(io.strimzi.operator.common.operator.resource.ClusterRoleBindingOperator) KafkaResources(io.strimzi.api.kafka.model.KafkaResources) Ca(io.strimzi.operator.cluster.model.Ca) PodDisruptionBudgetV1Beta1Operator(io.strimzi.operator.common.operator.resource.PodDisruptionBudgetV1Beta1Operator) StrimziPodSetBuilder(io.strimzi.api.kafka.model.StrimziPodSetBuilder) Map(java.util.Map) PodOperator(io.strimzi.operator.common.operator.resource.PodOperator) ResourceOperatorSupplier(io.strimzi.operator.cluster.operator.resource.ResourceOperatorSupplier) AbstractModel(io.strimzi.operator.cluster.model.AbstractModel) StatefulSetOperator(io.strimzi.operator.cluster.operator.resource.StatefulSetOperator) KafkaVersionChange(io.strimzi.operator.cluster.model.KafkaVersionChange) ModelUtils(io.strimzi.operator.cluster.model.ModelUtils) ListenersUtils(io.strimzi.operator.cluster.model.ListenersUtils) ListenerAddress(io.strimzi.api.kafka.model.status.ListenerAddress) SecretOperator(io.strimzi.operator.common.operator.resource.SecretOperator) Set(java.util.Set) ClientsCa(io.strimzi.operator.cluster.model.ClientsCa) HasMetadata(io.fabric8.kubernetes.api.model.HasMetadata) NodeUtils(io.strimzi.operator.cluster.model.NodeUtils) Future(io.vertx.core.Future) Collectors(java.util.stream.Collectors) ListenerStatus(io.strimzi.api.kafka.model.status.ListenerStatus) List(java.util.List) KafkaConfiguration(io.strimzi.operator.cluster.model.KafkaConfiguration) Labels(io.strimzi.operator.common.model.Labels) StrimziPodSet(io.strimzi.api.kafka.model.StrimziPodSet) PersistentVolumeClaim(io.fabric8.kubernetes.api.model.PersistentVolumeClaim) Secret(io.fabric8.kubernetes.api.model.Secret) RouteOperator(io.strimzi.operator.common.operator.resource.RouteOperator) AdminClientProvider(io.strimzi.operator.common.AdminClientProvider) ClusterCa(io.strimzi.operator.cluster.model.ClusterCa) PodDisruptionBudgetOperator(io.strimzi.operator.common.operator.resource.PodDisruptionBudgetOperator) PlatformFeaturesAvailability(io.strimzi.operator.PlatformFeaturesAvailability) SuppressFBWarnings(edu.umd.cs.findbugs.annotations.SuppressFBWarnings) ClusterOperatorConfig(io.strimzi.operator.cluster.ClusterOperatorConfig) IntStream(java.util.stream.IntStream) ClusterRoleBinding(io.fabric8.kubernetes.api.model.rbac.ClusterRoleBinding) KafkaStatus(io.strimzi.api.kafka.model.status.KafkaStatus) GenericKafkaListener(io.strimzi.api.kafka.model.listener.arraylistener.GenericKafkaListener) BackOff(io.strimzi.operator.common.BackOff) IngressOperator(io.strimzi.operator.common.operator.resource.IngressOperator) NetworkPolicyOperator(io.strimzi.operator.common.operator.resource.NetworkPolicyOperator) HashMap(java.util.HashMap) ListenerAddressBuilder(io.strimzi.api.kafka.model.status.ListenerAddressBuilder) LocalObjectReference(io.fabric8.kubernetes.api.model.LocalObjectReference) Function(java.util.function.Function) Supplier(java.util.function.Supplier) FeatureGates(io.strimzi.operator.cluster.FeatureGates) StorageDiff(io.strimzi.operator.cluster.model.StorageDiff) MetricsAndLogging(io.strimzi.operator.common.MetricsAndLogging) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) ServiceOperator(io.strimzi.operator.common.operator.resource.ServiceOperator) CompositeFuture(io.vertx.core.CompositeFuture) KafkaCluster(io.strimzi.operator.cluster.model.KafkaCluster) ServiceAccountOperator(io.strimzi.operator.common.operator.resource.ServiceAccountOperator) ConfigMapOperator(io.strimzi.operator.common.operator.resource.ConfigMapOperator) ANNO_STRIMZI_IO_KAFKA_VERSION(io.strimzi.operator.cluster.model.KafkaCluster.ANNO_STRIMZI_IO_KAFKA_VERSION) KafkaRoller(io.strimzi.operator.cluster.operator.resource.KafkaRoller) Admin(org.apache.kafka.clients.admin.Admin) ReconcileResult(io.strimzi.operator.common.operator.resource.ReconcileResult) ConcurrentDeletionException(io.strimzi.operator.cluster.operator.resource.ConcurrentDeletionException) Node(io.fabric8.kubernetes.api.model.Node) JbodStorage(io.strimzi.api.kafka.model.storage.JbodStorage) ReconciliationLogger(io.strimzi.operator.common.ReconciliationLogger) NodeOperator(io.strimzi.operator.common.operator.resource.NodeOperator) Promise(io.vertx.core.Promise) Vertx(io.vertx.core.Vertx) Pod(io.fabric8.kubernetes.api.model.Pod) PodSetUtils(io.strimzi.operator.cluster.model.PodSetUtils) StorageClassOperator(io.strimzi.operator.common.operator.resource.StorageClassOperator) StatefulSet(io.fabric8.kubernetes.api.model.apps.StatefulSet) PvcOperator(io.strimzi.operator.common.operator.resource.PvcOperator) ConfigMap(io.fabric8.kubernetes.api.model.ConfigMap) ExecutionException(java.util.concurrent.ExecutionException) Reconciliation(io.strimzi.operator.common.Reconciliation) ImagePullPolicy(io.strimzi.operator.cluster.model.ImagePullPolicy) ANNO_STRIMZI_IO_STORAGE(io.strimzi.operator.cluster.model.AbstractModel.ANNO_STRIMZI_IO_STORAGE) Util(io.strimzi.operator.common.Util) Kafka(io.strimzi.api.kafka.model.Kafka) StrimziPodSet(io.strimzi.api.kafka.model.StrimziPodSet) StrimziPodSetBuilder(io.strimzi.api.kafka.model.StrimziPodSetBuilder) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ConfigMap(io.fabric8.kubernetes.api.model.ConfigMap) HashSet(java.util.HashSet)

Example 72 with Reconciliation

use of io.strimzi.operator.common.Reconciliation in project strimzi by strimzi.

the class ManualPodCleaner method cleanPodPvcAndPodSet.

/**
 * Handles the modification of the StrimziPodSet controlling the pod which should be cleaned. In order
 * to clean the pod and its PVCs, we first need to remove the pod from the StrimziPodSet. Otherwise, the
 * StrimziPodSet will break the process by recreating the pods or PVCs. This method first modifies the StrimziPodSet
 * and then calls other method to delete the Pod, PVCs and create the new PVCs. Once this method completes, it
 * will update the StrimziPodSet again. The Pod will be then recreated by the StrimziPodSet and this method just
 * waits for it to become ready.
 *
 * The complete flow looks like this
 *     1. Remove the deleted pod from the PodSet
 *     2. Trigger the Pod and PVC deletion and recreation
 *     3. Recreate the original PodSet
 *     4. Wait for the Pod to be created and become ready
 *
 * @param podSetName    Name of the StrimziPodSet to which this pod belongs
 * @param podName       Name of the Pod which should be cleaned / deleted
 * @param desiredPvcs   The list of desired PVCs which should be created after the old Pod and PVCs are deleted
 * @param currentPvcs   The list of current PVCs which should be deleted
 *
 * @return              Future indicating the result of the cleanup
 */
private Future<Void> cleanPodPvcAndPodSet(String podSetName, String podName, List<PersistentVolumeClaim> desiredPvcs, List<PersistentVolumeClaim> currentPvcs) {
    return strimziPodSetOperator.getAsync(reconciliation.namespace(), podSetName).compose(podSet -> {
        List<Map<String, Object>> desiredPods = podSet.getSpec().getPods().stream().filter(pod -> !podName.equals(PodSetUtils.mapToPod(pod).getMetadata().getName())).collect(Collectors.toList());
        StrimziPodSet reducedPodSet = new StrimziPodSetBuilder(podSet).editSpec().withPods(desiredPods).endSpec().build();
        return strimziPodSetOperator.reconcile(reconciliation, reconciliation.namespace(), podSetName, reducedPodSet).compose(ignore -> cleanPodAndPvc(podName, desiredPvcs, currentPvcs)).compose(ignore -> {
            // We recreate the StrimziPodSet in its old configuration => any further changes have to be done by rolling update
            // These fields need to be cleared before recreating the StatefulSet
            podSet.getMetadata().setResourceVersion(null);
            podSet.getMetadata().setSelfLink(null);
            podSet.getMetadata().setUid(null);
            podSet.setStatus(null);
            return strimziPodSetOperator.reconcile(reconciliation, reconciliation.namespace(), podSetName, podSet);
        }).compose(ignore -> podOperator.readiness(reconciliation, reconciliation.namespace(), podName, 1_000L, operationTimeoutMs)).map((Void) null);
    });
}
Also used : AbstractScalableResourceOperator(io.strimzi.operator.common.operator.resource.AbstractScalableResourceOperator) ReconciliationLogger(io.strimzi.operator.common.ReconciliationLogger) StrimziPodSetOperator(io.strimzi.operator.common.operator.resource.StrimziPodSetOperator) Pod(io.fabric8.kubernetes.api.model.Pod) PodSetUtils(io.strimzi.operator.cluster.model.PodSetUtils) Annotations(io.strimzi.operator.common.Annotations) PvcOperator(io.strimzi.operator.common.operator.resource.PvcOperator) Future(io.vertx.core.Future) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) Reconciliation(io.strimzi.operator.common.Reconciliation) CompositeFuture(io.vertx.core.CompositeFuture) List(java.util.List) Labels(io.strimzi.operator.common.model.Labels) StrimziPodSet(io.strimzi.api.kafka.model.StrimziPodSet) StrimziPodSetBuilder(io.strimzi.api.kafka.model.StrimziPodSetBuilder) Map(java.util.Map) PodOperator(io.strimzi.operator.common.operator.resource.PodOperator) PersistentVolumeClaim(io.fabric8.kubernetes.api.model.PersistentVolumeClaim) ResourceOperatorSupplier(io.strimzi.operator.cluster.operator.resource.ResourceOperatorSupplier) ClusterOperatorConfig(io.strimzi.operator.cluster.ClusterOperatorConfig) StatefulSetOperator(io.strimzi.operator.cluster.operator.resource.StatefulSetOperator) StrimziPodSet(io.strimzi.api.kafka.model.StrimziPodSet) StrimziPodSetBuilder(io.strimzi.api.kafka.model.StrimziPodSetBuilder) Map(java.util.Map)

Example 73 with Reconciliation

use of io.strimzi.operator.common.Reconciliation in project strimzi by strimzi.

the class PvcReconciler method resizeAndReconcilePvcs.

/**
 * Resizes and reconciles the PVCs based on the model and list of PVCs passed to it. It will return a future with
 * collection containing a list of pods which need restart to complete the filesystem resizing. The PVCs are only
 * created or updated. This method does not delete any PVCs. This is done by a separate method which should be
 * called separately at the end of the reconciliation.
 *
 * @param podNameProvider   Function to generate a pod name from its index
 * @param pvcs              List of desired PVC used by this controller
 *
 * @return                  Future with list of pod names which should be restarted to complete the filesystem resizing
 */
public Future<Collection<String>> resizeAndReconcilePvcs(Function<Integer, String> podNameProvider, List<PersistentVolumeClaim> pvcs) {
    Set<String> podsToRestart = new HashSet<>();
    // Has to use Raw type because of the CompositeFuture
    @SuppressWarnings({ "rawtypes" }) List<Future> futures = new ArrayList<>(pvcs.size());
    for (PersistentVolumeClaim desiredPvc : pvcs) {
        Future<Void> perPvcFuture = pvcOperator.getAsync(reconciliation.namespace(), desiredPvc.getMetadata().getName()).compose(currentPvc -> {
            if (currentPvc == null || currentPvc.getStatus() == null || !"Bound".equals(currentPvc.getStatus().getPhase())) {
                // * The PVC is not Bound, we should reconcile it
                return pvcOperator.reconcile(reconciliation, reconciliation.namespace(), desiredPvc.getMetadata().getName(), desiredPvc).map((Void) null);
            } else if (currentPvc.getStatus().getConditions().stream().anyMatch(cond -> "Resizing".equals(cond.getType()) && "true".equals(cond.getStatus().toLowerCase(Locale.ENGLISH)))) {
                // The PVC is Bound, but it is already resizing => Nothing to do, we should let it resize
                LOGGER.debugCr(reconciliation, "The PVC {} is resizing, nothing to do", desiredPvc.getMetadata().getName());
                return Future.succeededFuture();
            } else if (currentPvc.getStatus().getConditions().stream().anyMatch(cond -> "FileSystemResizePending".equals(cond.getType()) && "true".equals(cond.getStatus().toLowerCase(Locale.ENGLISH)))) {
                // The PVC is Bound and resized but waiting for FS resizing => We need to restart the pod which is using it
                String podName = podNameProvider.apply(getPodIndexFromPvcName(desiredPvc.getMetadata().getName()));
                podsToRestart.add(podName);
                LOGGER.infoCr(reconciliation, "The PVC {} is waiting for file system resizing and the pod {} needs to be restarted.", desiredPvc.getMetadata().getName(), podName);
                return Future.succeededFuture();
            } else {
                // The PVC is Bound and resizing is not in progress => We should check if the SC supports resizing and check if size changed
                Long currentSize = StorageUtils.convertToMillibytes(currentPvc.getSpec().getResources().getRequests().get("storage"));
                Long desiredSize = StorageUtils.convertToMillibytes(desiredPvc.getSpec().getResources().getRequests().get("storage"));
                if (!currentSize.equals(desiredSize)) {
                    // The sizes are different => we should resize (shrinking will be handled in StorageDiff, so we do not need to check that)
                    return resizePvc(currentPvc, desiredPvc);
                } else {
                    // size didn't change, just reconcile
                    return pvcOperator.reconcile(reconciliation, reconciliation.namespace(), desiredPvc.getMetadata().getName(), desiredPvc).map((Void) null);
                }
            }
        });
        futures.add(perPvcFuture);
    }
    return CompositeFuture.all(futures).map(podsToRestart);
}
Also used : ReconciliationLogger(io.strimzi.operator.common.ReconciliationLogger) Collection(java.util.Collection) Annotations(io.strimzi.operator.common.Annotations) StorageClassOperator(io.strimzi.operator.common.operator.resource.StorageClassOperator) Set(java.util.Set) PvcOperator(io.strimzi.operator.common.operator.resource.PvcOperator) Future(io.vertx.core.Future) Function(java.util.function.Function) ArrayList(java.util.ArrayList) StorageUtils(io.strimzi.operator.cluster.model.StorageUtils) HashSet(java.util.HashSet) Reconciliation(io.strimzi.operator.common.Reconciliation) CompositeFuture(io.vertx.core.CompositeFuture) List(java.util.List) Locale(java.util.Locale) PersistentVolumeClaim(io.fabric8.kubernetes.api.model.PersistentVolumeClaim) AbstractModel(io.strimzi.operator.cluster.model.AbstractModel) ArrayList(java.util.ArrayList) Future(io.vertx.core.Future) CompositeFuture(io.vertx.core.CompositeFuture) PersistentVolumeClaim(io.fabric8.kubernetes.api.model.PersistentVolumeClaim) HashSet(java.util.HashSet)

Example 74 with Reconciliation

use of io.strimzi.operator.common.Reconciliation in project strimzi by strimzi.

the class EntityOperatorTest method testImagePullSecretsFromCo.

@ParallelTest
public void testImagePullSecretsFromCo() {
    LocalObjectReference secret1 = new LocalObjectReference("some-pull-secret");
    LocalObjectReference secret2 = new LocalObjectReference("some-other-pull-secret");
    List<LocalObjectReference> secrets = new ArrayList<>(2);
    secrets.add(secret1);
    secrets.add(secret2);
    Kafka resource = new KafkaBuilder(ResourceUtils.createKafka(namespace, cluster, replicas, image, healthDelay, healthTimeout)).editSpec().withNewEntityOperator().withTopicOperator(entityTopicOperatorSpec).withUserOperator(entityUserOperatorSpec).endEntityOperator().endSpec().build();
    EntityOperator eo = EntityOperator.fromCrd(new Reconciliation("test", resource.getKind(), resource.getMetadata().getNamespace(), resource.getMetadata().getName()), resource, VERSIONS, true);
    Deployment dep = eo.generateDeployment(true, null, secrets);
    assertThat(dep.getSpec().getTemplate().getSpec().getImagePullSecrets().size(), is(2));
    assertThat(dep.getSpec().getTemplate().getSpec().getImagePullSecrets().contains(secret1), is(true));
    assertThat(dep.getSpec().getTemplate().getSpec().getImagePullSecrets().contains(secret2), is(true));
}
Also used : LocalObjectReference(io.fabric8.kubernetes.api.model.LocalObjectReference) Reconciliation(io.strimzi.operator.common.Reconciliation) ArrayList(java.util.ArrayList) Kafka(io.strimzi.api.kafka.model.Kafka) Deployment(io.fabric8.kubernetes.api.model.apps.Deployment) KafkaBuilder(io.strimzi.api.kafka.model.KafkaBuilder) ParallelTest(io.strimzi.test.annotations.ParallelTest)

Example 75 with Reconciliation

use of io.strimzi.operator.common.Reconciliation in project strimzi by strimzi.

the class EntityOperatorTest method testFromCrdNoUserOperatorInEntityOperator.

@ParallelTest
public void testFromCrdNoUserOperatorInEntityOperator() {
    EntityOperatorSpec entityOperatorSpec = new EntityOperatorSpecBuilder().withNewTopicOperator().endTopicOperator().build();
    Kafka resource = new KafkaBuilder(ResourceUtils.createKafka(namespace, cluster, replicas, image, healthDelay, healthTimeout)).editSpec().withEntityOperator(entityOperatorSpec).endSpec().build();
    EntityOperator entityOperator = EntityOperator.fromCrd(new Reconciliation("test", resource.getKind(), resource.getMetadata().getNamespace(), resource.getMetadata().getName()), resource, VERSIONS, true);
    assertThat(entityOperator.topicOperator(), is(notNullValue()));
    assertThat(entityOperator.userOperator(), is(nullValue()));
}
Also used : EntityOperatorSpec(io.strimzi.api.kafka.model.EntityOperatorSpec) Reconciliation(io.strimzi.operator.common.Reconciliation) Kafka(io.strimzi.api.kafka.model.Kafka) KafkaBuilder(io.strimzi.api.kafka.model.KafkaBuilder) EntityOperatorSpecBuilder(io.strimzi.api.kafka.model.EntityOperatorSpecBuilder) ParallelTest(io.strimzi.test.annotations.ParallelTest)

Aggregations

Reconciliation (io.strimzi.operator.common.Reconciliation)748 Checkpoint (io.vertx.junit5.Checkpoint)504 Test (org.junit.jupiter.api.Test)496 Future (io.vertx.core.Future)478 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)474 ResourceOperatorSupplier (io.strimzi.operator.cluster.operator.resource.ResourceOperatorSupplier)462 Vertx (io.vertx.core.Vertx)450 VertxTestContext (io.vertx.junit5.VertxTestContext)446 VertxExtension (io.vertx.junit5.VertxExtension)436 List (java.util.List)436 ExtendWith (org.junit.jupiter.api.extension.ExtendWith)436 Map (java.util.Map)426 AfterAll (org.junit.jupiter.api.AfterAll)406 BeforeAll (org.junit.jupiter.api.BeforeAll)394 Kafka (io.strimzi.api.kafka.model.Kafka)392 PlatformFeaturesAvailability (io.strimzi.operator.PlatformFeaturesAvailability)392 ResourceUtils (io.strimzi.operator.cluster.ResourceUtils)390 CoreMatchers.is (org.hamcrest.CoreMatchers.is)380 KafkaVersionTestUtils (io.strimzi.operator.cluster.KafkaVersionTestUtils)368 Mockito.when (org.mockito.Mockito.when)360