在 K8S 中配置域名解析
在应用开发中,我们不应把远程服务的 ip 硬编码到应用中。有些同学习惯使用域名来标定远程服务,通过修改解析,来区分开发测试和生产环境,这是一个挺好的习惯。在 k8s 系统中,我们使用服务名来调用服务,并通过 coredns 来进行解析。但那些集群外的服务,并且已经被硬编码的域名如何访问呢?
此文拷贝自自己的旧文章,为防止知识过期,在 aws eks 上重新验证成功。
方法1:修改容器实例的 hosts
设想:把 hosts 文件内容存储在 ConfigMap 中,通过 volume 绑定到 /etc/hosts。但很不幸,/etc/hosts 被 k8s 征用了,无法修改。
但 K8S 给我们提供了 hostAliases 来解决此问题。
apiVersion: apps/v1
kind: Deployment
metadata:
name: hosts-append
labels:
app: hosts-append
spec:
replicas: 1
selector:
matchLabels:
app: hosts-append
template:
metadata:
labels:
app: hosts-append
spec:
hostAliases:
- ip: "127.0.0.1"
hostnames:
- "foo.local"
- "bar.local"
- ip: "10.1.2.3"
hostnames:
- "foo.remote"
- "bar.remote"
containers:
- image: nginx:alpine
name: hosts-append
ports:
- containerPort: 80
protocol: TCP
部署后,pod 里面的 hosts 文件已经追加了解析记录。查看结果如下:
kubectl exec hosts-append-<your-id> -- cat /etc/hosts
# Kubernetes-managed hosts file.
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
10.10.6.23 hosts-append-6f96d5449f-rldxr
# Entries added by HostAliases.
127.0.0.1 foo.local bar.local
10.1.2.3 foo.remote bar.remote
此方法的缺点是:不同环境下的域名映射是不一样的,必须为环境编写不同的 yaml 部署文件,并且给每一个 deployment 编写 hostAliases 会有点“侵入”。
方法2:使用内置 coredns 解析
K8S 内部默认已经安装了 coredns 服务,可以通过修改 coredns 的配置来达到内部解析的目的。
coredns 的配置写在了 configmap 的 kube-system 命名空间下的 coredns 配置节点了。只需要修改 hosts 配置节点内容就好。
编辑他:
kubectl edit cm -n kube-system coredns
配置示例(其中 hosts 节点是自定义的解析节点,如果没有 hosts 节点,可以增加一个):
.:53 {
errors
health
kubernetes cluster.local. in-addr.arpa ip6.arpa {
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
}
hosts {
127.0.0.1 foo.local
8.8.8.8 foo.remote
fallthrough
}
prometheus :9153
proxy . /etc/resolv.conf
cache 30
reload
loadbalance
}
修改完成后,要等等。配置下发完成即可生效。可以进入 pod 内部 ping 一下域名看看。
方法3. 使用自定义域名服务器解析
在 coredns 的 ConfigMap 中,还可以自定义 name server,配置类似:
apiVersion: v1
kind: ConfigMap
metadata:
annotations:
labels:
eks.amazonaws.com/component: coredns
k8s-app: kube-dns
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
domain-name:53 {
errors
cache 30
forward . custom-dns-server
reload
}
- 在
domain-name:53
节点中可以定义 name server - 如果没有这个节点,可以增加一个,此节点与
.:53
平级。
下面以 aws route53 为例进行测试。
首选进入 route53 控制台,进入 创建托管区。如图:
创建完成可以看到解析记录里 name server,地址类似如下:
ns-1536.awsdns-00.co.uk.
ns-0.awsdns-00.com.
ns-1024.awsdns-00.org.
ns-512.awsdns-00.net.
并添加一个新解析 A 记录,如下图:
编辑 ConfigMap,参考上面的配置,修改 K8S/EKS 的 name server
kubectl edit cm -n kube-system coredns
在 domain-name:53
节点设置 forward . ns-1536.awsdns-00.co.uk.
即可。
设置完成,进入 EKS 的 任意 pod 测试,ping 或者 dig 一下,结果如下:
# dig www.youbug.cn
; <<>> DiG 9.16.33-Debian <<>> www.youbug.cn
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42026
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: d032981648385382 (echoed)
;; QUESTION SECTION:
;www.youbug.cn. IN A
;; ANSWER SECTION:
www.youbug.cn. 30 IN A 192.168.0.1
;; Query time: 0 msec
;; SERVER: 172.20.0.10#53(172.20.0.10)
;; WHEN: Wed Dec 07 02:39:49 UTC 2022
;; MSG SIZE rcvd: 83
可以看到已经生效了。
其他云厂商的或者自建域名服务器可以使用类似方法,不一一赘述了。
使用场景总结
名称 | 方法 | 适用场景 |
hostAliases | 修改 pod 的 hosts 配置 | K8S 集群内部分 workloads 需要单独解析。开发者临时测试没有 ConfigMap 权限等。A/B Test。 |
coredns 直接解析 | 修改 ConfigMap 直接解析 | 完整的 K8S 开发测试环境,UAT 环境等 |
自定义 dns server | 修改 ConfigMap 配置以使用自定义域名服务器 | 多 K8S 集群,有非 K8S 负载,VPC 范围解析 |
当然,更好的做法是把 配置文件与应用解耦,所有的配置,包括远程服务的域名或 ip 都可以被远程修改。