注:本文基于kubeadm安装的k8s集群编写
k8s中的服务通过ingress暴露给外部后,我们就能访问该服务。但是此时我们只能基于ingress暴露的ip来访问,这肯定不是个好主意,此时我们就需要将域名绑定到IP上。一般来说这里都需要手动到DNS服务商配置,对于ip变化频繁的话,还是很繁琐的。这时我们就可以考虑使用external-dns服务。
external-dns将Kubernetes的Service/Ingress暴露的服务(的DNS记录)同步给外部的DNS Provider
为了更方便演示效果,我们直接用coredns做为external-dns的提供商,但是这样解析的效果只能作用于集群内,大家可以根据实际情况与aws集成。
因为我们使用的是coredns,因此后端存储就用集群内的etcd实例,需要添加对应插件,其实就是添加响应的配置,
.:53 {
...
etcd example.org {
path /skydns
endpoint https://192.168.0.180:2379
tls /tls/server.crt /tls/server.key /tls/ca.crt
fallthrough .
}
}
修改coredns的configmap,添加etcd section,其中,
example.org:指定应用的域名范围
path:指定数据存放路径
endpoint:指定etcd的地址,这里需要用节点ip,不能用127地址,不然其他节点就无法访问
tls:指定对应的证书,因为我们需要从其他节点访问,因此需要验证,后面还会对这个路径说明
上面用到的证书,其实就是目录/etc/kubernetes/pki/etcd/下的证书,由kubeadm生成,我们可以将他们导入集群,作为secret来引用,
kubectl create secret generic etcd-client-certs --from-file=ca.crt=/etc/kubernetes/pki/etcd/ca.crt --from-file=server.crt=/etc/kubernetes/pki/etcd/server.crt --from-file=server.key=/etc/kubernetes/pki/etcd/server.key -n kube-system
修改对应deployment,添加对应的volume和volumeMounts,
spec:
volumes:
- name: etcd-client-certs
secret:
secretName: etcd-client-certs
defaultMode: 400
...
containers:
- name: coredns
...
volumeMounts:
- name: etcd-client-certs
readOnly: true
mountPath: /tls/
这样,coredns部分就就绪了,下面就可以开始安装external-dns。
我们直接使用helm来安装,先添加external-dns的repo,这里我们使用bitnami,
helm repo add bitnami https://charts.bitnami.com/bitnami
然后我们需要设置一些配置,
helm install external-dns bitnami/external-dns --namespace=external-dns \
--set sources="{ingress}" --set policy=sync --set logLevel=debug \
--set provider=coredns --set image.tag=0.10.0 \
--set coredns.etcdEndpoints=https://192.168.0.180:2379 \
--set coredns.etcdTLS.enabled=true \
--set coredns.etcdTLS.caFilename=ca.crt \
--set coredns.etcdTLS.certFilename=server.crt \
--set coredns.etcdTLS.keyFilename=server.key
其中,
另外,因为coredns provider默认使用etcd-client-certs这个secret,因此我们需要将对应的证书导入,和上面coredns里类似,只不过换个namespace,
kubectl create secret generic etcd-client-certs --from-file=ca.crt=/etc/kubernetes/pki/etcd/ca.crt --from-file=server.crt=/etc/kubernetes/pki/etcd/server.crt --from-file=server.key=/etc/kubernetes/pki/etcd/server.key -n external-dns
这样,external-dns也配置完毕,我们可以看下pod状态,
[root@master etcd]# kubectl get pod -n external-dns
NAME READY STATUS RESTARTS AGE
external-dns-76cb6d74c6-c8vq5 1/1 Running 0 23h
为了测试效果,我们需要新建一个ingress资源,假设集群里已经部署了一个webservice的服务,我们需要将其域名设置为web.example.org,
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test1-ingress
annotations:
ingress.kubernetes.io/rewrite-target: /
namespace: ingress-nginx
spec:
ingressClassName: nginx
rules:
- host: web.example.org
http:
paths:
- path: /
backend:
service:
name: webservice
port:
number: 10080
pathType: Prefix
创建资源后,确认address已分配,
[root@master ingress]# kubectl get ingress -n ingress-nginx
NAME CLASS HOSTS ADDRESS PORTS AGE
test1-ingress nginx web.example.org 192.168.0.180 80 24h
此时,我们可以在集群中创建一个debug pod来测试这个域名,
[root@master ~]# kubectl run centos -it --image=centos:7 -- /bin/bash
If you don't see a command prompt, try pressing enter.
[root@centos /]# yum install -y bind-utils
[root@centos /]# nslookup web.example.org
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: web.example.org
Address: 192.168.0.180
可见此时域名已经在集群内生效了。
一般我们在生产环境中,会部署两套external-dns,一套对内,一套的对外,这样更方便管理。
参考文档: