FunTester Fabric8 Kubernetes 教程——Metrics、Resource

FunTester · April 02, 2025 · 645 hits

Kubernetes 客户端提供了丰富的 API 来管理和操作 Kubernetes 集群中的资源。以下是一些常见的操作示例,涵盖了指标获取、资源管理、自定义资源定义(CRD)以及类型化和无类型资源 API 的使用。

获取 Metrics

Kubernetes 客户端支持从启用了指标的 API 服务器获取指标。你可以通过 client.top() 访问指标。

获取所有节点的 NodeMetrics

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

获取特定节点的 NodeMetrics

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

获取所有命名空间中所有 Pod 的 PodMetrics

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

获取某个特定命名空间中所有 Pod 的 PodMetrics

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

获取特定 Pod 的 PodMetrics

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

Resource API

Resource 是 Kubernetes 中表示集群中可用计算资源(如 CPU、内存)的抽象概念,用于定义 Pod 的资源请求(requests)和限制(limits)。

Kubernetes 客户端提供了一个通用 API 来处理不同类型的 Kubernetes 资源。大多数 Kubernetes 资源都扩展了 HasMetadata 类。

从 Kubernetes API 服务器获取 Kubernetes 资源:

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

将 Kubernetes 资源应用到 Kubernetes 集群(服务器端应用):

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").serverSideApply();

应用 Kubernetes 资源并等待资源准备就绪:

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

删除 Kubernetes 资源:

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

Resource List

Kubernetes 客户端还提供了一个通用 API 来处理 Kubernetes 列表。

将 Kubernetes 资源列表应用到 Kubernetes 集群:

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();

// 应用
client.resourceList(list).inNamespace("default").serverSideApply();

删除资源列表:

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

自定义资源定义(CRD)

自定义资源定义(CRD) 是 Kubernetes 中允许用户扩展 API 的机制,用于定义和管理自定义资源(Custom Resource),满足特定应用或业务需求。

CustomResourceDefinition 是 Kubernetes API 中 CustomResource 对象的模板。

从 yaml 文件加载 CustomResourceDefinition

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

从 Kubernetes API 服务器获取 CustomResourceDefinition

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

创建 CustomResourceDefinition

CustomResourceDefinition customResourceDefinition = new CustomResourceDefinitionBuilder()
      .withApiVersion("apiextensions.k8s.io/v1")
      .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.apiextensions().v1().customResourceDefinitions().resource(customResourceDefinition).create();

应用 CustomResourceDefinition

CustomResourceDefinition crd = client.apiextensions().v1().customResourceDefinitions().resource(customResourceDefinition).serverSideApply();

列出 CustomResourceDefinition

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

删除 CustomResourceDefinition

client.apiextensions().v1().customResourceDefinitions().withName("sparkclusters.radanalytics.io").delete();

资源类型化 API

任何资源(无论是自定义资源还是内置资源)都可以通过 client.resources(Class) 方法访问。

获取自定义资源的客户端实例:

MixedOperation<CronTab, KubernetesResourceList<CronTab>, Resource<CronTab>> cronTabClient = client.resources(CronTab.class);

从 Kubernetes API 服务器获取自定义资源:

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

创建 CustomResource

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

列出 CustomResource

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

删除 CustomResource

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

替换 CustomResource 的状态:

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

修补 CustomResource 的状态:

cronTabClient.inNamespace("default").resource(updatedCronTab).patchStatus();

编辑 CustomResource 的状态:

cronTabClient.inNamespace("default").resource(cronTab1).editStatus(cronTab -> updatedCronTab);

监听 CustomResource

cronTabClient.inNamespace("default").watch(new Watcher<>() {
   @Override
   public void eventReceived(Action action, CronTab resource) {
        // 根据操作类型执行某些操作
   }

   @Override
   public void onClose(WatcherException cause) {
        // 处理关闭事件
   }
});

无类型资源

如果你不需要或不想使用强类型的客户端,Kubernetes 客户端还提供了一个无类型/原始 API 来处理资源。

创建 ResourceDefinitionContext

ResourceDefinitionContext resourceDefinitionContext = new ResourceDefinitionContext.Builder()
      .withGroup("jungle.example.com")
      .withVersion("v1")
      .withPlural("animals")
      .withNamespaced(true)
      .build();

从 YAML 文件加载资源:

GenericKubernetesResource customResource = client.genericKubernetesResources(context).load(new FileInputStream("cr.yaml")).item();

从 Kubernetes API 服务器获取资源:

GenericKubernetesResource customResourceObject = client.genericKubernetesResources(resourceDefinitionContext).inNamespace(currentNamespace).withName("otter").get();

创建资源:

GenericKubernetesResource object = client.genericKubernetesResources(resourceDefinitionContext).inNamespace(currentNamespace).load(new FileInputStream("test-rawcustomresource.yml")).create();

列出 CustomResource

GenericKubernetesResourceList list = client.genericKubernetesResources(resourceDefinitionContext).inNamespace(currentNamespace).list();

更新 CustomResource

GenericKubernetesResource walrus = client.genericKubernetesResources(resourceDefinitionContext).inNamespace(currentNamespace).withName("walrus").get();
Map<String, Object> spec = (Map<String, Object>) walrus.getAdditionalProperties().get("spec");
spec.put("image", "my-updated-awesome-walrus-image");
walrus.getAdditionalProperties().put("spec", spec);
client.genericKubernetesResources(resourceDefinitionContext).inNamespace(currentNamespace).resource(walrus).update();

删除 CustomResource

client.genericKubernetesResources(resourceDefinitionContext).inNamespace(currentNamespace).withName("otter").delete();

监听 CustomResource

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

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

Spark Operator

以下示例展示了如何通过 Spark Operator 的示例以两种不同的方式为自定义资源定义相同的上下文。

类型化资源 API:

@Group("sparkoperator.k8s.io")
@Plural("sparkapps")
@Version("v1beta2")
@Kind("SparkApplication")
public class SparkOperatorResource extends GenericKubernetesResource implements Namespaced { ... }

使用类型化资源 API 的 SparkOperatorResource

kubernetesClient.resources(SparkOperatorResource.class).inNamespace("myNamespace")...

无类型资源 API:

public static ResourceDefinitionContext getResourceDefinitionContext() {
    return new ResourceDefinitionContext.Builder()
            .withGroup("sparkoperator.k8s.io")
            .withPlural("sparkapps")
            .withVersion("v1beta2")
            .withKind("SparkApplication")
            .withNamespaced(true)
            .build();
}

使用无类型资源 API:

kubernetesClient.genericKubernetesResources(getResourceDefinitionContext()).inNamespace("myNamespace")...

通过这些 API,你可以灵活地管理和操作 Kubernetes 集群中的各种资源,无论是内置资源还是自定义资源。

FunTester 原创精华
【免费合集】从 Java 开始性能测试
故障测试与 Web 前端
服务端功能测试
性能测试专题
Java、Groovy、Go
测试开发、自动化、白盒
测试理论、FunTester 风采
视频专题
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
No Reply at the moment.
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up