linux运维、架构之路-K8s通过Service访问Pod
一、通过Service访问Pod
每个Pod都有自己的IP地址,当Controller用新的Pod替换发生故障的Pod时,新Pod会分配到新的IP地址,例如:有一组Pod对外提供HTTP服务,它们的IP很可能发生变化,那么客户端如何找到并访问这个服务呢,Service由此而生。Service从逻辑上代表了一组Pod,具体是哪些则由label来挑选,Service有自己的IP,并且这个IP是不变的,客户端只需要访问Service IP,无论后端Pod如何变化,对客户端访问不会有任何影响,k8s负责建立和维护Service与Pod映射关系。
1、创建Service
①创建示例文件
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: httpd spec: replicas: 3 template: metadata: labels: app: httpd #Service将会用这个label来挑选Pod spec: containers: - name: httpd image: httpd ports: - containerPort: 80
②创建一个Httpd的Deployment应用
[root@k8s-node1 ~]# kubectl apply -f httpd.yaml deployment.extensions "httpd" created [root@k8s-node1 ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE httpd-fcdb8b4d8-bzsq8 1/1 Running 0 2m 10.2.72.180 192.168.56.12 httpd-fcdb8b4d8-k5ds9 1/1 Running 0 2m 10.2.72.182 192.168.56.12 httpd-fcdb8b4d8-ks4qq 1/1 Running 0 2m 10.2.72.181 192.168.56.12
上图Pod分配了各自的IP,这些IP只能被k8s集群中的容器和节点访问
[root@k8s-node2 ~]# curl 10.2.72.180 <html><body><h1>It works!</h1></body></html>
③创建Service文件
apiVersion: v1 #Service的apiVersion kind: Service #资源类型 metadata: name: httpd-svc #Service的名字 spec: selector: app: httpd #标签选择,挑选哪些label为app: httpd的Pod作为Service的后端 ports: - protocol: TCP #将Service的8080端口映射到Pod的80端口,使用TCP协议 port: 8080 targetPort: 80
④创建Service并查看
[root@k8s-node1 ~]# kubectl apply -f httpd-svc.yaml service "httpd-svc" created [root@k8s-node1 ~]# kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE httpd-svc ClusterIP 10.1.168.37 <none> 8080/TCP 7s kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 8d
httpd-svc分配到一个集群IP,可以通过该IP访问后端的Pod
[root@k8s-node2 ~]# curl 10.1.168.37:8080 <html><body><h1>It works!</h1></body></html>
⑤查看httpd-svc和Pod的对应关系
[root@k8s-node1 ~]# kubectl describe service httpd-svc Name: httpd-svc Namespace: default Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"httpd-svc","namespace":"default"},"spec":{"ports":[{"port":8080,"protocol":"TC... Selector: app=httpd Type: ClusterIP IP: 10.1.168.37 Port: <unset> 8080/TCP TargetPort: 80/TCP Endpoints: 10.2.72.180:80,10.2.72.181:80,10.2.72.182:80 Session Affinity: None Events: <none>
Service的Cluster IP是通过iptables映射到Pod中
2、DNS访问Service
①k8s集群中的DNS服务
[root@k8s-node1 ~]# kubectl get deployment --namespace=kube-system NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE coredns 2 2 2 2 4d heapster 1 1 1 1 4d
coredns插件是一个DNS服务,当有新的Service被创建,就会添加到DNS记录,集群中的Pod可以通过SERVICE_NAME访问Service
②创建示例
[root@k8s-node1 ~]# kubectl run busybox --rm -it --image=busybox /bin/sh If you don't see a command prompt, try pressing enter. / # / # / # / # / # / # wget httpd-svc.default:8080 Connecting to httpd-svc.default:8080 (10.1.168.37:8080) saving to 'index.html' index.html 100% |*************************************************************************| 45 0:00:00 ETA 'index.html' saved
同一个命名空间下,busybox Pod可以直接通过httpd-svc访问Service,这也验证了DNS的效性。
不同命名空间下,访问Service需要带上namespace,
wget httpd-svc.demon:8080
二、外网访问Service
- 1、ClusterIP
- Service通过Cluster内部的IP对外提供服务,只有集群内的节点和Pod可以访问,这是默认的Service类型
- 2、NodePort
- Service通过Cluster节点的静态端口对外提供服务,Cluster外部可以通过NodeIP:访问Service
- 3、LoadBalancer
- Service 利用cloud provider特有的load balancer对外提供服务,cloud provider负责将load balancer的流量导向Service,目前支持GCP、AWS、Azur等
1、NodePort
①创建示例文件
apiVersion: v1 kind: Service metadata: name: httpd-svc spec: type: NodePort selector: app: httpd ports: - protocol: TCP port: 8080 targetPort: 80
②创建并查看
[root@k8s-node1 ~]# kubectl apply -f httpd-svc.yaml service "httpd-svc" created [root@k8s-node1 ~]# kubectl get svc httpd-svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE httpd-svc NodePort 10.1.186.145 <none> 8080:57643/TCP 12s
1、EXTERNAL-IP为nodes,表示可以通过Cluster每个节点自身的IP访问Service
2、PORT(S) 8080:57643,8080是ClusterIP监听的端口,57643刚是节点上监听的端口,k8s默认会从30000~32767这个范围内分配一个可用的端口,每个节点都会监听此端口,并将请求转发给Service
③测试NodePort
[root@k8s-node1 ~]# curl 192.168.56.12:57643 <html><body><h1>It works!</h1></body></html>
NodePort与ClusterIP一样,也是通过iptables规则实现,负载均衡到每一个Pod,NodePort默认的是随机选择,也可以指定某个固定端口
apiVersion: v1 kind: Service metadata: name: httpd-svc spec: type: NodePort selector: app: httpd ports: - protocol: TCP nodePort: 30000 #指节点上监听的端口 port: 8080 #指ClusterIP上监听的端口 targetPort: 80 #指Pod监听的端口
Node和ClusterIP在各自端口上接收到的请求都会通过iptables转发到Pod的targetPort