Kubernetes中容器关联方案咨询:同Pod部署还是配置网络?
Question
我尝试创建各自运行独立容器的不同Pod,此前曾通过Docker命令实现容器关联:
Docker命令示例:
# 启动Postgres容器 docker run -d -e POSTGRES_USER=name -e POSTGRES_PASSWORD=pass -e POSTGRES_DB=postgres --name db postgres:10 # 启动应用容器 docker run -p port:port --name image-name --link db:db -t image
目前已在Kubernetes中创建如下Deployment:
DB Deployment:
apiVersion: apps/v1 kind: Deployment metadata: name: db labels: app: db spec: replicas: 1 selector: matchLabels: app: db template: metadata: labels: app: db spec: containers: - name: db image: postgres ports: - containerPort: 5432 env: - name: "POSTGRES_DB" value: "postgres" - name: "POSTGRES_USERNAME" value: "name" - name: "POSTGRES_PASSWORD" value: "pass"
APP Deployment:
apiVersion: apps/v1 kind: Deployment metadata: name: APP labels: app: APP spec: replicas: 1 selector: matchLabels: app: APP template: metadata: labels: app: APP spec: containers: - name: APP image: image ports: - containerPort: port
现咨询:我是否需要将容器部署在同一个Pod中并采用类似Docker命令的命名方式(如db=db),还是只需正确配置网络即可让容器解析主机名?
Answer
不需要把两个容器塞进同一个Pod里!Kubernetes的网络模型和Docker的--link机制完全不同,只要正确配置Service来暴露你的数据库Pod,应用就能通过Service的名称解析到数据库,实现类似Docker link的效果,而且比它更灵活可靠。
为什么不用同一个Pod?
同一个Pod里的容器共享网络命名空间,虽然能直接用localhost访问,但这会带来几个明显的问题:
- 扩缩容不灵活:如果你的应用需要扩容,数据库也会跟着被复制,这显然不合理——数据库通常是单实例或集群部署,和应用的扩缩容需求完全不一致
- 耦合性太高:一个容器挂了,整个Pod都会重启,会连带影响另一个容器的正常运行
- 资源隔离差:两个容器争抢Pod的资源配额,后续排查性能或稳定性问题时会更麻烦
正确的做法:用Service实现服务发现
Kubernetes的Service会自动为Pod提供稳定的DNS名称,步骤非常清晰:
为数据库创建Service
创建一个默认的ClusterIP类型Service,关联你的db Deployment的标签:apiVersion: v1 kind: Service metadata: name: db-service spec: selector: app: db # 匹配db Pod的标签 ports: - protocol: TCP port: 5432 # Service对外暴露的端口 targetPort: 5432 # 数据库容器的实际端口这个Service会自动把流量转发到所有标签为
app: db的Pod上,而且在集群内可以直接通过db-service这个名称访问数据库。修改应用的连接配置
你的应用需要把数据库连接地址改成db-service:5432,可以通过环境变量或者配置文件来设置。比如在APP Deployment里添加对应的环境变量:spec: containers: - name: APP image: image ports: - containerPort: port env: - name: DB_HOST value: "db-service" - name: DB_PORT value: "5432" - name: DB_USER value: "name" - name: DB_PASSWORD value: "pass" - name: DB_NAME value: "postgres"
额外说明
- Kubernetes集群内的DNS服务(比如CoreDNS)会自动为每个Service分配一个域名,格式是
{service-name}.{namespace}.svc.cluster.local。如果你的两个Deployment在同一个namespace下,直接用db-service就能正常解析;如果不在同一个namespace,就需要用完整域名。 - Docker的
--link是一种比较老旧的容器关联方式,在Kubernetes里完全不需要使用。Service+DNS的方式是K8s生态的标准最佳实践,更适合分布式部署的场景,也更符合云原生的设计理念。
内容的提问来源于stack exchange,提问作者omeraiman
相关产品推荐
相关产品推荐

