external-dns介绍和基本使用

欢迎加入本站的kubernetes技术交流群,QQ群号:450203387,微信群:加Blue_L。


external-dns用来将集群内的pod,service,ingress等资源注册到外面的dns上,这样集群外的服务可通过统一的dns访问到集群内的服务,external-dns支持将域名注册到不同的域名服务,如aws,linode,或coredns,bind-dns等。external-dns支持众多kubernetes资源到外部域名服务的注册发布,具体支持的资源类型可进入source目录查看,同时也支持众多的外部域名服务支持,具体可进入provider目录查看。

项目主页:https://github.com/kubernetes-sigs/external-dns

本文主要使用bind作为外部dns服务进行演示测试,将集群内的service,ingress,和istio-gateway,istio-virtualservice注册到外面的dns上。

域名划分

首先我们需要对域名做一个划分:

  • svc.mydomain.com kubernetes集群内服务域名,此处我们集群内外使用相同的域
  • hosts.mydomain.com 主机节点的dns解析域
  • mydomain.com 基础服务

部署bind

bind的主配置文件修改了本地监听的ip地址,注释掉了ipv6的监听,使用tsig-keygen -a hmac-sha256 externaldns命令生成了认证密匙并配置到了配置文件中,加入forwarders转发配置,此处要求配置为客户基础环境中的。

[root@vm10-77-1-87 ~]# cat /etc/named.conf
//
// named.conf
//
// Provided by Red Hat bind package to configure the ISC BIND named(8) DNS
// server as a caching only nameserver (as a localhost DNS resolver only).
//
// See /usr/share/doc/bind*/sample/ for example named configuration files.
//
// See the BIND Administrator's Reference Manual (ARM) for details about the
// configuration located in /usr/share/doc/bind-{version}/Bv9ARM.html
​
options {
        listen-on port 53 { 10.77.1.87; };
        // listen-on-v6 port 53 { ::1; };
        directory         "/var/named";
        dump-file         "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";
        recursing-file  "/var/named/data/named.recursing";
        secroots-file   "/var/named/data/named.secroots";
        # allow-query     { localhost; };
        
        /*
         - If you are building an AUTHORITATIVE DNS server, do NOT enable recursion.
         - If you are building a RECURSIVE (caching) DNS server, you need to enable
           recursion.
         - If your recursive DNS server has a public IP address, you MUST enable access
           control to limit queries to your legitimate users. Failing to do so will
           cause your server to become part of large scale DNS amplification
           attacks. Implementing BCP38 within your network would greatly
           reduce such attack surface
        */
        recursion yes;
​
        dnssec-enable yes;
        dnssec-validation yes;
​
        /* Path to ISC DLV key */
        bindkeys-file "/etc/named.root.key";
​
        managed-keys-directory "/var/named/dynamic";
​
        pid-file "/run/named/named.pid";
        session-keyfile "/run/named/session.key";
​
        forwarders {
           198.18.254.30;
           198.18.254.31;
        };
};
​
logging {
        channel default_debug {
                file "data/named.run";
                severity dynamic;
        };
};
​
zone "." IN {
        type hint;
        file "named.ca";
};
​
// 使用这个命令生成认证密匙:tsig-keygen -a hmac-sha256 externaldns
// 该密匙也需要配置在external-dns中
key "externaldns" {
        algorithm hmac-sha256;
        secret "Dz6q1pxwh0OISUuIZvjlY8hdd3MJc+wInizrtyuiops=";
};
​
include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";

修改zones配置文件,添加mydomain.com域配置

[root@vm10-77-1-87 ~]# cat /etc/named.rfc1912.zones
// named.rfc1912.zones:
//
// Provided by Red Hat caching-nameserver package
//
// ISC BIND named zone configuration for zones recommended by
// RFC 1912 section 4.1 : localhost TLDs and address zones
// and http://www.ietf.org/internet-drafts/draft-ietf-dnsop-default-local-zones-02.txt
// (c)2007 R W Franks
//
// See /usr/share/doc/bind*/sample/ for example named configuration files.
//
​
zone "localhost.localdomain" IN {
        type master;
        file "named.localhost";
        allow-update { none; };
};
​
zone "localhost" IN {
        type master;
        file "named.localhost";
        allow-update { none; };
};
​
zone "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" IN {
        type master;
        file "named.loopback";
        allow-update { none; };
};
​
zone "1.0.0.127.in-addr.arpa" IN {
        type master;
        file "named.loopback";
        allow-update { none; };
};
​
zone "0.in-addr.arpa" IN {
        type master;
        file "named.empty";
        allow-update { none; };
};
​
zone "mydomain.com" IN {
        type master;
        file "mydomain.com.zone";
        allow-transfer {
            key "externaldns";
        };
        update-policy {
            grant externaldns zonesub ANY;
        };
};

创建mydomain.com域

[root@vm10-77-1-87 ~]# cat /var/named/mydomain.com.zone
$ORIGIN .
$TTL 86400       ; 1 day
mydomain.com       IN SOA       dns1.mydomain.com. hostmaster.mydomain.com. (
                               2001062516 ; serial
                               21600     ; refresh (6 hours)
                               3600       ; retry (1 hour)
                               604800     ; expire (1 week)
                               86400     ; minimum (1 day)
                              )
                      NS       dns1.mydomain.com.
$ORIGIN mydomain.com.
dns1                       A        10.77.1.87
harbor                       A        10.77.1.87
yumrepo                       A        10.77.1.87
$ORIGIN hosts.mydomain.com.
master1                       A        10.77.1.42
master2                       A        10.77.1.69
master3                       A        10.77.1.33
worker1                       A        10.77.1.219
worker2                       A        10.77.1.160
worker3                       A        10.77.1.72

推荐节点的域名配置规则为hostname.hosts.mydomain.com或hostname.hosts.cluster.local等带hosts前缀的。

resolv.conf中的search配置为hosts.${domain-name} svc.${domain-name} ${domain-name},如

search hosts.mydomain.com svc.mydomain.com mydomain.com

部署external-dns

参考:https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/rfc2136.md

测试时的external-dns版本不兼容1.22版本kubernetes(链接),主要在Ingress资源,external-dns目前使用的是v1beta1版本接口,1.22中已经废弃。

修改下面–rfc2136开头的和domain相关的参数配置为实际值。经过测试,与istio-1.11.2版本兼容。

apiVersion: v1
kind: Namespace
metadata:
  name: external-dns
  labels:
    name: external-dns
---
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
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: external-dns
  namespace: external-dns
---
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
---
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
        # rfc开头的相关配置和bind中的保持一致
        - --rfc2136-host=10.77.1.87
        - --rfc2136-port=53
        - --rfc2136-zone=mycluster.domain
        - --rfc2136-tsig-secret=Dz6q1pxwh0OISUuIZvjlY8hdd3MJc+wInizrtyuiops=
        - --rfc2136-tsig-secret-alg=hmac-sha256
        - --rfc2136-tsig-keyname=externaldns
        - --rfc2136-tsig-axfr
        - --source=service
        - --source=ingress
        - --source=istio-gateway
        - --source=istio-virtualservice
        - --domain-filter=svc.mydomain.com
        - --interval=30s
        - --log-level=debug

部署

kubectl apply -f external-dns.yaml

测试service/ingress

kubectl run nginx --image=nginx --port=80
kubectl expose pod nginx --port=80 --target-port=80 --type=LoadBalancer
# 查看负载均衡器ip地址
[root@master3 ~]# kubectl get svc nginx
NAME    TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
nginx   LoadBalancer   172.17.12.39   10.77.1.220   80:31339/TCP   175m
kubectl annotate service nginx "external-dns.alpha.kubernetes.io/hostname=nginx.svc.mydomain.com."
# kubectl annotate service nginx "external-dns.alpha.kubernetes.io/hostname-"
# 查看dns是否可以解析
[root@master3 ~]# nslookup nginx.svc.mydomain.com 10.77.1.87
Server:                10.77.1.87
Address:        10.77.1.87#53
​
Name:        nginx.svc.mydomain.com
Address: 10.77.1.220
​
[root@master3 ~]# cat ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - host: ingress.svc.mydomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx
            port:
              number: 80
[root@master3 ~]#
[root@master3 ~]# curl -v -H 'Host: ingress.svc.mydomain.com' 10.77.1.220
* About to connect() to 10.77.1.220 port 80 (#0)
*   Trying 10.77.1.220...
* Connected to 10.77.1.220 (10.77.1.220) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Accept: */*
> Host: ingress.svc.mydomain.com
>
< HTTP/1.1 503 Service Unavailable
< date: Fri, 10 Sep 2021 06:39:03 GMT
< server: istio-envoy
< content-length: 0
<
* Connection #0 to host 10.77.1.220 left intact

测试istio-gateway/istio-virtualservice

部署istio之后,创建helloworld服务。

修改gateway和virtualservice中的hosts配置,两种测试方法:

  1. gateway中的hosts=*,virtualservice中的hosts=helloworld-vs.svc.mydomain.com
  2. virtualservice中的hosts=*,gateway中的hosts=helloworld-gw.svc.mydomain.com
[root@master3 helloworld]# cat helloworld-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: helloworld-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: helloworld
spec:
  hosts:
  - "helloworld-vs.svc.mydomain.com"
  gateways:
  - helloworld-gateway
  http:
  - match:
    - uri:
        exact: /hello
    route:
    - destination:
        host: helloworld
        port:
          number: 5000
[root@master3 helloworld]# kubectl apply -f helloworld.yaml
service/helloworld unchanged
deployment.apps/helloworld-v1 unchanged
deployment.apps/helloworld-v3 unchanged
deployment.apps/helloworld-v2 unchanged
[root@master3 helloworld]# kubectl apply -f helloworld-gateway.yaml
gateway.networking.istio.io/helloworld-gateway unchanged
virtualservice.networking.istio.io/helloworld unchanged
[root@master3 helloworld]#
​
# 查询dns服务可得到dns解析记录,并且其地址是istio-ingressgateway的LoadBalancer的ip地址。
[root@master3 helloworld]# nslookup helloworld-vs.svc.mydomain.com 10.77.1.87
Server:                10.77.1.87
Address:        10.77.1.87#53
​
Name:        helloworld-vs.svc.mydomain.com
Address: 10.77.1.221

配置

[root@worker1 ~]# docker run -it --rm k8s.gcr.io/external-dns/external-dns:v0.7.6 --help
usage: external-dns --source=source --provider=provider [<flags>]
​
ExternalDNS synchronizes exposed Kubernetes Services and Ingresses with DNS providers.
​
Note that all flags may be replaced with env vars - `--flag` -> `EXTERNAL_DNS_FLAG=1` or `--flag value` -> `EXTERNAL_DNS_FLAG=value`
​
Flags:
  --help                         Show context-sensitive help (also try --help-long and --help-man).
  --version                      Show application version.
  --server=""                    The Kubernetes API server to connect to (default: auto-detect)
  --kubeconfig=""                Retrieve target cluster configuration from a Kubernetes configuration file (default: auto-detect)
  --request-timeout=30s          Request timeout when calling Kubernetes APIs. 0s means no timeout
  --cf-api-endpoint=""           The fully-qualified domain name of the cloud foundry instance you are targeting
  --cf-username=""               The username to log into the cloud foundry API
  --cf-password=""               The password to log into the cloud foundry API
  --contour-load-balancer="heptio-contour/contour"
                                 The fully-qualified name of the Contour load balancer service. (default: heptio-contour/contour)
  --skipper-routegroup-groupversion="zalando.org/v1"
                                 The resource version for skipper routegroup
  --source=source ...            The resource types that are queried for endpoints; specify multiple times for multiple sources (required, options: service, ingress, node, fake, connector, istio-gateway, istio-virtualservice,
                                 cloudfoundry, contour-ingressroute, contour-httpproxy, crd, empty, skipper-routegroup,openshift-route)
  --namespace=""                 Limit sources of endpoints to a specific namespace (default: all namespaces)
  --annotation-filter=""         Filter sources managed by external-dns via annotation using label selector semantics (default: all sources)
  --label-filter=""              Filter sources managed by external-dns via label selector when listing all resources; currently only supported by source CRD
  --fqdn-template=""             A templated string that's used to generate DNS names from sources that don't define a hostname themselves, or to add a hostname suffix when paired with the fake source (optional). Accepts comma separated
                                 list for multiple global FQDN.
  --combine-fqdn-annotation      Combine FQDN template and Annotations instead of overwriting
  --ignore-hostname-annotation   Ignore hostname annotation when generating DNS names, valid only when using fqdn-template is set (optional, default: false)
  --ignore-ingress-tls-spec      Ignore tls spec section in ingresses resources, applicable only for ingress sources (optional, default: false)
  --compatibility=               Process annotation semantics from legacy implementations (optional, options: mate, molecule)
  --publish-internal-services    Allow external-dns to publish DNS records for ClusterIP services (optional)
  --publish-host-ip              Allow external-dns to publish host-ip for headless services (optional)
  --always-publish-not-ready-addresses
                                 Always publish also not ready addresses for headless services (optional)
  --connector-source-server="localhost:8080"
                                 The server to connect for connector source, valid only when using connector source
  --crd-source-apiversion="externaldns.k8s.io/v1alpha1"
                                 API version of the CRD for crd source, e.g. `externaldns.k8s.io/v1alpha1`, valid only when using crd source
  --crd-source-kind="DNSEndpoint"
                                 Kind of the CRD for the crd source in API group and version specified by crd-source-apiversion
  --service-type-filter=SERVICE-TYPE-FILTER ...
                                 The service types to take care about (default: all, expected: ClusterIP, NodePort, LoadBalancer or ExternalName)
  --managed-record-types=A... ...
                                 Comma separated list of record types to manage (default: A, CNAME) (supported records: CNAME, A, NS
  --provider=provider            The DNS provider where the DNS records will be created (required, options: aws, aws-sd, google, azure, azure-dns, azure-private-dns, cloudflare, rcodezero, digitalocean, hetzner, dnsimple, akamai,
                                 infoblox, dyn, designate, coredns, skydns, inmemory, ovh, pdns, oci, exoscale, linode, rfc2136, ns1, transip, vinyldns, rdns, scaleway, vultr, ultradns)
  --domain-filter= ...           Limit possible target zones by a domain suffix; specify multiple times for multiple domains (optional)
  --exclude-domains= ...         Exclude subdomains (optional)
  --zone-name-filter= ...        Filter target zones by zone domain (For now, only AzureDNS provider is using this flag); specify multiple times for multiple zones (optional)
  --zone-id-filter= ...          Filter target zones by hosted zone id; specify multiple times for multiple zones (optional)
  --google-project=""            When using the Google provider, current project is auto-detected, when running on GCP. Specify other project with this. Must be specified when running outside GCP.
  --google-batch-change-size=1000
                                 When using the Google provider, set the maximum number of changes that will be applied in each batch.
  --google-batch-change-interval=1s
                                 When using the Google provider, set the interval between batch changes.
  --alibaba-cloud-config-file="/etc/kubernetes/alibaba-cloud.json"
                                 When using the Alibaba Cloud provider, specify the Alibaba Cloud configuration file (required when --provider=alibabacloud
  --alibaba-cloud-zone-type=     When using the Alibaba Cloud provider, filter for zones of this type (optional, options: public, private)
  --aws-zone-type=               When using the AWS provider, filter for zones of this type (optional, options: public, private)
  --aws-zone-tags= ...           When using the AWS provider, filter for zones with these tags
  --aws-assume-role=""           When using the AWS provider, assume this IAM role. Useful for hosted zones in another AWS account. Specify the full ARN, e.g. `arn:aws:iam::123455567:role/external-dns` (optional)
  --aws-batch-change-size=1000   When using the AWS provider, set the maximum number of changes that will be applied in each batch.
  --aws-batch-change-interval=1s
                                 When using the AWS provider, set the interval between batch changes.
  --aws-evaluate-target-health   When using the AWS provider, set whether to evaluate the health of a DNS target (default: enabled, disable with --no-aws-evaluate-target-health)
  --aws-api-retries=3            When using the AWS provider, set the maximum number of retries for API calls before giving up.
  --aws-prefer-cname             When using the AWS provider, prefer using CNAME instead of ALIAS (default: disabled)
  --aws-zones-cache-duration=0s  When using the AWS provider, set the zones list cache TTL (0s to disable).
  --azure-config-file="/etc/kubernetes/azure.json"
                                 When using the Azure provider, specify the Azure configuration file (required when --provider=azure
  --azure-resource-group=""      When using the Azure provider, override the Azure resource group to use (required when --provider=azure-private-dns)
  --azure-subscription-id=""     When using the Azure provider, specify the Azure configuration file (required when --provider=azure-private-dns)
  --azure-user-assigned-identity-client-id=""
                                 When using the Azure provider, override the client id of user assigned identity in config file (optional)
  --cloudflare-proxied           When using the Cloudflare provider, specify if the proxy mode must be enabled (default: disabled)
  --cloudflare-zones-per-page=50
                                 When using the Cloudflare provider, specify how many zones per page listed, max. possible 50 (default: 50)
  --coredns-prefix="/skydns/"    When using the CoreDNS provider, specify the prefix name
  --akamai-serviceconsumerdomain=""
                                 When using the Akamai provider, specify the base URL (required when --provider=akamai)
  --akamai-client-token=""       When using the Akamai provider, specify the client token (required when --provider=akamai)
  --akamai-client-secret=""      When using the Akamai provider, specify the client secret (required when --provider=akamai)
  --akamai-access-token=""       When using the Akamai provider, specify the access token (required when --provider=akamai)
  --infoblox-grid-host=""        When using the Infoblox provider, specify the Grid Manager host (required when --provider=infoblox)
  --infoblox-wapi-port=443       When using the Infoblox provider, specify the WAPI port (default: 443)
  --infoblox-wapi-username="admin"
                                 When using the Infoblox provider, specify the WAPI username (default: admin)
  --infoblox-wapi-password=""    When using the Infoblox provider, specify the WAPI password (required when --provider=infoblox)
  --infoblox-wapi-version="2.3.1"
                                 When using the Infoblox provider, specify the WAPI version (default: 2.3.1)
  --infoblox-ssl-verify          When using the Infoblox provider, specify whether to verify the SSL certificate (default: true, disable with --no-infoblox-ssl-verify)
  --infoblox-view=""             DNS view (default: "")
  --infoblox-max-results=0       Add _max_results as query parameter to the URL on all API requests. The default is 0 which means _max_results is not set and the default of the server is used.
  --dyn-customer-name=""         When using the Dyn provider, specify the Customer Name
  --dyn-username=""              When using the Dyn provider, specify the Username
  --dyn-password=""              When using the Dyn provider, specify the password
  --dyn-min-ttl=DYN-MIN-TTL      Minimal TTL (in seconds) for records. This value will be used if the provided TTL for a service/ingress is lower than this.
  --oci-config-file="/etc/kubernetes/oci.yaml"
                                 When using the OCI provider, specify the OCI configuration file (required when --provider=oci
  --rcodezero-txt-encrypt        When using the Rcodezero provider with txt registry option, set if TXT rrs are encrypted (default: false)
  --inmemory-zone= ...           Provide a list of pre-configured zones for the inmemory provider; specify multiple times for multiple zones (optional)
  --ovh-endpoint="ovh-eu"        When using the OVH provider, specify the endpoint (default: ovh-eu)
  --ovh-api-rate-limit=20        When using the OVH provider, specify the API request rate limit, X operations by seconds (default: 20)
  --pdns-server="http://localhost:8081"
                                 When using the PowerDNS/PDNS provider, specify the URL to the pdns server (required when --provider=pdns)
  --pdns-api-key=""              When using the PowerDNS/PDNS provider, specify the API key to use to authorize requests (required when --provider=pdns)
  --pdns-tls-enabled             When using the PowerDNS/PDNS provider, specify whether to use TLS (default: false, requires --tls-ca, optionally specify --tls-client-cert and --tls-client-cert-key)
  --ns1-endpoint=""              When using the NS1 provider, specify the URL of the API endpoint to target (default: https://api.nsone.net/v1/)
  --ns1-ignoressl                When using the NS1 provider, specify whether to verify the SSL certificate (default: false)
  --ns1-min-ttl=NS1-MIN-TTL      Minimal TTL (in seconds) for records. This value will be used if the provided TTL for a service/ingress is lower than this.
  --digitalocean-api-page-size=50
                                 Configure the page size used when querying the DigitalOcean API.
  --tls-ca=""                    When using TLS communication, the path to the certificate authority to verify server communications (optionally specify --tls-client-cert for two-way TLS)
  --tls-client-cert=""           When using TLS communication, the path to the certificate to present as a client (not required for TLS)
  --tls-client-cert-key=""       When using TLS communication, the path to the certificate key to use with the client certificate (not required for TLS)
  --exoscale-endpoint="https://api.exoscale.ch/dns"
                                 Provide the endpoint for the Exoscale provider
  --exoscale-apikey=""           Provide your API Key for the Exoscale provider
  --exoscale-apisecret=""        Provide your API Secret for the Exoscale provider
  --rfc2136-host=""              When using the RFC2136 provider, specify the host of the DNS server
  --rfc2136-port=0               When using the RFC2136 provider, specify the port of the DNS server
  --rfc2136-zone=""              When using the RFC2136 provider, specify the zone entry of the DNS server to use
  --rfc2136-insecure             When using the RFC2136 provider, specify whether to attach TSIG or not (default: false, requires --rfc2136-tsig-keyname and rfc2136-tsig-secret)
  --rfc2136-tsig-keyname=""      When using the RFC2136 provider, specify the TSIG key to attached to DNS messages (required when --rfc2136-insecure=false)
  --rfc2136-tsig-secret=""       When using the RFC2136 provider, specify the TSIG (base64) value to attached to DNS messages (required when --rfc2136-insecure=false)
  --rfc2136-tsig-secret-alg=""   When using the RFC2136 provider, specify the TSIG (base64) value to attached to DNS messages (required when --rfc2136-insecure=false)
  --rfc2136-tsig-axfr            When using the RFC2136 provider, specify the TSIG (base64) value to attached to DNS messages (required when --rfc2136-insecure=false)
  --rfc2136-min-ttl=0s           When using the RFC2136 provider, specify minimal TTL (in duration format) for records. This value will be used if the provided TTL for a service/ingress is lower than this
  --transip-account=""           When using the TransIP provider, specify the account name (required when --provider=transip)
  --transip-keyfile=""           When using the TransIP provider, specify the path to the private key file (required when --provider=transip)
  --policy=sync                  Modify how DNS records are synchronized between sources and providers (default: sync, options: sync, upsert-only, create-only)
  --registry=txt                 The registry implementation to use to keep track of DNS record ownership (default: txt, options: txt, noop, aws-sd)
  --txt-owner-id="default"       When using the TXT registry, a name that identifies this instance of ExternalDNS (default: default)
  --txt-prefix=""                When using the TXT registry, a custom string that's prefixed to each ownership DNS record (optional). Mutual exclusive with txt-suffix!
  --txt-suffix=""                When using the TXT registry, a custom string that's suffixed to the host portion of each ownership DNS record (optional). Mutual exclusive with txt-prefix!
  --txt-wildcard-replacement=""  When using the TXT registry, a custom string that's used instead of an asterisk for TXT records corresponding to wildcard DNS records (optional)
  --txt-cache-interval=0s        The interval between cache synchronizations in duration format (default: disabled)
  --interval=1m0s                The interval between two consecutive synchronizations in duration format (default: 1m)
  --once                         When enabled, exits the synchronization loop after the first iteration (default: disabled)
  --dry-run                      When enabled, prints DNS record changes rather than actually performing them (default: disabled)
  --events                       When enabled, in addition to running every interval, the reconciliation loop will get triggered when supported sources change (default: disabled)
  --log-format=text              The format in which log messages are printed (default: text, options: text, json)
  --metrics-address=":7979"      Specify where to serve the metrics and health check endpoint (default: :7979)
  --log-level=info               Set the level of logging. (default: info, options: panic, debug, info, warning, error, fatal

同域与不同域

集群内的域名可和外面的dns配置相同的域

# 集群内的解析,如果集群内有相同名称的服务可定先解析到集群内的
service-name
service-name.default
service-name.default.svc
service-name.default.svc.mydomain.com
# 然后使用集群外的search
service-name.hosts.mydomain.com
service-name.svc.mydomain.com
service-name.mydomain.com

# 集群外的解析,取决于annotation
service-name.hosts.mydomain.com
service-name.svc.mydomain.com
service-name.mydomain.com

可能会把所有svc.mydomain.com的域名都发布到外面dns,针对istio-virtualservice,需要针对不发布的手动打注释

集群内的域名和外面的dns配置不同的域

集群内的解析,如果集群内有相同名称的服务可定先解析到集群内的
service-name
service-name.default
service-name.default.svc
service-name.default.svc.cluster.local
# 然后使用集群外的search
service-name.hosts.mydomain.com
service-name.svc.mydomain.com
service-name.mydomain.com

集群外的解析,取决于annotation
service-name.hosts.mydomain.com
service-name.svc.mydomain.com
service-name.mydomain.com

针对直接暴露的service可能会有curl -H'Host: service-name.namespace.svc.cluster.local'的问题,使用ingress和istio暴露的服务应该没问题。

使用同域或不同域应该根据具体情况决定。

注意事项

如果集群的clusterDomain和external-dns配置的domain(一般这个就是外部dns的域)相同的话,可能会导致所有的istio virtualservice都会发布到外部dns上(如果virtualservice里配置的域和external-dns配置的域相同的话)。

对于istio的virtualservice来说,可以给每个virtualservice加下面这个注释,就不会发布到外面的dns上。默认情况下没有这个注释或这个注释的值为“dns-controller”,就会发布到外面的dns中。

kubectl annotate vs helloworld external-dns.alpha.kubernetes.io/controller=kubectl

# 示例virtual-service
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: helloworld
spec:
  hosts:
  #- "*"
  - "helloworld-vs.mydomain.com"
  - "helloworld-vs.svc.mydomain.com"
  gateways:
  - helloworld-gateway
  http:
  - match:
    - uri:
        exact: /hello
    route:
    - destination:
        host: helloworld
        port:
          number: 5000

推荐external-dns的域名匹配规则为svc.mydomain.com或svc.cluster.local等待svc的。Istio gateway中可能也会配置多个域名,如果启用istio-gateway的source配置,那么external-dns也只会将带有svc的的域名发布到外面dns中。

不过,在实际应用中建议不启用istio-gateway source配置,使用istio-virtualservice可以做到单独对每个service是否发布进行控制,这样我们的域名匹配是否待svc都无所谓。

其他

external-dns可以根据txt记录判断是否为自己创建的dns记录。同步时,会把bind dns里所以记录拿过来判断是否为自己创建的。如果是自己创建的,但是当前这个服务在kubernetes中没有了,则会在dns里删除这个记录。

bind dns的zone文件里的内容不会及时更新,但是其实不会造成实质性影响,即使bind重新加载了配置,只要external-dns还在运行,迟早是会把过期的dns记录清理掉。

其他应用场景还可以结合calico的bgp模式将pod的ip传播到集群外,通过给pod加annotation载外面dns内给pod注册域名,这是pod和我们主机环境就完全互相打通了,对于使用来说非常方便。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注