Kubernetes【K8S】(五):Service
Service概念
Kubernetes Service定义了一个Pod的逻辑分组,一种可以访问它们的策略。这组Pod能被Service访问到,通常是通过label Selector。

Service能够提供负载均衡的能力,它只提供4层负载均衡的能力,而没有7层功能,有时我们可能需要更多的匹配规则来转发请求,这点上4层负载均衡是不支持的。
Service的类型
Service在K8S中有四种类型
ClusterIp:默认类型,自动分配一个仅Cluster内部可以访问的虚拟IP。NodePort:在ClusterIP基础上为Service在每台机器上绑定一个端口,这样就可以通过NodePort来访问服务。LoadBalancer:在NodePort的基础上,借助cloud provider创建一个外部负载均衡器,并将请求转发到NodePort。ExternalName:把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,只有Kubernetes1.7或更高版本的kube-dns才支持。
VIP和Service代理
在Kubernetes集群中,每个Node运行一个kube-proxy进程。kube-proxy负责为Service实现了一种VIP(虚拟IP)的形式,而不是ExternalName的形式。在Kubernetes v1.0版本,代理v完全在userspace。在Kubernetes v1.1版本,新增了iptables代理,但并不是默认的运行模式。从Kubernetes v1.2起,默认就是iptables代理。在Kubernetes v1.8.0-beta.0中,添加了ipvs代理,在Kubernetes 1.14版本开始默认使用ipvs代理。在Kubernetes v1.0版本,Service是“4层”(TCP/UDP over IP)的概念。在Kubernetes v1.1版本,新增了Ingress API(beta版),用来表示“7层”(HTTP)服务。

代理模式的分类
userspace代理模式

iptables代理模式

ipvs代理模式kube-proxy会监视KubernetesService对象和Endpoints对象,调用netlink接口以相应地创建ipvs规则并定期与KubernetesService对象和Endpoints对象同步ipvs规则,以确保ipvs状态与期望一致。访问服务时,流量将被重定向到其中一个后端Pod。与iptables类似,ipvs于netfilter的hook功能,但使用哈希表作为底层数据结构并在内核空间中工作。这意味着ipvs可以更快地重定向流量,并在同步代理规则时具有更好地性能。此外,ipvs为负载均衡算法提供了更多选项,例如:rr:轮询调度lc:最小连接数dh:目标哈希sh:源哈希sed:最短期望延迟nq:不排队调度
注意:ipvs模式假定在运行kube-proxy之前在节点上都已经安装了ipvs内核模块。当kube-proxy以ipvs代理模式启动时,kube-proxy将验证节点上是否安装了ipvs模块,如果未安装,则kube-proxy将回退到iptables代理模式。

Service的 spec.type
ClusterIP
ClusterIP主要在每个node节点使用iptables,将发向clusterIP对应端口的数据,转发到kube-proxy中。然后kube-proxy自己内部实现有负载均衡的方法,并可以查询到这个service下对应pod的地址和端口,进而把数据转发给对应的pod地址和端口。

- 用户通过
kubectl命令向apiserver发送创建service的命令,apiserver收到请求后将数据存储到etcd中。 kubernetes的每个节点中都有一个叫做kube-proxy的进程,这个进程负责感知service,pod的变化,并将变化的信息写入本地的iptables规则中。iptables使用NAT等技术将virtualIP的流量转至endpoint中。
创建myapp-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
labels:
app: myapp-deploy
spec:
replicas: 3
template:
metadata:
name: myapp-deploy
labels:
app: myapp-deploy
release: stabel
env: test
spec:
containers:
- name: myapp-deploy
image: chinda.com/library/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: http
restartPolicy: Always
selector:
matchLabels:
app: myapp-deploy
release: stabel
创建myapp-service.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: myapp-service
release: stabel
ports:
- port: 80
targetPort: 80
name: http
type: ClusterIP
测试
[root@k8s-master01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
myapp-service ClusterIP 10.107.157.192 <none> 80/TCP 9s
[root@k8s-master01 ~]# curl 10.107.157.192
curl: (7) Failed connect to 10.107.157.192:80; Connection refused
[root@k8s-master01 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.96.0.1:443 rr
-> 192.168.0.150:6443 Masq 1 3 0
TCP 10.96.0.10:53 rr
-> 10.244.0.43:53 Masq 1 0 0
-> 10.244.0.44:53 Masq 1 0 0
TCP 10.96.0.10:9153 rr
-> 10.244.0.43:9153 Masq 1 0 0
-> 10.244.0.44:9153 Masq 1 0 0
TCP 10.107.157.192:80 rr
UDP 10.96.0.10:53 rr
-> 10.244.0.43:53 Masq 1 0 0
-> 10.244.0.44:53 Masq 1 0 0
[root@k8s-master01 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-deploy-6f87986465-2pcgp 1/1 Running 0 14m 10.244.1.123 k8s-node01 <none> <none>
myapp-deploy-6f87986465-7rhrq 1/1 Running 0 14m 10.244.1.124 k8s-node01 <none> <none>
myapp-deploy-6f87986465-scz2v 1/1 Running 0 14m 10.244.2.110 k8s-node02 <none> <none>
拒绝连接,ipvs检测service下没有挂载任何的pod,原因是deployment和service的spec.selector命名不相同。
修改后
修改后myapp-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
labels:
app: myapp-deploy
spec:
replicas: 3
template:
metadata:
name: myapp
labels:
app: myapp
release: stabel
env: test
spec:
containers:
- name: myapp-deploy
image: chinda.com/library/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: http
restartPolicy: Always
selector:
matchLabels:
app: myapp
release: stabel
修改后myapp-service.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
selector:
app: myapp
release: stabel
ports:
- port: 80
targetPort: 80
name: http
type: ClusterIP
检测
[root@k8s-master01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
myapp-service ClusterIP 10.104.50.207 <none> 80/TCP 10s
[root@k8s-master01 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.96.0.1:443 rr
-> 192.168.0.150:6443 Masq 1 3 0
TCP 10.96.0.10:53 rr
-> 10.244.0.43:53 Masq 1 0 0
-> 10.244.0.44:53 Masq 1 0 0
TCP 10.96.0.10:9153 rr
-> 10.244.0.43:9153 Masq 1 0 0
-> 10.244.0.44:9153 Masq 1 0 0
TCP 10.104.50.207:80 rr
-> 10.244.1.125:80 Masq 1 0 0
-> 10.244.1.126:80 Masq 1 0 0
-> 10.244.2.111:80 Masq 1 0 0
UDP 10.96.0.10:53 rr
-> 10.244.0.43:53 Masq 1 0 0
-> 10.244.0.44:53 Masq 1 0 0
[root@k8s-master01 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-deploy-677ccc888c-m42jt 1/1 Running 0 119s 10.244.1.125 k8s-node01 <none> <none>
myapp-deploy-677ccc888c-rgsn4 1/1 Running 0 119s 10.244.2.111 k8s-node02 <none> <none>
myapp-deploy-677ccc888c-w6hzg 1/1 Running 0 119s 10.244.1.126 k8s-node01 <none> <none>
[root@k8s-master01 ~]# curl 10.104.50.207
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
Headless Service
有时不需要或不想要负载均衡,以及单独的Service IP。遇到这种情况,可以通过指定Cluster IP(spec.clusterIP)的值为“None”来创建Headless Service。这类Service并不会分配Cluster IP,kube-proxy不会处理他们,而且平台也不会为它们进行负载均衡和路由。
创建myapp-headless-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-headless
spec:
selector:
app: myapp
ports:
- port: 80
targetPort: 80
clusterIP: None
解析coredns
# svc 创建成功会写入到coredns中
[root@k8s-master01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
myapp-headless ClusterIP None <none> 80/TCP 6s
myapp-service ClusterIP 10.104.50.207 <none> 80/TCP 16m
[root@k8s-master01 ~]# kubectl get pod -n kube-system -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
coredns-5c98db65d4-dhrw6 1/1 Running 21 13d 10.244.0.44 k8s-master01 <none> <none>
coredns-5c98db65d4-jhvv2 1/1 Running 21 13d 10.244.0.43 k8s-master01 <none> <none>
etcd-k8s-master01 1/1 Running 22 13d 192.168.0.150 k8s-master01 <none> <none>
kube-apiserver-k8s-master01 1/1 Running 22 13d 192.168.0.150 k8s-master01 <none> <none>
kube-controller-manager-k8s-master01 1/1 Running 22 13d 192.168.0.150 k8s-master01 <none> <none>
kube-flannel-ds-amd64-bm5px 1/1 Running 28 13d 192.168.0.150 k8s-master01 <none> <none>
kube-flannel-ds-amd64-cfhhg 1/1 Running 23 13d 192.168.0.152 k8s-node02 <none> <none>
kube-flannel-ds-amd64-mlqgl 1/1 Running 20 13d 192.168.0.151 k8s-node01 <none> <none>
kube-proxy-4f8dk 1/1 Running 19 13d 192.168.0.152 k8s-node02 <none> <none>
kube-proxy-lg875 1/1 Running 19 13d 192.168.0.151 k8s-node01 <none> <none>
kube-proxy-zwpmh 1/1 Running 22 13d 192.168.0.150 k8s-master01 <none> <none>
kube-scheduler-k8s-master01 1/1 Running 22 13d 192.168.0.150 k8s-master01 <none> <none>
# 安装dig命令
[root@k8s-master01 ~]# yum -y install bind-utils
# 访问svc {service-name}.{namespace}.svc.cluster.local
[root@k8s-master01 ~]# dig -t A myapp-headless.default.svc.cluster.local. @10.244.0.44
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-16.P2.el7_8.2 <<>> -t A myapp-headless.default.svc.cluster.local. @10.244.0.44
;; 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: 6438
;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;myapp-headless.default.svc.cluster.local. IN A
;; ANSWER SECTION:
myapp-headless.default.svc.cluster.local. 30 IN A 10.244.1.125
myapp-headless.default.svc.cluster.local. 30 IN A 10.244.1.126
myapp-headless.default.svc.cluster.local. 30 IN A 10.244.2.111
;; Query time: 0 msec
;; SERVER: 10.244.0.44#53(10.244.0.44)
;; WHEN: Fri May 01 09:57:24 CST 2020
;; MSG SIZE rcvd: 237
[root@k8s-master01 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-deploy-677ccc888c-m42jt 1/1 Running 0 48m 10.244.1.125 k8s-node01 <none> <none>
myapp-deploy-677ccc888c-rgsn4 1/1 Running 0 48m 10.244.2.111 k8s-node02 <none> <none>
myapp-deploy-677ccc888c-w6hzg 1/1 Running 0 48m 10.244.1.126 k8s-node01 <none> <none>
NodePort
NodePort的原理在于在Node上开了一个端口,将向该端口的流量导入kube-proxy,然后由kube-proxy进一步给对应的Pod。
创建nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-nodeport
spec:
selector:
app: myapp
release: stabel
ports:
- port: 80
targetPort: 80
type: NodePort
测试
[root@k8s-master01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
myapp-headless ClusterIP None <none> 80/TCP 36m
myapp-nodeport NodePort 10.105.209.63 <none> 80:31509/TCP 5s
myapp-service ClusterIP 10.104.50.207 <none> 80/TCP 52m
# 每个节点都会开放此端口
[root@k8s-master01 ~]# netstat -anp | grep 31509
tcp6 0 0 :::31509 :::* LISTEN 3338/kube-proxy

LoadBalancer
云供应商提供的服务,其实和NodePort是同一种方式。
ExternalName
这种类型的Service通过返回CNAME和它的值,可以将服务映射到externalName字段的内容(例如:www.123.com)。ExternalName Service是Service的特例,它没有selector,也没有定义任何的端口和Endpoint。相反的,对于运行在集群之外的服务,它通过返回该外部服务的别名这种方式来提供服务。
创建ex.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-ex
spec:
type: ExternalName
externalName: www.123.com
检测
[root@k8s-master01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13d
myapp-ex ExternalName <none> www.123.com <none> 6s
myapp-headless ClusterIP None <none> 80/TCP 99m
myapp-nodeport NodePort 10.105.209.63 <none> 80:31509/TCP 62m
myapp-service ClusterIP 10.104.50.207 <none> 80/TCP 115m
[root@k8s-master01 ~]# dig -t A myapp-ex.default.svc.cluster.local. @10.244.0.44
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-16.P2.el7_8.2 <<>> -t A myapp-ex.default.svc.cluster.local. @10.244.0.44
;; 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: 41068
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;myapp-ex.default.svc.cluster.local. IN A
;; ANSWER SECTION:
myapp-ex.default.svc.cluster.local. 30 IN CNAME www.123.com.
www.123.com. 30 IN A 61.132.13.130
;; Query time: 68 msec
;; SERVER: 10.244.0.44#53(10.244.0.44)
;; WHEN: Fri May 01 11:08:54 CST 2020
;; MSG SIZE rcvd: 149
当查询主机 myapp-ex.default.svc.cluster.local时,集群的DNS服务将返回一个值www.123.comd的CNAME记录。访问这个服务的工作方式和其他的相同,唯一不同的时重定向发生在DNS层,而且不会进行代理或转发。
Kubernetes【K8S】(五):Service的更多相关文章
- Kubernetes K8S之Service服务详解与示例
K8S之Service概述与代理说明,并详解所有的service服务类型与示例 主机配置规划 服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟) k8s-master Cent ...
- Kubernetes K8S在IPVS代理模式下Service服务的ClusterIP类型访问失败处理
Kubernetes K8S使用IPVS代理模式,当Service的类型为ClusterIP时,如何处理访问service却不能访问后端pod的情况. 背景现象 Kubernetes K8S使用IPV ...
- kubernetes 实践五:Service详解
Service 是 k8s 的核心概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上. Service 的定义 Servic ...
- 《两地书》--Kubernetes(K8s)基础知识(docker容器技术)
大家都知道历史上有段佳话叫“司马相如和卓文君”.“皑如山上雪,皎若云间月”.卓文君这么美,却也抵不过多情女儿薄情郎. 司马相如因一首<子虚赋>得汉武帝赏识,飞黄腾达之后便要与卓文君“故来相 ...
- Kubernetes(k8s)集群安装
一:简介 二:基础环境安装 1.系统环境 os Role ip Memory Centos 7 master01 192.168.25.30 4G Centos 7 node01 192.168.25 ...
- Kubernetes(K8s)基础知识(docker容器技术)
今天谈谈K8s基础知识关键词: 一个目标:容器操作:两地三中心:四层服务发现:五种Pod共享资源:六个CNI常用插件:七层负载均衡:八种隔离维度:九个网络模型原则:十类IP地址:百级产品线:千级物理机 ...
- 使用kubectl管理Kubernetes(k8s)集群:常用命令,查看负载,命名空间namespace管理
目录 一.系统环境 二.前言 三.kubectl 3.1 kubectl语法 3.2 kubectl格式化输出 四.kubectl常用命令 五.查看kubernetes集群node节点和pod负载 5 ...
- Istio(二):在Kubernetes(k8s)集群上安装部署istio1.14
目录 一.模块概览 二.系统环境 三.安装istio 3.1 使用 Istioctl 安装 3.2 使用 Istio Operator 安装 3.3 生产部署情况如何? 3.4 平台安装指南 四.Ge ...
- kubernetes系列08—service资源详解
本文收录在容器技术学习系列文章总目录 1.认识service 1.1 为什么要使用service Kubernetes Pod 是有生命周期的,它们可以被创建,也可以被销毁,然而一旦被销毁生命就永远结 ...
- Docker Kubernetes(K8s)简介
入职了新公司,使用了Docker和K8s,需要有一个基础的了解,对网络上相关信息进行了简单总结. 一Docker 1简介: Docker 将应用程序与该程序的依赖,打包在一个文件里面.运行这个文件,就 ...
随机推荐
- 博客新域名www.tecchen.tech
新年祝福 祝新的一年,大朋友实现所有梦想,小朋友健康成长- 新域名 https://www.tecchen.tech 有效期:10年 旧链接 之前的链接请自行替换为新链接地址,包括但不限于以下二级域名 ...
- Shamir秘密共享方案 (Python)
Shamir's Secret Sharing scheme is an important cryptographic algorithm that allows private informati ...
- python升级版本
前言 目前大部分使用的3.6或者3.7以及更低版本存在不少问题,随着python的更新很多问题得到修复并且具有更多新的功能. 更新 3.y.x版本升级到3.y.z 下载需要升级的exe安装包点击upg ...
- PC 端轮播图的实现
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8& ...
- keras实现MobileNet
利用keras实现MobileNet,并以mnist数据集作为一个小例子进行识别.使用的环境是:tensorflow-gpu 2.0,python=3.7 , GTX-2070的GPU 1.导入数据 ...
- day99:MoFang:Flask-JSONRPC提供RPC接口&在APP进行窗口页面操作(窗口-帧-帧组)
目录 1.服务端基于Flask-JSONRPC提供RPC接口 1.Flask-JSONRPC简介 2.安装Flask-JSONRPC模块 3.快速实现一个测试的RPC接口 4.移动端访问测试接口 2. ...
- 【抓取】6-DOF GraspNet 论文解读
[抓取]6-DOF GraspNet 论文解读 [注]:本文地址:[抓取]6-DOF GraspNet 论文解读 若转载请于明显处标明出处. 前言 这篇关于生成抓取姿态的论文出自英伟达.我在读完该篇论 ...
- CentOS基础命令使用技巧-1
less用法 g快速返回文件首部 G快速到文本最末端 /当前行向下搜索 ?当前行向上搜索 n显示下一个 q退出 cp用法 r拷贝一个目录必须加这个 rm用法 r删除目录 f强制删除,r后面删除不存在的 ...
- 关于element中修改组件使用深度选择器/deep/的问题
作为一个小白,在使用饿了么ui的时候,想改一下里面的组件属性,但是发现虽然在页面上能找到对应的标签,然而在代码里却没法找到,使用了两种方法来修改其中的默认样式 第一种,去除style标签里的scope ...
- JZOJ8月8日提高组反思
JZOJ8月8日提高组反思 T1 一开始打了个暴力 后来突然觉得是不是可以构造答案 然后就奇奇怪怪的调了1h 结果呢 Re-- 估计还是没调完 T2 这这这 好熟悉 往0点连,然后最小生成树跑一遍 结 ...