使用 Nginx ingress controller,External-DNS和CoreDNS(+etcd)来设置环境,将Ingress的主机自动注册到DNS并进行名称解析
首先
在本地 Kubernetes 上创建 Ingress 的同时,自动将在 Ingress 资源中指定的 VirtualHost 注册到 DNS 中,从而构建一个可以进行名称解析的环境。
由于 Ingress 是第一次尝试,因此记录了从安装 Nginx Ingress Controller 开始的过程。
执行环境 (shí
Kubernetes 集群 (Kubernetes
使用Kubespray构建的本地Kubernetes集群
版本:1.16.3
详细信息请查看以下链接:
https://qiita.com/suzuyui/items/e7531fe5e1e84c061b23
Metallb已经构建了负载均衡器
详细信息请参考以下链接:
https://qiita.com/suzuyui/items/c83554dd055ef0f4253a
Docker服务器
本次将使用Docker简单构建Coredns和Etcd的单节点配置,将考虑将其转化为Kubernetes并进行集群化的问题另行研究。
操作系统:CentOS 8.0.1905
Docker-CE版本:18.06.3-ce
docker-compose版本:1.25.0
服务器IP地址:192.168.129.16
※请注意,以下内容都是基于此IP进行记录。
DNS转发器
使用基于Vyatta的操作系统EdgeRouter X作为路由器,并将其用作DNS转发器(本次确认的桌面也参考了这一点)。
使Ingress使用的域名引用CoreDNS以进行操作。
Edgeroute-X网站:https://www.ui.com/edgemax/edgerouter-x/
简要描述
如果用图示来表示整体的组成概述,会是下面这样的感觉(橙色部分是本次记录的地方)。
在本地域名中使用 .home。

Nginx入口控制器
由于Kubernetes默认未实施Ingress Controller功能,因此在本地部署的Kubernetes中需要额外引入。而且,根据实现方式,其运行行为也会有所不同。
这次我们将使用Kubernetes存储库中的NGINX Ingress Controller。
※还有其他由NGINX, Inc.发布的NGINX和NGINX Plus控制器也可供使用。
网站: https://kubernetes.github.io/ingress-nginx/
Github: https://github.com/kubernetes/ingress-nginx
资源概览

以下是宣言的两个要点。

外部DNS,CoreDNS + Etcd
外部DNS
获取 Ingress 等列表,并将要公开给外部的主机注册到 DNS 上。
目前有各种不同的DNS服务器可供选择,其支持情况如下:Google Cloud DNS和AWS Route53是稳定版,其他则为测试版或开发版。
注意:除了Alpha版本外,没有其他支持本地实施的选项。
※截至2020年3月23日。
这次选择了能够支持External-DNS的CoreDNS。
External-DNS实际上会将其注册到Etcd中,因此我们引入Etcd作为CoreDNS的后端。
GitHub: https://github.com/kubernetes-sigs/external-dns (GitHub: https://github.com/kubernetes-sigs/external-dns)
CoreDNS与Etcd
用Go语言编写的DNS项目,是CNCF认可的项目之一。可以作为权威服务器和解析服务器的双重功能。可以使用Etcd、hosts和其他插件等多种方式作为记录的后端存储。
由于这次我们使用 External-DNS,所以选择将 Etcd 作为后端。
网站:https://coredns.io/
Github主页:https://github.com/coredns/coredns
资源配置概览图
構成概要图如下所示。
-
- External-DNS
kubernetes クラスタ上に構築
CoreDNS
Docker サーバ上に構築

设定如下,需要3个文件(红字),详细内容将在另外一处提及。

构建步骤
下面将通过以下步骤进行下一次的构建。
-
- 構築 Nginx Ingress Controller / Ingress 服务
-
- 構築 CoreDNS(+Etcd)
-
- 構築外部 DNS
- 配置 DNS 转发器(EdgeRouter X)
在构建之后,实际创建Ingress,确保解析名称和URL的访问。
1. 搭建Nginx ingress控制器/入口服务
Nginx入口控制器
从公式获取控制器的清单,应用并执行。
$ curl -OL https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
$ kubectl apply -f mandatory.yaml
namespace/ingress-nginx created
configmap/nginx-configuration created
configmap/tcp-services created
configmap/udp-services created
serviceaccount/nginx-ingress-serviceaccount created
clusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole created
role.rbac.authorization.k8s.io/nginx-ingress-role created
rolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding created
deployment.apps/nginx-ingress-controller created
limitrange/ingress-nginx created
请参考以下链接:https://kubernetes.github.io/ingress-nginx/deploy/
入口服务
从公式网站下载 ingress-nginx 服务的清单文件,只需添加 IP 设置后,然后进行应用。
$ curl -OL https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/cloud-generic.yaml
如果要将Ingress的IP设置为固定IP,则需要添加一行(如果不需要固定IP,则不必修改)。
loadBalancerIP: [固定IP]
以下是添加了上述一行的例子。
kind: Service
apiVersion: v1
metadata:
name: ingress-nginx
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
externalTrafficPolicy: Local
type: LoadBalancer
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
- name: https
port: 443
protocol: TCP
targetPort: https
loadBalancerIP: 192.168.131.80
---
申请使用。
$ kubectl apply -f cloud-generic-ipfix.yaml
service/ingress-nginx created
确保 Nginx Ingress 控制器正在运行。
$ kubectl get pods --all-namespaces -l app.kubernetes.io/name=ingress-nginx
NAMESPACE NAME READY STATUS RESTARTS AGE
ingress-nginx nginx-ingress-controller-7f74f657bd-mcfdx 1/1 Running 0 44m
2. 构建CoreDNS(+Etcd)
使用Docker-compose构建CoreDNS和Etcd。
以下是 docker-compose.yml 的示例
容器映像都是使用官方提供的。
---
version: '3.5'
services:
coredns:
container_name: coredns
image: coredns/coredns:1.6.7
restart: on-failure
ports:
- '53:53'
- '53:53/udp'
volumes:
- './config:/etc/coredns'
command: -conf /etc/coredns/Corefile
etcd:
container_name: etcd
image: quay.io/coreos/etcd:v3.4.5
ports:
- '2379:2379'
- '2380:2380'
- '4001:4001'
volumes:
- etcddata01:/etcd-data
command:
- /usr/local/bin/etcd
- --data-dir=/etcd-data
- --name=node1
- --listen-peer-urls=http://0.0.0.0:2380
- --advertise-client-urls=http://0.0.0.0:2379,http://0.0.0.0:4001
- --listen-client-urls=http://0.0.0.0:2379,http://0.0.0.0:4001
volumes:
etcddata01:
driver: local
在 Corefile 中编写域名配置。
以下示例将 ingress.home 作为要设置的域名名称在 ingress 中进行配置。
如果希望将 CoreDNS 用作 DNS 转发器,请取消这段注释。
# .:53 {
# forward . 8.8.8.8 9.9.9.9
# log
# errors
# }
ingress.home:53 {
etcd ingress.home {
path /skydns
endpoint http://192.168.129.16:2379
}
log
errors
}
使用docker-compose up -d命令启动
# docker-compose up -d
Creating network "coredns_default" with the default driver
Creating coredns ... done
Creating etcd ... done
# docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------------------------------------------------------
coredns /coredns -conf /etc/coredn ... Up 0.0.0.0:53->53/tcp, 0.0.0.0:53->53/udp
etcd /usr/local/bin/etcd --data ... Up 0.0.0.0:2379->2379/tcp, 0.0.0.0:2380->2380/tcp, 0.0.0.0:4001->4001/tcp
3. 外部域名解析系统的建立
建立外部DNS。
以下是对Minikube的官方实施示例进行了一部分修改的内容。
在环境变量ETCD_URLS中,记录CoreDNS的Etcd的IP:端口。
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: external-dns
rules:
- apiGroups: [""]
resources: ["services","endpoints","pods"]
verbs: ["get","watch","list"]
- apiGroups: ["extensions"]
resources: ["ingresses"]
verbs: ["get","watch","list"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["list"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: external-dns-viewer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: external-dns
subjects:
- kind: ServiceAccount
name: external-dns
namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
namespace: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
namespace: kube-system
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: external-dns
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: bitnami/external-dns:latest
# image: registry.opensource.zalan.do/teapot/external-dns:latest
args:
- --source=ingress
- --provider=coredns
# - --log-level=debug # debug only
env:
- name: ETCD_URLS
value: http://192.168.129.16:2379
执行上述的yaml文件。
$ kubectl apply -f external-dns.yaml
请参考以下网址获取关于启用RBAC的集群的CoreDNS配置清单:https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/coredns.md#manifest-for-clusters-with-rbac-enabled
4. EdgeRouter X的DNS转发设置
使用EdgeRouter X,通过使用DNS转发选项,对.home域将其设置为转发到CoreDNS服务器。
以下是一个设置示例。
set service dns forwarding name-server 8.8.8.8
set service dns forwarding name-server 8.8.8.4
set service dns forwarding options server=/home/192.168.129.16
请参考以下链接中的内容:https://help.ubnt.com/hc/zh-cn/articles/115010913367-EdgeRouter-DNS-Forwarding-Setup-and-Options。
动作确认:在 Ingress 构建和名称解析中的访问
我已经进行了在入口控制下公开 Prometheus/Grafana/AlertManager 并进行操作验证的测试。
创造出Ingress
Ingress 的例子如下所示。
本文描述了Prometheus / Grafana / AlertManager的主机注册和无主机指定设置。
无主机指定的设置可以使用IP进行访问。(在下面的测试中选择了Grafana)
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: prometheus
namespace: monitoring
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: "nginx"
nginx.com/health-checks: "true"
spec:
rules:
- host: grafana.ingress.home
http:
paths:
- path: /
backend:
serviceName: grafana
servicePort: 3000
- host: alertmanager.ingress.home
http:
paths:
- path: /
backend:
serviceName: alertmanager-main
servicePort: 9093
- host: prometheus.ingress.home
http:
paths:
- path: /
backend:
serviceName: prometheus-k8s
servicePort: 9090
- http:
paths:
- path: /
backend:
serviceName: grafana
servicePort: 3000
上述的 serviceName 是指定 Service 的 NAME。
以下是在执行环境中显示 Service Name 的示例。
$ kubectl get svc -n monitoring
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
alertmanager-main ClusterIP 10.233.48.158 <none> 9093/TCP 2d16h
grafana ClusterIP 10.233.55.79 <none> 3000/TCP 2d16h
prometheus-k8s ClusterIP 10.233.4.237 <none> 9090/TCP 2d16h
申请执行宣言。
分配地址可能需要一些时间。
$ kubectl apply -f prometheus-ingress.yaml
ingress.networking.k8s.io/prometheus created
$ kubectl get ingress -n monitoring
NAME HOSTS ADDRESS PORTS AGE
prometheus grafana.ingress.home,alertmanager.ingress.home,prometheus.ingress.home + 1 more... 192.168.131.80 80 2m20s
确认访问
我进行了通过搜寻(经由转发器)确认姓名解决以及在浏览器上确认 URL 访问。
挖掘
通过使用dig命令查询,可以确认返回A记录子的结果。
※ 192.168.129.254 是EdgeRouter X的IP地址。
$ dig -p 53 @192.168.129.254 A grafana.ingress.home +noall +answer
; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> -p 53 @192.168.129.254 A grafana.ingress.home +noall +answer
; (1 server found)
;; global options: +cmd
grafana.ingress.home. 300 IN A 192.168.131.80
$ dig -p 53 @192.168.129.254 A prometheus.ingress.home +noall +answer
; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> -p 53 @192.168.129.254 A prometheus.ingress.home +noall +answer
; (1 server found)
;; global options: +cmd
prometheus.ingress.home. 300 IN A 192.168.131.80
$ dig -p 53 @192.168.129.254 A alertmanager.ingress.home +noall +answer
; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> -p 53 @192.168.129.254 A alertmanager.ingress.home +noall +answer
; (1 server found)
;; global options: +cmd
alertmanager.ingress.home. 300 IN A 192.168.131.80
浏览器
通过在浏览器中访问每个URL,可以确认是否能够正确访问。




最后
创建Ingress后,可以自动构建具有名称解析访问功能的环境。
将来,我们希望在Ingress方面能够尝试并涵盖各种事务,例如TLS终止和身份验证等。
此外,我们也希望通过使用etcd-operator等技术,将CoreDNS / Etcd进行冗余和Kubernetes化。