spring-cloud / spring-cloud-kubernetes

Kubernetes integration with Spring Cloud Discovery Client, Configuration, etc...
Apache License 2.0
3.47k stars 1.03k forks source link

reload configmap #506

Closed damon008 closed 4 years ago

damon008 commented 4 years ago

Describe the bug Using examples, I wrote one,but I found the app not reload configmap after execute 'kubectl edit cm demo-configmap', Then I delete the pod of app, it can get the latest config

Sample my bootstrap.yaml image

lubumbax commented 4 years ago

@damon008 , can you try naming your ConfigMap the same as the spring application?. Something like:

apiVersion: v1
kind: ConfigMap
metadata:
  name: edge-admin
  namespace: your-namespace

The management.endpoint.restart.enabled: "true" property is not really mandatory, at least in the latest releases.

Adding to that, I have been able to make that work on Greenwich.SR4 (and SR1, SR2, SR3).

        <spring-boot.version>2.1.8.RELEASE</spring-boot.version>
        <spring-cloud.version>Greenwich.SR4</spring-cloud.version>
        <spring.cloud.k8s.version>1.1.1.RELEASE</spring.cloud.k8s.version>

Unfortunately, if I change to Hoxton.SR1 the changes in a ConfigMap won't be reloaded anymore.

damon008 commented 4 years ago

@lubumbax I add application.yaml for mybatis and server port and so on in my project.Does it have any influence?

damon008 commented 4 years ago

what is the views of the official spring?

damon008 commented 4 years ago

@lubumbax do what you said, the app run failed, show the log: image

lubumbax commented 4 years ago

@lubumbax I add application.yaml for mybatis and server port and so on in my project.Does it have any influence?

Not sure what "mybatis" means.
Combining an application.yaml with ConfigMap is fine. You can also add a bootstrap.yaml to that if you want. You can add properties to either of them.
I prefer (like many others) adding all possible app/service properties to ConfigMap and only those that are most critical for the app to start to bootstrap.yaml. That said, I would get rid of application.yaml and put as much as possible in ConfigMap.

The views of the official spring are well documented here: https://cloud.spring.io/spring-cloud-static/spring-cloud-kubernetes/1.1.1.RELEASE/reference/html/#kubernetes-propertysource-implementations My advise is that you make a thorough read of that chapter and see if something rings a bell.

A bit more about application.yaml vs bootstrap.yaml here.

Regarding the last screenshot, I can't really say what causes that exception. What dependencies have you added to your POM (assuming you are using Maven)?

damon008 commented 4 years ago

@lubumbax it print log when I edit cm configmap-name,it show me that it reload image The following levels of reload are supported (by setting the spring.cloud.kubernetes.reload.strategy property): * refresh (default): Only configuration beans annotated with @ConfigurationProperties or @RefreshScope are reloaded. I use @ConfigurationProperties ,but I can not get the new value from the configmap of what I edit.

damon008 commented 4 years ago

@lubumbax Can you show your demo?

damon008 commented 4 years ago

@lubumbax Hello, I found what happened.After add db such as mybatis or redis when use the springcloud-kubernetes with configmap, the configmap can not be reloaded.

you can try when add db resource such as redis or mysql.

damon008 commented 4 years ago

@lubumbax Do you have a similar problem?

lubumbax commented 4 years ago

Not really. I added the following dependencies to one of my services:

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
            <type>jar</type>
        </dependency>

Then configured a JedisConnectionFactory bean that connected to Redis running on another service.

A change in the ConfigMap of that service triggered reload.

damon008 commented 4 years ago

@lubumbax What kind of your JedisConnectionFactory? and about mysql , what kind of mybatis? about the bean

damon008 commented 4 years ago

@lubumbax you can try this:

<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>

In my project, this can not

damon008 commented 4 years ago

@lubumbax I try what uou said, I found it not reload before delete pod

lubumbax commented 4 years ago

I would need to get a link to a code repo with a sample application reproducing the issue; please provide it here.

damon008 commented 4 years ago

@lubumbax

the demo code: Base on

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.8.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <swagger.version>2.6.1</swagger.version>
        <xstream.version>1.4.7</xstream.version>
        <pageHelper.version>4.1.6</pageHelper.version>
        <fastjson.version>1.2.51</fastjson.version>
        <shiro.version>1.3.0</shiro.version>
        <!-- <kubernetes-client-version>6.0.1</kubernetes-client-version> -->
        <kubernetes-client-version>5.0.0</kubernetes-client-version>
        <fabric8-kubernetes-client.version>4.6.1</fabric8-kubernetes-client.version><!-- 对应k8s v1.15.3 -->
        <springcloud.version>Greenwich.SR4</springcloud.version>
        <springcloud.kubernetes.version>1.1.1.RELEASE</springcloud.kubernetes.version>
        <mysql.version>5.1.46</mysql.version>
    </properties>

            <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
        </dependency>

        <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>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

redis :

<dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <type>jar</type>
        </dependency>

redis bean:

@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
    private Logger logger = LoggerFactory.getLogger(RedisCacheConfig.class);

    private static JedisPool jedisPool;

    @Autowired
    private EnvConfig envConfig;

    /**
     * redis连接工厂
     */
    @Bean
    public JedisPool redisPoolFactory() {
        logger.info("redis url: " + envConfig.getSpring_redis_host() + ":" + envConfig.getSpring_redis_port());
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(8);
        jedisPoolConfig.setMaxWaitMillis(10000);
        if(StringUtils.isBlank(envConfig.getSpring_redis_pwd())) {
             jedisPool = new JedisPool(jedisPoolConfig, envConfig.getSpring_redis_host(), Integer.parseInt(envConfig.getSpring_redis_port()), 10000);
        } else {
             jedisPool = new JedisPool(jedisPoolConfig, envConfig.getSpring_redis_host(), Integer.parseInt(envConfig.getSpring_redis_port()), 10000, envConfig.getSpring_redis_pwd());
        }
        return jedisPool;
    }

    public JedisPool getJedisPool(){
        if(null == jedisPool){
            redisPoolFactory();
        }
        return jedisPool;
    }

demo:

        @Autowired
    private RedisCacheConfig redisCacheConfig;

    @GetMapping(value = "/getTest")
    public String getTest() {
        Jedis jedis = null;
        try {
            JedisPool jedisPool = redisCacheConfig.getJedisPool();
            jedis = jedisPool.getResource();
            return envConfig.getBase_path();
        } 
        catch (JedisException e) {
            logger.error("get redisResource failed", e);
        }
        catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return null;
    }

In EnvConfig, the value of base_path can not reload after edit cm

damon008 commented 4 years ago

@lubumbax Can you show your demo code? about mysql ,after add mysql or mybatis, you can reload the value of Env from the modified configmap. I also can not get the newest value from configmap when add redis or mysql (mybatis).

damon008 commented 4 years ago

@lubumbax I care what kind of your pom?

damon008 commented 4 years ago

@lubumbax @geoand After I edit cm, the log show it change and refresh. image

but I cannot get the edited value with redis or mybatis (mysql), and if I remove db or some pertinent dependence of db (redis). or I means if use db or redis in the project, it also can not reload the newest value after edited the configmap,but if without db or redis, it can.

But In my project, it must have redis and db(mysql) and other beans. It's impossible without these
geoand commented 4 years ago

I am sorry but I don't really know why redis or mysql configuration would not be reloaded after a config change

damon008 commented 4 years ago

@lubumbax Can you show your all demo with redis or mysql? @lubumbax Can you show your all demo with redis or mysql?

Haybu commented 4 years ago

would you please give this spin with version 1.1.3.BUILD-SNAPSHOT and report back your findings

spring-projects-issues commented 4 years ago

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

spring-projects-issues commented 4 years ago

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.