kubernetes集群中如何正确配置环境?
How to properly configure the environment in kubernetes cluster?
我有一个 spring 启动应用程序,它有两个配置文件,dev 和 prod,我的 docker 文件是:
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG DEPENDENCY=target/dependency
COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY ${DEPENDENCY}/META-INF /app/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-Dspring.profiles.active=dev","-cp","app:app/lib/*","com.my.Application"]
请注意,在构建图像时,我将入口点指定为命令行参数。
这是我使用此映像的 kubernetes 部署的容器部分:
containers:
- name: myapp
image: myregistry.azurecr.io/myapp:0.1.7
imagePullPolicy: "Always"
ports:
- containerPort: 8080
name: myapp
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
timeoutSeconds: 3
periodSeconds: 20
failureThreshold: 3
可以用但是有一个很大的缺陷:我现在如何在不重建镜像的情况下切换到生产环境?
最好是在我的 docker 文件中删除那个 ENTRYPOINT 并在我的 kubernetes yml 中提供这个配置,这样我就可以始终使用相同的图像...这可能吗?
编辑:我看到有一个生命周期指令,但请注意我有一个基于 spring 引导执行器的就绪探测器。如果我使用这个构造,它总是会失败。
您可以使用 Kubernetes Pod 规范的 command
属性 覆盖图像的 ENTRYPOINT
。同样,您可以使用 args
属性(另请参阅 the documentation)覆盖 CMD
:
containers:
- name: myapp
image: myregistry.azurecr.io/myapp:0.1.7
imagePullPolicy: "Always"
command: ["java","-Dspring.profiles.active=prod","-cp","app:app/lib/*","com.my.Application"]
ports:
- containerPort: 8080
name: myapp
或者,为了提供更高级别的抽象,您可以编写自己的入口点脚本,从环境变量中读取应用程序配置文件:
#!/bin/sh
PROFILE="${APPLICATION_CONTEXT:-dev}"
exec java "-Dspring.profiles.active=$PROFILE" -cp app:app/lib/* com.my.Application
然后,您可以简单地将环境变量传递到您的 pod 中:
containers:
- name: myapp
image: myregistry.azurecr.io/myapp:0.1.7
imagePullPolicy: "Always"
env:
- name: APPLICATION_CONTEXT
value: prod
ports:
- containerPort: 8080
name: myapp
而不是将 spring.profiles.active
放在入口点的 dockerfile 中。
利用configmaps and application.properties.
您在 dockerfile 中的 ENTRYPOINT 应如下所示:
ENTRYPOINT ["java","-cp","app:app/lib/*","com.my.Application","--spring.config.additional-location=/config/application-dev.properties"]
为您的 springboot 应用程序创建一个充当 application.properties 的配置映射
---
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
namespace: flow
data:
application-dev.properties: |
spring.application.name=myapp
server.port=8080
spring.profiles.active=dev
注意:这里我们指定了spring.profiles.active.
在我的 kubernetes 部署的容器部分中,将 configmap 安装在容器内,它将充当 application.properties。
containers:
- name: myapp
image: myregistry.azurecr.io/myapp:0.1.7
imagePullPolicy: "Always"
command: ["java","-cp","app:app/lib/*","com.my.Application","--spring.config.additional-location=/config/application-dev.properties"]
ports:
- containerPort: 8080
name: myapp
volumeMounts:
- name: myapp-application-config
mountPath: "/config"
readOnly: true
volumes:
- name: myapp-application-config
configMap:
name: myapp-config
items:
- key: application-dev.properties
path: application-dev.properties
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
timeoutSeconds: 3
periodSeconds: 20
failureThreshold: 3
注意:--spring.config.additional-location
指向我们在配置映射中创建的 application.properties 的位置。
因此,使用 configmaps 和 application.properties 可以在不重建映像的情况下覆盖应用程序的任何配置。
如果您想添加新配置或更新现有配置的值,只需在 configmap 和 kubectl apply
中进行适当的更改。然后缩小和放大您的应用程序 pod,使新配置生效。
希望对您有所帮助。
有many many ways to set Spring configuration values. With some rules,可以使用普通的环境变量来指定个别的属性值。您可能会看到是否可以使用它来代替单独的 Spring 配置文件控制。
在这里使用环境变量有两个优点:这意味着您(或您的 DevOps 团队)可以更改 deploy-time 设置而无需重新编译应用程序;如果您使用像 Helm 这样的部署管理器,其中一些细节(例如主机名)本质上是不可预测的,这使您可以指定在部署时才能知道的值。
例如,假设您有一个 Redis 依赖项:
cache:
redis:
url: redis://localhost:6379/0
您可以在部署时通过设置
覆盖它
containers:
- name: myapp
env:
- name: CACHE_REDIS_URL
value: "redis://myapp-redis.default.svc.cluster.local:6379/0"
一种方法是使用 spring 云 Kubernetes,如此处所述
https://docs.spring.io/spring-cloud-kubernetes/docs/current/reference/html/index.html#configmap-propertysource
您可以在配置图中定义您的配置文件,如下所示
kind: ConfigMap
apiVersion: v1
metadata:
name: demo
data:
application.yml: |-
greeting:
message: Say Hello to the World
farewell:
message: Say Goodbye
---
spring:
profiles: development
greeting:
message: Say Hello to the Developers
farewell:
message: Say Goodbye to the Developers
---
spring:
profiles: production
greeting:
message: Say Hello to the Ops
然后可以通过在 Kubernetes 部署清单中传递环境变量来 select 所需的配置文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-name
labels:
app: deployment-name
spec:
replicas: 1
selector:
matchLabels:
app: deployment-name
template:
metadata:
labels:
app: deployment-name
spec:
containers:
- name: container-name
image: your-image
env:
- name: SPRING_PROFILES_ACTIVE
value: "development"
我有一个 spring 启动应用程序,它有两个配置文件,dev 和 prod,我的 docker 文件是:
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG DEPENDENCY=target/dependency
COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY ${DEPENDENCY}/META-INF /app/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-Dspring.profiles.active=dev","-cp","app:app/lib/*","com.my.Application"]
请注意,在构建图像时,我将入口点指定为命令行参数。
这是我使用此映像的 kubernetes 部署的容器部分:
containers:
- name: myapp
image: myregistry.azurecr.io/myapp:0.1.7
imagePullPolicy: "Always"
ports:
- containerPort: 8080
name: myapp
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
timeoutSeconds: 3
periodSeconds: 20
failureThreshold: 3
可以用但是有一个很大的缺陷:我现在如何在不重建镜像的情况下切换到生产环境?
最好是在我的 docker 文件中删除那个 ENTRYPOINT 并在我的 kubernetes yml 中提供这个配置,这样我就可以始终使用相同的图像...这可能吗?
编辑:我看到有一个生命周期指令,但请注意我有一个基于 spring 引导执行器的就绪探测器。如果我使用这个构造,它总是会失败。
您可以使用 Kubernetes Pod 规范的 command
属性 覆盖图像的 ENTRYPOINT
。同样,您可以使用 args
属性(另请参阅 the documentation)覆盖 CMD
:
containers:
- name: myapp
image: myregistry.azurecr.io/myapp:0.1.7
imagePullPolicy: "Always"
command: ["java","-Dspring.profiles.active=prod","-cp","app:app/lib/*","com.my.Application"]
ports:
- containerPort: 8080
name: myapp
或者,为了提供更高级别的抽象,您可以编写自己的入口点脚本,从环境变量中读取应用程序配置文件:
#!/bin/sh
PROFILE="${APPLICATION_CONTEXT:-dev}"
exec java "-Dspring.profiles.active=$PROFILE" -cp app:app/lib/* com.my.Application
然后,您可以简单地将环境变量传递到您的 pod 中:
containers:
- name: myapp
image: myregistry.azurecr.io/myapp:0.1.7
imagePullPolicy: "Always"
env:
- name: APPLICATION_CONTEXT
value: prod
ports:
- containerPort: 8080
name: myapp
而不是将 spring.profiles.active
放在入口点的 dockerfile 中。
利用configmaps and application.properties.
您在 dockerfile 中的 ENTRYPOINT 应如下所示:
ENTRYPOINT ["java","-cp","app:app/lib/*","com.my.Application","--spring.config.additional-location=/config/application-dev.properties"]
为您的 springboot 应用程序创建一个充当 application.properties 的配置映射
---
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
namespace: flow
data:
application-dev.properties: |
spring.application.name=myapp
server.port=8080
spring.profiles.active=dev
注意:这里我们指定了spring.profiles.active.
在我的 kubernetes 部署的容器部分中,将 configmap 安装在容器内,它将充当 application.properties。
containers:
- name: myapp
image: myregistry.azurecr.io/myapp:0.1.7
imagePullPolicy: "Always"
command: ["java","-cp","app:app/lib/*","com.my.Application","--spring.config.additional-location=/config/application-dev.properties"]
ports:
- containerPort: 8080
name: myapp
volumeMounts:
- name: myapp-application-config
mountPath: "/config"
readOnly: true
volumes:
- name: myapp-application-config
configMap:
name: myapp-config
items:
- key: application-dev.properties
path: application-dev.properties
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
timeoutSeconds: 3
periodSeconds: 20
failureThreshold: 3
注意:--spring.config.additional-location
指向我们在配置映射中创建的 application.properties 的位置。
因此,使用 configmaps 和 application.properties 可以在不重建映像的情况下覆盖应用程序的任何配置。
如果您想添加新配置或更新现有配置的值,只需在 configmap 和 kubectl apply
中进行适当的更改。然后缩小和放大您的应用程序 pod,使新配置生效。
希望对您有所帮助。
有many many ways to set Spring configuration values. With some rules,可以使用普通的环境变量来指定个别的属性值。您可能会看到是否可以使用它来代替单独的 Spring 配置文件控制。
在这里使用环境变量有两个优点:这意味着您(或您的 DevOps 团队)可以更改 deploy-time 设置而无需重新编译应用程序;如果您使用像 Helm 这样的部署管理器,其中一些细节(例如主机名)本质上是不可预测的,这使您可以指定在部署时才能知道的值。
例如,假设您有一个 Redis 依赖项:
cache:
redis:
url: redis://localhost:6379/0
您可以在部署时通过设置
覆盖它containers:
- name: myapp
env:
- name: CACHE_REDIS_URL
value: "redis://myapp-redis.default.svc.cluster.local:6379/0"
一种方法是使用 spring 云 Kubernetes,如此处所述 https://docs.spring.io/spring-cloud-kubernetes/docs/current/reference/html/index.html#configmap-propertysource
您可以在配置图中定义您的配置文件,如下所示
kind: ConfigMap
apiVersion: v1
metadata:
name: demo
data:
application.yml: |-
greeting:
message: Say Hello to the World
farewell:
message: Say Goodbye
---
spring:
profiles: development
greeting:
message: Say Hello to the Developers
farewell:
message: Say Goodbye to the Developers
---
spring:
profiles: production
greeting:
message: Say Hello to the Ops
然后可以通过在 Kubernetes 部署清单中传递环境变量来 select 所需的配置文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-name
labels:
app: deployment-name
spec:
replicas: 1
selector:
matchLabels:
app: deployment-name
template:
metadata:
labels:
app: deployment-name
spec:
containers:
- name: container-name
image: your-image
env:
- name: SPRING_PROFILES_ACTIVE
value: "development"