20230219-k8s实战课程贴

课程贴

k8s课程记录.pdf (230.1 KB)

kubeconfig

保存到家目录下:~/.kube/config
修改/etc/hosts, 添加:47.93.32.161 kubernetes

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJek1ESXhNakEwTlRrek5sb1hEVE16TURJd09UQTBOVGt6Tmxvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTnBHCnNZaC9valIrNm92STVIcVBNblpOMEFWRkhOdkJjMVlMQzJYaVQxMmNvQnJpeWZ3ay9ZYzRZQUp6c0JyZU1oR3QKMGxxQUhXbm5PM0RTVXJRbHhBK2I5TlJrY0Y5WlZtd3FOOHF1MFROU0g1NGxHMVRndksxdXIyYTk3ZW1QV1dDNgpoRUpONWFxc2gwSGxpbkNiSEZObkdLTnNidzlDRTdjOC80aUhPZS9BNk5udEpkdXNmT1ZockE3NTVqZ004Z2tSClRXSjFGUHNlYURBa2FqYTBVcmRSeHdYRXViUFQ2U3RWTDBhN1h2QlhvV1FlZGRIN3pkejZ6akhDYjV5RmtMWjMKQTRUczdHd0gxM3dEamFvelUvWCttNEhORnVRTUlTc2JMc2x2djlyQWUxbTdxNWxXQktMdVcvVFdlNTEybWVCVgp3Z2lPUHZtb3Z3eFcxTDU0bmtVQ0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFEUzR4SWJXanpMNnJIVVVYbkN4SUhxOUhETkMKQXZiRUduaENYeUtXYk5mY2lYbkpFc3dRdFVCSSs5Y3BTTEwvb2lUWHY4TE5XaXNzMlAyb1BWbGYrT051ZTNKYwo5SnEyTW91ckVxZnRsdHpteGZ6NDdFMy9tZnpoYzRTR0NlK01oSWhXTCtoYnpkY0I5cUU1cTlURXA0WTRxS1FjCnJxbmFDZiswU0lsSm9uU09TbnVlWFhhMmlwVXpad2FDcHJxek42WFVXK1BRNW5JS0pkays4Qkp0YkhESzVkMUYKVzBaWUtOYU5kTlFxZVdFRnFXWmNqaG93ZDNORmx0V1hxTTN3b1o1QjFJOEpRN3cyVzN0NldIZThOUk1SVlZwSgpPa3E0RktRZU9WUWRvMkpwRVRLKzNLUnprbHJJSkZMOW01NVFuWGpGRmMxVmZtWFhpNmFoSk1KT05Obz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
    server: https://kubernetes:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM4akNDQWRxZ0F3SUJBZ0lJUHA4MWQ4NmgzakF3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TXpBeU1USXdORFU1TXpaYUZ3MHlOREF5TVRJd05EVTVNemRhTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTFMRDhvejlNbnlhMzdTRFYKb2dka05IV0UzamtRaWtaS1MrQVhsVUNjeGhtaGgxa0xNTkxMUVMyUW00eDRKZDFxaG82M05hUkZPWHdjVnBweQo3RXF0azNNSkphSmFwTkIvUnp1Sk9ZNmlpM21wZEIrYWNFWGlPTlJnK2Jnd3V4Y0lyZGxHWVE4RnJpR013eDIrClBZNWZnNzExazhLa0R5b1pubWVRV25UVTJzc0w4eDZUZk1JNHh2ZGxncFFYTTJhREhsZjU3MFl6SCtxZGJTdXoKYXVPbitENzdSMEUzanZnMlJKakVuVXhjTGloVXpDOFZ1QkZKQ0xweVBBZHZkRUlIVkFjT0FwVG4xOHVRMkc0UAo5QmhmbHhuaCt6b0xDUEs4OFYzNUY3aWVpMUNyTHhLOEcvZWVMVjJsS0RsbFRLWnBWUjV2SVBJM0ZrZFBpUE1LCmFpaFVsUUlEQVFBQm95Y3dKVEFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFCMHROS0l3TjBhZjFmNlkxZ0Y2ZE1UcGNlUDRrZ1c1NjhEZgpMMFpiMDhEdkpKY2g5VUtoRGx0ZFdCTzJWZzFTK05zRzA3cGxqWlZnbVNnRlhxUllUWHMyeCtueE5tb2x2QW4xCkRFV1ZMTUQ5OGxKcGhMOFZhKzM0WElXZHBtZTM0SDdVSnlYVzdWSGNWQmJRN3hRVm9HbWJNYmV3eFpsVHIzcVIKaFVLNjQ2Q2JMeDV1U204cXpXZEs0ZXdHUmRJOVpSdUU2Y0Z0RVBYOXlUaGNzM0tEZHdaZnNyelIwb0RTY29uQwpNOWt5ZWNUb2FaYm80Yk95c1lUclNtcEM4VGY2NEF1UFhQVSs1VWxyazV6UjUrMVl5OENHdlBFckIyeEl2V2pjClJkQmhNZDRoem0wb3JIL1luQTFxSkwzUFVhQldIdUp5YzY0YldraEtJcFRSNWt2VE9WMD0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
    client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBMUxEOG96OU1ueWEzN1NEVm9nZGtOSFdFM2prUWlrWktTK0FYbFVDY3hobWhoMWtMCk1OTExRUzJRbTR4NEpkMXFobzYzTmFSRk9Yd2NWcHB5N0VxdGszTUpKYUphcE5CL1J6dUpPWTZpaTNtcGRCK2EKY0VYaU9OUmcrYmd3dXhjSXJkbEdZUThGcmlHTXd4MitQWTVmZzcxMWs4S2tEeW9abm1lUVduVFUyc3NMOHg2VApmTUk0eHZkbGdwUVhNMmFESGxmNTcwWXpIK3FkYlN1emF1T24rRDc3UjBFM2p2ZzJSSmpFblV4Y0xpaFV6QzhWCnVCRkpDTHB5UEFkdmRFSUhWQWNPQXBUbjE4dVEyRzRQOUJoZmx4bmgrem9MQ1BLODhWMzVGN2llaTFDckx4SzgKRy9lZUxWMmxLRGxsVEtacFZSNXZJUEkzRmtkUGlQTUthaWhVbFFJREFRQUJBb0lCQVFDTlJVbG8vUUJkclkvNQpGeGdPMlMzN2todEFwMUtQSllUdnhOYWxNaGR2bFZLdTNid0xIOWdWWUxodU9PME02WFo2RFkwdk9mOG80WURKCkhTazhQWlh4SERWMUk5TmxLWCtBeHRDc3hFcStyWDZhUE91TnF6MUpWZmRicHJYbmJyTTdGZGdqVzZFQU9oU08KL05DQmZuRit4WGExUUZGTUtVQis4SGIzUGlhcmM0QnVqN3pGOGw3NkZVTmZ4c0xFbTMwV3hwTkVXV0ZOMm1uRApRTUwvRUh6Y0NWUW85dnNTKyszRjJTK3lhbGx2YXRJZnJ0WmMrSWNmcG9YSXZaY2pWby9xcFNFUjZJSVNLQm5JCi9MRTNOdUlzMnhacnFvQjNBTktaSjJRRGc5cUJUc20zdUF3S0ppWnZQdjF6T1hhTnhjODgwM2wzanpYcUE3cXkKREcybUIvSjVBb0dCQU9xQkRZV2QyRXpkb3UzRUFjZHhSQWkvdUtEandOb2liaExhZWdyM1hVbDg1bFAvNE1UYQpQMHBrdkR0eG40dWtIZUJSOVBJTmFEb2ErdVBOcHh0RTd3aXIzTzFkY1krUEF0b2Y4WkZPNSsrTjEzRndXQVdmCmdvTlFyM2tuL0k3R3kwVFB4VU51MXN5R2ZnQ3UvanpZM0I0eHA5REFpaEQxQ1VWbzhZbUY4M01IQW9HQkFPZ3cKRWF0eXUxeXgwdHFLQktLUkNkK3BsV3Vpb3FNVlkzZUxSK1NDVXhOT3ltMFhLRmZVZVU3YVgrNk10aGlBSXI4SQpxTWpDWGdvcC9zM1NLRE9ITUNqN01yb3JIQmwrclREbDM0R05FSlAxZCtuNEVHdmxxVHpseTVTUHl2QytrdHlCCndVSUtabGM1aHBDU0xFVEVsOUVhb0RzY2FCM2pwWmFLaHhrYzBjaURBb0dBY2NlSC9ncW1CaldMZGYyaU4xaTMKZjk4MS82cEJ5aFRtZjNOTnY4QmhuT1JqQk9LajloOUdraHZxVUpWQ3FnaEpEcXYxUXZSS1c5YjNZRXhLQmlzZQpKNERyd3FlU0QrdDlvTVBhKzN2amdSRzdOS2tqckNiR3Rsd1JwNkZGSXlsRk91L3NjRmw1RXVjMmY3Sm9YTEdECnE0ckFOOE1UdWtLSjZ3bU9HQUhNSzBVQ2dZQjBicVp0c3pzQllLcTdyRHBteXhTSWRDSFp0OVNXczBNTnoycGQKekh5Y1VnWndiZ3hzL3I5V0sydXYxQi84YVVVRFJ2UmN1QnN3UFo3bzExb1JmTmxKczYzY2JZSEp4eHhTU1BPcgpvM0dNd0t0QlNJUHpsMWNta3BWa0NqZGFRamFqSE80c2o4cUNNdmFueUtVcVZ1dEtrRytKTk5XQko0Y0IxcldvCmdpc3d3UUtCZ1FES29ES3RiaXlOQWRLdlFvY2FCdDJCTkwxNmFzL2tkN0c2K2pTU0QvdEl0ZHIzbmRoQ1BKNHoKZkxCcVpDalhxTXlpK1NUVmE4WGRRZkIzME9FcVdnMmhKUytjaS9TTnlvbVdETlpSL2d3VlNnWmtEU3lBcml1TQpBQWRQc1NwOVJTYVJQaHpDZDF0L3h3OW1Cd0JuOTgyMDVrK2JzU3lQd3UrOWpHdjFpd2dsekE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=

启动grid 配置文件

apiVersion: apps/v1
kind: Deployment
metadata:
  name: selenium-hub
  labels:
    name: selenium-hub
spec:
  replicas: 1
  selector:
    matchLabels:
      name: selenium-hub
  template:
    metadata:
      labels:
        name: selenium-hub
    spec:
      containers:
        - name: selenium-hub
          image: selenium/hub:4.0.0-rc-2-prerelease-20210923
          imagePullPolicy: IfNotPresent
          resources:
            limits:
              cpu: "0.5"
            requests:
              cpu: "0.5"
          ports:
            - containerPort: 4444
            - containerPort: 4442
            - containerPort: 4443
            - containerPort: 5557
          env:
            - name: TZ
              value: "Asia/Shanghai"
          volumeMounts:
            - mountPath: "/etc/localtime"
              name: "host-time"
          livenessProbe:
            httpGet:
              path: /grid/console
              port: 4444
            initialDelaySeconds: 30
            timeoutSeconds: 1
            periodSeconds: 5
            failureThreshold: 3
          readinessProbe:
            httpGet:
              path: /grid/console
              port: 4444
            initialDelaySeconds: 30
            timeoutSeconds: 1
            periodSeconds: 5
            failureThreshold: 3
      volumes:
        - name: "host-time"
          hostPath:
            path: "/etc/localtime"
---
apiVersion: v1
kind: Service
metadata:
  name: selenium-hub
  labels:
    name: selenium-hub
spec:
  type: NodePort
  ports:
    - name: port1
      protocol: TCP
      port: 4442
      targetPort: 4442
    - name: port2
      protocol: TCP
      port: 4443
      targetPort: 4443
    - name: port3
      protocol: TCP
      port: 5557
      targetPort: 5557
    - port: 4444
      targetPort: 4444
      name: port0
      nodePort: 32757
  selector:
    name: selenium-hub
  sessionAffinity: None

node.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: selenium-node-chrome
  labels:
    name: selenium-node-chrome
spec:
  replicas: 2
  selector:
    matchLabels:
      name: selenium-node-chrome
  template:
    metadata:
      labels:
        name: selenium-node-chrome
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - topologyKey: kubernetes.io/hostname
              labelSelector:
                matchLabels:
                  name: selenium-node-chrome
      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

kubectl命令

模式:kubectl [action] [object] [options]

客户端操作

java 依赖
<dependencies>
        <dependency>
            <groupId>io.kubernetes</groupId>
            <artifactId>client-java</artifactId>
            <version>5.0.0</version>
        </dependency>
    </dependencies>
python依赖

pip3 install kubernetes

打印pod名称

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:
K8SClient("/Users/cainsun/.kube/config")

client = get_master_k8s_client()
    namespaces = client.corev1.list_namespace()
    for ns in namespaces.items:
        pods = client.corev1.list_namespaced_pod(ns.metadata.name)
        for p in pods.items:
            # print(p.spec)
            print(p.metadata.name)
扫描工具

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.*;
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("=============没有配置生存探针=======");
                }
            }

        }

    }


}


python版本:

deploys = client.appsv1.list_deployment_for_all_namespaces()
    for d in deploys.items:
        for c in d.spec.template.spec.containers:
            if c.readiness_probe is None:
                print("%s 没有就绪探针" % d.metadata.name)
watch的使用

java版本:

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();
        }
    }
}


python版本:

v1 = client.corev1
    w = watch.Watch()
    count = 10
    for event in w.stream(client.corev1.list_namespace, _request_timeout=60):
        print("Event: %s %s" % (event['type'], event['object'].metadata.name))
        count -= 1
        if not count:
            w.stop()