Як я можу тримати контейнер, що працює на Kubernetes?


124

Зараз я намагаюся запустити простий контейнер з оболонкою (/ bin / bash) на кластері Kubernetes.

Я подумав, що існує спосіб зберегти контейнер, який працює на контейнері Docker, використовуючи pseudo-ttyопцію і від'єднати ( -tdопція за docker runкомандою).

Наприклад,

$ sudo docker run -td ubuntu:latest

Чи є такий варіант у Kubernetes?

Я спробував запустити контейнер за допомогою kubectl run-containerкоманди типу:

kubectl run-container test_container ubuntu:latest --replicas=1

Але контейнер виходить на кілька секунд (подібно до запуску з docker runкомандою без параметрів, про які я згадував вище). І ReplicationController запускає його знову кілька разів.

Чи є спосіб зберегти контейнер, що працює на Kubernetes, як -tdпараметри в docker runкоманді?


Використання цього зображення (як підказує документ Kubernetes ) є досить зручним:kubectl run curl --image=radial/busyboxplus:curl -i --tty
Матей Сантана

Це питання було згадано в цьому відео: Kubernetes дуже важкий шлях в Datadog з слайд-назвою «Cargo culting З вікіпедії :. Термін культ карго програміст може застосовуватися , коли недосвідчений або програміст (або один недосвідчений з проблемою під рукою) копіює якийсь програмний код з одного місця в інше, майже не розуміючи, як він працює, чи потрібен він на новій посаді.
tgogos,

Відповіді:


49

Контейнер виходить, коли його основний процес закінчується. Робити щось на кшталт:

docker run -itd debian

тримати контейнер відкритим - це відверто хак, який слід використовувати лише для швидких тестів та прикладів. Якщо ви просто хочете контейнер для тестування на кілька хвилин, я би зробив:

docker run -d debian sleep 300

Що має ту перевагу, що контейнер автоматично вийде, якщо ви забудете про нього. Крім того, ви можете помістити щось подібне у whileцикл, щоб він постійно працював, або просто запустити такий додаток, як top. Все це має бути легко зробити в Кубернетах.

Справжнє питання - чому ви хочете це зробити? Ваш контейнер повинен надавати послугу, процес якої зберігатиме контейнер працювати у фоновому режимі.


Спасибі за вашу відповідь. Зараз я намагаюся зрозуміти поведінку контейнерів, коли десятки контейнерів працюють одночасно. Нескінченний цикл і використання іншої важкої команди заважають мені знати, яка поведінка контейнерів. Саме тому мені потрібен простий контейнер, наприклад, лише біг / бін / баш.
Springwell

Поки я спробую запустити catбез аргументів topі sleepз аргументом великої кількості.
Springwell

30
sleep infinityпрацює у багатьох випадках (не
зайнятий

1
Для цього є маса причин. Наприклад, ви можете розгорнути свої стручки з штурвальними випусками та ін'єкційною конфігурацією, що зробить відтворення подібних середовищ дратівливим і громіздким. Але наявність контейнера з такою конфігурацією у випадках, коли інші стручки виходять з ладу / видаляються, може бути нескінченно корисним.
Річард Левехерте

Тому що моя служба складається з декількох процесів.
Константин Ван

135

Контейнери призначені для запуску до завершення. Вам потрібно надати контейнеру завдання, яке ніколи не закінчиться. Щось подібне повинно працювати:

apiVersion: v1
kind: Pod
metadata:
  name: ubuntu
spec:
  containers:
  - name: ubuntu
    image: ubuntu:latest
    # Just spin & wait forever
    command: [ "/bin/bash", "-c", "--" ]
    args: [ "while true; do sleep 30; done;" ]

Але це найкраща практика?
aneesh joshi

3
@aneeshjoshi Я б не сказав, що це найкраща практика . Це лише приклад надання стручка, який працюватиме без негайного виходу. Найкраща практика - створити ваші контейнери для того, щоб виконати роботу, для якої вони були розроблені (робота, яка працює до завершення, веб-сервер, який працює постійно тощо). Я розмістив це як приклад, тому що Kubernetes може спочатку відчувати розчарування, коли ви продовжуєте створювати стручки лише для того, щоб зникнути, оскільки команда за замовчуванням негайно закінчується.
Джоель Б

@JoelB Дякую Мені було цікаво, який "правильний" спосіб це зробити.
aneesh joshi

1
дякую за це, оскільки мені потрібен контейнер, який може жити деякий час, що дозволяє мені ввести його. Я намагався зробити те ж саме з більш світлим зображенням, ніж ubuntuспробував bashзображення, але не міг змусити його працювати. Будь-яка ідея, як зробити так само, як це із bashзображенням?
cryanbhu

1
@cryanbhu Для більш світлого зображення ви можете використовувати альпійський, специфікація контейнера може мати такий вигляд: {"name": "util", "image": "alpine", "command": [ "/bin/sh", "-c", "--" ], "args": [ "while true; do sleep 30; done;" ]}(лише json, оскільки yaml не буде форматувати тут коментарі.) Важливий біт /bin/shзамість /bin/bash.
bschlueter

111

Ви можете використовувати цей CMD у своїх Dockerfile:

CMD exec /bin/bash -c "trap : TERM INT; sleep infinity & wait"

Це дозволить зберегти ваш контейнер живим, поки йому не скажуть зупинитися. Використання пастки та очікування змусить ваш контейнер негайно реагувати на запит про зупинку . Без пастки / очікування зупинка займе кілька секунд.

Для зображень на основі зайнятої скриньки (використовуваних на зображеннях на альпійській мові) сон не знає про аргумент нескінченності. Це вирішення дає вам таку ж негайну відповідь на docker stopподібну у наведеному вище прикладі:

CMD exec /bin/sh -c "trap : TERM INT; (while true; do sleep 1000; done) & wait"

Я використовую те ж саме для кубернетів розгортання yaml для налагодження
sdkks

це дає мені "сон: недійсне число 'нескінченність" "
arunkjn

@arunkjn Дякую за це. Ви, мабуть, застрягли в зображенні, яке використовує зайнятий ящик (наприклад, альпійські зображення). Дивіться оновлену відповідь.
itsafire

24
  1. У своєму Dockerfile використовуйте цю команду:

    CMD ["sh", "-c", "tail -f /dev/null"]
    
  2. Створіть своє зображення докера.

  3. Натисніть на кластер або подібне, щоб переконатися, що зображення доступне.
  4. kubectl run debug-container -it --image=<your-image>
    

Чудові поради щодо налагодження контейнера.
kta

16

Для того, щоб підтримувати ПДД ПД, слід виконувати певне завдання, інакше Kubernetes вважає його непотрібним, тому він виходить. Існує багато способів зберегти POD.

Я зіткнувся з подібними проблемами, коли мені потрібен був ПОД просто, щоб постійно працювати, не роблячи нічого. Нижче наведено два способи, які працювали для мене:

  1. Запуск команди сну під час запуску контейнера.
  2. Запуск нескінченної петлі всередині контейнера.

Хоча перший варіант простіший за другий і може вистачити вимоги, це не найкращий варіант. Так, існує обмеження на кількість секунд, які ви збираєтеся призначити в команді сну. Але контейнер з нескінченною петлею, що працює всередині нього, ніколи не виходить.

Однак я опишу обидва способи (враховуючи, що ви використовуєте контейнер зайнятих ящиків):

1. Команда сну

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  containers:
  - name: busybox
    image: busybox
    ports:
    - containerPort: 80
    command: ["/bin/sh", "-ec", "sleep 1000"]
  nodeSelector:
    beta.kubernetes.io/os: linux

2. Нескінченна петля

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  containers:
  - name: busybox
    image: busybox
    ports:
    - containerPort: 80
    command: ["/bin/sh", "-ec", "while :; do echo '.'; sleep 5 ; done"]
  nodeSelector:
    beta.kubernetes.io/os: linux

Виконайте таку команду, щоб запустити поділ:

kubectl apply -f <pod-yaml-file-name>.yaml

Сподіваюся, це допомагає!


Чи можу я запитати, що таке сон? Це команда внутрішня для Ubuntu? Або команда docker?
Фараз

@Faraz Це команда оболонки Linux, вона не специфічна для докера.
Арбааз

11

Мені вдалося зробити це для роботи з командою sleep infinityв Kubernetes, яка буде тримати контейнер відкритим. Дивіться цю відповідь щодо альтернатив, коли це не працює.


Це не дає відповіді на запитання. Щоб критикувати або вимагати роз'яснення у автора, залиште коментар під їх публікацією. - З огляду
Буде

1
@ Будемо впевнені, що це зробити. sleep infinityзберігає контейнер відкритим, забезпечуючи той самий тип функціональності, про який задається питання (для більшості типів контейнерів). Він також надає посилання на альтернативні випадки, коли ця конкретна команда не працює
rwilson04

Це було з огляду. Якщо ви додасте текст коментаря до відповіді, то це якісна відповідь :) Мій початковий прапор / похвала ґрунтувався на тому, що ваш коментар був невдалим, тому я думаю, що це повинен був бути коментарем. Додано швидке редагування та оновлено.
Буде чи

"... нескінченність сну в Кубернетах" - це неінформоване твердження. Це означає, що на знімку немає ні unix, ні докера.
ммла

10

Найпростіша команда, яка може бути для маніфесту k8s pod для запуску контейнера назавжди:

apiVersion: v1
kind: Pod
metadata:
  name: ubuntu
spec:
  containers:
  - name: ubuntu
    image: ubuntu:latest
    # Just sleep forever
    command: [ "sleep" ]
    args: [ "infinity" ]

5

Використовуйте цю команду всередині вашого Dockerfile, щоб контейнер працював у вашому кластері K8s:

  • ХМД хвіст -f / dev / null

3

У моєму випадку стручок із initContainer не вдалося ініціалізувати. Запуск, docker ps -aа потім docker logs exited-container-id-hereдав мені повідомлення журналу, яке kubectl logs podnameне відображалося. Таємниця вирішена :-)


1

Існує багато різних способів досягти цього, але один з найелегантніших :

kubectl run -i --tty --image ubuntu:latest ubuntu-test --restart=Never --rm /bin/sh

Чому ви вважаєте це найелегантнішим рішенням?
mordowiciel

1

Мої кілька центів на цю тему. Якщо припустити, що kubectlпрацює, то найближча команда, яка була б еквівалентна команді docker, про яку ви згадали у своєму запитанні, буде щось подібне.

$ kubectl run ubuntu --image=ubuntu --restart=Never --command sleep infinity

Вище команда створить сингл Podу defaultпросторі імен, і він виконає sleepкоманду з infinityаргументом - таким чином у вас буде процес, який працює в передньому плані, зберігаючи контейнер живим.

Післямови, з якими ви можете взаємодіяти, Podвиконавши kubectl execкоманду.

$ kubectl exec ubuntu -it -- bash

Цей прийом дуже корисний для створення ресурсу Pod та спеціальної налагодження.


1
Чудово працює. Не потрібно --restart=Never, просто зателефонуйтеkubectl run ubuntu --image=ubuntu -- sleep infinity
Ноам Манос
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.