Pod 访问问题
Pod 被创建之后,该如何访问呢?直接访问 Pod 会有以下几个问题:
- Pod 的 IP 地址是在 Pod 启动后才被分配,在启动前并不知道 Pod 的 IP 地址。
- Pod 的 IP 存在变化的可能性,被 Deployment 重建 IP 就会发生变化。
- 应用服务往往是一组 Pod 组成,逐个访问 Pod 也不现实。
为了以一种固定的方式访问 Pod,Kubernetes 提供了一种负载均衡和服务发现的机制: Service。Service 创建后会提供一个固定的虚拟 IP(以 ClusterIP 类型的 Service 为例), 这样,用户无需关心 Pod 在哪个节点,通过固定 Service IP 即可实现对 Pod 地访问,并且 Service 可以对访问进行负载均衡。
示例:创建一个 Service
apiVersion: v1 kind: Service metadata: name: nginx # Service的名称 spec: selector: # Label Selector,选择包含app=nginx标签的Pod app: nginx ports: - name: service0 targetPort: 80 # Pod的端口 port: 8080 # Service对外暴露的端口 protocol: TCP # 转发协议类型,支持TCP和UDP type: ClusterIP # Service的类型
使用 ServiceName 访问 Service
使用 IP 直连有一个问题,如果 Service 被删除,相应的 Cluster IP 也会被回收。域名发现
为此 Kubernetes 结合 DNS 的。CoreDNS 安装成功后会成为 DNS 服务器,当创建 Service 后,CoreDNS 会将 Service 的名称与 IP 记录起来,这样 Pod 就可以通过向 CoreDNS 查询 Service 的名称获得 Service 的 IP 地址。
coreDNS 提供格式如 <service-name>.<namespace-name>.svs.cluster.local 的服务,访问该地址,集群内的域名解析解析服务器会返回该服务所对应的 A 记录。实际使用中,同一个命名空间下可以省略<namespace>.svc.cluster.local,直接使用 ServiceName 即可。
例如上面创建的名为 nginx 的 Service,直接通过 nginx:8080 就可以访问到 Service,进而访问 Pod, 这样无需感知具体 Service 的 IP 地址。
Service 类型
Service 的类型除了 ClusterIP 还有 NodePort、LoadBalancer 和 Headless Service,这几种类型的 Service 有着不同的用途。
- ClusterIP:用于在集群内部互相访问的场景,通过 ClusterIP 访问 Service。
- NodePort:用于从集群外部访问的场景,通过节点上的端口访问 Service,详细介绍请参见 NodePort 类型的 Service。
- LoadBalancer:用于从集群外部访问的场景,其实是 NodePort 的扩展,通过一个特定的 LoadBalancer 访问 Service,这个 LoadBalancer 将请求转发到节点的 NodePort,而外部只需要访问 LoadBalancer。
- Headless Service:用于 Pod 间互相发现,该类型的 Service 并不会分配单独的 ClusterIP, 而且集群也不会为它们进行负载均衡和路由。您可通过指定 spec.clusterIP 字段的值为 “None” 来创建 Headless Service。
NodePort 类型的 Service
NodePort 类型的 Service 可以让 Kubernetes 集群每个节点上保留一个相同的端口, 外部访问连接首先访问节点 IP:Port,然后将这些连接转发给服务对应的 Pod。如下图所示。
下面是一个创建 NodePort 类型的 Service。创建完成后,可以通过节点的 IP:Port访问到后台 Pod