Eu consigo executar o Ollama como um k8s STS. Estou usando-o para o aplicativo Python Langchain LLM/RAG. No entanto, o seguinte ENTRYPOINT
script Dockerfile que tenta puxar uma lista de imagens exportadas como MODELS
ENV do manifesto k8s STS encontra problemas. O Dockerfile tem o seguinte ENTRYPOINT
e CMD
:
ENTRYPOINT ["/usr/local/bin/run.sh"]
CMD ["bash"]
run.sh
:
#!/bin/bash
set -x
ollama serve&
sleep 10
models="${MODELS//,/ }"
for i in "${models[@]}"; do \
echo model: $i \
ollama pull $i \
done
Registros do k8s:
+ models=llama3.2
/usr/local/bin/run.sh: line 10: syntax error: unexpected end of file
Solução de David Maze:
lifecycle:
postStart:
exec:
command:
- bash
- -c
- |
for i in $(seq 10); do
ollama ps && break
sleep 1
done
for model in ${MODELS//,/ }; do
ollama pull "$model"
done
ollama-0 1/2 CrashLoopBackOff 4 (3s ago) 115s
ollama-1 1/2 CrashLoopBackOff 4 (1s ago) 115s
Warning FailedPostStartHook 106s (x3 over 2m14s) kubelet PostStartHook failed
$ k logs -fp ollama-0
Defaulted container "ollama" out of: ollama, fluentd
Error: unknown command "ollama" for "ollama"
Atualizar Dockerfile
:
ENTRYPOINT ["/bin/ollama"]
#CMD ["bash"]
CMD ["ollama", "serve"]
Preciso personalizar Dockerfile
para poder instalar o Nvidia Container Toolkit.
Em um nível mecânico, as barras invertidas dentro do
for
loop estão causando problemas. Isso faz com que o shell combine as linhas, então você obtém um único comandoecho model: $i ollama pull $i done
, mas não há umdone
comando independente para encerrar o loop.O próximo problema que você encontrará é que esse script de ponto de entrada é a única coisa que o contêiner executa, e quando esse script sai, o contêiner também sai. Não importa que você tenha iniciado o servidor Ollama em segundo plano. Se você quisesse executar o contêiner dessa forma, precisaria
wait
que o servidor saísse. Isso seria algo comoNo entanto, esse modelo de iniciar um processo em segundo plano e depois
wait
executar ing para ele geralmente não é a melhor abordagem. Se o Pod for desligado, por exemplo, o sinal de término irá para o script wrapper e não para o servidor Ollama, e você não conseguirá ter um desligamento limpo.Em um contexto do Kubernetes (você diz que está executando isso em um StatefulSet), um hook PostStart se encaixa aqui. Isso permitirá que você execute uma imagem não modificada, mas adicione seu próprio script que é executado quase ao mesmo tempo que a inicialização do contêiner. Em um manifesto do Kubernetes, isso pode parecer:
Esta configuração grava um script de shell inline no manifesto do Kubernetes. Ele o envolve
/bin/sh -c
para que possa ser executado dessa forma. Isso usa um mecanismo "exec", então o script é executado como um processo secundário no mesmo contêiner. O primeiro fragmento espera até 10 segundos para que o servidor esteja em execução, e o segundo é o loop para carregar os modelos.