8-通过Service访问Pod

Pod中的容器很可能因为各种原因发生故障而死掉。

而使用Deployment等Controller可以动态创建和销毁Pod来保证应用整体的健壮性。

每个Pod都有自己的IP地址。当Controller用新Pod替代发生故障的Pod时,新Pod会分配到新的IP地址。如果直接通过Pod的ip访问服务,就会产生问题。

为了解决这个问题,Kubernetes提供了Service,并通过service访问pod中的服务。

创建Service

Service从逻辑上代表了一组Pod。Service有自己的IP,而且这个IP是不变的。
客户端只需要访问Service的IP,Kubernetes则负责建立和维护Service与Pod的映射关系。

看个例子,创建下面的这个Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd
spec:
  replicas: 3
  selector:
    matchLabels:
      app: httpd
  template:
    metadata:
      labels:
        app: httpd
    spec:
      containers:
      - name: httpd
        image: httpd
        ports:
        - containerPort: 80

启动了3个pod

pod分配了各自的IP,这些IP只能被集群内的容器和节点访问

接下来创建Service,配置文件如下

apiVersion: v1
kind: Service
metadata:
  name: httpd-svc
spec:
  selector:
    app: httpd
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 80

①v1是Service的apiVersion。
②指明当前资源的类型为Service。
③Service的名字为httpd-svc。
④selector使用标签和pod关联。
⑤将Service的8080端口映射到Pod的80端口,使用TCP协议。

执行kubectl apply创建Service httpd-svc

[root@master ~]# kubectl apply -f httpd-svc.yml 
service/httpd-svc created
[root@master ~]# kubectl get service
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
httpd-svc    ClusterIP   10.97.164.120           8080/TCP   40s
kubernetes   ClusterIP   10.96.0.1               443/TCP    4h51m

httpd-svc分配到一个CLUSTER-IP 10.97.164.120。可以通过该IP访问后端的httpd Pod,根据前面的端口映射,这里要使用8080端口

[root@master ~]# curl 10.97.164.120:8080

It works!

这和直接访问Pod IP:80是一样的

除了我们创建的httpd-svc,还有一个Service kubernetes,Cluster内部通过这个Service访问Kubernetes API Server。

通过describe查看service的详细信息,从中可以看到Endpoints即为与之对应的Pod


Cluster IP底层实现

CLUSTER-IP是如何映射到Pod IP的呢?答案是iptables。

可以通过iptables-save命令打印出当前节点的iptables规则

大概意思是经过规则跳转,最终将请求转发到后端的三个Pod。

结论:iptables将访问Service的流量转发到后端Pod,而且使用类似轮询的负载均衡策略。

另外,需要补充一点:Cluster的每一个节点都配置了相同的iptables规则,这样就确保了整个Cluster都能够通过Service的Cluster IP访问Service


DNS访问Service

kubeadm部署时会默认安装coredns组件

coredns是一个DNS服务器。每当有新的Service被创建,coredns会添加该Service的DNS记录。Cluster中的Pod可以通过.访问Service。

如下在一个临时的busybox Pod中验证了DNS的有效性。

另外,由于这个Pod与httpd-svc同属于default namespace,因此可以省略default直接用httpd-svc访问Service

用nslookup查看httpd-svc的DNS信息

Server是DNS服务器
httpd-svc.default.svc.cluster.local是httpd-svc的完整域名


外网如何访问Service

Kubernetes提供了多种类型的Service,默认是ClusterIP。

ClusterIP只能在Cluster内部访问,如果要在外部访问service,这就要通过NodePort来实现。

apiVersion: v1
kind: Service
metadata:
  name: httpd-svc
spec:
  type: NodePort
  selector:
    app: httpd
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 80

添加type: NodePort,重新创建httpd-svc

Kubernetes依然会为httpd-svc分配一个ClusterIP,8080是ClusterIP监听的端口
除此之外,8080后的端口:31639,则是节点监听的端口,每个节点都会监听此端口并将请求转发给Service

在master节点上测试

集群外访问测试

这时,集群外也可以访问服务了

NodePort默认的是随机选择,可以用nodePort指定某个特定端口

现在配置文件中就有三个Port了:
(1)nodePort是节点上监听的端口。
(2)port是ClusterIP上监听的端口。
(3)targetPort是Pod监听的端口。


也可以通过expose命令创建service

查看service

浏览器访问节点ip:30355

你可能感兴趣的:(8-通过Service访问Pod)