LoginSignup
13
8

More than 3 years have passed since last update.

Nginx ingress controller と External-DNS と CoreDNS(+etcd) を入れて Ingress の Host を DNS へ自動登録して名前解決できる環境構築

Posted at

はじめに

オンプレ Kubernetes 上で、Ingress を作成すると自動で Ingress リソースに記載した VirtualHost を DNS に登録し、名前解決ができる環境を構築した

Ingress も初めてだったため、Nginx ingress controller の導入から記載している

実行環境

Kubernetes クラスタ

kubespray で構築した オンプレ kuberntes クラスタ
Versoin: 1.16.3

詳細は下記
https://qiita.com/suzuyui/items/e7531fe5e1e84c061b23

Metallb で Laodbalancer 構築済
詳細は下記
https://qiita.com/suzuyui/items/c83554dd055ef0f4253a

Docker サーバ

coredns + etcd は今回は簡易的に Docker でのシングルで構築
kubernetes 化、クラスタ化は別途検討

OS: CentOS 8.0.1905
Docker-CE: 18.06.3-ce
docker-compose: 1.25.0

サーバIP: 192.168.129.16
※以下、この IP で記載しているので注記

DNS フォワーダ

EdgeRouter X という Vyatta ベースの OS で動作する Router で、 DNS フォワーダとしても動作させている (今回確認のデスクトップもこちらを参照させている)
今回の Ingress 用のドメインを、CoreDNS の方を参照させるように動作させる

Edgeroute-Xサイト: https://www.ui.com/edgemax/edgerouter-x/

概要説明

全体の構成概要を図示すると下記のような感じになる (オレンジ部分が今回記載箇所)
ローカルドメインには .home を使用する

ingress_externaldns_coredns_連携概要図_suzuyu.png

Nginx ingress controller

Kubernetes は Ingress Controller をデフォルトでは実装していないため、オンプレでの Kubernetes では追加で導入する必要がある。
また、実装によって動作も異なる。

今回は、Kubernetes リポジトリ配下の NGINX Ingress Controller を使用する。
※その他に NGINX, Inc. が公開している NGINX, NGINX Plus を利用する Contoroller もある

サイト: https://kubernetes.github.io/ingress-nginx/
Github: https://github.com/kubernetes/ingress-nginx

リソース概要

リソースの概要図を記載すると下記の通り。
IP については固定 IP をアサインしておきたかったので、その箇所だけ追記している。(赤字)
nginx_controller.png

マニフェストは 2 つで下記の通り。

nginx_controller_manifest.png

External-DNS, CoreDNS + Etcd

External-DNS

Ingress 等のリストを取得して、外部公開するホストを DNS へ登録してくれる。

対応している DNS は様々で、対応状況は、Google Cloud DNSAWS Route53Stable だが、それ以外は Beta or Alpha となる。
※オンプレ実装可能なものは Alpha しかない
※ 2020.03.23時点

今回は、External-DNS が対応可能な CoreDNS を選択した。
External-DNS は実際には Etcd へ登録を実施するため、CoreDNS のバックエンドとして Etcd を導入する。

Github: https://github.com/kubernetes-sigs/external-dns

CoreDNS + Etcd

Go で書かれた DNS で、CNCF graduated project の 1 つ。
権威サーバ、リゾルバサーバ両方として動作可能。
レコードのバックエンドとしては、Etcd, hosts、その他 Plugin など様々なものをとすることができる。

今回は 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 Serivce 構築
  2. CoreDNS(+Etcd) 構築
  3. External-DNS 構築
  4. DNSフォワーダ設定 (EdgeRouter X)

構築後に実際に Ingress を作成して、名前解決および URL アクセスも確認する。

1. Nginx ingress controller / Ingress Serivce 構築

Nginx ingress controller

公式からコントローラ用のマニフェストを落としてきて apply する。

$ 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 Service

公式から ingress-nginx Service 用のマニフェストを落としてきて、IP 設定だけ追加して apply する。

$ curl -OL https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/cloud-generic.yaml

Ingress の IP を固定 IP とする場合は、1行追加する (固定 IP 不要の場合は、手を加えなくても良い)

  loadBalancerIP: [固定IP]

下記は、上記の一行を追加した例。

cloud-generic-ipfix.yaml
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

---

apply する。

$ 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) 構築

CoreDNS と Etcd を Docker-compose で構築する。

下記は docker-compose.yml 例
コンテナイメージはどちらも公式のものを使用した。

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 フォワーダとしても使用したい場合は、コメントを解除する。

config/Corefile
# .: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. External-DNS 構築

External-DNS を構築する。

下記は公式にあった Minikube での実施例で書いてあったものを一部手を加えたもの。

env:ETCD_URLS には CoreDNS の Etcd の IP:Port を記載する。

external-dns.yaml
---
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 を apply する。

$ kubectl apply -f external-dns.yaml 

参考: https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/coredns.md#manifest-for-clusters-with-rbac-enabled

4. DNSフォワーダ設定 (EdgeRouter X)

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/en-us/articles/115010913367-EdgeRouter-DNS-Forwarding-Setup-and-Options

動作確認: Ingress 作成と名前解決でのアクセス

Prometheus / Grafana / AlertManager を Ingress で公開する場合で、動作確認を実施した。

Ingress 作成

Ingress 作成例は下記の通り。

Prometheus / Grafana / AlertManager の host 登録と、host指定無しの設定を記載している。
host 指定無しは IP でのアクセスで使用できる。 (下記テストでは Grafana を指定した)

prometheus-ingress.yaml
---
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

マニフェストを apply する。
ADDRESS の割り当てには少し時間がかかる場合がある。

$ 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

アクセス確認

dig で名前解決確認 (フォワーダ経由) と、ブラウザでの URL アクセス確認を実施した。

dig

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 をブラウザでアクセスして、正しくアクセスできることが確認できる。

http://grafana.ingress.home でのアクセス
スクリーンショット 2020-03-23 13.05.28.png

http://prometheus.ingress.home でのアクセス
スクリーンショット 2020-03-23 13.06.02.png

http://alertmanager.ingress.home でのアクセス
スクリーンショット 2020-03-23 13.06.22.png

http://192.168.131.80 でのアクセス
スクリーンショット 2020-03-23 13.25.44.png

おわりに

Ingress を作成すると、自動で名前解決でアクセスができる環境まで構築ができた

今後、Ingress は TLS 終端や、認証などできることは多岐に渡るので試していきたい。
また、CoreDNS / Etcd についても etcd-operator などで冗長化・Kubernetes 化も実施していきたい。

13
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
8