Configuration management of Spring Cloud Kubernetes (with code implementation)

All along, people who play springcloud are basically playing springboot1 x. Many related components of spring cloud (Dalston version) are used for configuration center, service registration and discovery. The gateway uses LB made by Netflix for springboot, etc., but these things are too heavy and complex. In a k8s based iaas service system, it is unreasonable to do these things without k8s features. The reason is not repeated. Bottom line: reduce the complexity of system services.

This article mainly introduces how spring cloud combines k8s to do configuration management to avoid redundancy of more service components.

actual combat

Environmental Science:

  • ubuntu16.04
  • docker18.04
  • k8s1.13.x +
  • maven3.5.3
  • java1.8 +
  • springboot 2.1.1
  • spring-cloud-kubernetes: 1.0.1.RELEAS

premise

Install docker18.0 under Ubuntu 04 or other higher versions, k8s1 13. X and above, jvm environment, etc.

Create project

First of all, we need to introduce basic dependency. When managing configuration based on K8s, we need to add the dependency of spring cloud kubernetes component on configmap:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-actuator</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-actuator-autoconfigure</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-kubernetes-config</artifactId>
</dependency>

If redis and db are operated, corresponding dependencies are introduced:

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.1.1</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>${mysql.version}</version>
</dependency>

<!--Paging plug-in-->
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>${pageHelper.version}</version>
    </dependency>

<!-- datasource pool-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.3</version>
</dependency>

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-redis</artifactId>
        <version>1.4.7.RELEASE</version>
</dependency>

The above mainly focuses on the core configuration dependency and the persistence layer dependency of database and redis. Let's look at the main function below:

@SpringBootApplication(scanBasePackages = { "com.leinao" })
@EnableConfigurationProperties(EnvConfig.class)
@EnableDiscoveryClient
@EnableHystrix
@EnableScheduling
public class AdminApp {
	public static void main(String[] args) {
		SpringApplication.run(AdminApp.class, args);
	}
}

Note: EnableConfigurationProperties is added here to introduce the configuration management class. In this way, the property is assigned through the management class. At the same time, if you have the function of adding service registration and discovery, you can introduce @ EnableDiscoveryClient here.

Note that when the startup class is created here, the springboot project is optimized to avoid a lot of loading and heavy startup

Then we are configuring. Note: according to the official, do not create an application under the src\main\resources path of the project YML file, just create a file named bootstrap YML file:

management:
  endpoint:
    restart:
      enabled: true
    health:
      enabled: true
    info:
      enabled: true

spring:
  application:
    name: edge-admin
  cloud:
    kubernetes:
      config:
        sources:
         - name: ${spring.application.name}
           namespace: default
      discovery:
        all-namespaces: true
      reload:
        enabled: true
        mode: polling
        period: 500

Here, we set the automatic update configuration switch to on and update the configuration information at the same time: polling is active pull, and the interval of active pull is 500 milliseconds. You can also set event to be an event notification.

Here, I created the bootstrap file and also added the application file. When starting, I will load the bootstrap first to verify that it is valid.

In application In yaml, we add the following contents:

server:
  port: 9999
  undertow:
    accesslog:
      enabled: false
      pattern: combined
  servlet:
    session:
      timeout: PT120M

Note: the server here sets the session timeout for springboot2.0 0 is completely different from 1.0, depending on the content.

Next, configure the environment configuration:

EnvConfig. The Java class is configured as an environment variable, and the prefix = "spring_cloud" of ConfigurationProperties is annotated, indicating that the configuration items used by this class are sub contents of the configuration item named "spring_cloud":

package com.demo.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConfigurationProperties(prefix = "greeting")
public class EnvConfig {
    private String message = "This is a dummy message";
    public String getMessage() {
        return this.message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
 }

Next, we write a demo interface:

@RestController
public class DemoController {
    @Autowired
    private EnvConfig envConfig;

    @GetMapping(value = "/getMsg")
    public String getMsg() {
            return envConfig.getMessage();
    }
}

Important: the default svc does not have permission to access k8s the resources of API Server. Execute the following script to increase the permission and allow it to access the readable permission of configmap:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: fabric8-rbac
subjects:
  - kind: ServiceAccount
    # Reference to upper's `metadata.name`
    name: default
    # Reference to upper's `metadata.namespace`
    namespace: default
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

Configure configmap:

kind: ConfigMap
apiVersion: v1
metadata:
  name: edge-admin
data:
  application.yaml: |-
    greeting:
      message: Say Hello to the World
    ---
    spring:
      profiles: dev
    greeting:
      message: Say Hello to the Developers

The next step is to execute the deployment startup project:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: edge-admin-deployment
  labels:
    app: edge-admin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: edge-admin
  template:
    metadata:
      labels:
        app: edge-admin
    spec:
      nodeSelector:
        edge-admin: "true"
      containers:
      - name: edge-admin
        image: 10.11.2.20:8000/harbor/edge-admin
        imagePullPolicy: IfNotPresent
        ports:
          - name: admin01
            containerPort: 1002
        volumeMounts:
        - mountPath: /home/edge-admin
          name: edge-admin-path
        - mountPath: /data/edge-admin
          name: edge-admin-log-path
        - mountPath: /etc/kubernetes
          name: kube-config-path
        - mountPath: /abnormal_data_dir
          name: abnormal-data-dir
        args: ["sh", "-c", "nohup java $JAVA_OPTS -jar -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms1024m -Xmx1024m -Xmn256m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC edge-admin.jar --spring.profiles.active=dev", "&"]
      hostAliases:
      - ip: "10.10.1.5"
        hostnames:
        - "k8s.api.server"
        - "foo.remote"
      - ip: "127.0.0.1"
        hostnames:
        - "foo.localhost"
      - ip: "0.0.0.0"
        hostnames:
        - "foo.all"
      #Using admin RBAC Yaml to get permission
      #serviceAccount: config-reader
      #serviceAccountName: config-reader
      volumes:
      - name: edge-admin-path
        hostPath:
          path: /var/pai/edge-admin
      - name: edge-admin-log-path
        hostPath:
          path: /data/edge-admin
      - name: kube-config-path
        hostPath:
          path: /etc/kubernetes
      - name: abnormal-data-dir
        hostPath:
          path: /data/images/detect_result/defect

As mentioned earlier, the performance optimization of project startup parameters is the parameter setting of jvm. Execute kubectl apply - f deployment Yaml and configmap Yaml, the resources of the configmap used to create the demo and the startup project using k8s deployment.

Finally, open the browser and execute ip:port/getMsg to see the corresponding attribute value in configmap. It will not be shown here. If you are interested, you can try it.

The above is the first combination of springcloud and k8s. After that, we can use its configmap feature to do configuration management, abandon the components of springcloud config and spring boot starter actuator, and reduce the complexity of the system. After all, k8s is bound to be used, so we can directly use its feature to do the environment configuration management of system services.

Keywords: Java Docker Spring Spring Boot Vue

Added by Zwiter on Sat, 29 Jan 2022 06:15:36 +0200