四层代理service # 功能:为一组pods上的应用程序公开网络服务的抽象方法,并为这一组pod提供相同的DNS名字,从而实现负载均衡。 # 产生背景: 正常的K8S环境都是集群部署,运行在pod中的某个服务可以在集群内通过POD IP访问 [root@master-worker-node-1 service]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test 1/1 Running 0 20s 10.244.31.42 only-worker-node-3 <none> <none> [root@master-worker-node-1 service]# curl 10.244.31.42 the version is 1.1.0, this is a nginx server in container, and the ip is 10.244.31.42/32 能够访问的原因是现场集群部署过程中使用了ipip类型的calico网络,etcd会记录每个node上的pod subnet信息,主机上的tunl0网卡直接将流量发送给pod。 [root@master-worker-node-1 service]# ip add show tunl0 5: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000 link/ipip 0.0.0.0 brd 0.0.0.0 inet 10.244.123.128/32 scope global tunl0 valid_lft forever preferred_lft forever [root@master-worker-node-1 service]# tcpdump -i tunl0 -p icmp -nnvvv dropped privs to tcpdump tcpdump: listening on tunl0, link-type RAW (Raw IP), capture size 262144 bytes 21:30:57.712908 IP (tos 0x0, ttl 64, id 8740, offset 0, flags [DF], proto ICMP (1), length 84) 10.244.123.128 > 10.244.31.42: ICMP echo request, id 5, seq 117, length 64 21:30:57.714115 IP (tos 0x0, ttl 63, id 19327, offset 0, flags [none], proto ICMP (1), length 84) 10.244.31.42 > 10.244.123.128: ICMP echo reply, id 5, seq 117, length 64 但是这类通常我们不会使用这类自主式pod运行业务pod,因为主机关机或者误删除pod,都将导致业务不可访问。哪怕是通过控制器控制pod数量,但pod的删除、重建将导致的ip地址变化同样是服务不可访问。 因此,将pod上的应用程序公开网络服务需要解决两个问题:1、即使pod地址发生变化,业务仍不受影响;2、多个pod提供相同应用服务时,如何进行四成负载。 # K8S集群中的三个IP # 1、node IP:集群节点的物理网络 [root@master-worker-node-1 service]# ip add show ens3 2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 52:54:00:53:50:5f brd ff:ff:ff:ff:ff:ff inet 192.168.122.89/24 brd 192.168.122.255 scope global noprefixroute ens3 valid_lft forever preferred_lft forever inet 192.168.122.253/24 scope global secondary ens3 valid_lft forever preferred_lft forever inet6 fe80::df8:5c2e:6181:c92b/64 scope link noprefixroute valid_lft forever preferred_lft forever # 2、pod IP:pod地址 [root@master-worker-node-1 service]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test 1/1 Running 0 17m 10.244.31.42 only-worker-node-3 <none> <none> # 3、cluster IP:集群IP,或者叫service IP,仅存在iptables或者ipvs规则中 [root@master-worker-node-1 service]# kubectl get service -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR gray-release-service ClusterIP 10.105.60.46 <none> 30080/TCP 30h version=gray-release kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16d <none> Service type: NodePort、Cluster IP,集群内集群外的区别,语法区别不大 # service基本语法 [root@master-worker-node-1 service]# cat first-service.yaml kind: Service apiVersion: v1 metadata: name: test-service spec: selector: func: test-service type: NodePort # ClusterIP、ExternalName、NodePort、LoadBalancer ports: - name: test port: 31111 # port that will be exposed by this service. protocol: TCP # TCP UDP SCTP nodePort: 32333 # The port on each node on which this service is exposed when type is NodePort or LoadBalancer. Usually assigned by the system. targetPort: 80 # Number or name of the port to access on the pods targeted by the service. # 通过deployment创建pod [root@master-worker-node-1 service]# kubectl get deployment -o wide NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR nginx-deploy 3/3 3 3 5m24s nginx-test nginx:stable-alpine-perl func=test-service [root@master-worker-node-1 service]# kubectl get pods --show-labels -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS nginx-deploy-76cc5c5b-kjwxn 1/1 Running 0 3m51s 10.244.31.44 only-worker-node-3 <none> <none> func=test-service,pod-template-hash=76cc5c5b nginx-deploy-76cc5c5b-q6dt7 1/1 Running 0 3m51s 10.244.31.46 only-worker-node-3 <none> <none> func=test-service,pod-template-hash=76cc5c5b nginx-deploy-76cc5c5b-rzj96 1/1 Running 0 3m51s 10.244.54.50 only-worker-node-4 <none> <none> func=test-service,pod-template-hash=76cc5c5b # 创建service [root@master-worker-node-1 service]# kubectl get service test-service -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR test-service NodePort 10.105.161.8 <none> 31111:31123/TCP 2m54s func=test-service # 创建service的时候会同步创建一个同名的endpoints资源 [root@master-worker-node-1 service]# kubectl get endpoints test-service NAME ENDPOINTS AGE test-service 10.244.31.44:80,10.244.31.46:80,10.244.54.50:80 3h26m # service和pod自动关联 [root@master-worker-node-1 service]# kubectl describe service test-service Name: test-service Namespace: default Labels: <none> Annotations: <none> Selector: func=test-service Type: NodePort # 通过访问每个节点的物理网络都可以访问到pod内的应用资源 IP Family Policy: SingleStack IP Families: IPv4 IP: 10.105.161.8 # service的地址 IPs: 10.105.161.8 Port: test 31111/TCP # 将service的31111端口映射到内部pod的80端口 TargetPort: 80/TCP # 表示内部pod暴露的端口 NodePort: test 31123/TCP # 将service的31111端口和每个集群中的物理节点31123端口绑定 Endpoints: 10.244.31.44:80,10.244.31.46:80,10.244.54.50:80 # 标签选择器对应上的pod ip Session Affinity: None External Traffic Policy: Cluster Events: <none> # 访问service IP的地址+端口可以访问内部资源 [root@master-worker-node-1 service]# curl 10.105.161.8:31111 the version is 1.1.0, this is a nginx server in container, and the ip is 10.244.54.50/32 [root@master-worker-node-1 service]# curl 10.105.161.8:31111 the version is 1.1.0, this is a nginx server in container, and the ip is 10.244.31.46/32 [root@master-worker-node-1 service]# curl 10.105.161.8:31111 the version is 1.1.0, this is a nginx server in container, and the ip is 10.244.31.44/32 # 在集群中任意一个节点上,访问其物理网络的31123端口也能访问到pod内部资源 [root@master-worker-node-2 ~]# ip add show ens3 | grep 192 inet 192.168.122.106/24 brd 192.168.122.255 scope global noprefixroute ens3 [root@master-worker-node-2 ~]# curl 192.168.122.106:31123 the version is 1.1.0, this is a nginx server in container, and the ip is 10.244.54.50/32 [root@master-worker-node-1 service]# ip add show ens3 | grep 192 inet 192.168.122.89/24 brd 192.168.122.255 scope global noprefixroute ens3 inet 192.168.122.253/24 scope global secondary ens3 [root@master-worker-node-1 service]# curl 192.168.122.89:31123 the version is 1.1.0, this is a nginx server in container, and the ip is 10.244.31.46/32 # 上述环境中,能访问的原因与ipvs规则有关 [root@master-worker-node-1 manifests]# kubectl get configmaps -n kube-system -o yaml | grep -E "ipvs|Proxy" ipvs: kind: KubeProxyConfiguration mode: ipvs # 每一个节点上都有ipvs规则 [root@master-worker-node-1 manifests]# ipvsadm -Ln | grep 31123 -A 3 TCP 172.17.0.1:31123 rr -> 10.244.31.44:80 Masq 1 0 0 # rr表示轮询 -> 10.244.31.46:80 Masq 1 0 0 -> 10.244.54.50:80 Masq 1 0 0 TCP 192.168.122.89:31123 rr -> 10.244.31.44:80 Masq 1 0 0 -> 10.244.31.46:80 Masq 1 0 0 -> 10.244.54.50:80 Masq 1 0 0 TCP 192.168.122.253:31123 rr -> 10.244.31.44:80 Masq 1 0 0 -> 10.244.31.46:80 Masq 1 0 0 -> 10.244.54.50:80 Masq 1 0 0 -- TCP 10.244.123.128:31123 rr -> 10.244.31.44:80 Masq 1 0 0 -> 10.244.31.46:80 Masq 1 0 0 -> 10.244.54.50:80 Masq 1 0 0 Service type: ExternalName # 背景:默认情况下,访问同名空间下的service仅需要访问service-name就行,而一个命名空间下的pod想要其他命名空间下的service,需要使用完整域名才行。 # 完整域名: service-name.namespace-name.svc.cluster.local [root@master-worker-node-1 ~]# kubectl get svc -o wide -A | grep -E "NAME|service" NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR default service-default ClusterIP 10.109.121.131 <none> 30000/TCP 7h36m func=test-service ns-1 service-ns-1 ClusterIP 10.103.47.187 <none> 30000/TCP 7h25m func=test-service ns-2 service-ns-2 ClusterIP 10.103.149.111 <none> 30000/TCP 7h24m func=test-service [root@master-worker-node-1 ~]# kubectl exec -it -n ns-1 centos -- bash [root@centos /]# cat /etc/resolv.conf search ns-1.svc.cluster.local svc.cluster.local cluster.local # 域名 nameserver 10.96.0.10 options ndots:5 [root@centos /]# curl service-ns-1:30000 the version is 1.1.0, this is a nginx server in container, and the ip is 10.244.31.55/32 [root@centos /]# curl service-ns-2:30000 curl: (6) Could not resolve host: service-ns-2 [root@centos /]# curl service-ns-2.ns-2.svc.cluster.local:30000 the version is 1.1.0, this is a nginx server in container, and the ip is 10.244.54.57/32 [root@centos /]# host service-ns-1 service-ns-1.ns-1.svc.cluster.local has address 10.103.47.187 [root@centos /]# host service-ns-2 Host service-ns-2 not found: 3(NXDOMAIN) [root@centos /]# curl 10.103.109.121.131:30000 curl: (6) Could not resolve host: 10.103.109.121.131 [root@centos /]# curl 10.109.121.131:30000 the version is 1.1.0, this is a nginx server in container, and the ip is 10.244.31.52/32 # 上面的例子看到,虽然访问短域名不行,但是可以通过完整域名和clusterip进行访问,那为什么还需要external name呢? # 我理解这就是因为1、service IP可能因为集群环境的重启的发生变化,而且地址记忆没有域名清晰;2、带service-name和namespace-name的域名不好记忆,可以通过命名别名一样完成配置。方便维护 # 在上面的例子中,ns-1中的POD想要访问ns-2中的service,就可以将ns-2的完整域名配置一个软连接,external Name # externalName配置文件 [root@master-worker-node-1 service]# cat external-name.yaml apiVersion: v1 kind: Service metadata: name: test-external-name namespace: ns-1 spec: type: ExternalName externalName: service-ns-2.ns-2.svc.cluster.local [root@master-worker-node-1 service]# kubectl apply -f external-name.yaml service/test-external-name created [root@master-worker-node-1 service]# kubectl get service -o wide -A | grep service default service-default ClusterIP 10.109.121.131 <none> 30000/TCP 8h func=test-service ns-1 service-ns-1 ClusterIP 10.103.47.187 <none> 30000/TCP 7h49m func=test-service ns-1 test-external-name ExternalName <none> service-ns-2.ns-2.svc.cluster.local <none> 6m10s <none> ns-2 service-ns-2 ClusterIP 10.103.149.111 <none> 30000/TCP 7h49m func=test-service [root@master-worker-node-1 service]# kubectl exec -it centos -n ns-1 -- bash [root@centos /]# host test-external-name test-external-name.ns-1.svc.cluster.local is an alias for service-ns-2.ns-2.svc.cluster.local. service-ns-2.ns-2.svc.cluster.local has address 10.103.149.111 [root@centos /]# ping test-external-name -c 2 PING service-ns-2.ns-2.svc.cluster.local (10.103.149.111) 56(84) bytes of data. 64 bytes from service-ns-2.ns-2.svc.cluster.local (10.103.149.111): icmp_seq=1 ttl=64 time=0.129 ms 64 bytes from service-ns-2.ns-2.svc.cluster.local (10.103.149.111): icmp_seq=2 ttl=64 time=0.201 ms --- service-ns-2.ns-2.svc.cluster.local ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 0.129/0.165/0.201/0.036 ms [root@centos /]# curl test-external-name:30000 the version is 1.1.0, this is a nginx server in container, and the ip is 10.244.31.56/32 # 感觉像是访问自己命名空间下的资源一样。 小结 1、k8s中有三种ip,node IP、Pod IP和Cluster IP; 2、service的类型有四种: cluster ip:只能在集群内访问;means a service will only be accessible inside the cluster, via the cluster IP nodePort: 可以在集群外访问,也可以在集群内访问。means a service will be exposed on one port of every node, in addition to 'ClusterIP' type. ExternalName:means a service consists of only a reference to an external name that kubedns or equivalent will return as a CNAME record, with no exposing or proxying of any pods involved. LoadBalancer: means a service will be exposed via an external load balancer (if the cloud provider supports it), in addition to 'NodePort' type. 3、k8s中的namespace没有网络隔离功能,不能的ns只能算是不同的项目,不是内核态的namespace。因此,不同ns下的pod默认是互通的,pod也能访问其他ns下的资源。但是访问需要使用IP地址或者完整域名。此时为了方便,可以创建externalName的链接来实现跨namespace的互访。
标签:node,ns,service,--,worker,10.244,K8S,root From: https://www.cnblogs.com/woshinidaye123/p/16977479.html