题目
设计一个多容器Pod并通过Service暴露服务
信息
- 类型:问答
- 难度:⭐⭐
考点
Pod多容器设计, Service类型选择, 端口映射
快速回答
实现步骤:
- 创建包含主应用容器和日志收集容器的Pod
- 使用
ports字段暴露主容器端口 - 创建ClusterIP类型的Service
- 通过标签选择器关联Pod
关键配置:
- Pod中共享日志卷(
emptyDir) - Service的
targetPort映射容器端口 - ClusterIP提供内部服务发现
场景需求
某应用需要同时运行Web服务器和日志收集器:
- Web容器(Nginx)提供HTTP服务(端口80)
- 日志容器(Filebeat)收集Nginx访问日志
- 集群内其他服务需通过固定域名访问Web服务
解决方案
1. 多容器Pod设计
apiVersion: v1
kind: Pod
metadata:
name: web-log-pod
labels:
app: web-log
spec:
volumes:
- name: log-volume
emptyDir: {}
containers:
- name: nginx-container
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: log-volume
mountPath: /var/log/nginx
- name: filebeat-container
image: docker.elastic.co/beats/filebeat:8.5.0
volumeMounts:
- name: log-volume
mountPath: /logs关键点:
- 共享卷
log-volume使两个容器访问相同日志文件 containerPort声明暴露端口(非实际开放端口)- 标签
app: web-log用于Service关联
2. Service配置
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
type: ClusterIP
selector:
app: web-log
ports:
- protocol: TCP
port: 8080 # Service端口
targetPort: 80 # 容器端口关键点:
selector匹配Pod标签实现动态关联targetPort必须与Pod中containerPort一致- ClusterIP类型提供集群内部访问(域名:
web-service.default.svc.cluster.local)
最佳实践
- 容器职责分离:主容器专注业务,sidecar容器处理辅助功能(日志/监控)
- 端口命名:建议命名端口便于维护
ports: - name: http containerPort: 80 - 服务发现:通过
<service-name>.<namespace>.svc.cluster.local访问
常见错误
| 错误类型 | 后果 | 解决方案 |
|---|---|---|
未定义selector | Service无法关联Pod | 检查标签匹配关系 |
targetPort与容器端口不一致 | 连接超时 | 使用kubectl describe pod验证端口 |
忘记声明containerPort | Service可创建但流量不通 | 显式声明容器端口 |
扩展知识
- Headless Service:设置
clusterIP: None直接返回Pod IP,适用于StatefulSet - 就绪探针:添加
readinessProbe确保流量只转发到就绪的PodreadinessProbe: httpGet: path: /healthz port: 80 - NodePort/LoadBalancer:修改
type可暴露服务到集群外部