如何在Kubernetes集群中正确配置环境?

时间:2019-07-21 09:24:23

标签: spring-boot docker kubernetes jib

我有一个带有两个配置文件dev和prod的spring boot应用程序,我的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中进行此配置,以便我可以始终使用同一映像...这可能吗?

edit:我看到有一个生命周期说明,但请注意,我有一个基于弹簧保护套执行器的就绪探测器。如果我使用此构造,它将总是失败。

4 个答案:

答案 0 :(得分:2)

您可以使用Kubernetes Pod规范的ENTRYPOINT属性覆盖图像的command。同样,您可以使用CMD属性来覆盖args(另请参见the documentation):

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

答案 1 :(得分:2)

而不是将spring.profiles.active放在入口点的dockerfile中。

使用configmapsapplication.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。然后缩小并扩大您的应用程序窗格,以使新配置生效。

希望这会有所帮助。

答案 2 :(得分:0)

many many ways可以设置Spring配置值。通过some rules,您可以使用普通的环境变量来指定各个属性值。您可能会看到是否可以使用它来代替单独的Spring配置文件控件。

在这里使用环境变量有两个好处:这意味着您(或您的DevOps团队)可以在不重新编译应用程序的情况下更改部署时间设置;并且如果您使用的是诸如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"

答案 3 :(得分:0)

一种方法是使用 spring cloud Kubernetes,如此处所述 https://docs.spring.io/spring-cloud-kubernetes/docs/current/reference/html/index.html#configmap-propertysource

您可以在如下所示的 configmap 中定义您的配置文件

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 部署清单中传递环境变量来选择所需的配置文件

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"