获取client

k8s集群的config文件位于:$HOME/.kube
$HOME/.kube/config中包含相关集群、权限验证信息(这里是集群最高权限)

如果需要限制访问权限需要单独生成config文件

Config kubeConfig = new ConfigBuilder()
  .withMasterUrl("https://192.168.66.66:666/")
  .build()
try (final KubernetesClient client = new DefaultKubernetesClient(config)) {
  // Do stuff with client
}

这里额外提供两种获取Config的方法:

通过File获取

File configFile = new File("E:/a/b/config");
final String configYAML = String.join("\n", Files.readAllLines(configFile.toPath()));
Config config = Config.fromKubeconfig(configYAML);
config.setTrustCerts(true);
KubernetesClient client = new DefaultKubernetesClient(config);

通过数据库字段获取

	// get the KubernetesClient by clusterCode
    public KubernetesClient getKubernetesClient(int id) throws IOException {
    	// 从数据库查询config文件的字节数组
        CustomerEntity entity= customerService.selectById(id);
        byte[] configFile = clusterEntity.getConfigFile();

        // 创建Config对象
        final String configYAML = String.join("\n", byte2yamlString(configFile));
        Config config = Config.fromKubeconfig(configYAML);
        config.setTrustCerts(true);

        return new DefaultKubernetesClient(config);
    }

    // 参考 Files.readAllLines 源码
    private List<String> byte2yamlString(byte[] bytes) throws IOException{

        if (bytes == null || bytes.length == 0) {
            return null;
        }
        InputStream inputStream = new ByteArrayInputStream(bytes);
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
        BufferedReader reader  =  new BufferedReader(inputStreamReader);
        List<String> result = new ArrayList<>();
        for (;;) {
            String line = reader.readLine();
            if (line == null)
                break;
            result.add(line);
        }
        return result;
    }

使用client操作k8s集群

上一步获取的KubernetesClient 可操作集群中的以下资源:

Pods
Service
Deployment
ReplicaSet
ReplicationController
ConfigMap
Secret
Job
CronJob
Namespace
ServiceAccount
Ingress
StatefulSet
DaemonSet
PersistentVolumeClaim
PersistentVolume
NetworkPolicy
PodDisruptionBudget
SelfSubjectAccessReview
SubjectAccessReview
LocalSubjectAccessReview
SelfSubjectRulesReview
Top/Metrics
Generic Resource API
Generic ResourceList API
CustomResourceDefinition
CustomResource Typed API
CustomResource Typeless API
CertificateSigningRequest
SharedInformers
List Options
Delete Options
Watch Options
Log Options
Serializing to yaml
Running a Pod

这里举几个常用的例子:

获取Pod

// 通过指定的namespace和podName直接获取
client.pods().inNamespace(nsName).withName(podName).get()

但这样的方式真正的用途不大,因为你的pod很可能是这样的:
pod
并且当pod重启后,后面的字符串还会发生改变。

虽然可以先获取到PodList,之后在程序中使用podName进行模糊匹配,但这并不是一个很好的解决方式。

pod的name虽然会改变,但是deployment的name不会改变,因此可以通过deploymentName再加上matchLabels获取到对应得PodList(List的长度是由deployment中的spec.replicas 决定的)

    // getpod by deploymentName
    public Pod getPodByLabel(String clusterCode, String nsName, String deploymentName) throws IOException {
        KubernetesClient client = getKubernetesClient(clusterCode);
        //通过 deploymentName、namespace 获取matchLabels 
        Map<String, String> matchLabels = client.apps()
                .deployments()
                .inNamespace(nsName)
                .withName(deploymentName)
                .get()
                .getSpec()
                .getSelector()
                .getMatchLabels();
         // 获取PodList
        List<Pod> items = client.pods().inNamespace(nsName).withLabels(matchLabels).list().getItems();
        if (CollectionUtils.isEmpty(items)) {
            return null;
        }
        int podCount = 0;
        Iterator<Pod> iterator = items.iterator();
        // 检验Pod状态
        while (iterator.hasNext()) {
            Pod it = iterator.next();
            if ("Running".equals(it.getStatus().getPhase())) {
                podCount ++;
            } else {
                iterator.remove();
            }
        }
        // 随机获取单个Pod
        double d = Math.random();
        int i = (int)(d*100);
        int index = i % podCount ;
        return items.get(index);
    }

执行kubectl exec pod [-n namespace] cmd

ExecWatch watch = client.pods()
		.inNamespace(nsName)
		.withName(podName)
		.inContainer(containerName) // 如果Pod中只有一个容器,不需要指定
		.writingOutput(System.out)
		.exec("sh", "-c", cmd);

writingOutput() 需要指定一个OutPutStream,可以使用PipedOutputStream获取。

读取Pod中的File

CopyOrReadable<Boolean, InputStream, Boolean> file = client.pods()
		.inNamespace(nsName)
		.withName(podName)
		.inContainer(containerName) // 如果Pod中只有一个容器,不需要指定
		.file(fileName);
// 转String
try (InputStream is = file.read())  {
   return new BufferedReader(new InputStreamReader(is)).lines().collect(Collectors.joining("\n"));
}

拓展:OpenShift Client

获取OpenShiftClient

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

同样可以通过KubernetesClient 获取 KubernetesClient

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

用途

可以直接直接操作一些常用的资源,比如:Prometheus ……

DeploymentConfig
BuildConfig
Route
Project
ImageStream
CatalogSource
PrometheusRule
ServiceMonitor
CluserResourceQuota
ClusterVersion
EgressNetworkPolicy

对于具体资源的操作比直接使用KubernetesClient 略为方便。
参考:kubernetes-client.

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐