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类似,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的更多相关文章

  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. Metasploit 脚本Web传递(Web Delivery)

    Metasploit 脚本Web传递(Web Delivery)

  2. Docker学习第二天(Docker容器管理)

    简介 emmmm Docker 容器管理 推荐文章:容器技术概述 run里面的子选项 1.使用run命令创建容器 docker container run -it ubuntu /bin/bash / ...

  3. java后端开发三年!你还不了解Spring 依赖注入,凭什么给你涨薪

    前言 前两天和一个同学吃饭的时候同学跟我说了一件事,说他公司有个做了两年的人向他提出要涨薪资,他就顺口问了一个问题关于spring依赖注入的,那个要求涨薪的同学居然被问懵了...事后回家想了想这一块确 ...

  4. FL Studio乐理教程之和弦进行

    和弦级数 在一个调内,分别由调内7个音为根音组成的和弦总共有7个,每个和弦依次为1-7级和弦.例如在C大调内,以C为根音建立和弦,就是一级和弦,以D为根音建立和弦,即是二级和弦,以此类推. 图1:1- ...

  5. 左右声道音频怎么制作,用Vegas就对啦

    一款优秀的视频剪辑软件,不仅有高水平的视频制作功能,它的音频编辑功能也是必不可少的.Vegas就是这么一款软件,同时具备视频制作特效制作的同时,还能帮助制作轨道音频效果. 下面,就让小编带大家去学习, ...

  6. symfony中,使用原声的sql语句

    1 /** 2 * 数组形式的原生sql 3 */ 4 public function arrayA(array $did) 5 { 6 $statement = $this->getEntit ...

  7. 对于char,short和byte类型的运算

    对于char,short和byte这些类型在计算时都会提升到int型来计算,所以a+b=3(这个3是int型的,所以我们需要将它强转成为byte类型,才不会出错.但是使用 += 或者 ++ 运算符可以 ...

  8. C语言讲义——dll调用

    DLL:Dynamic Link Library,动态链接库.一个应用程序可使用多个DLL文件,一个DLL文件也可以被不同的应用程序使用. 先新建一个dll项目 再创建C项目进行调用 #include ...

  9. OllyDbg使用入门

    OllyDbg的四个窗口: http://www.360doc.com/content/16/0913/07/16447955_590419156.shtml 反汇编窗口:显示被调试程序的反汇编代码, ...

  10. Java动态代理设计模式

    本文主要介绍Java中两种常见的动态代理方式:JDK原生动态代理和CGLIB动态代理. 什么是代理模式 就是为其他对象提供一种代理以控制对这个对象的访问.代理可以在不改动目标对象的基础上,增加其他额外 ...