介绍
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 的适用场景:它在应用程序运行时为其提供支持。


