Service
Kubernetes集群为我们提供了这样的一个对象 Service,Service是一种抽象的对象,它定义了一组Pod的逻辑集合和一个用于访问它们的策略,其实这个概念和微服务非常类似。一个Serivce下面包含的Pod集合一般是由Label Selector来决定的。

环境
192.168.48.101 master01
192.168.48.201 node01
192.168.48.202 node0
三种IP
在继续往下学习Service之前,我们需要先弄明白Kubernetes系统中的三种IP这个问题,因为经常有同学混乱。
- Node IP:
Node节点的IP地址 - Pod IP:
Pod的IP地址 - Cluster IP:
Service的IP地址
首先,Node IP是Kubernetes集群中节点的物理网卡IP地址(一般为内网),所有属于这个网络的服务器之间都可以直接通信,所以Kubernetes集群外要想访问Kubernetes集群内部的某个节点或者服务,肯定得通过Node IP进行通信(这个时候一般是通过外网IP了)
然后Pod IP是每个Pod的IP地址,它是Docker Engine根据docker0网桥的IP地址段进行分配的(我们这里使用的是flannel这种网络插件保证所有节点的Pod IP不会冲突)
最后Cluster IP是一个虚拟的IP,仅仅作用于Kubernetes Service这个对象,由Kubernetes自己来进行管理和分配地址,当然我们也无法ping这个地址,他没有一个真正的实体对象来响应,他只能结合Service Port来组成一个可以通信的服务。
定义Service
先创建一个deployment
vim myapp-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
namespace: default
labels:
app: myapp
type: deploy
spec:
replicas: 2
selector:
matchLabels:
app: myapp
type: deploy
template:
metadata:
name: myapp-pod
labels:
app: myapp
type: deploy
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
[root@master01 deploy_yaml]# kubectl apply -f myapp-deploy.yaml
deployment.apps/myapp-deploy created
[root@master01 deploy_yaml]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-deploy-8675c97685-6br95 1/1 Running 0 21s 10.244.1.51 node01 <none> <none>
myapp-deploy-8675c97685-d9jh4 1/1 Running 0 21s 10.244.2.42 node02 <none> <none>
直接访问pod试试
[root@master01 deploy_yaml]# curl 10.244.1.51
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master01 deploy_yaml]# curl 10.244.2.42
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master01 deploy_yaml]#
创建service
Cluster IP
vim myapp-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
namespace: default
labels:
type: svc
app: myapp
spec:
selector:
app: myapp
type: deploy
type: ClusterIP
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
[root@master01 svc_yaml]# kubectl apply -f myapp-svc.yaml
service/myapp-svc created
[root@master01 svc_yaml]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d <none>
myapp-svc ClusterIP 10.102.65.215 <none> 80/TCP 39s app=myapp,type=deploy
Service能够将一个接收端口映射到任意的targetPort。 默认情况下,targetPort将被设置为与port字段相同的值。 Service能够支持 TCP 和 UDP 协议,默认是 TCP 协议。
测试试试
[root@master01 svc_yaml]# curl 10.102.65.215
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
NodePort
vim myapp-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
namespace: default
labels:
type: svc
app: myapp
spec:
selector:
app: myapp
type: deploy
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30080
protocol: TCP
name: http
[root@master01 svc_yaml]# kubectl apply -f myapp-svc.yaml
service/myapp-svc configured
[root@master01 svc_yaml]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d <none>
myapp-svc NodePort 10.102.65.215 <none> 80:30080/TCP 6m25s app=myapp,type=deploy
测试
[root@master01 svc_yaml]# curl 10.102.65.215
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master01 svc_yaml]# curl 192.168.48.200:30080
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master01 svc_yaml]# curl 192.168.48.201:30080
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master01 svc_yaml]# curl 192.168.48.202:30080
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
默认调度是轮训
[root@master01 svc_yaml]# while true;do curl 192.168.48.200:30080/hostname.html;sleep 1;done
myapp-deploy-8675c97685-6br95
myapp-deploy-8675c97685-d9jh4
myapp-deploy-8675c97685-d9jh4
myapp-deploy-8675c97685-6br95
myapp-deploy-8675c97685-d9jh4
myapp-deploy-8675c97685-6br95
myapp-deploy-8675c97685-d9jh4
sessionAffinity: ClientIP
也可以pod绑定
vim myapp-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
namespace: default
labels:
type: svc
app: myapp
spec:
selector:
app: myapp
type: deploy
type: NodePort
sessionAffinity: ClientIP
ports:
- port: 80
targetPort: 80
nodePort: 30080
protocol: TCP
name: http
[root@master01 svc_yaml]# kubectl apply -f myapp-svc.yaml
service/myapp-svc configured
[root@master01 svc_yaml]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d
myapp-svc NodePort 10.102.65.215 <none> 80:30080/TCP 16m
测试试试
[root@master01 svc_yaml]# while true;do curl 192.168.48.200:30080/hostname.html;sleep 1;done
myapp-deploy-8675c97685-d9jh4
myapp-deploy-8675c97685-d9jh4
myapp-deploy-8675c97685-d9jh4
myapp-deploy-8675c97685-d9jh4
myapp-deploy-8675c97685-d9jh4
无头service
vim myapp-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
namespace: default
labels:
type: svc
app: myapp
spec:
selector:
app: myapp
type: deploy
clusterIP: None
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
[root@master01 svc_yaml]# kubectl apply -f myapp-svc.yaml
service/myapp-svc created
[root@master01 svc_yaml]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d
myapp-svc ClusterIP None <none> 80/TCP 28s
解析测试下
[root@master01 svc_yaml]# yum install bind-utils -y
[root@master01 svc_yaml]# kubectl get svc -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
heapster ClusterIP 10.108.106.25 <none> 80/TCP 2d
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 10d
kubernetes-dashboard NodePort 10.103.36.52 <none> 443:30001/TCP 2d2h
metrics-server ClusterIP 10.100.95.210 <none> 443/TCP 2d1h
[root@master01 svc_yaml]# dig -t A myapp-svc.default.svc.cluster.local @10.96.0.10
; <<>> DiG 9.9.4-RedHat-9.9.4-73.el7_6 <<>> -t A myapp-svc.default.svc.cluster.local @10.96.0.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55803
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;myapp-svc.default.svc.cluster.local. IN A
;; ANSWER SECTION:
myapp-svc.default.svc.cluster.local. 5 IN A 10.244.2.42
myapp-svc.default.svc.cluster.local. 5 IN A 10.244.1.51
;; Query time: 0 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Wed Apr 10 21:51:25 CST 2019
;; MSG SIZE rcvd: 166
ExternalName
ExternalName 是 Service 的特例,它没有 selector,也没有定义任何的端口和 Endpoint。 对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务。
kind: Service
apiVersion: v1
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.com
当查询主机 my-service.prod.svc.cluster.local (后面服务发现的时候我们会再深入讲解)时,集群的 DNS 服务将返回一个值为 my.database.example.com 的 CNAME 记录。 访问这个服务的工作方式与其它的相同,唯一不同的是重定向发生在 DNS 层,而且不会进行代理或转发。
本文深入探讨Kubernetes中的Service概念,包括其类型如ClusterIP、NodePort、无头Service及ExternalName,以及如何通过Service实现Pod的访问和负载均衡。
4246

被折叠的 条评论
为什么被折叠?



