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的相关配置参数如上表所示。
posted @ 2025-02-15 21:08  尹正杰  阅读(167)  评论(0)    收藏  举报