Skip to content

Commit

Permalink
Merge branch 'master' into issue-239-multiple-targets
Browse files Browse the repository at this point in the history
  • Loading branch information
grimmy committed Apr 12, 2018
2 parents 0d0c171 + 804dca0 commit 0e83547
Show file tree
Hide file tree
Showing 25 changed files with 1,722 additions and 220 deletions.
6 changes: 4 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ os:
language: go

go:
- 1.9
- 1.x
- tip

matrix:
Expand All @@ -16,6 +16,7 @@ matrix:
before_install:
- make dep
- go get github.com/mattn/goveralls
- go get github.com/lawrencewoodman/roveralls
- go get github.com/alecthomas/gometalinter

install:
Expand All @@ -24,4 +25,5 @@ install:
script:
- vendor/github.com/kubernetes/repo-infra/verify/verify-boilerplate.sh --rootdir=$(pwd)
- vendor/github.com/kubernetes/repo-infra/verify/verify-go-src.sh -v --rootdir $(pwd)
- travis_wait 20 goveralls -service=travis-ci
- travis_wait 20 roveralls
- goveralls -coverprofile=roveralls.coverprofile -service=travis-ci
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
- Add a flag that allows FQDN template and annotations to combine (#513) @helgi
- Fix: Use PodIP instead of HostIP for headless Services (#498) @nrobert13
- Support a comma separated list for the FQDN template (#512) @helgi
- Google Provider: Add auto-detection of Google Project when running on GCP (#492) @drzero42
- Add custom TTL support for DNSimple (#477) @jbowes
- Fix docker build and delete vendor files which were not deleted (#473) @njuettner
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# limitations under the License.

# builder image
FROM golang:1.9 as builder
FROM golang as builder

WORKDIR /go/src/github.com/kubernetes-incubator/external-dns
COPY . .
Expand Down
8 changes: 7 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,15 @@ Here's a rough outline on what is to come (subject to change):
- [x] Support for DigitalOcean
- [x] Multiple DNS names per Service


### v0.5

- [ ] Support for creating DNS records to multiple targets

### v0.6

- [ ] Ability to replace Kops' [DNS Controller](https://github.com/kubernetes/kops/tree/master/dns-controller) (This could also directly become `v1.0`)

### v1.0

- [ ] Ability to replace Kops' [DNS Controller](https://github.com/kubernetes/kops/tree/master/dns-controller)
Expand All @@ -167,11 +176,11 @@ Here's a rough outline on what is to come (subject to change):

### Yet to be defined

* Support for CoreDNS and Azure DNS
* Support for CoreDNS
* Support for record weights
* Support for different behavioral policies
* Support for Services with `type=NodePort`
* Support for TPRs
* Support for CRDs
* Support for more advanced DNS record configurations

Have a look at [the milestones](https://github.com/kubernetes-incubator/external-dns/milestones) to get an idea of where we currently stand.
Expand Down
14 changes: 9 additions & 5 deletions docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,18 @@ Services exposed via `type=LoadBalancer` and for the hostnames defined in Ingres

### How do I specify DNS name for my Kubernetes objects?

There are three sources of information for ExternalDNS to decide on DNS name. ExternalDNS will pick one in order as listed below:
There are three sources of information for ExternalDNS to decide on DNS name. ExternalDNS will pick one in order as listed below:

1. For ingress objects ExternalDNS will create a DNS record based on the host specified for the ingress object. For services ExternalDNS will look for the annotation `external-dns.alpha.kubernetes.io/hostname` on the service and use the corresponding value.

2. If compatibility mode is enabled (e.g. `--compatibility={mate,molecule}` flag), External DNS will parse annotations used by Zalando/Mate, wearemolecule/route53-kubernetes. Compatibility mode with Kops DNS Controller is planned to be added in the future.

3. If `--fqdn-template` flag is specified, e.g. `--fqdn-template={{.Name}}.my-org.com`, ExternalDNS will use service/ingress specifications for the provided template to generate DNS name.

### Can I specify multiple global FQDN templates?

Yes, yes you can. Pass in a comma separated list to `--fqdn-template`. Beaware this will double (triple, etc) the amount of DNS entries based on how many services, ingresses and so on you have and will get you faster towards the API request limit of your DNS provider.

### Which Service and Ingress controllers are supported?

Regarding Services, we'll support the OSI Layer 4 load balancers that Kubernetes creates on AWS and Google Container Engine, and possibly other clusters running on Google Compute Engine.
Expand Down Expand Up @@ -91,13 +95,13 @@ Yes — Zalando replaced [Mate](https://github.com/linki/mate) with ExternalDNS

### How can we start using ExternalDNS?

Check out the following descriptive tutorials on how to run ExternalDNS in [GKE](tutorials/gke.md) and [AWS](tutorials/aws.md).
Check out the following descriptive tutorials on how to run ExternalDNS in [GKE](tutorials/gke.md) and [AWS](tutorials/aws.md).

### Why is ExternalDNS only adding a single IP address in Route 53 on AWS when using the `nginx-ingress-controller`? How do I get it to use the FQDN of the ELB assigned to my `nginx-ingress-controller` Service instead?

By default the `nginx-ingress-controller` assigns a single IP address to an Ingress resource when it's created. ExternalDNS uses what's assigned to the Ingress resource, so it too will use this single IP address when adding the record in Route 53.

In most AWS deployments, you'll instead want the Route 53 entry to be the FQDN of the ELB that is assigned to the `nginx-ingress-controller` Service. To accomplish this, when you create the `nginx-ingress-controller` Deployment, you need to provide the `--publish-service` option to the `/nginx-ingress-controller` executable under `args`. Once this is deployed new Ingress resources will get the ELB's FQDN and ExternalDNS will use the same when creating records in Route 53.
In most AWS deployments, you'll instead want the Route 53 entry to be the FQDN of the ELB that is assigned to the `nginx-ingress-controller` Service. To accomplish this, when you create the `nginx-ingress-controller` Deployment, you need to provide the `--publish-service` option to the `/nginx-ingress-controller` executable under `args`. Once this is deployed new Ingress resources will get the ELB's FQDN and ExternalDNS will use the same when creating records in Route 53.

According to the `nginx-ingress-controller` [docs](https://github.com/kubernetes/ingress/tree/master/controllers/nginx) the value you need to provide `--publish-service` is:

Expand Down Expand Up @@ -208,7 +212,7 @@ Sometimes you need to run an internal and an external dns service.
The internal one should provision hostnames used on the internal network (perhaps inside a VPC), and the external
one to expose DNS to the internet.
To do this with ExternalDNS you can use the `--annotation-filter` to specifically tie an instance of ExternalDNS to
To do this with ExternalDNS you can use the `--annotation-filter` to specifically tie an instance of ExternalDNS to
an instance of a ingress controller. Let's assume you have two ingress controllers `nginx-internal` and `nginx-external`
then you can start two ExternalDNS providers one with `--annotation-filter=kubernetes.io/ingress.class=nginx-internal`
then you can start two ExternalDNS providers one with `--annotation-filter=kubernetes.io/ingress.class=nginx-internal`
and one with `--annotation-filter=kubernetes.io/ingress.class=nginx-external`.
128 changes: 81 additions & 47 deletions docs/tutorials/azure.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

# Setting up ExternalDNS for Services on Azure

This tutorial describes how to setup ExternalDNS for usage within a Kubernetes cluster on Azure.
Expand Down Expand Up @@ -49,55 +50,79 @@ To create the secret:
```
$ kubectl create secret generic azure-config-file --from-file=/etc/kubernetes/azure.json
```
### Other hosting providers
If the Kubernetes cluster is not hosted by Azure Container Services and you still want to use Azure DNS, you need to create the secret manually. The secret should contain an object named azure.json with content similar to this:
```
{
"tenantId": "837b898d-7dd5-4967-b718-7dfd25878104",
"subscriptionId": "670d2139-c4ef-4a98-8f38-b7052d5a06b2",
"aadClientId": "a0b083bd-c0fc-473d-be48-e2a4df3ec908",
"aadClientSecret": "11c78103-8109-40af-a6d4-3db265fed095",
"resourceGroup": "MyDnsResourceGroup",
}
```
If you have all the information necessary: create a file called azure.json containing the json structure above and substitute the values. Otherwise create a service principal as shown below before creating the Kubernetes secret.

Then add the secret to the Kubernetes cluster before continuing:
```
kubectl create secret generic azure-config-file --from-file=azure.json
```
### Azure Kubernetes Services (aka AKS)
When your cluster is created, unlike ACS there are no Azure credentials stored and you must create an azure.json object manually like with other hosting providers. In order to create the azure.json you must first create an Azure AD service principal in the Azure AD tenant linked to your Azure subscription that is hosting your DNS zone.

#### (Optional) Create service principal
A Service Principal with a minimum access level of contribute to the resource group containing the Azure DNS zone(s) is necessary for ExternalDNS to be able to edit DNS records. This is an Azure CLI example of how you can create a resource group, service principal and dns resource pointing out key information you need to put in the azure.json file.
#### Create service principal
A Service Principal with a minimum access level of contribute to the resource group containing the Azure DNS zone(s) is necessary for ExternalDNS to be able to edit DNS records. This is an Azure CLI example on how to query the Azure API for the information required for the Resource Group and DNS zone you would have already created in previous steps.

```
>az login
...
# find the relevant subscription and set the az context. This is the "subscriptionId" value.
>az account set --subscription "670d2139-c4ef-4a98-8f38-b7052d5a06b2"
# find the relevant subscription and set the az context. id = subscriptionId value in the azure.json.
>az account list
{
"cloudName": "AzureCloud",
"id": "<subscriptionId GUID>",
"isDefault": false,
"name": "My Subscription",
"state": "Enabled",
"tenantId": "AzureAD tenant ID",
"user": {
"name": "name",
"type": "user"
}
>az account set -s id
...
>az group create --name MyDnsResourceGroup --location "West Europe"
>az group show --name externaldns
{
"id": "/subscriptions/670d2139-c4ef-4a98-8f38-b7052d5a06b2/resourceGroups/MyDnsResourceGroup",
"id": "/subscriptions/id/resourceGroups/externaldns",
...
}
# use the id from the previous step in the scopes argument
>az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/670d2139-c4ef-4a98-8f38-b7052d5a06b2/resourceGroups/MyDnsResourceGroup" -n ExternalDnsServicePrincipal
>az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/id/resourceGroups/externaldns" -n ExternalDnsServicePrincipal
{
"appId": "a0b083bd-c0fc-473d-be48-e2a4df3ec908", <-- aadClientId value
"appId": "appId GUID", <-- aadClientId value
...
"password": "11c78103-8109-40af-a6d4-3db265fed095", <-- aadClientSecret value
"tenant": "837b898d-7dd5-4967-b718-7dfd25878104" <-- tenantId value
"password": "password", <-- aadClientSecret value
"tenant": "AzureAD Tenant Id" <-- tenantId value
}
>az network dns zone create -g MyDnsResourceGroup -n example.com
...
```
### Other hosting providers
If the Kubernetes cluster is not hosted by Azure Container Services and you still want to use Azure DNS, you need to create the secret manually. The secret should contain an object named azure.json with content similar to this:
```
{
"tenantId": "AzureAD tenant Id",
"subscriptionId": "Id",
"aadClientId": "Service Principal AppId",
"aadClientSecret": "Service Principal Password",
"resourceGroup": "MyDnsResourceGroup",
}
```
If you have all the information necessary: create a file called azure.json containing the json structure above and substitute the values. Otherwise create a service principal as previously shown before creating the Kubernetes secret.

Then add the secret to the Kubernetes cluster before continuing:
```
kubectl create secret generic azure-config-file --from-file=azure.json
```



## Deploy ExternalDNS

This deployment assumes that you will be using nginx-ingress. When using nginx-ingress do not deploy it as a Daemon Set. This causes nginx-ingress to write the Cluster IP of the backend pods in the ingress status.loadbalancer.ip property which then has external-dns write the Cluster IP(s) in DNS vs. the nginx-ingress service external IP.

Ensure that your nginx-ingress deployment has the following arg: added to it:

```
- --publish-service=namespace/nginx-ingress-controller-svcname
```

For more details see here: [nginx-ingress external-dns](https://github.com/kubernetes-incubator/external-dns/blob/master/docs/faq.md#why-is-externaldns-only-adding-a-single-ip-address-in-route-53-on-aws-when-using-the-nginx-ingress-controller-how-do-i-get-it-to-use-the-fqdn-of-the-elb-assigned-to-my-nginx-ingress-controller-service-instead)

Connect your `kubectl` client to the cluster you want to test ExternalDNS with.
Then apply one of the following manifests file to deploy ExternalDNS.
Expand All @@ -121,6 +146,7 @@ spec:
image: registry.opensource.zalan.do/teapot/external-dns:v0.4.8
args:
- --source=service
- --source=ingress
- --domain-filter=example.com # (optional) limit to only example.com domains; change to match the zone created above.
- --provider=azure
- --azure-resource-group=externaldns # (optional) use the DNS zones from the tutorial's resource group
Expand Down Expand Up @@ -184,6 +210,7 @@ spec:
image: registry.opensource.zalan.do/teapot/external-dns:v0.4.8
args:
- --source=service
- --source=ingress
- --domain-filter=example.com # (optional) limit to only example.com domains; change to match the zone created above.
- --provider=azure
- --azure-resource-group=externaldns # (optional) use the DNS zones from the tutorial's resource group
Expand Down Expand Up @@ -227,36 +254,43 @@ spec:
apiVersion: v1
kind: Service
metadata:
name: nginx
annotations:
external-dns.alpha.kubernetes.io/hostname: example.com
name: nginx-svc
spec:
ports:
- port: 80
protocol: tcp
targetPort: 80
selector:
app: nginx
type: LoadBalancer
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: server.example.com
http:
paths:
- backend:
serviceName: nginx-svc
servicePort: 80
path: /
```
Note the annotation on the service; use the same hostname as the Azure DNS zone created above. The annotation may also be a subdomain
of the DNS zone (e.g. 'www.example.com').
When using external-dns with ingress objects it will automatically create DNS records based on host names specified in ingress objects that match the domain-filter argument in the external-dns deployment manifest. When those host names are removed or renamed the corresponding DNS records are also altered.
ExternalDNS uses this annotation to determine what services should be registered with DNS. Removing the annotation
will cause ExternalDNS to remove the corresponding DNS records.
Create the deployment and service:
Create the deployment, service and ingress object:
```
$ kubectl create -f nginx.yaml
```

It takes a little while for the Azure cloud provider to create an external IP for the service. Check the status by running
`kubectl get services nginx`. If the `EXTERNAL-IP` field shows an address, the service is ready to be accessed externally.

Once the service has an external IP assigned, ExternalDNS will notice the new service IP address and synchronize
the Azure DNS records.
Since your external IP would have already been assigned to the nginx-ingress service, the DNS records pointing to the IP of the nginx-ingress service should be created within a minute.

## Verifying Azure DNS records

Expand Down
Loading

0 comments on commit 0e83547

Please sign in to comment.