文章目录
Kubernetes(6)service访问pod
作用和概念
我们不应该期望Kubernetes Pod是健壮的,而是要假设Pod中的容器很可能因为各种原因发生故障而死掉。Deployment等Controller会通过动态创建和销毁Pod来保证应用整体的健壮性。换句话说,Pod是脆弱的,但应用是健壮的
Pod的IP地址是Docker Daemon根据docker0网桥的IP地址段进行分配的,但Service的Cluster IP地址是Kubernetes系统中的虚拟IP地址,由系统动态分配。Service的Cluster IP地址相对于Pod的IP地址来说相对稳定,Service被创建时即被分配一个IP地址,在销毁该Service之前,这个IP地址都不会再变化了。而Pod在Kubernetes集群中生命周期较短,可能被ReplicationContrller销毁、再次创建,新创建的Pod将会分配一个新的IP地址
每个Pod都有自己的IP地址。当Controller用新Pod替代发生故障的Pod时,新Pod会分配到新的IP地址,这样就产生了一个问题:如果一组Pod对外提供服务(比如HTTP),它们的IP很有可能发生变化,那么客户端如何找到并访问这个服务呢?
Kubernetes给出的解决方案是Service
服务,是一个虚拟概念,逻辑上代理后端pod。众所周知,pod生命周期短,状态不稳定,pod异常后新生成的pod ip会发生变化,之前pod的访问方式均不可达。通过service对pod做代理,service有固定的ip和port,ip:port组合自动关联后端pod,即使pod发生改变,kubernetes内部更新这组关联关系,使得service能够匹配到新的pod。这样,通过service提供的固定ip,用户再也不用关心需要访问哪个pod,以及pod是否发生改变,大大提高了服务质量。如果pod使用rc创建了多个副本,那么service就能代理多个相同的pod,通过kube-proxy,实现负载均衡
三种IP
Node IP:Node节点的IP地址
Pod IP:Pod的IP地址
Cluster IP:Service的IP地址
首先,Node IP是Kubernetes集群中节点的物理网卡IP地址(一般为内网),所有属于这个网络的服务器之间都可以直接通信,所以Kubernetes集群外要想访问Kubernetes集群内部的某个节点或者服务,肯定得通过Node IP进行通信(这个时候一般是通过外网IP了)
然后Pod IP是每个Pod的IP地址,它是Docker Engine根据docker0网桥的IP地址段进行分配的(我们这里使用的是flannel这种网络插件保证所有节点的Pod IP不会冲突)
最后Cluster IP是一个虚拟的IP,仅仅作用于Kubernetes Service这个对象,由Kubernetes自己来进行管理和分配地址,当然我们也无法ping这个地址,他没有一个真正的实体对象来响应,他只能结合Service Port来组成一个可以通信的服务。
Service 类型
ClusterIP:通过集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问,这也是默认的 ServiceType。
NodePort:通过每个 Node 上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求 :,可以从集群的外部访问一个 NodePort 服务。
LoadBalancer:使用云提供商的负载局衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务。
ExternalName:通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容(例如, foo.bar.example.com)。 没有任何类型代理被创建,这只有 Kubernetes 1.7 或更高版本的 kube-dns 才支持。
创建Service
Service从逻辑上代表了一组Pod,具体是哪些Pod则是
由label来挑选的。Service有自己的IP,而且这个IP是不变的。客户端只需要访问Service的IP,Kubernetes则负责建立和维护Service与Pod的映射关系。无论后端Pod如何变化,对客户端不会有任何影响,因为Service没有变
来看个例子,创建下面的这个Deployment
[k8s@server1 ~]$ cat httpd.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd
spec:
replicas: 3
selector:
matchLabels:
run: httpd
template:
metadata:
labels:
run: httpd
spec:
containers:
- name: httpd
image: httpd
ports:
- containerPort: 80
# 注意的是:node节点上的docker服务必须是好的,而且虚拟机要能上网
[k8s@server1 ~]$ kubectl apply -f httpd.yml
deployment.apps/httpd created
[k8s@server1 ~]$ kubectl get pod -o wide #注意:ip的出现是需要时间的(容器的准备也是需要时间的)
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
httpd-69cb5b9fdd-cwqk2 1/1 Running 0 14s 10.244.2.22 server3 <none> <none>
httpd-69cb5b9fdd-wprs9 1/1 Running 0 14s 10.244.1.24 server2 <none> <none>
httpd-69cb5b9fdd-xj9mp 1/1 Running 0 14s 10.244.1.23 server2 <none> <none>
# 我们可以看到的是:Pod分配了各自的IP,这些IP只能被Kubernetes Cluster中的容器和节点访问
[k8s@server1 ~]$ curl 10.244.2.22
<html><body><h1>It works!</h1></body></html>
[k8s@server1 ~]$ curl 10.244.1.24
<html><body><h1