All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.fabric8.jgroups.KubernetesDiscovery Maven / Gradle / Ivy

There is a newer version: 3.0.12
Show newest version
/**
 *  Copyright 2005-2016 Red Hat, Inc.
 *
 *  Red Hat licenses this file to you under the Apache License, version
 *  2.0 (the "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 *  implied.  See the License for the specific language governing
 *  permissions and limitations under the License.
 */
package io.fabric8.jgroups;


import io.fabric8.kubernetes.api.KubernetesHelper;
import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.ContainerPort;
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.client.ConfigBuilder;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.utils.Filter;
import io.fabric8.utils.Strings;
import org.jgroups.Address;
import org.jgroups.Event;
import org.jgroups.Message;
import org.jgroups.PhysicalAddress;
import org.jgroups.annotations.MBean;
import org.jgroups.annotations.Property;
import org.jgroups.protocols.Discovery;
import org.jgroups.protocols.PingData;
import org.jgroups.protocols.PingHeader;
import org.jgroups.stack.IpAddress;
import org.jgroups.util.BoundedList;
import org.jgroups.util.Responses;
import org.jgroups.util.Tuple;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import java.util.*;

@MBean(description = "Kubernetes discovery protocol")
public class KubernetesDiscovery extends Discovery {

    private static final Logger LOGGER = LoggerFactory.getLogger(KubernetesDiscovery.class);

    @Property
    private String address;

    private KubernetesClient client;
    private List kubernetesHosts = Collections.emptyList();
    private BoundedList dynamic_hosts = new BoundedList<>(2000);
    
    @Override
    public void init() throws Exception {
        super.init();
        if (!Strings.isNullOrBlank(address)) {
            client = new DefaultKubernetesClient(new ConfigBuilder().withMasterUrl(address).build());
        } else {
            client = new DefaultKubernetesClient();
        }
    }

    public Object down(Event evt) {
        Object retval = super.down(evt);
        switch (evt.getType()) {
            case Event.VIEW_CHANGE:
                for (Address logical_addr : members) {
                    PhysicalAddress physical_addr = (PhysicalAddress) down_prot.down(new Event(Event.GET_PHYSICAL_ADDRESS, logical_addr));
                    if (physical_addr != null && !kubernetesHosts.contains(physical_addr)) {
                        dynamic_hosts.addIfAbsent(physical_addr);
                    }
                }
                break;
            case Event.SET_PHYSICAL_ADDRESS:
                Tuple tuple = (Tuple) evt.getArg();
                PhysicalAddress physical_addr = tuple.getVal2();
                if (physical_addr != null && !kubernetesHosts.contains(physical_addr))
                    dynamic_hosts.addIfAbsent(physical_addr);
                break;
        }
        return retval;
    }

    public void discoveryRequestReceived(Address sender, String logical_name, PhysicalAddress physical_addr) {
        super.discoveryRequestReceived(sender, logical_name, physical_addr);
        if (physical_addr != null) {
            if (!kubernetesHosts.contains(physical_addr))
                dynamic_hosts.addIfAbsent(physical_addr);
        }
    }

    @Override
    public void findMembers(List
members, boolean initial_discovery, Responses responses) { kubernetesHosts = findKubernetesHosts(); PhysicalAddress physical_addr = (PhysicalAddress) down(new Event(Event.GET_PHYSICAL_ADDRESS, local_addr)); // https://issues.jboss.org/browse/JGRP-1670 PingData data = new PingData(local_addr, false, org.jgroups.util.UUID.get(local_addr), physical_addr); PingHeader hdr = new PingHeader(PingHeader.GET_MBRS_REQ).clusterName(cluster_name); Set cluster_members = new HashSet<>(kubernetesHosts); cluster_members.addAll(dynamic_hosts); if (use_disk_cache) { // this only makes sense if we have PDC below us Collection list = (Collection) down_prot.down(new Event(Event.GET_PHYSICAL_ADDRESSES)); if (list != null) for (PhysicalAddress phys_addr : list) if (!cluster_members.contains(phys_addr)) cluster_members.add(phys_addr); } for (final PhysicalAddress addr : cluster_members) { if (physical_addr != null && addr.equals(physical_addr)) // no need to send the request to myself continue; // the message needs to be DONT_BUNDLE, see explanation above final Message msg = new Message(addr).setFlag(Message.Flag.INTERNAL, Message.Flag.DONT_BUNDLE, Message.Flag.OOB) .putHeader(this.id, hdr).setBuffer(marshal(data)); log.trace("%s: sending discovery request to %s", local_addr, msg.getDest()); down_prot.down(new Event(Event.MSG, msg)); } } public List findKubernetesHosts() { List addresses = new ArrayList<>(); Map labels = Collections.singletonMap(Constants.JGROUPS_CLUSTER_NAME, cluster_name); for (Pod pod : client.pods().withLabels(labels).list().getItems()) { List containers = KubernetesHelper.getContainers(pod); for (Container container : containers) { for (ContainerPort port : container.getPorts()) { if (Constants.JGROUPS_TCP_PORT.equals(port.getName())) { try { String ip = pod.getStatus().getPodIP(); if (ip != null) { addresses.add(new IpAddress(ip, port.getContainerPort())); } } catch (Exception ex) { LOGGER.warn("Failed to create Address {}.", pod.getStatus().getPodIP()); } } } } } return addresses; } @Override public boolean isDynamic() { return true; } private static List filterPods(List pods, Filter podFilter) { List result = new ArrayList<>(); for (Pod pod : pods) { if (podFilter.matches(pod)) { result.add(pod); } } return result; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy