6月12日容器编排课程贴

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处于随机调度状态");
            }
        }

    }
}