When developing web projects, we typically have multiple environments (dev, Beta, RC,production) and then specify profiles each time we use Maven to package

mven clean package -P beta
Copy the code

This will put application-{profile}.properties into the JAR package. This means different packages for different environments, even though they have different configuration information.

Is there a way to use the same application code in different environments? Of course, SpringBoot provides the opportunity to decide which configuration file to load in a number of ways, although this article is not about how to load external configuration files.

It’s like I only take one scoop. So this time we just specify the location of the property file

java -jar myproject.jar --spring.config.location=classpath:/default.properties,/myconfig/application.properties
Copy the code

That’s true, but most projects are now deployed on the K8S, so what should be done?

Here I use K8S configMap to load external configuration files for our purposes.

First, configMap is generated here

kubectl create configmap application-configmap --from-file=application.properties=.. /smcp-web/src/main/resources/application-beta.properties -o yaml -n smcp| kubectl replace-f -
Copy the code

The application-ConfigMap is generated every time after the image is packed. Key = application. The properties, the value is in the project application – beta. The properties of the content

There are many ways to generate configmap, can be generated according to their own needs, you can view the official document kubernetes. IO/docs/tasks /… -n specifies the namespace. If you use the default namespace, you do not need to specify the namespace. -n == –namespace

The configMap we generated above can be viewed by using kubectl get configMap application- configMap -o yaml -n SMCP

apiVersion: v1
data:
  application.properties: | logging.level.com.project.smcp=INFO logging.level.org.apache.shiro=INFO logging.level.okhttp3.OkHttpClient=ERRORkind: ConfigMap
metadata:
  creationTimestamp: 2019- 10- 24T11:41:57Z
  name: application-configmap
  namespace: smcp
  resourceVersion: "62755048"
  uid: 48c8ab36-f653-11e9-9eab-fa163fea9021

Copy the code

You can see that you have copied the contents of the application-beta.properties file into data, and then the key of all these values is application.properties. What about in our deployment.yml file

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: smcp-service
  namespace: smcp
spec:
  selector:
    matchLabels:
      app: smcp-service
  replicas: 1
  template:
    metadata:
      labels:
        app: smcp-service
    spec:
      containers:
      - name: smcp-service
        image: docker-registry.xxx.com/xxx/smcp-web:latest
        args: ["--spring.config.location=/smcp-config/application.properties"]
        ports:
        - containerPort: 9000
        volumeMounts:
        - name: application-config
          mountPath: smcp-config
        envFrom:
        - secretRef:
            name: my-secret
      volumes:
      - name: application-config
        configMap:
          name: application-configmap
          items:
            - key: application.properties
              path: application.properties
---
apiVersion: v1
kind: Service
metadata:
  name: smcp-service
  namespace: smcp
  labels:
    app: smcp-service
spec:
  ports:
  - targetPort: 9000
    port: 9000
    protocol: TCP
  selector:
    app: smcp-service
  type: NodePort
Copy the code

With the above configuration, the application.properties file is now under /smcp-config. Some may wonder why MY configMap can be generated using separate commands, rather than declaring configMap type configurations separately in the demployment. Yaml file. This can work, however, if you can add configurations in demployment. Yml for each time you add environment variables, you could have to configure it twice (application-{profile}.properties), so I can use the command generation, Do not consider the existence of K8S during development.

Also notice the args parameter above, by which we specify the path to the external environment variable. For a dockerfile that generates an image, it’s actually quite simple

FROM java:8
EXPOSE 9090
ADD target/smcp-web.jar /smcp-web.jar
ENTRYPOINT ["java"."-jar"."/smcp-web.jar"]
Copy the code

Finally, when we execute the following command, we can deploy our container to K8S

kubectl apply -f deployment.yml
Copy the code

After the final deployment, when you enter the Pod, you can see the following directory structure

smcp-web.jar
smcp-config
  -- application.properties
Copy the code

The startup command also becomes the following, which can be viewed through ps -ef

java -jar /smcp-web.jar --spring.config.location=/smcp-config/application.properties
Copy the code

You can also use configMap directly in environment variables (see secretRef above). When injecting configMap using environment variables, you need to generate data using commands like the following.

kubectl create configmap application-configmap --fron-env-file=src/main/resources/application-beta.properties
Copy the code

Add the following volumes to the yamL file for configMap. Use environment variables to delete volumes.

envFrom:
- configMapRef:
  name: application-configmap
Copy the code

One thing to note about using environment variable injection is that when you update the configMap without redeploying, the variables in the container are not updated, whereas if you use mountPath, the values of the environment variables are updated (about 10 seconds).

If you use mountPath and subpath at the same time, it will not be updated