【问题标题】:Kubernetes pplication run error when using env from ConfigMaps使用 ConfigMaps 中的 env 时 Kubernetes 应用程序运行错误
【发布时间】:2020-08-22 18:15:52
【问题描述】:

我有一个用 Go 编写的应用程序,它从 config.toml 文件中读取环境变量。 config.toml 文件包含的键值为

Server="mongodb://mongo-0.mongo,mongo-1.mongo,mongo-2.mongo"
Database="nrfdb"
NRFAddrPort = ":9090"

在我的应用程序中,我正在将 .toml 文件中的所有变量读取到我的应用程序中

// Represents database and server credentials
type Config struct {
    Server      string
    Database    string
    NRFAddrPort string
}

var NRFAddrPort string

// Read and parse the configuration file
func (c *Config) Read() {
    if _, err := toml.DecodeFile("config.toml", &c); err != nil {
        log.Print("Cannot parse .toml configuration file ")
    }
    NRFAddrPort = c.NRFAddrPort
}

我想在我的 Kubernetes 集群(3 个虚拟机、一个主节点和 2 个工作节点)中部署我的应用程序。创建一个 docker 并推送到 docker hub 后,当使用 configMaps 部署我的应用程序来解析变量时,我的应用程序运行了几秒钟,然后给出了错误。 似乎应用程序无法从 configMap 读取 env 变量。下面是我的 configMap 和 deployemnt。

apiVersion: v1
kind: ConfigMap
metadata:
  name: nrf-config
  namespace: default
data:
  config-toml: |
    Server="mongodb://mongo-0.mongo,mongo-1.mongo,mongo-2.mongo"
    Database="nrfdb"
    NRFAddrPort = ":9090"
apiVersion: apps/v1 
kind: Deployment
metadata:
  name: nrf-instance
spec:
  selector:
    matchLabels:
      app: nrf-instance
  replicas: 1 
  template:
    metadata:
      labels:
        app: nrf-instance
        version: "1.0"
    spec:
      nodeName: k8s-worker-node2
      containers:
      - name: nrf-instance
        image: grego/appapi:1.0.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9090
        volumeMounts:
        - name: config-volume
          mountPath: /home/ubuntu/appapi    
      volumes:
        - name: config-volume
          configMap:
            name: nrf-config

还有一件事我不明白是 volumeMounts 中的 mountPath。我需要将 config.toml 复制到这个 mountPath 吗? 当我在我的应用程序中对这些变量进行硬编码并在 kubernetes 中部署 docker 映像时,它可以正常运行。 我现在的问题是如何使用 kubernetes configMap 或任何方法将这些环境变量解析到我的应用程序,以便它可以在我的 Kubernetes 集群中运行,而不是在我的应用程序中硬编码它们。任何帮助。

另外附上我的 Dockerfile 内容

# Dockerfile References: https://docs.docker.com/engine/reference/builder/

# Start from the latest golang base image
FROM golang:latest as builder

# Set the Current Working Directory inside the container
WORKDIR /app

# Copy go mod and sum files
COPY go.mod go.sum ./

# Download all dependencies. Dependencies will be cached if the go.mod and go.sum files are not changed
RUN go mod download

# Copy the source from the current directory to the Working Directory inside the container
COPY . .

# Build the Go app
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

######## Start a new stage from scratch #######
FROM alpine:latest

RUN apk --no-cache add ca-certificates

WORKDIR /root/

# Copy the Pre-built binary file from the previous stage
COPY --from=builder /app/main .

# Expose port 9090 to the outside world
EXPOSE 9090

# Command to run the executable
CMD ["./main"]

内容有什么问题吗?

将值作为 env 值传递为

apiVersion: apps/v1 
kind: Deployment
metadata:
  name: nrf-instance
spec:
  selector:
    matchLabels:
      app: nrf-instance
  replicas: 1 
  template:
    metadata:
      labels:
        app: nrf-instance
        version: "1.0"
    spec:
      nodeName: k8s-worker-node2
      containers:
      - name: nrf-instance
        image: grego/appapi:1.0.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9090
        env:
          - name: Server
            valueFrom:
              configMapKeyRef:
                name: nrf-config
                key: config-toml
          - name: Database
            valueFrom:
              configMapKeyRef:
                name: nrf-config
                key: config-toml
          - name: NRFAddrPort
            valueFrom:
              configMapKeyRef:
                name: nrf-config
                key: config-toml

【问题讨论】:

标签: go kubernetes


【解决方案1】:

您当前拥有的内容将为您的配置映射中的每个键在挂载点创建一个文件。您的代码正在寻找“config.toml”,但关键是“config-toml”,所以它没有找到。

如果您希望保持密钥原样,您可以控制将哪些密钥写入何处(在挂载内),如下所示:

volumes:
  - name: config-volume
    configMap:
       name: nrf-config
       items:
          - key: config-toml
            path: config.toml

【讨论】:

  • 在添加 volumes.configMap.items 和 CrashLoopBackOff 后仍然出现相同的错误。关于 mountPath,它是一个将在容器内创建的挂载路径,我需要将 config.toml 文件复制到 Dockerfile 中?
  • 我已经添加了我的 Dockerfile 的内容。内容有问题吗?
【解决方案2】:

您不能将这些值作为单独的环境变量传递,因为它们被读取为一个文本 blob,而不是单独的 key:values。当前的 configmap 如下所示:

Data
====
config.toml:
----
Server="mongodb://mongo-0.mongo,mongo-1.mongo,mongo-2.mongo"
Database="nrfdb"
NRFAddrPort = ":9090"

要将其作为环境变量传递,您必须修改configmap 以将这些值读取为key: value pair

kind: ConfigMap 
apiVersion: v1 
metadata:
  name: example-configmap
data:
  Server: mongodb://mongo-0.mongo,mongo-1.mongo,mongo-2.mongo
  Database: nrfdb
  NRFAddrPort: :9090

这样,这些值将被分隔并可以作为环境变量传递:

Data
====
Database:
----
nrfdb
NRFAddrPort:
----
:9090
Server:
----
mongodb://mongo-0.mongo,mongo-1.mongo,mongo-2.mongo

当你将它传递给 pod 时:

[...]   
 spec:    
      containers:
      - name: nrf-instance
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9090
        envFrom:
        - configMapRef:
            name: example-configmap

您可以看到它被正确传递了,例如通过在 pod 内执行env 命令:

kubectl exec -it env-6fb4b557d7-zw84w -- env
NRFAddrPort=:9090
Server=mongodb://mongo-0.mongo,mongo-1.mongo,mongo-2.mongo
Database=nrfdb

值作为单独的环境变量读取,例如Server值:

kubectl exec -it env-6fb4b557d7-zw84w -- printenv Server
mongodb://mongo-0.mongo,mongo-1.mongo,mongo-2.mongo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-27
    • 1970-01-01
    • 1970-01-01
    • 2016-05-18
    • 2014-01-18
    • 1970-01-01
    相关资源
    最近更新 更多