Skip to content

Commit aa0c24f

Browse files
Migrate Extend DNS for ROSA custom domain
1 parent 6960ee7 commit aa0c24f

File tree

2 files changed

+341
-0
lines changed

2 files changed

+341
-0
lines changed

_topic_maps/_topic_map_rosa.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ Topics:
104104
File: cloud-experts-aws-secret-manager
105105
- Name: Using AWS Controllers for Kubernetes on ROSA
106106
File: cloud-experts-using-aws-ack
107+
- Name: Deploying the External DNS Operator on ROSA
108+
File: cloud-experts-external-dns
107109
---
108110
Name: Getting started
109111
Dir: rosa_getting_started
Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
1+
:_content-type: ASSEMBLY
2+
[id="cloud-experts-external-dns"]
3+
= Tutorial: Deploying the External DNS Operator on ROSA
4+
include::_attributes/attributes-openshift-dedicated.adoc[]
5+
:context: cloud-experts-external-dns
6+
7+
toc::[]
8+
9+
//Mobb content metadata
10+
//Brought into ROSA product docs 2023-09-20
11+
//---
12+
//date: '2021-06-10'
13+
//title: External DNS for ROSA custom domain
14+
//weight: 1
15+
//tags: ["AWS", "ROSA"]
16+
//authors:
17+
// - Chris Kang
18+
// - Dustin Scott
19+
//---
20+
21+
Configuring the xref:../applications/deployments/osd-config-custom-domains-applications.adoc[Custom Domain Operator] requires a wildcard CNAME DNS record in your Amazon Route 53 hosted zone. If you do not want to use a wildcard record, you can use the `External DNS` Operator to create individual entries for routes.
22+
23+
This tutorial guides you through deploying and configuring the External DNS Operator with a custom domain in {product-title} (ROSA).
24+
25+
[IMPORTANT]
26+
====
27+
The External DNS Operator does not support IRSA/STS and uses long-lived IAM credentials. This tutorial will be updated once STS is supported.
28+
====
29+
30+
[id="cloud-experts-external-dns-prerequisites"]
31+
== Prerequisites
32+
33+
* A ROSA cluster
34+
* You have access to the OpenShift CLI (`oc`)
35+
* You have access to the AWS CLI (`aws`)
36+
* A unique domain, such as *.apps.<company_name>.io
37+
* An Amazon Route 53 public hosted zone for the above domain
38+
39+
=== Environment setup
40+
41+
* Prepare the environment variables:
42+
+
43+
[source,terminal]
44+
----
45+
$ export DOMAIN=apps.<company_name>.io <1>
46+
$ export AWS_PAGER=""
47+
$ export CLUSTER_NAME=$(oc get infrastructure cluster -o=jsonpath="{.status.infrastructureName}" | sed 's/-[a-z0-9]\{5\}$//')
48+
$ export REGION=$(oc get infrastructure cluster -o=jsonpath="{.status.platformStatus.aws.region}")
49+
$ export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
50+
$ export SCRATCH="/tmp/${CLUSTER_NAME}/external-dns"
51+
$ mkdir -p ${SCRATCH}
52+
$ echo "Cluster: ${CLUSTER_NAME}, Region: ${REGION}, AWS Account ID: ${AWS_ACCOUNT_ID}"
53+
----
54+
<1> The custom domain.
55+
56+
[id="cloud-experts-external-dns-custom-domain-setup"]
57+
== Custom domain setup
58+
59+
ROSA manages secondary Ingress Controllers using the Custom Domain Operator. The following procedure outlines how to deploy a secondary Ingress Controller using a custom domain.
60+
61+
.Prerequisites
62+
63+
* A unique domain, such as `*.apps.<company_name>.io`
64+
* A custom SAN or wildcard certificate, such as `CN=*.apps.<company_name>.io`
65+
66+
.Procedure
67+
68+
. Create a new project
69+
+
70+
[source,terminal]
71+
----
72+
$ oc new-project external-dns-operator
73+
----
74+
75+
. Create a new TLS secret from a private key and a public certificate, where `fullchain.pem` is your full wildcard certificate chain (including any intermediaries) and `privkey.pem` is your wildcard certificate's private key.
76+
+
77+
.Example
78+
[source,terminal]
79+
----
80+
$ oc -n external-dns-operator create secret tls external-dns-tls --cert=fullchain.pem --key=privkey.pem
81+
----
82+
83+
. Create a new `CustomDomain` custom resource (CR):
84+
+
85+
.Example `external-dns-custom-domain.yaml`
86+
[source,yaml]
87+
----
88+
apiVersion: managed.openshift.io/v1alpha1
89+
kind: CustomDomain
90+
metadata:
91+
name: external-dns
92+
spec:
93+
domain: apps.<company_name>.io <1>
94+
scope: External
95+
loadBalancerType: NLB
96+
certificate:
97+
name: external-dns-tls
98+
namespace: external-dns-operator
99+
----
100+
<1> The custom domain.
101+
102+
. Apply the CR:
103+
+
104+
.Example
105+
[source,terminal]
106+
----
107+
$ oc apply -f external-dns-custom-domain.yaml
108+
----
109+
110+
. Verify that your custom domain Ingress Controller has been deployed and is `Ready`:
111+
+
112+
[source,terminal]
113+
----
114+
$ oc get customdomains
115+
----
116+
+
117+
.Example output
118+
[source,terminal]
119+
----
120+
NAME ENDPOINT DOMAIN STATUS
121+
external-dns xxrywp.<company_name>.cluster-01.opln.s1.openshiftapps.com *.apps.<company_name>.io Ready
122+
----
123+
124+
[id="cloud-experts-external-dns-prepare-aws-account"]
125+
== Prepare AWS account
126+
127+
. Retrieve the Amazon Route 53 public hosted zone ID:
128+
+
129+
[source,terminal]
130+
----
131+
$ export ZONE_ID=$(aws route53 list-hosted-zones-by-name --output json \
132+
--dns-name "${DOMAIN}." --query 'HostedZones[0]'.Id --out text | sed 's/\/hostedzone\///')
133+
----
134+
+
135+
. Create an AWS IAM Policy document that allows the External DNS Operator to update _only_ the custom domain public hosted zone:
136+
+
137+
[source,terminal]
138+
----
139+
$ cat << EOF > "${SCRATCH}/external-dns-policy.json"
140+
{
141+
"Version": "2012-10-17",
142+
"Statement": [
143+
{
144+
"Effect": "Allow",
145+
"Action": [
146+
"route53:ChangeResourceRecordSets"
147+
],
148+
"Resource": [
149+
"arn:aws:route53:::hostedzone/${ZONE_ID}"
150+
]
151+
},
152+
{
153+
"Effect": "Allow",
154+
"Action": [
155+
"route53:ListHostedZones",
156+
"route53:ListResourceRecordSets"
157+
],
158+
"Resource": [
159+
"*"
160+
]
161+
}
162+
]
163+
}
164+
EOF
165+
----
166+
+
167+
. Create an AWS IAM policy:
168+
+
169+
[source,terminal]
170+
----
171+
$ export POLICY_ARN=$(aws iam create-policy --policy-name "${CLUSTER_NAME}-AllowExternalDNSUpdates" \
172+
--policy-document file://${SCRATCH}/external-dns-policy.json \
173+
--query 'Policy.Arn' --output text)
174+
----
175+
+
176+
. Create an AWS IAM user:
177+
+
178+
[source,terminal]
179+
----
180+
$ aws iam create-user --user-name "${CLUSTER_NAME}-external-dns-operator"
181+
----
182+
. Attach the policy:
183+
+
184+
[source,terminal]
185+
----
186+
$ aws iam attach-user-policy --user-name "${CLUSTER_NAME}-external-dns-operator" --policy-arn $POLICY_ARN
187+
----
188+
+
189+
[NOTE]
190+
====
191+
This will be changed to STS using IRSA in the future.
192+
====
193+
. Create AWS keys for the IAM user:
194+
+
195+
[source,terminal]
196+
----
197+
$ SECRET_ACCESS_KEY=$(aws iam create-access-key --user-name "${CLUSTER_NAME}-external-dns-operator")
198+
----
199+
. Create static credentials:
200+
+
201+
[source,terminal]
202+
----
203+
$ cat << EOF > "${SCRATCH}/credentials"
204+
[default]
205+
aws_access_key_id = $(echo $SECRET_ACCESS_KEY | jq -r '.AccessKey.AccessKeyId')
206+
aws_secret_access_key = $(echo $SECRET_ACCESS_KEY | jq -r '.AccessKey.SecretAccessKey')
207+
EOF
208+
----
209+
210+
[id="cloud-experts-external-dns-install-external-dns-operator"]
211+
== Install the External DNS Operator
212+
213+
. Install the External DNS Operator from OperatorHub:
214+
+
215+
[source,terminal]
216+
----
217+
$ cat << EOF | oc apply -f -
218+
apiVersion: operators.coreos.com/v1
219+
kind: OperatorGroup
220+
metadata:
221+
name: external-dns-group
222+
namespace: external-dns-operator
223+
spec:
224+
targetNamespaces:
225+
- external-dns-operator
226+
---
227+
apiVersion: operators.coreos.com/v1alpha1
228+
kind: Subscription
229+
metadata:
230+
name: external-dns-operator
231+
namespace: external-dns-operator
232+
spec:
233+
channel: stable-v1.1
234+
installPlanApproval: Automatic
235+
name: external-dns-operator
236+
source: redhat-operators
237+
sourceNamespace: openshift-marketplace
238+
EOF
239+
----
240+
+
241+
. Wait until the External DNS Operator is running:
242+
+
243+
[source,terminal]
244+
----
245+
$ oc rollout status deploy external-dns-operator --timeout=300s
246+
----
247+
+
248+
. Create a secret from the AWS IAM user credentials:
249+
+
250+
[source,terminal]
251+
----
252+
$ oc -n external-dns-operator create secret generic external-dns \
253+
--from-file "${SCRATCH}/credentials"
254+
----
255+
. Deploy the ExternalDNS controller:
256+
+
257+
[source,terminal]
258+
----
259+
$ cat << EOF | oc apply -f -
260+
apiVersion: externaldns.olm.openshift.io/v1beta1
261+
kind: ExternalDNS
262+
metadata:
263+
name: ${DOMAIN}
264+
spec:
265+
domains:
266+
- filterType: Include
267+
matchType: Exact
268+
name: ${DOMAIN}
269+
provider:
270+
aws:
271+
credentials:
272+
name: external-dns
273+
type: AWS
274+
source:
275+
openshiftRouteOptions:
276+
routerName: external-dns
277+
type: OpenShiftRoute
278+
zones:
279+
- ${ZONE_ID}
280+
EOF
281+
----
282+
. Wait until the controller is running:
283+
+
284+
[source,terminal]
285+
----
286+
$ oc rollout status deploy external-dns-${DOMAIN} --timeout=300s
287+
----
288+
289+
[id="cloud-experts-external-dns-deploy-a-sample-application"]
290+
== Deploy a sample application
291+
292+
. Create a new project for our sample application:
293+
+
294+
[source,terminal]
295+
----
296+
$ oc new-project hello-world
297+
----
298+
+
299+
. Deploy a hello world application:
300+
+
301+
[source,terminal]
302+
----
303+
$ oc new-app -n hello-world --image=docker.io/openshift/hello-openshift
304+
----
305+
+
306+
. Create a route for the application specifying your custom domain name:
307+
+
308+
.Example
309+
+
310+
[source,terminal]
311+
----
312+
$ oc -n hello-world create route edge --service=hello-openshift hello-openshift-tls \
313+
--hostname hello-openshift.${DOMAIN}
314+
----
315+
. Check if the DNS record was created automatically by ExternalDNS:
316+
+
317+
[NOTE]
318+
====
319+
It can take a few minutes for the record to appear in Amazon Route 53.
320+
====
321+
+
322+
[source,terminal]
323+
----
324+
$ aws route53 list-resource-record-sets --hosted-zone-id ${ZONE_ID} \
325+
--query "ResourceRecordSets[?Type == 'CNAME']" | grep hello-openshift
326+
----
327+
. You can also view the TXT records that indicate they were created by ExternalDNS:
328+
+
329+
[source,terminal]
330+
----
331+
$ aws route53 list-resource-record-sets --hosted-zone-id ${ZONE_ID} \
332+
--query "ResourceRecordSets[?Type == 'TXT']" | grep ${DOMAIN}
333+
----
334+
. Navigate to your custom console domain in the browser where you see the OpenShift login.
335+
+
336+
[source,terminal]
337+
----
338+
$ echo console.${DOMAIN}
339+
----

0 commit comments

Comments
 (0)