Service API是kubernetes的组成部分,它是一种抽象,邦族你将Pod集合在网络上公开出去。每个Service对象定义端点的一个逻辑集合(通常这些端点就是Pod)以及如何访问到这些Pod的策略。
例如,开了一个无状态的图像处理端,其中运行3个副本(Replicas)。这些副本是可互换的——前端不需要关心它们调用的是哪个后端,即便构成后端集合的实际Pod可能会发生变化,前端客户端不应该也没有必要知道这些,而且它们也不必亲自跟踪后端的状态变化。
Service抽象使这种解耦成为可能。
Service对应的Pod集合通常由你定义的标签来确定。
如果你的工作负载使用HTTP通信,你可能会选择使用Ingress来控制Web流量如何到达该工作负载。Ingress不是一种Service,但它可用作集群的入口点。Ingress能让你的路由规则整合到同一个资源内,这样你就能工作负载的多个组件公开出去,这些组件使用同一个侦听器,但各自独立运行在集群中。
type时使用的默认值。你可以使用Ingress或者Gateway API向公共互联网公开服务。
ClusterIP类型的基础上进行构建。.spec.clusterIP设置为"None"则Kubernetes不会为其分配IP地址。type: ClusterIP的Service。
type字段设置为NodePort,则Kubernetes控制平面将在--service-node-port-range标志所指定的范围内分配端口(默认值:30000-32767)每个节点将该端口(每个节点上的相同端口号)上的流量代理到你的Service。你的Service在其.spec.ports[*].nodePort字段中指定分配的对外访问的端口。type: NodePort服务type设置为"LadBanlancer",则平台会为Service提供负载均衡器。负载均衡器的实际创建过程是异步进行的,关于所制备的负载均衡器的信息将会通过Service的status.loadBalancer字段公开出来kubectl这类工具来替你发起这些API调用。app.kubernetes.io/name=MyApp标签。你可以定义一个Service来发布该TCP侦听器。[root@master ~]# vim service.yaml
apiVersion: "v1"
kind: Service
metadata:
name: my-service
spec:
# 标签选择器,意味着将会把流量路由到带有此标签的Pod上
selector:
app.kubernetes.io/name: MyApp
ports: # ports定义Service暴露的端口信息
- name: http # 为端口起个名字,可以清晰标识每个端口的作用
protocol: TCP # 指定了端口使用的协议,这里指定的是TCP
port: 80 # 定义Service对外暴露的端口
targetPort: 9376 # 定义如果访问到Service对外暴露的80端口,流量将会被路由到9376容器侦听端口上
# 应用上述清单时,系统将创建一个名为“my-service”的、服务类型默认为ClusterIP的Service。该Service指向带有标签"app.kubernetes.io/name: MyApp"的所有Pod的TCP端口9376
# Kubernetes为该Service分配一个IP地址(称为集群IP),供虚拟IP地址机制使用
# 此Service的控制器会不断操作与其选择算符匹配的Pod集合,然后对Service的EndpointSlice集合执行必要的更新。
# Service对象的名称必须是有效的RFC 1035标签名称
# 说明:Service能够任意入站,port映射到某个targetPort。默认情况下,出于方便考虑,targetPort会被设置为与port字段相同的值
# 加载资源
[root@master ~]# kubectl apply -f service.yaml
# 你可以使用此命令查看刚刚创建的Service对象
[root@master ~]# kubectl get svc my-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-service ClusterIP 10.96.239.56 <none> 80/TCP 30m
targetPort属性中引用这些名字。例如,我们可以通过以下方式将Service的targetPort绑定到Pod端口:[root@master ~]# vim service.yaml
apiVersion: "v1"
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
ports: # 定义容器要暴露的端口
- containerPort: 80 # 指定容器内部监听的端口
name: http-web-svc # 为这个端口指定一个名称,通过端口名称可以更灵活引用端口
---
apiVersion: "v1"
kind: Service
metadata:
name: nginx-service
spec:
selector: # 标签选择器
app: nginx # Service会把流量路由到带有app=nginx标签的Pod上
ports:
- name: name-of-service-port # 定义service端口名称
protocol: TCP # 指定网络协议
port: 80 # 定义service的端口号(对外暴露的端口)
targetPort: http-web-svc # 指定Pod中监听端口名称
# 即使在Service中混合使用配置名称相同的多个Pod,各Pod通过不同的端口号支持相同的网络协议,此机制也可以工作。这一机制为Service的部署和演化提供了较高的灵活性。例如,你可以在后端软件新版本中更改Pod的公开端口号,但不会影响到客户端。
# Service的默认协议是TCP;你还可以使用其他受支持的任何协议
# 由于许多Service需要公开多个端口,所以Kubernetes为同一Service定义多个端口。每个端口定义可以具有相同的protocol,也可以具有不同协议。
# 创建资源
[root@master ~]# kubectl apply -f service.yaml
# 查看pod和service资源
[root@master ~]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/nginx 1/1 Running 0 26m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d12h
service/nginx-service ClusterIP 10.109.37.65 <none> 80/TCP 26m
# 你可以通过刚刚查看到service的集群IP地址访问后端Pod
[root@master ~]# curl 10.109.37.65
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@master ~]# vim service.yaml
apiVersion: "v1"
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
ports: # 定义容器要暴露的端口
- containerPort: 80 # 指定容器内部监听的端口
name: http-web-svc # 为这个端口指定一个名称,通过端口名称可以更灵活引用端口
---
apiVersion: "v1"
kind: Service
metadata:
name: nginx-service
spec:
selector: # 标签选择器
app: nginx # Service会把流量路由到带有app=nginx标签的Pod上
ports:
- name: http # 定义service端口名称
protocol: TCP # 指定网络协议
port: 80 # 定义service的端口号(对外暴露的端口)
targetPort: http-web-svc # 指定Pod中监听端口名称
- name: https
protocol: TCP
port: 443 # Service对外暴露的端口
targetPort: 80 # 此处直接指定了Pod内部暴露的端口
# 创建资源
[root@master ~]# kubectl apply -f service.yaml
# 查看Pod和Service资源
[root@master ~]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/nginx 1/1 Running 0 36s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d12h
service/nginx-service ClusterIP 10.105.238.225 <none> 80/TCP,443/TCP 36s
# 你可以通过刚刚查看到service的集群IP地址访问后端Pod
# 访问http
[root@master ~]# curl 10.105.238.225:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
# 访问https
[root@master ~]# curl 10.105.238.225:443
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@master ~]# vim service_clusterip.yaml
apiVersion: "apps/v1"
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: test-nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: "v1"
kind: Service
metadata:
name: nginx
spec:
selector: # 标签选择器
app: nginx # 指定后端服务Pod,把流量路由到带有app=nginx的后端Pod上
type: ClusterIP
ports:
- port: 80 # 对外暴露80端口
targetPort: 80 # 此处填写容器真实暴露出来的端口,流量将会被路由到这个端口上
# 创建资源
[root@master ~]# kubectl apply -f service_clusterip.yaml
# 查看Pod和Service资源
[root@master ~]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/nginx-585dbbb7c7-hq98j 1/1 Running 0 115s
pod/nginx-585dbbb7c7-t6dh7 1/1 Running 0 115s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d13h
service/nginx ClusterIP 10.107.19.45 <none> 80/TCP 115s
# 你可以通过刚刚查看到service的集群IP地址访问后端Pod
# ClusterIP类型只能在集群内部访问
[root@master ~]# curl 10.107.19.45
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@master ~]# curl 10.107.19.45
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
.spec.ports.nodePort指定,或由Kubernetes再配置好的池里面分配(默认为30000-32767)即可从Kubernetes集群通过虚拟IP:端口访问也可以从集群外部通过Node节点的IP:nodePort访问# 以下是type: NodePort服务的一个清单示例,其中指定了NodePort值(本次案例为30007)
[root@master ~]# vim service_nodePort.yaml
apiVersion: "apps/v1"
kind: Deployment
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: "v1"
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
selector:
run: my-nginx # 定义标签选择器,将会把流量路由到带有run=my-nginx标签的pod上的端口上
type: NodePort
ports:
# 默认情况下,为了方便起见,'targetPort'被设置为与'port'字段相同的值
- port: 80
protocol: TCP
targetPort: 80
# nodePort可选字段
# 默认情况下,为了方便起见,kubernetes控制平面会从某个范围内分配一个端口号
# (默认情况:30000-32767)
nodePort: 30007
# 创建资源
[root@master ~]# kubectl apply -f service_nodePort.yaml
# 查看Pod和Service资源
# nodePor类型的Service可以从集群外部访问
[root@master ~]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/my-nginx-597fd96b76-hqvcv 1/1 Running 0 85s
pod/my-nginx-597fd96b76-vv8p9 1/1 Running 0 85s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d13h
service/my-nginx NodePort 10.107.85.136 <none> 80:30007/TCP 85s
# 你可以通过刚刚查看到service的集群IP地址访问后端Pod
# 访问的时候集群任意节点IP地址加上暴露出去的NodePort端口
C:\Users\Lenovo>curl http://192.168.93.145:30007
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
# 定义ExternalName类型的Service
apiVersion: "v1"
kind: Namespace
metadata:
name: dev
---
apiVersion: "v1"
kind: Pod
metadata:
name: nginx
namespace: dev
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: "v1"
kind: Service
metadata:
name: search
namespace: dev
spec:
type: ExternalName
externalName: www.baidu.com # 访问这个特定的service路径将会访问到www.baidu.com
# 创建资源
[root@master ~]# kubectl apply -f externalname-nginx.yaml
# 查看Pod和Service资源
[root@master ~]# kubectl get pod,svc -n dev
NAME READY STATUS RESTARTS AGE
pod/nginx 1/1 Running 0 6s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/search ExternalName <none> www.baidu.com <none> 4m26s
# 此时,在集群内部的Pod就可以通过search.dev.svc.cluster.local访问www.baidu.comle
# 下面验证一下,首先查看K8s内部使用的DNS地址
[root@master ~]# kubectl exec -it -n dev nginx -- cat /etc/resolv.conf
nameserver 10.96.0.10 # 这个就是k8s内部的DNS地址
search dev.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
# 然后使用dig命令验证
[root@master ~]# yum -y install bind-utils-9.11.4-26.P2.el7_9.16.x86_64
[root@master ~]# dig @10.96.0.10 search.dev.svc.cluster.local
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7_9.16 <<>> @10.96.0.10 search.dev.svc.cluster.local
; (1 server found)
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44519
;; flags: qr aa rd; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;search.dev.svc.cluster.local. IN A
;; ANSWER SECTION:
search.dev.svc.cluster.local. 30 IN CNAME www.baidu.com.
www.baidu.com. 30 IN CNAME www.a.shifen.com.
www.a.shifen.com. 30 IN A 220.181.38.150
www.a.shifen.com. 30 IN A 220.181.38.149
;; Query time: 57 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: 一 8月 05 22:51:59 CST 2024
;; MSG SIZE rcvd: 219