DNS
Kubernetes中存在一个DNS服务,其作用是提供一个service名和IP的对应关系
以下是DNS服务常见的资源
[root@master ~]# kubectl get deploy,po,svc,ep -n kube-system | grep dns
deployment.apps/coredns 2/2 2 2 25h
pod/coredns-66f779496c-dvbjx 1/1 Running 1 (5h56m ago) 25h
pod/coredns-66f779496c-fvjkt 1/1 Running 1 (5h56m ago) 25h
service/kube-dns ClusterIP 10.65.0.10 <none> 53/UDP,53/TCP,9153/TCP 25h
endpoints/kube-dns 10.64.219.73:53,10.64.219.75:53,10.64.219.73:53 + 3 more... 25h
CoreDNS 是一个灵活可扩展的 DNS 服务器,可以作为 Kubernetes 集群 DNS。 与 Kubernetes 一样,CoreDNS 项目由 CNCF 托管。目前使用官方的kubeadm安装工具进行部署会自动安装CoreDNS,其他的Kubernetes 发行版也将CoreDNS 作为默认的DNS服务,如rancher。
配置文件格式
配置文件使用cm进行传递,格式如下:
[root@master ~]# kubectl get cm -n kube-system coredns -o yaml
apiVersion: v1
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local 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: "2023-12-13T05:47:21Z"
name: coredns
namespace: kube-system
resourceVersion: "255"
uid: d1ad3fbe-7c4a-45d8-af31-10c082c3a442
大括号中即是CoreDNS的配置项,意义如下:
- errors:错误信息到标准输出。
- health:CoreDNS自身健康状态报告,默认监听端口8080,一般用来做健康检查。您可以通过http://10.18.206.207:8080/health获取健康状态。(10.18.206.207为coredns其中一个Pod的IP)
- ready:CoreDNS插件状态报告,默认监听端口8181,一般用来做可读性检查。
- kubernetes:CoreDNS kubernetes插件,提供集群内服务解析能力。
- prometheus:CoreDNS自身metrics数据接口。
- forward:将域名查询请求转到预定义的DNS服务器。
- cache:DNS缓存时长,单位秒。
- loop:环路检测,如果检测到环路,则停止CoreDNS。
- reload:允许自动重新加载已更改的Corefile。编辑ConfigMap配置后,请等待两分钟以使更改生效。
- loadbalance:循环DNS负载均衡器,可以在答案中随机A、AAAA、MX记录的顺序。
服务入口
服务入口有三个主要概念:
ingress:用来定义路由规则
ingress controller:解析ingress定义的路由规则并提供服务
ingress class:将ingress与ingress controller关联在一起
ingress
ingress对象描述了一组服务的访问规则,并通过ingress插件将服务发布出去,用户和其他系统通过对应的规则访问到对应的服务。
ingress示例:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /apppath
spec:
rules:
- http:
paths:
- path: /apppath
backend:
service:
name: test
port: 80
ingress controller
仅创建 Ingress 资源本身是没有任何作用的,还需要部署 Ingress Controller。为了让 Ingress 资源工作,集群必须有一个正在运行的 Ingress Controller。
Ingress Controller不是随集群自动启动的。 基于此页面,可选择最适合你的集群的 ingress 控制器实现。
Kubernetes 作为一个项目,目前支持和维护 AWS、 GCE 和 Nginx Ingress 控制器。
常见的ingress controller可以在此地址查看:
https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress-controllers/#additional-controllers
ingress class
在 Kubernetes 1.18 之前,需要在 Ingress 资源上通过 kubernetes.io/ingress.class 注解来指定使用的 Ingress Controller。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /apppath
spec:
rules:
- http:
paths:
- path: /apppath
backend:
service:
name: test
port: 80
在创建 Ingress Controller 对象时,通过 --ingress-class 来指定此 Ingress Controller 对应的 class,如:
spec:
containers:
- args:
- /nginx-ingress-controller
- --ingress-class=nginx
这种方式可以将 Ingress 资源与 Ingress Controller 联系在一起,进行工作。但带来的问题是这两个资源的关联非常紧密。
随着集群规模不断变大,应用的访问需求不断增加,单一的 Ingress Controller 很难满足需求,可能需要用到不同的 Ingress Controller 共同协作,这样紧密的关系无法满足部署多个 Ingress Controller 的场景,这样就有了 ingress class。
示例如下:
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb
spec:
controller: example.com/ingress-controller
parameters:
apiGroup: k8s.example.com
kind: IngressParameters
name: external-lb
其中重要的属性是 metadata.name 和 spec.controller,前者是这个 IngressClass 的名称,需要设定在 Ingress 中,后者是 Ingress Controller 的名称。
spec.parameters属性用于定义一些额外的配置。
在 Ingress 中添加 spec.ingressClassName 参数即可关联在此 IngressClass 上。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
spec:
ingressClassName: external-lb
defaultBackend:
service:
name: test
port:
number: 80
节点调度
K8S调度器kube-schduler的主要作用是将新创建的Pod调度到集群中的合适节点上运行。kube-schduler的调度算法非常灵活,可以根据不同的需求进行自定义配置,比如资源限制、亲和性和反亲和性等。
kube-schduler的工作原理:
- 监听API Server:kube-schduler会监听API Server上的Pod对象,以获取需要被调度的Pod信息。
- 节点预选:kube-schduler会根据Pod的资源需求和约束条件筛选出可用的Node节点。
- 计算分值:kube-schduler会为每一个可用节点计算一个分值,计算方法可以通过调度算法指定。
- 选择节点:kube-schduler会选择分值最高的节点作为最终的调度目标,如果多个节点分数相等,kube-schduler会随机选择一个节点。
- 更新API Server:kube-schduler会更新API Server上的Pod对象,将选定的Node节点信息写入Pod对象的spec字段中。
NodeSelector
NodeSelector会将Pod根据定义的标签选定到匹配的Node上去。
关键词:
- nodeSelector:预选规则,调度器的节点选择范围缩小有某一个或几个标签的节点上
示例:
apiVersion: v1
kind: Pod
metadata:
name: nginx-ssd
spec:
containers:
- name: nginx-ssd
image: nginx:1.23.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
nodeSelector:
disktype: ssd
此示例会把此pod调度到含有 disktype: ssd 标签的节点中,但由于其是预选函数,调度器会将所有含有同样标签的节点都作为备选的调度节点,然后根据调度算法选取一个最优节点进行调度。
节点亲和性NodeAffinity
NodeAffinity的目的是把Pod部署到符合要求的Node上。
关键词:
- requiredDuringSchedulingIgnoredDuringExecution:表示强匹配,必须要满足,否则不进行调度
- preferredDuringSchedulingIgnoredDuringExecution:表示弱匹配,尽可能满足,优先在符合要求的节点调度
示例:
apiVersion: v1
kind: Pod
metadata:
name: node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: ##必须满足下面匹配规则
nodeSelectorTerms:
- matchExpressions:
- key: env
operator: NotIn ##逻辑运算符支持:In,NotIn,Exists,DoesNotExist,Gt,Lt
values:
- test
- dev
preferredDuringSchedulingIgnoredDuringExecution: ##尽可能满足,但不保证
- weight: 1
preference:
matchExpressions:
- key: project
operator: In
values:
- app
containers:
- name: redis
image: redis
Pod亲和性与反亲和
podAffinity、podantiAffinity的目的是把Pod部署到符合要求的Node上。‘
关键词:
- podAffinity:将Pod与符合匹配规则的Pod调度在一起
- podAntiAffinity:将Pod与符合匹配规则的Pod不调度在一起
- requiredDuringSchedulingIgnoredDuringExecution:表示强匹配,必须要满足,否则不进行调度
- preferredDuringSchedulingIgnoredDuringExecution:表示弱匹配,尽可能满足,优先在符合要求的节点调度
示例:
apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAffinity: # pod亲和规则
requiredDuringSchedulingIgnoredDuringExecution: # 必须要满足此规则,此规则匹配 security = S1 的Pod
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: kubernetes.io/hostname
podAntiAffinity: # 反亲和规则
preferredDuringSchedulingIgnoredDuringExecution: # 尽量满足此规则,此规则匹配 security = S2 的Pod
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S2
topologyKey: kubernetes.io/hostname
containers:
- name: with-pod-affinity
image: k8s.gcr.io/pause:2.0
此示例定义了一个Pod,此Pod有特殊的调度方式:
- 需要将其与拥有 security = S1 标签的Pod调度在一起
- 同时需要注意尽量不和拥有 security = S2 标签的Pod调度在一起
污点和容忍
污点(Taint)针对节点来说,和节点亲和性正好相对,节点亲和性使Pod被吸引到一类特定的节点,而污点则使节点能够排斥一类特定的Pod。
容忍度(Toleration)应用于Pod上,它用来允许调度器调度带有对应污点的节点。 容忍度允许调度但并不保证调度:作为其功能的一部分, 调度器也会评估其他参数。
污点和容忍度(Toleration)相互配合,可以避免Pod被分配到不合适的节点上。 每个节点上都可以应用一个或多个污点,这表示对于那些不能容忍这些污点的Pod, 是不会被该节点接受的。
命令格式如下:
kubectl taint node [node] key=value:[effect]
说明:
其中[effect] 可取值:[ NoSchedule | PreferNoSchedule | NoExecute ]:
NoSchedule :一定不能被调度,已经在运行中的Pod不受影响。
PreferNoSchedule:尽量不要调度,实在没有节点可调度再调度到此节点。
NoExecute:不仅不会调度,还会驱逐Node上已有的Pod。
清除污点命令格式:
kubectl taint node [node] key:[effect]-
设置容忍的几种规则:
1、 匹配特定污点
tolerations:
- key: "taintKey" #和污点的key名字保持一致
operator: "Equal" #匹配类型,Equal表示匹配污点的所有值
value: "taintValue" #和污点key的值保持一致
effect: "NoSchedule" #污点类型
2、不完全匹配(未比对污点key的value)
tolerations:
- key: "taintKey" #和污点的key名字保持一致
operator: "Exists" #匹配类型,只要符合污点设置的key即可
effect: "NoSchedule" #污点的类型
3、范围匹配(仅匹配了污点key是否存在)
tolerations:
- key: "taintKey" #和污点的key名字保持一致
operator: "Exists"
4、匹配所有(仅匹配了是否存在污点)
tolerations:
- operator: "Exists"
可以通过以下配置设置驱逐容忍时间:
如果这个Pod 正在运行,此时节点被打上对应的污点,那么Pod还将继续在节点上运行3600秒,然后被驱逐。 如果在此之前上述污点被删除了,则Pod不会被驱逐。
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
tolerationSeconds: 3600
完整Pod YAML示例:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: dev
spec:
containers:
- name: ng
image: nginx:1.21.0
tolerations:
- key: name
operator: Exists
effect: NoSchedule