添加 Sidecar 容器

KubernetesBeginner
立即练习

介绍

Sidecar 容器与应用程序容器运行在同一个 Pod 中,并在应用程序运行时为其提供支持。这与初始化容器(Init Container)不同,初始化容器必须在应用启动前完成任务。Sidecar 常用于日志传输、代理、同步或其他需要共享 Pod 生命周期辅助行为的场景。

在本实验中,你将创建一个多容器 Pod,其中包含一个将日志写入共享 emptyDir 卷的应用容器,以及一个跟踪该文件的 Sidecar 容器。你将检查这两个容器,读取 Sidecar 日志,然后将相同的 Sidecar 模式应用到 Deployment 模板中。

准备 Sidecar 命名空间

在此步骤中,你将准备一个干净的命名空间,用于进行 Sidecar 练习。

从 /home/labex/project 开始。你将在此目录下编写 Pod 清单和 Deployment 清单。

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

检查 Kubernetes API 服务器是否可达。如果虚拟机刚启动且节点尚未就绪,请等待几秒钟后再运行该命令。

kubectl get nodes --request-timeout=5s

预期输出包括:

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

在创建工作负载之前,请等待集群网络 Pod 就绪。

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

创建多容器 Pod

在此步骤中,你将创建一个包含应用程序容器和 Sidecar 容器的 Pod。

两个容器都在 /var/log/shared 挂载了同一个 emptyDir 卷。应用容器将日志行写入 /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

等待 Pod 就绪。多容器 Pod 只有在所有常规容器都就绪时才算就绪。

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

预期输出:

pod/sidecar-demo condition met

列出 Pod 中的容器名称:

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

读取应用容器的日志。应用仅在 shell 命令启动时才写入标准输出(stdout);其重复的行会进入共享文件。

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

应用容器可能不会将重复的行打印到标准输出。重要的证据在于共享文件和 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 模板中。

独立 Pod 对于学习很有用,但应用程序通常通过控制器运行。Deployment 可以创建替换 Pod,每个替换 Pod 都将包含模板中的应用容器和 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 创建的 Pod:

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

预期输出显示生成的 Pod 名称:

sidecar-worker-...

从 Deployment 创建的 Pod 中读取 Sidecar 日志:

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

预期输出包括:

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

总结

你创建了一个包含应用容器和 Sidecar 容器的多容器 Pod,使用 emptyDir 卷共享日志文件,确认了两个容器协同运行,并将相同的 Sidecar 模式迁移到了 Deployment 模板中。现在你了解了 Sidecar 的适用场景:它在应用程序运行时为其提供支持。