zoukankan      html  css  js  c++  java
  • 【Kubernetes】Spring Boot Actuator

    环境

    1. kubernetes 1.20.2
    2. Spring Boot 2.5.0-M1

    目标

    构建一个 Spring Boot Actuator 镜像,并在 Kubernetes 环境上运行,查看与普通环境上的区别。

    Spring Boot Actuator

    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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.5.0-M1</version>
            <relativePath /> <!-- lookup parent from repository -->
        </parent>
        <groupId>jiangbo.spring.demo</groupId>
        <artifactId>spring-demo</artifactId>
        <version>actuator</version>
        <name>spring-boot-demo</name>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>build-info</id>
                            <goals>
                                <goal>build-info</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
        <repositories>
            <repository>
                <id>spring-milestones</id>
                <name>Spring Milestones</name>
                <url>https://repo.spring.io/milestone</url>
            </repository>
        </repositories>
        <pluginRepositories>
            <pluginRepository>
                <id>spring-milestones</id>
                <name>Spring Milestones</name>
                <url>https://repo.spring.io/milestone</url>
            </pluginRepository>
        </pluginRepositories>
    
    </project>
    

    SpringDemoApplication

    package jiangbo.spring.docker;
    
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.info.BuildProperties;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @SpringBootApplication
    @RestController
    public class SpringDemoApplication {
    
        private final BuildProperties buildProperties;
    
        public SpringDemoApplication(BuildProperties buildProperties) {
    
            this.buildProperties = buildProperties;
        }
    
        private static String hostname;
    
        public static void main(String[] args) throws UnknownHostException {
    
            hostname = InetAddress.getLocalHost().getHostName();
            SpringApplication.run(SpringDemoApplication.class, args);
        }
    
        @GetMapping("/hostname")
        public String hello() {
    
            return hostname + " " + buildProperties.getVersion();
        }
    
    }
    

    application.yaml

    management:
      endpoint:
        shutdown:
          enabled: true
      endpoints:
        web:
          exposure:
            include: "*"
    

    Dockerfile

    FROM openjdk:8-jre-alpine as builder
    ARG JAR_FILE=target/*.jar
    COPY ${JAR_FILE} application.jar
    RUN java -Djarmode=layertools -jar application.jar extract
    
    FROM openjdk:8-jre-alpine
    COPY --from=builder dependencies/ ./
    COPY --from=builder snapshot-dependencies/ ./
    COPY --from=builder spring-boot-loader/ ./
    COPY --from=builder application/ ./
    ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
    

    构建镜像

    打包

    PS D:workspacestsspring-demo> mvn clean package
    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------< jiangbo.spring.demo:spring-demo >-------------------
    [INFO] Building spring-boot-demo actuator
    [INFO] --------------------------------[ jar ]---------------------------------
    [INFO]
    [INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ spring-demo ---
    [INFO] Deleting D:workspacestsspring-demo	arget
    [INFO]
    [INFO] --- spring-boot-maven-plugin:2.5.0-M1:build-info (build-info) @ spring-demo ---
    [INFO]
    [INFO] --- maven-resources-plugin:3.2.0:resources (default-resources) @ spring-demo ---
    [INFO] Using 'UTF-8' encoding to copy filtered resources.
    [INFO] Using 'UTF-8' encoding to copy filtered properties files.
    [INFO] Copying 1 resource
    [INFO] Copying 0 resource
    [INFO]
    [INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ spring-demo ---
    [INFO] Changes detected - recompiling the module!
    [INFO] Compiling 1 source file to D:workspacestsspring-demo	argetclasses
    [INFO]
    [INFO] --- maven-resources-plugin:3.2.0:testResources (default-testResources) @ spring-demo ---
    [INFO] Using 'UTF-8' encoding to copy filtered resources.
    [INFO] Using 'UTF-8' encoding to copy filtered properties files.
    [INFO] skip non existing resourceDirectory D:workspacestsspring-demosrc	est
    esources
    [INFO]
    [INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ spring-demo ---
    [INFO] Changes detected - recompiling the module!
    [INFO]
    [INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ spring-demo ---
    [INFO]
    [INFO] --- maven-jar-plugin:3.2.0:jar (default-jar) @ spring-demo ---
    [INFO] Building jar: D:workspacestsspring-demo	argetspring-demo-actuator.jar
    [INFO]
    [INFO] --- spring-boot-maven-plugin:2.5.0-M1:repackage (repackage) @ spring-demo ---
    [INFO] Replacing main artifact with repackaged archive
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  7.433 s
    [INFO] Finished at: 2021-01-25T21:47:17+08:00
    [INFO] ------------------------------------------------------------------------
    

    构建镜像

    PS D:workspacestsspring-demo> docker build -t jiangbo920827/spring-demo:actuator .
    Sending build context to Docker daemon   19.2MB
    Step 1/10 : FROM openjdk:8-jre-alpine as builder
     ---> f7a292bbb70c
    Step 2/10 : ARG JAR_FILE=target/*.jar
     ---> Using cache
     ---> 061b93704007
    Step 3/10 : COPY ${JAR_FILE} application.jar
     ---> 20e5f2fa61e3
    Step 4/10 : RUN java -Djarmode=layertools -jar application.jar extract
     ---> Running in e5028a5d2546
    Removing intermediate container e5028a5d2546
     ---> 6cfa89d4fe04
    Step 5/10 : FROM openjdk:8-jre-alpine
     ---> f7a292bbb70c
    Step 6/10 : COPY --from=builder dependencies/ ./
     ---> Using cache
     ---> 94c069dd1619
    Step 7/10 : COPY --from=builder snapshot-dependencies/ ./
     ---> Using cache
     ---> 1aba6579c120
    Step 8/10 : COPY --from=builder spring-boot-loader/ ./
     ---> Using cache
     ---> 1f67b70f1647
    Step 9/10 : COPY --from=builder application/ ./
     ---> 6143bdef4fd0
    Step 10/10 : ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
     ---> Running in 3bee9efaf294
    Removing intermediate container 3bee9efaf294
     ---> 27b1db723cf2
    Successfully built 27b1db723cf2
    Successfully tagged jiangbo920827/spring-demo:actuator
    SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. 
    All files and directories added to build context will have '-rwxr-xr-x' permissions. 
    It is recommended to double check and reset permissions for sensitive files and directories.
    

    推送到远程仓库

    PS D:workspacestsspring-demo> docker push jiangbo920827/spring-demo:actuator
    The push refers to repository [docker.io/jiangbo920827/spring-demo]
    da6a673c5c81: Pushed
    b06e2e5a3a34: Mounted from jiangbo920827/spring-docker
    7d97b13df67a: Mounted from jiangbo920827/spring-docker
    edd61588d126: Mounted from jiangbo920827/spring-docker
    9b9b7f3d56a0: Mounted from jiangbo920827/spring-docker
    f1b5933fe4b5: Mounted from library/openjdk
    actuator: digest: sha256:fef2dd74c274e783e4cf2f270da15cadbc0766c8a0d24dad31dd0258e2eb4722 size: 1576
    

    创建 Pod

    pod.yaml

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-demo
    
    spec:
      containers:
        - name: pod-demo
          image: jiangbo920827/spring-demo:actuator
          ports:
            - containerPort: 8080
    
    

    创建

    [root@master pod]# kubectl apply  -f pod.yaml 
    pod/pod-demo created
    

    查看

    [root@master pod]# kubectl get -f pod.yaml -o wide
    NAME       READY   STATUS    RESTARTS   AGE     IP            NODE    NOMINATED NODE   READINESS GATES
    pod-demo   1/1     Running   0          5m12s   10.244.1.16   node1   <none>           <none>
    

    比较

    同时在本地和 Kubernetes 环境上访问 http://localhost:8080/actuator/health

    本地访问

    {
        "status": "UP"
    }
    

    Kubernetes 访问

    URL 根据 Pod 的实际 IP 填写。

    {
      "status": "UP",
      "groups": [
        "liveness",
        "readiness"
      ]
    }
    

    总结

    介绍了创建 Spring Boot Actuator 的镜像,并以 Pod 的方式启动。
    比较了本地和 Kubernetes 的环境暴露健康端点的不通。

    附录

    Spring Boot 判断 Kubernetes 环境

    Spring Boot 判断 Kubernetes 环境的源码如下:

    /**
      * Kubernetes platform.
      */
    KUBERNETES {
    
      private static final String KUBERNETES_SERVICE_HOST = "KUBERNETES_SERVICE_HOST";
    
      private static final String KUBERNETES_SERVICE_PORT = "KUBERNETES_SERVICE_PORT";
    
      private static final String SERVICE_HOST_SUFFIX = "_SERVICE_HOST";
    
      private static final String SERVICE_PORT_SUFFIX = "_SERVICE_PORT";
    
      @Override
      public boolean isDetected(Environment environment) {
        if (environment instanceof ConfigurableEnvironment) {
          return isAutoDetected((ConfigurableEnvironment) environment);
        }
        return false;
      }
    
      private boolean isAutoDetected(ConfigurableEnvironment environment) {
        PropertySource<?> environmentPropertySource = environment.getPropertySources()
            .get(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);
        if (environmentPropertySource != null) {
          if (environmentPropertySource.containsProperty(KUBERNETES_SERVICE_HOST)
              && environmentPropertySource.containsProperty(KUBERNETES_SERVICE_PORT)) {
            return true;
          }
          if (environmentPropertySource instanceof EnumerablePropertySource) {
            return isAutoDetected((EnumerablePropertySource<?>) environmentPropertySource);
          }
        }
        return false;
      }
    
      private boolean isAutoDetected(EnumerablePropertySource<?> environmentPropertySource) {
        for (String propertyName : environmentPropertySource.getPropertyNames()) {
          if (propertyName.endsWith(SERVICE_HOST_SUFFIX)) {
            String serviceName = propertyName.substring(0,
                propertyName.length() - SERVICE_HOST_SUFFIX.length());
            if (environmentPropertySource.getProperty(serviceName + SERVICE_PORT_SUFFIX) != null) {
              return true;
            }
          }
        }
        return false;
      }
    
    };
    

    判断 Kubernetes 环境

    if (CloudPlatform.getActive(environment) == CloudPlatform.KUBERNETES) {
      return ConditionOutcome.match(message.because("running on Kubernetes"));
    }
    
  • 相关阅读:
    树的计数 + prufer序列与Cayley公式 学习笔记
    链表
    密码学摘要
    查找与排序
    匿名内部类 调用方法内局部变量
    <c:url>标签相关知识点
    Oracle 导入导出数据库
    oracle cursor
    Oracle 删除用户和表空间------创建表空间和用户
    iOS延迟执行方法
  • 原文地址:https://www.cnblogs.com/jiangbo44/p/14327762.html
Copyright © 2011-2022 走看看