直接访问 Pod 的问题
负载创建完成后,如何访问负载呢?访问负载实际上就是访问Pod,但是直接访问Pod 会有如下几个问题:
● Pod会随时被Deployment这样的控制器删除重建,那访问Pod的结果就会变得不 可预知。
● Pod的IP地址是在Pod启动后才被分配,在启动前并不知道Pod的IP地址。
● 应用往往都是由多个运行相同镜像的一组Pod组成,一个个Pod的访问也变得不现 实。
举个例子,假设有这样一个应用程序,使用Deployment创建了前台和后台,前台会调 用后台做一些计算处理,如图7-1所示。后台运行了3个Pod,这些Pod是相互独立且可 被替换的,当Pod出现状况被重建时,新建的Pod的IP地址是新IP,前台的Pod无法直 接感知。
开发指南 7 使用 Service 和 Ingress 管理网络访问
图7-1 负载间访问
Service 是如何工作的
Kubernetes中的Service对象就是用来解决上述Pod访问问题的。Service有一个固定IP 地址,Service将访问他的流量转发给Pod,具体转发给哪些Pod通过Label来选择,而 且Service可以给这些Pod做负载均衡。
那么对于上面的例子,通过为前后台添加两个Service,通过Service来访问Pod,这样 前台Pod就无需感知后台Pod的变化,如图7-2所示。
图7-2 通过 Service 访问 Pod
创建 Service
下面示例创建一个名为“nginx”的Service,通过selector选择到标签“app:nginx”的 Pod,目标Pod的端口为80,Service对外暴露的端口为8080。
访问服务只需要通过“服务名称:对外暴露的端口”接口,对应本例即“nginx:
8080”。这样,在其他负载中,只需要通过“nginx:8080”就可以访问到“nginx”关 联的Pod。
apiVersion: v1 kind: Service metadata:
name: nginx # Service的名称 spec:
selector: # Label Selector,选择包含app=nginx标签的Pod app: nginx
ports:
- name: service0
targetPort: 80 # Pod的端口
开发指南 7 使用 Service 和 Ingress 管理网络访问
port: 8080 # Service对外暴露的端口
# kubectl create -f nginx-svc.yaml -n $namespace_name service/nginx created
# kubectl get svc -n $namespace_name
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
使用 ServiceName 访问 Service
云容器实例中您可以使用CoreDNS插件给Service做域名解析,然后使用
LoadBalancer 类型的 Service
现在您知道可以创建ClusterIP类型的Service,通过Service的IP可以访问到Service后端 的Pod。
云容器实例同时还支持创建LoadBalancer类型的Service,将增强型ELB实例与Service 绑定,这样访问ELB实例的流量就会访问到Service。
ELB实例根据IP地址不同可以分为私网ELB实例和公网ELB实例,区别在于公网ELB实例 绑定了一个公网IP,您可以根据需要选择。您可以调用创建负载均衡器(增强型)创 建ELB实例,更方便的方法是通过ELB控制台创建增强型ELB实例。
说明
● ELB实例必须与Service在同一个VPC内,否则无法绑定。
● 跨namespace不支持service或ELB域名访问,只能通过ELB内网IP:端口访问。
图7-3 LoadBalancer Service
下面是一个创建LoadBalancer类型的Service。创建完成后,可以通过ELB的IP:Port访 问到后端Pod。
apiVersion: v1 kind: Service metadata:
name: nginx annotations:
kubernetes.io/elb.id: 77e6246c-a091-xxxx-xxxx-789baa571280 # ELB的ID
开发指南 7 使用 Service 和 Ingress 管理网络访问
spec:
selector:
app: nginx ports:
- name: service0 targetPort: 80
port: 8080 # ELB访问端口 protocol: TCP
type: LoadBalancer # Service的类型