Service是Kubernetes最核心的概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求进行负载分发到后端的各个容器应用上。
1、Service的四种类型
1、ClusterIP: 默认类型,自动分配一个仅cluster内部可以访问的虚拟ip。
2、NodePort: 在clusterip基础上为service在每台机器上绑定一个端口,这样就可以通过Nodeip:port方式来访问该服务。
3、LoadBalancer:在NodePort基础上,接触cloud provider创建一个外部负载均衡器,并将请求转发到nodeip:port。
4、ExternalName: 把集群外部的服务引入到集群内部,在集群内中直接使用,没有任何类型的代理被创建。
Endpoint 介绍:
Endpoint是可被访问的服务端点,即一个状态为running的Pod,它是Service访问的落点,只有Service关联的Pod才可能成为Endpoint。
Endpoint、Service 和 Pod 的关系:
Endpoints表示一个Service对应的所有Pod副本的访问地址。
Node上的Kube-proxy进程获取每个Service的Endpoints,实现Service的负载均衡功能。
ReplicaSet参数控制Pod的数量,ReplicaSet被Deployment配置文件管理。
Deployment控制Pod应用的升级、回滚,当然也能控制pod的数量。
Service为同一类label的Pod提供一个统一固定入口,负责将前端请求均衡的转发给Pod中。
2、Service 部署
1、创建Deployment + ClusterIP Service
apiVersion: apps/v1
# 声明一个Deployment资源对象
kind: Deployment
metadata:
# 定义 pod 名称
name: demo1-nginx-deployment
spec:
# 通过 replicas 声明 pod 个数是4
replicas: 4
# 通过标签选择被控制的 pod
selector:
matchLabels:
name: demo-nginx
# 在 template 中定义 pod
template:
metadata:
# 给pod打上标签
labels:
name: demo-nginx
type: pod
release: stable
spec:
containers:
# 声明容器名称,注意不是pod名称,pod名称应该定义在metadata中
- name: demo-nginx-container
image: nginx
ports:
- name: http
containerPort: 80
# 在一个yaml文件中通过---分割多个资源对象
---
apiVersion: v1
# 声明一个Service资源对象
kind: Service
metadata:
name: demo1-nginx-service
labels:
name: demo-nginx
type: clusterip
release: stable
spec:
# 设置 nodePort 映射到物理机,同时这是Service的类型为nodePort
# 如果不设置 type 则为默认的 ClusterIP 类型
# type: NodePort
# demo1-nginx-service 选择标签包含 demo-nginx 的pod
selector:
name: demo-nginx
ports:
- protocol: TCP
name: http
# service 的监听端口
port: 80
# 转发到 pod 的端口
targetPort: 80
# 暴露在服务器上的端口
# nodePort: 30080
[root@k8s-1 k8s-yaml]# kubectl apply -f test-service.yaml
deployment.apps/demo1-nginx-deployment created
service/demo1-nginx-service created
查看容器状态:
使用 kubectl describe svc demo1-nginx-service
查看 demo1-nginx-service
的详细信息,我们可以知道 demo1-nginx-service
的 IP是10.98.135.41,访问 10.98.135.41:80 会将请求转发到 10.244.1.47:80,10.244.2.46:80,10.244.2.47:80 + 1 more...
四个 real server 上。
测试服务是否可用:
2、创建Deployment + NodePort Service
将上方 ClusterIP Service 的yaml配置文件添加两行配置。可以将ClusterIP升级为NodePort Service。
Service.spec.type
# 设置 nodePort 映射到物理机,同时这是Service的类型为nodePort
type: NodePort
Service.spec.ports.nodePort
# 暴露在服务器上的端口
nodePort: 30080
使用NodePort类型,将服务暴露出来,可以通过 http://ip:30080 来进行访问
tips:
1、对于Service 的升级操作,从ClusterIP升级为NodePort是可以的,但是不建议从NodePort降级为ClusterIP,容易发生问题,建议重新创建。
2、因为Service其实是iptables或ipvs的转发规则,不支持ICMP协议,所以是没有办法ping通的。
3、LoadBalancer
LoadBalancer 和 NodePort 其实是同一种方式。区别在于 loadBalancer 比 nodePort 多了一步,就是可以调用 cloud provider 去创建 LB 来向节点导入流量。
4、ExternalName
这种类型的 Service 通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容( 例如:www.baidu.com )。ExternalName Service 是 Service 的特例,它没有 selector,也没有定义任何的端口和 Endpoint。相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务。
apiVersion: v1
kind: Service
metadata:
# svc 的名称,也是内部访问的域名
name: test-external
# 标签
labels:
name: test-external
type: externalname
release: stable
# 所属命名空间
namespace: default
spec:
# Service 的类型
type: ExternalName
# 外部地址,可以使用ip或者域名
externalName: www.baidu.com
检测 ExternalName 是否ok:
[root@k8s-1 k8s-yaml]# kubectl run test-pod -it --rm --image=busybox:1.28.3 -n default
/ # nslookup test-external
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: test-external
Address 1: 163.177.151.110
Address 2: 163.177.151.109
# 163.177.151.110、163.177.151.109 就是百度的ip
当查询主机 test-external 时,集群的 DNS 服务将返回一个 CNAME 记录。访问这个服务的工作方式和其他的相同,唯一不同的是重定向发生在 DNS 层,而且不会进行代理或转发。