k8s java客户端pom.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>k8s-java-client</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>Monitor</mainClass> <!-- 你的主类名 -->
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>io.kubernetes</groupId>
<artifactId>client-java</artifactId>
<version>5.0.0</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<java.version>1.8</java.version>
</properties>
</project>
java客户端代码
import io.kubernetes.client.ApiClient;
import io.kubernetes.client.ApiException;
import io.kubernetes.client.Configuration;
import io.kubernetes.client.apis.AppsV1Api;
import io.kubernetes.client.apis.CoreV1Api;
import io.kubernetes.client.apis.ExtensionsV1beta1Api;
import io.kubernetes.client.models.V1Namespace;
import io.kubernetes.client.models.V1Pod;
import io.kubernetes.client.models.V1PodList;
import io.kubernetes.client.util.ClientBuilder;
import io.kubernetes.client.util.KubeConfig;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class TestK8SClient {
public static void main(String[] args) throws IOException, ApiException {
String kubeConfigPath = System.getenv("HOME") + "/.kube/config";
ApiClient client =
ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))).build();
Configuration.setDefaultApiClient(client);
CoreV1Api api = new CoreV1Api();
api.setApiClient(client);
V1PodList list =
api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null);
for (V1Pod item : list.getItems()) {
System.out.println(item.getMetadata().getName());
}
}
}
python 客户端demo
import os
from kubernetes.client import V1Deployment, V1Service, V1ConfigMap, V1Secret, V1Pod
from kubernetes import client, config
from kubernetes.stream import stream
# ns = client.CoreV1Api().list_namespace()
# print(ns)
class K8SClient(object):
def __init__(self, kube_config_path=None):
if os.path.exists(kube_config_path):
self.kube_config_path = kube_config_path
config.load_kube_config(kube_config_path)
else:
config.load_incluster_config()
self.corev1 = client.CoreV1Api()
self.appsv1 = client.AppsV1Api()
def get_deployment_info(self, deployment_name, namespace) -> V1Deployment:
deployment_list = self.appsv1.list_namespaced_deployment(namespace)
for d in deployment_list.items:
if deployment_name in d.metadata.name:
return d
def get_service_into(self, service_name, namespace) -> V1Service:
return self.corev1.read_namespaced_service(service_name, namespace, pretty=True)
def get_configmap_info(self, configmap_name, namespace) -> V1ConfigMap:
return self.corev1.read_namespaced_config_map(name=configmap_name, namespace=namespace, pretty=True)
def get_secret_info(self, secret_name, namespace) -> V1Secret:
return self.corev1.read_namespaced_secret(secret_name, namespace, pretty=True)
def pod_exec_info(self, pod_name, namespace, exec_command, container_name):
return stream(self.corev1.connect_get_namespaced_pod_exec, pod_name, namespace, container=container_name,
command=exec_command, stderr=True, stdin=False, stdout=True, tty=False)
def get_master_k8s_client():
return K8SClient("/root/.kube/config")
HAScanner
import io.kubernetes.client.ApiClient;
import io.kubernetes.client.ApiException;
import io.kubernetes.client.Configuration;
import io.kubernetes.client.apis.AppsV1Api;
import io.kubernetes.client.apis.CoreV1Api;
import io.kubernetes.client.apis.ExtensionsV1beta1Api;
import io.kubernetes.client.models.*;
import io.kubernetes.client.util.ClientBuilder;
import io.kubernetes.client.util.KubeConfig;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
public class HAScanner {
public static void main(String[] args) throws IOException, ApiException {
String kubeConfigPath = System.getenv("HOME") + "/.kube/config";
ApiClient client =
ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))).build();
Configuration.setDefaultApiClient(client);
AppsV1Api api = new AppsV1Api();
V1DeploymentList list =
api.listDeploymentForAllNamespaces(null, null, null, null, null, null, null, null, null);
for (V1Deployment item : list.getItems()) {
System.out.println(item.getMetadata().getName());
// 扫描单点部署
if (item.getSpec().getReplicas() == 1){
System.out.println("==============是单副本部署=============");
}
// 扫描是否配置了pod反亲和性
if (item.getSpec().getTemplate().getSpec().getAffinity() == null||item.getSpec().getTemplate().getSpec().getAffinity().getPodAffinity() ==null){
System.out.println("=============没有配置Pod反亲和=======");
}
// 扫描是否配置了探针
List<V1Container> containers = item.getSpec().getTemplate().getSpec().getContainers();
for (V1Container container: containers){
if (container.getReadinessProbe()==null){
System.out.println("=============没有配置就绪探针=========");
}
}
for (V1Container container: containers){
if (container.getLivenessProbe()==null){
System.out.println("=============没有配置生存探针=======");
}
}
}
}
}
k8s监控
import com.google.gson.reflect.TypeToken;
import com.squareup.okhttp.OkHttpClient;
import io.kubernetes.client.ApiClient;
import io.kubernetes.client.ApiException;
import io.kubernetes.client.Configuration;
import io.kubernetes.client.PodLogs;
import io.kubernetes.client.apis.CoreV1Api;
import io.kubernetes.client.models.V1ContainerStatus;
import io.kubernetes.client.models.V1Namespace;
import io.kubernetes.client.models.V1Pod;
import io.kubernetes.client.models.V1PodList;
import io.kubernetes.client.util.ClientBuilder;
import io.kubernetes.client.util.KubeConfig;
import io.kubernetes.client.util.Watch;
import java.io.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import io.kubernetes.client.util.Config;
public class Monitor {
public static final int DEFAULT_BUFFER_SIZE = 8192;
private static String convertInputStreamToString(InputStream is) throws IOException {
ByteArrayOutputStream result = new ByteArrayOutputStream();
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int length;
while ((length = is.read(buffer)) != -1) {
result.write(buffer, 0, length);
}
// Java 1.1
//return result.toString(StandardCharsets.UTF_8.name());
return result.toString("UTF-8");
// Java 10
//return result.toString(StandardCharsets.UTF_8);
}
public static void main(String[] args) throws ApiException, IOException {
ApiClient client = null;
String kubeConfigPath = System.getenv("HOME") + "/.kube/config";
File file = new File(kubeConfigPath);
if (file.exists()) {
System.out.println("kubeconfig文件已存在");
client = ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))).build();
} else {
System.out.println("kubeconfig文件不存在");
client = Config.defaultClient();
}
client.getHttpClient().setReadTimeout(0, TimeUnit.SECONDS);
// client.setHttpClient(httpClient);
Configuration.setDefaultApiClient(client);
CoreV1Api api = new CoreV1Api();
PodLogs logs = new PodLogs();
Watch<V1Pod> watch =
Watch.createWatch(
client,
api.listPodForAllNamespacesCall(
null, null, null, null, null, null, null, 300, true, null, null),
new TypeToken<Watch.Response<V1Pod>>() {}.getType());
try {
for (Watch.Response<V1Pod> item : watch) {
System.out.printf("%s : %s%n", item.type, item.object.getMetadata().getName());
List<V1ContainerStatus> list = item.object.getStatus().getContainerStatuses();
if (list != null){
for (V1ContainerStatus cs : list){
if (cs.getState().getTerminated()!=null){
System.out.println(cs.getState().getTerminated().getReason());
InputStream is = logs.streamNamespacedPodLog(item.object);
String result = Monitor.convertInputStreamToString(is);
System.out.println(result);
}
}
}
}
} finally {
watch.close();
}
}
}
rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: java-client
namespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: java-client
rules:
- apiGroups: [ "", "apps", "autoscaling", "batch" ]
resources: [ "*" ]
verbs: [ "*" ]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: java-client
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: java-client
subjects:
- kind: ServiceAccount
name: java-client
namespace: default
java-client in k8s
apiVersion: apps/v1
kind: Deployment
metadata:
name: k8s-client
labels:
name: k8s-client
spec:
replicas: 1
selector:
matchLabels:
name: k8s-client
template:
metadata:
labels:
name: k8s-client
spec:
serviceAccount: java-client
containers:
- name: k8s-client
image: localhost:5000/k8s-client
imagePullPolicy: IfNotPresent
dockerfile
FROM williamyeh/java8
ADD target/k8s-java-client-1.0-SNAPSHOT.jar /k8s-java-client-1.0-SNAPSHOT.jar
ENTRYPOINT ["java","-jar","/k8s-java-client-1.0-SNAPSHOT.jar"]
build.sh
mvn clean package
docker build -t 39.102.35.92:5000/k8s-client .
docker push 39.102.35.92:5000/k8s-client
ds.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: selenium-node-chrome
labels:
name: selenium-node-chrome
spec:
selector:
matchLabels:
name: selenium-node-chrome
template:
metadata:
labels:
name: selenium-node-chrome
spec:
containers:
- name: selenium-node-chrome
image: selenium/node-chrome:4.0.0-rc-2-prerelease-20210923
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5900
- containerPort: 5553
env:
- name: SE_EVENT_BUS_HOST
value: "selenium-hub"
- name: SE_EVENT_BUS_PUBLISH_PORT
value: "4442"
- name: SE_EVENT_BUS_SUBSCRIBE_PORT
value: "4443"
- name: SE_NODE_MAX_SESSIONS
value: "20"
- name: SE_NODE_OVERRIDE_MAX_SESSIONS
value: "true"
- name: TZ
value: "Asia/Shanghai"
resources:
requests:
memory: "500Mi"
volumeMounts:
- mountPath: "/dev/shm"
name: "dshm"
- mountPath: "/etc/localtime"
name: "host-time"
volumes:
"node_ds.yaml" 68L, 1659C 12,5 顶端
apiVersion: apps/v1
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: selenium-node-chrome
labels:
name: selenium-node-chrome
spec:
selector:
matchLabels:
name: selenium-node-chrome
template:
metadata:
labels:
name: selenium-node-chrome
spec:
containers:
- name: selenium-node-chrome
image: selenium/node-chrome:4.0.0-rc-2-prerelease-20210923
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5900
- containerPort: 5553
env:
- name: SE_EVENT_BUS_HOST
value: "selenium-hub"
- name: SE_EVENT_BUS_PUBLISH_PORT
value: "4442"
- name: SE_EVENT_BUS_SUBSCRIBE_PORT
value: "4443"
- name: SE_NODE_MAX_SESSIONS
value: "20"
- name: SE_NODE_OVERRIDE_MAX_SESSIONS
value: "true"
- name: TZ
value: "Asia/Shanghai"
resources:
requests:
memory: "500Mi"
volumeMounts:
- mountPath: "/dev/shm"
name: "dshm"
- mountPath: "/etc/localtime"
name: "host-time"
volumes:
- name: "dshm"
hostPath:
path: "/dev/shm"
- name: "host-time"
hostPath:
path: "/etc/localtime"
---
apiVersion: v1
kind: Service
metadata:
name: selenium-node-chrome
labels:
name: selenium-node-chrome
spec:
type: NodePort
ports:
- port: 5900
targetPort: 5900
name: port0
nodePort: 31002
selector:
name: selenium-node-chrome
sessionAffinity: None
扫描随机调度
public class StableScanner {
public static void main(String[] args) throws IOException, ApiException {
String kubeConfigPath = System.getenv("HOME") + "/.kube/config";
ApiClient client =
ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))).build();
Configuration.setDefaultApiClient(client);
CoreV1Api api = new CoreV1Api();
api.setApiClient(client);
V1PodList list =
api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null);
for (V1Pod item : list.getItems()) {
System.out.println(item.getMetadata().getName());
if (item.getSpec().getAffinity() == null || item.getSpec().getAffinity().getNodeAffinity() == null || item.getSpec().getNodeSelector() == null) {
System.out.println("当前Pod处于随机调度状态");
}
}
}
}