使用 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。

ingress_externaldns_coredns_連携概要図_suzuyu.png

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

资源概览

nginx_controller.png

以下是宣言的两个要点。

nginx_controller_manifest.png

外部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 サーバ上に構築

externaldns_coredns_概要_suzuyu.png

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

externaldns_coredns_概要_manifest_suzuyu.png

构建步骤

下面将通过以下步骤进行下一次的构建。

    1. 構築 Nginx Ingress Controller / Ingress 服务

 

    1. 構築 CoreDNS(+Etcd)

 

    1. 構築外部 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,可以确认是否能够正确访问。

スクリーンショット 2020-03-23 13.05.28.png
スクリーンショット 2020-03-23 13.06.02.png
スクリーンショット 2020-03-23 13.06.22.png
スクリーンショット 2020-03-23 13.25.44.png

最后

创建Ingress后,可以自动构建具有名称解析访问功能的环境。

将来,我们希望在Ingress方面能够尝试并涵盖各种事务,例如TLS终止和身份验证等。
此外,我们也希望通过使用etcd-operator等技术,将CoreDNS / Etcd进行冗余和Kubernetes化。

bannerAds