service服务的实现依赖于kubenetes的一个附件DNS,在1.11之前的版本使用的是kube-dns,目前使用的是CoreDNS。service的名称解析是强依赖与DNS附件的,因此在部署完k8s之后必须要部署一个DNS附件(CoreDNS或者kube-dns,目前使用的是CoreDNS。service的名称解析是强依赖与DNS附件的,因此在部署完k8s之后必须要部署一个DNS附件)。
接下来定义一个service资源,类型为ClusterIP,IP地址可以自动生成,也可以手动指定,但要避免地址冲突。
[root@master kube_manifest]# vim deploy-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: deploy
namespace: default
spec:
selector: ##用于关联后端的哪些pod资源
app: myapp
release: canary
clusterIP: 10.97.98.99
type: ClusterIP
ports:
- port: 9527
targetPort: 80
[root@master kube_manifest]# kubectl apply -f deploy-svc.yaml
service/deploy created
查看svc信息
[root@master kube_manifest]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
deploy ClusterIP 10.97.98.99 <none> 9527/TCP 16m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 12d
[root@master kube_manifest]# kubectl describe svc deploy
Name: deploy
Namespace: default
Labels: <none>
Annotations: Selector: app=myapp,release=canary
Type: ClusterIP
IP: 10.97.98.99
Port: <unset> 9527/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.17:80,10.244.1.18:80,10.244.1.19:80 + 2 more...
Session Affinity: None
Events: <none>
访问测试
[root@node1 ~]# curl 10.97.98.99:9527
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
定义一个NodePort类型的service,用于与外部通信
[root@master kube_manifest]# vim deploy-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: deploy
namespace: default
spec:
selector:
app: myapp
release: canary
clusterIP: 10.99.98.99
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30080
查看详细信息。
[root@master kube_manifest]# kubectl describe svc deploy
Name: deploy
Namespace: default
Labels: <none>
Annotations: Selector: app=myapp,release=canary
Type: NodePort
IP: 10.99.98.99
Port: <unset> 80/TCP
TargetPort: 80/TCP
NodePort: <unset> 30080/TCP
Endpoints: 10.244.1.17:80,10.244.1.18:80,10.244.1.19:80 + 2 more...
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
[root@master kube_manifest]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
deploy NodePort 10.99.98.99 <none> 80:30080/TCP 6m17s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 12d
外部访问测试
service还支持会话亲和性,使用sessionAffinity字段指定,支持"ClientIP" 和 “None"两种类型,默认为"None”。使用kubectl patch打补丁的方式把deploy这个service改为支持会话亲和性。
[root@master kube_manifest]# kubectl patch svc deploy -p '{"spec":{"sessionAffinity":"ClientIP"}}'
service/deploy patched
[root@master kube_manifest]# kubectl describe svc deploy
Name: deploy
Namespace: default
Labels: <none>
Annotations: Selector: app=myapp,release=canary
Type: NodePort
IP: 10.99.98.99
Port: <unset> 80/TCP
TargetPort: 80/TCP
NodePort: <unset> 30080/TCP
Endpoints: 10.244.1.17:80,10.244.1.18:80,10.244.1.19:80 + 2 more...
Session Affinity: ClientIP
External Traffic Policy: Cluster
Events: <none>
访问测试,验证了同一客户端的请求始终发往同一个后端。
[root@node1 ~]# for i in {1..10};do curl http://10.10.20.207:30080/hostname.html;done
myapp-deploy-65fb6c8459-qs4f8
myapp-deploy-65fb6c8459-qs4f8
myapp-deploy-65fb6c8459-qs4f8
myapp-deploy-65fb6c8459-qs4f8
myapp-deploy-65fb6c8459-qs4f8
myapp-deploy-65fb6c8459-qs4f8
myapp-deploy-65fb6c8459-qs4f8
myapp-deploy-65fb6c8459-qs4f8
myapp-deploy-65fb6c8459-qs4f8
myapp-deploy-65fb6c8459-qs4f8
无头service服务。既没有clusterIP,service解析时直接解析后端pod的IP。只需在service中的clusterIP字段定位为None或者""即可。(注意:无头service不支持NodePort类型)
apiVersion: v1
kind: Service
metadata:
name: deploy-headless
namespace: default
spec:
selector:
app: myapp
release: canary
clusterIP: None
ports:
- port: 80
targetPort: 80
##不指定type则默认为ClusterIP
查看SVC信息
[root@master kube_manifest]# kubectl apply -f deploy-svc-headless.yaml
service/deploy-headless created
[root@master kube_manifest]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
deploy NodePort 10.99.98.99 <none> 80:30080/TCP 58m
deploy-headless ClusterIP None <none> 80/TCP 10s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 12d
使用dig命令解析无头service的IP,可以看出service直接关联到后端pod的IP。
[root@master kube_manifest]# dig -t A deploy-headless.default.svc.cluster.local. @10.96.0.10
; <<>> DiG 9.9.4-RedHat-9.9.4-50.el7 <<>> -t A deploy-headless.default.svc.cluster.local. @10.96.0.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37632
;; flags: qr aa rd; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;deploy-headless.default.svc.cluster.local. IN A
;; ANSWER SECTION:
deploy-headless.default.svc.cluster.local. 30 IN A 10.244.1.19
deploy-headless.default.svc.cluster.local. 30 IN A 10.244.1.21
deploy-headless.default.svc.cluster.local. 30 IN A 10.244.1.17
deploy-headless.default.svc.cluster.local. 30 IN A 10.244.1.20
deploy-headless.default.svc.cluster.local. 30 IN A 10.244.1.18
;; Query time: 88 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: 三 6月 03 13:16:10 CST 2020
;; MSG SIZE rcvd: 355
[root@master kube_manifest]# kubectl get pod -o wide -l app=myapp,release=canary
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-deploy-65fb6c8459-822hz 1/1 Running 0 21h 10.244.1.17 node1 <none> <none>
myapp-deploy-65fb6c8459-f99zs 1/1 Running 0 21h 10.244.1.18 node1 <none> <none>
myapp-deploy-65fb6c8459-fjsqr 1/1 Running 0 5h14m 10.244.1.21 node1 <none> <none>
myapp-deploy-65fb6c8459-psg9d 1/1 Running 0 5h14m 10.244.1.20 node1 <none> <none>
myapp-deploy-65fb6c8459-qs4f8 1/1 Running 0 5h14m 10.244.1.19 node1 <none> <none>
注意上面使用10.96.0.10这个DNS解析,是系统coreDNS的service服务的ip。
[root@master kube_manifest]# kubectl get svc -n kube-system -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 12d k8s-app=kube-dns