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会监视Kubernetes Service对象和Endpoints对象,调用netlink接口以相应地创建ipvs规则并定期与Kubernetes Service对象和Endpoints对象同步ipvs规则,以确保ipvs状态与期望一致。访问服务时,流量将被重定向到其中一个后端Pod。与iptables类似,ipvsnetfilterhook功能,但使用哈希表作为底层数据结构并在内核空间中工作。这意味着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的进程,这个进程负责感知servicepod的变化,并将变化的信息写入本地的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的更多相关文章

  1. Kubernetes K8S之Service服务详解与示例

    K8S之Service概述与代理说明,并详解所有的service服务类型与示例 主机配置规划 服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟) k8s-master Cent ...

  2. Kubernetes K8S在IPVS代理模式下Service服务的ClusterIP类型访问失败处理

    Kubernetes K8S使用IPVS代理模式,当Service的类型为ClusterIP时,如何处理访问service却不能访问后端pod的情况. 背景现象 Kubernetes K8S使用IPV ...

  3. kubernetes 实践五:Service详解

    Service 是 k8s 的核心概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上. Service 的定义 Servic ...

  4. 《两地书》--Kubernetes(K8s)基础知识(docker容器技术)

    大家都知道历史上有段佳话叫“司马相如和卓文君”.“皑如山上雪,皎若云间月”.卓文君这么美,却也抵不过多情女儿薄情郎. 司马相如因一首<子虚赋>得汉武帝赏识,飞黄腾达之后便要与卓文君“故来相 ...

  5. Kubernetes(k8s)集群安装

    一:简介 二:基础环境安装 1.系统环境 os Role ip Memory Centos 7 master01 192.168.25.30 4G Centos 7 node01 192.168.25 ...

  6. Kubernetes(K8s)基础知识(docker容器技术)

    今天谈谈K8s基础知识关键词: 一个目标:容器操作:两地三中心:四层服务发现:五种Pod共享资源:六个CNI常用插件:七层负载均衡:八种隔离维度:九个网络模型原则:十类IP地址:百级产品线:千级物理机 ...

  7. 使用kubectl管理Kubernetes(k8s)集群:常用命令,查看负载,命名空间namespace管理

    目录 一.系统环境 二.前言 三.kubectl 3.1 kubectl语法 3.2 kubectl格式化输出 四.kubectl常用命令 五.查看kubernetes集群node节点和pod负载 5 ...

  8. Istio(二):在Kubernetes(k8s)集群上安装部署istio1.14

    目录 一.模块概览 二.系统环境 三.安装istio 3.1 使用 Istioctl 安装 3.2 使用 Istio Operator 安装 3.3 生产部署情况如何? 3.4 平台安装指南 四.Ge ...

  9. kubernetes系列08—service资源详解

    本文收录在容器技术学习系列文章总目录 1.认识service 1.1 为什么要使用service Kubernetes Pod 是有生命周期的,它们可以被创建,也可以被销毁,然而一旦被销毁生命就永远结 ...

  10. Docker Kubernetes(K8s)简介

    入职了新公司,使用了Docker和K8s,需要有一个基础的了解,对网络上相关信息进行了简单总结. 一Docker 1简介: Docker 将应用程序与该程序的依赖,打包在一个文件里面.运行这个文件,就 ...

随机推荐

  1. 实验吧[WEB]——what a fuck!这是什么鬼东西?

    解题链接:http://ctf5.shiyanbar.com/DUTCTF/1.html 原题链接:http://www.shiyanbar.com/ctf/56 解题必看: 的jother编码定义: ...

  2. MathType颜色设置的技巧

    MathType功能非常强大,在编辑公式时使用非常方便.运用MathType不仅可以改变公式的字体和字号,也可以改变公式字体颜色,MathType颜色设置还是有一套技术的,下面我们就一起来看看公式编辑 ...

  3. 刚安装好的MathType怎么使用

    对于刚接触公式编辑器的新手来说,难免会存在很多疑问:如何使用刚安装好的Word公式编辑器?安装好公式编辑器之后,我们在哪里找到这个工具呢?下面就针对大家的这些疑问,来给大家介绍下首次使用MathTyp ...

  4. css3系列之@font-face

    @font-face 这个属性呢,必须设置在 css的根下,也就是说,不能设置在任何元素里面. @font-face: 参数: font-family:  给这个文字库 起个名字. src: url( ...

  5. php filesize不能统计临时文件

    文件上传时要统计上传的文件的大小,使用filesize('文件名')的时候,其中 的文件名就得是文件在本地的临时文件但是会出现一个错误显示成 filesize(): stat failed for D ...

  6. Acwing 245.你能回答这些问题吗

    题目描述 给定长度为N的数列A,以及M条指令,每条指令可能是以下两种之一: 1."1 x y",查询区间 [x,y] 中的最大连续子段和,即 maxx≤l≤r≤y{∑ri=lA[i ...

  7. 精尽MyBatis源码分析 - 插件机制

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  8. Java基础教程——继承

    继承 一个类 可以 继承自 另一个类: 派生的类(子类)继承父类的方法和数据成员: 关键字:子类 extends 父类. public class 继承 { public static void ma ...

  9. [BUGCASE]层叠上下文和z-index属性使用不当引发的文本被遮挡的问题

    一.问题描述 在一个fixed-data-table(一个React组件)制作的表格中,需要给表头的字段一个提示的特效,所以做了一个提示层 这个提示层被固定(拖动表格的水平滚动条时固定)的表格列遮住 ...

  10. 16_Android的数据存储_ SharedPreference、XML和JSON

    1. Android读写首选项 1.1 SharedPreferences SharedPreferences 是一种轻型的数据存储方式,它的本质是基于XML文件存储Key-Value键值对数据,通常 ...