Kubernetes Service从逻辑上代表了一组Pod,具体是哪些Pod则是由label来挑选的。Service有自己的IP,而且这个IP是不变的。客户端只需要访问Service的IP,Kubernetes则负责建立和维护Service与Pod的映射关系。无论后端Pod如何变化,对客户端不会有任何影响,因为Service没有变。
首先创建Pod,vi httpd.yml文件如下:
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: httpd
- spec:
- replicas: 2
- selector:
- matchLabels:
- app: httpd
- template:
- metadata:
- labels:
- app: httpd
- spec:
- containers:
- - name: httpd
- image: httpd
- ports:
- - containerPort: 80
我们启动了两个Pod,运行httpd镜像,label是app: httpd,Service将会用这个label来挑选Pod,kubectl get pod -o wid如下图所示:

Pod分配了各自的IP,这些IP只能被Kubernetes Cluster中的容器和节点访问

接下来创建Service,vi httpd-svc.yml配置如下图所示:
- apiVersion: v1
- kind: Service
- metadata:
- name: httpd-svc
- spec:
- selector:
- app: httpd
- ports:
- - protocol: TCP
- port: 8080
- targetPort: 80
执行kubectl apply -f httpd-svc.yml创建Service

httpd-svc分配到一个CLUSTER-IP 10.97.198.28。可以通过该IP访问后端的httpd Pod,如下图所示

通过kubectl describe可以查看httpd-svc与Pod的对应关系

Cluster IP是一个虚拟IP,是由Kubernetes节点上的iptables规则管理的。
可以通过iptables-save命令打印出当前节点的iptables规则,因为输出较多,这里只截取与httpd-svc Cluster IP 10.99.229.179相关的信息,如图所示
![]()
这两条规则含义如下:
规则如图所示:

跳转规则如下:

即将请求分别转发到后端的两个Pod。通过上面的分析,我们得到结论:iptables将访问Service的流量转发到后端Pod,而且使用类似轮询的负载均衡策略。
除了Cluster内部可以访问Service,很多情况下我们也希望应用的Service能够暴露给Cluster外部。Kubernetes提供了多种类型的Service,默认是ClusterIP。
下面我们来实践NodePort,Service httpd-svc的配置文件修改如下
- apiVersion: v1
- kind: Service
- metadata:
- name: httpd-svc
- spec:
- type: NodePort
- selector:
- app: httpd
- ports:
- - protocol: TCP
- port: 8080
- targetPort: 80
重新创建的httpd-svc,如下图所示:

Kubernetes依然会为httpd-svc分配一个ClusterIP,不同的是:
下面测试NodePod是否正常工作:

与ClusterIP一样,NodePort也是借助了iptables。与ClusterIP相比,每个节点的iptables中都增加了下面两条规则:
![]()
访问31276会应用规则KUBE-SVC-IYRDZZKXS5EOQ6Q6
NodePort默认的是随机选择,不过我们可以用nodePort指定某个 特定端口。