k8s 用命名空间 namespace 把资源进行隔离, 默认情况下, 相同的命名空间里的服务可以相互通讯, 反之进行隔离.
服务 Service
1.1 Service
Kubernetes 中一个应用服务会有一个或多个实例 (Pod,Pod 可以通过 rs 进行多复本的建立), 每个实例(Pod) 的 IP 地址由网络插件动态随机分配(Pod 重启后 IP 地址会改变). 为屏蔽这些后端实例的动态变化和对多实例的负载均衡, 引入了 Service 这个资源对象, 如下所示:
- apiVersion: v1
- kind: Service
- metadata:
- name: nginx-svc
- labels:
- App: nginx
- spec:
- type: ClusterIP
- ports:
- - port: 80
- targetPort: 80
- selector: #service 通过 selector 和 pod 建立关联
- App: nginx
根据创建 Service 的 type 类型不同, 可分成 4 种模式:
ClusterIP: 默认方式. 根据是否生成 ClusterIP 又可分为普通 Service 和 Headless Service 两类:
普通 Service: 通过为 Kubernetes 的 Service 分配一个集群内部可访问的固定虚拟 IP(Cluster IP), 实现集群内的访问. 为最常见的方式.
Headless Service: 该服务不会分配 Cluster IP, 也不通过 kube-proxy 做反向代理和负载均衡. 而是通过 DNS 提供稳定的络 ID 来访问, DNS 会将 headless service 的后端直接解析为 podIP 列表. 主要供 StatefulSet 使用.
NodePort: 除了使用 Cluster IP 之外, 还通过将 service 的 port 映射到集群内每个节点的相同一个端口, 实现通过 nodeIP:nodePort 从集群外访问服务.
LoadBalancer: 和 nodePort 类似, 不过除了使用一个 Cluster IP 和 nodePort 之外, 还会向所使用的公有云申请一个负载均衡器(负载均衡器后端映射到各节点的 nodePort), 实现从集群外通过 LB 访问服务.
ExternalName: 是 Service 的特例. 此模式主要面向运行在集群外部的服务, 通过它可以将外部服务映射进 k8s 集群, 且具备 k8s 内服务的一些特征 (如具备 namespace 等属性), 来为集群内部提供服务. 此模式要求 kube-dns 的版本为 1.7 或以上. 这种模式和前三种模式(除 headless service) 最大的不同是重定向依赖的是 dns 层次, 而不是通过 kube-proxy.
比如, 在 service 定义中指定 externalName 的值 "my.database.example.com":
此时 k8s 集群内的 DNS 服务会给集群内的服务名 ..svc.cluster.local 创建一个 CNAME 记录, 其值为指定的 "my.database.example.com".
当查询 k8s 集群内的服务 my-service.prod.svc.cluster.local 时, 集群的 DNS 服务将返回映射的 CNAME 记录 "foo.bar.example.com".
备注:
前 3 种模式, 定义服务的时候通过 selector 指定服务对应的 pods, 根据 pods 的地址创建出 endpoints 作为服务后端; Endpoints Controller 会 watch Service 以及 pod 的变化, 维护对应的 Endpoint 信息. kube-proxy 根据 Service 和 Endpoint 来维护本地的路由规则. 当 Endpoint 发生变化, 即 Service 以及关联的 pod 发生变化, kube-proxy 都会在每个节点上更新 iptables, 实现一层负载均衡.
而 ExternalName 模式则不指定 selector, 相应的也就没有 port 和 endpoints.
ExternalName 和 ClusterIP 中的 Headles Service 同属于 Headless Service 的两种情况. Headless Service 主要是指不分配 Service IP, 且不通过 kube-proxy 做反向代理和负载均衡的服务.
1.2 Port
Service 中主要涉及三种 Port: * port 这里的 port 表示 service 暴露在 clusterIP 上的端口, clusterIP:Port 是提供给集群内部访问 kubernetes 服务的入口.
targetPort
containerPort,targetPort 是 pod 上的端口, 从 port 和 nodePort 上到来的数据最终经过 kube-proxy 流入到后端 pod 的 targetPort 上进入容器.
nodePort
nodeIP:nodePort 是提供给从集群外部访问 kubernetes 服务的入口.
总的来说, port 和 nodePort 都是 service 的端口, 前者暴露给从集群内访问服务, 后者暴露给从集群外访问服务. 从这两个端口到来的数据都需要经过反向代理 kube-proxy 流入后端具体 pod 的 targetPort, 从而进入到 pod 上的容器内.
1.3 IP
使用 Service 服务还会涉及到几种 IP:
ClusterIP
Pod IP 地址是实际存在于某个网卡 (可以是虚拟设备) 上的, 但 clusterIP 就不一样了, 没有网络设备承载这个地址. 它是一个虚拟地址, 由 kube-proxy 使用 iptables 规则重新定向到其本地端口, 再均衡到后端 Pod. 当 kube-proxy 发现一个新的 service 后, 它会在本地节点打开一个任意端口, 创建相应的 iptables 规则, 重定向服务的 clusterIP 和 port 到这个新建的端口, 开始接受到达这个服务的连接.
Pod IP
Pod 的 IP, 每个 Pod 启动时, 会自动创建一个镜像为 gcr.io/google_containers/pause 的容器, Pod 内部其他容器的网络模式使用 container 模式, 并指定为 pause 容器的 ID, 即: network_mode: "container:pause 容器 ID", 使得 Pod 内所有容器共享 pause 容器的网络, 与外部的通信经由此容器代理, pause 容器的 IP 也可以称为 Pod IP.
节点 IP
Node-IP,service 对象在 Cluster IP range 池中分配到的 IP 只能在内部访问, 如果服务作为一个应用程序内部的层次, 还是很合适的. 如果这个 service 作为前端服务, 准备为集群外的客户提供业务, 我们就需要给这个服务提供公共 IP 了. 指定 service 的 spec.type=NodePort, 这个类型的 service, 系统会给它在集群的各个代理节点上分配一个节点级别的端口, 能访问到代理节点的客户端都能访问这个端口, 从而访问到服务.
来源: http://www.bubuko.com/infodetail-3335609.html