说明:'严格意义上'并不是讲解service,讲的是'core-dns',只是二者的关俩深度比较广
一 官网文档
说明: 本文主要讲解Service的'服务发现'机制,依赖于'core-dns'这个'add-on插件'
二 服务发现
(1)问题引入
我们可以通过 Service '生成的 ClusterIP(VIP)' 来访问 Pod 提供的服务,但是在使用的时候还有一个'问题':我们'怎么知道'某个应用的 VIP 呢?
场景: 比如我们'有两个应用',一个是 api 应用,一个是 db 应用,'两个应用'都是通过 Deployment 进行管理的,并且都'通过 Service 暴露'出了端口提供服务
api 需要连接到 db 这个应用,我们只知道 'db 应用的名称'和 'db 对应的 Service 的名称',但是'并不知道'它的 VIP 地址,我们知道了 VIP 的地址是不是就行了?
++++ '如何解决' ++++
早期'环境变量'、后期'Core-dns'-->可以理解为'集群内置'的'dns服务器'
(2)服务查找
① 环境变量
'了解'该参数即可
查看Pod中'注入的'环境变量
为了解决'上面的'问题,在之前的版本中,Kubernetes 采用了'环境变量'的方法
'特点': 每个 Pod 启动的时候,会把系统中'已有kubernetes中的Service'注入到环境变量中,通过环境变量设置'所有服务的 IP 和 port 信息',这样 Pod 中的应用可以通过'读取环境变量'来获取依赖'服务的地址信息',这种方法使用起来'相对简单'
'缺点': 依赖的服务必须在 'Pod 启动之前'就存在,不然是'不会被注入'到环境变量中的-->也即后面创建的Service是'不会注入'到到这个Pod中,除非Pod'重启'-->因为:'环境变量是系统启动后才注入的'
② core-dns
1)kubernetes服务
说明: 这个就是之前说过的'自己创建'Service和Endpoints --> 类似于把'集群外二进制的etcd'引入到'kubernetes集群内'
2)core-dns
由于上面'环境变量'这种方式的'局限性',我们需要一种更加'智能'的方案
比较'理想的方案':那就是可以直接使用 'Service 的名称',因为 Service 的名称'不会变化',我们不需要去关心'分配的' ClusterIP 的地址,因为这个地址并'不是固定不变的',所以如果我们'直接使用' Service 的名字,然后对应的 ClusterIP '地址的转换能够自动完成'就很好了。
我们知道'名字'和 'IP' 直接的转换是不是和我们平时'访问的网站'非常类似啊?他们之间的转换功能'通过 DNS' 就可以解决了,同样的'Kubernetes 也提供了 DNS 的方案'来解决上面的服务发现的问题
+++++++++++++++++++++'分割线1'+++++++++++++++++++++
DNS 服务'不是一个独立'的系统服务,而是作为'一种 addon 插件'而存在,现在'比较推荐'的插件: 'CoreDNS',kubernets'新版本'中已经默认是 CoreDNS 了
备注:kubernetes'早期插件'是kube-dns,但是kube-dns '默认'一个 Pod 中需要'3个容器'配合使用,CoreDNS 只需要一个容器即可
+++++++++++++++++++++'分割线2'+++++++++++++++++++++
CoreDns 是用 'GO语言' 写的高性能,高扩展性的 DNS 服务,基于 'HTTP/2 Web 服务 Caddy' 进行编写的。
CoreDns 内部采用'插件机制',所有功能都是'对应插件'形式编写,用户也可以'扩展'自己的插件
+++++++++++++++++++++'分割线3'+++++++++++++++++++++
查看Kubernetes 部署 CoreDns 时的'默认配置'-->'Corefile'
1)每个 '{}' 代表一个 'zone',格式是 "Zone:port{}", 其中"."代表默认zone
2)'{} 内'的每个名称代表'插件的名称',只有配置的插件才会启用
3)当'解析域名时',会先匹配 zone'都未匹配会执行默认 zone',然后 zone 内的插件从'上到下'依次执行,匹配后返回处理(执行过的插件从下到上依次处理返回逻辑),不再执行下一个插件
备注: 这个顺序并'不是配置文件内'谁在前面的顺序.而是core/dnsserver/'zdirectives.go内'的顺序
3)core-dns的设置
CoreDNS 的 Service 地址一般情况下'是固定的',CoreDNS 的 Service 地址就是 '10.96.0.10-->默是第10个'
备注1: 该 IP 被分配后,kubelet 会将使用 '--cluster-dns=<dns-service-ip>' 参数配置的 DNS 传递给'每个Pod中的容器'。
备注2: DNS 名称也需要域名,本地域可以使用参数--cluster-domain = <default-local-domain> '在 kubelet 中配置'
以下是'命令行'的方式,官方说'废弃了','不建议'用
4)创建Service 生成的 DNS 记录
备注: 为了防止core-dns做'无效的'解析,最好写上'service的全路径'
① 普通Service
普通的 Service: 会生成 'servicename.namespace.svc.cluster.local' 的域名,会解析到 Service 对应的 ClusterIP 上
备注1: 在 Pod 之间的调用可以'简写成' servicename.namespace
备注2: 如果处于'同一个命名空间'下面,甚至可以'省略简写'成 'servicename'
② Headless Service
'无头服务',就是把 clusterIP 设置为 'None' 的,访问'Headless Service'会被解析为指定 Pod 的 IP 列表
命名形式: 'podname'.headless-service-name.namespace.svc.cluster.local 访问到'具体的'某一个 Pod
5) dns策略
需要注意的是 'Default' 并'不是默认的 DNS 策略',如果'未明确指定' dnsPolicy,则'使用 ClusterFirst'
各'参数'的含义
了解'coredns'对应的pod
kubectl get pods -n kube-system coredns-6d56c8448f-pz2j7 '-o yaml'
备注: 实际coredns相关pod中的'/etc/resolv.conf'默认是node中的'/etc/resolv.conf'
需求: '自定义'pod中的/etc/resolv.conf
Pod中进行'自定义配置'-->'必须配置这两个参数'
dnsPolicy: None
dnsConfig:
+++'案例如下'+++
apiVersion: v1
kind: Pod
metadata:
namespace: default
name: dns-example
spec:
containers:
- name: test
image: nginx
dnsPolicy: "None"
dnsConfig:
nameservers:
- 1.2.3.4
searches:
- ns1.svc.cluster-domain.example
- my.dns.search.suffix
options:
- name: ndots
value: "2"
- name: edns0
说明: /etc/resolv.conf'自己生成'
结果
nameserver 1.2.3.4
search ns1.svc.cluster-domain.example my.dns.search.suffix
options ndots:2 edns0
三 给pod中注入一条记录
1)方式1:hostALias
说明: '1.7+之后'提供的新特性
说明: 观察容器中'/etc/hosts'的变化
说明: 设置的话默认给'ns下所有的Pod'注入相应的记录 -->'准入控制器'
3)hosts插件
具体: 修改coredns这个'deployment'的configmap
coredns '自带 hosts 插件','开箱即用',允许像配置 hosts 一样配置'自定义 DNS 解析'
kubectl edit cm -n kube-system coredns --> '在线编辑'
说明1: configmap'热更新'需要'1~2'分钟才生效
说明2: 生效后作用全局-->所有的'ns'
说明3: 并没有在所有container的'/etc/hosts'本地解析注入
四 给Pod添加DNS解析记录
(1)StatefulSet自动给Pod添加DNS解析记录
我们都知道 'StatefulSet 中的 Pod' 是拥有'单独的 DNS 记录'的
举例: 比如一个 'StatefulSet 名称'为 etcd,而它关联的 'Headless SVC 名称'为 etcd-headless,那么 CoreDNS 就会为它的'每个 Pod 解析'如下的记录:
etcd-0.etcd-headless.default.svc.cluster.local
etcd-1.etcd-headless.default.svc.cluster.local
+++++++++++++++++++'问题抛出'+++++++++++++++++++
除了 StatefulSet 管理的 Pod 之外,'其他的 Pod' 是否也可以'生成 DNS 记录'呢?
(2)普通Pod添加DNS解析记录
强调: hostname 和 pod 的名字是'有区别的'
Pod 规范中包含一个'可选的 hostname 字段',可以用来'指定 Pod 的主机名',当这个字段被设置时,它将'优先于 Pod 的名字'成为该 Pod 的主机名
举个例子:给定一个 hostname 设置为 "my-host" 的 Pod,该 Pod 的主机名将被设置为 "my-host",Pod 规约还有一个'可选的 subdomain 字段',可以用来指定 Pod 的子域名
举个例子:某 Pod 的 hostname 设置为 'foo',subdomain 设置为 'bar', 在名字空间 'my-namespace' 中对应的完全限定域名为 'foo.bar.my-namespace.svc.cluster-domain.example'
+++++++++++++++++'在DNS中的记录'+++++++++++++++++
<hostname>.<subdomain>.<pod namespace>.svc.<cluster domain>
# individual-pods-example.yaml
apiVersion: v1
kind: Service
metadata:
name: default-subdomain
spec:
selector:
name: busybox
clusterIP: None
ports:
- name: foo # Actually, no port is needed.
port: 1234
targetPort: 1234
---
apiVersion: v1
kind: Pod
metadata:
name: busybox1
labels:
name: busybox
spec:
hostname: busybox-1 '核心关注1'
subdomain: default-subdomain '核心关注2'
containers:
- image: busybox:1.28
command:
- sleep
- "3600"
name: busybox
---
apiVersion: v1
kind: Pod
metadata:
name: busybox2
labels:
name: busybox
spec:
hostname: busybox-2
subdomain: default-subdomain
containers:
- image: busybox:1.28
command:
- sleep
- "3600"
name: busybox
结论: 看到有 'ANSWER 记录'回来了
强调: 'hostname' 和 'subdomain' 二者都'必须显式指定',缺一不可
五 添加一个自定义的dns服务器
说明: 本文主要是'扩展'知识
七 5s超时
service ip是如何避免冲突