因為想要使用FQDN的方式連接到Kubernetes cluster內部的應用服務,加上早已使用Linux Bind為測試環境的主要DNS,希望在滿足以下條件之下實現我的需求:
所以找到了一個老牌的Project: ExternalDNS,但滿多文章都是直接利用CoreDNS來進行名稱解析,但這種方式只能適用於Cluster內部,讓內部服務可以找到彼此,而ExternalDNS用來將服務對外部公開,就可以透過自定義FQDN來存取Kubernetes cluster內部服務,ExternalDNS官網就有提供與各家Provider的做法,而且其實不難,那我們就開始吧!!
實現將Kubernetes Cluster內的pod, service, ingress等資源註冊到外面dns。讓外部的服務可以透過統一的dns訪問到cluster內的服務。
external-dns支援將domain name註冊到不同的domain service,如aws, linode、coredns,bind-dns等。以下官方github provider頁面找尋你需要串接的dns provider:
外部domain name支援,細節可以到provider
目錄確認。
提醒一下,Bind provider需套用rfc2316 rule,可以先將rfc2316所需要的內容準備好,我們會使用到的domain name如下:
PS. 建議如果有Loadbalancer最好,例如MetalLB (之後會再跟大家說明)
# 產生certificates
[master]# tsig-keygen -a hmac-sha256 externaldns
key "externaldns" {
algorithm hmac-sha256;
secret "BL4uv5x5Pd0DWbioNS6BvqG2fWAM/F3ZQcyic2q+SwE=";
};
# 修改named
key "externaldns" {
algorithm hmac-sha256;
secret "BL4uv5x5Pd0DWbioNS6BvqG2fWAM/F3ZQcyic2q+SwE=";
};
zone "test.example.poc" IN {
type master;
file "named.test.example.poc.zone";
allow-transfter {
key "externaldns";
};
update-policy {
grant externaldns zonesub ANY;
};
};
# 建立namespace
[master]# kubectl create externaldns
# 建立clusterrole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: external-dns
namespace: external-dns
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- pods
- nodes
verbs:
- get
- watch
- list
- apiGroups:
- extensions
- networking.k8s.io
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- networking.istio.io
resources:
- gateways
- virtualservices
verbs:
- get
- watch
- list
# 建立SA
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
namespace: external-dns
# 建立rolebinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: external-dns-viewer
namespace: external-dns
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: external-dns
subjects:
- kind: ServiceAccount
name: external-dns
namespace: external-dns
# 建立deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
namespace: external-dns
spec:
selector:
matchLabels:
app: external-dns
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: k8s.gcr.io/external-dns/external-dns:v0.7.6
args:
- --registry=txt
- --txt-prefix=external-dns-
- --txt-owner-id=k8s
- --provider=rfc2136
- --rfc2136-host=10.107.88.9
- --rfc2136-port=53
- --rfc2136-zone=test.example.poc
- --rfc2136-tsig-secret=BL4uv5x5Pd0DWbioNS6BvqG2fWAM/F3ZQcyic2q+SwE=
- --rfc2136-tsig-secret-alg=hmac-sha256
- --rfc2136-tsig-keyname=externaldns
- --rfc2136-tsig-axfr
- --source=service
- --source=ingress
- --domain-filter=apps.test.example.poc
- --interval=30s
- --log-level=debug
# 執行以上YAML
[master]# kubectl create -f clusterrole.yaml -n external-dns
[master]# kubectl create -f ac.yaml -n external-dns
[master]# kubectl create -f clusterrolebinding.yaml -n external-dns
[master]# kubectl create -f deployment.yaml -n external-dns
# 測試service/ingress
[master]# kubectl run nginx --image=nginx --port=80
[master]# kubectl expose pod nginx --port=80 --target-port=80 --type=LoadBalancer
[master]# kubectl get svc -n external-dns
[[master]# kubectl annotate service nginx "external-dns.alpha.kubernetes.io/hostname=nginx.apps.test.example.poc."
//確認是否可以解析
[master]# nslookup nginx.apps.test.example.poc 10.107.88.9
以上就實現在地端的dns服務,ExternalDNS是一個從Kube-DNS所沿伸出來的專門為了外部DNS服務的專案,包含許多知名的平台都有支援。
以正式環境來說,建議從使用的平台角度出發來決定FQDN的解決方案會更符合實際環境的需求。但以小型/LAB使用的規模,ExternalDNS還是一個非常不錯的選項。
之後有時間的話再跟大家分享ExternalDNS的運作原理 :)
參考: