十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
service是要通过coreDNS来管理pod的。
创新互联公司自2013年起,先为新化等服务建站,新化等地企业,进行企业商务咨询服务。为新化企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。kube-proxy始终监视着apiserver,获取与service资源的变动状态。一旦发现有service资源发生变动,kube-proxy都要把它转变为当前节点之上的,能够实现service资源调度,包括将客户端资源调度到pod的规则(iptables或者ipvs)。
service工作模式有三种:userspace(k8s 1.1版本之前),iptables(k8s 1.10版本之前)和ipvs(k8s 1.11版本之后)
userspace模型:用户空间模型。k8s 1.11版本用ipvs了,这个比iptables效率高。
[root@master ~]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1443/TCP 16d redis ClusterIP 10.106.138.181 6379/TCP 23h
[root@master ~]# kubectl delete svc redis service "redis" deleted
注意kubernetes这个service千万别删,因为K8s都是通过10.96.0.1这个地址联系的。
[root@master ~]# kubectl explain svc
service类型:
a)、ExternalName:表示把集群外部的服务引入到集群内部中来,即实现了集群内部pod和集群外部的服务进行通信;
b)、ClusterIP:只能在集群内部通讯;
c)、NodePort:可以和集群外部通讯;
d)、LoadBalancer:这个表示我们把k8s部署在虚拟机上,自动在外部创建负载均衡器。比如在阿里云上,底层是LBAAS。
以前我们使用kubectl expose创建service,下面我们使用清单来创建service。
[root@master manifests]# cat redis-svc.yaml apiVersion: v1 kind: Service metadata: name: redis namespace: default spec: selector: app: redis role: logstor clusterIP: 10.97.97.97 #这个ip可以不指定,让它自动分配 type: ClusterIP ports: - port: 6379 #service ip中的端口 targetPort: 6379 #容器ip中的端口
[root@master manifests]# kubectl apply -f redis-svc.yaml service/redis created
[root@master manifests]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1443/TCP 16d redis ClusterIP 10.97.97.97 6379/TCP 1m
[root@master manifests]# kubectl describe svc redis Name: redis Namespace: default Labels:Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"redis","namespace":"default"},"spec":{"clusterIP":"10.97.97.97","ports":[{"por... Selector: app=redis,role=logstor Type: ClusterIP IP: 10.97.97.97 Port: 6379/TCP TargetPort: 6379/TCP Endpoints: 10.244.2.65:6379 ##这是pod的ip Session Affinity: None Events:
资源记录:SVC_NAME.NAMESPACE_NAME.DOMAIN.LTD
集群默认后缀是svc.cluster.local
比如我们创建的redis默认名称就是redis.defalut.svc.cluster.local
访问路径:client---->NodeIP:NodePoint----->ClusterIP:ServerPort---->PodIP:containerPort
[root@master manifests]# cat myapp-svc.yaml apiVersion: v1 kind: Service metadata: name: myapp namespace: default spec: selector: app: myapp release: canary clusterIP: 10.99.99.99 #这个ip可以不指定,让他自动分配 type: NodePort ports: - port: 80 #service ip的端口 targetPort: 80 #容器ip的端口 nodePort: 30080 #node节点上端口,这个端口也可以不指定,会自动分配端口
[root@master manifests]# kubectl apply -f myapp-svc.yaml service/myapp created
[root@master manifests]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1443/TCP 16d myapp NodePort 10.99.99.99 80:30080/TCP 44s redis ClusterIP 10.97.97.97 6379/TCP 15m
[root@master manifests]# curl http://172.16.1.101:30080/hostname.html myapp-deploy-69b47bc96d-79fqh [root@master manifests]# curl http://172.16.1.101:30080/hostname.html myapp-deploy-69b47bc96d-tc54k
注意:172.16.1.101是Node节点的Ip,并且可以看到访问是做了负载均衡的
下面我们再把来自同一个客户端会话请求用sessionAffinity粘滞到一个固定的pod上,这样就不会出现负载均衡现象了,相当于nginx的 ip_hash功能,如下:
[root@master manifests]# kubectl patch svc myapp -p '{"spec":{"sessionAffinity":"ClientIP"}}' service/myapp patched
上面打的补丁也可以直接用edit方法编辑。
[root@master manifests]# kubectl describe svc myapp Session Affinity: ClientIP
再改回负载均衡模式: [root@master manifests]# kubectl patch svc myapp -p '{"spec":{"sessionAffinity":"None"}}' service/myapp patched
我们前面介绍的service是service name解析为cluster ip,然后cluster ip对应到后面的pod ip。
而无头service是指service name 直接解析为后面的pod ip。
无头就是没有cluster ip牵头了。
[root@master manifests]# cat myapp-svc-headless.yaml apiVersion: v1 kind: Service metadata: name: myapp-svc namespace: default spec: selector: app: myapp #挑选的pod还是myapp。一个pod可以有多个service release: canary clusterIP: None #None表示是无头service ports: - port: 80 #service ip中的端口 targetPort: 80 #容器ip中的端口
[root@master manifests]# kubectl apply -f myapp-svc-headless.yaml service/myapp-svc created
[root@master manifests]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1443/TCP 16d myapp NodePort 10.99.99.99 80:30080/TCP 1h myapp-svc ClusterIP None 80/TCP 28s redis ClusterIP 10.97.97.97 6379/TCP 1h
看到上面myapp-svc的cluster-ip是空,这就是无头service。
[root@master manifests]# kubectl get svc -n kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kube-dns ClusterIP 10.96.0.1053/UDP,53/TCP 16d
可以看到coreDNS的地址是10.96.0.10
[root@master manifests]# dig -t A myapp-svc.default.svc.cluster.local. @10.96.0.10 ; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7_5.1 <<>> -t A myapp-svc.default.svc.cluster.local. @10.96.0.10 ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10702 ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;myapp-svc.default.svc.cluster.local. INA ;; ANSWER SECTION: myapp-svc.default.svc.cluster.local. 5 IN A10.244.1.63 myapp-svc.default.svc.cluster.local. 5 IN A10.244.2.51 ;; Query time: 0 msec ;; SERVER: 10.96.0.10#53(10.96.0.10) ;; WHEN: Mon Sep 24 00:22:07 EDT 2018 ;; MSG SIZE rcvd: 166
[root@master manifests]# kubectl get pods -o wide -l app=myapp NAME READY STATUS RESTARTS AGE IP NODE myapp-deploy-69b47bc96d-79fqh 1/1 Running 0 1d 10.244.1.63 node1 myapp-deploy-69b47bc96d-tc54k 1/1 Running 0 1d 10.244.2.51 node2
上面看到无头service name直接被解析到另个pod上的ip了。
我们可以用ExternalName对Service名称和集群外部服务地址做一个映射,使之访问Service名称就是访问外部服务。例如下面的例子是将 svc1 和 xxx.xxx.xxx.xxx 做了对等关系。
kind: Service apiVersion: v1 metadata: name: svc1 namespace: default spec: type: ExternalName externalName: somedomain.org
不过,ExternalName 类型的服务适用于外部服务使用域名的方式,缺点是不能指定端口。
另外,要实现集群内访问集群外服务的这个需求,也是非常简单的。因为集群内的Pod会继承Node上的DNS解析规则。因此只要Node可以访问的服务,Pod中也可以访问到。