介绍
service 是 pod 与外界沟通的桥梁。service 本质上是一个网络服务。
功能:
与外部:外部环境无法直接与 pod 通信,中间隔着 宿主机,需要代理将 pod 挂到宿主机的某个端口上。
与内部:pod 一旦发生异常,重建, ip 就会发生改变。通过 ip 连是极其不稳定的,需要一个代理将 pod 地址代理过来。
描述文件
定义一个 最基本的 service 服务:
apiVersion: v1
kind: Service
metadata:
name: kubia
spec:
ports:
- port: 80 <-- 服务可用端口
targetPort: 8080 <-- 服务器将转发的端口
selector:
app: kubia <-- 具有 app=kubia 标签的 pod 都属于该服务
上述文件创建了一个名叫 kubia 的网络服务,它将在端口 80 接收请求并将连接路由到具有标签选择器是 app=kubia 的 pod 的 8080 端口上。
通过 kubectl get svc 可以查看到新建的服务。
上述描述文件的局限性: 该 service 只能在集群内部使用,集群内部的 pod 才能访问这组 pod。如果想要集群外部访问,需要加入更多的配置。
暴露多个端口
一个 service 暴露多个端口:
apiVersion: v1
kind: Service
metadata:
name: kubia
spec:
ports:
- name: http
port: 80 <-- pod 的 8080 端口 映射成 80 端口
targetPort: 8080
- name: https
port: 443 <-- pod 的 8443 端口 映射成 443 端口
target: 8443
selector:
app: kubia
使用命名端口
在 pod 中使用命名端口, service 服务中引用:
kind: Pod
spec:
containers:
- name: kubia
ports:
- name: http <-- 8080 端口命名为 http
containerPort: 8080
- name: https <-- 8443 端口命名为 https
containerPort: 8443
-----
apiVersion: v1
kind: Service
spec:
ports:
- name: http <-- 将端口 80 映射到容器中被称为 http 的端口
port: 80
targetPort: http
- name: https <-- 将端口 443 映射到容器中被称为 https 的端口
port: 443
targetPort: https
采用命名端口的方式优点:即使更换了端口号,也无需更改service 的 spec。
headless service
以上三个 service的配置,都可以通过 kubectl get svc -o wide -n namespace_name 看到这些 service 的 ip ,我们统称它们为 normal service。
在 service 中存在一种特殊的 service,它不需要 ip 的。
normal service 内部有自己的一套负载均衡策略,当访问该 service 时,它会根据负载均衡策略将其中一个 ip 发送给客户端。
但是在某些场景中,客户端想要和指定的的 pod 直接通信,或者 开发人员希望自己控制负载均衡的策略时,normal service 就不太适用了,可以试试 headless service。
Headless service 对应的 YAML 文件如下:
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
Headless Service 与 normal Service 中定义唯一不同的是 spec.clusterIP: None,也就是不需要 Cluster IP 的 Service ,即:这个 Service,没有一个 VIP 作为“头”。这也就是 Headless 的含义。所以,这个 Service 被创建后并不会被分配一个 VIP,而是会以 DNS 记录的方式暴露出它所代理的 Pod。
VIP 全称 virtual ip ,虚拟 ip。
按照这样的方式创建了一个 Headless Service 之后,它所代理的所有 Pod 的 IP 地址,都会被绑定一个这样格式的 DNS 记录:
<pod-name>.<svc-name>.<namespace>.svc.cluster.local
这个 DNS 记录,是 Kubernetes 项目为 Pod 分配的唯一的“可解析身份”(Resolvable Identity)。
有了这个“可解析身份”,只要知道了一个 Pod 的名字,以及它对应的 Service 的名字,就可以非常确定地通过这条 DNS 记录访问到 Pod 的 IP 地址。
当客户端访问 headless service 时,它会返回它所代理的所有 pod 的 ip,由客户端自己来决定访问哪个 pod。
除了 headless Service 这种特殊的 service 外, service 还有以下几种 hostNetwork 、hostPort、nodePort、loadBalancer 对外暴露的形式。根据不同的应用场景使用不同的类型。
hostNetWork service
[root@lk8s01 yaml]# cat end-nginx.yaml
apiVersion: v1
kind: pod
metadata:
name: nginx
labels:
app: web
spec:
hostNetwork: true
containers:
- name: ng-web
image: nginx:lastest
imagePullPolicy: Never
使用 hostNetwork 参数时,容器内部服务与宿主机处于同一网段。
特点 : 当 pod 调度到哪个节点就使用哪个节点的 ip 地址,客户端使用 ip 地址访问容器里面的服务。 一个 node 只能启动一个 pod 端口,端口不能冲突。
hostPort service
[root@k8s01 yaml]# cat end-nginx2.yaml
apiVersion: v1
kind: pod
metadata:
name: nginx2
labels:
app: web
spec:
containers:
- name: ng-web2
image: nginx:lastest
imagePullpolicy: Never
ports:
- name: http
containerPort: 80 -- 容器端口
hostPort: 80 -- 暴露端口
使用 hostPort 参数时,会将容器内端口暴露出来。
特点:pod 调度到哪个节点就用哪个节点的 ip 地址访问,端口可以随机指定。生产环境 pod 必须与宿机绑定才可使用。
NodePort service
[root@k8s01 yaml]# cat end-nginx3.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx3
labels:
api: web
spec:
containers:
- name: ng-web3
image: nginx:latest
imagePullPolicy: Never
ports:
- containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
name: ng-service
spec:
type: NodePort
ports:
- name: http
port: 80
nodePort: 31000
selector: -- 后端 pod 标签
api: web
// nodePort 参数,有 port 和 targetPort 的概念
port : 表示集群 IP 的端口号
targetPort : 表示背后 pod 的目标端口
nodePort:通过集群节点的 31000 端口可以访问该服务
使用 NodePort 参数时,会将service的类型设置成 NodePort:每个集群节点都会在节点上打开一个端口,对于 NodePort 服务,每个集群节点在节点本身(因此得名叫 NodePort)上打开一个端口,并将在该端口上接收到的流量重定向到基 础服务。
特点: 使用 node 节点的 IP ➕ 端口可以访问 pod 服务,master 节点 ip 不可以访问。端口范围 30000-32767。
LoadBalance service
[root@k8s01 yaml]# cat end-nginx4.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx4
labels:
app: web
spec:
containers:
- name: ng-web4
image: nginx:latest
imagePullPolicy: Never
ports:
- containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
name: ng-lb
ports:
- name: http
port: 80
selector:
app: web
status: -- 如果有 vip 就要写,没有就不用写
loadBalancer:
ingress:
- ip: 192.168.54.131
LoadBalance 是 NodePort 类型的一种扩展,可以使得服务通过一个专用的负载均衡器来访问,这是由Kubernetes中 正在运行的云基础设施提供的。负载均衡器将流量重定向到跨所有节点 的节点端口。客户端通过负载均衡器的IP连接到服务。
特点:必须使用云服务商提供一个 VIP 地址,只能 node 节点的 ip 地址访问,master 地址不能访问
通过 公开的 IP 地址,就会将所有连接重定向到服务。 如果在 不支持 Load Badancer 服务的环境中运行,则不会调配负载均衡器,该服务就如同一个 NodePort 服务。
其他访问 pod 的方法
1. 使用 kubectl expost 创建一个 service
2. 使用 kubectl port-forward 也可以配置端口转发
kubectl port-forward pod_name 8888:8080 执行完后,就将宿主机内部的 8080 端口,转发到 pod 内部的 8888 端口。
用 port-forward 命令做端口转发 适用于 测试特定 pod 的方法。如果持久性,则需要使用 service。