Search in sources :

Example 1 with NodeAddress

use of io.fabric8.kubernetes.api.model.NodeAddress in project fabric8 by fabric8io.

the class KubernetesHelper method getServiceURL.

/**
 * Returns the URL to access the service; using the environment variables, routes
 * or service clusterIP address
 *
 * @throws IllegalArgumentException if the URL cannot be found for the serviceName and namespace
 */
public static String getServiceURL(KubernetesClient client, String serviceName, String serviceNamespace, String serviceProtocol, String servicePortName, boolean serviceExternal) {
    Service srv = null;
    String serviceHost = KubernetesServices.serviceToHostOrBlank(serviceName);
    String servicePort = KubernetesServices.serviceToPortOrBlank(serviceName, servicePortName);
    String serviceProto = serviceProtocol != null ? serviceProtocol : KubernetesServices.serviceToProtocol(serviceName, servicePort);
    // Use specified or fallback namespace.
    String actualNamespace = Strings.isNotBlank(serviceNamespace) ? serviceNamespace : client.getNamespace();
    // 1. Inside Kubernetes: Services as ENV vars
    if (!serviceExternal && Strings.isNotBlank(serviceHost) && Strings.isNotBlank(servicePort) && Strings.isNotBlank(serviceProtocol)) {
        return serviceProtocol + "://" + serviceHost + ":" + servicePort;
    // 2. Anywhere: When namespace is passed System / Env var. Mostly needed for integration tests.
    } else if (Strings.isNotBlank(actualNamespace)) {
        try {
            srv = client.services().inNamespace(actualNamespace).withName(serviceName).get();
        } catch (Exception e) {
            LOGGER.warn("Could not lookup service:" + serviceName + " in namespace:" + actualNamespace + ", due to: " + e.getMessage());
        }
    }
    if (srv == null) {
        // lets try use environment variables
        String hostAndPort = Systems.getServiceHostAndPort(serviceName, "", "");
        if (!hostAndPort.startsWith(":")) {
            return serviceProto + "://" + hostAndPort;
        }
    }
    if (srv == null) {
        throw new IllegalArgumentException("No kubernetes service could be found for name: " + serviceName + " in namespace: " + actualNamespace);
    }
    String answer = getOrCreateAnnotations(srv).get(Annotations.Service.EXPOSE_URL);
    if (Strings.isNotBlank(answer)) {
        return answer;
    }
    try {
        if (Strings.isNullOrBlank(servicePortName) && isOpenShift(client)) {
            OpenShiftClient openShiftClient = client.adapt(OpenShiftClient.class);
            Route route = openShiftClient.routes().inNamespace(actualNamespace).withName(serviceName).get();
            if (route != null) {
                return (serviceProto + "://" + route.getSpec().getHost()).toLowerCase();
            }
        }
    } catch (KubernetesClientException e) {
        if (e.getCode() == 403) {
            LOGGER.warn("Could not lookup route:" + serviceName + " in namespace:" + actualNamespace + ", due to: " + e.getMessage());
        } else {
            throw e;
        }
    }
    ServicePort port = findServicePortByName(srv, servicePortName);
    if (port == null) {
        throw new RuntimeException("Couldn't find port: " + servicePortName + " for service:" + serviceName);
    }
    String clusterIP = srv.getSpec().getClusterIP();
    if ("None".equals(clusterIP)) {
        throw new IllegalStateException("Service: " + serviceName + " in namespace:" + serviceNamespace + "is head-less. Search for endpoints instead.");
    }
    Integer portNumber = port.getPort();
    if (Strings.isNullOrBlank(clusterIP)) {
        IngressList ingresses = client.extensions().ingresses().inNamespace(serviceNamespace).list();
        if (ingresses != null) {
            List<Ingress> items = ingresses.getItems();
            if (items != null) {
                for (Ingress item : items) {
                    String ns = getNamespace(item);
                    if (Objects.equal(serviceNamespace, ns)) {
                        IngressSpec spec = item.getSpec();
                        if (spec != null) {
                            List<IngressRule> rules = spec.getRules();
                            List<IngressTLS> tls = spec.getTls();
                            if (rules != null) {
                                for (IngressRule rule : rules) {
                                    HTTPIngressRuleValue http = rule.getHttp();
                                    if (http != null) {
                                        List<HTTPIngressPath> paths = http.getPaths();
                                        if (paths != null) {
                                            for (HTTPIngressPath path : paths) {
                                                IngressBackend backend = path.getBackend();
                                                if (backend != null) {
                                                    String backendServiceName = backend.getServiceName();
                                                    if (serviceName.equals(backendServiceName) && portsMatch(port, backend.getServicePort())) {
                                                        String pathPostfix = path.getPath();
                                                        if (tls != null) {
                                                            for (IngressTLS tlsHost : tls) {
                                                                List<String> hosts = tlsHost.getHosts();
                                                                if (hosts != null) {
                                                                    for (String host : hosts) {
                                                                        if (Strings.isNotBlank(host)) {
                                                                            if (Strings.isNullOrBlank(pathPostfix)) {
                                                                                pathPostfix = "/";
                                                                            }
                                                                            return "https://" + URLUtils.pathJoin(host, pathPostfix);
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                        answer = rule.getHost();
                                                        if (Strings.isNotBlank(answer)) {
                                                            if (Strings.isNullOrBlank(pathPostfix)) {
                                                                pathPostfix = "/";
                                                            }
                                                            return "http://" + URLUtils.pathJoin(answer, pathPostfix);
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        // lets try use the status on GKE
        ServiceStatus status = srv.getStatus();
        if (status != null) {
            LoadBalancerStatus loadBalancerStatus = status.getLoadBalancer();
            if (loadBalancerStatus != null) {
                List<LoadBalancerIngress> loadBalancerIngresses = loadBalancerStatus.getIngress();
                if (loadBalancerIngresses != null) {
                    for (LoadBalancerIngress loadBalancerIngress : loadBalancerIngresses) {
                        String ip = loadBalancerIngress.getIp();
                        if (Strings.isNotBlank(ip)) {
                            clusterIP = ip;
                            break;
                        }
                    }
                }
            }
        }
    }
    if (Strings.isNullOrBlank(clusterIP)) {
        // on vanilla kubernetes we can use nodePort to access things externally
        boolean found = false;
        Integer nodePort = port.getNodePort();
        if (nodePort != null) {
            try {
                NodeList nodeList = client.nodes().list();
                if (nodeList != null) {
                    List<Node> items = nodeList.getItems();
                    if (items != null) {
                        for (Node item : items) {
                            NodeStatus status = item.getStatus();
                            if (!found && status != null) {
                                List<NodeAddress> addresses = status.getAddresses();
                                if (addresses != null) {
                                    for (NodeAddress address : addresses) {
                                        String ip = address.getAddress();
                                        if (Strings.isNotBlank(ip)) {
                                            clusterIP = ip;
                                            portNumber = nodePort;
                                            found = true;
                                            break;
                                        }
                                    }
                                }
                            }
                            if (!found) {
                                NodeSpec spec = item.getSpec();
                                if (spec != null) {
                                    clusterIP = spec.getExternalID();
                                    if (Strings.isNotBlank(clusterIP)) {
                                        portNumber = nodePort;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            } catch (Exception e) {
                // ignore could not find a node!
                LOG.warn("Could not find a node!: " + e, e);
            }
        }
    }
    return (serviceProto + "://" + clusterIP + ":" + portNumber).toLowerCase();
}
Also used : JsonNode(com.fasterxml.jackson.databind.JsonNode) ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) IngressList(io.fabric8.kubernetes.api.model.extensions.IngressList) HTTPIngressPath(io.fabric8.kubernetes.api.model.extensions.HTTPIngressPath) IngressSpec(io.fabric8.kubernetes.api.model.extensions.IngressSpec) IngressRule(io.fabric8.kubernetes.api.model.extensions.IngressRule) HTTPIngressRuleValue(io.fabric8.kubernetes.api.model.extensions.HTTPIngressRuleValue) Route(io.fabric8.openshift.api.model.Route) Ingress(io.fabric8.kubernetes.api.model.extensions.Ingress) SSLHandshakeException(javax.net.ssl.SSLHandshakeException) SSLException(javax.net.ssl.SSLException) TextParseException(org.xbill.DNS.TextParseException) IOException(java.io.IOException) UnknownHostException(java.net.UnknownHostException) ParseException(java.text.ParseException) KubernetesClientException(io.fabric8.kubernetes.client.KubernetesClientException) SSLProtocolException(javax.net.ssl.SSLProtocolException) SSLKeyException(javax.net.ssl.SSLKeyException) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) SSLPeerUnverifiedException(javax.net.ssl.SSLPeerUnverifiedException) DefaultOpenShiftClient(io.fabric8.openshift.client.DefaultOpenShiftClient) OpenShiftClient(io.fabric8.openshift.client.OpenShiftClient) IngressTLS(io.fabric8.kubernetes.api.model.extensions.IngressTLS) IngressBackend(io.fabric8.kubernetes.api.model.extensions.IngressBackend) KubernetesClientException(io.fabric8.kubernetes.client.KubernetesClientException)

Example 2 with NodeAddress

use of io.fabric8.kubernetes.api.model.NodeAddress in project ephemerals by LivePersonInc.

the class KubernetesDeploymentEndpointWaiter method getDeploymentEndpoint.

@Override
protected DeploymentEndpoints.Endpoint getDeploymentEndpoint() {
    String ip = null;
    int port = 0;
    String serviceType = kubernetesClient.services().withName(deployment.getId()).get().getSpec().getType();
    logger.debug("Kubernetes service type: " + serviceType);
    if (serviceType.equals("LoadBalancer")) {
        ip = kubernetesClient.services().withName(deployment.getId()).get().getStatus().getLoadBalancer().getIngress().get(0).getIp();
    } else {
        // nodeport
        List<ServicePort> servicePortList = kubernetesClient.services().withName(deployment.getId()).get().getSpec().getPorts();
        for (ServicePort servicePort : servicePortList) {
            if (servicePort.getPort().equals(deploymentPort.getPort())) {
                port = servicePort.getNodePort();
            }
        }
        /**
         * Fetch Node IP address:
         *  - External IP takes precedence over internal IP
         *  - If external IP isn't found, return internal IP
         *  - If both IPs not found, return null
         */
        // Since node port is shared across all nodes, use first node
        List<NodeAddress> nodeAddressList = kubernetesClient.nodes().list().getItems().get(0).getStatus().getAddresses();
        String nodeInternalIp = null, nodeExternalIp = null;
        for (NodeAddress nodeAddress : nodeAddressList) {
            if (nodeAddress.getType().equals("ExternalIP")) {
                nodeExternalIp = nodeAddress.getAddress();
            } else if (nodeAddress.getType().equals("InternalIP")) {
                nodeInternalIp = nodeAddress.getAddress();
            }
        }
        // External IP takes precedence over internal IP
        if (nodeExternalIp != null) {
            ip = nodeExternalIp;
            logger.debug("Using node ExternalIP: " + nodeExternalIp);
        } else if (nodeInternalIp != null) {
            ip = nodeInternalIp;
            logger.debug("Using node InternalIP: " + nodeInternalIp);
        }
    }
    if (ip == null) {
        logger.info("Endpoint not found");
        return null;
    } else {
        logger.info("Endpoint found...");
        logger.info(String.format("Checking connection to endpoint IP %s and port %d", ip, port));
        try (Socket socket = new Socket()) {
            socket.connect(new InetSocketAddress(ip, port), 2 * 1000);
            logger.info("Endpoint is reachable");
            endpoint = new DeploymentEndpoints.Endpoint(deploymentPort.getName(), ip, port);
            return endpoint;
        } catch (IOException e) {
            logger.warn("Endpoint is unreachable");
            // Either timeout or unreachable or failed DNS lookup.
            return null;
        }
    }
}
Also used : ServicePort(io.fabric8.kubernetes.api.model.ServicePort) DeploymentEndpoints(com.liveperson.ephemerals.deploy.DeploymentEndpoints) InetSocketAddress(java.net.InetSocketAddress) NodeAddress(io.fabric8.kubernetes.api.model.NodeAddress) IOException(java.io.IOException) Socket(java.net.Socket)

Example 3 with NodeAddress

use of io.fabric8.kubernetes.api.model.NodeAddress in project flink by apache.

the class Fabric8FlinkKubeClient method getLoadBalancerRestEndpoint.

private Optional<Endpoint> getLoadBalancerRestEndpoint(LoadBalancerStatus loadBalancer, int restPort) {
    boolean hasIngress = loadBalancer.getIngress() != null && !loadBalancer.getIngress().isEmpty();
    String address;
    if (hasIngress) {
        address = loadBalancer.getIngress().get(0).getIp();
        // Use hostname when the ip address is null
        if (address == null || address.isEmpty()) {
            address = loadBalancer.getIngress().get(0).getHostname();
        }
    } else {
        // Use node port. Node port is accessible on any node within kubernetes cluster. We'll
        // only consider IPs with the configured address type.
        address = internalClient.nodes().list().getItems().stream().flatMap(node -> node.getStatus().getAddresses().stream()).filter(nodeAddress -> nodePortAddressType.name().equals(nodeAddress.getType())).map(NodeAddress::getAddress).filter(ip -> !ip.isEmpty()).findAny().orElse(null);
        if (address == null) {
            LOG.warn("Unable to find any node ip with type [{}]. Please see [{}] config option for more details.", nodePortAddressType, KubernetesConfigOptions.REST_SERVICE_EXPOSED_NODE_PORT_ADDRESS_TYPE.key());
        }
    }
    boolean noAddress = address == null || address.isEmpty();
    return noAddress ? Optional.empty() : Optional.of(new Endpoint(address, restPort));
}
Also used : LoadBalancerStatus(io.fabric8.kubernetes.api.model.LoadBalancerStatus) IntOrString(io.fabric8.kubernetes.api.model.IntOrString) ServiceType(org.apache.flink.kubernetes.kubeclient.services.ServiceType) LoggerFactory(org.slf4j.LoggerFactory) ServicePort(io.fabric8.kubernetes.api.model.ServicePort) ExceptionUtils(org.apache.flink.util.ExceptionUtils) KubernetesService(org.apache.flink.kubernetes.kubeclient.resources.KubernetesService) KubernetesConfigMap(org.apache.flink.kubernetes.kubeclient.resources.KubernetesConfigMap) KubernetesPod(org.apache.flink.kubernetes.kubeclient.resources.KubernetesPod) NamespacedKubernetesClient(io.fabric8.kubernetes.client.NamespacedKubernetesClient) Map(java.util.Map) ExternalServiceDecorator(org.apache.flink.kubernetes.kubeclient.decorators.ExternalServiceDecorator) Preconditions.checkNotNull(org.apache.flink.util.Preconditions.checkNotNull) ServiceBuilder(io.fabric8.kubernetes.api.model.ServiceBuilder) KubernetesClientException(io.fabric8.kubernetes.client.KubernetesClientException) KubernetesUtils(org.apache.flink.kubernetes.utils.KubernetesUtils) KubernetesConfigOptions(org.apache.flink.kubernetes.configuration.KubernetesConfigOptions) CompletionException(java.util.concurrent.CompletionException) HasMetadata(io.fabric8.kubernetes.api.model.HasMetadata) Collectors(java.util.stream.Collectors) ExecutorUtils(org.apache.flink.util.ExecutorUtils) List(java.util.List) KubernetesException(org.apache.flink.kubernetes.kubeclient.resources.KubernetesException) Optional(java.util.Optional) PossibleInconsistentStateException(org.apache.flink.runtime.persistence.PossibleInconsistentStateException) Constants(org.apache.flink.kubernetes.utils.Constants) KubernetesPodsWatcher(org.apache.flink.kubernetes.kubeclient.resources.KubernetesPodsWatcher) CompletableFuture(java.util.concurrent.CompletableFuture) KubernetesWatch(org.apache.flink.kubernetes.kubeclient.resources.KubernetesWatch) OwnerReference(io.fabric8.kubernetes.api.model.OwnerReference) Function(java.util.function.Function) ArrayList(java.util.ArrayList) FutureUtils(org.apache.flink.util.concurrent.FutureUtils) KubernetesLeaderElectionConfiguration(org.apache.flink.kubernetes.configuration.KubernetesLeaderElectionConfiguration) KubernetesConfigMapSharedInformer(org.apache.flink.kubernetes.kubeclient.resources.KubernetesConfigMapSharedInformer) NodeAddress(io.fabric8.kubernetes.api.model.NodeAddress) Service(io.fabric8.kubernetes.api.model.Service) ExecutorService(java.util.concurrent.ExecutorService) InternalServiceDecorator(org.apache.flink.kubernetes.kubeclient.decorators.InternalServiceDecorator) Logger(org.slf4j.Logger) FlinkRuntimeException(org.apache.flink.util.FlinkRuntimeException) OwnerReferenceBuilder(io.fabric8.kubernetes.api.model.OwnerReferenceBuilder) Configuration(org.apache.flink.configuration.Configuration) Pod(io.fabric8.kubernetes.api.model.Pod) File(java.io.File) ConfigMap(io.fabric8.kubernetes.api.model.ConfigMap) TimeUnit(java.util.concurrent.TimeUnit) KubernetesLeaderElector(org.apache.flink.kubernetes.kubeclient.resources.KubernetesLeaderElector) Deployment(io.fabric8.kubernetes.api.model.apps.Deployment) Collections(java.util.Collections) NodeAddress(io.fabric8.kubernetes.api.model.NodeAddress) IntOrString(io.fabric8.kubernetes.api.model.IntOrString)

Aggregations

NodeAddress (io.fabric8.kubernetes.api.model.NodeAddress)2 ServicePort (io.fabric8.kubernetes.api.model.ServicePort)2 KubernetesClientException (io.fabric8.kubernetes.client.KubernetesClientException)2 IOException (java.io.IOException)2 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)1 JsonNode (com.fasterxml.jackson.databind.JsonNode)1 ArrayNode (com.fasterxml.jackson.databind.node.ArrayNode)1 ObjectNode (com.fasterxml.jackson.databind.node.ObjectNode)1 DeploymentEndpoints (com.liveperson.ephemerals.deploy.DeploymentEndpoints)1 ConfigMap (io.fabric8.kubernetes.api.model.ConfigMap)1 HasMetadata (io.fabric8.kubernetes.api.model.HasMetadata)1 IntOrString (io.fabric8.kubernetes.api.model.IntOrString)1 LoadBalancerStatus (io.fabric8.kubernetes.api.model.LoadBalancerStatus)1 OwnerReference (io.fabric8.kubernetes.api.model.OwnerReference)1 OwnerReferenceBuilder (io.fabric8.kubernetes.api.model.OwnerReferenceBuilder)1 Pod (io.fabric8.kubernetes.api.model.Pod)1 Service (io.fabric8.kubernetes.api.model.Service)1 ServiceBuilder (io.fabric8.kubernetes.api.model.ServiceBuilder)1 Deployment (io.fabric8.kubernetes.api.model.apps.Deployment)1 HTTPIngressPath (io.fabric8.kubernetes.api.model.extensions.HTTPIngressPath)1