在之前的Nodeport和hostNetwork中,大致了解了暴露的用法,此后有Ingress Controller的用法。之前不管那种方式,对于调用前端而言是不清楚后端pod的ip地址的。但是,有一些有状态的应用程序就需要清楚的联系到每个容器的ip地址,直接与容器通信。那就是Service的No ClusterIP无头服务。
None
-
无头服务(No ClusterIP):此前,每一个service都会有一个service名称,解析的结果都是cluster ip,请求由cluster ip DNAT到后端的pod上。因此cluster ip的解析结果只会有一个ip。但是,现在可以去掉中间这层cluster ip(既不会动态分配也不会手动指定),而后的解析将会解析到pod ip上,而pod的ip是取决于集群大小。这类的service就是无头service。直达后端pod。如下图:准备测试的yaml文件,其中使用
DaemonSet
pod控制器,也就意味着每个node上面会创建一个容器,而后配置标签管理,分别是app: nginx
和release: www
,容器使用marksugar/nginx:1.14.a
apiVersion: apps/v1 kind: DaemonSet metadata: name: nginx-linuxea namespace: default spec: selector: matchLabels: app: nginx release: www template: metadata: labels: app: nginx release: www spec: containers: - name: linuxea image: "marksugar/nginx:1.14.a" ports: - name: http containerPort: 80
编写service的yaml文件,标签和上述pod一致,
clusterIP
为None
。而后applyapiVersion: v1 kind: Service metadata: name: none-linuxea namespace: default spec: selector: app: nginx release: www clusterIP: None ports: - port: 80 targetPort: 80
[root@linuxea linuxea]# kubectl apply -f none-linuxea.yaml service/none-linuxea created
启动之后
kubectl get svc
查看CLUSTER-IP
这列为None
[root@linuxea linuxea]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 18d none-linuxea ClusterIP None <none> 80/TCP 4s redis ClusterIP 10.96.65.65 <none> 6379/TCP 5d
此刻
kubectl get pods -o wide
查看到获取的pod IP,这里的pod ip会被直接解析到命名空间 - 如果不适用无头服务,那么解析的是一个Cluster IP地址,由这个IP DNAT到后端每个容器上
[root@linuxea linuxea]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
nginx-linuxea-2qkmf 1/1 Running 0 2m 172.16.2.44 linuxea.node-2.com <none>
nginx-linuxea-8hvk6 1/1 Running 0 2m 172.16.3.46 linuxea.node-3.com <none>
nginx-linuxea-dk5hg 1/1 Running 0 2m 172.16.1.42 linuxea.node-1.com <none>
使用dig none-linuxea.default.svc.cluster.local
命名空间得到的ip便是三个pod的真是ip。如果此时需要在内部调用可直接使用none-linuxea.default.svc.cluster.local
进行调用即可
[root@linuxea linuxea]# dig -t A none-linuxea.default.svc.cluster.local. @10.96.0.10
; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> -t A none-linuxea.default.svc.cluster.local. @10.96.0.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32900
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;none-linuxea.default.svc.cluster.local. IN A
;; ANSWER SECTION:
none-linuxea.default.svc.cluster.local. 5 IN A 172.16.1.42
none-linuxea.default.svc.cluster.local. 5 IN A 172.16.2.44
none-linuxea.default.svc.cluster.local. 5 IN A 172.16.3.46
;; Query time: 0 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Mon Sep 10 14:10:34 BST 2018
;; MSG SIZE rcvd: 229
[root@linuxea linuxea]#
如果此时解析有头的(有ClusterIP的)就会解析到ClusterIP上,在前面提到过,请求到service的ClusterIP,而后DNAT到pod IP的
其中,service定义后,尤其在nodePort中需要做两级代理,甚至两级转换或者调度,无论是iptables还是ipvs都是四层调度。倘若运行https服务的话,那意味着每台nodePort service都需要配置成https主机。在四层调度中本身是无法卸载https会话。kubeneres的ingress可以引入进群外部流量的七层调度(7层pod),将流量引入到内部来,引入方式如:nginx,haproxy等等!
ExternalName
当pod内的客户端去访问kubernes集群外的服务,(外部名称)ExternalName便用于实现于此。
- 外部名称:外部的服务的名称,通过服务名称来访问外部服务。从而使得集群内部的pod像使用集群内部的服务一样使用集群外部的服务。并且pod client访问的是一个名称(通过coredns解析)pod client想要访问kubernetes外部服务,需要通过service层级转换到(SNAT),请求到外部服务中,外部服务响应与node ip,再由node ip转交给service,service转交给pod client,从而使得pod client访问外部服务。