-
假设Pod中的容器可能因为各种原因发生故障而死掉,Deployment等controller会通过动态创建和销毁Pod来保证应用整体的健壮性,换句话说,Pod是脆弱的,但应用是健壮的
-
每个Pod都有自己的Ip,当controller用新的Pod替代发生故障的Pod时,新的Pod会分配到新的Ip地址,,所以kubernetes利用service来解决这样的问题:如果一组Pod对外提供服务,比如HTTP,他们的IP很可能会发生变化,那么客户端如何找到并访问这个服务
-
创建Service
-
kubernetes从逻辑上代表了一组pod,具体是哪些Pod则是由label来挑选的,Service有自己的IP,而且这个IP是不变的,客户端只需要访问Service的IP,kubernetes则负责建立和维护Service与Pod的映射关系,无论后端Pod如何变化,对客户端不会有任何影响,因为Service没有变
-
创建一个Deployment
-
启动了三个Pod,运行httpd镜像,label是run:httpd ,service将会用这个label来挑选Pod
-
Pod分配了各自的IP,这些IP只能被kubernetes cluster中的容器和节点访问
-
创建service,配置文件为:
- v1是service的apiVersion
- 指明当前资源的类型为Service
- Service的名字为httpd-svc
- selector指明挑选哪些label为run: https的pod作为Service的后端
- 将service的8080端口映射到Pod的80端口,使用TCP协议
- 执行kubectl apply 创建Service httpd-svc
-
httpd-svc分配到一个cluster-ip 10.99.299.179,可以通过该IP访问后端的httpd pod
-
根据前面的端口映射,这里要使用8080端口,
-
除了自己创建的httpd-svc,还有一个Service kubernetes,Cluster内部通过这个Service访问Kubernetes API Service
-
通过kubectl describe 可以查看httpd-svc与pod的对应关系
-
-
cluster IP底层实现
-
Cluster IP是一个虚拟IP,是由Kubernetes节点上的iptables规则管理的,可以通过iptables-save命令打印出当前节点的iptables规则,
-
这两条规则的含义:
-
如果Cluster内的Pod(原地址来自10.244.0.0/16)要访问httpd-svc,则允许
-
其他原地址访问httpd-svc,跳转到规则KUBE-SVC-RL3JAE4GN7VOGDGP,
-
1/3的概率跳转到规则KUBE-SEP-C5KB52P4BBJQ35PH
-
1/3的概率(剩下的2/3的一半)跳转到规则KUBE-SEP-HGVKQQZZCF7RV41T
-
1/3的概率跳转到规则KUBE-SEP-XE25WGVXLHEIRV05
-
将请求分别转发到后端的三个pod,iptables将访问Service的流量转发到后端Pod,而且使用类似轮询的负载均衡策略,
-
Cluster的每一个节点都配置了相同的iptables规则,这样就确保了整个Cluster都能够通过Service的Cluster IP访问Service
-
-
-
-
DNS访问Service
-
kube-dns是一个DNS服务器,每当有新的Service被创建,kube-dns会添加该Service的DNS记录,Cluster中的Pod可以通过<SERVICE_NAME>.<NAMESPACE_NAME>访问Service,比如可以用httpd-svc访问Service httpd-svc
-
在一个临时的busybox pod中验证了DNS的有效性,由于这个Pod与httpd-svc同属于default namespace,因此可以省略default直接用httpd-svc访问Service
-
用nslookup查看httpd-svc的DNS信息
-
DNS服务器是kube-dns.kube-system.svc.cluster.local,这实际上就是kube-dns组件,他本身是部署在kube-system namespace中的一个service。http-svc.default.svc.cluster.local是httpd-svc的完整域名,如果要访问其他namespace中的Service,就必须带上namespace,kubectl get namespace查看已有的namespace
-
在kube-public中部署Service httpd2-svc
-
通过namespace:kube-public指定资源所属的namespace,多个资源可以在一个YAML文件中定义,用 – 分割,执行kubectl apply创建资源
-
查看kube-public的Service
-
在busybox pod中访问httpd-svc
-
因为不属于同一个namespace,所以必须使用httpd2-svc.kube-public才能访问到
-
-
外网如何访问Service
-
除了cluster内部可以访问Service,暴露给cluster外部的service,kubernetes提供了多种类型的Service,默认是Cluster IP
-
clusterIP:service通过cluster内部的IP对外提供服务,只有cluster内部的节点和pod可以访问,这时默认的service类型,前面提到的service都是cluster ip
-
NodePort:service通过cluster节点的静态端口对外提供服务,cluster外部可以通过:访问Service
-
LoadBalancer:service利用cloud provider特有的load balancer对外提供服务,cloud provider负责将load balancer的流量导向service,目前支持的cloud provider有GCP,AWS,Azur等
-
添加type: NodePort,重新创建httpd-svc
-
kubernetes依然会为httpd-svc分配一个clusterIP,不同的是:
-
EXTERNAL-IP为nodes,表示可以通过cluster每个节点自身的IP访问Service
-
PORT(S)为8080:32312,8080是clusterIP监听的端口,32312则是节点上监听的端口,Kuberetes会从30000-32767中分配一个可用的端口,每个节点都会监听此端口并将请求转发给Service
-
测试NodePort是否正常工作
-
通过三个节点IP+32312端口都能够访问httpd-svc
-
-
Kubernetes如何将:映射到Pod的
-
与cluster ip一样,也是借助了iptables,与clusterIp相比,每个节点的iptables中都增加了下面两条规则
-
规则的含义是:访问当前节点的32312端口的请求会应用规则KUBE-SVC-RL3JAE4GN7VOGDGP
-
作用就是负载均衡到每一个pod,NodePort默认的是随机选择,不过我们可以用nodePort指定某个特定端口
-
现在配置文件中就有三个port了:
- nodePort是节点上监听的端口
- port是ClusterIP上监听的端口
- targetPort是Pod监听的端口
-
最终Node和Cluster在各自端口上接收到的请求都会通过iptables转发到Pod的targetPort
-
-