Kubernetes Service
# 1. Service 简介
# 1.1 什么是 Service
Kubernetes 中 Service 是 将运行在一个或一组 Pod 上的网络应用程序公开为网络服务的方法。
Kubernetes 中 Service 的一个关键目标是让你无需修改现有应用以使用某种不熟悉的服务发现机制。 你可以在 Pod 集合中运行代码,无论该代码是为云原生环境设计的,还是被容器化的老应用。 你可以使用 Service 让一组 Pod 可在网络上访问,这样客户端就能与之交互。
通俗定义: Service 用来为 pod 提供网络服务的一种方式。
# 1.2 为什么需要 Service
问题: 如果一组 Pod(称为“后端”)为集群内的其他 Pod(称为“前端”)提供功能, 那么前端如何找出并跟踪要连接的 IP 地址,以便前端可以使用提供工作负载的后端部分?

如果这是一个图片处理后端,它运行了 3 个副本。这些副本是可互换的 —— 前端不需要关心它们调用了哪个后端副本。 然而组成这一组后端程序的 Pod 实际上可能会发生变化, 前端客户端不应该也没必要知道,而且也不需要跟踪这一组后端的状态。 Service 定义的抽象能够解耦这种关联。

# 2. Service 特征
- Service 通过 label 关联对应的 Pod
- Servcie 生命周期不跟 Pod 绑定,不会因为 Pod 重新创建而改变 IP
- 提供了负载均衡功能,自动转发流量到不同 Pod
- 可对集群外部提供访问端口
- 集群内部可通过服务名字访问
# 3. Service 和 Pod 关系

# 4. Service 的使用
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 1
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
restartPolicy: Always
selector:
matchLabels:
app: nginx
---
apiVersion: v1
kind: Service # 使用 Service
metadata:
name: nginx
spec:
selector:
app: nginx
ports:
- port: 8080 # service 端口
targetPort: 80 # 容器端口
nodePort: 31001 # node 节点端口 固定在 30000-32767 之间
type: NodePort
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
注意:节点端口固定在
30000-32767之间
# 5. Service 多端口使用
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 1
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
restartPolicy: Always
selector:
matchLabels:
app: nginx
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app: nginx
ports: # 多端口
- port: 8080 # service 端口
name: write
targetPort: 80 # 容器端口
nodePort: 31001 # node 节点端口 固定在 30000-32767 之间
- port: 8081
name: read
targetPort: 80
nodePort: 31002
type: NodePort
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 6. Service Type(类型)
官网文档: https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/ (opens new window)
对一些应用的某些部分(如前端),可能希望将其暴露给 Kubernetes 集群外部的 IP 地址。
Kubernetes ServiceTypes 允许指定你所需要的 Service 类型。
ClusterIP:在集群内部暴露 Service,只能被集群内部的其他对象访问,通常用于内部服务发现,不会向集群外部暴露。NodePort:将 Service 暴露在 Node 的某个端口上,从而可以通过 Node 的 IP 地址和端口号来访问 Service,通常用于开发和测试环境。LoadBalancer:通过云服务商提供的负载均衡器来将 Service 暴露到公网上,使得外部用户可以访问 Service。ExternalName:将 Service 映射到一个 DNS 名称上,从而可以通过 DNS 名称来访问 Service,通常用于访问外部服务。
# 6.1 ClusterIP 类型
这是最常用的 Service 类型之一。在集群内部创建一个虚拟 IP 地址,它可以被其他在同一集群内的 Pod访问, 但不能被集群外部的请求所访问。这种类型的服务通常用于内部服务的暴露,例如数据库或者缓存服务。比如在一个 Web应用中, 你可能需要连接到一个数据库,但是这个数据库并不需要在应用之外暴露。这时候,你可以使用 ClusterIP 类型的Service, 让应用可以访问到数据库。
# 6.2 NodePort 类型
这种类型的 Service 将会创建一个端口,并绑定到每个集群节点上,从而允许
外部流量访问 Service。这个类型通常用于公共服务的暴露, 例如 Web 应用或者 API。比如你需要在集群外部访问到一个运行在集群中的 Web 应用,你就可以创建一个 NodePort 类型的 Service, 通过指定 Service 的nodePort字段,来将 Service 暴露给集群外部。如果你将
type字段设置为NodePort,则 Kubernetes 控制平面将在--service-node-port-range标志指定的范围内分配端口(默认值:30000-32767)。
# 6.3 LoadBalancer 类型
- 这种类型的 Service 类似于 NodePort,但是会在云厂商中创建一个
负载均衡器。这个类型通常用于在云平台上部署应用。云平台的负载均衡器将流量分发到集群中的节点。这个类型的 Service 只能在云平台上使用,并且需要云厂商提供支持。
# 6.4 ExternalName 类型
- 这种类型的 Service 允许 Service 到任何需要访问的 CNAME DNS 条目的转发。与其它类型的 Service 不同,
它并不会代理请求到任何 Pod。相反,它将请求转发到配置的外部地址。这种类型的 Service
通常用于将服务代理到集群外部的其他服务。 比如你有一个运行在外部网络上的服务,你希望在 Kubernetes 集群中使用该服务,这时候你可以创建一个 ExternalName 类型的 Service, 将服务的 DNS 解析到 Kubernetes 集群中。
# 7. 内部通信
# 7.1 创建 pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
labels:
app: mysql
spec:
selector:
matchLabels:
app: mysql
replicas: 1
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql/mysql-server:8.0
env:
- name: MYSQL_ROOT_PASSWORD
value: root
ports:
- name: mysql
containerPort: 3306
---
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
selector:
app: mysql
ports:
- name: mysql
port: 3306
targetPort: 3306
type: ClusterIP
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
hostNetwork: true
containers:
- name: nginx
image: nginx:latest
#command: ["/bin/sh", "-c"]
#args:
#- apt-get update && apt-get install -y mysql-client && nginx -g 'daemon off;'
ports:
- name: http
containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
app: nginx
ports:
- name: http
port: 8081
targetPort: 80
type: ClusterIP
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 7.2 相互访问
# step 1:进入 nginx
$ kubectl exec -it nginx -c nginx -- bash
# step 2:在 nginx 中访问 mysql 服务
$ mysql -h mysql -u root -p password
2
3
4
注意:这里的 mysql 是
MySQL Service的名称,而不是 Pod 的名称。