Service 也是一种资源对象,service 解决pod 集群对外访问的统一性问题,
一个pod 集群对外暴露统一的接口,供集群外访问和调用,该资源的抽象就是
service
Service 的三种类型 ClusterIP、NodePort 和 LoadBalancer
ClusterIP
默认的service 类型,service 通过该ip 对外提供服务, 只有culster 内的节点和pod 可访问
ClusterIP 是一种虚拟IP,他并不是真是存在,它由k8s的iptables规则所管理, 他不能被ping 通
NodePort
Service 通过设置NodePort 将Pod的端口映射到节点物理机上。这样外部系统可以通过node ip 加 该端口来访问 Service。
通过NodePort的形式,将我们的Pod服务通过集群节点的真实IP提供给集群外部系统进行访问。
LoadBalancer
Service 可以通过LoadBalancer 映射到云服务商提供的LoadBalancer 地址。
这种方式需要我们将kubernetes集群部署在公有云上,然后通过这些云供应商提供的一个LoadBalancer IP地址,将外部访问流量通过LoadBalancer 的IP地址进行负载均衡和路由转发。
基本原理:
k8s 通过service CLUSTER-IP 访问 pod, 是通过访问endpoint 这个对象实现的, 新创建的pod 如果被svc 的标签选择器选中,则会自动生成endpoint 对象,加入到svc 当中,并且给pod加入必要的环境变量。且看如下例子
先创建一个svc,我们没有指定svc 的type ,默认就是ClusterIP 类型
[root@k8s-master1 test]# cat nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
clusterIP: 10.96.173.64
ports:
- protocol: TCP
port: 8000
targetPort: 80
selector:
app: nginx
备注: clustIP 可以手动指定,也可以从ip 池中由dhcp 服务自动分配
此时我们去查endpoints ,还有describe svc
接下来我们创建两个标签选择器为nginx 的pod,来看svc 发生的变化
[root@k8s-master1 test]# cat nginx1.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx1
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
[root@k8s-master1 test]# cat nginx2.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx2
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
我们发现这个endpoint 对象生成了,这也就意味这我们这个svc 网络打通了, 现在通过访问svc 的clustip 就能访问到集群内的两个pod
pod 内环境变量中加入了svc 的clustip 和端口
我们登录进两个nginx pod 内将nginx1 的默认访问页改为nginx1, nginx2的默认访问页改为nginx2, 用curl 访问集群ip 测试下:
[root@k8s-master1 test]# kubectl exec -it nginx1 -- bash
root@nginx1:/# echo "nginx1" >/usr/share/nginx/html/index.html
root@nginx1:/# exit
[root@k8s-master1 test]# kubectl exec -it nginx2 -- bash
root@nginx2:/# echo "nginx2" >/usr/share/nginx/html/index.html
root@nginx2:/# exit
curl 10.96.173.64:8000
发现已成功访问到集群内部,
再来看下nodeport
先创建一个Nodetype 类型的svc
[root@k8s-master1 test]# cat webapp.yaml
apiVersion: v1
kind: Service
metadata:
name: webapp
spec:
type: NodePort
ports:
- port: 8001
targetPort: 80
selector:
app: webapp
如上yaml 所示,添加 type: NodePort ,这样就可以将pod 的端口映射到节点物理机上,这种物理机和pod 的网络是一种桥接的模式
如上所示,此时tcp 列多了一个映射端口,现在集群外,通过访问node ip 加 该端口, 就能访问到后台的pod应用
我们创建一个标签选择器为webapp 的nginx3 pod 来实验下
[root@k8s-master1 test]# cat nginx3.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx3
labels:
app: webapp
spec:
containers:
- name: nginx
image: nginx:1.14.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
更改pod nginx3 的默认访问页,分别用clust IP和 node IP访问下:
最后一个知识点:
k8s 内部,由svc 名称构成的域名通过k8s dns 服务,比如core-dns 解析到集群ip 上
apiVersion: v1
kind: Pod
metadata:
name: busybox
labels:
app: webapp
spec:
containers:
- name: busybox
image: busybox:1.34
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
restartPolicy: Always