SpringBoot开发中的一些小细节(三)

SpringBoot开发中的一些小细节(三)

2018, Dec 25    

前言

最近主要在获取到的k8s中的相关service和pod的信息的变化,将原来全量获取数据的方式改进为增量的方式,此篇主要记录使用过程中遇到的坑和相信的解决方式

KubernetesClient的包的依赖的引用

使用的是fabric8的kubernetes-client,添加如下依赖即可

<!--在pom.xml文件-->
<dependency>
  <groupId>io.fabric8</groupId>
  <artifactId>kubernetes-client</artifactId>
  <version>4.0.5</version>
</dependency>

配置文件配置相关的属性

application.yml文件

添加k8s集群的主机url,token

api:
  server:
    k8s:
      key: "kubernetes.auth.token"
      token: "***********************************"
      url: "https://10.0.0.0:6443"

这里就有一个坑,就是这个token,由于kubernetes的安全机制,原来获取到的token都只有一天的时效,第二天都需要重新更新一个新的token
这样是肯定不行的,解决的方式有大概下面几种:

  • 使用证书的方式,需要三个文件,CaCertFile,ClientCertFile,ClientKeyFile
  • 获取一种长效的永久的token,这个需要的权限比较高,需要找到kubernetes的负责人,拥有的权限比较高的人
    (查看本地的token,cd ~/.kube,然后cat config,就能看到自己本地的token)
  • 使用账号密码进行登录

configuration的实现

在configuration文件夹下面新建一个class,取名为KubernetesConfig
主要文件内容如下

@Setter
@Configuration
@ConfigurationProperties(prefix = "api.server")
public class KubernetesConfig {
    private K8s k8s;

    private static final int REQUEST_TIMEOUT = 3 * 1000;
    private static final int CONNECTION_TIMEOUT = 3 * 1000;

    @Bean("kubernetesClient")
    public KubernetesClient kubernetesClient() {
        Config config = new ConfigBuilder()
                .withMasterUrl(k8s.getUrl())
                .withOauthToken(k8s.getToken())
                .withTrustCerts(true)
                .removeFromTlsVersions(TlsVersion.TLS_1_0)
                .removeFromTlsVersions(TlsVersion.TLS_1_1)
                .removeFromTlsVersions(TlsVersion.TLS_1_2)
                .withRequestTimeout(REQUEST_TIMEOUT)
                .withConnectionTimeout(CONNECTION_TIMEOUT)
                .build();
        KubernetesClient client = new DefaultKubernetesClient(config);
        return client;
    }

    @Bean("k8s")
    public K8s getK8s() {
        return k8s;
    }

    @Setter
    @Getter
    public static class K8s {
        private String token;
        private String key;
        private String url;
    }

}

以上是使用的是token的方式,进行的登录

还可以使用证书的方式:

  • 将需要的三个证书文件放到项目当中,右键copy path,然后删除src前面的路径
  • 将上面代码中的.withOauthToken(k8s.getToken())替换为

    .withCaCertFile(“src/main/resources/CaCert.crt”)
    .withClientCertFile(“src/main/resources/ClientCert.crt”)
    .withClientKeyFile(“src/main/resources/ClientKey.key”)

还可以使用账号密码的方式进行登录:

  • 将上面代码中的.withOauthToken(k8s.getToken())替换为

    .withUsername(“username”)
    .withPassword(“password”)

使用KubernetesClient实现watch的功能

kubernetesClient.services().inAnyNamespace().watch(new Watcher<Service>() {
      @Override
      public void eventReceived(Action action, Service service) {
          log.debug("service watch action:{}",action);
          log.debug("service watch service:{}",service.toString());
          log.debug("                                            ");
      }

      @Override
      public void onClose(KubernetesClientException e) {

      }
  });

主要的功能实现都在这个event类中实现了,如果想watch pod的话,只需要将services()换成pods()即可

主要的坑是在何处实现?

原本的kubernetes中相关的信息收集,是在定时任务中实现的
但是kubernetes的watch就已经相当于是一个线程了,如果做到让这个功能随着服务的启动而直接就启动了呢?

我的处理方式,依然是使用的定时任务,不过是将定时任务的时间,设置了一个特别长的间隔,这样就算是只启动了一次了
代码如下:

@Scheduled(fixedDelay = 999999999)
public void collectPod() {
    kubernetesService.watchPods();
}