<p>I was playing with Kubernetes in Minikube. I could able to deploy spring boot sample application into Kubernetes. </p>

<p>I am exploring Kubernetes configMap. I could successfully run a spring boot application with a spring cloud starter and picking the property keys from config map. Till here I am successful.</p>

<p>The issue I am facing currently is configmap reload. </p>

<p>Here is my config map :</p>

<p><strong>ConfigMap.yaml</strong></p>

<pre><code> apiVersion: v1
kind: ConfigMap
metadata:
  name: minikube-sample
  namespace: default
data:
  app.data.name: name
  application.yml: |-
    app:
      data:
        test: test
</code></pre>

<p><strong>bootstrap.yaml</strong></p>

<pre><code>management:
    endpoint:
        health:
            enabled: true
        info:
            enabled: true
        restart:
            enabled: true
spring:
    application:
        name: minikube-sample
    cloud:
        kubernetes:
            config:
                enabled: true
                name: ${spring.application.name}
                namespace: default
            reload:
                enabled: true
</code></pre>

<p><strong>HomeController:</strong></p>

<pre><code>package com.minikube.sample.rest.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.minikube.sample.properties.PropertiesConfig;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Lookup;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Gorantla, Eresh
 * @created 06-12-2018
 */
@RestController
@RequestMapping("/home")
public class HomeResource {

    @Autowired
    PropertiesConfig config;

    @GetMapping("/data")
    public ResponseEntity&lt;ResponseData&gt; getData() {
        ResponseData responseData = new ResponseData();
        responseData.setId(1);
        responseData.setName(config.getName());
        responseData.setPlace("Hyderabad");
        responseData.setValue(config.getTest());
        return new ResponseEntity&lt;&gt;(responseData, HttpStatus.OK);
    }

    @Getter
    @Setter
    public class ResponseData {
        private String name;
        private Integer id;
        private String place;
        private String value;
    }
}
</code></pre>

<p><strong>deployment.yaml</strong></p>

<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: minikube-sample
  namespace: default
spec:
  selector:
      matchLabels:
        app: minikube-sample

  replicas: 1
  template:
    metadata:
      labels:
        app: minikube-sample
    spec:
      containers:
        - name: minikube-sample
          image: minikube-sample:latest
          imagePullPolicy: Never
          ports:
            - containerPort: 8080
          env:
            - name: env.namespace
              value: default
          volumeMounts:
            - name: config
              mountPath: /config
      volumes:
        - name: config
          configMap:
            name: minikube-sample
</code></pre>

<p>I used @ConfigurationProperties to reload properties.</p>

<p><strong>Dependencies</strong></p>

<pre><code> &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
            &lt;artifactId&gt;spring-cloud-starter-kubernetes&lt;/artifactId&gt;
            &lt;version&gt;1.1.0.RELEASE&lt;/version&gt;
        &lt;/dependency&gt;

        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
            &lt;artifactId&gt;spring-cloud-starter-kubernetes-config&lt;/artifactId&gt;
            &lt;version&gt;1.1.0.RELEASE&lt;/version&gt;
        &lt;/dependency&gt;
</code></pre>

<p><strong>What I did ?</strong>
I have gone through spring cloud documentation.  <strong>"The view role on the service account is required in order to listen for config map changes."</strong>
Then I created cluster view role through below command</p>

<pre><code>C:\Users\eresh.gorantla\apps\minikube-sample\src\main\fabric8 (master -&gt; origin)
λ kubectl create clusterrolebinding minikube-sample --clusterrole=view --serviceaccount=default:minikube --namespace=default
clusterrolebinding.rbac.authorization.k8s.io/minikube-sample created
</code></pre>

<p>But when I update the configmap in kubernetes, the properties are not reloaded on the fly.
I suspect something wrong in clusterrolebinding. 
Please provide your thoughts. Any help is appreciated. </p>

<p>To access ConfigMaps and get Refresh events:</p>
<ol>
<li><p>see annotations on config properties class
<code>@Configuration(proxyBeanMethods = false)</code>
see also <code>@RefreshScope</code> on config properties class.</p>
<pre><code>@Configuration(proxyBeanMethods = false)
@ConfigurationProperties(prefix = &quot;bean&quot;)
@RefreshScope
public class ClientConfig {

 private String message = &quot;Default Message from java code - to be overwritten from config&quot;;

 public String getMessage() {...
 public void setMessage(String message) {...
}
</code></pre>
</li>
</ol>
<p>2 Add permissions to access ConfigMaps</p>
<pre><code>kubectl create -f perm.yaml -n &lt;NAMESPACE&gt;
</code></pre>
<p>where perm.yaml is:</p>
<pre><code>  kind: Role
  apiVersion: rbac.authorization.k8s.io/v1
  metadata:
    namespace: yldbg
    name: namespace-reader
  rules:
    - apiGroups: [&quot;&quot;, &quot;extensions&quot;, &quot;apps&quot;]
      resources: [&quot;configmaps&quot;, &quot;pods&quot;, &quot;services&quot;, &quot;endpoints&quot;, &quot;secrets&quot;]
      verbs: [&quot;get&quot;, &quot;list&quot;, &quot;watch&quot;]
  ---
  kind: RoleBinding
  apiVersion: rbac.authorization.k8s.io/v1
  metadata:
    name: namespace-reader-binding
    namespace: yldbg
  subjects:
  - kind: ServiceAccount
    name: default
    apiGroup: &quot;&quot;
  roleRef:
    kind: Role
    name: namespace-reader
    apiGroup: &quot;&quot;
</code></pre>
<ul>
<li><p>After creating permissions, deploy pods and services.</p>
</li>
<li><p>when modifying the config map, you will see a refresh event in pod logs</p>
<pre><code>EventBasedConfigurationChangeDetector - Detected change in config maps
EventBasedConfigurationChangeDetector - Reloading using strategy: REFRESH
PropertySourceBootstrapConfiguration - Located property source: [BootstrapPropertySource {name='bootstrapProperties-configmap.client-svc.myns'}]
SpringApplication - The following profiles are active: kubernetes
</code></pre>
</li>
</ul>
<p>by yl</p>
