Jak mogę utrzymać działający kontener na Kubernetes?

124

Teraz próbuję uruchomić prosty kontener z powłoką (/ bin / bash) w klastrze Kubernetes.

Pomyślałem, że istnieje sposób na utrzymanie kontenera działającego na kontenerze Dockera za pomocą pseudo-ttyopcji i odłączania ( -tdopcja na docker runpolecenie).

Na przykład,

$ sudo docker run -td ubuntu:latest

Czy jest taka opcja w Kubernetes?

Próbowałem uruchomić kontener za pomocą kubectl run-containerpolecenia takiego jak:

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

Ale kontener wychodzi na kilka sekund (podobnie jak uruchomienie docker runkomendą bez opcji, o których wspomniałem powyżej). ReplicationController uruchamia go ponownie wielokrotnie.

Czy istnieje sposób, aby kontener działał na Kubernetes, tak jak -tdopcje w docker runpoleceniu?

Springwell
źródło
Używanie tego obrazu (jak sugeruje dokumentacja Kubernetes ) jest całkiem przydatne:kubectl run curl --image=radial/busyboxplus:curl -i --tty
Matheus Santana,
To pytanie zostało wspomniane w tym filmie: Kubernetes bardzo trudna droga w Datadog z tytułem slajdu „Kultura Cargo . Z Wikipedii: Termin programista kultowego ładunku może odnosić się do niewykwalifikowanego lub początkującego programisty komputerowego (lub niedoświadczonego z problemem pod ręką) kopiuje kod programu z jednego miejsca do drugiego z niewielkim lub
zerowym

Odpowiedzi:

50

Kontener kończy pracę, gdy kończy się jego główny proces. Robię coś takiego:

docker run -itd debian

trzymanie kontenera otwarte to szczerze mówiąc hack, którego należy używać tylko do szybkich testów i przykładów. Jeśli potrzebujesz pojemnika do testowania przez kilka minut, zrobiłbym:

docker run -d debian sleep 300

Co ma tę zaletę, że pojemnik automatycznie wyjdzie, jeśli o nim zapomnisz. Alternatywnie możesz umieścić coś takiego w whilepętli, aby działało na zawsze, lub po prostu uruchomić aplikację, taką jak top. Wszystko to powinno być łatwe do zrobienia w Kubernetes.

Prawdziwe pytanie brzmi: dlaczego chcesz to zrobić? Twój kontener powinien zapewniać usługę, której proces będzie utrzymywał kontener działający w tle.

Adrian Mouat
źródło
Dziękuję za Twoją odpowiedź. Teraz próbuję zrozumieć zachowanie kontenerów, z których dziesiątki są uruchomione w tym samym czasie. Niekończąca się pętla i użycie innego ciężkiego polecenia uniemożliwiają mi poznanie zachowania kontenerów. To jest powód, dla którego potrzebuję prostego kontenera, takiego jak tylko uruchomiony / bin / bash.
Springwell
Na razie postaram bieg catbez argumentów i toporaz sleepz argumentem dużej liczbie.
Springwell
30
sleep infinitydziała w wielu przypadkach (nie busybox)
rwilson04
1
Jest wiele powodów, aby to zrobić. Na przykład możesz wdrożyć swoje kapsuły z wydaniami steru i wstrzykniętą konfiguracją, co spowoduje, że odtwarzanie podobnych środowisk będzie denerwujące i uciążliwe. Ale posiadanie kontenera z taką konfiguracją w przypadkach, gdy inne pody ulegną awarii / zostaną usunięte, może być nieskończenie przydatne.
Richard Løvehjerte
Ponieważ moja usługa składa się z wielu procesów.
Константин Ван
135

Kontenery mają biegać do końca. Musisz zapewnić swojemu kontenerowi zadanie, które nigdy się nie zakończy. Coś takiego powinno działać:

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;" ]
Joel B.
źródło
Ale czy to najlepsza praktyka?
aneesh joshi
3
@aneeshjoshi Nie powiedziałbym, że to najlepsza praktyka . To tylko przykład dostarczający kapsułę, która będzie działać bez natychmiastowego zamykania. Najlepszą praktyką jest tworzenie kontenerów do wykonywania zadań, do których zostały zaprojektowane (zadanie, które trwa do końca, serwer WWW działający bez przerwy itp.). Opublikowałem to jako przykład, ponieważ Kubernetes może początkowo być frustrujący, gdy tworzysz pody tylko po to, aby znikały, ponieważ domyślne polecenie natychmiast kończy się.
Joel B
@JoelB Thanks. Zastanawiałem się, jaki jest „właściwy” sposób na zrobienie tego.
aneesh joshi
1
dziękuję za to, bo potrzebuję kontenera, który może trochę żyć, pozwalając mi do niego wejść. Próbowałem zrobić to samo z jaśniejszym obrazem niż ubuntui wypróbowałem bashobraz, ale nie mogłem go uruchomić. Masz jakiś pomysł, jak zrobić to samo z bashobrazem?
cryanbhu
1
@cryanbhu Aby uzyskać lżejszy obraz, możesz użyć alpine, specyfikacja kontenera może wyglądać następująco: {"name": "util", "image": "alpine", "command": [ "/bin/sh", "-c", "--" ], "args": [ "while true; do sleep 30; done;" ]}(tylko json, ponieważ yaml nie zostanie sformatowany w komentarzach). Ważnym bitem jest /bin/shzamiast /bin/bash.
bschlueter
111

Możesz użyć tego CMD w Dockerfile:

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

Utrzyma to pojemnik przy życiu, dopóki nie zostanie nakazany, aby się zatrzymać. Użycie pułapki i czekania spowoduje, że kontener natychmiast zareaguje na żądanie zatrzymania . Bez pułapki / oczekiwania zatrzymanie zajmie kilka sekund.

W przypadku obrazów opartych na busybox (używanych w obrazach alpejskich) sen nie zna argumentu nieskończoności. To obejście daje taką samą natychmiastową odpowiedź na docker stoppodobne w powyższym przykładzie:

CMD exec /bin/sh -c "trap : TERM INT; (while true; do sleep 1000; done) & wait"
itsafire
źródło
Używam tego samego na yaml wdrożenia Kubernetes do celów debugowania
sdkks,
to daje mi „sen: nieprawidłowa liczba 'nieskończoność'”
arunkjn
@arunkjn Dzięki za to. Prawdopodobnie utknąłeś z obrazem, który używa busybox (jak obrazy alpejskie). Zobacz zaktualizowaną odpowiedź.
itsafire
25
  1. W swoim pliku Dockerfile użyj tego polecenia:

    CMD ["sh", "-c", "tail -f /dev/null"]
    
  2. Zbuduj swój obraz Dockera.

  3. Przenieś go do swojego klastra lub podobnego, aby upewnić się, że obraz jest dostępny.
  4. kubectl run debug-container -it --image=<your-image>
    
Radu Gabriel
źródło
Świetne wskazówki dotyczące debugowania kontenera.
kta
16

Aby POD działał, powinien wykonywać określone zadanie, w przeciwnym razie Kubernetes uzna go za niepotrzebny i dlatego się zatrzymuje. Istnieje wiele sposobów utrzymywania działania POD.

Napotkałem podobne problemy, gdy potrzebowałem POD-a tylko do ciągłego działania bez wykonywania żadnej użytecznej operacji. Oto dwa sposoby, w jakie to zadziałało:

  1. Uruchamianie komendy uśpienia podczas uruchamiania kontenera.
  2. Uruchomienie nieskończonej pętli wewnątrz kontenera.

Chociaż pierwsza opcja jest łatwiejsza niż druga i może wystarczyć, nie jest to najlepsza opcja. Ponieważ istnieje ograniczenie co do liczby sekund, które zamierzasz przypisać w poleceniu uśpienia. Ale kontener z nieskończoną pętlą biegnącą w środku nigdy nie jest zamykany.

Jednak opiszę oba sposoby (biorąc pod uwagę, że korzystasz z kontenera busybox):

1. Polecenie uśpienia

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. Nieskończona pętla

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

Uruchom następujące polecenie, aby uruchomić pod:

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

Mam nadzieję, że to pomoże!

Arbaaz
źródło
Mogę zapytać, co to jest sen? Czy jest to polecenie wewnętrzne Ubuntu? Albo polecenie docker?
Faraz
@Faraz To polecenie powłoki systemu Linux, nie jest specyficzne dla dockera.
Arbaaz
11

Udało mi się zmusić to do pracy za pomocą polecenia sleep infinityw Kubernetes, które utrzyma kontener otwarty. Zapoznaj się z tą odpowiedzią, aby poznać alternatywne rozwiązania, gdy to nie działa.

rwilson04
źródło
To nie daje odpowiedzi na pytanie. Aby skrytykować lub poprosić autora o wyjaśnienie, zostaw komentarz pod jego postem. - Z recenzji
będzie
1
@ Na pewno tak. sleep infinityutrzymuje kontener otwarty, zapewniając ten sam typ funkcjonalności, o jaki pyta pytanie (dla większości typów kontenerów). Zawiera również link do alternatyw dla przypadków, gdy to konkretne polecenie nie działa
rwilson04
To było z recenzji. Jeśli dodasz tam tekst komentarza do odpowiedzi, to jest to odpowiedź jakościowa :) Moja pierwsza flaga / pochwała polegała na tym, że twój komentarz nie był udany, co sprawiło, że pomyślałem, że to komentarz. Dodano szybką edycję i głosowano za.
Będzie
„... Sleep Infinity in Kubernetes” to niedoinformowane stwierdzenie. Oznacza to, że na obrazku nie ma unixa ani dockera.
mmla
11

Najprostsze polecenie, jakie może być dla manifestu pod K8s, aby uruchamiać kontener na zawsze:

apiVersion: v1
kind: Pod
metadata:
  name: ubuntu
spec:
  containers:
  - name: ubuntu
    image: ubuntu:latest
    # Just sleep forever
    command: [ "sleep" ]
    args: [ "infinity" ]
Włodek B.
źródło
5

Użyj tego polecenia wewnątrz pliku Dockerfile, aby utrzymać działanie kontenera w klastrze K8s:

  • Ogon CMD -f / dev / null
Omar Khaled
źródło
3

W moim przypadku inicjalizacja poda z initContainer nie powiodła się. Uruchomiony, docker ps -aa następnie docker logs exited-container-id-heredał mi komunikat dziennika, który kubectl logs podnamenie został wyświetlony. Zagadka rozwiązana :-)

Stefan L.
źródło
1

Można to osiągnąć na wiele różnych sposobów, ale jednym z najbardziej eleganckich jest:

kubectl run -i --tty --image ubuntu:latest ubuntu-test --restart=Never --rm /bin/sh
Ivan Aracki
źródło
Dlaczego uważasz to za najbardziej eleganckie rozwiązanie?
mordowiciel
1

Moje kilka centów w tej sprawie. Zakładając, że kubectldziała, najbliższe polecenie, które byłoby równoważne z poleceniem dockera, o którym wspomniałeś w swoim pytaniu, byłoby mniej więcej takie.

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

Powyższe polecenie utworzy pojedynczy Podw defaultprzestrzeni nazw i wykona sleeppolecenie z infinityargumentem - w ten sposób będziesz miał proces działający na pierwszym planie, utrzymując kontener przy życiu.

Afterwords możesz wchodzić w interakcje Pod, uruchamiając kubectl execpolecenie.

$ kubectl exec ubuntu -it -- bash

Ta technika jest bardzo przydatna do tworzenia zasobu Poda i debugowania ad-hoc.

Łukasz Dynowski
źródło
1
Działa świetnie. Nie ma potrzeby --restart=Never, po prostu zadzwońkubectl run ubuntu --image=ubuntu -- sleep infinity
Noam Manos