本章要点
- Service 的概念和原理
- ClusterIP 类型 service
- NodePort 类型的 service
- LoadBalancer 类型的 service
- ExternalName 类型的 service
- Service 的多端口设置
- Kubernetes 服务发现
前言
在当今的云计算和微服务架构中,Kubernetes(简称 K8s)已成为容器编排和管理的事实标准。通过它可将应用轻松部署到集群,确保高可用性和可扩展性。但应用部署后,如何将服务暴露给外部用户访问是关键问题。
传统架构中,用户访问内部服务需经 Nginx、Haproxy、LVS 等负载均衡工具或公有云的 SLB、ELB 等多层组件。Kubernetes 实现负载均衡和域名路由技术类似,只是名称和配置方式不同。
Kubernetes 中,Service 和 Ingress 是核心概念,分别用于实现负载均衡和域名路由。Service 为一组 Pod 提供稳定虚拟 IP,实现负载均衡和服务发现;Ingress 通过配置域名路由规则,让外部用户可通过域名访问集群服务。二者有效管理服务暴露和访问,保障应用的高可用性和可扩展性。
本章将详细介绍 Kubernetes 中 Service 的概念、工作原理及不同类型的应用场景,助读者深入理解如何通过 Service 将应用暴露给外部用户,实现高效负载均衡和服务发现。
一、Service 的定义
Service 是 Kubernetes 中的一种抽象,用于定义一组 Pod 及访问这组 Pod 的策略。其作用是将一组 Pod 封装为虚拟服务,提供统一入口供客户端访问,支持负载均衡、服务发现、服务暴露等功能。
Service 为一组提供服务的 Pod 抽象稳定网络访问地址,是 K8s 实现微服务的核心概念。通过 Service 定义的访问地址是 DNS 域名格式的服务名称,客户端应用网络访问方式不变。它还提供负载均衡器功能,将客户端请求负载分发到后端各 Pod。
Service 主要用于提供网络服务,通过定义为客户端应用提供稳定访问地址(域名或 IP 地址)和负载均衡功能,屏蔽后端 EndPoint 变化,是 Kubernetes 实现微服务的核心资源。
总之,Service 是 Kubernetes 中重要概念,用于将外部请求代理到内部 Pod,提供 4 层负载均衡和服务发现功能,构建高可用和可扩展的应用程序。
二、Service 工作原理
(一)service 基本原理介绍
Kubernetes 中,Pod 的 IP 地址动态变化,无法直接通过其 IP 访问。Service 为此创建虚拟 IP 地址,客户端请求该虚拟 IP 时,会被负载均衡到其中一个 Pod,完成访问。
Service 的实现依赖 kube-proxy 组件。它在每个节点监听 Service 变化,一旦变化就更新本地 iptables 规则,实现流量转发和负载均衡。
Service 还与 CoreDNS 有关。CoreDNS 是集群中的 DNS 解析服务,Service 的虚拟 IP 会注册到 CoreDNS,使客户端可通过 Service 名称访问其虚拟 IP。在 Service 定义中,可通过 spec.selector 字段指定属于该 Service 的 Pod,将请求负载均衡到这些 Pod。
总之,Service 是 Kubernetes 中重要的资源对象,让 Pod 对外提供服务,提供负载均衡、服务发现等功能。其实现依赖 kube-proxy 和 CoreDNS 组件,二者协作将 Service 与 Pod 连接,实现对 Pod 的代理访问。
(二)Service 的负载均衡机制
当 Kubernetes 集群中定义 Service 对象后,集群内客户端应用可通过服务 IP 访问具体 Pod 容器提供的服务。从服务 IP 到后端 Pod 的负载均衡机制由每个 node 上的 kube-proxy 代理实现。
Kubeproxy 的代理模式有:userspace、iptables、ipvs 和 kernelspace。
1. userspace
起初,kube-proxy 进程是真实的 TCP/UDP 代理。当 Pod 以 clusterIP 方式访问 Service 时,流量被 Pod 所在本机的 iptables 转发到本机 kube-proxy 进程,再转发到后端 Pod。具体过程为:
- kube-proxy 为每个 Service 在 node 上打开随机端口作为代理端口
- 建立 iptables 规则,将 clusterip 请求重定向到代理端口(用户空间)
- 到达代理端口的请求由 kubeproxy 转发到后端
由于 clusterip 重定向到 kube-proxy 服务过程存在内核态到用户态切换,开销大,故产生 iptables 模式,userspace 模式被废弃。
2. iptables
Kubernetes 从 1.2 版本开始将 iptables 模式作为默认模式,此模式下 kube-proxy 不再起 proxy 作用。其核心功能是通过 API Server 的 Watch 接口实时跟踪 Service 和 Endpoint 变更信息,并更新对应的 iptables 规则,Client 请求流量通过 iptables 的 NAT 机制 "直接路由" 到目标 Pod。
不同于 userspace,iptables 模式中 kube-proxy 不负责转发数据包,主要完成对 iptables 策略的动态管理。数据包走向由 iptables 规则决定,无内核态到用户态切换,效率高。但随着 Service 增加,iptables 规则增多,导致内核繁忙(如同读无索引的大表)。
3. ipvs
从 Kubernetes 1.8 版本引入第三代的 IPVS 模式,它基于 netfilter 实现,但定位不同:iptables 为防火墙设计,IPVS 专门用于高性能负载均衡,使用高效数据结构 Hash 表,允许几乎无限规模扩张。
ipvs 为负载均衡提供更多算法:rr(轮训)、lc(最小连接数)、df(目标哈希)、sh(源哈希)、sed(预计延迟最短)、nq(从不排队)。
可将 ipset 简单理解为 ip 集合,内容可为 IP 地址、IP 网段、端口等,iptables 可直接添加规则对其操作,减少 iptables 规则数量,降低性能损耗。
若操作系统未启用 IPVS 内核模块,kube-proxy 自动运行为 iptables 模式;若启用,则运行为 ipvs 模式。查看系统是否开启 ipvs 模块,可用命令:lsmod | grep ip_vs。
4. kernelspace
这是 Windows Server 上的代理模式,此处不介绍。
(三)service 的 4 种类型
Kubernetes 支持 4 种 service 类型。
1. ClusterIP
这是最常用的 Service 类型,为 Pod 提供虚拟 IP 地址。其他 Pod 访问该 Service 时,使用此虚拟 IP 即可,Kubernetes 自动将请求路由到相应 Pod。
2. NodePort
该 Service 类型将 Pod 公开为集群中所有节点上的某个端口。外部请求到达任一节点的该端口时,Kubernetes 将请求路由到相应 Pod。
3. LoadBalancer
LoadBalancer Service 使用云提供商的负载均衡器将请求路由到后端 Pod。Kubernetes 自动创建和配置负载均衡器,并绑定到 Service。
4. externalName
ExternalName Service 允许将 Service 映射到集群外部的某个名称。Pod 访问该 Service 时,使用该名称解析出相应 IP 地址。
三、生成用于测试 service 的 Deployment
编写 Deployment 用于各种 service 的验证。
应用 Service 概念前,先创建提供 web 服务的 Pod 集合,由两个 Tomcat 容器副本组成,每个容器服务端口为 8080。
(一)编辑 deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
replicas: 2 ##pod的副本数
selector: ##目标Pod的标签选择器,
matchLabels: ##需要匹配的标签
app: webapp ##对应目标pod的标签名称
template: ##自动创建新pod副本的模板
metadata:
labels: ##定义pod的标签
app: webapp ##标签值为app:webapp
spec:
containers:
- name: webapp
image: kubeguide/tomcat-app:v1
ports:
- name: http
containerPort: 8080
protocol: TCP
selector(选择器)用于资源匹配,只有符合条件的资源才会被调用或使用,可对集群各类资源进行分配。Kubernetes 中核心资源 Deployment、StatefulSet 管理的 Pod 由选择器字段决定,通过 Service 访问后端 Pod 也由选择器字段决定。
label(标签)可对 Kubernetes 其他资源配置,当对系统 API 对象如 Pod 分组时,添加标签以精准选择对应 API 对象。
(二)创建该 Deployment
[root@k8s-master ~]# kubectl create -f webapp-deployment.yaml
(三)查看 pod 创建情况
[root@k8s-master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
webapp-8554f77548-9xwmm 1/1 Running 0 93s
webapp-8554f77548-jrw7f 1/1 Running 0 93s
(四)查看各个 pod 的 IP 地址
[root@k8s-master ~]# kubectl get pods -l app=webapp -o wide
NAME READY STATUS RESTARTS AGE IP NODE
NOMINATED NODE READINESS GATES
webapp-8554f77548-9xwmm 1/1 Running 0 2m55s 172.17.125.3 k8s-node01 <none> <none>
webapp-8554f77548-jrw7f 1/1 Running 2m55s 172.27.14.195 k8s-node02 <none> <none>
(五)访问这两个地址
[root@k8s-master~]# curl 172.17.125.3:8080
[root@k8s-master ~]# curl 172.27.14.195:8080
四、service 的创建
(一)创建一个 clusterIP 类型 service
描述:ClusterIP 是默认 Service 类型,创建虚拟 ClusterIP 地址,用于集群内部访问 Service。
使用场景:适用于集群内部服务通信,如连接前端和后端服务供内部其他服务使用。
1. 方法一:通过 expose 命令创建 ClusterIP 类型的 Service
为让客户端应用访问前面创建的两个 Tomcat Pod 实例,需创建 Service 提供服务。k8s 提供快速方法,即通过 kubectl expose 命令创建 Service。
(1) 执行 expose 命令暴露端口
[root@k8s-master ~]# kubectl expose deployment webapp
(2) 查看创建的 Servic
[root@k8s-master~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 9d
webapp ClusterIP 10.104.162.209 <none> 8080/TCP 32s
可见系统分配了虚拟 IP 地址,Service 端口号从 pod 复制而来,可通过该虚拟 IP 和端口号访问 Service。
(3) 访问测试
[root@k8s-master~]# curl 10.104.162.209:8080
客户端对 Service 的访问自动负载分发到后端两个 pod 之一。Kubernetes 自动完成请求转发到后端多个 EndPoint 的负载分发,通过负载均衡机制实现分布式应用统一入口,免去客户端获知后端服务实例列表和变化的复杂度。
(4) 删除此 Service
[root@k8s-master ~]# kubectl delete service webapp
2. 方法二:使用 yaml 文件创建 Service
除用 expose 命令创建 Service,更便于管理的是用 yaml 文件创建。
(1) 编辑 service 文件
apiVersion: v1
kind: Service
metadata:
name: webapp
spec:
ports:
- protocol: TCP
port: 8080
targetPort: 8080
selector:
app: webapp
本案例中 ports 定义 Service 本身端口号 8080(供外部用户访问),targetPort 指定后端 Pod 容器端口号,selector 定义后端 Pod 拥有的 label。
(2) 利用 yaml 创建此服务
[root@k8s-master ~]# kubectl create -f webapp-service.yaml
(3) 查看创建的 Service,并访问测试
[root@k8s-master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 9d
webapp ClusterIP 10.108.79.50 <none> 8080/TCP 9s
[root@k8s-master ~]# curl 10.108.79.50:8080
(4) 查看 EndPoint 列表
Service 对应的后端由 Pod 的 IP 地址和容器端口号组成,即完整的 IP:Port 访问地址,在 k8s 中叫 EndPoint。查看 Service 详细信息可看到后端 EndPoint 列表
[root@k8s-master ~]# kubectl describe svc webapp
Name: webapp
Namespace: default
Labels: <none>
Annotations : <none>
Selector: app=webapp
Type: ClusterIP
IP Family Policy: SingleStack
IP Families : IPv4
IP: 10.108.79.50
IPs: 10.108.79.50
Port: <unset>8080/TCP
TargetPort: 8080/TCP
Endpoints: 172.17.125.4:8080,172.27.14.196:8080
Session Affinity: None
Events: <none>
(5) 查看 EndPoint 资源对象
实际上 k8s 自动创建了与 Service 关联的 EndPoint 资源对象,可通过 EndPoint 对象查看
[root@k8s-master ~]# kubectl get endpoints
NAME ENDPOINTS AGE
kubernetes 192.168.10.101:6443 9d
webapp 172.17.125.4:8080,172.27.14.196:8080 6m19s
(6) 删除这个 Service
[root@k8s-master ~]# kubectl delete -f webapp-service.yaml
或
[root@k8s-master ~]# kubectl delete service webapp
(二)创建 NodePort 类型的 service
NodePort 在每个节点公开一个端口,将流量转发到 Service。它创建 ClusterIP,并将指定端口映射到每个节点的相同端口。
这种 service 适用于需从外部访问集群服务时,可通过节点 IP 和映射端口访问,对开发和测试环境有用。
(1) 创建 Service 文件
设置 Service 类型为 NodePort,设具体 nodePort 端口号为 30008
apiVersion: v1
kind: Service
metadata:
name: webapp
spec:
type: NodePort
ports:
- port: 8080
targetPort: 8080
nodePort: 30008
selector:
app: webapp
各关键字含义:
- port:8080:Service 内部端口,客户端请求发送到此端口,由 Kubernetes 负载均衡到后端 Pods。
- targetPort:8080:指向后端 Pods 实际容器端口,流量通过 Service 到达后端 Pods 时转发到此端口。
- nodePort:30008:每个节点打开的端口,用于外部流量进入集群,外部客户端可通过<node-ip>:<node-port>访问该 Service。
nodePort 端口范围在 1.23.6 版本中为 30000-32767。
(2) 创建此 Service
继续用刚才的 webapp 的 Deployment,为此 Deployment 创建 NodePort 类型的 service。
[root@k8s-master~]# kubectl create -f webapp-svc-nodeport.yaml
(3) 查看创建的 Service
[root@k8s-master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 9d
webapp NodePort 10.98.184.252 <none> 8080:30008/TCP 119s
(4) 在 windows 宿主机上用浏览器测试访问
http://192.168.10.101:30008
因 NodePort 方式在每个 Node 节点创建该端口,故在任一节点用 netstat -anpt| grep30008 命令查询都可见此端口,访问时 IP 地址可用任一主机 IP。
(5) 删除该 Service
[root@k8s-master~]# kubectl delete -f webapp-svc-nodeport.yaml
(三)创建 LoadBalancer 类型的 service
通常在公有云环境中用 LoadBalancer 类型,可将 Service 映射到公有云提供的负载均衡器 IP 地址,客户端通过负载均衡器 IP 和 Service 端口号访问具体服务。
描述:LoadBalancer 为 Service 创建外部负载均衡器,分配外部 IP 地址,通常由云提供商的负载均衡服务实现。
使用场景:适用于需将流量从外部负载均衡器分发到集群内部服务,如在生产环境暴露 Web 应用程序。
(1) 编写 LoadBalancer 类型的 Service 文件
apiVersion: v1
kind:Service
metadata:
name:webapp
namespace: default
labels:
app:webapp
spec:
type:LoadBalancer
ports:
- port:8080
targetPort:http
protoco1:TCP
name:http
nodePort:31771 ##没有此参数,系统会自动指定一个随机端口
selector:
app:webapp
这个 Service 创建好后,云服务商会在 Service 定义中补充 LoadBalancer 的 IP 地址,之后就可以在客户端访问该 Service 了。nodePort 的端口范围在 30000-32767 之间。
(2) 创建此 Service
[root@k8s-master ~]# kubectl create -f webapp-svc-loadbalancer.yaml
(3) 查看创建结果
[root@k8s-master~]#kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 9d
webapp LoadBalancer 10.111.51.212 <pending> 8080:31458/TCP 2m56s
(4) 在 windows 宿主机上访问
A不安全|192.168.10.101:31458
Documentation Configuration Examples Wiki Mailing Lists Find Help
Apache Tomcat/8.0.35 The Apache Software Foundation
If you're seeing this,you've successfully installed Tomcat.Congratulations!
Recommended Reading: Server Status
Securty Considertions HOW.TO Manager Application HOW-TQ Manager App
Clustering/Session Replication HOW-TO Host Manager
Developer Quick Start sat Set
Fint Web Agdiction Examples Servlet Specliceion Tomcat Versions
(5) 删除此 Service
[root@k8s-master ~]#kubectl delete -f webapp-svc-loadbalancer.yaml
4:创建 ExternalName 类型的 service
ExternalName 允许 Service 通过返回 CNAME 记录来引用集群外部的服务。它没有 ClusterIP, NodePort 或 LoadBalancer。
适用于需要将 K8s 内部的服务与集群外的现有服务进行关联,例如连接到外部的数据库或其他资源。
ExternalName 类型是 Service 的特例,用于将集群外的服务定义为 Kubernetes 的集群 Service, 并通过 ExternalName 字段指定外部服务的地址,可以使用域名或 IP 格式。集群内客户端应用通过访问这个 Service 就能访问外部服务了。他没有选择器,没有定义任何端口和 EndPoint, 他通过返回该外部服务的别名来提供服务。
也可以用于两个不同的 namespace 之间的不同 pod 可以通过 name 的形式访问。
两个不同的命名空间中的 pod, 可以直接使用他们的 IP 地址进行通信,但是 pod 的 IP 地址是随机分配的,重建 pod 后其 IP 地址就改变了,因此我们要用 pod 对应的 service 名称进行通信。但是跨命名空间是不能解析其他命名空间中创建的 service 名称的。这个时候就可以使用 ExternalName 实现两个不同命名空间中的各个 pod 间的通信。接下来,我们一两个命名空间内 Pod 之间的访问为例,讲解 ExternalName 的使用方法。
(1) 创建案例所需的两个命名空间
[root@k8s-master ~]# kubectl create namespace test01
[root@k8s-master ~]# kubectl create namespace test02
(2) 第一个 Pod
-
创建命名空间为 test01 的 Pod
apiVersion:apps/v1
kind: Deployment
metadata:
name:myapp01
namespace:test01
spec:
replicas:1
selector: #标签选择器
matchLabels:#匹配的标签为
app:myapp01
release:canary
template:
metadata:
labels:
app:myapp01 #和上面的myapp要匹配
release:canary
spec:
containers:- name: myapp
image: ikubernetes/myapp:v1
ports: - name: http01
containerPort:80
[root@k8s-master ~]# kubect1 create -f myapp01.yaml
- name: myapp
-
创建一个无头 (headless) Service
apiVersion:v1
kind:Service
metadata:
name:myapp-svc01
namespace:test01
spec:
selector:
app:myapp01#挑选的pod还是myapp01。一个pod可以有多个service
release:canary
clusterIP:None #None表示是无头service
ports:
-port:39320#serviceip中的端口
targetPort:80#容器ip中的端口
(Headless Service) 无头 Service: 这种服务没有入口地址 (没有 ClusterIP),kube-proxy 无头服务创建出来之后,对于其他外部的 pod 来讲,该 pod 对应的名字就确定了下来,其固定的格式是:无头服务名。命名空间.svc.cluster.local
[root@k8s-master~]#kubectl create -f myapp-svc-headless01.yaml
-
创建 extername
kind: Service
apiVersion: v1
metadata:
name: myapp-svcname02
namespace: test01
spec:
type:ExternalName
externa1Name: myapp-svc02.test02.svc.c1uster.1ocal
关键字段的含义:
-
name:myapp-svcname02 指的是外部的服务名称
-
myapp-svc02.test02.svc.cluster.local 对方无头服务的名字,对方命名空间的名字.svc.cluster.local
[root@k8s-master~]#kubectl create -f myapp-svc-extername01.yaml
[root@k8s-master ~]#ku get svc -n test01
NAME
TYPE
CLUSTER-IP
EXTERNAL-IP
PORT(S)
AGE
myapp-svc01
ClusterIP
None
<none>
39320/TCP
6m19s
yapp-svcname02 Externa1Name
<none>
myapp-svce2.test02.svc.cluster.1ocal
<none>
55s
(3) 创建第二个 Pod
-
创建命名空间为 test02 的 Pod
apiVersion:apps/v1
kind:Deployment
metadata:
name:myapp02
namespace:test02
spec:
replicas:1
selector:#标签选择器
matchLabe1s:#匹配的标签为
app: myapp02
release:canary
template:
metadata:
labels:
app:myapp02#和上面的myapp要匹配
release:canary
spec:
containers:
name:myapp02
image:ikubernetes/myapp:v1
ports:
name:http02
containerPort:80[root@k8s-master ~]#kubectl create-f myapp02.yaml
-
创建一个无头 (headless) Service
apiVersion: v1
kind:Service
metadata:
name: myapp-svc02
namespace:test02
spec:
selector:
app: myapp02 #挑选的pod还是myapp。一个pod可以有多个service
release: canary
clusterIP:None#None表示是无头service
ports:
port:39320 #serviceip中的端口
targetPort:80 #容器ip中的端口[root@k8s-master ~]# kubect1 create-f myapp-svc-headless02.yaml
-
创建 extername
kind:Service
apiVersion:v1
metadata:
name:myapp-svcname01
namespace: test02
spec:
type:ExternalName
externalName: myapp-svc01.test01.svc.cluster.1ocal
备注: name:myapp-svcname01 指的是外部的服务名称
[root@k8s-master ~]#kubectl create -fmyapp-svc-extername02.yaml
(4) 验证 Pod 间的通信
查看命名空间为 test01 的 Pod
[root@k8s-master~]#kubectl get pods -n test01 NAME READY STATUS RESTARTS AGE myapp01-696c886d6b-tq7vv 1/1 Running 0 54s
[root@k8s-master~]#kubectl exec-it myapp01-696c886d6b-tq7vv -n test01--/bin/sh
/#nslookup myapp-svcname02 /#ping myapp-svcname02 PING myapp-svcname01 (172.17.125.3):56 data bytes 64 bytes_from 172.17.125.3:seq=0tt1=62time=0.903ms 64 bytes from 172.17.125.3:seq=1 tt1=62 time=3.139ms
/#nslookup myapp-svc02.test02.svc.cluster.local /#ping myapp-svc02.test02.svc.cluster.1ocal PING myapp-svc02.test02.svc.cluster.local (172.17.125.3):56 data bytes 64 bytes from 172.17.125.3:seq=0tt1=62time=1.240ms
64 bytes from 172.17.125.3:seq=1tt1=62time=2,462ms
[root@k8s-master~]#kubectl get pods -n test02-0wide
NAME
READY
STATUS
RESTARTS
AGE
IP
NODE
NOMINATED NODE
READINESS GATES
myapp-6bb4786bcd-hsr28
1/1
Running
0
7m31s
172.17.125.3
k8s-node01
<none>
<none>
[root@k8s-master~]#kubectl get pods -n test01
-o wide
NAME
READY
STATUS
RESTARTS
AGE
IP
NODE
NOMINATED NODE READINESS GATES
myapp01-696c886d6b-tndns
1/1
Running
0
9m30s
172.25.244.197
k8s-master01
<none>
<none>
查看命名空间为 test02 的 Pod
[root@k8s-master~]#kubectl get svc-n test02-0wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
AGE SELECTOR
myapp-SVc ClusterIP None <none>
39320/TCP 7m25s app=myapp,release=canary
myapp-svcname ExternalName <none> myapp-svc.test02.svc.cluster.1ocal
<none> 6m45s <none>
[root@k8s-master ~]#kubectl get svc -n testo1-0wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
AGE SELECTOR
myapp-svc ClusterIP None <none>
39320/TCP 10m app=myapp,release=canary
myapp-svcname ExternalName <none> myapp-svc.test02.svc.cluster.1ocal
<none>
9m59s
<none>
五:service 的其他应用
1:Service 的多端口设置
一个容器应用可以提供多个端口的服务,在 Service 的定义中也可以相应的设置多个端口号。
(1) 创建 service 文件
apiVersion:v1
kind: Service
metadata:
name:webapp
spec:
ports:
- port:8080
targetPort:8080
name:web
protocol:TCP
- port:8005
targetPort:8005
name:management
protocol:TCP
selector:
app:webapp
注意:selector 中的 app:webapp 的标签对应的是 webapp-deployment.yaml 中的 pod 的标签
(2) 创建 service
[root@k8s-master ~]#kubectl create -f service-multiple-ports.yaml
(3) 查看 EndPoint 列表
[root@k8s-master~]#kubectl describe svc webapp
(4) 查看创建的 Service
[root@k8s-master~]# kubect1 get svc webapp
(5) 删除这个 Service
[root@k8s-master ~]#kubect1 delete -f webapp-service.yaml
或
[root@k8s-master~]#kubectl delete service webapp
2:Kubernetes 服务发现
服务发现机制是指客户端如何在一个 kubernetes 集群中获知后端服务的访问地址。
Kubernetes 的服务发现有两种方式:环境变量和 DNS
(1) 基于环境变量的服务发现
当 Pod 部署到一个 node 节点后,该 node 节点上的 kubelet 会在该 pod 内部设置一组环境变量,这些环境变量是根据活跃的 Service 生成的,所以,要使用基于环境变量的服务发现,需要先创建对应的 Service 后再创建所需的 Pod。在一个 Pod 运行起来的时候,系统会自动为其容器运行环境注入所有集群中有效 Service 的信息,Service 的相关信息包括服务 IP、服务端口号、各端口号相关的协议等。然后,客户端应用就能够根据 Service 相关环境变量的命名规则,从环境变量中获取需要访问的目标服务 (Pod) 的地址了。
先创建出之前用的 service
[root@k8s-master ~]# kubect1create -f service-multiple-ports.yaml
[root@k8s-master ~]# kubectl create -f webapp-deployment.yaml
[root@k8s-master ~]#kubectl get pod
NAME
READY STATUS
RESTARTS
AGE
webapp-86b5d9fc88-Cv6qq
1/1
Running0
82s
webapp-86b5d9fc88-s4smp
1/1
Running
0
82s
任意的 Pod 都会根据这些 Service 创建一组变量用于服务发现。
[root@k8s-master ~]#kubectlexec-it webapp-86b5d9fc88-cv6qq--env
PATH=/usr/1ocal/tomcat/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTAME=webapp-86b5d9fc88-cv6qq
TERM=xterm
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
MYNGINX_SERVICE_PORT_HTTP=80
MYNGINX_PORT_ 80 TCP_PORT=80
MYNGINX_PORT_80_TCP_ADDR=10.109.164.93
KUBERNETES_ PORT_443_TCP_PORT=443
MYNGINX_SERVICE_PORT=80
MYNGINX PORT_80_TCP=tcp://10.109.164.93:80
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_ TCP_ ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
MYNGINX_PORT_80_TCP_PROTO=tcp
KUBERNETES_ PORT=tcp://10.96.0.1:443
MYNGINX_SERVICE_HOST=10.109.164.93
MYNGNX_POR=tcp://10.109.164.93:80
LANG=C.UTF-8
JAVA_HOME=/usr/1ib/jvm/java-7-openjdk-amd64/jre
JAVA_VERSION=7u101