Kubernetes

Fabric8操作Kubernetes(三)

2020-11-10  本文已影响0人  王勇1024

Fetching Metrics

Kubernetes Client also supports fetching metrics from API server if metrics are enabled on it. You can access metrics via client.top(). Here are some examples of its usage:

NodeMetricsList nodeMetricList = client.top().nodes().metrics();

NodeMetrics nodeMetric = client.top().nodes().metrics("minikube");

PodMetricsList podMetricsList = client.top().pods().metrics();

PodMetricsList podMetricsList = client.top().pods().metrics("default");

PodMetrics podMetrics = client.top().pods().metrics("default", "nginx-pod");

Resource API

Kubernetes Client also offers a generic API to handle different kind of Kubernetes resources. Most of the Kubernetes resources in Kubernetes Model are extending a class named HasMetadata. Resource API can work with any kind of Kubernetes Resource which extends this class. Here are some examples it it's usage:

Pod pod = client.resource(pod1).inNamespace("default").get();

Pod pod1 = new PodBuilder()
  .withNewMetadata().withName("resource-pod-" + RandomStringUtils.randomAlphanumeric(6).toLowerCase(Locale.ROOT)).endMetadata()
  .withNewSpec()
  .addNewContainer().withName("nginx").withImage("nginx").endContainer()
  .endSpec()
  .build();

client.resource(pod1).inNamespace("default").createOrReplace();

Pod p = client.resource(pod1).createOrReplaceAnd().waitUntilReady(10, TimeUnit.SECONDS);

Boolean isDeleted = client.resource(pod1).inNamespace("default").delete();

ResourceList API

Just like generic Kubernetes Resource API, Kubernetes client also provides a generic API to deal with Kubernetes List. Here are some examples of its usage:

Service service =  new ServiceBuilder()
  .withNewMetadata().withName("my-service").endMetadata()
  .withNewSpec()
  .addToSelector("app", "Myapp")
  .addNewPort().withProtocol("TCP").withPort(80).withTargetPort(new IntOrString(9376)).endPort()
  .endSpec()
  .build();

ConfigMap configMap = new ConfigMapBuilder()
  .withNewMetadata().withName("my-configmap").endMetadata()
  .addToData(Collections.singletonMap("app", "Myapp"))
  .build();

KubernetesList list = new KubernetesListBuilder().withItems(deployment, service, configMap).build();

// Create them for the first time
client.resourceList(list).inNamespace("default").createOrReplace();

KubernetesList list = new KubernetesListBuilder().withItems(updatedService, updatedConfigMap).build();
client.resourceList(list).inNamespace("default").deletingExisting().createOrReplace();

Boolean deleted = client.resourceList(new PodListBuilder().withItems(pod1, pod2, pod3).build()).inNamespace("default").delete();

CustomResourceDefinition

CustomResourceDefinition which are like templates for CustomResource objects in Kubernetes API are available in Kubernetes Client API via client.customResourceDefinitions(). Here are some examples of it's common usage:

CustomResourceDefinition customResourceDefinition = client.customResourceDefinitions().load(new FileInputStream("/sparkapplication-crd.yml")).get();

CustomResourceDefinition crd = client.customResourceDefinitions().withName("sparkclusters.radanalytics.io").get();


CustomResourceDefinition customResourceDefinition = new CustomResourceDefinitionBuilder()
      .withApiVersion("apiextensions.k8s.io/v1beta1")
      .withNewMetadata().withName("sparkclusters.radanalytics.io")
      .endMetadata()
      .withNewSpec()
      .withNewNames()
      .withKind("SparkCluster")
      .withPlural("sparkclusters")
      .endNames()
      .withGroup("radanalytics.io")
      .withVersion("v1")
      .withScope("Namespaced")
      .withNewValidation()
      .withNewOpenAPIV3SchemaLike(readSchema())
      .endOpenAPIV3Schema()
      .endValidation()
      .endSpec()
      .build();

CustomResourceDefinition crd = client.customResourceDefinitions().createOrReplace(customResourceDefinition);

CustomResourceDefinition crd = client.customResourceDefinitions().createOrReplace(customResourceDefinition);

CustomResourceDefinitionList crdList = client.customResourceDefinitions().list();

Boolean deleted = client.customResourceDefinitions().withName("sparkclusters.radanalytics.io").delete();

CustomResource Typed API

CustomResources are available in Kubernetes API via the client.customResources(...). In order to use typed API, you need to provide POJOs for your Custom Resource which client can use for serialization/deserialization. client.customResources(...) take things like CustomResourceDefinitionContext for locating the CustomResources, CustomResource class, it's list class etc. It returns an instance of a client which you can use for your CustomResource related operations. In order to get some idea of how POJOs should look like. Here's an example of POJO for CronTab CustomResource specified in Kubernetes CustomResource docs my-crontab.yml

apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
  name: my-new-cron-object
spec:
  cronSpec: "* * * * */5"
  image: my-awesome-cron-image

For a CustomResource like this one, we should have a CronTab java class like this:

Note: Please make sure that your CustomResource POJO is implementing Namespaced interface if it's a namespaced resource. Otherwise it would be considered a Cluster scoped resource.

/**
 * Copyright (C) 2015 Red Hat, Inc.
 *
 * Licensed 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.kubernetes.client.mock.crd;

import io.fabric8.kubernetes.api.model.Namespaced;
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.kubernetes.client.CustomResource;

public class CronTab extends CustomResource implements Namespaced {
    private CronTabSpec spec;
    private CronTabStatus status;

    @Override
    public ObjectMeta getMetadata() {
        return super.getMetadata();
    }

    public CronTabSpec getSpec() {
        return spec;
    }

    public void setSpec(CronTabSpec spec) {
        this.spec = spec;
    }

    public CronTabStatus getStatus() {
        return status;
    }

    public void setStatus(CronTabStatus status) {
        this.status = status;
    }

    @Override
    public String getApiVersion() {
        return "stable.example.com/v1";
    }

    @Override
    public String toString() {
        return "CronTab{"+
                "apiVersion='" + getApiVersion() + "'" +
                ", metadata=" + getMetadata() +
                ", spec=" + spec +
                ", status=" + status +
                "}";
    }
}

You can find other helper classes related to CronTab in our tests. For now, we can proceed with it's common usage examples:

// Alternatively use CustomResourceDefinitionContext.fromCrd(crd) if you already have a CustomResourceDefinition
CustomResourceDefinitionContext context = new CustomResourceDefinitionContext.Builder()
      .withGroup("stable.example.com)
      .withVersion("v1")
      .withScope("Namespaced")
      .withName("crontabs.stable.example.com)
      .withPlural("crontabs")
      .withKind("CronTab")
      .build()
MixedOperation<CronTab, CronTabList, DoneableCronTab, Resource<CronTab, DoneableCronTab>> cronTabClient = client
  .customResources(cronTabCrd, CronTab.class, CronTabList.class, DoneableCronTab.class);

KubernetesDeserializer.registerCustomKind("stable.example.com/v1", "CronTab", CronTab.class);

CronTab ct = cronTabClient.inNamespace("default").withName("my-second-cron-object").get();

cronTabClient.inNamespace("default").create(cronTab1);

CronTabList cronTabList = cronTabClient.inNamespace("default").list();

Boolean isDeleted = cronTabClient.inNamespace("default").withName("my-third-cron-object").delete();

cronTabClient.inNamespace("default").updateStatus(updatedCronTab);

cronTabClient.inNamespace("default").watch(new Watcher<CronTab>() {
  @Override
  public void eventReceived(Action action, CronTab resource) {
    // Do something depending upon action type
  }

  @Override
  public void onClose(KubernetesClientException cause) {

  }
});

CustomResource Typeless API

Although, you should be using Typed API since it's type-safe. But it can get a bit compilcated to maintain your CustomResource POJOs and sometimes people don't even have them. Kubernetes Client also provides a typeless/raw API to handle your CustomResource objects in form of HashMaps. In order to use it, you need to provide it with a CustomResourceDefinitionContext, which carries necessary information about CustomResource. Here is an example on how to create one:

CustomResourceDefinitionContext customResourceDefinitionContext = new CustomResourceDefinitionContext.Builder()
      .withName("animals.jungle.example.com")
      .withGroup("jungle.example.com")
      .withVersion("v1")
      .withPlural("animals")
      .withScope("Namespaced")
      .build();

Once you have built it, you can pass it to typeless DSL as argument client.customResource(customResourceDefinitionContext). With this in place, you can do your standard CustomResource operations, but you would have to deal with Serialization/Deserialization part yourself. You can convert HashMap to some JSON object using JSON parsing libraries available on internet.

Map<String, Object> customResource = client.customResource(crdContext).load(new FileInputStream("cr.yaml"));

Map<String, Object> customResourceObject = client.customResource(customResourceDefinitionContext).get(currentNamespace, "otter");

// Create via file
Map<String, Object> object = client.customResource(customResourceDefinitionContext).create(currentNamespace, new FileInputStream("test-rawcustomresource.yml"));

// Create via raw JSON string

String rawJsonCustomResourceObj = "{\"apiVersion\":\"jungle.example.com/v1\"," +
  "\"kind\":\"Animal\",\"metadata\": {\"name\": \"walrus\"}," +
  "\"spec\": {\"image\": \"my-awesome-walrus-image\"}}";
Map<String, Object> object = client.customResource(customResourceDefinitionContext).create(currentNamespace, rawJsonCustomResourceObj);

Map<String, Object> list = client.customResource(customResourceDefinitionContext).list(currentNamespace);

Map<String, Object> list = client.customResource(customResourceDefinitionContext).list(currentNamespace, Collections.singletonMap("foo", "bar"));

Map<String, Object> object = client.customResource(customResourceDefinitionContext).get(currentNamespace, "walrus");
((HashMap<String, Object>)object.get("spec")).put("image", "my-updated-awesome-walrus-image");
object = client.customResource(customResourceDefinitionContext).edit(currentNamespace, "walrus", new ObjectMapper().writeValueAsString(object));

client.customResource(customResourceDefinitionContext).delete(currentNamespace, "otter");

Map<String, Object> result = client.customResource(customResourceDefinitionContext).updateStatus("ns1", "example-hello", objectAsJsonString);


  final CountDownLatch closeLatch = new CountDownLatch(1);
  client.customResource(crdContext).watch(namespace, new Watcher<String>() {
    @Override
    public void eventReceived(Action action, String resource) {
      logger.info("{}: {}", action, resource);
    }

    @Override
    public void onClose(KubernetesClientException e) {
      logger.debug("Watcher onClose");
      closeLatch.countDown();
      if (e != null) {
        logger.error(e.getMessage(), e);
      }
    }
  });
  closeLatch.await(10, TimeUnit.MINUTES);

CertificateSigningRequest

Kubernetes Client provides using CertificateSigningRequest via the client.certificateSigningRequests() DSL interface. Here is an example of creating CertificateSigningRequest using Fabric8 Kubernetes Client:

try (KubernetesClient client = new DefaultKubernetesClient()) {
    CertificateSigningRequest csr = new CertificateSigningRequestBuilder()
            .withNewMetadata().withName("test-k8s-csr").endMetadata()
            .withNewSpec()
            .addNewGroup("system:authenticated")
            .withRequest("LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJRWJqQ0NBbFlDQVFBd0tURVBNQTBHQTFVRUF3d0dhMmxrYjI1bk1SWXdGQVlEVlFRS0RBMWtZWFJoTFdWdQpaMmx1WldWeU1JSUNJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBZzhBTUlJQ0NnS0NBZ0VBc2dVZXl0S0F6ZDkyClN1S2pZL1RqbmRsZ0lkSFVVYWFxbHJIVW1nbTloKzY2RTJCNGs0TSt6Q0tOQmovemlMdWV6NFNUeHJ6SFk3RlUKNGUxWElBU3lMS0dmRGNPaks5NThURThwcXBRM21VdlpWMmxnK25BTVF5dlZUYWdZSmFId2JWUzVlNHgvRmpKcQoxTWpQZ1VoSGFXeEdIYTQrQnZYQU9Kdk5BdnV4alpZaVJET251dGxHVzloQkRKRlhoUk5jOGFKNnFiZWVBWnNiCmozWUFMaUcydWp1VmhoTUVRNEJxdFVHVGZCMzBQNGhRK2t2bWVKc2ZUU3Vsb2xiWFdIdVZGWnh1d0FJek5RbmQKMTd4VHd2cU04OGZFb3ZJazBJV0ZCWTk2aHRvaUVNdThZUms4SEZ6QkJralhsZGlkbVNNSHkwK0plcFRONmdQTQpEYVVsd1cxS0lCcW9TbnZNcjY4cFRVWEVhZVRjc040anMxTUIwK3FwR0JBS1puWWVxM0JmMkxVVFBNaG1VZ2VVCmFUTFlqODI2WVorZjJrOWJ1cngwK1NOSmVZbWoxVTl0N3A2YWM0dDIzZHVYQ1BzYkNrUFNKeGtrU3dudUlVVzkKdmJVVGtJNGtVMlFVMnE0NzRaMW1uMlkvejF2TEdQdEpsTDFYUVFVNEdsb2hrQkVkM1BsUTRtOGU1WGZSRkV6ZgpYZnhMRXFRczFTeEg1ekhjcnVaOWxJdnBkeEw5Tkc5WlR6M0tmT0tIbCtSUzdxMGdKaExac0RubUJKNXZab3p4CldXci9IRW9PamFYbGh0VitDN3M4TUg5Y0lKZENZNnpjcFVrZis1NmZ0Z1FuN0YrT1RYdDI0UVJQYWNFZnRFOTkKVERPb2luTGtOMm1kckxiMTgxQUZNUWJ0bTFLc1k2MENBd0VBQWFBQU1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQwpBUUNQYU1WdDd4YWhkZlF1L1BySFVTTW5LK2I0SlJScEdEYlpWUXk4aUtkSmdHM0VrYnNBZ21qQmN4Q1IvL2t1CkVhU0plSGNWK20xVlFUTEp1ZFU3ZHFUeFBLOVFCNlB2aHlBbCttNnFaQkt1Q25VM1BKc2k5azBYSE5GWXBqRmYKVFNwTlpJSnRuanVEQWVtT05kcjJYMm1rODZmSmpWTEUvYnA1KzM5dFBkN0xjL3dZR2JoRU0xcExtUGpQK0Z6eQpzZnBiYW5PcmZFSG5NMmlsRFpGZURVSEpYL3F5Ykt1RC9BRmdoZk1Ua0x3ODNLNkNRdCtDQm05djRCeEtCS2xqCkdBWEQyUEhUTWlzektUbGpBM3czYUphanZzU0FwQXFCWnFocjB3QzdOb1dYM1h6S0p3ck9MaWVxemo3SXlpUGEKTEI5SmJveFpOQTdBSU5ucEdsa1hDZlRGT2RManZtQkVRQXV5Ym9wLzdqV2RiSzJHRkZKS2UwdlVlbWNUeGdHVwp5c0ZyV2pqMUlvdVBVNFZ6ck82QVBVQnZCZUFtdU1Bbm9yVng5emc4akhlT1pkd2RWdFRnOUwrK0VnWjlxK0htCjVtUlJGVHlZOWo4WVVvd2J6TzRlRUZnaVN0di84T1p0YmtOeDFROWFQWHJ3VUV1Q1I0SUthWG0wNlJUYXJOYXUKTWFsbk5oZm9WYi9Bc1R5d1ArNlc1dGErcTBpckR5cnVkZk5pRkFWbkRMZEU5a2hWZzVrU0lPRzhYbEZUMklwSQpkdVNpcUl0NlNUTlY3UmdaRzBGTFN5akxoc3laWnY2bitpUzl3Ky9OOFpoUzgvalViUUVidG1VTnNJU3Z5WS9JCmZqcHNZQUdleExvVW5mN2pDaUhkbTVhSnJ5SU1kdmZ2akJsMDhIVk5nWG1McVE9PQotLS0tLUVORCBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0K")
            .addNewUsage("client auth")
            .endSpec()
            .build();

    client.certificateSigningRequests().create(csr);
}

SharedInformers

Kubernetes Client also provides SharedInformer support in order to stay updated to events happening to your resource inside Kubernetes. It's implementation is just list and watch operations after a certain interval of time. Here are some of the common usages:

SharedInformerFactory sharedInformerFactory = client.informers();

SharedIndexInformer<Pod> podInformer = sharedInformerFactory.sharedIndexInformerFor(Pod.class, PodList.class, 30 * 1000L);
podInformer.addEventHandler(new ResourceEventHandler<Pod>() {
  @Override
  public void onAdd(Pod pod) {
    logger.info("{} pod added", pod.getMetadata().getName());
  }

  @Override
  public void onUpdate(Pod oldPod, Pod newPod) {
    logger.info("{} pod updated", oldPod.getMetadata().getName());
  }

  @Override
  public void onDelete(Pod pod, boolean deletedFinalStateUnknown) {
    logger.info("{} pod deleted", pod.getMetadata().getName());
  }
});

CustomResourceDefinitionContext crdContext = new CustomResourceDefinitionContext.Builder()
    .withVersion("v1")
    .withScope("Namespaced")
    .withGroup("demo.fabric8.io")
    .withPlural("dummies")
    .build();
SharedIndexInformer<Dummy> dummyInformer = sharedInformerFactory.sharedIndexInformerForCustomResource(crdContext, Dummy.class, DummyList.class, 1 * 60 * 1000);
dummyInformer.addEventHandler(new ResourceEventHandler<Dummy>() {
  @Override
  public void onAdd(Dummy dummy) {
    System.out.printf("%s dummy added\n", dummy.getMetadata().getName());
  }

  @Override
  public void onUpdate(Dummy oldDummy, Dummy newDummy) {
    System.out.printf("%s dummy updated\n", oldDummy.getMetadata().getName());
  }

  @Override
  public void onDelete(Dummy dummy, boolean deletedFinalStateUnknown) {
    System.out.printf("%s dummy deleted \n", dummy.getMetadata().getName());
  }
});

SharedInformerFactory sharedInformerFactory = client.informers();
SharedIndexInformer<Pod> podInformer = sharedInformerFactory.sharedIndexInformerFor(
        Pod.class,
        PodList.class,
        new OperationContext().withNamespace("default"),
        30 * 1000L);
logger.info("Informer factory initialized.");

podInformer.addEventHandler(new ResourceEventHandler<Pod>() {
    @Override
    public void onAdd(Pod pod) {
        logger.info("Pod " + pod.getMetadata().getName() + " got added");
    }

    @Override
    public void onUpdate(Pod oldPod, Pod newPod) {
        logger.info("Pod " + oldPod.getMetadata().getName() + " got updated");
    }

    @Override
    public void onDelete(Pod pod, boolean deletedFinalStateUnknown) {
        logger.info("Pod " + pod.getMetadata().getName() + " got deleted");
    }
});

CustomResourceDefinitionContext crdContext = new CustomResourceDefinitionContext.Builder()
    .withVersion("v1")
    .withScope("Namespaced")
    .withGroup("demo.fabric8.io")
    .withPlural("dummies")
    .build();
SharedIndexInformer<Dummy> dummyInformer = sharedInformerFactory.sharedIndexInformerForCustomResource(crdContext,
    Dummy.class,
    DummyList.class,
    new OperationContext().withNamespace("default"), // Namespace to watch
    1 * 60 * 1000);
dummyInformer.addEventHandler(new ResourceEventHandler<Dummy>() {
  @Override
  public void onAdd(Dummy dummy) {
    System.out.printf("%s dummy added\n", dummy.getMetadata().getName());
  }

  @Override
  public void onUpdate(Dummy oldDummy, Dummy newDummy) {
    System.out.printf("%s dummy updated\n", oldDummy.getMetadata().getName());
  }

  @Override
  public void onDelete(Dummy dummy, boolean deletedFinalStateUnknown) {
    System.out.printf("%s dummy deleted \n", dummy.getMetadata().getName());
  }
});

sharedInformerFactory.startAllRegisteredInformers();

sharedInformerFactory.stopAllRegisteredInformers();

List Options

There are various options provided by Kubernetes Client API when it comes to listing resources. Here are some of the common examples provided:

PodList podList = client.pods().inNamespace("myproject").list(5, null);

podList = client.pods().inNamespace("myproject").list(5, podList.getMetadata().getContinue());

PodList podList = client.pods().inNamespace("default").withLabel("foo", "bar").list();

PodList podList = client.pods().inNamespace("default").withLabels(Collections.singletonMap("foo", "bar")).list();

PodList podList = client.pods().inNamespace("default").withoutLabel("foo", "bar").list();

PodList podList = client.pods().inNamespace("default").withoutLabels(Collections.singletonMap("foo", "bar")).list();

PodList podList = client.pods().inNamespace("default").withLabelIn("foo", "bar").list();

PodList podList =client.pods().inNamespace("default").withLabelNotIn("foo", "bar").list();

PodList podList = client.pods().inNamespace("default").withField("foo", "bar").list();

PodList podList = client.pods().inNamespace("default").withFields(Collections.singletonMap("foo", "bar")).list();

PodList podList = client.pods().inNamespace("default").withoutField("foo", "bar").list();

PodList podList = client.pods().inNamespace("default").withoutFields(Collections.singletonMap("foo", "bar")).list();

PodList podList = client.pods().inNamespace("default").list(new ListOptionsBuilder()
  .withLimit(1L)
  .withContinue(null)
  .build());

Delete Options

Kubernetes Client also provides way to delete dependents of some Kubernetes resource. Here are some examples:

Boolean isDeleted = client.apps().deployments().inNamespace("default").withName("nginx-deploy").cascading(true).delete();

Boolean isDeleted = client.apps().deployments().inNamespace("default").withName("nginx-deploy").withPropagationPolicy("Foreground").delete();

Boolean isDeleted = client.apps().deployments().inNamespace("ns1").withName("mydeployment").withPropagationPolicy(DeletionPropagation.FOREGROUND).withGracePeriod(10).delete();

Watch Options

Kubernetes Client provides namely three different ways of using Watch:

client.pods().inNamespace(namespace).watch(new Watcher<Pod>() {
    @Override
    public void eventReceived(Action action, Pod pod) {
        logger.log(Level.INFO, action.name() + " " + pod.getMetadata().getName());
        switch (action.name()) {
            case "ADDED":
                logger.log(Level.INFO, pod.getMetadata().getName() + "got added");
                break;
            case "DELETED":
                logger.log(Level.INFO, pod.getMetadata().getName() + "got deleted");
                break;
            case "MODIFIED":
                logger.log(Level.INFO, pod.getMetadata().getName() + "got modified");
                break;
            default:
                logger.log(Level.SEVERE, "Unrecognized event: " + action.name());
        }
    }

    @Override
    public void onClose(KubernetesClientException e) {
        logger.log(Level.INFO, "Closed");
        isWatchClosed.countDown();
    }
});

// Wait till watch gets closed
isWatchClosed.await();

String resourceVersion = "20012";
client.pods().inNamespace(namespace).watch(resourceVersion, new Watcher<Pod>() {
    @Override
    public void eventReceived(Action action, Pod pod) {
        logger.log(Level.INFO, action.name() + " " + pod.getMetadata().getName());
        switch (action.name()) {
            case "ADDED":
                logger.log(Level.INFO, pod.getMetadata().getName() + "got added");
                break;
            case "DELETED":
                logger.log(Level.INFO, pod.getMetadata().getName() + "got deleted");
                break;
            case "MODIFIED":
                logger.log(Level.INFO, pod.getMetadata().getName() + "got modified");
                break;
            default:
                logger.log(Level.SEVERE, "Unrecognized event: " + action.name());
        }
    }

    @Override
    public void onClose(KubernetesClientException e) {
        logger.log(Level.INFO, "Closed");
        isWatchClosed.countDown();
    }
});

// Wait till watch gets closed
isWatchClosed.await();
} catch (InterruptedException interruptedException) {
logger.log(Level.INFO, "Thread Interrupted!");
Thread.currentThread().interrupt();
}

client.pods().watch(new ListOptionsBuilder().withTimeoutSeconds(30L).build(), new Watcher<Pod>() {
  @Override
  public void eventReceived(Action action, Pod resource) { }

  @Override
  public void onClose(KubernetesClientException cause) { }
});

Log Options

client.pods().inNamespace("test").withName("foo").withPrettyOutput().getLog();

client.pods().inNamespace("test").withName("foo").inContainer("container1").getLog();

client.pods().inNamespace("test").withName("foo").terminated().getLog();

client.pods().inNamespace("test").withName("foo").sinceTime("2020-09-10T12:53:30.154148788Z").getLog();

client.pods().inNamespace("test").withName("foo").sinceSeconds(10).getLog();

client.pods().inNamespace("test").withName("foo").tailingLines(10).getLog();

client.pods().inNamespace("test").withName("foo").limitBytes(102).getLog();

client.pods().inNamespace("test").withName("foo").usingTimestamps().getLog();

Serializing to yaml

Resources can be exported to a yaml String via the SerializationUtils class:

Pod myPod;

String myPodAsYaml = SerializationUtils.dumpAsYaml(myPod);
// Your pod might have some state that you don't really care about, to remove it:
String myPodAsYamlWithoutRuntimeState = SerializationUtils.dumpWithoutRuntimeStateAsYaml(myPod);

Running a Pod

Kubernetes Client also provides mechanism similar to kubectl run in which you can spin a Pod just by specifying it's image and name:

try (KubernetesClient client = new DefaultKubernetesClient()) {
    client.run().inNamespace("default")
            .withName("hazelcast")
            .withImage("hazelcast/hazelcast:3.12.9")
            .done();
}

try (KubernetesClient client = new DefaultKubernetesClient()) {
    client.run().inNamespace("default")
            .withRunConfig(new RunConfigBuilder()
                    .withName("nginx")
                    .withImage("nginx:latest")
                    .withLabels(Collections.singletonMap("foo", "bar"))
                    .withEnv(Collections.singletonMap("KUBERNETES_TEST", "fabric8"))
                    .build())
            .done();
}

OpenShift Client DSL Usage

Fabric8 Kubernetes Client also has an extension for OpenShift. It is pretty much the same as Kubernetes Client but has support for some additional OpenShift resources.

Initializing OpenShift Client:

Initializing OpenShift client is the same as Kubernetes Client. Yo

try (final OpenShiftClient client = new DefaultOpenShiftClient()) {
  // Do stuff with client
}

This would pick up default settings, reading your kubeconfig file from ~/.kube/config directory or whatever is defined inside KUBECONFIG environment variable. But if you want to customize creation of client, you can also pass a Config object inside DefaultKubernetesClient like this:

Config kubeConfig = new ConfigBuilder()
            .withMasterUrl("https://api.ci-ln-3sbdl1b-d5d6b.origin-ci-int-aws.dev.examplecloud.com:6443")
            .withOauthToken("xxxxxxxx-41oafKI6iU637-xxxxxxxxxxxxx")
            .build())) {
try (final OpenShiftClient client = new DefaultOpenShiftClient(config)) {
  // Do stuff with client
}

You can also create OpenShiftClient from an existing instance of KubernetesClient. There is a method called adapt(..) for this. Here is an example:

KubernetesClient client = new DefaultKubernetesClient();
OpenShiftClient openShiftClient = client.adapt(OpenShiftClient.class);

DeploymentConfig

DeploymentConfig is available in OpenShift client via client.deploymentConfigs(). Here are some examples of its common usage:

DeploymentConfig deploymentConfig = client.deploymentConfigs().inNamespace(currentNamespace)
  .load(new FileInputStream("test-deploymentconfig.yml")).get();

DeploymentConfig dc = client.deploymentConfigs().inNamespace(currentNamespace).withName("deploymentconfig1").get();

DeploymentConfig dc = new DeploymentConfigBuilder()
      .withNewMetadata().withName("deploymentconfig1").endMetadata()
      .withNewSpec()
      .withReplicas(2)
      .withNewTemplate()
      .withNewMetadata()
      .addToLabels("app", "database")
      .endMetadata()
      .withNewSpec()
      .addNewContainer()
      .withName("mysql")
      .withImage("openshift/mysql-55-centos7")
      .endContainer()
      .endSpec()
      .endTemplate()
      .endSpec()
      .build();

DeploymentConfig dcCreated = client.deploymentConfigs().inNamespace("default").create(dc);

DeploymentConfig dc = client.deploymentConfigs().inNamespace("default").createOrReplace(dcToCreate);

DeploymentConfigList aDeploymentConfigList = client.deploymentConfigs().inNamespace("default").list();

DeploymentConfigList dcList = client.deploymentConfigs().inAnyNamespace().list();

DeploymentConfigList dcList = client.deploymentConfigs().inNamespace("default").withLabel("foo", "bar").list();

DeploymentConfig deploymentConfig1 = client.deploymentConfigs().inNamespace(currentNamespace).withName("deploymentconfig1").edit()
  .editSpec().withReplicas(3).endSpec().done();

Boolean bDeleted = client.deploymentConfigs().inNamespace("default").withName("deploymentconfig1").delete();

client.deploymentConfigs().inNamespace("default").watch(new Watcher<DeploymentConfig>() {
  @Override
  public void eventReceived(Action action, DeploymentConfig resource) {
    // Do something depending upon action    
  }

  @Override
  public void onClose(KubernetesClientException cause) {

  }
});

BuildConfig

BuildConfig resource is available in OpenShift Client via client.buildConfigs(). Here are some examples of it's common uses:

<article class="markdown-body entry-content container-lg" itemprop="text" style="box-sizing: border-box; display: block; max-width: 1012px; margin-right: auto; margin-left: auto; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; font-size: 16px; line-height: 1.5; overflow-wrap: break-word;">

BuildConfig aBuildConfig = client.buildConfigs().inNamespace(currentNamespace)
  .load(new FileInputStream("/test-buildconfig.yml")).get();

BuildConfig bc = client.buildConfigs().inNamespace(currentNamespace).withName("bc1").get();

BuildConfig buildConfig1 = new BuildConfigBuilder()
  .withNewMetadata().withName("bc1").endMetadata()
  .withNewSpec()
  .addNewTrigger()
  .withType("GitHub")
  .withNewGithub()
  .withSecret("secret101")
  .endGithub()
  .endTrigger()
  .addNewTrigger()
  .withType("Generic")
  .withNewGeneric()
  .withSecret("secret101")
  .endGeneric()
  .endTrigger()
  .addNewTrigger()
  .withType("ImageChange")
  .endTrigger()
  .withNewSource()
  .withType("Git")
  .withNewGit()
  .withUri("https://github.com/openshift/ruby-hello-world")
  .endGit()
  .withDockerfile("FROM openshift/ruby-22-centos7\\nUSER example")
  .endSource()
  .withNewStrategy()
  .withType("Source")
  .withNewSourceStrategy()
  .withNewFrom()
  .withKind("ImageStreamTag")
  .withName("origin-ruby-sample:latest")
  .endFrom()
  .endSourceStrategy()
  .endStrategy()
  .withNewOutput()
  .withNewTo()
  .withKind("ImageStreamTag")
  .withName("origin-ruby-sample:latest")
  .endTo()
  .endOutput()
  .withNewPostCommit()
  .withScript("bundle exec rake test")
  .endPostCommit()
  .endSpec()
  .build();

client.buildConfigs().inNamespace("default").create(buildConfig1);

BuildConfig bc = client.buildConfigs().inNamespace("default").create(buildConfig1);

BuildConfigList bcList = client.buildConfigs().inNamespace("default").list();

BuildConfigList bcList = client.buildConfigs().inNamespace("default").list();

BuildConfigList bcList = client.buildConfigs().inNamespace("default").withLabel("foo", "bar").list();

Boolean bDeleted = client.buildConfigs().inNamespace("default").withName("bc1").delete();

client.buildConfigs().inNamespace("default").watch(new Watcher<BuildConfig>() {
  @Override
  public void eventReceived(Action action, BuildConfig resource) {
    // Do something depending upon action type    
  }

  @Override
  public void onClose(KubernetesClientException cause) {

  }
});

Route

Route resource is available in OpenShift client API via client.routes(). Here are some examples of its common usage:

Route aRoute = client.routes().inNamespace("default").load(new FileInputStream("test-route.yml")).get();

Route route1 = client.routes().inNamespace("default").withName("route1").get();

Route route1 = new RouteBuilder()
      .withNewMetadata().withName("route1").endMetadata()
      .withNewSpec().withHost("www.example.com").withNewTo().withKind("Service").withName("service-name1").endTo().endSpec()
      .build();

client.routes().inNamespace("defalt").create(route1);

Route route = client.routes().inNamespace("default").createOrReplace(route1);

RouteList aRouteList = client.routes().inNamespace("default").list();

RouteList aRouteList = client.routes().inAnyNamespace().list();

RouteList routeList = client.routes().inNamespace("default").withLabel("foo", "bar").list();

boolean bDeleted = client.routes().inNamespace("default").withName("route1").delete();

Project

OpenShift Project resource can be found in OpenShift Client API via client.projects(). Here are some examples of its usage:

Project myProject = client.projects().withName("default").get();

ProjectRequest request = client.projectrequests().createNew().withNewMetadata().withName("thisisatest").endMetadata().withDescription("Fabric8").withDisplayName("Fabric8).done();

ProjectList projectList = client.projects().list();

Boolean isDeleted = client.projects().withName("default").delete();

ImageStream

ImageStream resource is available in OpenShift client via client.imageStreams(). Here are some examples of its common usage:

ImageStream aImageStream = client.imageStreams()
  .load(new FileInputStream("test-imagestream.yml")).get();

ImageStream is =client.imageStreams().inNamespace("default").withName("example-camel-cdi").get();

ImageStream imageStream1 = new ImageStreamBuilder()
      .withNewMetadata()
      .withName("example-camel-cdi")
      .endMetadata()
      .withNewSpec()
      .addNewTag()
      .withName("latest")
      .endTag()
      .withDockerImageRepository("fabric8/example-camel-cdi")
      .endSpec()
      .withNewStatus().withDockerImageRepository("").endStatus()
      .build();

client.imageStreams().inNamespace("default").create(imageStream1);

ImageStream is = client.imageStreams().inNamespace("default").createOrReplace(imageStream1);

ImageStreamList aImageStreamList = client.imageStreams().inNamespace("default").list();

ImageStreamList isList = client.imageStreams().inAnyNamespace().list();

ImageStreamList isList = client.imageStreams().inNamespace("default").withLabel("foo", "bar").list();

Boolean bDeleted = client.imageStreams().inNamespace("default").withName("example-camel-cdi").delete();

CatalogSource

CatalogSource is available for usage in OpenShift Client via client.operatorHub().catalogSources(). Here are some common examples of it's usage:

CatalogSource cs = client.operatorHub().catalogSources()
  .load(new FileInputStream("/test-catalogsource.yml").get();

CatalogSource cs = new CatalogSourceBuilder()
  .withNewMetadata().withName("foo").endMetadata()
  .withNewSpec()
  .withSourceType("Foo")
  .withImage("nginx:latest")
  .withDisplayName("Foo Bar")
  .withPublisher("Fabric8")
  .endSpec()
  .build();
client.operatorHub().catalogSources().inNamespace("default").createOrReplace(cs);

CatalogSourceList csList = client.operatorHub().catalogSources().inNamespace("ns1").list();

CatalogSourceList csList = client.operatorHub().catalogSources().inAnyNamespace().list();

CatalogSourceList csList = client.operatorHub().catalogSources().inNamespace("default").withLabel("foo", "bar").list();

client.operatorHub().catalogSources().inNamespace("default").withName("foo").delete();

PrometheusRule

PrometheusRule is available for usage in OpenShift Client via client.monitoring().prometheusRules(). Here are some common examples of it's usage:

PrometheusRule prometheusRule = client.monitoring().prometheusRules()
  .load(new FileInputStream("/test-prometheusrule.yml").get();

PrometheusRule prometheusRule = new PrometheusRuleBuilder()
    .withNewMetadata().withName("foo").endMetadata()
    .withNewSpec()
    .addNewGroup()
    .withName("./example-rules")
    .addNewRule()
    .withAlert("ExampleAlert")
    .withNewExpr().withStrVal("vector(1)").endExpr()
    .endRule()
    .endGroup()
    .endSpec()
    .build();
client.monitoring().prometheusRules().inNamespace("default").createOrReplace(prometheusRule);

PrometheusRuleList prList = client.monitoring().prometheusRules().inNamespace("ns1").list();

PrometheusRuleList prList = client.monitoring().prometheusRules().inAnyNamespace().list();

PrometheusRuleList prList = client.monitoring().prometheusRules().inNamespace("default").withLabel("foo", "bar").list();

client.monitoring().prometheusRules().inNamespace("default").withName("foo").delete();

ServiceMonitor

ServiceMonitor is available for usage in OpenShift Client via client.monitoring().serviceMonitors(). Here are some common examples of it's usage:

ServiceMonitor serviceMonitor = client.monitoring().serviceMonitors()
  .load(new FileInputStream("/test-servicemonitor.yml").get();

ServiceMonitor serviceMonitor = new ServiceMonitorBuilder()
    .withNewMetadata()
    .withName("foo")
    .addToLabels("prometheus", "frontend")
    .endMetadata()
    .withNewSpec()
    .withNewNamespaceSelector().withAny(true).endNamespaceSelector()
    .withNewSelector()
    .addToMatchLabels("prometheus", "frontend")
    .endSelector()
    .addNewEndpoint()
    .withPort("http-metric")
    .withInterval("15s")
    .endEndpoint()
    .endSpec()
    .build();

client.monitoring().serviceMonitors().inNamespace("rokumar").createOrReplace(serviceMonitor)

ServiceMonitorList serviceMonitorList = client.monitoring().serviceMonitors().inNamespace("ns1").list();

ServiceMonitorList serviceMonitorList = client.monitoring().serviceMonitors().inAnyNamespace().list();

ServiceMonitorList serviceMonitorList = client.monitoring().catalogSources().inNamespace("default").withLabel("foo", "bar").list();

client.operatorHub().monitoring().inNamespace("default").withName("foo").delete();

ClusterResourceQuota

try (OpenShiftClient client = new DefaultOpenShiftClient()) {
    Map<String, Quantity> hard = new HashMap<>();
    hard.put("pods", new Quantity("10"));
    hard.put("secrets", new Quantity("20"));
    ClusterResourceQuota acrq = new ClusterResourceQuotaBuilder()
            .withNewMetadata().withName("foo").endMetadata()
            .withNewSpec()
            .withNewSelector()
            .addToAnnotations("openshift.io/requester", "foo-user")
            .endSelector()
            .withQuota(new ResourceQuotaSpecBuilder()
                    .withHard(hard)
                    .build())
            .endSpec()
            .build();

    client.quotas().clusterResourceQuotas().createOrReplace(acrq);
}

ClusterResourceQuotaList clusterResourceQuotaList = client.quotas().clusterResourceQuotas().list();

client.quotas().clusterResourceQuotas().withName("foo").delete();

ClusterVersion

try (OpenShiftClient client = new DefaultOpenShiftClient()) {
    ClusterVersion clusterVersion = client.config().clusterVersions().withName("version").get();
    System.out.println("Cluster Version: " + clusterVersion.getStatus().getDesired().getVersion());
}

EgressNetworkPolicy

EgressNetworkPolicy is available for usage in OpenShift Client via client..egressNetworkPolicys(). Here are some common examples of it's usage:

EgressNetworkPolicy egressNetworkPolicy = client.egressNetworkPolicies()
  .load(new FileInputStream("/test-enp.yml").get();

try (OpenShiftClient client = new DefaultOpenShiftClient()) {
    EgressNetworkPolicy enp = new EgressNetworkPolicyBuilder()
            .withNewMetadata()
            .withName("foo")
            .withNamespace("default")
            .endMetadata()
            .withNewSpec()
            .addNewEgress()
            .withType("Allow")
            .withNewTo()
            .withCidrSelector("1.2.3.0/24")
            .endTo()
            .endEgress()
            .addNewEgress()
            .withType("Allow")
            .withNewTo()
            .withDnsName("www.foo.com")
            .endTo()
            .endEgress()
            .endSpec()
            .build();
    client.egressNetworkPolicies().inNamespace("default").createOrReplace(enp);
}

EgressNetworkPolicyList egressNetworkPolicyList = client.egressNetworkPolicies().inNamespace("default").list();

EgressNetworkPolicyList egressNetworkPolicyList = client.egressNetworkPolicies().inAnyNamespace().list();

EgressNetworkPolicyList egressNetworkPolicyList = client.egressNetworkPolicies().inNamespace("default").withLabel("foo", "bar").list();

client.egressNetworkPolicies().inNamespace("default").withName("foo").delete();

Tekton Client

Fabric8 Kubernetes Client also has an extension for Tekton. It is pretty much the same as Kubernetes Client but has support for some additional Tekton resources.

Initializing Tekton Client

Initializing Tekton client is the same as Kubernetes Client. You

try (final TektonClient client = new DefaultTektonClient()) {
  // Do stuff with client
}

This would pick up default settings, reading your kubeconfig file from ~/.kube/config directory or whatever is defined inside KUBECONFIG environment variable. But if you want to customize creation of client, you can also pass a Config object inside DefaultTektonClient. You can also create TektonClient from an existing instance of KubernetesClient. There is a method called adapt(..) for this. Here is an example:

KubernetesClient client = new DefaultKubernetesClient();
TektonClient tektonClient = client.adapt(TektonClient.class);

Tekton Client DSL Usage

The Tekton client supports CRD API version tekton.dev/v1alpha1 as well as tekton.dev/v1beta1. tekton.dev/v1alpha1 includes the CRDs Pipeline, PipelineRun, PipelineResource, Task, TaskRun, Condition and ClusterTask. All tekton.dev/v1alpha1 resources are available using the DSL tektonClient.v1alpha1(). tekton.dev/v1beta1 includes the CRDs Pipeline, PipelineRun, Task, TaskRun and ClusterTask. All tekton.dev/v1beta1 resources are available using the DSL tektonClient.v1beta1(). In addition to the Tekton Pipelines CRDs, the client also supports Tekton Triggers. TriggerTemplate, TriggerBinding, EventListener and ClusterTriggerBinding are available using the DSL tektonClient.v1alpha1().

The usage of the resources follows the same pattern as for K8s resources like Pods or Deployments. Here are some common examples:

PipelineRunList list = tektonClient.v1beta1().pipelineRuns().inNamespace("default").list();

PipelineRun pipelineRun = new PipelineRunBuilder()
        .withNewMetadata().withName("demo-run-1").endMetadata()
        .withNewSpec()
        .withNewPipelineRef().withName("demo-pipeline").endPipelineRef()
        .addNewParam().withName("greeting").withNewValue("Hello World!").endParam()
        .endSpec()
        .build();

tektonClient.v1beta1().pipelineRuns().inNamespace("default").create(pipelineRun);

Knative Client

Fabric8 Kubernetes Client also has an extension for Knative. It is pretty much the same as Kubernetes Client but has support for some additional Knative resources.

Initializing Knative Client

Initializing Knative client is the same as Kubernetes Client.

try (final KnativeClient client = new DefaultKnativeClient()) {
  // Do stuff with client
}

This would pick up default settings, reading your kubeconfig file from ~/.kube/config directory or whatever is defined inside KUBECONFIG environment variable. But if you want to customize creation of client, you can also pass a Config object inside DefaultKnativeClient. You can also create KnativeClient from an existing instance of KubernetesClient. There is a method called adapt(..) for this. Here is an example:

KubernetesClient client = new DefaultKubernetesClient();
KnativeClient knativeClient = client.adapt(KnativeClient.class);

Knative Client DSL Usage

The usage of the resources follows the same pattern as for K8s resources like Pods or Deployments. Here are some common examples:

ServiceList list = knativeClient.services().inNamespace("default").list();

try (KnativeClient kn = new DefaultKnativeClient()) {
    // Create Service object
    Service service = new ServiceBuilder()
            .withNewMetadata().withName("helloworld-go").endMetadata()
            .withNewSpec()
            .withNewTemplate()
            .withNewSpec()
            .addToContainers(new ContainerBuilder()
                    .withImage("gcr.io/knative-samples/helloworld-go")
                    .addNewEnv().withName("TARGET").withValue("Go Sample V1").endEnv()
                    .build())
            .endSpec()
            .endTemplate()
            .endSpec()
            .build();

    // Apply it onto Kubernetes Server
    kn.services().inNamespace("default").createOrReplace(service);
}

</article>

<details class="details-reset details-overlay details-overlay-dark" id="jumpto-line-details-dialog" style="box-sizing: border-box; display: block;"><summary data-hotkey="l" aria-label="Jump to line" role="button" style="box-sizing: border-box; display: list-item; cursor: pointer; list-style: none;"></summary></details>

</main>

上一篇 下一篇

猜你喜欢

热点阅读