javax.ws.rs.WebApplicationException: HTTP 404 服务器找不到请求的资源

javax.ws.rs.WebApplicationException: HTTP 404 the server could not find the requested resource

我一直在使用 fabric8 的 Java Kubernetes Client API 构建一个创建 Kubernetes 复制控制器的应用程序,如下所示。

import io.fabric8.kubernetes.api.KubernetesClient;
import io.fabric8.kubernetes.api.KubernetesFactory;
import io.fabric8.kubernetes.api.model.*;
import io.fabric8.kubernetes.api.model.resource.Quantity;
import io.fabric8.kubernetes.client.KubernetesClientException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.stratos.kubernetes.client.interfaces.ReplicationControllerClientAPIInterface;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ReplicationControllerClientAPI implements ReplicationControllerClientAPIInterface {

    private final KubernetesClient kubernetesClient;

    private static final Log LOG = LogFactory.getLog(ReplicationControllerClientAPI.class);

    public ReplicationControllerClientAPI(String endpointURL) {
        kubernetesClient = new KubernetesClient(new KubernetesFactory(endpointURL));
        System.out.println(endpointURL);
    }

    public void createReplicationController(String replicationControllerID, String selectorLabel,
            int replicas, String containerName, String dockerImage, int cpu, int memory,
            List<ContainerPort> ports) throws KubernetesClientException {

        try {
            int memoryInMB = 1024 * 1024 * memory;
            if (LOG.isDebugEnabled()) {
                LOG.debug(String.format("Creating kubernetes replication-controller: [rc-id] %s "
                                + "[container-name] %s [docker-image] %s "
                                + "[cpu] %d [memory] %d MB [ports] %s",
                        replicationControllerID, containerName, dockerImage, cpu, memoryInMB, ports));
            }

            // Create replication-controller definition
            ReplicationController replicationController = new ReplicationController();

            replicationController.setApiVersion(ReplicationController.ApiVersion.V_1);
            replicationController.setKind(KubernetesConstantsExtended.KIND_REPLICATION_CONTROLLER);

            ObjectMeta replicationControllerMetaData = new ObjectMeta();
            replicationControllerMetaData.setName(replicationControllerID);
            replicationController.setMetadata(replicationControllerMetaData);

            ReplicationControllerSpec replicationControllerSpec = new ReplicationControllerSpec();
            replicationControllerSpec.setReplicas(replicas);

            // Setup label selectors for the replication controller
            Map<String, String> selectors = new HashMap<String, String>();
            selectors.put(KubernetesConstantsExtended.LABEL_NAME_REPLICATION_CONTROLLER, selectorLabel);
            replicationControllerSpec.setSelector(selectors);

            PodTemplateSpec podTemplateSpec = new PodTemplateSpec();

            ObjectMeta podMetaData = new ObjectMeta();
            podMetaData.setLabels(selectors);
            podTemplateSpec.setMetadata(podMetaData);

            PodSpec podSpec = new PodSpec();

            List<Container> containers = new ArrayList<Container>();
            // Create container definition
            Container container = new Container();
            container.setName(containerName);
            container.setImage(dockerImage);
            // Set resource limits
            ResourceRequirements resources = new ResourceRequirements();
            Map<String, Quantity> limits = new HashMap<String, Quantity>();
            limits.put(KubernetesConstants.RESOURCE_CPU, new Quantity(String.valueOf(cpu)));
            limits.put(KubernetesConstants.RESOURCE_MEMORY, new Quantity(String.valueOf(memoryInMB)));
            resources.setLimits(limits);
            container.setResources(resources);
            // Add container definition to the list of containers
            containers.add(container);

            podSpec.setContainers(containers);

            // Add Pod Spec to the Pod Template Spec
            podTemplateSpec.setSpec(podSpec);
            // Add Pod Template Spec to the ReplicationController Spec
            replicationControllerSpec.setTemplate(podTemplateSpec);
            // Add Replication Controller Spec to the Replication Controller instance
            replicationController.setSpec(replicationControllerSpec);

            // Create the replication-controller
            kubernetesClient.createReplicationController(replicationController);
        } catch (Exception e) {
            String message = String.format("Could not create kubernetes replication-controller: "
                    + "[rc-id] %s", replicationControllerID);
            LOG.error(message, e);
            throw new KubernetesClientException(message, e);
        }
    }

    public ReplicationController getReplicationController(String replicationControllerID)
            throws KubernetesClientException {
        try {
            return kubernetesClient.getReplicationController(replicationControllerID);
        } catch (Exception e) {
            String message = String.format("Could not retrieve kubernetes replication-controller"
                    + ": [rc-id] %s", replicationControllerID);
            LOG.error(message, e);
            throw new KubernetesClientException(message, e);
        }
    }

    public ReplicationControllerList getReplicationControllers()
            throws KubernetesClientException {
        try {
            return kubernetesClient.getReplicationControllers();
        } catch (Exception e) {
            String message = String.format("Could not retrieve kubernetes replication-controllers");
            LOG.error(message, e);
            throw new KubernetesClientException(message, e);
        }
    }

    public void deleteReplicationController(String replicationControllerID)
            throws KubernetesClientException {
        try {
            kubernetesClient.deleteReplicationController(replicationControllerID);
        } catch (Exception e) {
            String message = String.format("Could not delete kubernetes replication-controller"
                    + ": [rc-id] %s", replicationControllerID);
            LOG.error(message, e);
            throw new KubernetesClientException(message, e);
        }
    }
}

当我执行上面的代码时,我发现应用程序抛出了以下异常。

javax.ws.rs.WebApplicationException: HTTP 404 the server could not find the requested resource
    at io.fabric8.kubernetes.api.ExceptionResponseMapper.fromResponse(ExceptionResponseMapper.java:44)
    at io.fabric8.kubernetes.api.ExceptionResponseMapper.fromResponse(ExceptionResponseMapper.java:35)
    at org.apache.cxf.jaxrs.client.ClientProxyImpl.checkResponse(ClientProxyImpl.java:302)
    at org.apache.cxf.jaxrs.client.ClientProxyImpl.handleResponse(ClientProxyImpl.java:725)
    at org.apache.cxf.jaxrs.client.ClientProxyImpl.doChainedInvocation(ClientProxyImpl.java:683)
    at org.apache.cxf.jaxrs.client.ClientProxyImpl.invoke(ClientProxyImpl.java:224)
    at com.sun.proxy.$Proxy18.createReplicationController(Unknown Source)
    at io.fabric8.kubernetes.api.KubernetesClient.createReplicationController(KubernetesClient.java:460)
    at io.fabric8.kubernetes.api.KubernetesClient.createReplicationController(KubernetesClient.java:450)
    at org.apache.stratos.kubernetes.client.ReplicationControllerClientAPI.createReplicationController(ReplicationControllerClientAPI.java:108)
    at org.apache.stratos.kubernetes.client.ReplicationControllerTestSuite.createReplicationController(ReplicationControllerTestSuite.java:44)
    at org.apache.stratos.kubernetes.client.ReplicationControllerTestExecutor.main(ReplicationControllerTestExecutor.java:22)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

Exception in thread "main" io.fabric8.kubernetes.client.KubernetesClientException: Could not create kubernetes replication-controller: [rc-id] helloworldrc
    at org.apache.stratos.kubernetes.client.ReplicationControllerClientAPI.createReplicationController(ReplicationControllerClientAPI.java:113)
    at org.apache.stratos.kubernetes.client.ReplicationControllerTestSuite.createReplicationController(ReplicationControllerTestSuite.java:44)
    at org.apache.stratos.kubernetes.client.ReplicationControllerTestExecutor.main(ReplicationControllerTestExecutor.java:22)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: javax.ws.rs.WebApplicationException: HTTP 404 the server could not find the requested resource
    at io.fabric8.kubernetes.api.ExceptionResponseMapper.fromResponse(ExceptionResponseMapper.java:44)
    at io.fabric8.kubernetes.api.ExceptionResponseMapper.fromResponse(ExceptionResponseMapper.java:35)
    at org.apache.cxf.jaxrs.client.ClientProxyImpl.checkResponse(ClientProxyImpl.java:302)
    at org.apache.cxf.jaxrs.client.ClientProxyImpl.handleResponse(ClientProxyImpl.java:725)
    at org.apache.cxf.jaxrs.client.ClientProxyImpl.doChainedInvocation(ClientProxyImpl.java:683)
    at org.apache.cxf.jaxrs.client.ClientProxyImpl.invoke(ClientProxyImpl.java:224)
    at com.sun.proxy.$Proxy18.createReplicationController(Unknown Source)
    at io.fabric8.kubernetes.api.KubernetesClient.createReplicationController(KubernetesClient.java:460)
    at io.fabric8.kubernetes.api.KubernetesClient.createReplicationController(KubernetesClient.java:450)
    at org.apache.stratos.kubernetes.client.ReplicationControllerClientAPI.createReplicationController(ReplicationControllerClientAPI.java:108)
    ... 7 more

Process finished with exit code 1

我已经通过 Docker 将 KubernetesClient 的端点 URL 设置为 http://127.0.0.1:8080,因为我是 运行 Kubernetes,出于测试目的。我关注了之前几篇与类似问题相关的帖子,但其中 none 似乎在这种情况下对我有所帮助。

我在 .bashrc 中设置了以下环境变量。

export KUBERNETES_SERVICE_HOST=127.0.0.1
export KUBERNETES_SERVICE_PORT=8080

以下代码示例用于在我的应用程序中设置 KubernetesClient。

private final ReplicationControllerClientAPIInterface REPLICATION_CONTROLLER_CLIENT;

    public ReplicationControllerTestSuite() {
        REPLICATION_CONTROLLER_CLIENT = new ReplicationControllerClientAPI("http://"
                + ReplicationControllerTestConstants.KUBERNETES_SERVICE_HOST + ":"
                + ReplicationControllerTestConstants.KUBERNETES_SERVICE_PORT);

//        REPLICATION_CONTROLLER_CLIENT = new ReplicationControllerClientAPI("http://localhost:8080");
    }

    public void createReplicationController(int replicas) {
        List<ContainerPort> exposedPorts = new ArrayList<ContainerPort>();
        ContainerPort port = new ContainerPort();
        port.setContainerPort(ReplicationControllerTestConstants.EXPOSED_PORT);
        exposedPorts.add(port);

        REPLICATION_CONTROLLER_CLIENT.createReplicationController(
                ReplicationControllerTestConstants.REPLICATION_CONTROLLER_ID, ReplicationControllerTestConstants.SELECTOR_LABEL,
                replicas, ReplicationControllerTestConstants.CONTAINER_NAME, ReplicationControllerTestConstants.DEFAULT_DOCKER_IMAGE,
                ReplicationControllerTestConstants.CPU_CORES, ReplicationControllerTestConstants.MEMORY_ALLOCATION, exposedPorts);
    }

上述代码中的常量指的是:

    protected static final String KUBERNETES_SERVICE_HOST = "127.0.0.1";
    protected static final String KUBERNETES_SERVICE_PORT = "8080";
    protected static final String SELECTOR_LABEL = "helloworld";
    protected static final String REPLICATION_CONTROLLER_ID = "helloworldrc";
    // Container specific
    protected static final String DEFAULT_DOCKER_IMAGE = "helloworld";
    protected static final String CONTAINER_NAME = "helloworld";
    protected static final int CPU_CORES = 1;
    protected static final int MEMORY_ALLOCATION = 512;
    protected static final int EXPOSED_PORT = 8080;

非常感谢有关此问题的任何帮助,因为我对 REST API 和 Kubernetes 的了解有限。

有一个重写的 fabric8 kubernetes 客户端版本,依赖更少,DSL 流畅,监视支持得到改进。它在 https://github.com/fabric8io/kubernetes-client 的单独回购中,Maven 中心可用的工件使用以下依赖项:

<dependency>
  <groupId>io.fabric8</groupId>
  <artifactId>kubernetes-client</artifactId>
  <version>1.3.6</version>
</dependency>

请注意,经常发布更新,但截至目前 API 已稳定并可用于生产。

创建复制控制器的 example 如下所示:

Config config = new ConfigBuilder().withMasterUrl(master).build();

try (final KubernetesClient client = new DefaultKubernetesClient(config)) {

    client.replicationControllers().inNamespace("thisisatest").createNew()
        .withNewMetadata().withName("nginx2-controller").addToLabels("server", "nginx").endMetadata()
        .withNewSpec().withReplicas(0)
        .withNewTemplate()
        .withNewMetadata().addToLabels("server", "nginx2").endMetadata()
        .withNewSpec()
        .addNewContainer().withName("nginx").withImage("nginx")
        .addNewPort().withContainerPort(80).endPort()
        .endContainer()
        .endSpec()
        .endTemplate()
        .endSpec().done();

} catch (Exception e) {
  e.printStackTrace();
  logger.error(e.getMessage(), e);
}

客户端可通过配置构建器进行高度配置,涵盖所有核心 Kubernetes 类型以及 OpenShift 3 扩展。

更新:根据你自己的回复,我已经提出了一个 JIRA 与 Stratos 项目迁移到新客户端 - 他们目前正在对旧客户端进行某种重新打包 &这可能是导致您出现问题的原因。见 issues.apache.org/jira/browse/STRATOS-1524

我设法通过避免使用 https://github.com/apache/stratos 来解决上述问题,这是我在代码中使用的一个依赖项。我打算在我的代码中使用它已经创建的功能,例如 KubernetesClientException,但由于这种依赖性,上述问题似乎会弹出。

但是,我不完全确定特定问题背后的原因。