Service及CoreDNS实战
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
目录
一.Service 概述
1.什么是Service
Service是Kubernetes标准的API资源类型之一,Service的负责基于单个端点暴露部署在一组Pod上的服务端应用程序,可为动态、短生命周期的Pod资源提供稳定的IP地址和DNS名称来提供可靠的流量接入机制。
Service依赖于同名的Endpoints资源维护匹配的后端各Pod的IP和Port。
Service的三个特性:
- 1.统一客户端访问入口:
为动态的Pod资源提供近似静态的流量访问入口;
- 2.服务发现:
通过标签选择器筛选同一名称空间下的Pod资源的标签,完成Pod筛选。
- 3.负载均衡:
由运行各工作节点的kube-proxy根据配置的模式生成相应的流量调度规则
支持"iptables mode"和"ipvs mode"两种模式。
2.Service类型及ExternalName示例
- ClusterIP:
K8S集群内部客户端流量通过ClusterIP和Service Port接入。
- NodePort:
外部客户端流量通过NodeIP和NodePort接入,相当于增强版的ClusterIP。
它使用NodePort接入集群外部客户端流量,使用ClusterIP接入集群内部流量。
- LoadBalancer
外部客户端流量通过LB_IP和LB_Port接入,相当于增强版的NodePort。
- ExternalName:
内部客户端流量通过ServiceName发现并访问外部服务。
- ExternalName案例:(没有CLUSTER-IP哟~)
1.创建ExternalName类型svc
[root@master231 yinzhengjie-k8s]# cat 05-externalName-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: externalname-mysql
spec:
type: ExternalName
# 定义CNAME的域名
# externalName: www.baidu.com
externalName: www.cnblogs.com
ports:
- port: 3306
[root@master231 yinzhengjie-k8s]#
[root@master231 yinzhengjie-k8s]# kubectl apply -f 05-externalName-svc.yaml
service/externalname-mysql created
[root@master231 yinzhengjie-k8s]#
[root@master231 yinzhengjie-k8s]# kubectl get -f 05-externalName-svc.yaml
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
externalname-mysql ExternalName <none> www.cnblogs.com 3306/TCP 3s
[root@master231 yinzhengjie-k8s]#
2.测试解析DNS记录,发现访问SVC的FQDN,访问的确实"www.cnblogs.com"的域名哟~
[root@master231 yinzhengjie-k8s]# host -t A externalname-mysql.default.svc.yinzhengjie.com 10.200.0.10
Using domain server:
Name: 10.200.0.10
Address: 10.200.0.10#53
Aliases:
externalname-mysql.default.svc.yinzhengjie.com is an alias for www.cnblogs.com.
www.cnblogs.com has address 118.31.180.41
www.cnblogs.com has address 101.37.225.65
[root@master231 yinzhengjie-k8s]#
3.Endpoints和EndpointSlice概述
Endpoints负责维护由相关Service标签选择器匹配的Pod对象:
- 1.Endpoints("即端点")对象上保存Service匹配到的所有Pod的IP和Port信息;
- 2.后端每个Pod的每次变动,都需更新整个Endpoints对象,并需要将该对象同步至每个节点的kube-proxy;
为什么需要EndpointSlice?
- 即便只有一个Pod的IP等信息发生变动也会全量更新:
- 1.也必须向集群中的每个kube-proxy发送整个endpoints对象。
- 存储在etcd中的对象的默认大小限制为1.5MB:
- 1.这也决定了单个Endpoints对象的存储上限,至多可以存储5000个左右的端点信息。
- 极端场景:
- 1.2000个节点的集群,更新一个有着5000个Pod IP的Endpoints对象(1.5M),需要发送3GB的数据;
- 2.若以滚动更新机制,一次替换一个Pod的信息,更新这个Endpoints对象需要发送15T的数据;
- EndpointSlice资源通过将Endpoints切分为多片来解决上述问题。
- 1.自Kubernetes v1.16引入;
- 2.每个端点信息的变动,仅需要更新和发送一个EndpointSlice,而非整个Endpoints;
- 3.每个EndpointSlice默认存储100个端点信息,不会触达etcd对单个对象的存储限制;
- 4.可在kube-controller-manager程序上使用“--max-endpoints-per-slice”选项进行配置;
EndpointSlice并未取代Endpoints,二者同时存在。
4.标签和标签选择器
标签:附加在资源对象上的键值型元数据。
- 键标识:
由“key_prefix(可选)”和“key_name”组成,格式为: “key_prefix/key_name”
- 1.key_prefix必须使用DNS域名格式
- 2.key_name的命名格式:支持字母、数字、连接号、下划线和点号,且只能以字母或数字开头;最长63个字符;
- “kubectl label”:
命令可管理对象的标签。
标签选择器:基于标签筛选对象的过滤条件,支持两种类型
- 1.基于等值关系的选择器
操作符:=或==、!=
- 2.基于集合关系的选择器
操作符:in、notin和exists
使用格式:KEY in (VALUE1, VALUE2, …)、 KEY notin (VALUE1, VALUE2, …)、KEY 和 !KEY
5.Service资源规范
apiVersion: v1
kind: Service
metadata:
name: …
namespace: …
spec:
# Service类型,默认为ClusterIP
type: <string>
# Service的集群IP,建议由系统自动分配
clusterIP: <string>
# 外部流量策略处理方式,Local表示由当前节点处理,Cluster表示向集群范围调度
externalTrafficPolicy <string>
# 外部负载均衡器使用的IP地址,仅适用于LoadBlancer
loadBalancerIP <string>
# 外部服务名称,该名称将作为Service的DNS CNAME值
externalName <string>
# 等值类型的标签选择器,内含“与”逻辑
selector: <map[string]string>
# Service的端口对象列表
ports:
# 端口名称
- name: <string>
# 协议,目前仅支持TCP、UDP和SCTP,默认为TCP
protocol:<string>
# Service的端口号
port: <integer>
# 后端目标进程的端口号或名称,名称需由Pod规范定义
targetPort: <string>
# 节点端口号,仅适用于NodePort和LoadBalancer类型
nodePort: <integer>
6.Headless Service示例
Service的各类型中,ClusterIP、NodePort和LoadBalancer都为其Service配置一个ClusterIP,CoreDNS上这些Service对象的A记录也解析为它的ClusterIP。
广义上,那些没有ClusterIP的Service则称为Headless Service,它们又可以为分两种情形:
- 有标签选择器,或者没有标签选择器,但有着与Service对象同名的Endpoint资源
- 1.Service的DNS名称直接解析为后端各就绪状态的Pod的IP地址;
- 2.调度功能也将由DNS完成;
- 3.各Pod IP相关PTR记录将解析至Pod自身的名称,假设Pod IP为a.b.c.d,则其名称为a-b-c-d.<service>.<ns>.svc.<zone>;
- 4.这种类型也就是狭义上的Headless Service;
- 5.被StatefulSet所依赖;
- 无标签选择器且也没有与Service对象同名的Endpoint资源
- 1.Service的DNS名称将会生成一条CNAME记录,对应值由Service对象上的spec.externalName字段指定。
实战案例:
1.创建headless svc
[root@master231 yinzhengjie-k8s]# cat 06-svc-headless.yaml
apiVersion: v1
kind: Service
metadata:
name: headless-svc
spec:
type: ClusterIP
clusterIP: None
ports:
- port: 80
selector:
apps: v2
[root@master231 yinzhengjie-k8s]#
[root@master231 yinzhengjie-k8s]# kubectl apply -f 06-svc-headless.yaml
service/headless-svc created
[root@master231 yinzhengjie-k8s]#
[root@master231 yinzhengjie-k8s]# kubectl get -f 06-svc-headless.yaml
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
headless-svc ClusterIP None <none> 80/TCP 3s
[root@master231 yinzhengjie-k8s]#
2.测试验证
[root@master231 yinzhengjie-k8s]# kubectl get pods --show-labels -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
xiuxian-dnspolicy-dnsconfig-65cd677c9d-c86p4 1/1 Running 0 28m 10.100.140.105 worker233 <none> <none> apps=v2,pod-template-hash=65cd677c9d
[root@master231 yinzhengjie-k8s]#
[root@master231 yinzhengjie-k8s]# host -t A headless-svc.default.svc.yinzhengjie.com 10.200.0.10
Using domain server:
Name: 10.200.0.10
Address: 10.200.0.10#53
Aliases:
headless-svc.default.svc.yinzhengjie.com has address 10.100.140.105
[root@master231 yinzhengjie-k8s]#
二.CoreDNS概述
1.CoreDNS概述
Cluster DNS(CoreDNS)是Kubernetes集群的必备附件,负责为Kubernetes提供名称解析和服务发现。
- 1.每个svc资源对象,在CoreDNS上都会自动生成一个遵循“<service>.<ns>.svc.<zone>”格式的名称:
<service>:
当前Service对象的名称
<ns>:
当前Service对象所属的名称空间
<zone>:
当前Kubernetes集群使用的域名后缀,默认为“cluster.local”。
- 2.围绕“<service>.<ns>.svc.<zone>”名称会生成一些DNS格式的资源记录。
CoreDNS会持续监视API Server上的Service资源对象的变动,并实时反映到相关的DNS资源记录中。
Pod中各容器默认会在/etc/resolv.conf中,将nameserver指向CoreDNS相关的Service的ClusterIP。
由kubelet创建Pod时根据指定的配置自动注入。
每个Service,在CoreDNS上都会有A/AAAA、SRV和PTR资源记录,Pod可基于Service的DNS名称向其发起服务访问请求。
2.Pod上的DNS解析策略示例
Kubernetes支持在单个Pod资源规范上自定义DNS解析策略和配置,并组合生效
- Pod.spec.dnsPolicy:DNS解析策略
- Pod.spec.dnsConfig:名称解析机制
DNS解析策略:
- ClusterFirst:
优先使用集群自有的DNS Server进行<zone>(默认为"cluster.local")域名的解析。
对于<zone>之外的域名,则交由Pod所在节点的"/etc/resolv.conf"指定的DNS解析。
- ClusterFirstWithHostNet:
专用于在设置了hostNetwork的Pod对象上使用的ClusterFirst策略。
- Default:
从运行在的节点继承DNS名称解析相关的配置
- None:
用于忽略Kubernetes集群的默认设定,而仅使用由dnsConfig自定义的配置。
DNS解析机制
- nameservers <[]string>:
DNS名称服务器列表,附加于由dnsPolicy生成的DNS名称服务器之后。
一般指定了svc的ClusterIP地址。
- searches <[]string>:
DNS名称解析时的搜索域,附加由于dnsPolicy生成的搜索域之后。
当用户使用非完整的FQDN时,会自动在其后缀依次补充"searches"列表的域名后缀,如果所有列表的后缀都尝试后都无法解析,则判断解析失败。
- options <[]Object>:
DNS解析选项列表,同dnsPolicy生成的解析选项合并成最终生效的定义。
比如"ndots: 5"表示有FQDN域名解析时最多出现"."的次数。
实战案例:
1.测试dnsPolicy和dnsConfig
[root@master231 yinzhengjie-k8s]# cat 04-pod-with-dnspolicy-dnsconfig.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: xiuxian-dnspolicy-dnsconfig
spec:
replicas: 1
selector:
matchLabels:
apps: v2
template:
metadata:
labels:
apps: v2
spec:
dnsPolicy: None
dnsConfig:
nameservers:
- 10.100.0.10
- 223.5.5.5
- 223.6.6.6
searches:
- svc.yinzhengjie.com
- yinzhengjie.com
- cluster.local
options:
- name: ndots
value: "5"
containers:
- name: c2
image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2
[root@master231 yinzhengjie-k8s]#
2.创建测试
[root@master231 yinzhengjie-k8s]# kubectl apply -f 04-pod-with-dnspolicy-dnsconfig.yaml
deployment.apps/xiuxian-dnspolicy-dnsconfig created
[root@master231 yinzhengjie-k8s]#
[root@master231 yinzhengjie-k8s]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
xiuxian-dnspolicy-dnsconfig-65cd677c9d-c86p4 1/1 Running 0 8s 10.100.140.105 worker233 <none> <none>
[root@master231 yinzhengjie-k8s]#
[root@master231 yinzhengjie-k8s]# kubectl exec xiuxian-dnspolicy-dnsconfig-65cd677c9d-c86p4 -- cat /etc/resolv.conf
nameserver 10.100.0.10
nameserver 223.5.5.5
nameserver 223.6.6.6
search svc.yinzhengjie.com yinzhengjie.com cluster.local
options ndots:5
[root@master231 yinzhengjie-k8s]#
3.CoreDNS的默认配置
| 插件名称 | 描述 |
|---|---|
| errors | 启用错误日志 |
| health | 启用CoreDNS进程自身的健康状态检测功能,默认的端点为8080端口上的/health,路径/health固定,但可使用自定义的套接字,例如"health localhost:8081"。 |
| ready | 启用CoreDNS进程自身的就绪状态报告功能,默认的端点为8181端口上的/ready,路径/ready固定,但可使用自定义的套接字,例如“health localhost:8082" |
| kubernetes | 用于从kubernetes集群加载区域解析相关的数据,从而为Kubernetes集群提供内部服务解析功能。 |
| prometheus | 启用CoreDNS内置的Prometheus格式的指标,默认的端点为8181端口上的/metrics”,路径/metrics固定,但可使用自定义的套接字,例如"health localhost:8083" |
| forward|proxy | 将DNS名称查询请求转发给指定的其它DNS服务器;Kubernetes CoreDNS默认配置中的forward指令能够将对所有域名的查询请求转发给(宿主机的)/etc/resolv.conf文件中指定的DNS服务器 |
| cache | 启用对DNS查询结果的缓存功能;查询结果来自后端服务且开销较高时能产生高价值;默认缓存时长为3600s |
| loop | 启用DNS查询过程中的环路检测功能,该插件会在检测到环路时停止查询操作。 |
| reload | 允许自动重载更改的Corefile配置 |
| loadbalance | 基于随机算法,为A、AAAA或MX类型的资源记录的多条查询结果上启用负载均衡功能。 |
| hosts | 使用类似于/etc/hosts网格的文件格式提供区域解析数据,仅支持A、AAAA和PTR记录类型。 |
| bind | 为服务器配置段指定要监听的IP地址或网络接口,格式为"bind ADDRESS|IFACE ...",例如:"bind eth0"。 |
CoreDNS的配置都存储在名为coredns的ConfigMap对象中,如下所示:
[root@master231 ~]# kubectl -n kube-system get cm coredns -o yaml
apiVersion: v1
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes yinzhengjie.com in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
kind: ConfigMap
metadata:
creationTimestamp: "2020-12-15T07:46:40Z"
name: coredns
namespace: kube-system
resourceVersion: "281"
uid: 57ed9148-c8ee-4be5-8ae3-01785ab3874f
[root@master231 ~]#
关于CoreDNS的相关配置参数如上表所示。
本文来自博客园,作者:尹正杰,转载请注明原文链接:https://www.cnblogs.com/yinzhengjie/p/18717410,个人微信: "JasonYin2020"(添加时请备注来源及意图备注,有偿付费)
当你的才华还撑不起你的野心的时候,你就应该静下心来学习。当你的能力还驾驭不了你的目标的时候,你就应该沉下心来历练。问问自己,想要怎样的人生。

浙公网安备 33010602011771号