1 - 安装

1.1 - 使用 kubectl apply

安装

Clusterpedia 的安装分为两个部分:

用户如果使用已有的存储组件(MySQL 或者 PostgreSQL),则直接跳过安装存储组件。

拉取项目:

git clone https://github.com/clusterpedia-io/clusterpedia.git
cd clusterpedia
git checkout v0.7.0

安装存储组件

Clusterpedia 安装时提供了 MySQL 8.0PostgreSQL 12 两种存储组件以供选择。

用户如果使用已有的存储组件(MySQL 或者 PostgreSQL),则直接跳过存储组件安装。

进入所选存储组件的安装目录

cd ./deploy/internalstorage/postgres

进入所选存储组件的安装目录

cd ./deploy/internalstorage/mysql

存储组件使用 Local PV 的方式存储数据,部署时需要指定 Local PV 所在节点

用户可以选择自己提供 PV

export STORAGE_NODE_NAME=<节点名称>
sed "s|__NODE_NAME__|$STORAGE_NODE_NAME|g" `grep __NODE_NAME__ -rl ./templates` > clusterpedia_internalstorage_pv.yaml

部署存储组件

kubectl apply -f .

# 跳回 Clusterpedia 项目根目录
cd ../../../

安装 Clusterpedia

存储组件部署完成后,便可安装 Clusterpedia。

如果选择使用已存在的存储组件,则需要参考 配置存储层 来将存储组件对接到默认存储层中。

在 clusterpedia 项目根目录下进行操作。

# 部署 Clusterpedia CRD 与组件
kubectl apply -f ./deploy

安装完成

检查组件 Pods 运行是否正常。

kubectl -n clusterpedia-system get pods

部署集群自动接入策略 —— ClusterImportPolicy

0.4.0 后,Clusterpedia 提供了更加友好的接入多云平台的方式。

用户通过创建 ClusterImportPolicy 来自动发现多云平台中纳管的集群,并将这些集群自动同步为 PediaCluster,用户不需要根据纳管的集群来手动去维护 PediaCluster 了。

我们在 Clusterpedia 仓库 中维护了各个多云平台的 ClusterImportPolicy大家也提交用于对接其他多云平台的 ClusterImportPolicy

用户在安装 Clusterpedia 后,创建合适的 ClusterImportPolicy 即可,用户也可以根据自己的需求来创建新的 ClusterImportPolicy

具体可以参考 接入多云平台

kubectl get clusterimportpolicy

卸载

删除 ClusterImportPolicy

如果用户部署了 ClusterImportPolicy 那么需要先清理 ClusterImportPolicy 资源

kubectl get clusterimportpolicy

清理 PediaCluster

在卸载 Clusterpedia 前,需要查看环境中是否还存在 PediaCluster 资源,如果存在那么需要删除这些资源。

kubectl get pediacluster

卸载 Clusterpedia

PediaCluster 资源清理完成后,卸载 Clusterpedia 相关组件。

# delete compontents
kubectl delete -f ./deploy/clusterpedia_apiserver_apiservice.yaml
kubectl delete -f ./deploy/clusterpedia_apiserver_deployment.yaml
kubectl delete -f ./deploy/clusterpedia_clustersynchro_manager_deployment.yaml
kubectl delete -f ./deploy/clusterpedia_controller_manager_deployment.yaml
kubectl delete -f ./deploy/clusterpedia_apiserver_rbac.yaml

# delete crds
kubectl delete -f ./deploy/cluster.clusterpedia.io_clustersyncresources.yaml
kubectl delete -f ./deploy/cluster.clusterpedia.io_pediaclusers.yaml
kubectl delete -f ./deploy/policy.clusterpedia.io_clusterimportpolicies.yaml
kubectl delete -f ./deploy/policy.clusterpedia.io_pediaclusterlifecycles.yaml

卸载存储组件

根据选择的存储组件类型,来移除相关的资源。

kubectl delete -f ./deploy/internalstorage/<storage type>

清理 Local PV 以及数据

存储组件卸载后,PV 和相应的数据会依然遗留在节点中,我们需要手动清理。

通过 Local PV 资源详情,来查看挂载的节点。

kubectl get pv clusterpedia-internalstorage-<storage type>

得知数据保存的节点后,删除 Local PV。

kubectl delete pv clusterpedia-internalstorage-<storage type>

登录数据所在节点,清理数据。

# 遗留数据所在节点
rm -rf /var/local/clusterpedia/internalstorage/<storage type>

1.2 - 使用 Helm

1.3 - 配置

1.3.1 - 配置存储层

Clusterpedia 的默认存储层支持 MySQLPostgreSQL 两种存储组件。

用户在安装 Clusterpedia 时,可以使用已存在的存储组件, 不过需要创建相应的默认存储层配置(ConfigMap)存储组件密码 Secret

默认存储层配置

用户需要在 clusterpedia-system 命名空间下创建 clusterpedia-internalstorage ConfigMap。

# internalstorage configmap example
apiVersion: v1
kind: ConfigMap
metadata:
  name: clusterpedia-internalstorage
  namespace: clusterpedia-system
data:
  internalstorage-config.yaml: |
    type: "mysql"
    host: "clusterpedia-internalstorage-mysql"
    port: 3306
    user: root
    database: "clusterpedia"
    connPool:
      maxIdleConns: 10
      maxOpenConns: 100
      connMaxLifetime: 1h
    log:
      slowThreshold: "100ms"
      logger:
        filename: /var/log/clusterpedia/internalstorage.log
        maxbackups: 3    

internalstorage config 支持以下基本字段:

field description
type 存储组件的类型,支持 “postgres” 和 “mysql”
host 存储组件地址,可以使用 IP 或者 Service Name
port 存储组件端口
user 存储组件用户
password 存储组件密码
database Clusterpedia 所使用的 database

存储组件的访问密码,最好存放在 Secret,参考 配置存储组件密码 Secret

数据库连接池配置

field description
connPool.maxIdleConns 空闲连接池中的最大数量,默认为 10
connPool.maxOpenConns 打开的数据库连接的最大数量,默认为 100
connPool.connMaxLifetime 连接可以复用的最大时间,默认为 1h

根据用户的当前环境,合理设置数据库连接池

日志配置

支持配置存储层日志,通过 log 字段来开启日志打印慢 SQL 和错误

field description
log.stdout 打印日志到标准输出
log.colorful 是否开启彩色打印
log.slowThreshold 设置慢 SQL 阀值,例如 “100ms”
log.level 设置日志级别,支持 Slient, Error, Warn, Info
log.logger 日志轮滚配置

开启日志打印后,如果 log.stdout 不为 true,则将日志输出到 /var/log/clusterpedia/internalstorage.log 文件中

日志轮滚配置

将存储层的日志保存到文件中,并且可以配置日志文件的轮滚

field description
log.logger.filename 日志文件路径, 默认为 /var/log/clusterpedia/internalstorage.log
log.logger.maxsize 触发日志轮滚的最大文件大小,单位为 MB
log.logger.maxage 轮滚的旧日志的最大存活时间
log.logger.maxbackups 轮滚的旧日志的最大数量
log.logger.localtime 是否为本地时间,默认为 UTC
log.logger.compress 是否将轮滚的日志文件进行压缩,默认不进行压缩

关闭日志打印

在 internalstorage config 不填写 log 字段,便会忽略日志打印,例如:

type: "mysql"
host: "clusterpedia-internalstorage-mysql"
port: 3306
user: root
database: "clusterpedia"

更多配置

默认存储层还提供了有关 MySQL 和 PostgreSQL 的更多配置,可以参考 internalstorage/config.go

配置存储组件密码 Secret

Clusterpedia 的安装 yaml 会从 internalstorage-password 的 Secret 中获取密码。

将存储组件的密码配置到 Secret 中

kubectl -n clusterpedia-system create secret generic \
    internalstorage-password --from-literal=password=<存储组件访问密码>

2 - 概念

2.1 - PediaCluster

Clusterpedia 中使用 PediaCluster 资源来代表一个需要同步资源的集群。

Clusterpedia 需要非常友好的对接到其他多云平台中,而多云平台可能会使用 Cluster 资源来代表纳管的集群,为了避免冲突 Clusterpedia 使用 PediaCluster。

$ kubectl get pediacluster
NAME        APISERVER                        VERSION            STATUS
demo1       https://10.6.101.100:6443        v1.22.3-aliyun.1   Healthy
demo2       https://10.6.101.100:6443        v1.21.0            Healthy
apiVersion: cluster.clusterpedia.io/v1alpha2
kind: PediaCluster
metadata:
  name: demo1
spec:
  apiserver: https://10.6.101.100:6443
  kubeconfig:
  caData:
  tokenData:
  certData:
  keyData:
  syncResources: []
  syncAllCustomResources: false
  syncResourcesRefName: ""

PediaCluster 有两个作用

  • 配置集群的认证信息
  • 配置同步的资源

配置集群认证信息可以参考 集群接入

有三个字段可以配置同步的资源:

  • spec.syncResources 配置该集群需要同步的资源
  • spec.syncAllCustomResources 同步所有的自定义资源
  • spec.syncResourcesRefName 引用 公共的集群资源同步配置

具体配置同步资源,可以参考 同步集群资源

2.2 - 公共的集群资源同步配置(ClusterSyncResources)

Clusterpedia 提供了公共的集群资源同步配置 ——  ClusterSyncResources

kubectl get clustersyncresources

ClusterSyncResources 的 spec.syncResources 字段和 PediaCluster 的 spec.syncResources 配置方式相同,可以参考 同步集群资源

apiVersion: cluster.clusterpedia.io/v1alpha2
kind: ClusterSyncResources
metadata:
  name: global-base
spec:
  syncResources:
    - group: ""
      resources:
        - pods
    - group: "apps"
      resources:
        - "*"

未来会支持 spec.syncAllCustomResources 字段来支持设置同步所有的自定义资源

任何 PediaCluster 都可以通过 spec.syncResourcesRefName 引用相同的 ClusterSyncResources

apiVersion: cluster.clusterpedia.io/v1alpha2
kind: PediaCluster
metadata:
  name: demo1
spec:
  syncResourcesRefName: "global-base"

当我们修改 ClusterSyncResources 时,所有引用它的 PediaCluster 内同步的资源都会发生相应的修改。

如果 PediaCluster 同时设置了 spec.syncResourcesRefNamespec.syncResources,那么会取两者的并集

apiVersion: cluster.clusterpedia.io/v1alpha2
kind: PediaCluster
metadata:
  name: demo1
spec:
  syncResourcesRefName: "global-base"
  syncResources:
    - group: ""
      resources:
        - pods
        - configmaps

上例中,clusterpedia 会同步 demo1 集群中 pods 和 configmaps,以及 apps group 下的所有资源。

2.3 - 聚合资源(Collection Resource)

Clusterpedia 为了能够一次性获取多个类型的资源,在单个资源类型的基础上提供了一种新的资源 —— 聚合资源(Collection Resource)

聚合资源是由不同的资源类型组合而成,可以对这些资源类型进行统一的检索和分页。

具体支持哪些聚合资源是由存储层来决定的,例如 默认存储层 支持 anyworkloadskuberesources 两种聚合资源。

kubectl get collectionresources
# 输出:
NAME            RESOURCES
any             * 
workloads       deployments.apps,daemonsets.apps,statefulsets.apps
kuberesources   .*,*.admission.k8s.io,*.admissionregistration.k8s.io,*.apiextensions.k8s.io,*.apps,*.authentication.k8s.io,*.authorization.k8s.io,*.autoscaling,*.batch,*.certificates.k8s.io,*.coordination.k8s.io,*.discovery.k8s.io,*.events.k8s.io,*.extensions,*.flowcontrol.apiserver.k8s.io,*.imagepolicy.k8s.io,*.internal.apiserver.k8s.io,*.networking.k8s.io,*.node.k8s.io,*.policy,*.rbac.authorization.k8s.io,*.scheduling.k8s.io,*.storage.k8s.io

any 表示任意的资源,用户在使用时需要传递想要组合的 groups 或者 resources,具体使用可以参考 使用 Any CollectionResource

kuberesources 包含了所有 kube 的内置资源,我们可以通过 kuberesources 来对所有的内置资源进行统一的过滤和检索。

以 yaml 形式查看支持的聚合资源

kubectl get collectionresources -o yaml
# 输出:
apiVersion: v1
items:
- apiVersion: clusterpedia.io/v1beta1
  kind: CollectionResource
  metadata:
    creationTimestamp: null
    name: any
  resourceTypes: []
- apiVersion: clusterpedia.io/v1beta1
  kind: CollectionResource
  metadata:
    creationTimestamp: null
    name: workloads
  resourceTypes:
  - group: apps
    resource: deployments
    version: v1
  - group: apps
    resource: daemonsets
    version: v1
  - group: apps
    resource: statefulsets
    version: v1
- apiVersion: clusterpedia.io/v1beta1
  kind: CollectionResource
  metadata:
    creationTimestamp: null
    name: kuberesources
  resourceTypes:
  - group: ""
  - group: admission.k8s.io
  - group: admissionregistration.k8s.io
  - group: apiextensions.k8s.io
  - group: apps
  - group: authentication.k8s.io
  - group: authorization.k8s.io
  - group: autoscaling
  - group: batch
  - group: certificates.k8s.io
  - group: coordination.k8s.io
  - group: discovery.k8s.io
  - group: events.k8s.io
  - group: extensions
  - group: flowcontrol.apiserver.k8s.io
  - group: imagepolicy.k8s.io
  - group: internal.apiserver.k8s.io
  - group: networking.k8s.io
  - group: node.k8s.io
  - group: policy
  - group: rbac.authorization.k8s.io
  - group: scheduling.k8s.io
  - group: storage.k8s.io
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""

可以看到 workloads 包含了 deploymentsdaemonsetsstatefulsets 三种资源。

kuberesources 则包含了 kube 内置的所有资源。

更多关于聚合资源的操作可以查看 聚合资源检索

自定义聚合资源

Clusterpedia 计划提供两种方式来让用户随意组合想要查询的资源类型

  • Any CollectionResource —— 使用聚合资源 any
  • CustomCollectionResource —— 自定义聚合资源

0.4 中,Clusterpedia 提供了 any collectionresource 来让用户通过传递 groupsresources 参数来组合不同类型的资源。

不过需要注意 any collectionresource 不能使用 kubectl 来获取,具体使用可以参考 使用 Any CollectionResource

$ kubectl get collectionresources any
Error from server (BadRequest): url query - `groups` or `resources` is required

自定义聚合资源允许用户通过 kubectl apply collectionresource <collectionresource name> 来创建或者更新一个 Collection Resource,用户随意的配置 Collection Resource 的资源类型

apiVersion: clusterpedia.io/v1beta1
kind: CollectionResource
metadata:
  name: workloads
resourceTypes:
- group: apps
  resource: deployments
- group: apps
  resource: daemonsets
- group: apps
  resource: statefulsets
- group: batch
  resource: cronjobs

当前还未支持自定义聚合资源

2.4 - 集群自动接入策略(ClusterImportPolicy)

自定义资源 ClusterImportPolicy 定义了某种类型的资源应该如何转换成 PediaCluster,这样 clusterpedia 便可以根据某种资源来自动的创建、更新和删除 PediaCluster

首先需要在 ClusterImportPolicy 资源中定义监听(想要转换的)的资源类型,我们将被监听的资源称为 Source 资源。

当一个 Source 资源被创建或者删除时,ClusterImportPolicy Controller 会创建相应 PediaClusterLifecycle 资源。 而 PediaClusterLifecycle 会根据具体的 Source 资源来创建,更新以及删除 PediaCluster

在创建和更新 PediaCluster 时,Source 资源可能会将集群的认证信息(例如 CA,Token 等)保存在其他资源中,我们将这些涉及到的其他资源统称为 References 资源。

对于 ClusterImportPolicyPediaClusterLifecycle 的调协由 Clusterpedia Controller Manager 内的 ClusterImportPolicy ControllerPediaClusterLifecycle Controller 负责

ClusterImportPolicyPediaCusterLifecycle 资源结构的更新可能会比较频繁,为了避免对 cluster.clusterpedia.io group 带来不必要的影响,所以放在 policy.clusterpedia.io group 中, 未来 1.0 发布时,可能会迁移到 cluster.clusterpedia.io 中。

ClusterImportPolicy

一个完整 ClusterImportPolicy 示例如下:

apiVersion: policy.clusterpedia.io/v1alpha1
kind: ClusterImportPolicy
metadata:
  name: mcp
spec:
  source:
    group: "cluster.example.io"
    resource: clusters
    selectorTemplate: ""
  references:
    - group: ""
      resource: secrets
      namespaceTemplate: "{{ .source.spec.authSecretRef.namespace }}"
      nameTemplate: "{{ .source.spec.authSecretRef.name }}"
      key: authSecret
  nameTemplate: "mcp-{{ .source.metadata.name }}"
  template: |
    spec:
      apiserver: "{{ .source.spec.apiEndpoint }}"
      caData: "{{ .references.authSecret.data.ca }}"
      tokenData: "{{ .references.authSecret.data.token }}"
      syncResources:
        - group: ""
          resources:
          - "pods"
        - group: "apps"
          resources:
          - "*"    
  creationCondition: |
    {{ if ne .source.spec.apiEndpoint "" }}
      {{ range .source.status.conditions }}
        {{ if eq .type "Ready" }}
          {{ if eq .status "True" }} true {{ end }}
        {{ end }}
      {{ end }}
    {{ end }}    

主要分为三部分

  • spec.sourcespec.references 分别定义 Source 资源和 References 资源
  • spec.nameTemplate 定义生成的 PediaClusterLifecyclePediaCluster 的名称,可以根据 Source 资源进行渲染
  • spec.templatespec.creationCondition 定义资源转换策略。

references,template,creationCondition 内的模板均支持由 sprig 提供的 70 多种模版函数Sprig Function Documentation

Source 和 References 资源

ClusterImportPolicy 资源中我们首先需要定义的就是 Source 资源类型以及 References 资源

apiVersion: policy.clusterpedia.io/v1alpha1
kind: ClusterImportPolicy
metadata:
  name: multi-cluster-polatform
spec:
  source:
    group: "example.io"
    resource: clusters
    versions: []
    selectorTemplate: |
            {{ if eq .source.metadata.namespace "default" }} true {{ end }}
  references:
    - group: ""
      resource: secrets
      versions: []
      namespaceTemplate: "{{ .source.spec.secretRef.namespace }}"
      nameTemplate: "{{ .source.spec.secretRef.name }}"
      key: secret

Source 资源通过 spec.source.groupspec.source.resource 指定了资源组和资源名称。我们也可以使用 spec.source.versions 来限制 Source 的资源版本,默认是不会对 Source 资源版本进行限制

一种 Source 资源只能有一个负责转换该资源的 ClusterImportPolicy 资源

用户也可以通过 spec.source.selectorTemplate 字段来过滤 Source

apiVersion: policy.clusterpedia.io/v1alpha1
kind: ClusterImportPolicy
metadata:
  name: kubevela
spec:
  source:
    group: ""
    resource: secrets
    selectorTemplate: |
      {{ if eq .source.metadata.namespace "vela-system" }}
        {{ if .source.metadata.labels }}
          {{ eq (index .source.metadata.labels "cluster.core.oam.dev/cluster-credential-type") "X509Certificate" }}
        {{ end }}
      {{ end }}      

source 资源可以通过 {{ .source.<field> }} 来用于其他的模版字段

spec.references 中定义了在转换过程中涉及到的资源,我们需要指定资源的类型,以及通过 namespace 和 name 模版来获取具体的 reference 资源。我们也可以和 Source 资源一样对 Reference 资源的版本进行限制。

除此之外还要为 reference 资源设置一个 key,这个 key 会以 {{ .references.<key> }} 的方式来让后续模版字段使用

spec.references 中后面的项也可以通过 .references.<key> 来引用前面的项

spec:
  references:
  - group: a.example.io
    resource: aresource
    namespaceTemplate: "{{ .source.spec.aNamespace }}"
    nameTemplate: "{{ .source.spec.aName }}"
    key: refA
  - group: b.example.io
    resource: bresource
    namespaceTemplate: "{{ .references.refA.spec.bNamespace }}"
    nameTemplate: "{{ .references.refA.spec.bName }}"
    key: refB

PediaClusterLifecycle

当一个 Source 被创建后,ClusterImportPolicy Controller 会根据 ClusterImportPolicy 创建相应的 PediaClusterLifecycle 资源。

PediaClusterLifecycle 资源的名字是通过 ClusterImportPolicyspec.nameTemplate 字段来设置的。

apiVersion: policy.clusterpedia.io/v1alpha1
kind: ClusterImportPolicy
metadata:
  name: multi-cluster-platform
spec:
  nameTemplate: "mcp-{{ .source.metadata.namespace }}-{{ .source.metadata.name }}"

nameTemplate 只能根据 Source 资源来渲染模版,通常根据是否为 Cluster Scoped 资源来设置该字段:

  • nameTemplate: "<prefix>-{{ .source.metadata.namespace}}-{{ .source.metadata.name }}"
  • nameTemplate: "<prefix>-{{ .source.metadata.name }}"

nameTemplate 前缀通常是多云平台或者其他有意义的名字,当然也可以没有前缀。

PediaClusterLifecycle 中会设置具体的 source 资源和 references 资源以及转换策略

apiVersion: policy.clusterpedia.io/v1alpha1
kind: PediaClusterLifecycle
metadata:
  name: <prefix>-example
spec:
  source:
    group: example.io
    version: v1beta1
    resource: clusters
    namespace: ""
    name: example
  references:
    - group: ""
      resource: secrets
      version: v1
      namespaceTemplate: "{{ .source.spec.secretRef.namespace }}"
      nameTemplate: "{{ .source.spec.secretRef.name }}"
      key: secret

PediaClusterLifecyclespec.source 设置了一个具体的 Source 资源,包括了资源的具体版本,命名空间和名称。

spec.references 相比 ClusterImportPolicy 包含了具体的资源版本,其他字段和 ClusterImportPolicy 内的 References 定义相同。 references 资源的命名空间和名字会在转换资源时进行解析。

PediaClusterLifecycle 和 PediaCluster

PediaClusterLifecycle 的名字会和 PediaCluster 进行一一对应,PediaClusterLifecycle 根据转换策略创建和更新同名的 PediaCluster

PediaCluster 转换策略

我们在定义转换策略时,主要关注以下方面:

  • 用于创建或者更新 PediaCluster 的模版
  • 什么时候触发 PediaCluster 的创建

ClusterImportPolicy 中,我们使用 spec.templatespec.creationCondition 来定义他们

apiVersion: policy.clusterpedia.io/v1alpha1
kind: ClusterImportPolicy
metadata:
  name: mcp
spec:
... other fields
  template: |
    spec:
      apiserver: "{{ .source.spec.apiEndpoint }}"
      caData: "{{ .references.authSecret.data.ca }}"
      tokenData: "{{ .references.tokenData.data.token }}"
      syncResources:
        - group: ""
          resources:
          - "pods"
        - group: "apps"
          resources:
          - "*"    
  creationCondition: |
    {{ if ne .source.spec.apiEndpoint "" }}
      {{ range .source.status.conditions }}
        {{ if eq .type "Ready" }}
          {{ if eq .status "True" }} true {{ end }}
        {{ end }}
      {{ end }}
    {{ end }}    

这两个字段都是模版字段,需要根据 Source 资源和 References 资源来渲染。

Source 资源被创建后,ClusterImportPolicy Controller 会根据 ClusterImportPolicy 创建对应的 PediaClusterLifecycle,并且 PediaClusterLifecycle 中也会包含转换策略。

当然如果 ClusterImportPolicy 内的策略发生修改,也会同步给所属的所有 PediaClusterLifecycle 资源。

apiVersion: policy.clusterpedia.io/v1alpha1
kind: ClusterImportPolicy
metadata:
  name: mcp-example
spec:
... other fields
  template: |
    spec:
      apiserver: "{{ .source.spec.apiEndpoint }}"
      caData: "{{ .references.authSecret.data.ca }}"
      tokenData: "{{ .references.tokenData.data.token }}"
      syncResources:
        - group: ""
          resources:
          - "pods"
        - group: "apps"
          resources:
          - "*"    
  creationCondition: |
    {{ if ne .source.spec.apiEndpoint "" }}
      {{ range .source.status.conditions }}
        {{ if eq .type "Ready" }}
          {{ if eq .status "True" }} true {{ end }}
        {{ end }}
      {{ end }}
    {{ end }}    

PediaClusterLifecycle 会负责根据 spec.creationConditionspec.template 来创建更新具体的 PediaCluster

Creation Condition

我们有时在 Source 资源创建后并不会立刻创建 PediaCluster, 而是需要等到 Source 资源某些字段或者某些状态就绪后再创建 PediaCluster

spec.creationCondition 使用模版语法来判断是否满足创建条件,当模版渲染后的值为 True(大小写模糊)后则会根据 spec.Template 创建 PediaCluster

如果 PediaCluster 已经存在,spec.creationCondition 不会影响后续对 PediaCluster 的更新。

PediaCluster Template

spec.template 定义了 PediaCluster 资源模版,在创建或者更新 PediaCluster 时,会根据 Source 资源和 References 资源来渲染出具体的资源。

PediaCluster 模版可以分成三部分:

  • 元信息:labels 和 annotations
  • 集群访问与认证字段:spec.apiserverspec.caDataspec.tokenDataspec.certDataspec.keyData 还有 spec.kubeconfig
  • 资源同步字段:spec.syncResourcesspec.syncAllCustomResourcesspec.syncResourcesRefName

PediaCluster 资源的元信息资源同步字段只有在创建 PediaCluser 时才会有效,在更新 PediaCluster 资源时,只会更新集群访问与认证字段

PediaCluster 的删除

如果一个 PediaCluster 是由 PediaClusterLifecycle 创建,那么会将 PediaClusterLifecycle 设置为该 PediaCluster 资源的 owner

apiVersion: cluster.clusterpedia.io/v1alpha2
kind: PediaCluster
metadata:
  name: mcp-example
  ownerReferences:
  - apiVersion: policy.clusterpedia.io/v1alpha1
    kind: PediaClusterLifecycle
    name: mcp-example
    uid: f932483a-b1c5-4894-a524-00f78ea34a9f

当一个 Source 资源被删除时,会同步删除 PediaClusterLifecyclePediaCluster 会自动删除。

如果 PediaClusterPediaClusterLifecycle 前已经出现了,那么 Source 删除时不会自动的删除 PediaCluster

未来会增加 DeletionCondition 来允许用户强制或者提前删除 PediaCluster

3 - 使用

3.1 - 集群接入

Clusterpedia 使用自定义资源 PediaCluster 资源来代表接入的集群

apiVersion: cluster.clusterpedia.io/v1alpha2
kind: PediaCluster
metadata:
  name: cluster-example
spec:
  apiserver: "https://10.30.43.43:6443"
  kubeconfig:
  caData:
  tokenData:
  certData:
  keyData:
  syncResources: []

用户有两种方式来配置接入的集群:

  1. 直接配置 base64 编码的 kube config 到 kubeconfig 字段用于集群连接和验证
  2. 分别配置接入集群的地址,以及验证信息

在使用 apiserver 字段来设置接入集群的地址时,验证字段的配置有多种选择:

  • caData + tokenData
  • caData + certData + keyData

caData 在集群 APIServer 允许 Insecure 连接的情况下,也可以不填

这些验证字段都需要 base64 编码,如果这些字段的值是直接从 ConfigMap 或者 Secret 中获取的话,那么就已经 base64 过。

使用 kube config 来接入集群

使用 kube config 来连接和验证集群是最简单的一种方式。

首先需要将接入集群的 kube config base64 编码。

# mac
cat ./kubeconfig | base64

# linux
cat ./kubeconfig | base64 -w 0
# 输出 base64 编码后的配置
YXBpVmVyc2lvbjogdjEKY2x1c3RlcnM6Ci0gY2x1c3RlcjoKICAgIGNlcnRpZmljYXRlLWF1dGhvcml0eS1kYXRhOiBMUzB0TFMxQ1JVZEpUaUJEUlZKVVNVWkpRMEZVUlMwdExTMHRDazFKU1VNdmFrTkRRV1ZoWjBGM1NVSkJaMGxDUVVSQlRrSm5hM0ZvYTJsSE9YY3dRa0ZSYzBaQlJFRldUVkpOZDBWUldVUldVVkZFUlhkd2NtUlhTbXdLWTIwMWJHUkhWbnBOUWpSWVJGUkplRTFFYTNsT1JFVjNUVlJOZVU1R2IxaEVWRTE0VFVScmVVMXFSWGROVkUxNVRrWnZkMFpVUlZSTlFrVkhRVEZWUlFwQmVFMUxZVE5XYVZwWVNuVmFXRkpzWTNwRFEwRlRTWGRFVVZsS1MyOWFTV2gyWTA1QlVVVkNRbEZCUkdkblJWQkJSRU5EUVZGdlEyZG5SVUpCVHk5VENuWnRhMVU1YmsxdVVsUklUM2x2SzNoamRGUkpZMGxQWW5NemMwRjVjVEkyZGpSUVlrVnRiM1pXTTJ4UE9WUXdNVEYyY0U5NlMwcHlPVUZ4ZVZaTVJuWUtWWEZCUkhCVGFrTTNXWGQzTW5ad1NsZDNiREV5U2xCdlVtMXhaMUZCU0ZOa1lsSnBVM0JEVERSdWRqbHZSMjVWT1dJMmRsbFdTeTlpUml0a1VWRkNTQXBuUTFoNk5uWm9UR1k0V21kMk4ydFVRMkpCZGtGUGFFOU9TbFUzTWxsWVRFOHpUMGxaUWpKdmExTkNSR0ZWVWpOdk5ucHdaR1ZXVGt0NVYwRXlOVkEzQ2tSb2JrOHlUazAxUXpscFJFUnFUVFJMWTJGVGEzSlBTa0p2YlVsc1NIRlpSalJ3VlhkVFRsRnZjR1ZHUlZSeVozWnpjVGt3U2tzMllVSlZTMHQ1YWpZS0syTkdkakkzUzBrNEsxWk1VRXRhU1RFMmMyNU1ibmcyUlhSVGF6WnRaakpYVEhkSlpsaHlRbGd3UkVzdllYQkVRMDE1UjJwRWIyZENhR3BKU1Zob1ZBcDJialZRWm5kRldVTnNkR1pGVEVoS1NrZFZRMEYzUlVGQllVNWFUVVpqZDBSbldVUldVakJRUVZGSUwwSkJVVVJCWjB0clRVRTRSMEV4VldSRmQwVkNDaTkzVVVaTlFVMUNRV1k0ZDBoUldVUldVakJQUWtKWlJVWkpWRGhMUkhkQ2JVVnZNSGxhZFVGRVpraGtLelExTDNaRll6ZE5RbFZIUVRGVlpFVlJVVThLVFVGNVEwTnRkREZaYlZaNVltMVdNRnBZVFhkRVVWbEtTMjlhU1doMlkwNUJVVVZNUWxGQlJHZG5SVUpCVDBGNVZIUTRTM1pGTjBkdlJFaFFUMDlwZGdveVIySTJXV1ZzVVU1S2NVTXphMWRJT1hjMU5URk5hR1p2UzNaaU0yMVZhVVY2WlZNd09VTndaVVFyVEZoNVpubHFRemhaWWtKeFFqWlhTRmhOWldNckNucFBkRE5QYXpSWVYwRm1aVlZaVFhoT1ExRkpibGM0Y2pJNGNtWm5ibEVyYzFOQ2RIUXllRVJRTjFSWlkwOW9OVlpHWmtJMkszSnRUbUZUYmxaMU5qZ0tTRkZ4ZGxGTU5FRlhiVmhrUjA5alJXTkJSVGhZZGtkaU9XaHdTalZOY2tSSGR6UTBVVFl5T0c5WWF6WjBOMDFhV1RGT01VTlFkVzlIWjFWbVMxTjNiZ28xTVVGV1JURk9WVmROVjB0RVFYaGFhMkk0YkVodlIzVldhREZ6V21kM1NuSlJRalI1Y2xoMWNteEdOMFkyYlZSbFltNHJjRFZLTTB0b1QwVjRLemxzQ2pGWGRrd3diV2t4TDFKMmJWSktObTExWW10aldVd3pOMUZKV2pJMVlYZHlhRVpNTjBaMWVqTlJTVEZxVFRkWU1IWkVUMlZVTTJWdVZVRkNaVzVTTVM4S1VubG5QUW90TFMwdExVVk9SQ0JEUlZKVVNVWkpRMEZVUlMwdExTMHRDZz09CiAgICBzZXJ2ZXI6IGh0dHBzOi8vMTAuNi4xMDAuMTA6NjQ0MwogIG5hbWU6IGt1YmVybmV0ZXMKY29udGV4dHM6Ci0gY29udGV4dDoKICAgIGNsdXN0ZXI6IGt1YmVybmV0ZXMKICAgIHVzZXI6IGt1YmVybmV0ZXMtYWRtaW4KICBuYW1lOiBrdWJlcm5ldGVzLWFkbWluQGt1YmVybmV0ZXMKY3VycmVudC1jb250ZXh0OiBrdWJlcm5ldGVzLWFkbWluQGt1YmVybmV0ZXMKa2luZDogQ29uZmlnCnByZWZlcmVuY2VzOiB7fQp1c2VyczoKLSBuYW1lOiBrdWJlcm5ldGVzLWFkbWluCiAgdXNlcjoKICAgIGNsaWVudC1jZXJ0aWZpY2F0ZS1kYXRhOiBMUzB0TFMxQ1JVZEpUaUJEUlZKVVNVWkpRMEZVUlMwdExTMHRDazFKU1VSSlZFTkRRV2R0WjBGM1NVSkJaMGxKV2s0eVNscE5TbnAwU21kM1JGRlpTa3R2V2tsb2RtTk9RVkZGVEVKUlFYZEdWRVZVVFVKRlIwRXhWVVVLUVhoTlMyRXpWbWxhV0VwMVdsaFNiR042UVdWR2R6QjVUVlJCTlUxcVVYaE5SRVY2VFdwU1lVWjNNSGxOYWtFMVRXcFJlRTFFUlhwTmFtaGhUVVJSZUFwR2VrRldRbWRPVmtKQmIxUkViazQxWXpOU2JHSlVjSFJaV0U0d1dsaEtlazFTYTNkR2QxbEVWbEZSUkVWNFFuSmtWMHBzWTIwMWJHUkhWbnBNVjBackNtSlhiSFZOU1VsQ1NXcEJUa0puYTNGb2EybEhPWGN3UWtGUlJVWkJRVTlEUVZFNFFVMUpTVUpEWjB0RFFWRkZRVFZEUkdSYVdIcEliMXAxVVRKeFJEZ0tTakpRZGtWdWEyTk1UV05RVG14RE1DOVRTR1YzV25kME5FRjRLM2RDWTFSSVJ6aGpWakJhZUZSYVQwdDNPSFJ4UWxrMk1tcGtOM1p4VkdoeFRWbHdad3AyYzNwSFVXeHlXbGRyZHpSUmFrUldORnBLY1dSbFRITkRVV3BqZUZsa05Ea3JSalEyYkVsS1VUSjVjRXhTUjBkb2NGTlpZMlYzWkdOTVkweHNTamRIQ21wRlJFTnlVRGxrWTFsSWRWUTFlSE5YVG5aQlFXcG5RM051UTNsU1ZXbExOVzAyTDFaR1JEQllTVFp6TlZFclFuZDBPVXNyUzFkblJrSlBVQ3M0TlRBS1Vra3ZZblJSYTJsdmNIZFphMGR1WmtkVE9FeEJiM2t2TTBwUWFsTXlWbXAwUVN0aVR6SnhUa1pFTmpWcWEwRXhWa05XVGxFeFIxVmphV1pYUTFaQ2RRcHpOM2hQUWpnME9WZzVjMUZ6TVhaTlpWSTNTbTh6VjBSRFJEWm9lVTFXZDNOb1FqbEdhR2QxYm5acFNFRlRibkJ5UTJWME9EUjJaMnBSYVdWT1RITmhDbWRFZEhaRlVVbEVRVkZCUW04eFdYZFdSRUZQUW1kT1ZraFJPRUpCWmpoRlFrRk5RMEpoUVhkRmQxbEVWbEl3YkVKQmQzZERaMWxKUzNkWlFrSlJWVWdLUVhkSmQwUkJXVVJXVWpCVVFWRklMMEpCU1hkQlJFRm1RbWRPVmtoVFRVVkhSRUZYWjBKVFJTOURaemhCV21oTFRrMXRZbWRCTTNnelpuVlBaamQ0U0FwUGVrRk9RbWRyY1docmFVYzVkekJDUVZGelJrRkJUME5CVVVWQk5XNWlRME5LYTBwTk5qQkRjVlZsZFdWVVUwbzBaRXBWWkc5S1NHVkhVblJGTWtKRkNrOVNXWEJIVUVVMllqUk5VVlJYY3pSbFZrOTFiRlUzYnpabU9WZFFVV1pDWm5JMmVGSlBXRFo1YUVoM2NIcDNkRVpVVW1od1lqaE5TVWxKV2pscWRqWUtaVVZ3TXpoWmFtUnBPVkV3SzBSaFkzRkxka0pVTURsMVEzWmtNR2x3UnpkTFNuVlNibkZMVVd4VWNtVnRkWFJsVGpOMk9HOUNTVGxXWjJsc2JXUllaZ3BwWkdGS1lqUlJaelpZVkdvemNFMUdkbFpqWTNOSGFWZG9UMHh5T1ZaSVZDdFFWazVaTjB4WlVHeG1Xa2RETkRCSk1URmlTVFZuUlZadVUydHZNa1JqQ21Od1NXOHJNbmRWZFRGU1IybExZMUp3V0RSb1FtUnBORWxYYlM4ek5sTXhaM2gzTW1KMFdFOWxNV3Q2T1c5SFlVNVplazVXU1VObkwzZDNiRzVEYVVNS2FtWjRiVFJJZWtOR1NXcHZRMGRxVFdWWVJFMVhieTlGT0d0U2RuaDFhMnQzYlc1MWN6aHpVV05FTVcxUkswZFFlbWM5UFFvdExTMHRMVVZPUkNCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2c9PQogICAgY2xpZW50LWtleS1kYXRhOiBMUzB0TFMxQ1JVZEpUaUJTVTBFZ1VGSkpWa0ZVUlNCTFJWa3RMUzB0TFFwTlNVbEZiM2RKUWtGQlMwTkJVVVZCTlVORVpGcFlla2h2V25WUk1uRkVPRW95VUhaRmJtdGpURTFqVUU1c1F6QXZVMGhsZDFwM2REUkJlQ3QzUW1OVUNraEhPR05XTUZwNFZGcFBTM2M0ZEhGQ1dUWXlhbVEzZG5GVWFIRk5XWEJuZG5ONlIxRnNjbHBYYTNjMFVXcEVWalJhU25Ga1pVeHpRMUZxWTNoWlpEUUtPU3RHTkRac1NVcFJNbmx3VEZKSFIyaHdVMWxqWlhka1kweGpUR3hLTjBkcVJVUkRjbEE1WkdOWlNIVlVOWGh6VjA1MlFVRnFaME56YmtONVVsVnBTd28xYlRZdlZrWkVNRmhKTm5NMVVTdENkM1E1U3l0TFYyZEdRazlRS3pnMU1GSkpMMkowVVd0cGIzQjNXV3RIYm1aSFV6aE1RVzk1THpOS1VHcFRNbFpxQ25SQksySlBNbkZPUmtRMk5XcHJRVEZXUTFaT1VURkhWV05wWmxkRFZrSjFjemQ0VDBJNE5EbFlPWE5SY3pGMlRXVlNOMHB2TTFkRVEwUTJhSGxOVm5jS2MyaENPVVpvWjNWdWRtbElRVk51Y0hKRFpYUTROSFpuYWxGcFpVNU1jMkZuUkhSMlJWRkpSRUZSUVVKQmIwbENRVUU0YTFZd01uSk5Tbm8zWkVkMmRRcHFORFJXZUdkTFZqUXhZbVJvTldJeFYwYzBUVEV6Y0VkWldUQnFhSGswT0RKa2JtcFVhVUpGTTNKU2JHWkxjSFZWUVZVMllXTmxWVFp3WkhreFUyMW5DbTgzWkVkYVJYQXpUMVZKVkVkU1JHSnhVR0ZzTHpCaUx6TjFZbWx1WWxSSGRucE1SVEZ1TDBoSWFrcEtabWhyZEhSd05ITk5jMjl6THlzNVFsWjRWbmNLVkVsR01uTjJWa1Z3WmtWdmVrdGhaMGhXYW5kcVVtZFpiVFpWTkZWYWVIVjJaRmcwVVhGdVVIRm5hVmgyZUd3eU5HeFhibkV6V25wYVQwSjJXa0p6Y2dwM1NWbERlRlJJWWprek5YbGplV3RMS3pKaEwxTlllRGRaUm5GTkwwRXdXbXMyWmxoMVRHeHVVME5wUkdSdlVsUjFWbTFtYWpjMU9VVkRVMjV1YzFCeENreE1hVnBxY1dwc2J6SlNaRlpSVlVOeVRrSk1MMHBGUjJ4aE5IZ3pkRUpxU21NdmFTdDJLekF2Tms1aVdtVm5aMk5tYlcxQk5USk5TRm8xVVVaVVZrb0tkRTkxT0RnMFJVTm5XVVZCTlZKd1FuSmFZazFXVW1sd1dVOVNPVkl4WVdjclZVeHhORlEzUW1sMU5XWkZXQzloZWtoemVsQmlUR0ZvYURaWVFuQjNTQW95YUZKa01XbDJObUZRVkZOSFRYbDFOR2M0WmtSM1owdzJOVE51VVZCVloxUlRURmxVV2xwb2NqUkNPRTUxYmxFMU9XOUZjREUzVW5VNWFIWkhOV1Z5Q204emNIZ3hNRXhRVUdaaUsyUnpNazU2UWxab2IwVlVNSGx5ZFcxbGNXbzFUemxNY1djeFVqRk1NbE5zWlc4M1ZTOXBVRVJMTUd0RFoxbEZRUzkxYkZVS1RHRnBObWRoWVN0VVV5dDRNVEowTlhWblZYaE5kRGROWkhSc2NsRkpjRkl4V2xsV04xQk1kVXBxVDJsSE1HaHdkM2RGWjNkcVdEVXZRMncxU1d0MVNRbzJWaXRKVjFWdFpGcERZbkZoTURsME9XcDZTVXB5TDFjMU5IcFJabmRUWWxsdE9YRjBPVVpZU0cxNWNFMXpUblZKSzBKb1IweENSRGh4UmpKQ1FVaFFDbXhXTkdwSFYxTkJSSG94Y2t0WVNGVkRkRTh4U21KUmMxSTRieXRqWkdGM05XTm1VMGhaYTBObldVVkJNMHc1YlRVd1lqQjZWVEk0TjI5S1lXWXJSbXdLY1RaamFIZEVWVU56WTFseGVtbGhLMmRQV2pSdlozUjVZVmRoVTB0TGEzaEhOVEJwUzFadmIzQjJZVEprV0ZSTVZWVkJNbk5tYjFReWEzaEZXbG9yVEFwS2VXWmhLMU01WTBsdmJWQndhVEl5ZGpVclptVnNSblpxZVhKc1N6bFpRbUZNZUhwamJrZExWa2M1YjBWeWNrOHhVVlZLUlhrNEswZDRWMmxRU0VGU0NqZGxWekZXZVU5TE5HdGFPRGs1UlcxUk1WaGpSMUpyUTJkWlFqa3pUMng1WW1ab1FUUm1jbVZyTm10ck5qSXdPRWQ1YjNseGRUSmlNVlJvZFhOd01EY0tZalZMT1RONWExWmtZazFhT0RSUk9VRTRZVkF2YVZSRWFrSnlRMmQ2WkVSMU5tSlJTakZtZFZKdlZFTnVXVW95TjFsWlMwVXZhbWhrV21KUk1FazJSUXBoVDNwNFprRjVaU3RvYjBVNVdtWm9XVkF5ZDA5blFXbDNabEpMWjBSYWJEQjNhRlJzYkhKbmNUTjJTa0lyYjJoMWJYbGpRa1F4UlRaVFozZ3ZNRnA1Q2k5c2JsSjFVVXRDWjBaTWNGWTVVQzg1Y21GbWJtUjBXRFZZZVZWMFQwMHZRbmt6UlZsbmJGbHZSMDlrUlhGTmFIaFlSeXQzUTFaQ1ZFSlZUMlJ6Y0V3S1RreGlVVkI0YW1KT1ZFMVFTakI2U0ZwcVppdDFhMHBvU1U5MGR6UmlUbk51YzNCa1NsTnpWMmRtTlhVeGRqZFBaMkUyVnpKMGFFRkNSelE1VEZGbFJ3cHRNWEZHUTJkTFpEZFpVRzlMUldKbGIwMXpTRXBSZUhCR2VYWnZSSE40VEZVNU0wOUVVblE1YVVGSFpFMUpZMll5Y25CTkNpMHRMUzB0UlU1RUlGSlRRU0JRVWtsV1FWUkZJRXRGV1MwdExTMHRDZz09Cg==

如果 base64 后存在换行,那么可以使用 base64 -w 0 ./kubeconfig

将 base64 后的内容设置到 PeidaCluster 的 spec.kubeconfig 中即可,并且 spec.apiserver 以及其他验证字段都不需要填写

不过由于集群地址在 kube config 中配置,所以使用 kubectl get pediacluster 时 APIServer 为空

kubectl get pediacluster
# 输出:
NAME           APISERVER URL       VERSION    STATUS
cluster-1                          v1.22.2    Healthy

未来会增加 Mutating admission webhooks 来自动设置 spec.apiserver,当前如果用户想要在 kubectl get 时显示集群地址,那么需要手动额外配置 spec.apiserver 字段

使用 ServiceAccount 来接入集群

用户也可以选择在被接入集群中创建 ServiceAccount 并配置相应的 RBAC 来接入集群。

# 注意:当前 kubectl 连接到被接入集群
kubectl apply -f https://raw.githubusercontent.com/clusterpedia-io/clusterpedia/main/examples/clusterpedia_synchro_rbac.yaml

# 获取 Service Account 对应 CA 和 Token
SYNCHRO_CA=$(kubectl -n default get secret $(kubectl -n default get serviceaccount clusterpedia-synchro -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.ca\.crt}')
SYNCHRO_TOKEN=$(kubectl -n default get secret $(kubectl -n default get serviceaccount clusterpedia-synchro -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}')

$SYNCHRO_CA$SYNCHRO_TOKEN 分别填写到 PediaCluster 资源的 spec.caDataspec.tokenData 字段中

创建 PediaCluster

完善集群的验证信息后,就可以获得一个完整的 PediaCluster 资源了。直接使用 kubectl apply -f 直接创建即可

eg.

apiVersion: cluster.clusterpedia.io/v1alpha2
kind: PediaCluster
metadata:
  name: cluster-example
spec:
  apiserver: https://10.6.100.10:6443
  caData: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeE1Ea3lOREV3TVRNeU5Gb1hEVE14TURreU1qRXdNVE15TkZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTy9TCnZta1U5bk1uUlRIT3lvK3hjdFRJY0lPYnMzc0F5cTI2djRQYkVtb3ZWM2xPOVQwMTF2cE96S0pyOUFxeVZMRnYKVXFBRHBTakM3WXd3MnZwSld3bDEySlBvUm1xZ1FBSFNkYlJpU3BDTDRudjlvR25VOWI2dllWSy9iRitkUVFCSApnQ1h6NnZoTGY4Wmd2N2tUQ2JBdkFPaE9OSlU3MllYTE8zT0lZQjJva1NCRGFVUjNvNnpwZGVWTkt5V0EyNVA3CkRobk8yTk01QzlpRERqTTRLY2FTa3JPSkJvbUlsSHFZRjRwVXdTTlFvcGVGRVRyZ3ZzcTkwSks2YUJVS0t5ajYKK2NGdjI3S0k4K1ZMUEtaSTE2c25Mbng2RXRTazZtZjJXTHdJZlhyQlgwREsvYXBEQ015R2pEb2dCaGpJSVhoVAp2bjVQZndFWUNsdGZFTEhKSkdVQ0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZJVDhLRHdCbUVvMHladUFEZkhkKzQ1L3ZFYzdNQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBT0F5VHQ4S3ZFN0dvREhQT09pdgoyR2I2WWVsUU5KcUMza1dIOXc1NTFNaGZvS3ZiM21VaUV6ZVMwOUNwZUQrTFh5ZnlqQzhZYkJxQjZXSFhNZWMrCnpPdDNPazRYV0FmZVVZTXhOQ1FJblc4cjI4cmZnblErc1NCdHQyeERQN1RZY09oNVZGZkI2K3JtTmFTblZ1NjgKSFFxdlFMNEFXbVhkR09jRWNBRThYdkdiOWhwSjVNckRHdzQ0UTYyOG9YazZ0N01aWTFOMUNQdW9HZ1VmS1N3bgo1MUFWRTFOVVdNV0tEQXhaa2I4bEhvR3VWaDFzWmd3SnJRQjR5clh1cmxGN0Y2bVRlYm4rcDVKM0toT0V4KzlsCjFXdkwwbWkxL1J2bVJKNm11YmtjWUwzN1FJWjI1YXdyaEZMN0Z1ejNRSTFqTTdYMHZET2VUM2VuVUFCZW5SMS8KUnlnPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
  tokenData: ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklrMHRSalJtZGpSdVgxcFljMGxsU1ZneFlXMHpPSFZOY0Zwbk1UTkhiVFpsVFZwQ2JIWk9SbU5XYW5NaWZRLmV5SnBjM01pT2lKcmRXSmxjbTVsZEdWekwzTmxjblpwWTJWaFkyTnZkVzUwSWl3aWEzVmlaWEp1WlhSbGN5NXBieTl6WlhKMmFXTmxZV05qYjNWdWRDOXVZVzFsYzNCaFkyVWlPaUprWldaaGRXeDBJaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5elpXTnlaWFF1Ym1GdFpTSTZJbU5zZFhOMFpYSndaV1JwWVMxemVXNWphSEp2TFhSdmEyVnVMVGsxYTJSNElpd2lhM1ZpWlhKdVpYUmxjeTVwYnk5elpYSjJhV05sWVdOamIzVnVkQzl6WlhKMmFXTmxMV0ZqWTI5MWJuUXVibUZ0WlNJNkltTnNkWE4wWlhKd1pXUnBZUzF6ZVc1amFISnZJaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5elpYSjJhV05sTFdGalkyOTFiblF1ZFdsa0lqb2lNREl5WXpNMk5USXRPR1k0WkMwME5qSmtMV0l6TnpFdFpUVXhPREF3TnpFeE9HUTBJaXdpYzNWaUlqb2ljM2x6ZEdWdE9uTmxjblpwWTJWaFkyTnZkVzUwT21SbFptRjFiSFE2WTJ4MWMzUmxjbkJsWkdsaExYTjVibU5vY204aWZRLkF4ZjhmbG5oR0lDYjJaMDdkT0FKUW11aHVIX0ZzRzZRSVY5Sm5sSmtPUnF5aGpWSDMyMkVqWDk1bVhoZ2RVQ2RfZXphRFJ1RFFpLTBOWDFseGc5OXpYRks1MC10ZzNfYlh5NFA1QnRFOUpRNnNraUt4dDFBZVJHVUF4bG5fVFU3SHozLTU5Vnl5Q3NwckFZczlsQWQwRFB6bTRqb1dyS1lKUXpPaGl5VjkzOWpaX2ZkS1BVUmNaMVVKVGpXUTlvNEFFY0hMdDlyTEJNMTk2eDRkbzA4ZHFaUnVtTzJZRXFkQTB3ZnRxZ2NGQzdtTGlSVVhkWElkYW9CY1BuWXBwM01MU3B5QjJQMV9vSlRFNS1nd3k4N2Jwb3U1RXo2TElSSExIeW5NWXAtWVRLR2hBbDJwMXdJb0tDZUNnQng4RlRfdzM4Rnh1TnE0UDRoQW5RUUh6bU9Ndw==
  syncResources: []

集群查看

集群接入成功后,可以通过 kubectl get pediacluster 命令来查看所有接入的集群,以及集群状态

kubectl get pediacluster
# 输出:
NAME           APISERVER URL               VERSION    STATUS
cluster-1      https://10.6.100.10:6443    v1.22.2    Healthy
cluster-2      https://10.50.10.11:16443   v1.10.11   Healthy

接下来

继续查看 同步集群资源

3.2 - 接入多云平台

0.4.0 后,Clusterpedia 提供了更加友好的接入多云平台的方式。

用户通过创建 ClusterImportPolicy 来自动发现多云平台中纳管的集群,并将这些集群自动同步为 PediaCluster,用户不需要根据纳管的集群来手动去维护 PediaCluster 了。

我们在 Clusterpedia 仓库 中维护了各个多云平台的 ClusterImportPolicy大家也提交用于对接其他多云平台的 ClusterImportPolicy

用户在安装 Clusterpedia 后,创建合适的 ClusterImportPolicy 即可,用户也可以根据自己的需求来创建新的 ClusterImportPolicy

Cluster API ClusterImportPolicy

用户可以参考 Cluster API Quick Start 来安装 Cluster API,或者参考 快速部署 Cluster API + Clusterpedia 来搭建示例环境。

创建用于对接 Cluster API 平台的 ClusterImportPolicy

$ kubectl apply -f https://raw.githubusercontent.com/clusterpedia-io/clusterpedia/main/deploy/clusterimportpolicy/cluster_api.yaml
$ kubectl get clusterimportpolicy
NAME          AGE
cluster-api   4d19h

如果集群中已经存在由 Cluster API 创建的集群,那么可以查看 ClusterPediaCluster 资源

$ kubectl get cluster
NAME                PHASE         AGE     VERSION
capi-quickstart     Provisioned   3d23h   v1.24.2
capi-quickstart-2   Provisioned   3d23h   v1.24.2

$ kubectl get pediaclusterlifecycle
NAME                        AGE
default-capi-quickstart     3d23h
default-capi-quickstart-2   3d23h

$ kubectl get pediacluster
NAME                        READY   VERSION   APISERVER
default-capi-quickstart     True    v1.24.2
default-capi-quickstart-2   True    v1.24.2

PediaCluster 会根据 Cluster 自动创建,并且当 Cluster 的 kubeconfig 发生变动时会自动更新 PediaCluster.

新建一个 Cluster 资源时,Clusterpedia 根据 Cluster API ClusterImportPolicy 等到 ControlPlaneInitialized 为 True 时才会自动创建 PediaCluster,可以通过 kubectl get kubeadmcontrolplane 来查看集群的初始化状态

NAME                    CLUSTER           INITIALIZED   API SERVER AVAILABLE   REPLICAS   READY   UPDATED   UNAVAILABLE   AGE   VERSION
capi-quickstart-2xcsz   capi-quickstart   true                                 1                  1         1             86s   v1.24.2

Cluster 初始化完成后,就可以直接使用 kubectl 来检索多集群资源了

使用 kubectl 前,需要为多集群资源检索生成集群快捷配置 —— 为 kubectl 生成集群访问的快捷配置

$ # Since CNI is not installed, the nodes are not ready.
$ kubectl --cluster clusterpedia get no
CLUSTER                     NAME                                            STATUS     ROLES           AGE   VERSION
default-capi-quickstart-2   capi-quickstart-2-ctm9k-g2m87                   NotReady   control-plane   12m   v1.24.2
default-capi-quickstart-2   capi-quickstart-2-md-0-s8hbx-7bd44554b5-kzcb6   NotReady   <none>          11m   v1.24.2
default-capi-quickstart     capi-quickstart-2xcsz-fxrrk                     NotReady   control-plane   21m   v1.24.2
default-capi-quickstart     capi-quickstart-md-0-9tw2g-b8b4f46cf-gggvq      NotReady   <none>          20m   v1.24.2

Karmada ClusterImportPolicy

对于 Karmada 平台,用户首先需要先将 Clusterpedia 部署在 Karmada APIServer 中,部署步骤可以参考 https://github.com/Iceber/deploy-clusterpedia-to-karmada

创建用于对接 Karmada 平台的 ClusterImportPolicy

$ kubectl create -f https://raw.githubusercontent.com/clusterpedia-io/clusterpedia/main/deploy/clusterimportpolicy/karmada.yaml
$ kubectl get clusterimportpolicy
NAME      AGE
karmada   7d5h

查看 Karmada ClusterPediaClusterLifecycle

$ kubectl get cluster
NAME      VERSION   MODE   READY   AGE
argocd              Push   False   8d
member1   v1.23.4   Push   True    22d
member3   v1.23.4   Pull   True    22d

$ kubectl get pediaclusterlifecycle
NAME              AGE
karmada-argocd    7d5h
karmada-member1   7d5h
karmada-member3   7d5h

Clusterpedia 会为每一个 Karmada Cluster 创建对应的 PediaClusterLifecycle,可以使用 kubectl describe pediaclusterlifecycle <name> 来查看 Karmada Cluster 与 PediaCluster 的转换状态

未来会在 kubectl get pediaclusterlifecycle 中详细状态

查看成功创建的 PediaCluster

NAME              APISERVER                 VERSION   STATUS
karmada-member1   https://172.18.0.4:6443   v1.23.4   Healthy

karmada clusterimportpolicy 要求 karmada 集群为 Push 模式,并且处于 Ready 状态,所以为 member-1 集群创建了 karmada-member-1 pediacluster 资源。

VCluster ClusterImportPolicy

创建用于自动发现 VClusterClusterImportPolicy

$ kubectl create -f https://raw.githubusercontent.com/clusterpedia-io/clusterpedia/main/deploy/clusterimportpolicy/vcluster.yaml
$ kubectl get clusterimportpolicy
NAME      AGE
vclsuter  5h

需要注意,VCluster 集群在创建时需要保证生成的 kubeconfig 的 Server 地址可以由宿主集群内的其他 Pod 访问。

可以设置为 VCluster Service 域名,也可以是 Node IP 或者 Ingress 地址

syncer:
  extraArgs:
  - --out-kube-config-server=https://<vcluster name>.<namespace>.svc
  - --tls-san=<vcluster name>.<namespace>.svc,127.0.0.1

在 default 命名空间创建两个 VCluster, 创建虚拟集群 vcluster-1

# vcluster-1.yaml
syncer:
  extraArgs:
  - --out-kube-config-server=https://vcluster-1.default.svc
  - --tls-san=vcluster-1.default.svc,127.0.0.1
$ vcluster create -n default -f vcluster-1.yaml vcluster-1

创建虚拟集群 vcluster-2

# vcluster-2.yaml
syncer:
  extraArgs:
  - --out-kube-config-server=https://vcluster-2.default.svc
  - --tls-san=vcluster-2.default.svc,127.0.0.1
$ vcluster create -n default -f vcluster-2.yaml vcluster-2

查看所有的 VCluster 集群

$ vcluster list
 NAME              NAMESPACE         STATUS    CONNECTED   CREATED                         AGE
 caiwei-vcluster   caiwei-vcluster   Running               2022-08-26 16:10:52 +0800 CST   484h49m6s
 vcluster-1        default           Running               2022-09-15 20:57:59 +0800 CST   1m59s
 vcluster-2        default           Running               2022-09-15 20:59:34 +0800 CST   24s

我们可以直接使用 kubectl + Clusterpedia 来检索任意 VCluster 内的资源

使用 kubectl 前,需要为多集群资源检索生成集群快捷配置 —— 为 kubectl 生成集群访问的快捷配置

 $ kubectl --cluster clusterpedia get po -A
NAMESPACE     CLUSTER                              NAME                       READY   STATUS    RESTARTS   AGE
default       vc-caiwei-vcluster-caiwei-vcluster   backend-77f8f45fc8-5ssww   1/1     Running   0          20d
default       vc-caiwei-vcluster-caiwei-vcluster   backend-77f8f45fc8-j5m4c   1/1     Running   0          20d
default       vc-caiwei-vcluster-caiwei-vcluster   backend-77f8f45fc8-vjzf6   1/1     Running   0          20d
kube-system   vc-default-vcluster-1                coredns-669fb9997d-cxktv   1/1     Running   0          3m40s
kube-system   vc-default-vcluster-2                coredns-669fb9997d-g7w8l   1/1     Running   0          2m6s
kube-system   vc-caiwei-vcluster-caiwei-vcluster   coredns-669fb9997d-x6vc2   1/1     Running   0          20d

$ kubectl --cluster clusterpedia get ns
CLUSTER                              NAME              STATUS   AGE
vc-default-vcluster-2                default           Active   2m49s
vc-default-vcluster-1                default           Active   4m24s
vc-caiwei-vcluster-caiwei-vcluster   default           Active   20d
vc-default-vcluster-2                kube-node-lease   Active   2m49s
vc-default-vcluster-1                kube-node-lease   Active   4m24s
vc-caiwei-vcluster-caiwei-vcluster   kube-node-lease   Active   20d
vc-default-vcluster-2                kube-public       Active   2m49s
vc-default-vcluster-1                kube-public       Active   4m24s
vc-caiwei-vcluster-caiwei-vcluster   kube-public       Active   20d
vc-default-vcluster-2                kube-system       Active   2m49s
vc-default-vcluster-1                kube-system       Active   4m24s
vc-caiwei-vcluster-caiwei-vcluster   kube-system       Active   20d

Clusterpedia 会自动发现宿主集群内的虚拟集群(VCluster),并根据 VCluster ClusterImportPolicy 创建相应的 PediaCluster,用户可以直接访问 Clusterpedia 来检索资源

$ kubectl get pediaclusterlifecycle
NAME                                 AGE
vc-caiwei-vcluster-caiwei-vcluster   20d
vc-default-vcluster-1                5m57s
vc-default-vcluster-2                4m24s

$ kubectl get pediacluster
NAME                                 READY   VERSION        APISERVER
vc-caiwei-vcluster-caiwei-vcluster   True    v1.23.5+k3s1   https://caiwei-vcluster.caiwei-vcluster.svc
vc-default-vcluster-1                True    v1.23.5+k3s1   https://vcluster-1.default.svc
vc-default-vcluster-2                True    v1.23.5+k3s1   https://vcluster-2.default.svc

新建 ClusterImportPolicy

如果 Clusterpedia 仓库 中没有维护某个平台的 ClusterImportPolicy,那么我们可以新建 ClusterImportPolicy

关于 ClusterImportPolicy 原理和字段的详细描述可以参考 集群自动接入策略

现在假定有一个多云平台 MCP,该平台使用自定义资源 —— Cluster 来代表被纳管的集群,并且将集群的认证信息保存在和集群同名的 Secret 中

apiVersion: cluster.mcp.io
kind: Cluster
metadata:
  name: cluster-1
spec:
  apiEndpoint: "https://172.10.10.10:6443"
  authSecretRef:
    namespace: "default"
    name: "cluster-1"
status:
  conditions:
    - type: Ready
      status: True
---
apiVersion: v1
kind: Secret
metadata:
  name: cluster-1
data:
  ca: **cluster ca bundle**
  token: **cluster token**

我们为 MCP 平台定义一个 ClusterImportPolicy 资源,并且默认同步 pods 和 apps group 下的资源

apiVersion: policy.clusterpedia.io/v1alpha1
kind: ClusterImportPolicy
metadata:
  name: mcp
spec:
  source:
    group: "cluster.mcp.io"
    resource: clusters
    versions: []
  references:
    - group: ""
      resource: secrets
      versions: []
      namespaceTemplate: "{{ .source.spec.authSecretRef.namespace }}"
      nameTemplate: "{{ .source.spec.authSecretRef.name }}"
      key: authSecret
  nameTemplate: "mcp-{{ .source.metadata.name }}"
  template: |
    spec:
      apiserver: "{{ .source.spec.apiEndpoint }}"
      caData: "{{ .references.authSecret.data.ca }}"
      tokenData: "{{ .references.authSecret.data.token }}"
      syncResources:
        - group: ""
          resources:
          - "pods"
        - group: "apps"
          resources:
          - "*"
      syncResourcesRefName: ""    
  creationCondition: |
    {{ if ne .source.spec.apiEndpoint "" }}
      {{ range .source.status.conditions }}
        {{ if eq .type "Ready" }}
          {{ if eq .status "True" }} true {{ end }}
        {{ end }}
      {{ end }}
    {{ end }}    
  • spec.source 定义了需要监听的资源 Cluster
  • spec.references 定义了将 MCP Cluster 转换为 PediaCluster 时涉及到的资源,当前只有 secrets 资源
  • spec.nameTemplate 会根据 MCP Cluster 资源渲染出 PediaCluster 资源的名字
  • spec.template 通过 MCP Cluster 和 spec.references 中定义的资源来渲染出 PediaCluster 资源,具体规则可以参考 PediaCluster Template
  • spec.creationCondition 可以根据 MCP Cluster 和 spec.references 定义的资源来可以决定了什么时候可以创建 PediaCluster,这里定义了当 MCP Cluster 处于 Ready 后再创建 PediaCluster,具体使用可以参考 Creation Condition

3.3 - 同步集群资源

Clusterpedia 的主要功能,便是提供对多集群内的资源进行复杂检索。

通过 PediaCluster 资源来指定该集群中哪些资源需要支持复杂检索,Clusterpedia 会将这些资源实时的通过存储层同步到存储组件

# example
apiVersion: cluster.clusterpedia.io/v1alpha2
kind: PediaCluster
metadata:
  name: cluster-example
spec:
  apiserver: "https://10.30.43.43:6443"
  syncResources:
  - group: apps
    resources:
     - deployments
  - group: ""
    resources:
     - pods
     - configmaps
  - group: cert-manager.io
    versions:
      - v1
    resources:
      - certificates

内置资源同步

PediaCluster 为了方便管理和查看这些同步的资源,用户需要以 Group 为单位来配置资源

syncResources:
 - group: apps
   versions: []
   resources:
     - deployments
     - daemonsets

对于内置资源,不需要填写 versions 字段。

Clusterpedia 会根据该集群内所支持的资源版本自动选择合适的版本来收集, 并且用户无需担心版本转换的问题, Clusterpedia 会开放出该内置资源的所有版本接口。

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis/apps" | jq
{
  "kind": "APIGroup",
  "apiVersion": "v1",
  "name": "apps",
  "versions": [
    {
      "groupVersion": "apps/v1",
      "version": "v1"
    },
    {
      "groupVersion": "apps/v1beta2",
      "version": "v1beta2"
    },
    {
      "groupVersion": "apps/v1beta1",
      "version": "v1beta1"
    }
  ],
  "preferredVersion": {
    "groupVersion": "apps/v1",
    "version": "v1"
  }
}

可以看到 Clusterpedia 支持 v1v1beta2v1beta1 三个版本的 Deployment

自定义资源同步

相比内置资源,自定义资源在资源版本的配置上会稍有不同。

syncResources:
 - group: cert-manager.io
   versions: []
   resources:
    - certificates

用户同样可以忽略 versions 字段,这时 Clusterpedia 就会同步该 Group 在该集群的前三个版本。

以 cert-manager.io 为例,获取被接入集群中 cert-manager.io 支持的 Group

# 在被接入集群内执行
kubectl get --raw="/apis/cert-manager.io" | jq
{
  "kind": "APIGroup",
  "apiVersion": "v1",
  "name": "cert-manager.io",
  "versions": [
    {
      "groupVersion": "cert-manager.io/v1",
      "version": "v1"
    },
    {
      "groupVersion": "cert-manager.io/v1beta1",
      "version": "v1beta1"
    },
    {
      "groupVersion": "cert-manager.io/v1alpha3",
      "version": "v1alpha3"
    },
    {
      "groupVersion": "cert-manager.io/v1alpha2",
      "version": "v1alpha2"
    }
  ],
  "preferredVersion": {
    "groupVersion": "cert-manager.io/v1",
    "version": "v1"
  }
}

可以看到,被接入集群支持 cert-manager.iov1v1beta1v1alpha3v1alpha2 四个版本。

syncResources.[group].versions 为空时,Clusterpedia 就会以 APIGroup.versions 列表的顺序,收集 v1v1beta1v1alpah3 三个版本,而 v1alpha2 不会被收集

指定自定义资源的同步版本

如果用户指定了 versions,那么就会按照 versions 的配置来收集指定的版本资源。

syncResources:
 - group: cert-manager.io
   versions:
    - v1beta1
   resources:
    - certificates

这时,只会收集 v1beta1 版本。

使用注意

自定义资源收集暂时不支持版本转换,收集了哪些版本,那么就只支持哪些资源版本的收集。

这时在检索多集群资源时,如果 cluster-1 只收集了 v1beta1 版本的资源,而检索请求 v1 版本的资源便会忽略 cluster-1 所收集的 v1beta1 版本

需要用户去协调处理自定义资源在多个集群内的版本情况

同步所有的自定义资源

自定义资源类型和版本会随着 CRD 进行变动,当一个 CRD 被创建时,我们不想同时修改 spec.syncResources 来同步资源,这时我们就可以设置 spec.syncAllCustomResources 来同步所有的自定义资源

spec:
  syncAllCustomResources: true

但是需要注意,使用该功能需要在 clustersynchro-manager 中开启相应的 Feature Gate,具体操作可以参考 同步所有自定义资源

使用通配符来同步资源

使用通配符,收集指定组下的所有类型资源

spec:
  syncResources:
  - group: "apps"
    resources:
    - "*"

通过组通配符可以收集指定的 Group 下的所有类型的资源。

例如上例中,便会同步 apps 下的所有资源

使用通配符,收集所有类型的资源

spec:
  syncResources:
  - group: "*"
    resources:
    - "*"

通过全资源通配符 可以同步集群中的内置资源,自定义资源以及聚合式 API 资源。

使用该功能会创建大量的长连接,所以需要谨慎使用,并且在 clustersynchro-manager 中开启相应的 Feature Gate, 具体操作可以参考 同步所有资源

引用 ClusterSyncResources

ClusterSyncResources 用于定义多个 PediaCluster 共同引用的集群资源同步配置,关于 ClusterSyncResources 可以查看 公共的集群资源同步配置(ClusterSyncResources)

PediaCluster 通过 spec.syncResourceRefName 来设置引用的 ClusterSyncResources

apiVersion: cluster.clusterpedia.io/v1alpha2
kind: ClusterSyncResources
metadata:
  name: global-base
spec:
  syncResources:
    - group: ""
      resources:
        - pods
    - group: "apps"
      resources:
        - "*"
---
apiVersion: cluster.clusterpedia.io/v1alpha2
kind: PediaCluster
metadata:
  name: demo1
spec:
  syncResourcesRefName: "global-base"
  syncResources:
    - group: ""
      resources:
        - pods
        - configmaps

如果 PediaCluster 同时设置了 spec.syncResourcesRefNamespec.syncResources,那么会取两者的并集。

上例中,clusterpedia 会同步 demo1 的 pods 和 confgimaps,以及 apps group 下的所有资源。

查看资源同步状态

我们可以通过 PediaCluster 资源的 Status 来查看资源的信息,同步的资源版本和状态以及存储版本

Status 中,资源会有同步版本存储版本

  • 同步版本是 Clusterpedia 从被同步集群中获取到的资源的版本
  • 存储版本是 Clusterpedia 存储到存储层中的版本
status:
  syncResources:
  - group: apps
    resources:
    - name: deployments
      kind: Deployment
      namespaced: true
      syncConditions:
      - lastTransitionTime: "2022-01-13T04:34:08Z"
        status: Syncing
        storageVersion: v1
        version: v1

通常集群资源的同步版本存储版本是相同的。

但是当接入一个比较老的集群时,集群只提供了 v1beta1 版本的 Deployment 资源,而这时资源的同步版本v1beta1存储版本v1

例如,同步 1.10 版本 Kubernetes 的 Deployment 时,同步状态为:

status:
  syncResources:
  - group: apps
    resources:
    - name: deployments
      kind: Deployment
      namespaced: true
      syncConditions:
      - lastTransitionTime: "2022-01-13T04:34:04Z"
        status: Syncing
        storageVersion: v1
        version: v1beta1

对于自定义资源来说,同步版本存储版本是一致的

接下来

资源同步完成后,便可以访问 Clusterpedia检索资源

3.4 - 访问 Clusterpedia

Clusterpedia 主要有两个组件:

  • ClusterSynchroManager 管理 主集群 内的 PediaCluster 资源,通过 PediaCluster 配置认证信息连接到指定集群,并且实时同步相应的资源。
  • APIServer 同样会监听 主集群 内的 PediaCluster 资源,并根据集群同步的资源以兼容 Kubernetes OpenAPI的方式来提供对资源的复杂检索。
  • ControllerManager

并且 Clusterpedia APIServer 会以聚合式 API 的方式注册到 主集群 的 APIServer 中, 这样我们通过和主集群相同的入口便可访问 Clusterpedia

Resources 和聚合资源

Clusterpedia APIServer 会在 Group —— clusterpedia.io 下提供两种检索资源:

kubectl api-resources | grep clusterpedia.io
# 输出:
NAME                 SHORTNAMES    APIVERSION                 NAMESPACED   KIND
collectionresources                clusterpedia.io/v1beta1    false        CollectionResource
resources                          clusterpedia.io/v1beta1    false        Resources
  • Resources 用于指定资源类型的方式来检索,在使用上兼容 Kubernetes OpenAPI
  • CollectionResource 用于检索由多个资源类型聚合而成的新的资源类型,以达到同时检索多种资源的目的

对于 Collection Resource 的概念和使用可以查看 什么是聚合资源(Collection Resource)聚合资源(Collection Resource)检索

访问 Clusterpedia 资源

在检索指定类型的资源时,可以按照 Kubernetes OpenAPI 的 Get/List 规范来请求, 这样我们不仅仅可以使用 URL 来访问 Clusterpedia Resources,还可以直接使用 kubectl 或者 client-go 来检索资源。

Clusterpedia 通过 URL Path 来区分请求是多集群资源还是指定集群:

多集群资源路径 直接以 Resources 资源路径为前缀 /apis/clusterpedia.io/v1beta1/resources

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/version"

指定集群资源路径 在 Resources 资源路径的基础上设置资源名称来指定集群 /apis/clusterpedia.io/v1beta1/resources/clusters/

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/clusters/cluster-1/version"

无论是多集群资源路径还是指定集群的资源路径,都可以在路径后拼接 Kubernetes 的 Get/List Path

为 kubectl 生成集群访问的快捷配置

尽管我们可以使用 URL 来访问 Clusterpedia 资源,但是如果想要更方便的使用 kubectl 来查询的话,就需要配置集群的 kubeconfig cluster 配置。

Clusterpedia 提供了一个简单的脚本来帮助生成 cluster kube config

curl -sfL https://raw.githubusercontent.com/clusterpedia-io/clusterpedia/v0.7.0/hack/gen-clusterconfigs.sh | sh -
# 输出:
Current Context: kubernetes-admin@kubernetes
Current Cluster: kubernetes
        Server: https://10.6.100.10:6443
        TLS Server Name:
        Insecure Skip TLS Verify:
        Certificate Authority:
        Certificate Authority Data: ***

Cluster "clusterpedia" set.
Cluster "cluster-1" set.
Cluster "cluster-2" set.

可以在 hack/gen-clusterconfigs.sh 找到该脚本

脚本会打印当前的集群信息,并将集群中 PediaCluster 配置到 kubeconfig 中。

cat ~/.kube/config
# .kube/config
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeE1Ea3lOREV3TVRNeU5Gb1hEVE14TURreU1qRXdNVE15TkZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTy9TCnZta1U5bk1uUlRIT3lvK3hjdFRJY0lPYnMzc0F5cTI2djRQYkVtb3ZWM2xPOVQwMTF2cE96S0pyOUFxeVZMRnYKVXFBRHBTakM3WXd3MnZwSld3bDEySlBvUm1xZ1FBSFNkYlJpU3BDTDRudjlvR25VOWI2dllWSy9iRitkUVFCSApnQ1h6NnZoTGY4Wmd2N2tUQ2JBdkFPaE9OSlU3MllYTE8zT0lZQjJva1NCRGFVUjNvNnpwZGVWTkt5V0EyNVA3CkRobk8yTk01QzlpRERqTTRLY2FTa3JPSkJvbUlsSHFZRjRwVXdTTlFvcGVGRVRyZ3ZzcTkwSks2YUJVS0t5ajYKK2NGdjI3S0k4K1ZMUEtaSTE2c25Mbng2RXRTazZtZjJXTHdJZlhyQlgwREsvYXBEQ015R2pEb2dCaGpJSVhoVAp2bjVQZndFWUNsdGZFTEhKSkdVQ0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZJVDhLRHdCbUVvMHladUFEZkhkKzQ1L3ZFYzdNQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBT0F5VHQ4S3ZFN0dvREhQT09pdgoyR2I2WWVsUU5KcUMza1dIOXc1NTFNaGZvS3ZiM21VaUV6ZVMwOUNwZUQrTFh5ZnlqQzhZYkJxQjZXSFhNZWMrCnpPdDNPazRYV0FmZVVZTXhOQ1FJblc4cjI4cmZnblErc1NCdHQyeERQN1RZY09oNVZGZkI2K3JtTmFTblZ1NjgKSFFxdlFMNEFXbVhkR09jRWNBRThYdkdiOWhwSjVNckRHdzQ0UTYyOG9YazZ0N01aWTFOMUNQdW9HZ1VmS1N3bgo1MUFWRTFOVVdNV0tEQXhaa2I4bEhvR3VWaDFzWmd3SnJRQjR5clh1cmxGN0Y2bVRlYm4rcDVKM0toT0V4KzlsCjFXdkwwbWkxL1J2bVJKNm11YmtjWUwzN1FJWjI1YXdyaEZMN0Z1ejNRSTFqTTdYMHZET2VUM2VuVUFCZW5SMS8KUnlnPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://10.6.100.10:6443/apis/clusterpedia.io/v1beta1/resources/clusters/cluster-1
  name: cluster-1
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeE1Ea3lOREV3TVRNeU5Gb1hEVE14TURreU1qRXdNVE15TkZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTy9TCnZta1U5bk1uUlRIT3lvK3hjdFRJY0lPYnMzc0F5cTI2djRQYkVtb3ZWM2xPOVQwMTF2cE96S0pyOUFxeVZMRnYKVXFBRHBTakM3WXd3MnZwSld3bDEySlBvUm1xZ1FBSFNkYlJpU3BDTDRudjlvR25VOWI2dllWSy9iRitkUVFCSApnQ1h6NnZoTGY4Wmd2N2tUQ2JBdkFPaE9OSlU3MllYTE8zT0lZQjJva1NCRGFVUjNvNnpwZGVWTkt5V0EyNVA3CkRobk8yTk01QzlpRERqTTRLY2FTa3JPSkJvbUlsSHFZRjRwVXdTTlFvcGVGRVRyZ3ZzcTkwSks2YUJVS0t5ajYKK2NGdjI3S0k4K1ZMUEtaSTE2c25Mbng2RXRTazZtZjJXTHdJZlhyQlgwREsvYXBEQ015R2pEb2dCaGpJSVhoVAp2bjVQZndFWUNsdGZFTEhKSkdVQ0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZJVDhLRHdCbUVvMHladUFEZkhkKzQ1L3ZFYzdNQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBT0F5VHQ4S3ZFN0dvREhQT09pdgoyR2I2WWVsUU5KcUMza1dIOXc1NTFNaGZvS3ZiM21VaUV6ZVMwOUNwZUQrTFh5ZnlqQzhZYkJxQjZXSFhNZWMrCnpPdDNPazRYV0FmZVVZTXhOQ1FJblc4cjI4cmZnblErc1NCdHQyeERQN1RZY09oNVZGZkI2K3JtTmFTblZ1NjgKSFFxdlFMNEFXbVhkR09jRWNBRThYdkdiOWhwSjVNckRHdzQ0UTYyOG9YazZ0N01aWTFOMUNQdW9HZ1VmS1N3bgo1MUFWRTFOVVdNV0tEQXhaa2I4bEhvR3VWaDFzWmd3SnJRQjR5clh1cmxGN0Y2bVRlYm4rcDVKM0toT0V4KzlsCjFXdkwwbWkxL1J2bVJKNm11YmtjWUwzN1FJWjI1YXdyaEZMN0Z1ejNRSTFqTTdYMHZET2VUM2VuVUFCZW5SMS8KUnlnPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://10.6.100.10:6443/apis/clusterpedia.io/v1beta1/resources/clusters/cluster-2
  name: cluster-2
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeE1Ea3lOREV3TVRNeU5Gb1hEVE14TURreU1qRXdNVE15TkZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTy9TCnZta1U5bk1uUlRIT3lvK3hjdFRJY0lPYnMzc0F5cTI2djRQYkVtb3ZWM2xPOVQwMTF2cE96S0pyOUFxeVZMRnYKVXFBRHBTakM3WXd3MnZwSld3bDEySlBvUm1xZ1FBSFNkYlJpU3BDTDRudjlvR25VOWI2dllWSy9iRitkUVFCSApnQ1h6NnZoTGY4Wmd2N2tUQ2JBdkFPaE9OSlU3MllYTE8zT0lZQjJva1NCRGFVUjNvNnpwZGVWTkt5V0EyNVA3CkRobk8yTk01QzlpRERqTTRLY2FTa3JPSkJvbUlsSHFZRjRwVXdTTlFvcGVGRVRyZ3ZzcTkwSks2YUJVS0t5ajYKK2NGdjI3S0k4K1ZMUEtaSTE2c25Mbng2RXRTazZtZjJXTHdJZlhyQlgwREsvYXBEQ015R2pEb2dCaGpJSVhoVAp2bjVQZndFWUNsdGZFTEhKSkdVQ0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZJVDhLRHdCbUVvMHladUFEZkhkKzQ1L3ZFYzdNQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBT0F5VHQ4S3ZFN0dvREhQT09pdgoyR2I2WWVsUU5KcUMza1dIOXc1NTFNaGZvS3ZiM21VaUV6ZVMwOUNwZUQrTFh5ZnlqQzhZYkJxQjZXSFhNZWMrCnpPdDNPazRYV0FmZVVZTXhOQ1FJblc4cjI4cmZnblErc1NCdHQyeERQN1RZY09oNVZGZkI2K3JtTmFTblZ1NjgKSFFxdlFMNEFXbVhkR09jRWNBRThYdkdiOWhwSjVNckRHdzQ0UTYyOG9YazZ0N01aWTFOMUNQdW9HZ1VmS1N3bgo1MUFWRTFOVVdNV0tEQXhaa2I4bEhvR3VWaDFzWmd3SnJRQjR5clh1cmxGN0Y2bVRlYm4rcDVKM0toT0V4KzlsCjFXdkwwbWkxL1J2bVJKNm11YmtjWUwzN1FJWjI1YXdyaEZMN0Z1ejNRSTFqTTdYMHZET2VUM2VuVUFCZW5SMS8KUnlnPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://10.6.100.10:6443/apis/clusterpedia.io/v1beta1/resources
  name: clusterpedia
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeE1Ea3lOREV3TVRNeU5Gb1hEVE14TURreU1qRXdNVE15TkZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTy9TCnZta1U5bk1uUlRIT3lvK3hjdFRJY0lPYnMzc0F5cTI2djRQYkVtb3ZWM2xPOVQwMTF2cE96S0pyOUFxeVZMRnYKVXFBRHBTakM3WXd3MnZwSld3bDEySlBvUm1xZ1FBSFNkYlJpU3BDTDRudjlvR25VOWI2dllWSy9iRitkUVFCSApnQ1h6NnZoTGY4Wmd2N2tUQ2JBdkFPaE9OSlU3MllYTE8zT0lZQjJva1NCRGFVUjNvNnpwZGVWTkt5V0EyNVA3CkRobk8yTk01QzlpRERqTTRLY2FTa3JPSkJvbUlsSHFZRjRwVXdTTlFvcGVGRVRyZ3ZzcTkwSks2YUJVS0t5ajYKK2NGdjI3S0k4K1ZMUEtaSTE2c25Mbng2RXRTazZtZjJXTHdJZlhyQlgwREsvYXBEQ015R2pEb2dCaGpJSVhoVAp2bjVQZndFWUNsdGZFTEhKSkdVQ0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZJVDhLRHdCbUVvMHladUFEZkhkKzQ1L3ZFYzdNQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBT0F5VHQ4S3ZFN0dvREhQT09pdgoyR2I2WWVsUU5KcUMza1dIOXc1NTFNaGZvS3ZiM21VaUV6ZVMwOUNwZUQrTFh5ZnlqQzhZYkJxQjZXSFhNZWMrCnpPdDNPazRYV0FmZVVZTXhOQ1FJblc4cjI4cmZnblErc1NCdHQyeERQN1RZY09oNVZGZkI2K3JtTmFTblZ1NjgKSFFxdlFMNEFXbVhkR09jRWNBRThYdkdiOWhwSjVNckRHdzQ0UTYyOG9YazZ0N01aWTFOMUNQdW9HZ1VmS1N3bgo1MUFWRTFOVVdNV0tEQXhaa2I4bEhvR3VWaDFzWmd3SnJRQjR5clh1cmxGN0Y2bVRlYm4rcDVKM0toT0V4KzlsCjFXdkwwbWkxL1J2bVJKNm11YmtjWUwzN1FJWjI1YXdyaEZMN0Z1ejNRSTFqTTdYMHZET2VUM2VuVUFCZW5SMS8KUnlnPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    server: https://10.6.100.10:6443
  name: kubernetes

脚本生成了用于多集群访问的 clusterpedia cluster 以及其他 PediaCluster Name 命名的 cluster config, 而且在访问 Clusterpedia 时会复用主集群的入口以及认证信息,相比主集群入口只是增加了 Clusterpedia Resources 的 path。

多集群的 kubeconfig 信息生成完成后,就可以使用 kubectl --cluster 来指定集群访问了

# 多集群检索时支持的资源
kubectl --cluster clusterpedia api-resources

# cluster-1 支持检索的资源
kubectl --cluster cluster-1 api-resources

查看支持检索的资源类型

我们可以根据 URL 路径来分别获取全局资源信息和指定集群的资源信息。

全局资源信息是所有集群同步的资源类型的并集。

Clusterpedia 开放的 Discovery API 同样兼容 Kubernetes OpenAPI,可以使用 kubectlclient-go/discoveryclient-go/restmapper 或者 controller-runtime/dynamic-restmapper 来访问。

使用 URL 来获取 APIGroupList 以及 APIGroup 信息

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis" | jq
{
  "kind": "APIGroupList",
  "apiVersion": "v1",
  "groups": [
    {
      "name": "apps",
      "versions": [
        {
          "groupVersion": "apps/v1",
          "version": "v1"
        },
        {
          "groupVersion": "apps/v1beta2",
          "version": "v1beta2"
        },
        {
          "groupVersion": "apps/v1beta1",
          "version": "v1beta1"
        }
      ],
      "preferredVersion": {
        "groupVersion": "apps/v1",
        "version": "v1"
      }
    },
    {
      "name": "cert-manager.io",
      "versions": [
        {
          "groupVersion": "cert-manager.io/v1",
          "version": "v1"
        }
      ],
      "preferredVersion": {
        "groupVersion": "cert-manager.io/v1",
        "version": "v1"
      }
    }
  ]
}
kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis/apps" | jq
{
  "kind": "APIGroup",
  "apiVersion": "v1",
  "name": "apps",
  "versions": [
    {
      "groupVersion": "apps/v1",
      "version": "v1"
    },
    {
      "groupVersion": "apps/v1beta2",
      "version": "v1beta2"
    },
    {
      "groupVersion": "apps/v1beta1",
      "version": "v1beta1"
    }
  ],
  "preferredVersion": {
    "groupVersion": "apps/v1",
    "version": "v1"
  }
}

使用 kubectl 来获取 api-resources

kubectl --cluster clusterpedia api-resources
# 输出:
NAME          SHORTNAMES   APIVERSION           NAMESPACED   KIND
configmaps    cm           v1                   true         ConfigMap
namespaces    ns           v1                   false        Namespace
nodes         no           v1                   false        Node
pods          po           v1                   true         Pod
secrets                    v1                   true         Secret
daemonsets    ds           apps/v1              true         DaemonSet
deployments   deploy       apps/v1              true         Deployment
replicasets   rs           apps/v1              true         ReplicaSet
issuers                    cert-manager.io/v1   true         Issuer

3.5 - 资源检索

Clusterpedia 支持对 多个集群内资源指定集群的资源 以及聚合资源 的复杂检索,

并且这些复杂检索的条件可以通过两种方式传递给 Clusterpedia APIServer

  • URL Query:直接将查询条件作为 Query 来传递
  • Search Labels:为了兼容 Kubernetes OpenAPI,可以将查询条件设置在 Label Selector。

Search LabelsURL Query 都支持与 Label Selector 相同的操作符:

  • existnot exist
  • ===!=
  • innotin

除了条件检索,Clusterpedia 还增强了 Field Selector ,满足我们通过 metadata.annotation 或者 status.* 等字段的过滤需求。

元信息检索

支持的操作符:===in

作用 search label key url query
过滤集群名称 search.clusterpedia.io/clusters clusters
过滤命名空间 search.clusterpedia.io/namespaces namespaces
过滤资源名称 search.clusterpedia.io/names names

暂时不支持例如 !=notin 操作符,如果有这些需求或者场景,可以在 issue 中讨论

模糊搜索

支持的操作符:===in

该功能暂时为试验性功能,暂时只提供 search label

作用 search label key url query
模糊搜索资源名称 internalstorage.clusterpedia.io/fuzzy-name -

创建时间区间检索

支持的操作符:===

基于资源的创建时间区间进行检索,采用的是左闭右开的区间

作用 search label key url query
指定 Since search.clusterpedia.io/since since
指定 Before search.clusterpedia.io/before before

创建时间的格式有四种:

  1. Unix 时间戳格式 为了方便使用会根据时间戳的长度来区分单位为 s 还是 ms。 10 位时间戳单位为秒,13 位时间戳单位为毫秒。
  2. RFC3339 2006-01-02T15:04:05Z or 2006-01-02T15:04:05+08:00
  3. UTC Date 2006-01-02
  4. UTC Datetime 2006-01-02 15:04:05

由于 kube label selector 的限制,search label 只支持 Unix 时间戳UTC Date.

使用 url query 的方式可以所有的格式

Owner 检索

只支持操作符:===

作用 search label key url query
指定 Owner UID search.clusterpedia.io/owner-uid ownerUID
指定 Owner Name search.clusterpedia.io/owner-name ownerName
指定 Owner Group Resource search.clusterpedia.io/owner-gr ownerGR
指定 Owner 辈分 internalstorage.clusterpedia.io/owner-seniority ownerSeniority

需要注意指定 Owner UID 时,Owner NameOwner Group Resource 会被忽略

Owner Group 的格式为 resource.group,例如 deployments.apps 或者 nodes

排序

只支持操作符:===in

作用 search label key url query
多字段排序 search.clusterpedia.io/orderby orderby

分页

只支持操作符 ===

作用 search label key url query
设置分页 size search.clusterpedia.io/size limit
设置分页 offset search.clusterpedia.io/offset continue
要求响应携带 Continue search.clusterpedia.io/with-continue withContinue
要求响应携带资源剩余数量 search.clusterpedia.io/with-remaining-count withRemainingCount

在使用 kubectl 操作时,分页 size 只能通过 kubectl --chunk-size 来设置,因为 kubectl 会将 limit 默认设置为 500。

Label 过滤

无论使用 kubectl 还是 URL,所有 Key 中不包含 clusterpedia.io 的 Label Selector 都会作为 Label Selector 来过滤资源。

所有行为和原生 Kubernetes 一致。

作用 kubectl url query
Label 过滤 kubectl -l or kubectl --label-selector labelSelector

字段过滤

Clusterpedia 的 Field Selector 在操作符上与 Label Selector 保持一致,同样支持:

existnot exist===!=innotin

无论是 URL 还是 kubectl 上的命令参数都原生 Field Selector 一致

作用 kubectl url query
字段过滤 kubectl --field-selector fieldSelector

详细可以查看:

高级检索(自定义条件检索)

自定义检索为 默认存储层 提供的功能,目的是为了满足用户更加灵活多变的检索需求

作用 search label key url query
自定义检索语句 - whereSQL

自定义检索并不支持通过 search lable,只能使用 url query 来传递自定义搜素的语句。

另外该功能暂时还是处于 alpha 阶段,需要用户在 clusterpedia apiserver 中开启相应的 Feature Gate,详细可以参考 自定义条件检索

CollectionResource URL Query

以下 URL Query 专属于 Collection Resource。

作用 url query example
只获取资源的 metadata onlyMetadata onlyMetadata=true
指定 any collectionresource 的 groups groups groups=apps,cert-manager.io/v1
指定 any collectionresource 的 resources resources resources=apps/deployments,batch/v1/cronjobs

3.5.1 - 多集群检索

多集群资源检索可以满足我们根据查询条件一次过滤多个集群内的资源,并提供对这些资源的分页排序的能力

在使用 kubectl 操作时,可以查看一下当前可以检索哪些资源

kubectl --cluster clusterpedia api-resources
# 输出:
NAME          SHORTNAMES   APIVERSION           NAMESPACED   KIND
configmaps    cm           v1                   true         ConfigMap
namespaces    ns           v1                   false        Namespace
nodes         no           v1                   false        Node
pods          po           v1                   true         Pod
secrets                    v1                   true         Secret
daemonsets    ds           apps/v1              true         DaemonSet
deployments   deploy       apps/v1              true         Deployment
replicasets   rs           apps/v1              true         ReplicaSet
issuers                    cert-manager.io/v1   true         Issuer

Clusterpedia 根据所有集群同步的资源来提供多集群的资源检索,可以查看 同步集群资源 来更新需要同步的资源

基本功能

指定集群

多集群检索时,会默认检索所有的集群,我们也可以指定单个或者一组集群

使用 Search Label search.clusterpedia.io/clusters 来指定一组集群

kubectl --cluster clusterpedia get deployments -l "search.clusterpedia.io/clusters in (cluster-1,cluster-2)"
# 输出:
NAMESPACE     CLUSTER     NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
kube-system   cluster-1   coredns                   2/2     2            2           68d
kube-system   cluster-2   coredns                   2/2     2            2           64d

对于指定单个集群的检索,同样可以使用 Search Label 来设置,也可以查看 指定集群检索 来使用 URL Path 的方式指定集群

# 指定单个集群
kubectl --cluster clusterpedia get deployments -l "search.clusterpedia.io/clusters=cluster-1"

# 指定集群也可以使用 --cluster <cluster name> 来指定
kubectl --cluster cluster-1 get deployments

使用 URL 时,使用 clusters 作为 URL Query 来传递

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis/apps/v1/deployments?clusters=cluster-1"

如果指定单个集群,也可以将 cluster name 放到 URL 路径中

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/clusters/cluster-1/apis/apps/v1/deployments"

了解更多指定集群检索

指定命名空间

可以像查看原生 Kube 一样来指定单个命名空间或者所有命名空间

使用 -n <namespace> 来指定命名空间,默认在 default 命名空间

kubectl --cluster clusterpedia get deployments -n kube-system
# 输出:
CLUSTER     NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
cluster-1   coredns                   2/2     2            2           68d
cluster-2   calico-kube-controllers   1/1     1            1           64d
cluster-2   coredns                   2/2     2            2           64d

使用 -A 或者 --all-namespaces 来查看所有集群的所有命名空间下的资源

kubectl --cluster clusterpedia get deployments -A
# 输出:
NAMESPACE     CLUSTER     NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
kube-system   cluster-1   coredns                   2/2     2            2           68d
kube-system   cluster-2   calico-kube-controllers   1/1     1            1           64d
kube-system   cluster-2   coredns                   2/2     2            2           64d
default       cluster-2   dd-airflow-scheduler      0/1     1            0           54d
default       cluster-2   dd-airflow-web            0/1     1            0           54d

获取资源的 URL Path 和原生 Kubernetes 一样 /apis/apps/v1/deployments

只是需要加上 Clusterpedia Resources 的路径前缀 /apis/clusterpedia.io/v1beta1/resources 来表示当前是 Clusterpedia 请求。

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis/apps/v1/deployments"

# 指定命名空间
kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis/apps/v1/namespaces/kube-system/deployments"

除了指定单个命名空间,还可以指定查看一组命名空间下的资源

使用 Search Label search.clusterpedia.io/namespaces 来指定一组命名空间

一定要指定 -A 参数,避免 kubectl 在路径中设置 default namespace

kubectl --cluster clusterpedia get deployments -A -l "search.clusterpedia.io/namespaces in (kube-system, default)"
# 输出:
NAMESPACE     CLUSTER     NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
kube-system   cluster-1   coredns                   2/2     2            2           68d
kube-system   cluster-2   calico-kube-controllers   1/1     1            1           64d
kube-system   cluster-2   coredns                   2/2     2            2           64d
default       cluster-2   dd-airflow-scheduler      0/1     1            0           54d
default       cluster-2   dd-airflow-web            0/1     1            0           54d

使用 URL 时,就不需要使用 Label Selector 来传递参数了,直接使用 URL Query namespaces 即可

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis/apps/v1/deployments?namespaces=kube-system,default"

指定资源名称

用户可以通过一组资源名称来过滤资源

使用 Search Label search.clusterpedia.io/names 来指定一组资源名称 注意:如果在所有命名空间下检索资源,需要指定 -A 参数,或者使用 -n 来指定命名空间

kubectl --cluster clusterpedia get deployments -A -l "search.clusterpedia.io/names=coredns"
# 输出:
NAMESPACE     CLUSTER     NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
kube-system   cluster-1   coredns                   2/2     2            2           68d
kube-system   cluster-2   coredns                   2/2     2            2           64d

使用 URL 时,使用 names 作为 URL Query 来传递,如果需要指定命名空间,那么就在路径中加上 namespace。

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis/apps/v1/deployments?names=kube-coredns,dd-airflow-web"

# 在 default 命名空间下检索指定名字的资源
kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis/apps/v1/namespaces/default/deployments?names=kube-coredns,dd-airflow-web"

在多集群检索时,返回的数据实际是以类似 DeploymentList 的结构封装的数据。

如果我们想要获取到单个的 Deployment 那么就需要在 URL 路径中指定 cluster name,参考获取单个资源

创建时间的区间

创建时间的区间以左闭右开的方式来进行检索,since <= creation time < before

关于详细的时间区间参数可以查看 创建时间区间检索

使用 Search Label search.clusterpedia.io/sincesearch.clusterpedia.io/before 来指定时间区间

kubectl --cluster clusterpedia get deployments -A -l "search.clusterpedia.io/since=2022-03-24, \
    search.clusterpedia.io/before=2022-04-10"

直接使用 URL 时,可以 Query sincebefore 来分别指定时间的区间

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis/apps/v1/deployments?since=2022-03-24&before=2022-04-10"

模糊搜索

当前支持根据资源名称进行模糊搜索,由于模糊搜索还需要继续讨论,所以暂时以试验性功能来提供

只支持 Search Label 的方式,不支持 URL Query

kubectl --cluster clusterpedia get deployments -A -l "internalstorage.clusterpedia.io/fuzzy-name=test"

过滤出名字中包含 test 字符串的 deployments。

可以使用 in 操作符来传递多个参数,这样可以过滤出名字中包含所有字符串的资源

字段过滤

原生 Kubernetes 当前只支持对 metadata.namemetadata.namespace 的字段过滤,而且操作符只支持 =!===,能力非常有限。

Clusterpedia 在兼容已有的 Field Selector 功能的基础上,提供了更加强大的功能,支持和 Label Selector 相同的操作符。

Field Selector 的 key 当前支持三种格式:

  • 使用 . 分隔字段
kubectl --cluster clusterpedia get pods --field-selector="status.phase=Running"

# 也可以在首字符添加 `.`
kubectl --cluster clusterpedia get pods --field-selector=".status.phase notin (Running,Succeeded)"
  • 字段名称使用 '' 或者 "" 来包裹,可以用于带 . 之类的非法字符的字段
kubectl --cluster clusterpedia get deploy \
    --field-selector="metadata.annotations['test.io'] in (value1,value2),spec.replica=3"
  • 使用 [] 来分隔字段[] 内字符串必须使用 '' 或者 "" 来包裹
kubectl --cluster clusterpedia get pods --field-selector="status['phase']!=Running"

列表字段支持

实际在字段过滤的设计时考虑到了对列表元素内字段过滤,不过由于使用场景是否真正有意义还需要更多的讨论 issue: support list field filtering

示例:

kubectl get po --field-selector="spec.containers[].name!=container1"

kubectl get po --field-selector="spec.containers[].name == container1"

kubectl get po --field-selector="spec.containers[1].name in (container1,container2)"

根据父辈以及祖辈 Owner 查询

通过 Owner 检索是一个非常有用的检索功能, 并且 Clusterpedia 在 Owner 的基础上还支持对 Owner 进行辈分提升来进行祖辈甚至更高辈分的检索

通过 Owner 检索,可以一次查询到 Deployment 下的所有 Pods,无需中间再查询 ReplicaSet

Owner 查询必须指定单个集群,可以使用 Serach Label 或者 URL Query 来指定,也可以在 URL Path 中指定集群名称

关于根据 Owner 检索的具体使用方法,可以参考指定集群内根据父辈或者祖辈 Owenr 进行检索

分页与排序

分页和排序是资源检索必不可少的功能

根据多个字段进行排序

可以指定多个字段进行排序,而对排序字段的支持是由存储层来决定。

当前默认存储层支持对 clusternamespacenamecreated_atresource_version 进行正序和倒序的排序,字段也支持随意的组合

使用多个字段进行正序排序

kubectl --cluster clusterpedia get pods -l \
    "search.clusterpedia.io/orderby in (cluster, name)"

由于 Label Selector 对 value 的限制,倒序时需要在字段结尾加上 _desc

kubectl --cluster clusterpedia get pods -l \
    "search.clusterpedia.io/orderby in (namespace_desc, cluster, name)"

使用 URL Query 来指定排序字段

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis/apps/v1/deployments?orderby=namespace,cluster"

指定倒序字段时,在字段后添加 desc,以空格分隔

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis/apps/v1/deployments?orderby=namespace desc,cluster"

分页

原生 Kubernetes 实际是支持分页的,ListOptions 中便已经存在用于分页查询的字段。

Clusterpedia 复用 ListOptions.LimitListOptions.Continue 字段作为分页的 sizeoffset

kubectl 的 --chunk-size 实际通过设置 limit 来用于分片拉取。

原生的 Kubernetes APIServer 会在返回的响应中携带用于下一次拉取的 continue, 并根据 --chunk-sizeconintue 进行下一次拉取,直到相应的数据中 Conintue 为空。

Clusterpedia 为了保证在 kubectl 中实现分页检索,默认并不会在响应中返回 continue 字段,这样避免了 kubectl 使用分片拉取全部数据

kubectl --cluster cluster-1 get pods --chunk-size 10

需要注意 kubectl 在不设置 --chunk-size 的情况下,limit 会被设置成默认值 500, 也就是说 search.clusterpedia.io/size 实际是无法生效的,只是用于和 search.clusterpedia.io/offset 形成对应关系

URL Query 的优先级大于 Search Label

在 kubectl 中 continue 是没有 flag 可以设置的。所以还是要使用 Search Label 来传递。

kubectl --cluster clusterpedia get pods --chunk-size 10 -l \
    "search.clusterpedia.io/offset=10"

对资源进行分页检索,只需要在 URL 中设置 limitcontinue 即可

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis/apps/v1/deployments?limit=10&continue=5"

响应携带 Continue 信息

响应数据的 ListMeta.Continue 可以用于 ListOptions.Continue 中作为下一次拉取的 offset

分页功能中我们提到,为了避免 kubectl 进行对全量数据的分片拉取,Clusterepdia 不会在响应中携带 Continue 信息。

不过如果用户有需求那么可以要求响应中携带 Continue 信息

在使用 URL 访问 Clusterepdia 时,响应的 Continue 可以作为下一次请求的 offset

搭配分页功能使用

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis/apps/v1/deployments?withContinue=true&limit=1" | jq
{
  "kind": "DeploymentList",
  "apiVersion": "apps/v1",
  "metadata": {
    "continue": "1"
  },
  "items": [
    ...
  ]
}

在 kubectl 设置 search.clusterpedia.io/with-continue 会导致以分片拉取的形式拉取全量资源。

kubectl --cluster clusterpedia get deploy -l \
    "search.clusterpedia.io/with-continue=true"

响应携带剩余资源数量信息

在一些 UI 场景下,往往会需要获取到当前检索条件下的资源总量。

Kubernetes List 响应的 ListMeta 中存在 RemainingItemCount 字段,

通过复用该字段,便可在兼容 Kubernetes OpenAPI 的基础下计算出资源总量:

offset + len(list.items) + list.metadata.remainingItemCount

在 offset 过大时,remainingItemCount 可能为负数,保证总是可以计算出资源总量

URL Query 设置 withRemainingCount 即可要求响应携带剩余资源数量

搭配分页功能使用

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis/apps/v1/deployments?withRemainingCount&limit=1" | jq
{
  "kind": "DeploymentList",
  "apiVersion": "apps/v1",
  "metadata": {
    "remainingItemCount": 23
  },
  "items": [
    ...
  ]
}

需要以 URL 的方式使用该功能

3.5.2 - 指定集群检索

Clusterpedia 除了支持多个集群的混合检索,还可以指定集群来检索资源。

在性能上使用 Search Label 或者 URL Query 来指定单个集群和在 URL Path 中指定集群并无区别

本文主要讲述在 URL Path 中指定集群

在以指定集群的方式使用 kubectl 前,需要先配置 kubectl 的集群快捷方式

kubectl --cluster cluster-1 get deployments -n kube-system
# 输出:
NAMESPACE     CLUSTER     NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
kube-system   cluster-1   coredns                   2/2     2            2           68d

将 cluster name 放到 URL 路径中来指定集群

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/clusters/cluster-1/apis/apps/v1/deployments"

也可以通过 URL Query 来指定单个集群

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis/apps/v1/deployments?clusters=cluster-1"

指定集群支持的功能和多集群检索的作用基本相同,而且在 Owner 检索上更加方便, 另外在获取单个资源时也只能使用在 URL Path 中指定集群的方式

根据父辈或者祖辈 Owner 进行检索

Owner 查询必须指定单个集群,可以使用 Search Label 或者 URL Query 来指定,也可以在 URL Path 中指定集群名称

通过 Owenr UID 或者 Owner Name, 并且配合用于 Owner 辈分提升的 Owenr Senirority 可以完成基于祖辈 Owner 的资源检索。

关于具体的查询参数,可以参考 Owner 检索

通过这种方式,可以直接查询到 Deployment 相应的 Pods,无需查询有哪些 ReplicaSet 属于该 Deployment

指定 Owner 的 UID

在指定 Owenr UID 后,Owner NameOwenr Group Resource 会被忽略

首先使用 kubectl 获取 Deployment 的 UID

kubectl --cluster cluster-1 get deploy fake-deploy -o jsonpath="{.metadata.uid}"
#输出:
151ae265-28fe-4734-850e-b641266cd5da

在 kubectl 下获取 uid 可能比较麻烦,但是在 UI 场景中通常已经更容易查看 metadata.uid

使用 owner-uid 来指定 Owner 的 UID, owner-seniority 对 Owner 进行辈分提升。

owner-seniority 默认为 0,表示 Owner 为父辈。设置为 1,提升 Owenr 辈分成为祖父 Owenr

kubectl --cluster cluster-1 get pods -l \
    "search.clusterpedia.io/owner-uid=151ae265-28fe-4734-850e-b641266cd5da,\
     search.clusterpedia.io/owner-seniority=1"

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/clusters/cluster-1/api/v1/namespaces/default/pods?ownerUID=151ae265-28fe-4734-850e-b641266cd5da&ownerSeniority=1"

指定 Owner Name

如果事先并不知道 Owner 的 UID,那么指定 Owner UID 是一种比较麻烦的方式。

我们可以通过 Owner 的名字来指定 Owner,同时还可以指定 Owner Group Resource 来限制 Owner 的 Group Resource。

同样,我们以获取 Deployment 下相应的 Pods 来举例

kubectl --cluster cluster-1 get pods -l \
    "search.clusterpedia.io/owner-name=deploy-1,\
     search.clusterpedia.io/owner-seniority=1"

另外为了避免某些情况下,owner 资源存在多种类型,我们可以使用 Owner Group Resource 来限制 Owner 的类型

kubectl --cluster cluster-1 get pods -l \
    "search.clusterpedia.io/owner-name=deploy-1,\
     search.clusterpedia.io/owner-gr=deployments.apps,\
     search.clusterpedia.io/owner-seniority=1"

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/clusters/cluster-1/api/v1/namespaces/default/pods?ownerName=deploy-1&ownerSeniority=1"

获取单个资源

当我们想要使用资源名称获取(Get)一个资源时,就必须要以 URL Path 的方式将集群名称传递进去,就像 namespace 一样。

如果使用多集群方式传递一个资源名称会报错

kubectl --cluster cluster-1 get deploy fake-deploy 
# 输出:
CLUSTER     NAME        READY   UP-TO-DATE   AVAILABLE   AGE
cluster-1   fake-deploy 1/1     1            1           35d

当然在 kubectl 中也可以通过 Search Label 来指定一个资源名称。

不过在 -o yaml 或者其他方式查看返回的源数据时,和使用 kubectl --cluster <cluster name> 是不一样的。

# 实际服务端返回 DeploymentList 的资源,由 kubectl 替换成 List 资源
kubectl --cluster clusterpedia get deploy -l 
    "search.clusterpedia.io/clusters=cluster-1,\
     search.clusterpedia.io/names=fake-deploy" -o yaml
# 输出:
apiVersion: v1
items:
- ...
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""

实际返回的资源依然是一个 KindList,而 kubectl --cluster <clsuter name> 返回的便是具体的 Kind

kubectl --cluster cluster-1 get deploy fake-deploy -o yaml
# 输出:
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
    shadow.clusterpedia.io/cluster-name: cluster-1
  creationTimestamp: "2021-12-16T02:26:29Z"
  generation: 2
  name: fake-deploy
  namespace: default
  resourceVersion: "38085769"
  uid: 151ae265-28fe-4734-850e-b641266cd5da
spec:
  ...
status:
  ...

获取指定资源的 URL 可以分为三部分

  • 资源检索前缀: /apis/clusterpedia.io/v1beta1/resources
  • 指定集群名称 /clusters/< cluster name >
  • 原生 Kubernetes API 的资源 Path /apis/apps/v1/namespaces/< namespace >/deployments/< resource name >
kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/clusters/cluster-1/apis/apps/v1/namespaces/default/deployments/fake-deploy"

3.5.3 - 聚合资源检索

关于聚合资源的概念可以查看 什么是聚合资源 (Collection Resource)

由于 kubectl 的限制,我们无法通过 Label Selector 或者其他方式来传递检索参数, 所以建议以 URL 的方式来检索聚合资源

请求聚合资源时,由于资源数量可能会非常大,一定要搭配分页功能使用。

kubectl get --raw="/apis/clusterpedia.io/v1beta1/collectionresources/workloads?limit=1" | jq
# 输出
{
  "kind": "CollectionResource",
  "apiVersion": "clusterpedia.io/v1beta1",
  "metadata": {
    "name": "workloads",
    "creationTimestamp": null
  },
  "resourceTypes": [
    {
      "group": "apps",
      "version": "v1",
      "kind": "Deployment",
      "resource": "deployments"
    },
    {
      "group": "apps",
      "version": "v1",
      "resource": "daemonsets"
    },
    {
      "group": "apps",
      "version": "v1",
      "resource": "statefulsets"
    }
  ],
  "items": [
    {
      "apiVersion": "apps/v1",
      "kind": "Deployment",
      ...
    }
  ]
}

聚合资源的复杂检索和多集群资源检索 功能基本相同,只有部分操作不支持:

  • 不支持根据 Owner 检索,如果需要进行根据 Owner 检索需要指定具体的资源类型,可以参考 多集群检索指定集群检索
  • 不支持在 Collection Resource 中获取具体的单个资源,因为具体资源需要指定集群和资源类型,可以使用 获取单个资源

尽管 kubectl 无法很好的检索聚合资源,但是可以简单的体验一下。

由于无法传递分页以及其他检索条件,kubectl 会一次获取到所有的聚合资源,在接入了大量集群或者存在大量 deploymentsdaemonsetsstatefulsets 资源时,不要使用 kubectl 来查看聚合资源

kubectl get collectionresources workloads
# 输出
CLUSTER     GROUP   VERSION   KIND         NAMESPACE                     NAME                                          AGE
cluster-1   apps    v1        DaemonSet    kube-system                   vsphere-cloud-controller-manager              63d
cluster-2   apps    v1        Deployment   kube-system                   calico-kube-controllers                       109d
cluster-2   apps    v1        Deployment   kube-system                   coredns-coredns                               109d
...

请使用 URL 来检索聚合资源

Only Metadata

我们在检索 CollectionResource 时,获取到的资源默认是全量的资源信息,但是我们通常只需要获取资源的 metadata 即可。

在检索时我们可以使用 url query —— onlyMetadata 来只获取资源 Metadata。

$ kubectl get --raw "/apis/clusterpedia.io/v1beta1/collectionresources/workloads?onlyMetadata=true&limit=1" | jq
{
  "kind": "CollectionResource",
  "apiVersion": "clusterpedia.io/v1beta1",
  "metadata": {
    "name": "workloads",
    "creationTimestamp": null
  },
  "resourceTypes": [
    {
      "group": "apps",
      "version": "v1",
      "kind": "Deployment",
      "resource": "deployments"
    }
  ],
  "items": [
    {
      "apiVersion": "apps/v1",
      "kind": "Deployment",
      "metadata": {
        "annotations": {
          "deployment.kubernetes.io/revision": "1",
          "shadow.clusterpedia.io/cluster-name": "cluster-example"
        },
        "creationTimestamp": "2021-09-24T10:19:19Z",
        "generation": 1,
        "labels": {
          "k8s-app": "tigera-operator"
        },
        "name": "tigera-operator",
        "namespace": "tigera-operator",
        "resourceVersion": "125073610",
        "uid": "992f9d53-37cb-4184-a004-15b278b11f79"
      }
    }
  ]
}

Any CollectionResource

any collectionresource 是用户自由组合资源类型的方式之一,可以通过 自定义聚合资源 来查看更多。

clusterpedia 支持一种特殊的 CollectionResource —— any

$ kubectl get collectionresources
NAME            RESOURCES
any             *

在检索 any collectionresource 时,我们必须通过 url query 来指定一组资源类型,因此我们只能通过 clusterpedia-io/client-go 或者 url 来访问 any collectionresource

$ kubectl get collectionresources any
Error from server (BadRequest): url query - `groups` or `resources` is required

any collectionresource 支持两个 url query —— groupsresources

groupsresources 可以同时指定,当前是取两者并集,并且不会进行去重处理,由调用者负责去重,未来对该行为有一些优化。

$ kubectl get --raw "/apis/clusterpedia.io/v1beta1/collectionresources/any?onlyMetadata=true&groups=apps&resources=batch/jobs,batch/cronjobs" | jq

groups

groups 可以指定一组资源的组和版本,多个组版本使用 , 分隔,组版本格式为 < group >/< version >,也可以不指定版本 < group >对于 /api 下的资源,可以直接使用空字符串

示例:groups=apps/v1,,batch 指定了三个组 apps/v1, core, batch。

resources

resources 可以指定具体的资源类型,多个资源类型使用 , 分隔,资源类型格式为 < group >/< version >/< resource>,通过也可以不指定版本 < group >/< resource >

示例:resources=apps/v1/deployments,apps/daemonsets,/pods 指定了三种资源 deloyments,daemonsets 和 pods。

4 - 高级功能

4.1 - 多集群 kube-state-metrics

Clusterpedia 以极小的代价提供了多集群资源的 kube-state-metrics 功能,它提供的指标信息与 kube-state-metrics 一致,当然会额外增加了一个集群名称的 label.

kube_deployment_created{cluster="test-14",namespace="clusterpedia-system",deployment="clusterpedia-apiserver"} 1.676557618e+09

由于该功能处于试验阶段,所以使用该功能需要先额外通过标准方式安装 Clusterpedia.

Clusterpedia 安装完成后,我们需要更新 helm 来开启 多集群 kube-state-metrics 功能。

当前 main 分支中已经合并 kube-state-metrics 功能,未来会包含在 v0.8.0 中。 ghcr.io/iceber/clusterpedia/clustersynchro-manager:v0.8.0-ksm.1 镜像中包含该功能呢

开启多集群 kube-state-metrics

确保 Clusterpedia Chart 版本 >= v1.8.0

$ helm repo update clusterpedia
$ helm search clusterpedia
 NAME                            CHART VERSION   APP VERSION     DESCRIPTION
 clusterpedia/clusterpedia       1.8.0           v0.7.0          A Helm chart for Kubernetes

获取当前 chart values

$ helm -n clusterpedia-system get values clusterpedia > values.yaml

创建 patch values

echo "clustersynchroManager:
  image:
    repository: iceber/clusterpedia/clustersynchro-manager
    tag: v0.8.0-ksm.1
  kubeStateMetrics:
    enabled: true
" > patch.yaml

更新 Clusterpedia 开启多集群 kube-state-metrics

$ helm -n clusterpedia-system upgrade -f values.yaml -f patch.yaml clusterpedia clusterpedia/clusterpedia

查看 clusterpedia kube-state-metrics services

$ kubectl -n clusterpedia-system get svc
NAME                                          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
clusterpedia-apiserver                        ClusterIP   10.97.129.238   <none>        443/TCP    150d
clusterpedia-clustersynchro-manager-metrics   ClusterIP   10.108.129.32   <none>        8081/TCP   51m
clusterpedia-kube-state-metrics               ClusterIP   10.108.130.62   <none>        8080/TCP   43m
clusterpedia-mysql                            ClusterIP   10.102.38.225   <none>        3306/TCP   150d
clusterpedia-mysql-headless                   ClusterIP   None            <none>        3306/TCP   150d

For more information on importing clusters and using clusterpedia: Import Clusters

未来

多集群 kube-state-metrics 是一个非常有趣的功能,它可以让你不再需要在每一个集群中安装单集群版本的 kube-state-metrics,并且它可以很好的处理资源版本不同的问题。

这里有很多关于该功能的讨论,欢迎评论

也欢迎创建新的 issue

4.2 - 自定义存储层插件

Clusterpedia 可以通过存储层来使用不同的存储组件,例如 MySQL/PostgreSQL, Memory, Elasticsearch

当前,Clusterpedia 内置了两个存储层:

尽管 Clusterpedia 已经默认支持了关系型数据库和内存,但是用户的需求往往是多变和复杂的,固定的存储层可能无法满足不同用户对于存储组件和性能的要求,于是 Clusterpedia 支持通过插件的方式来接入用户自己实现的存储层,我们称这种方式为 自定义存储层插件,简称为 存储插件

通过存储插件,用户可以做到以下事情:

  • 使用任意的存储组件,例如 ElasticsearchRedisGraphEtcd,甚至是 MessageQueue 也没有问题
  • 允许用户针对自己的业务来优化资源的存储格式和查询性能
  • 针对存储组件的特性来实现更高级的检索功能

Clusterpedia 也维护了一些存储插件,用户可以根据需求选用:

存储插件是通过 Go Plugin 的方式来让 Clusterpedia 组件加载,相比 RPC 或者其他方式,这种方式在没有任何损耗的前提下提供非常灵活的插件接入。

关于 Go Plugin 对性能的影响可以简单参考 https://github.com/uberswe/goplugins

众所周知,Go Plugin 在开发和使用上都比较繁琐,不过 Clusterpedia 通过一些机制来巧妙的优化了存储插件的使用和开发,并且提供了 clusterpedia-io/sample-storage 插件作为参考。

下面我们以 clusterpedia-io/sample-storage 为例,分别介绍:

使用 自定义存储层插件

存储插件的使用可以大致分为三种方式:

  1. 运行 Clusterpedia 组件二进制并加载 存储插件
  2. 使用基础 Chart —— clusterpedia-core 来设置存储插件镜像和配置存储层
  3. 使用 Clusterpedia 高级 Chart,无需关心存储插件的设置

通过本地运行组件二进制,我们可以更加了解 Cluserpedia 组件是如何加载和运行 存储插件

用户在真正使用时通常是利用已经构建好的存储插件镜像,或者是直接部署 Clusterpedia 高级 Chart

本地运行

插件构建

存储插件实际是一个 .so 后缀的动态链接库,Clusterpedia 组件在启动时可以加载存储插件,并根据指定的存储层名称来使用具体的存储插件

我们以 clusterpedia-io/sample-storage 为例,构建出一个存储插件二进制

$ git clone --recursive https://github.com/clusterpedia-io/sample-storage.git && cd sample-storage
$ make build-plugin

使用 file 命令查看存储插件信息

$ file ./plugins/sample-storage-layer.so
./plugins/sample-storage-layer.so: Mach-O 64-bit dynamically linked shared library x86_64

Clusterpedia 的 ClusterSynchro ManagerAPIServer 组件可以通过环境变量和命令参数来加载和使用存储插件:

  • STORAGE_PLUGINS=<plugins dir> 环境变量设置插件所在目录,Clusterpedia 会将该目录下所有插件都加载到组件中
  • --storage-name=<storage name> 插件命令参数,设置存储层名称
  • --storage-config=<storage config path> 插件命令参数,设置存储层配置

组件构建

本地运行时,为了保证依赖一致,需要在本地通过 make build-components 命令构建 clusterpedia 组件

$ # 在 sample-storage 目录
$ make build-components
$ ls -al ./bin
-rwxr-xr-x   1 icebergu  staff  90707488 11  7 11:15 apiserver
-rwxr-xr-x   1 icebergu  staff  91896016 11  7 11:16 binding-apiserver
-rwxr-xr-x   1 icebergu  staff  82769728 11  7 11:16 clustersynchro-manager
-rwxr-xr-x   1 icebergu  staff  45682000 11  7 11:17 controller-manager

关于存储插件与 Clusterpedia 组件的构建可以查看 开发自定义存储层插件

存储插件运行时的配置文件

在运行 clusterpedia 前还需要准备存储插件在运行时的配置文件,sample-storage 提供了它的配置示例 example-config.yaml

在运行时 clusterpedia 组件时,通过 --storage-config=./config.yaml 来指定运行时配置文件

# example-config.yaml
type: mysql
host: 127.0.0.1
port: "3306"
user: root
password: dangerous0
database: clusterpedia
log:
  stdout: true
  colorful: true
  slowThreshold: 100ms

用户需要根据选择的存储层来配置运行时配置

运行 clusterpedia clustersynchro manager

$ STORAGE_PLUGINS=./plugins ./bin/clustersynchro-manager --kubeconfig ~/.kube/config \
    --storage-name=sample-storage-layer \
    --storage-config ./config.yaml

运行 clusterpedia apiserver

可以选择不使用自己生成的证书,这时需要在运行 apiserver 忽略掉 --client-ca-file ca.crt 参数

$ openssl req -nodes -new -x509 -keyout ca.key -out ca.crt
$ openssl req -out client.csr -new -newkey rsa:4096 -nodes -keyout client.key -subj "/CN=development/O=system:masters"
$ openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -sha256 -out client.crt

运行 apiserver

$ STORAGE_PLUGINS=./plugins ./bin/apiserver --client-ca-file ca.crt  --secure-port 8443 \
    --kubeconfig ~/.kube/config \
    --authentication-kubeconfig ~/.kube/config \
    --authorization-kubeconfig ~/.kube/config \
    --storage-name=sample-storage-layer \
    --storage-config ./config.yaml

存储插件镜像 + Helm Charts

Clusterpeida 已经提供了多个 Charts:

如果用户没有存储插件需求,默认存储层和关系型数据库已经可以满足需求的话,可以直接选用 charts/clusterpedia,开箱即用

clusterpedia-mysqlclusterpedia-postgresqlclusterpedia-elasticsearch 便是基于 clusterpedia-core 实现的高级 Charts,在这些 Charts 中通过默认配置 clusterpedia-core 的存储插件镜像和存储层配置来为用户屏蔽掉存储插件的复杂概念,开箱即用

尽管我们在使用中通常会直接使用高级 Charts,但是知道如何使用 clusterpedia-core 来设置存储插件镜像,可以让我们更好的理解插件镜像是如何工作的。

clusterpedia-core

我们以 clusterpedia-io/sample-storage 为例,使用 ghcr.io/clusterpedia-io/clusterpedia/sample-storage-layer 插件镜像来部署 Clusterpedia。

clusterpedia-core 不涉及任何存储组件的部署安装,所以用户需要根据已部署的存储组件来配置存储层

# myvalues.yaml
storage:
  name: "sample-storage-layer"
  image:
    registry: ghcr.io
    repository: clusterpedia-io/clusterpedia/sample-storage-layer
    tag: v0.0.0-v0.6.0
  config:
    type: "mysql"
    host: "10.111.94.196"
    port: 3306
    user: root
    password: dangerous0
    database: clusterpedia

storage.name 配置存储镜像插件的存储层名称

clusterpedia-core 会将 storage.image 定义的插件镜像中的存储插件复制到组件的插件目录下

# helm template clusterpedia -n clusterpedia-system -f myvalues.yaml ./clusterpedia-core
...
      initContainers:
      - name: copy-storage-plugin
        image: ghcr.io/clusterpedia-io/clusterpedia/sample-storage-layer:v0.0.0-v0.6.0
        imagePullPolicy: IfNotPresent
        command:
          - /bin/sh
          - -ec
          - cp /plugins/* /var/lib/clusterpedia/plugins/
        volumeMounts:
        - name: storage-plugins
          mountPath: /var/lib/clusterpedia/plugins
      containers:
      - name: clusterpedia-clusterpedia-core-apiserver
        image: ghcr.io/clusterpedia-io/clusterpedia/apiserver:v0.6.0
        imagePullPolicy: IfNotPresent
        command:
        - /usr/local/bin/apiserver
        - --secure-port=443
        - --storage-name=sample-storage-layer
        - --storage-config=/etc/clusterpedia/storage/config.yaml
        env:
        - name: STORAGE_PLUGINS
          value: /var/lib/clusterpedia/plugins
        volumeMounts:
        - name: storage-config
          mountPath: /etc/clusterpedia/storage
          readOnly: true
        - name: storage-plugins
          mountPath: /var/lib/clusterpedia/plugins
          readOnly: true
      volumes:
      - name: storage-config
        configMap:
          name: clusterpedia-clusterpedia-core-sample-storage-layer-config
      - name: storage-plugins
        emptyDir: {}
...

除了使用 storage.config 定义存储层的运行时配置 config.yaml 外,还可以使用已有的 configmap 以及 secret

# myvalues.yaml
storage:
  name: "sample-storage-layer"
  image:
    registry: ghcr.io
    repository: clusterpedia-io/clusterpedia/sample-storage-layer
    tag: v0.0.0-v0.6.0

  configMap: "sample-storage-config"
  componentEnv:
  - name: DB_PASSWORD
    valueFrom:
      secretKeyRef:
        name: "sample-storage-password"
        key: password

clusterpedia-core 为了能够作为子 Chart 被其他高级 Charts 引用,在存储层配置上是非常灵活的,但是用户实际在使用中并不一定需要直接使用 clusterpedia-core,只需要使用针对具体存储组件部署的高级 Charts 即可,例如 clusterpedia-mysqlclusterpedia-postgresql

在下节我们也会介绍如何基于 clusterpedia-core 来针对具体存储组件实现高级 Chart

开发自定义存储层插件

clusterpedia-io/sample-storage 不仅仅是一个存储插件示例,也是一个模版仓库,其中项目结构和大部分构建工具都可以在其他存储插件项目中使用

我们首先 clone sample-storage,或者根据 sample-storage 生成一个新的存储插件仓库

$ git clone --recursive https://github.com/clusterpedia-io/sample-storage.git && cd sample-storage

注意拉取仓库时,需要指定 --recursive 拉取子仓库

$ ls -al
...
-rw-r--r--   1 icebergu  staff    260 12 13 15:14 Dockerfile
-rw-r--r--   1 icebergu  staff   1836 12 13 16:03 Makefile
-rw-r--r--   1 icebergu  staff   2219 11 23 10:25 README.md
drwxr-xr-x  32 icebergu  staff   1024 11 23 10:30 clusterpedia
-rw-r--r--   1 icebergu  staff    156 11 23 10:25 example-config.yaml
-rw-r--r--   1 icebergu  staff   2376 12 13 15:33 go.mod
-rw-r--r--   1 icebergu  staff  46109 12 13 15:33 go.sum
-rw-r--r--   1 icebergu  staff    139 11 23 10:25 main.go
drwxr-xr-x  16 icebergu  staff    512 12 13 15:33 storage
drwxr-xr-x   9 icebergu  staff    288 12 13 15:33 vendor

整个项目结构分为三类

  • main.go, storage 包:自定义存储层插件的核心逻辑
  • clusterpedia 主库,用于本地开发和测试
  • DockerfileMakefile 用于项目构建和镜像打包,可以适用于任何存储插件项目

核心逻辑

main.go 是存储插件的主文件,主要用来调用 storage 包中的注册函数 —— RegisterStorageLayer

package main

import (
	plugin "github.com/clusterpedia-io/sample-storage-layer/storage"
)

func init() {
	plugin.RegisterStorageLayer()
}

storage 包中的是存储插件的核心逻辑:

  1. 实现 clusterpedia 存储层接口 storage.StorageFactory
import (
	"gorm.io/gorm"

	"github.com/clusterpedia-io/clusterpedia/pkg/storage"
)

type StorageFactory struct {
	db *gorm.DB
}

var _ storage.StorageFactory = &StorageFactory{}
  1. NewStorageFactory 函数来返回 storage.StorageFactory 实例
func NewStorageFactory(configPath string) (storage.StorageFactory, error)
  1. RegisterStorageLayer 函数将 NewStorageFactory 注册到 clusterpedia 中
const StorageName = "sample-storage-layer"

func RegisterStorageLayer() {
	storage.RegisterStorageFactoryFunc(StorageName, NewStorageFactory)
}

当用户通过 --storage-name 指定该存储层时,会自动调用注册的 NewStorageFactory 来创建 storage.StorageFactory 实例。

./bin/apiserver --storage-name=sample-storage-layer <other flags>

本地开发运行

为了方便开发测试,我们在存储插件的仓库中添加了 clusterpedia 主库作为子库

$ git submodule status
+4608c8d13101d82960525dfe39f51e4f64ed49b3 clusterpedia (v0.6.0)

并且将 go.mod 中 clusterpedia 仓库 replace 为本地子库

# go.mod
replace (
        github.com/clusterpedia-io/api => ./clusterpedia/staging/src/github.com/clusterpedia-io/api
        github.com/clusterpedia-io/clusterpedia => ./clusterpedia
)

在构建存储层镜像时,不会使用本地 cluserpedia 子库

存储插件构建

存储插件的构建分为两部分,分别是构建 clusterpedia 子库中组件和构建存储插件

$ make build-components
OUTPUT_DIR=/Users/icebergu/workspace/clusterpedia/sample-storage-layer ON_PLUGINS=true \
                /Library/Developer/CommandLineTools/usr/bin/make -C clusterpedia all
hack/builder.sh apiserver
hack/builder.sh binding-apiserver
hack/builder.sh clustersynchro-manager
hack/builder-nocgo.sh controller-manager

$ ls -al ./bin
-rwxr-xr-x   1 icebergu  staff  90724968 12 15 09:51 apiserver
-rwxr-xr-x   1 icebergu  staff  91936472 12 15 09:52 binding-apiserver
-rwxr-xr-x   1 icebergu  staff  82826584 12 15 09:52 clustersynchro-manager
-rwxr-xr-x   1 icebergu  staff  45677904 12 15 09:52 controller-manager

make build-components 命令会在调用 clusterpedia 库中的 make all,并将结果输出到存储插件项目的 ./bin 目录下

如果 clusterpedia 子库未发生更改,那么只需要构建组件即可

构建存储插件

$ make build-plugin
CLUSTERPEDIA_REPO=/Users/icebergu/workspace/clusterpedia/sample-storage/clusterpedia \
                clusterpedia/hack/builder.sh plugins sample-storage-layer.so

$ ls -al ./plugins
-rw-r--r--   1 icebergu  staff  53354352 12 15 09:47 sample-storage-layer.so

本地构建存储插件也是需要使用 clusterpedia 库的 builder.sh 脚本来构建插件二进制

关于运行存储层插件可以参考 本地运行存储插件

存储插件镜像

上文提到,存储插件在真正的部署中,是通过镜像的方式将存储插件共享给 clusterpedia。

Makefile 中提供 make image-plugin 来构建镜像,make push-images 来发布镜像

构建镜像

构建插件镜像时,我们需要使用 clusterpedia/builder 镜像作为基础镜像来构建插件,builder 镜像的版本需要和使用插件的 clusterpedia 组件的版本一致

$ BUILDER_IMAGE=ghcr.io/clusterpedia-io/clusterpedia/builder:v0.6.0 make image-plugin

clusterpedia 中维护了已发布版本的 builder 镜像,用户也可以使用自己本地构建的 builder 镜像

本地构建 builder 镜像

$ cd clusterpedia
$ make image-builder
docker buildx build \
                -t "ghcr.io/clusterpedia-io/clusterpedia"/builder-amd64:4608c8d13101d82960525dfe39f51e4f64ed49b3 \
                --platform=linux/amd64 \
                --load \
                -f builder.dockerfile . ; \

存储插件镜像的 tag 格式为 -<clusterpedia-version/commit>,例如: ghcr.io/clusterpedia-io/clusterpedia/sample-storage-layer:v0.0.0-v0.6.0

存储插件镜像可以部署在 <clusterpedia-version/commit> 版本的 Clusterpedia 中

镜像推送

make image-plugin 根据手动设置的 builder 镜像来构建存储插件镜像

而使用 make push-images 推送镜像时会自动为所有兼容版本和架构构建镜像

# Makefile
CLUSTERPEDIA_VERSIONS = v0.6.0-beta.1 v0.6.0
RELEASE_ARCHS ?= amd64 arm64

镜像构建好后,可以通过 cluserpedia-core 来使用存储插件镜像

基于 clusterpeida-core 实现高级 Chart

我们在实现自己的存储插件后,为了更加方便的使用,还是需要基于 clusterpedia-core Chart 来封装出高级 Chart

高级 Chart 需要提供以下能力:

  • 设置默认的存储插件镜像
  • 设置存储层名称
  • 支持动态设置存储层的运行时配置
  • 提供对存储组件的配置和安装

创建一个使用 sample-storage 存储插件的新 Chart —— clusterpedia-sample-mysql,这个 Chart 会使用 mysql 作为存储组件。

# Chart.yaml
dependencies:
  - name: mysql
    repository: https://charts.bitnami.com/bitnami
    version: 9.x.x
  - name: common
    repository: https://charts.bitnami.com/bitnami
    version: 1.x.x
  - name: clusterpedia-core
    repository: https://clusterpedia-io.github.io/clusterpedia-helm/
    version: 0.1.x

我们需要覆盖 clusterpedia-core 中存储层相关的设置,clusterpedia-core 提供 values.yaml动态模版两种方式来设置存储插件和存储层信息

我们在 values.yaml 覆盖存储层的静态设置,例如插件镜像存储层名称

# values.yaml
clusterpedia-core:
  storage:
    name: "sample-storage-layer"
    image:
      registry: "ghcr.io"
      repository: "clusterpedia-io/clusterpedia/sample-storage-layer"
      tag: "v0.0.0-v0.6.0"

自定义存储层的 config.yaml 和一些环境变量的设置,一般需要引用 ConfigMap 和 Secret,而这些资源的名称会根据 Chart 的 Release 名字动态变化,所以我们需要使用 动态模版 的方式来设置

clusterpedia-core 提供了三个可以覆盖的命名模版

# clusterpedia-core/templates/_storage_override.yaml
{{- define "clusterpedia.storage.override.initContainers" -}}
{{- end -}}

{{- define "clusterpedia.storage.override.configmap.name" -}}
{{- end -}}

{{- define "clusterpedia.storage.override.componentEnv" -}}
{{- end -}}

可以分别设置:

  • apiserverclustersynchro manager 组件运行前的 init containers
  • 保存存储插件需要读取的 config.yaml 配置的 ConfigMap 名称
  • 存储插件需要使用的环境变量

我们以 clusterpedia-mysql 为例,看看它的设置

# _storage_override.yaml
{{- define "clusterpedia.storage.override.initContainers" -}}
- name: ensure-database
  image: docker.io/bitnami/mysql:8.0.28-debian-10-r23
  command:
  - /bin/sh
  - -ec
  - |
    if [ ${CREARE_DATABASE} = "ture" ]; then
      until mysql -u${STORAGE_USER} -p${DB_PASSWORD} --host=${STORAGE_HOST} --port=${STORAGE_PORT} -e 'CREATE DATABASE IF NOT EXISTS ${STORAGE_DATABASE}'; do
      echo waiting for database check && sleep 1;
      done;
      echo 'DataBase OK ✓'
    else
      until mysqladmin status -u${STORAGE_USER} -p${DB_PASSWORD} --host=${STORAGE_HOST} --port=${STORAGE_PORT}; do sleep 1; done
    fi    
  env:
  - name: DB_PASSWORD
    valueFrom:
      secretKeyRef:
        name: {{ include "clusterpedia.mysql.storage.fullname" . }}
        key: password
  envFrom:
  - configMapRef:
      name: {{ include "clusterpedia.mysql.storage.initContainer.env.name" . }}
{{- end -}}

clusterpedia-mysql 在 storage-initcontainer-env-configmap.yaml 中定义了 init container 需要的环境变量

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ include "clusterpedia.mysql.storage.initContainer.env.name" . }}
  namespace: {{ .Release.Namespace }}
  labels: {{ include "common.labels.standard" . | nindent 4 }}
data:
  STORAGE_HOST: {{ include "clusterpedia.mysql.storage.host" . | quote }}
  STORAGE_PORT: {{ include "clusterpedia.mysql.storage.port" . | quote }}
  STORAGE_USER: {{ include "clusterpedia.mysql.storage.user" . | quote }}
  STORAGE_DATABASE: {{ include "clusterpedia.mysql.storage.database" . | quote }}
  CREARE_DATABASE: {{ .Values.externalStorage.createDatabase | quote }}

通过 clusterpedia.storage.override.initContainers 命名模版动态设置的 init container 会被渲染到 Deployment 中:

# helm template clusterpedia -n clusterpedia-system --set persistenceMatchNode=None .
...
    spec:
      initContainers:
      - name: ensure-database
        image: docker.io/bitnami/mysql:8.0.28-debian-10-r23
        command:
        - /bin/sh
        - -ec
        - |
          if [ ${CREARE_DATABASE} = "ture" ]; then
            until mysql -u${STORAGE_USER} -p${DB_PASSWORD} --host=${STORAGE_HOST} --port=${STORAGE_PORT} -e 'CREATE DATABASE IF NOT EXISTS ${STORAGE_DATABASE}'; do
            echo waiting for database check && sleep 1;
            done;
            echo 'DataBase OK ✓'
          else
            until mysqladmin status -u${STORAGE_USER} -p${DB_PASSWORD} --host=${STORAGE_HOST} --port=${STORAGE_PORT}; do sleep 1; done
          fi          
        env:
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: clusterpedia-mysql-storage
              key: password
        envFrom:
        - configMapRef:
            name: clusterpedia-mysql-storage-initcontainer-env

保存存储插件运行时配置 config.yaml 的 ConfigMap 和环境变量也是在 clusterpedia-mysql 中动态配置

# _storage_override.yaml

{{- define "clusterpedia.storage.override.configmap.name" -}}
{{- printf "%s-mysql-storage-config" .Release.Name -}}
{{- end -}}

{{- define "clusterpedia.storage.override.componentEnv" -}}
- name: DB_PASSWORD
  valueFrom:
    secretKeyRef:
      name: {{ include "clusterpedia.mysql.storage.fullname" . }}
      key: password
{{- end -}}

通过 values 静态覆盖和 命名模版的动态设置,存储层配置会被设置到 APIServer 和 ClusterSynchro Manager 的 Deployment 中

通过类似 clusterpedia-mysql高级 Chart 可以为用户屏蔽掉底层存储插件的使用,达到开箱即用。

5 - 特性功能

用户在使用特性功能时,需要开启相应的特性门控。 例如开启 clustersynchro manager 的 SyncAllResources 来允许使用 全资源通配符

# 忽略其他参数
./bin/clustersynchro-manager --feature-gates=SyncAllResources=true

Clusterpedia APIServer 和 Clusterpedia ClusterSynchro Manager 分别具有不同的特性门控

APIServer

作用 feature gate 默认值
设置默认返回剩余的资源数量 RemainingItemCount false
原生 SQL 查询 AllowRawSQLQuery false

ClusterSynchro Manager

作用 feature gate 默认值
裁剪 metadata.managedFields 字段 PruneManagedFields true
裁剪 metadata.annotations['lastAppliedConfiguration'] 字段 PruneLastAppliedConfiguration true
允许同步所有类型的自定义资源 AllowSyncCustomResources false
允许同步所有类型的资源 AllowSyncAllResources false
集群健康检查使用独立 TCP 连接 HealthCheckerWithStandaloneTCP false

5.1 - 返回剩余资源数量

我们在查询时,可以通过 search label 或者 url query,要求在响应中携带剩余的资源数量。

search label url query
search.clusterpedia.io/with-continue withContinue

详细使用可以参考 响应携带剩余资源数量信息

可以通过 Feature Gates —— RemainingItemCount 来设置默认返回剩余的资源数量,这样用户就不需要在每次请求时使用 search label 或者 url query 来显示要求了。

在默认返回剩余资源数量时,用于依然可以通过 search label 或者 url quera 来不返回剩余的资源数量

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis/apps/v1/deployments?withRemainingCount=false&limit=1" | jq

专属于 clusterpedia apiserver 的 Feature Gate

作用 feature gate 默认值
设置是否默认返回剩余的资源数量 RemainingItemCount false

由于该功能可能会对存储层的行为或者性能有影响,所以默认关闭

对于默认存储层,返回剩余资源数量会导致额外的 COUNT 查询

5.2 - 原生 SQL 查询

不同的用户的需求可能是不同的,尽管 clusterpedia 提供了很多简便的检索条件,例如指定一组命名空间或者资源名称,也可以指定 owner 进行查询,但是用户依然可能会有更加复杂的查询。

这时,用户可以使用默认存储层提供的 原生 SQL 条件查询 来传递更加复杂的检索条件

URL="/apis/clusterpedia.io/v1beta1/resources/apis/apps/v1/deployments"
kubectl get --raw="$URL?whereSQL=(cluster='global') OR (namespace IN ('kube-system','default'))"

示例中,我们传递一个用于 WHERE 查询的 SQL 语句 —— (cluster=‘global’) OR (namespace IN (‘kube-system’,‘default’)),

这个语句会检索 global 集群内所有命名空间下以及其他集群中 kube-systemdefault 命名空间下的 deployments

sql 语句需要符合具体的存储组件的 SQL 语法

该特性门控专属于 clusterpedia apiserver

作用 feature gates 默认值
允许使用原生 SQL 设置检索条件 AllowRawSQLQuery false

原生 SQL 查询当前还在 alpha 阶段,并且对 SQL 注入没有很好的防范,所以需要用户通过 Feature Gates 来开启该功能

5.3 - 独立健康检查连接

在 client-go 中使用相同的配置连接一个集群时,会使用同一条 TCP 连接 https://github.com/kubernetes/kubernetes/blob/3f823c0daa002158b12bfb2d53bcfe433516659d/staging/src/k8s.io/client-go/transport/transport.go#L54

这导致集群的健康检查会和资源同步的 Informer 使用相同的 TCP。在大量资源 Informer 启动时,由于 TCP 阻塞可能会导致健康检查的请求超时,这时即使集群是健康的也会导致健康检查失败。

我们现在允许健康检查使用单独的一条 TCP 连接,这样资源同步时的 TCP 拥堵并不会影响到健康检查的响应。该功能需要开启 Feature Gate —— HealthCheckerWithStandaloneTCP

作用 feature gates 默认值
集群健康检查使用独立 TCP 连接 HealthCheckerWithStandaloneTCP false

注意:开启该功能后,连接到成员集群的 TCP 长连接会从 1 变成 2,如果接入 1000 个集群,那么 ClusterSynchro Manager 会维持 2000 条 TCP 连接。

5.4 - 资源字段裁剪

资源的 metadata 中有一些字段在实际搜索中通常没有太大用处,所以在同步时我们会默认裁剪这些字段。

我们使用特性门控来分别控制这些字段是否在资源同步时被裁剪,这些特性门控专属于 clustersynchro manager 组件

field feature gates 默认值
metadata.managedFields PruneManagedFields true
metadata.annotations[‘lastAppliedConfiguration’] PruneLastAppliedConfiguration true

5.5 - 同步所有的自定义资源

自定义资源不同于 kube 的内置资源,kube 的内置资源通常不会经常性变动(依然有两种情况会导致原生资源类型资源改变), 而自定义资源的类型可能会被动态的创建和删除

用户如果想要根据被纳管集群中的 CRD 的变动来自动调节同步的资源类型,那么用户在 PediaCluster 中指定同步所有自定义资源。

spec:
  syncAllCustomResources: true

该功能可能会导致大量的长连接,所以需要在 clustersynchro manager 中开启 Feature Gate

作用 feature gate 默认值
允许同步所有的自定义资源 AllowSyncAllCustomResources true

5.6 - 同步所有的资源

用户可以通过 全资源通配符 来同步所有类型的资源,当被纳管集群中发生任意的资源类型变动(例如 kube 版本升级,group/version 被禁用,CRD 或者 APIService 变动)都会导致同步的资源类型发生修改。

spec:
  syncResources:
  - group: "*"
    resources:
    - "*"

请谨慎使用该功能,该功能会创建大量的长连接,未来 Clusterpedia 添加 Agent 功能后,可以避免长连接的创建

建议指定具体的资源类型,如果需要对自定义资源进行动态同步,可以使用 同步所有的自定义资源

使用全资源通配符 需要在 clustersynchro manager 中开启 Feature Gate

作用 feature gate 默认值
允许同步所有的资源 AllowSyncAllResources true

6 - 版本日志