Добавление sidecar-контейнера

KubernetesBeginner
Практиковаться сейчас

Введение

Sidecar-контейнер (вспомогательный контейнер) работает в том же поде (Pod), что и контейнер приложения, и поддерживает его работу. Это отличается от init-контейнера, который должен завершить свою работу до запуска основного приложения. Sidecar-контейнеры обычно используются для сбора логов, проксирования, синхронизации или других вспомогательных задач, жизненный цикл которых должен быть привязан к жизненному циклу пода.

В этой лабораторной работе вы создадите под с несколькими контейнерами: контейнер приложения, который записывает строки логов в общий том emptyDir, и sidecar-контейнер, который считывает этот файл. Вы проверите состояние обоих контейнеров, прочитаете логи sidecar-контейнера, а затем примените этот же шаблон sidecar в шаблоне Deployment.

Подготовка пространства имен для sidecar

На этом этапе вы подготовите чистое пространство имен (namespace) для практики работы с sidecar-контейнерами.

Начните работу в директории /home/labex/project. В этой директории вы будете создавать манифесты Pod и Deployment.

mkdir -p /home/labex/project
cd /home/labex/project

Убедитесь, что API-сервер Kubernetes доступен. Если виртуальная машина только что запустилась и узел еще не готов, подождите несколько секунд и выполните команду снова.

kubectl get nodes --request-timeout=5s

Ожидаемый вывод:

NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35...

Перед созданием рабочих нагрузок дождитесь готовности пода сетевого плагина кластера.

kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s

Ожидаемый вывод:

pod/calico-node-... condition met

Создайте пространство имен с именем ckad-prep-sidecar:

kubectl create namespace ckad-prep-sidecar

Установите это пространство имен в качестве текущего контекста:

kubectl config set-context --current --namespace=ckad-prep-sidecar

Проверьте текущее пространство имен:

kubectl config view --minify --output 'jsonpath={..namespace}'; echo

Ожидаемый вывод:

ckad-prep-sidecar

Создание пода с несколькими контейнерами

На этом этапе вы создадите под, содержащий контейнер приложения и sidecar-контейнер.

Оба контейнера монтируют один и тот же том emptyDir по пути /var/log/shared. Контейнер приложения записывает строки логов в файл /var/log/shared/app.log. Sidecar-контейнер работает одновременно и использует команду tail -f для потоковой передачи содержимого этого файла. Команда touch создает файл до запуска tail -f, поэтому sidecar-контейнер может безопасно ожидать появления данных, даже если приложение еще не записало ни одной строки.

Создайте файл sidecar-pod.yaml:

cat > sidecar-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: sidecar-demo
  labels:
    app: sidecar-demo
spec:
  terminationGracePeriodSeconds: 0
  volumes:
  - name: shared-logs
    emptyDir: {}
  containers:
  - name: app
    image: busybox:1.36
    command:
    - /bin/sh
    - -c
    - 'i=1; while true; do echo "app-line-${i}" >> /var/log/shared/app.log; i=$((i+1)); sleep 2; done'
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/shared
  - name: log-sidecar
    image: busybox:1.36
    command:
    - /bin/sh
    - -c
    - 'touch /var/log/shared/app.log; tail -n +1 -f /var/log/shared/app.log'
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/shared
EOF

Примените манифест:

kubectl apply -f sidecar-pod.yaml

Ожидаемый вывод:

pod/sidecar-demo created

Дождитесь готовности пода. Под с несколькими контейнерами считается готовым только тогда, когда все его контейнеры находятся в состоянии готовности.

kubectl wait --for=condition=Ready pod/sidecar-demo --timeout=120s

Ожидаемый вывод:

pod/sidecar-demo condition met

Выведите список имен контейнеров в поде:

kubectl get pod sidecar-demo -o 'jsonpath={.spec.containers[*].name}{"\n"}'

Ожидаемый вывод:

app log-sidecar

Проверка взаимодействия sidecar-контейнера

На этом этапе вы убедитесь, что оба контейнера запущены и sidecar-контейнер выполняет потоковую передачу файла логов приложения.

Сначала проверьте готовность контейнеров. Вывод покажет имя каждого контейнера и его статус готовности.

kubectl get pod sidecar-demo -o 'jsonpath={range .status.containerStatuses[*]}{.name}{" "}{.ready}{"\n"}{end}'

Ожидаемый вывод:

app true
log-sidecar true

Прочитайте логи контейнера приложения. Приложение выводит данные в стандартный поток вывода (stdout) только при запуске команды оболочки; повторяющиеся строки записываются в общий файл.

kubectl logs sidecar-demo -c app --tail=5

Контейнер приложения может не выводить повторяющиеся строки в stdout. Основным доказательством работы является содержимое общего файла и логи sidecar-контейнера.

Прочитайте общий файл через контейнер приложения:

kubectl exec sidecar-demo -c app -- sh -c 'tail -n 3 /var/log/shared/app.log'

Ожидаемый вывод содержит строки логов приложения:

app-line-...
app-line-...
app-line-...

Теперь прочитайте логи sidecar-контейнера. Поскольку sidecar считывает тот же файл, его логи должны содержать те же строки.

kubectl logs sidecar-demo -c log-sidecar --tail=3

Ожидаемый вывод:

app-line-...
app-line-...
app-line-...

Добавление шаблона sidecar в Deployment

На этом этапе вы добавите шаблон sidecar-контейнера в объект Deployment.

Отдельные поды полезны для обучения, но приложения обычно запускаются с помощью контроллеров. Deployment может создавать заменяющие поды, и каждый такой под будет включать как контейнер приложения, так и sidecar-контейнер из шаблона.

Создайте файл sidecar-deployment.yaml:

cat > sidecar-deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sidecar-worker
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sidecar-worker
  template:
    metadata:
      labels:
        app: sidecar-worker
    spec:
      terminationGracePeriodSeconds: 0
      volumes:
      - name: shared-logs
        emptyDir: {}
      containers:
      - name: app
        image: busybox:1.36
        command:
        - /bin/sh
        - -c
        - 'i=1; while true; do echo "worker-line-${i}" >> /var/log/shared/worker.log; i=$((i+1)); sleep 2; done'
        volumeMounts:
        - name: shared-logs
          mountPath: /var/log/shared
      - name: log-sidecar
        image: busybox:1.36
        command:
        - /bin/sh
        - -c
        - 'touch /var/log/shared/worker.log; tail -n +1 -f /var/log/shared/worker.log'
        volumeMounts:
        - name: shared-logs
          mountPath: /var/log/shared
EOF

Примените Deployment:

kubectl apply -f sidecar-deployment.yaml

Ожидаемый вывод:

deployment.apps/sidecar-worker created

Дождитесь готовности Deployment:

kubectl wait --for=condition=Available deployment/sidecar-worker --timeout=120s

Ожидаемый вывод:

deployment.apps/sidecar-worker condition met

Найдите под, созданный Deployment:

worker_pod="$(kubectl get pods -l app=sidecar-worker -o 'jsonpath={.items[0].metadata.name}')"
echo "$worker_pod"

Ожидаемый вывод показывает сгенерированное имя пода:

sidecar-worker-...

Прочитайте логи sidecar-контейнера из пода, созданного Deployment:

kubectl logs "$worker_pod" -c log-sidecar --tail=3

Ожидаемый вывод:

worker-line-...
worker-line-...
worker-line-...

Резюме

Вы создали под с несколькими контейнерами, состоящий из контейнера приложения и sidecar-контейнера, использовали том emptyDir для совместного использования файла логов, убедились, что оба контейнера работают вместе, и перенесли этот шаблон sidecar в Deployment. Теперь вы знаете, когда уместно использовать sidecar: он поддерживает работу приложения в течение всего времени его выполнения.