k8s集群coredns无法解析外部域名
1. 问题现象公司内部SaaS产品运行在阿里云kubernetes环境,使用阿里云[标准托管版]进行部署使用,[标准托管版] 版就是用户只需要自己运维k8s node节点,master节点由阿里云进行维护,当k8s环境部署完成之后,将公司生产业务部署后发现部分业务模块无法解析到阿里云OSS自定义的对象存储域名,导致业务出现异常;业务模块是可以通过域名访问其他业务模块及互联网域名的,而且业务模块配置
1. 问题现象
公司内部SaaS产品运行在阿里云kubernetes环境,使用阿里云[标准托管版]进行部署使用,[标准托管版] 版就是用户只需要自己运维k8s node节点,master节点由阿里云进行维护,当k8s环境部署完成之后,将公司生产业务部署后发现部分业务模块无法解析到阿里云OSS自定义的对象存储域名,导致业务出现异常;
业务模块是可以通过域名访问其他业务模块及互联网域名的,而且业务模块配置了SNAT都是可以访问互联网的
1.1. 问题分析
公司域名后缀为*.oneprocloud.com,统一方便管理,所有的资源均使用子域名
在阿里云我们采用2个4核16G的云主机作为Node节点进行部署公司生产业务,因为有部分业务模块需要访问阿里云OSS对象存储进行访问数据,OSS对象存储我们设置了自定义域名,为了方便访问,短域名地址为"downloads.oneprocloud.com",并配置了智能DNS解析,办公笔记本可以解析短域名地址,即判定自定义短域名生效,可以正常使用
在k8s业务模块内进行如下测试:
- nslookup进行解析互联网地址,是可以正常解析的
# www.baidu.com可以正常解析
[root@jumpserver-7596dc7dcb-lcs4n ~]# nslookup www.baidu.com
Server: 10.0.0.10
Address: 10.0.0.10#53
Non-authoritative answer:
www.baidu.com canonical name = www.a.shifen.com.
Name: www.a.shifen.com
Address: 220.181.38.149
Name: www.a.shifen.com
Address: 220.181.38.150
- nslookup解析自定义阿里云OSS域名地址,发现无法进行解析
# www.baidu.com可以正常解析
[root@jumpserver-7596dc7dcb-lcs4n ~]# nslookup downloads.oneprocloud
Server: 10.0.0.10
Address: 10.0.0.10#53
Server: 10.0.0.10
Address: 10.0.0.10#53
Non-authoritative answer:
*** Can't find downloads.oneprocloud.com: No answer
经过以上测试,分析为在k8s集群内部,都是去找coredns 10.0.0.10 DNS进行解析域名,www.baidu.com 就可以解析,但是我们自定义的downloads.oneprocloud.com就无法解析,这个现象很诡异,我们接着查看coredns的配置:
查看k8s集群的coredns配置:
# 查看kube-system下的coredns configmap
[root@jumpserver-7596dc7dcb-lcs4n ~]# kubectl get configmap -n kube-system
NAME DATA AGE
ack-cluster-profile 6 16d
acr-configuration 5 16d
coredns 1 16d
extension-apiserver-authentication 6 16d
kube-flannel-cfg 2 16d
kube-proxy-worker 2 16d
kubeadm-config 1 16d
kubelet-config-1.11 1 16d
kubelet-config-1.12 1 16d
kubelet-config-1.18 1 16d
kubernetes-dashboard-settings 1 13d
# 查看coredns的configmap的定义是如何的,其实就是看看dns的配置
[root@jumpserver-7596dc7dcb-lcs4n ~]# kubectl get configmap -n kube-system coredns -o yaml
apiVersion: v1
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes oneprocloud.com in-addr.arpa ip6.arpa { # 在Corefile配置文件我们发现dns的域配置的oneprocloud.com
pods verified
upstream
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
autopath @kubernetes
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
kind: ConfigMap
metadata:
annotations: # 这边的配置信息也是 oneprocloud.com域名
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","data":{"Corefile":".:53 {\n errors\n health {\n lameduck 5s\n }\n ready\n\n kubernetes oneprocloud.com in-addr.arpa ip6.arpa {\n\n pods verified\n upstream\n fallthrough in-addr.arpa ip6.arpa\n ttl 30\n }\n autopath @kubernetes\n prometheus :9153\n forward . /etc/resolv.conf\n cache 30\n loop\n reload\n loadbalance\n}\n"},"kind":"ConfigMap","metadata":{"annotations":{},"creationTimestamp":"2021-01-11T10:33:07Z","managedFields":[{"apiVersion":"v1","fieldsType":"FieldsV1","fieldsV1":{"f:data":{".":{},"f:Corefile":{}},"f:metadata":{"f:annotations":{".":{},"f:kubectl.kubernetes.io/last-applied-configuration":{}}}},"manager":"rc","operation":"Update","time":"2021-01-11T10:33:07Z"}],"name":"coredns","namespace":"kube-system","resourceVersion":"24861979","selfLink":"/api/v1/namespaces/kube-system/configmaps/coredns","uid":"7891c2a7-bff4-4f81-abaa-d06abb0ddf35"}}
creationTimestamp: "2021-01-11T10:33:07Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data: {}
f:metadata:
f:annotations: {}
manager: rc
operation: Update
time: "2021-01-11T10:33:07Z"
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
f:Corefile: {}
f:metadata:
f:annotations:
f:kubectl.kubernetes.io/last-applied-configuration: {}
manager: kubectl
operation: Update
time: "2021-01-27T10:22:30Z"
name: coredns
namespace: kube-system
resourceVersion: "145403500"
selfLink: /api/v1/namespaces/kube-system/configmaps/coredns
uid: 7891c2a7-bff4-4f81-abaa-d06abb0ddf35
问题分析结果如下:
通过以上信息查看,其实oneprocloud.com是coredns的解析域,这个应该是在阿里云上部署k8s的时候设置的,这个域名会在k8s集群内部进行生效,作用是什么那,比如两个业务模块之间需要访问的话,我定义了模块的services,我就可以通过xxx.oneprocloud.com这个域名去访问其他业务模块是实现域名注册,xxx就为子域名,只能在k8s集群内部访问,其实我们定义的downloads.oneprocloud.com也是 xxx的子域名,但是并没有在k8s集群内部定义这种services,所以解析的时候,coredns认为这是同一个域内部的,然后去解析发现解析不到,但是为什么www.baidu.com域名可以访问那,是因为非oneprocloud.com后缀域,coredns正常集群外域名如果coredns解析不了,会去coredns的ecs配置的nameserver解析。所以才会出现www.baidu.com可以解析,downloads.oneprocloud.com解析不了的现象;
2. 问题处理方法
针对此问题,个人能力有限,不确定是否有更好的解决办法,例如设置tag文件,写明同一个域的其他子域名,如果coredns在内部集群解析不到的话,先去查询此tag文件,然后再进行找外部dns进行解析,只是个人想法
以上问题的发生,因为k8s环境已经部署完成,业务也已经部署了,总不能重新部署吧,那这个代价也太大了,有没有办法修改coredns配置,让其更改一个另外的解析域。
我这边大概想到2个方案:
- 第一个方案
k8s集群内部解析域不变,变动外部自定义OSS对象域名,更换成其他的后缀域名
- 第二个方案
改变k8s集群内部解析域,外部自定义OSS对象域名保持不变
根据以上两个方案分析,其实第二个方案还是比较合适的,因为公司内部的注册域这个肯定不可能变化的,我总不能再注册一个其他的后缀域吧,这个维护和代价成本也比较大,k8s集群内部域其实就是一个内部的,只要服务能够直接可以解析就可以了,所以第二个方案比较合适,第二个方案的处理办法继续往下
2.1. 修改k8s内部解析域名
如何按照我们的解决方案,第二个方案更改k8s集群内部coredns配置,需要如下两个操作步骤:
- 修改集群的coredns configmap文件
- 修改所有k8s集群node节点的kubelet服务的配置文件,并重启kubelet服务
- 重建业务pod服务
2.1.1. 修改集群coredns cm文件
- 查看集群coredns cm配置文件并保存
[root@jumpserver-7596dc7dcb-lcs4n ~]# kubectl get configmap -n kube-system coredns -o yaml > coredns-configmap.yaml
- 修改coredns cm配置 (以下红色标记的两处域名,修改成其他自定义)
[root@jumpserver-7596dc7dcb-lcs4n ~]# vim coredns-configmap.yaml
apiVersion: v1
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes **cluster.local** in-addr.arpa ip6.arpa {
pods verified
upstream
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
autopath @kubernetes
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
kind: ConfigMap
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","data":{"Corefile":".:53 {\n errors\n health {\n lameduck 5s\n }\n ready\n\n kubernetes **oneprocloud.com** in-addr.arpa ip6.arpa {\n\n pods verified\n upstream\n fallthrough in-addr.arpa ip6.arpa\n ttl 30\n }\n autopath @kubernetes\n prometheus :9153\n forward . /etc/resolv.conf\n cache 30\n loop\n reload\n loadbalance\n}\n"},"kind":"ConfigMap","metadata":{"annotations":{},"creationTimestamp":"2021-01-11T10:33:07Z","managedFields":[{"apiVersion":"v1","fieldsType":"FieldsV1","fieldsV1":{"f:data":{".":{},"f:Corefile":{}},"f:metadata":{"f:annotations":{".":{},"f:kubectl.kubernetes.io/last-applied-configuration":{}}}},"manager":"rc","operation":"Update","time":"2021-01-11T10:33:07Z"}],"name":"coredns","namespace":"kube-system","resourceVersion":"24861979","selfLink":"/api/v1/namespaces/kube-system/configmaps/coredns","uid":"7891c2a7-bff4-4f81-abaa-d06abb0ddf35"}}
creationTimestamp: "2021-01-11T10:33:07Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data: {}
f:metadata:
f:annotations: {}
manager: rc
operation: Update
time: "2021-01-11T10:33:07Z"
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
f:Corefile: {}
f:metadata:
f:annotations:
f:kubectl.kubernetes.io/last-applied-configuration: {}
manager: kubectl
operation: Update
time: "2021-01-27T10:22:30Z"
name: coredns
namespace: kube-system
resourceVersion: "145403500"
selfLink: /api/v1/namespaces/kube-system/configmaps/coredns
uid: 7891c2a7-bff4-4f81-abaa-d06abb0ddf35
- 重新进行应用
[root@jumpserver-7596dc7dcb-lcs4n ~]# kubectl apply -f coredns-configmap.yaml
2.1.2. 修改所有k8s集群node节点配置文件
这里需要注意是所有的节点kubelet配置文件都需要更改并重启服务,包含以后横向扩展的node节点,一定要记得也要同步修改节点配置文件,例如:当前2个node节点更改了,后续增加1个多个节点,同样也需要重复以下步骤,不然还是无法进行解析
- 修改配置文件/etc/systemd/system/kubelet.service.d/10-kubeadm.conf
修改配置文件中标红的内容,修改成自定义的域名,要和coredns configmap修改的域名保持一致
[Service]
Environment="KUBELET_EXTRA_ARGS=--node-labels=HM-SAAS-Lable=Production"
EnvironmentFile=-/etc/kubernetes/kubelet-customized-args.conf
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_SYSTEM_PODS_ARGS=--max-pods 64 --pod-max-pids 16384 --pod-manifest-path=/etc/kubernetes/manifests"
Environment="KUBELET_NETWORK_ARGS=--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin --dynamic-config-dir=/etc/kubernetes/kubelet-config --v=3"
Environment="KUBELET_DNS_ARGS=--enable-controller-attach-detach=true --cluster-dns=10.0.0.10 --pod-infra-container-image=registry-vpc.cn-beijing.aliyuncs.com/acs/pause:3.2 --enable-load-reader --cluster-domain=**cluster.local** --cloud-provider=external --hostname-override=cn-beijing.192.168.1.156 --provider-id=cn-beijing.i-2ze6kkewztaauih0izyr"
Environment="KUBELET_AUTHZ_ARGS=--authorization-mode=Webhook --authentication-token-webhook=true --anonymous-auth=false --client-ca-file=/etc/kubernetes/pki/ca.crt"
Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=systemd"
Environment="KUBELET_CERTIFICATE_ARGS=--tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256 --tls-cert-file=/var/lib/kubelet/pki/kubelet.crt --tls-private-key-file=/var/lib/kubelet/pki/kubelet.key --rotate-certificates=true --cert-dir=/var/lib/kubelet/pki"
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_AUTHZ_ARGS $KUBELET_CGROUP_ARGS $KUBELET_CERTIFICATE_ARGS $KUBELET_EXTRA_ARGS $KUBELET_CUSTOMIZED_ARGS
- 重新加载配置文件并重启kubelet服务
[root@iZ2ze6kkewztaauih0izyrZ ~]# systemctl daemon-reload
[root@iZ2ze6kkewztaauih0izyrZ ~]# systemctl restart kubelet
2.1.3. 重建业务pod服务
将所有的业务pod重建,不然无法使用最新的coredns配置进行服务注册发现
# 按照业务pod重建方式
# kubectl replace --force -f xxxx.yaml
2.1.4. 验证业务域名访问
-
验证corends cm配置
-
验证域名解析
通过nslookup进行解析测试,发现已经可以正常解析外部域名
3. 问题分析结论
在k8s集群内部设置了域,例如*.oneprocloud.com,那么oneprocloud.com就会被认为是集群内的域名,只向coredns进行域名解析,如果你在互联网也设置了同样后缀的DNS域名解析,在coredns内部是解析不了的,需配置配置其他外部域进行访问,正常集群外域名如果coredns解析不了,例如:*.baidu.com 那么coredns会去coredns所在ecs节点配置的nameserver进行解析。
更多推荐
所有评论(0)