美文网首页
kubernetes之service

kubernetes之service

作者: 小小小笑呵 | 来源:发表于2019-06-25 20:06 被阅读0次

每创建一个pod,kubernetes都会为pod创建一个虚拟的ip地址,基于这样一个虚拟的IP地址,kebernetes下的每一个pod就可以相互访问了,而不用管该pod是否在同一个node上。如下图所示,node-worker1下的pod-1可以访问node-worker2下的pod-web提供的nginx服务。


pod.png
# 一个master节点和一个work节点
apiVersion: v1
kind: Pod
metadata:
  name: svc-pod1
spec:
  containers:
  - name: nginx
    image: nginx 
# 由于只有一个work节点,所以该pod将会被调度到work节点上
# 此时可以在master节点查看该pod的ip地址,在master节点上使用curl命令查看是否能否访问
# kubectl get pods -o wide
NAME                                READY   STATUS               RESTARTS   AGE     IP
svc-pod1                            1/1     Running              0          32m     10.44.0.30
# curl http://10.44.0.30
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
# 说明从master节点上可以访问来自于work节点上的pod所提供的服务

由kubernetes为pod创建的虚拟IP只能够在kubernetes集群范围内有效,集群外的客户端无法通过pod的ip地址加容器端口访问到其所提供的服务,因此kubernetes为Pod提供了一个端口映射的字段-hostPort。其作用是能够通过主机ip加端口的方式访问pod中容器提供的服务。基本原理是将hostport端口映射到pod中某一容器的端口上,从而实现访问。客户根据node的ip + hostport端口请求服务,node接到请求后,根据iptables,会将请求转发到pod_web上的nginx端口上去从而实现访问

apiVersion: v1
kind: Pod
metadata:
  name: svc-pod1
spec:
  containers:
  - name: nginx
    image: nginx 
    ports:
    - containerPort: 80
      hostPort: 10000
# 在有多个节点的情况下,首先需要查询该pod被调度在哪个node上,然后基于该node的ip地址加端口进行访问
# kubectl describe pod svc-pod1    # 查询node的ip地址
# curl http://node_ip:10000
# 需要注意的是,hostPort端口在node节点上必须是唯一的。若出现相同的hostPort则会应该port冲突导致pod创建失败。比如,在上一个pod的基础上,在同一个节点添加这样一个pod,则会创建失败
apiVersion: v1
kind: Pod
metadata:
  name: svc-pod2
spec:
  containers:
  - name: tomcat
    image: tomcat
    ports:
    - containerPort: 8080
      hostPort: 10000
# 报错如下
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  35s   default-scheduler  0/2 nodes are available: 1 node(s) didn't have free ports for the requested pod ports, 1 node(s) had taints that the pod didn't tolerate.

由于kubernete所提供强大的编排能力,根据上图所示,如果pod_web从worker2调度到worker1上,此时访问pod_web所提供nginx服务,就需要重新查询woker1的ip地址。也就是说通过hostport暴露pod服务是和node的ip地址所绑定的。

那么,有没有一种方式,不管pod被调度在哪里,也就是上图中的pod_web,我不管你在node_worker1上还是在node_worker2上,我都有一个固定的访问地址,能够访问pod所提供的服务呢?

service对象就是专门来做这样事情的,service是为多个功能相同的pod提供一个固定的访问入口,不管背后的pod是如何变化,是增加一个还是减少一个,还是从一个node调度到另外一个node。使用这个固定的访问入口就可以访问到背后的pod。。如下图所示,首先service对象(web-service)通过选择器选择相应的pod(web1和web2),然后通过配置映射相应的端口,最后kubernetes会为service生成一个cluster ip地址。就可以通过cluster ip加端口访问其选择的pod了。

pod2.png
# 分别在两个节点上创建一个pod
# cat pod1.yaml 
apiVersion: v1
kind: Pod
metadata:
 name: svc-pod1
 labels:
   app: web
spec:
 nodeName: compute1
 containers:
 - name: nginx
   image: nginx
 - name: tomcat
   image: tomcat
# cat pod2.yaml 
apiVersion: v1
kind: Pod
metadata:
 name: svc-pod2
 labels:
   app: web
spec:
 nodeName: worker1
 containers:
 - name: nginx
   image: nginx
 - name: tomcat
   image: tomcat
# 创建一个service对象
# cat svc1.yaml 
apiVersion: v1
kind: Service
metadata:
 name: svc-web1
spec:
 selector:
   app: web
 ports:
  - port: 80
    targetPort: 80
    name: nginx
  - port: 8080
    targetPort: 8080
    name: tomcat
# 查看service的cluster ip
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)
svc-web1       ClusterIP   10.102.136.177   <none>        80/TCP,8080/TCP
# 通过同一个cluster ip,即可以访问worker1上的pod,也可以访问worker2上的p,访问规则可以根据cpu等资源使用来确定,默认是轮询
# curl http://10.102.136.177:8080   # 在任何一个节点(master或worker)上都能够得到正常的响应

# 设置type为NodePort使得外部可以进行访问
# cat svc-web2
apiVersion: v1
kind: Service
metadata:
 name: svc-web2
spec:
 type: NodePort
 selector:
   app: web
 ports:
  - port: 80
    targetPort: 80
    name: nginx
    # nodePort: 30000  nodeport不手动指定,kubernetes会自动指定
  - port: 8080
    targetPort: 8080
    name: tomcat
#  kubectl get service -o wide
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S) 
svc-web2       NodePort    10.100.104.20    <none>        80:31245/TCP,8080:31723/TCP
# curl http://node_ip:31245  # 集群中的任何一个节点的ip地址都可以

外网访问流程(以上为例子)

  1. 创建一个service对象后,每个node上的kube-proxy会对iptables进行编写转发规则
  2. 发起一个请求 curl http://node_ip:31723
  3. iptables中的规则会将该流转发对某一个worker_ip
  4. iptables中的规则会将2中的流转发到servie_ip:
  5. iptables中的规则会将3中的流转发到pod_ip上去
  6. 最后请求到达了pod中的容器中去了

小结: 不管iptables怎么进行转换,最终的目的是将请求发送到某个pod里的某容器中去

相关文章

网友评论

      本文标题:kubernetes之service

      本文链接:https://www.haomeiwen.com/subject/yvptcctx.html