开发web项目的时候,咱们通常会有多个环境(dev,beta,rc,production),而后每次使用maven打包的时候都要指定profilehtml
mven clean package -P beta
复制代码
这样就能够将application-{profile}.properties打入jar包中。这也就意味着对于不一样的环境咱们要打不一样的包,虽然他们只有一些配置信息不一样而已。java
那么有没有办法在不一样的环境中使用相同的应用程序代码呢? 固然有,springboot提供了这样的机会,它容许咱们经过不少种方式来决定配置文件是哪个,固然啦本篇文章并非介绍有哪些加载外部配置文件的方式。web
就好比祸水三千,我只取一瓢。因此此次咱们直接指定property文件的位置便可spring
java -jar myproject.jar --spring.config.location=classpath:/default.properties,/myconfig/application.properties
复制代码
道理是这么个道理,可是如今大多的项目都是部署在k8s上的,那么应该如何作呢?docker
这里我借助了k8s configMap来实现加载外部配置文件达到咱们的目的。apache
首先这里生成了configMapapi
kubectl create configmap application-configmap --from-file=application.properties=../smcp-web/src/main/resources/application-beta.properties -o yaml -n smcp| kubectl replace -f -
复制代码
解释下上面命令的意思,每一次在打包镜像以后,都会从新生成configMap,生成的application-configmap中,key=application.properties,value则是项目中application-beta.properties的内容springboot
生成configmap有不少种方式,能够根据本身的需求来生成,能够查看官方文档 kubernetes.io/docs/tasks/… -n 的意思是指定namespace,若是你使用的是默认的namespace,那么能够不用指定。 -n == --namespacebash
咱们生成的上面的configMap能够经过kubectl get configmap application-configmap -o yaml -n smcp
查看app
apiVersion: v1
data:
application.properties: | logging.level.com.project.smcp=INFO logging.level.org.apache.shiro=INFO logging.level.okhttp3.OkHttpClient=ERROR kind: ConfigMap
metadata:
creationTimestamp: 2019-10-24T11:41:57Z
name: application-configmap
namespace: smcp
resourceVersion: "62755048"
uid: 48c8ab36-f653-11e9-9eab-fa163fea9021
复制代码
能够看到实际上是将application-beta.properties文件中的内容所有拷贝到了data中,而后这些全部值的key为application.properties.再来看看在咱们deployment.yml文件中如何使用
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
复制代码
通过上面的配置,如今application.properties文件就处于/smcp-config下了。看到这里可能会有人有疑问,为何个人configMap要单独用命令生成,而不是在demployment.yaml文件中单独声明configMap类型的配置呢? 其实也是能够的,可是若是这样作你每次添加了环境变量你都要去demployment.yml中添加配置,你这样可能就要配置两次(application-{profile}.properties中还要配置一次),因此我就干脆用命令生成,在开发的时候不要考虑k8s的存在。
还要注意上面的args参数,经过它咱们指定了外部环境变量的路径。而对于生成镜像的dockerfile,其实也很简单
FROM java:8
EXPOSE 9090
ADD target/smcp-web.jar /smcp-web.jar
ENTRYPOINT ["java", "-jar","/smcp-web.jar"]
复制代码
最后当咱们执行了下面的命令以后,就能够部署咱们的容器到k8s中了
kubectl apply -f deployment.yml
复制代码
最后部署后,进入Pod中,能够看到目录结构以下
smcp-web.jar
smcp-config
-- application.properties
复制代码
而启动命令也变成了下面这样,能够经过ps -ef
查看
java -jar /smcp-web.jar --spring.config.location=/smcp-config/application.properties
复制代码
上面使用configMap的方式处理,固然还能够直接在环境变量中使用configMap(参考上面secretRef的方式),当使用环境变量的方式注入configMap的时候,你须要使用下面这样的命令生成数据。
kubectl create configmap application-configmap --fron-env-file=src/main/resources/application-beta.properties
复制代码
同时yaml文件中关于configMap的修改为下面这样,使用环境变量的方式记得把volumes去掉。
envFrom:
- configMapRef:
name: application-configmap
复制代码
可是使用环境变量注入的方式有一点须要注意,当你更新了configMap而不从新部署的时候,容器中的变量是不会更新的,而若是使用mountPath的方式,环境变量的值就会更新(大概10s左右)。
若是你还使用mountPath的同时还使用了subpath一样不会更新