Kubernetes: O caminho de montagem do arquivo configmap resulta em um erro de comando não encontrado

Criado em 23 abr. 2017  ·  10Comentários  ·  Fonte: kubernetes/kubernetes

É um pedido de ajuda? (Em caso afirmativo, você deve usar nosso guia de solução de problemas e canais de suporte da comunidade, consulte http://kubernetes.io/docs/trou troubleshooting/.): Não

Quais palavras-chave você pesquisou nos problemas do Kubernetes antes de preencher este? (Se você encontrou alguma duplicata, você deve responder lá.): Command not found configmap kubernetes


Este é um RELATÓRIO DE BUGS ou PEDIDO DE RECURSO? (escolha um): BUG

Versão do Kubernetes (use kubectl version ):
Versão do cliente: v1.6.1 GitCommit: "b0b7a323cc5a4a2019b2e9520c21c7830b7f708e"
Versão do servidor: v1.6.0 GitCommit: "fff5156092b56e6bd60fff75aad4dc9de6b6ef37

Meio Ambiente :

  • Provedor de nuvem ou configuração de hardware :
  • SO (por exemplo, de / etc / os-release): host é ubuntu 16.04
  • Kernel (por exemplo, uname -a ): o host é Linux dev1 4.4.0-72-generic # 93-Ubuntu SMP Sex. 31 de março 14:07:41 UTC 2017 x86_64 x86_64 x86_64 GNU / Linux
  • Ferramentas de instalação :
  • Outros : Executando de dentro da versão do minikube: v0.18.0

O que aconteceu :
Quando tento criar uma implantação com um arquivo configmap montado no mesmo diretório do ponto de entrada, o contêiner falha ao iniciar com o seguinte erro
"Resposta de erro do daemon: Comando do recipiente '/app/app.sh' não encontrado ou não existe."
A especificação do pod inclui um configmap que é montado no mesmo diretório que o ponto de entrada

Parece que o script do ponto de entrada foi perdido após montar o volume para o mapa de configuração no mesmo diretório
Se eu montar o arquivo configmap em um subdiretório, tudo funcionará conforme o esperado

O que você esperava que acontecesse :
Eu esperava que o arquivo de mapa de configuração fosse criado no diretório sem afetar o conteúdo do diretório existente, que neste caso contém um script de ponto de entrada

Como reproduzi-lo (o mais mínimo e precisamente possível):

Arquivo Docker - observe o ponto de entrada

FROM busybox:latest

RUN        mkdir /app
COPY       app.sh /app

ENTRYPOINT ["/app/app.sh"]

Script de ponto de entrada - loop infinito

#!/bin/sh
seq=1
while [[ true ]]; do
    echo "${seq} $(date) working"
    sleep .5s   
    let seq=$((seq + 1))
done

k8s configmap e arquivo de implantação

apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    product: k8s-demo
  name: demo
data:
  settings.json: |
    {
      "store": {
        "type": "InMemory",
    }

---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  labels:
    product: k8s-demo
  name: demo
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: demo
        product: k8s-demo
    spec:
      containers:
      - name: demo
        image: pmcgrath/shellloop:1
        imagePullPolicy: Always
        volumeMounts:
          - name: demo-config
            mountPath: /app
      volumes:
        - name: demo-config
          configMap:
            name: demo
            items:
              - key: settings.json
                path: settings.json 

Quando executo o kubectl apply -d k8s.yaml e vejo o pod, vejo o seguinte erro

erro rpc: code = 2 desc = falhou ao iniciar o contêiner "f9e0112c80ebba568d4b508f99ffb053bf1ae5a4f095ce7f45bff5f38900b617": Resposta de erro do daemon: Comando do contêiner '/app/app.sh' não encontrado ou não existe.

Mais alguma coisa que precisamos saber :
Se eu mudar o mountPath do volume para qualquer outro diretório, ele funcionará conforme o esperado

Eu testei isso diretamente com docker no meu host (17.03.0-ce) e funcionou conforme o esperado

touch settings.json
docker container run -ti -v $(pwd)/settings.json:/app/settings.json pmcgrath/shellloop:1

Comentários muito úteis

@pmcgrath

Verifique aqui .

parece que entendo seu problema. Eu tenho a mesma pergunta antes, mas há uma resposta na sua situação.

Para resumir seu caso, você tem um configmap ( settings.json: blahblah ) e deseja montar em uma pasta /app . Então, abaixo está o que você precisa saber:

  1. Depois de montar um volume (não importa se é configmap ou outro), ele substitui o mountPath , portanto, no seu caso, a pasta /app conterá apenas settings.json .
  2. Eu sei que não é o que você esperava, então você tem que especificar mountPath: /app/settings.json , só assim, o conteúdo original nas pastas /app não será afetado.
  3. bem, quando você faz a segunda etapa, lembra que o configmap é na verdade uma lista de pares de valores-chave, você só precisa de uma das chaves (embora na verdade também tenha apenas uma), então você precisa dizer aos montes de volume para use um subcaminho do seu configmap.

Isso é algo que você obterá eventualmente:

containers:
- volumeMounts:
  - name: demo-config
    mountPath: /app/settings.json
    subPath: settings.json
volumes:
- name: demo-config
  configMap:
    name: demo

Todos 10 comentários

@pmcgrath

Verifique aqui .

parece que entendo seu problema. Eu tenho a mesma pergunta antes, mas há uma resposta na sua situação.

Para resumir seu caso, você tem um configmap ( settings.json: blahblah ) e deseja montar em uma pasta /app . Então, abaixo está o que você precisa saber:

  1. Depois de montar um volume (não importa se é configmap ou outro), ele substitui o mountPath , portanto, no seu caso, a pasta /app conterá apenas settings.json .
  2. Eu sei que não é o que você esperava, então você tem que especificar mountPath: /app/settings.json , só assim, o conteúdo original nas pastas /app não será afetado.
  3. bem, quando você faz a segunda etapa, lembra que o configmap é na verdade uma lista de pares de valores-chave, você só precisa de uma das chaves (embora na verdade também tenha apenas uma), então você precisa dizer aos montes de volume para use um subcaminho do seu configmap.

Isso é algo que você obterá eventualmente:

containers:
- volumeMounts:
  - name: demo-config
    mountPath: /app/settings.json
    subPath: settings.json
volumes:
- name: demo-config
  configMap:
    name: demo

@ zhouhaibing089
Obrigado pela resposta, funciona com base na sua sugestão, agradeço a explicação

Estou feliz por encerrar este problema
Pat

Para referência, a menção original desta solução parece estar aqui: https://github.com/kubernetes/kubernetes/issues/23748#issuecomment -230390309

Parece que a documentação para isso está faltando, o que torna este caso bastante confuso / enganoso, e os documentos de projeção também parecem torná-lo mais enganoso - não tenho certeza se está faltando porque as atualizações automáticas aparentemente não funcionam para esse problema

O requisito para que o nome do arquivo seja especificado em mountPath e subPath é contra-intuitivo.

A solução fornecida por @ zhouhaibing089 funciona, mas o conteúdo do arquivo montado em subPath não atualiza se o editarmos no ConfigMap semelhante.

IMO, isso não está _realmente_ resolvido. Deve haver uma opção para anexar cada chave em vez de sobrescrever.

Algo como:

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-conf
data:
  example1.conf: |
    server {
      server_name example1.com;
      # config here...
    }
  example2.conf: |
    server {
      server_name example2.com;
      # config here...
    }

De modo a...

- name: nginx-conf
  mountPath: /etc/nginx/conf.d
  append: true

... mantém o default.conf e quaisquer outros artefatos da imagem Docker, mas aumenta com example*.conf

Repetir a mesma informação no subPath é apenas _icky_.

+1 na opção append: true @leebenson .

De acordo com a resposta de @leebenson : alguém pode explicar de onde vem append: true option ??

não funciona para mim, eu tenho:

error: error validating "hdfs/21-namenode-statefulset.yaml": error validating data: ValidationError(StatefulSet.spec.template.spec.containers[1].volumeMounts[1]): unknown field "append" in io.k8s.api.core.v1.VolumeMount; if you choose to ignore these errors, turn validation off with --validate=false

Além disso, não está presente na documentação da API para montagem de volume:
https://k8smeetup.github.io/docs/api-reference/v1.9/#volumemount -v1-core

De acordo com a resposta de @leebenson : alguém pode explicar de onde vem append: true option ??

não funciona para mim, eu tenho:

error: error validating "hdfs/21-namenode-statefulset.yaml": error validating data: ValidationError(StatefulSet.spec.template.spec.containers[1].volumeMounts[1]): unknown field "append" in io.k8s.api.core.v1.VolumeMount; if you choose to ignore these errors, turn validation off with --validate=false

Além disso, não está presente na documentação da API para montagem de volume:
https://k8smeetup.github.io/docs/api-reference/v1.9/#volumemount -v1-core

não existe, é uma sugestão. um bom para o caso de uso.

Tentei usar este método, mas recebi um erro de sistema de arquivos somente leitura, quando apliquei o statefulset. Alguém sabe como consertar aquilo?
(Estou substituindo um arquivo existente, que contém configurações para elasticsearch, mensagem de erro real -> /usr/share/elasticsearch/bin/run.sh: line 28: ./config/elasticsearch.yml: Read-only file system )

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

arun-gupta picture arun-gupta  ·  3Comentários

broady picture broady  ·  3Comentários

jadhavnitind picture jadhavnitind  ·  3Comentários

ttripp picture ttripp  ·  3Comentários

sjenning picture sjenning  ·  3Comentários