kubernetes 的Service
Service概念:
Kubernetes中的 Pod是有生命周期的,它们可以被创建,也可以被销毁,然而一旦被销毁pod生命就永远结束,这个pod就不存在了,通过ReplicaSets能够动态地创建和销毁Pod(例如,需要进行扩缩容,或者执行滚动升级),每个Pod都会获取它自己的 IP 地址,这些IP地址并不是一直处于稳定的状态,可能随时改变。 在 Kubernetes 集群中,如果一组Pod(称为 backend)为其它Pod (称为 frontend)提供服务,那么那些 frontend(pod) 通过设置的标签来绑定service,进而对外提供网络服务
关于Service
Kubernetes Service定义了这样一种抽象:逻辑上的一组Pod,一种可以访问它们的策略-通常称为微服务。 这一组Pod能够被Service访问到,通常是通过Label Selector实现的。举个例子,考虑一个图片处理程序 backend,它运行了3个副本。这些副本是可互换的 —— frontend 不需要关心它们调用了哪个 backend 副本。 然而组成这一组 backend 程序的 Pod 实际上可能会发生变化,frontend 客户端不应该也没必要知道,而且也不需要跟踪这一组 backend 的状态。 Service 定义的抽象能够解耦这种关联。
例如想要用nginx反向代理tomcat,那么tomcat如果是通过pod部署的,pod的ip可能会随时变化,那么我们就需要在所有这些部署tomcat的pod前面加上一个固定接入层service,我们nginx反向代理只需要写service地址,就会代理到后端的pod,那么pod就算ip怎么变化,通过service都可以找到,对 Kubernetes 集群中的应用,Kubernetes 提供了简单的Endpoints API,只要Service中的一组Pod发生变更,应用程序就会被更新。 对非 Kubernetes 集群中的应用,Kubernetes 提供了基于 VIP 的网桥的方式访问Service,再由Service重定向到backend Pod。
简单归纳一下
service是一个固定接入层,客户端可以通过访问service来访问到service关联的后端pod,这个service工作依赖于在kubernetes集群之上部署的一个附件,就是kubernetes的dns服务(不同kubernetes版本的dns默认使用的也是不一样的,1.11之前的版本使用的是kubeDNs,较新的版本使用的是coredns),service的名称解析是依赖于dns附件的,因此在部署完k8s之后需要在部署dns附件,kubernetes要想给客户端提供网络功能,需要依赖第三方的网络插件(flannel,calico等)。
在kubernetes集群中有三类ip地址:node network(节点网络),pod network(pod 网络),这两种网络地址是我们实实在在配置的,其中节点网络地址是配置在节点接口之上,而pod网络地址是配置在pod资源之上的,因此这些地址都是配置在某些设备之上的,这些设备可能是硬件,也可能是软件模拟的,cluster network(集群地址,也成为service network),这个地址是虚拟的地址(virtual ip),没有配置在某个接口上,只是出现在service的规则当中。
每个K8s节点上都有一个工作的组件叫做kube-proxy,kube-proxy这个组件将始终监视着apiserver中有关service资源的变动信息,需要跟master之上的apiserver交互,随时连接到apiserver上获取任何一个与service资源相关的资源变动状态,这种是通过kubernetes中固有的一种请求方法watch(监视)来实现的,一旦有service资源的内容发生变动(如创建,删除),kube-proxy都会将它转化成当前节点之上的能够实现service资源调度,把我们请求调度到后端特定的pod资源之上的规则,这个规则可能是iptables,也可能是ipvs,取决于service的实现方式
service实现方式
第一种:iptables
客户端ip请求时直接请求service的ip,这个请求报文被本地内核空间中的service规则所截取,进而直接调度给相关的pod,这个方式是直接工作在内核空间,由iptables规则直接实现
第二种:ipvs
客户端请求到达内核空间之后直接由ipvs规则来调度到相关的pod资源
1.11之前的版本使用的是iptables
1.11+版本使用的是ipvs,ipvs如果没有被激活就会自动降级为iptables
如果某个服务背后的pod资源发生改变,比如service的标签选择器适用的pod又多了一个,这个pod使用的信息会立即反应在apiserver上,kube-proxy能监听到这个service的变化,将其立即转为service规则(如iptables规则)
编写server yaml 文件
[root@master-1 kongzhiqi]# cat deployment.yaml
apiVersion: apps/v1 #api版本
kind: Deployment #资源类型
metadata: #源数据
name: deployment #控制器名字
namespace: deployment # 所在的名称空间
labels: # 标签的设置
dev: deployment-test
spec: # 控制器期望状态
minReadySeconds: 4 # 等待就绪时间
revisionHistoryLimit: 5 # 保留的历史版本
replicas: 3 # pod 个数
strategy: # 更新策略
rollingUpdate: # 选择更新方式
maxSurge: 5 # 最大的pod 数量比pod个数多
maxUnavailable: 1 # 最大不可用的pod 数量
selector: # 标签选择器
matchLabels: # 标签选择器设定
dev: deployment-test # 标签的key与值的设定
template: # pod 属性定义
metadata: # 元数据
labels: # 标签设定
dev: deployment-test # 标签的key 与值
spec: # pod 的期望状态
containers: # 容器的属性定义
- name: web # 容器的名字
image: nginx:1.8.1 # 运行的镜像
imagePullPolicy: IfNotPresent # 获取镜像策略
ports: # 端口设置
- name: web # 端口的名字
containerPort: 80 # 容器的端口
livenessProbe: # 存活性探测属性设置
httpGet: # 探测类型
port: web # 探测的端口
path: index.html # 探测的url
initialDelaySeconds: 5 # 容器里进程初始化时间等待探测时间
periodSeconds: 5 # 探测周期
timeoutSeconds: 2 #探测超时时间
failureThreshold: 3 # 探测连续失败的最大次数
readinessProbe: # 就绪性探测
httpGet: # 探测的钩子
port: web # 探测的端 口
path: index.html #探测的url
initialDelaySeconds: 5 # 容器里进程初始化时间等待探测时间
periodSeconds: 5 # 探测周期
timeoutSeconds: 2 #探测超时时间
failureThreshold: 3 # 探测连续失败的最大次数
vim service.yaml
apiVersion: v1 #api版本
kind: Service # 资源类型
metadata: # 元数据
name: deployment-service # service 的名字
namespace: deployment # 名称空间
labels: # 设置标签属性
dev: dev-service
spec: #期望状态
selector: # 绑定拥有以下标签的pod
dev: deployment-test
ports: # 端口设置
- name: dev-chenxi # 名字
nodePort: 30880 # node 暴漏的端口;如果不写默认随机
port: 80 # 集群内部暴漏的端口,必写字段
protocol: TCP # 协议 支持"TCP", "UDP", and "SCTP",默认TCP
targetPort: web # 绑定的端口支持名字
type: NodePort # 暴露的类型支持ExternalName、ClusterIP、NodePort 和 LoadBalancer。“ClusterIP”为负载均衡分配集群内部 IP 地址“NodePort”建立在 ClusterIP 之上,并在每个节点上分配一个端口路由到与 clusterIP 相
同的端点。“LoadBalancer”建立在NodePort 并创建一个外部负载均衡器(如果当前支持cloud) 路由到与 clusterIP 相同的端点。 “外部名称”将此服务别名为指定的externalName。 其他几个领域不适用于 ExternalName 服务
运行service
[root@master-1 kongzhiqi]# kubectl apply -f service.yaml service/deployment-service created [root@master-1 kongzhiqi]# kubectl get svc -n deployment NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE deployment-service NodePort 10.10.198.163 <none> 80:30880/TCP 3s [root@master-1 kongzhiqi]# kubectl describe svc -n deployment Name: deployment-service Namespace: deployment Labels: dev=dev-service Annotations: <none> Selector: dev=deployment-test Type: NodePort IP Families: <none> IP: 10.10.198.163 IPs: 10.10.198.163 Port: dev-chenxi 80/TCP TargetPort: web/TCP NodePort: dev-chenxi 30880/TCP Endpoints: 10.244.84.163:80,10.244.84.164:80,10.244.84.165:80 Session Affinity: None External Traffic Policy: Cluster Events: <none>
访问node:30880

noselector 类型的service
[root@master-1 service]# cat noselector-service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-cx-1
spec:
ports:
- port: 80
protocol: TCP
targetPort: 3306
[root@master-1 service]# cat endpoints.yaml
apiVersion: v1
kind: Endpoints
metadata:
name: my-cx-1 # 注意名字与service 一致
subsets:
- addresses:
- ip: 1.2.3.4
ports:
- port: 3306
kubectl apply -f noselector-service.yaml
kubectl apply -f endpoints.yaml
[root@master-1 service]# kubectl get endpoints
NAME ENDPOINTS AGE
kubernetes 192.168.10.29:6443,192.168.10.30:6443,192.168.10.31:6443 2d
my-chenxi 172.16.84.131:80,172.16.84.132:80 12s
my-cx-1 1.2.3.4:3306 6m32s
[root@master-1 service]# kubectl describe svc my-cx-1
Name: my-cx-1
Namespace: default
Labels: <none>
Annotations: <none>
Selector: <none>
Type: ClusterIP
IP Families: <none>
IP: 10.255.154.164
IPs: 10.255.154.164
Port: <unset> 80/TCP
TargetPort: 3306/TCP
Endpoints: 1.2.3.4:3306
Session Affinity: None
Events: <none>
externalname service 格式
[root@master-1 service]# kubectl create namespace cx namespace/cx created [root@master-1 deployment]# cat externalname.yaml apiVersion: v1 kind: Service metadata: name: my-cx-2 namespace: cx spec: type: ExternalName externalName: www.baidu.com #返回的 域名 访问格式 name.namespace.svc.cluster.local
无头service
[root@master-1 service]# cat service_2.yaml
apiVersion: v1
kind: Service
metadata:
name: my-chenxi-2
spec:
clusterIP: 'None'
ports:
- port: 80
protocol: TCP
selector:
run: my-cx-2
[root@master-1 service]# kubectl get ep
NAME ENDPOINTS AGE
kubernetes 192.168.10.29:6443,192.168.10.30:6443,192.168.10.31:6443 2d2h
my-chenxi 172.16.84.131:80,172.16.84.132:80 79m
my-chenxi-2 <none> 9m19s
my-cx-1 1.2.3.4:3306 85m

浙公网安备 33010602011771号