1
1
# Multi-Cluster Tutorial
2
2
3
- This document will walk-through how to create two managed Kubernetes clusters on
4
- separate providers (GKE and EKS), deploying:
5
- - [ Dex] ( https://github.com/dexidp/dex ) as the OIDC issuer for both clusters.
6
- - [ Gangway] ( https://github.com/heptiolabs/gangway ) web server to authenticate
7
- users to Dex and help generate Kubeconfig files.
3
+ This document will walk-through how to create three managed Kubernetes clusters on
4
+ separate providers (Google, Amazon and Digitalocean), deploying:
5
+
6
+ - [ Dex] ( https://github.com/dexidp/dex ) as the OIDC issuer for both clusters.
7
+
8
+ - [ Gangway] ( https://github.com/heptiolabs/gangway ) web server to authenticate
9
+ users to Dex and help generate Kubeconfig files.
10
+
8
11
- [ kube-oidc-proxy] ( https://github.com/jetstack/kube-oidc-proxy ) to expose both
9
12
clusters to OIDC authentication.
13
+
10
14
- [ Contour] ( https://github.com/heptio/contour ) as the ingress controller with
11
15
TLS SNI passthrough enabled.
16
+
12
17
- [ Cert-Manager] ( https://github.com/jetstack/cert-manager ) to issue and manage
13
18
certificates.
14
19
@@ -17,17 +22,19 @@ supports, namely, username and password, and GitHub, however [more are
17
22
available.] ( https://github.com/dexidp/dex#connectors )
18
23
19
24
## Prerequisites
25
+
20
26
The tutorial will be using Cert-Manager to generate certificates signed by
21
- [ Let's Encrypt] ( https://letsencrypt.org/ ) for components in both GKE and EKS
22
- using a DNS challenge. Although not the only way to generate certificates, the
23
- tutorial assumes that a domain will be used which belongs to your Google Cloud
24
- project, and records of sub-domains of this domain will be created to assign DNS
25
- to the components. A Google Cloud Service Account will be created to manage
26
- these DNS challenges and it's secrets passed to Cert-Manager.
27
+ [ Let's Encrypt] ( https://letsencrypt.org/ ) for components in all clouds using a
28
+ DNS challenge. Although not the only way to generate certificates, the tutorial
29
+ assumes that a domain will be used which belongs to your Google Cloud project,
30
+ and records of sub-domains of this domain will be created to assign DNS to the
31
+ components. A Google Cloud Service Account will be created to manage these DNS
32
+ challenges and it's secrets passed to Cert-Manager.
27
33
28
34
A Service Account has been created for Terraform with its secrets stored at
29
35
` ~/.config/gcloud/terraform-admin.json ` . The Service Account needs at least
30
36
these IAM Roles attached:
37
+
31
38
```
32
39
Compute Admin
33
40
Kubernetes Engine Admin
@@ -43,57 +50,73 @@ relevent permissions to create a fully fledged cluster, including creating
43
50
load balancers, instance pools etc. Typically, these environment variables must
44
51
be set when running ` terraform ` and deploying the manifests before OIDC
45
52
authentication has been set up:
53
+
46
54
```
47
55
AWS_SECRET_ACCESS_KEY
48
56
AWS_SESSION_TOKEN
49
57
AWS_ACCESS_KEY_ID
50
58
```
51
59
60
+ For Digitalocean you need to get an write token from the console and export it
61
+ using this environment variable:
62
+
63
+ ```
64
+ DIGITALOCEAN_TOKEN
65
+ ```
66
+
52
67
## Infrastructure
68
+
53
69
First the GKE and EKS cluster will be created, along with secrets to be used for
54
70
OIDC authentication for each cluster. The Amazon Terraform module has dependant
55
71
resources on the Google module, so the Google module must be created first.
56
72
57
73
```
58
- CLOUD=google make terraform_apply
59
- CLOUD=amazon make terraform_apply
74
+ CLOUD=google make terraform_apply
75
+ CLOUD=amazon make terraform_apply
76
+ CLOUD=digitalocean make terraform_apply
60
77
```
61
78
62
- This will create a standard Kubernetes cluster in both EKS and GKE, a Service
79
+ This will create a Kubernetes cluster in EKS and GKE, a Service
63
80
Account to manage Google Cloud DNS records for DNS challenges and OIDC secrets
64
81
for both clusters. It should generate a JSON configuration file for both
65
82
clusters in ` ./manifests/google-config.json ` and ` ./manifests/amazon.json `
66
83
respectively.
67
84
68
-
69
85
## Configuration
70
- Copy ` config.dist.jsonnet ` to both ` gke-config.jsonnet ` and ` eks-config.jsonnet ` .
71
- These two files will hold configuration for setting up the OIDC authentication
72
- in both clusters as well as assigning DNS. Firstly, determine what sub-domain
73
- will be used for either cluster, using a domain you own in your Google Cloud
74
- Project, e.g.
86
+
87
+ Copy ` config.dist.jsonnet ` to ` config.jsonnet ` . This file will hold
88
+ configuration for setting up the OIDC authentication in all clusters as well as
89
+ assigning DNS. Firstly, determine what ` base_domain ` will be used for this
90
+ demo. Ensure the ` base_domain ` starts with a ` . ` .
91
+
92
+ The domain, which needs to be managed in Google Cloud DNS will have records
93
+ like this:
94
+
75
95
```
76
- gke.mydomain.company.net
77
- eks.mydomain.company.net
96
+ dex.mydomain.company.net
97
+ gangway-gke.mydomain.company.net
98
+ gangway-eks.mydomain.company.net
99
+ gangway-dok.mydomain.company.net
78
100
```
79
101
80
- Populate each configuration file with its corresponding domain and Let's
81
- Encrypt contract email.
102
+ Populate the configuration file with its corresponding domain
103
+ ( ` .mydomain.company.net ` in our example) and Let's Encrypt contact email.
82
104
83
- ### GKE
105
+ ### Dex customisations
84
106
85
- Since the GKE cluster will be hosting Dex, the OIDC issuer, its
86
- configuration file must contain how or what users will use to authenticate. Here
87
- we will show two methods, username and password, and GitHub.
107
+ Since the GKE cluster will be hosting Dex, the OIDC issuer, its configuration
108
+ file must contain how or what users will use to authenticate. Here we will show
109
+ two methods, username and password, and GitHub.
88
110
89
111
Usernames and passwords can be populated with the following block within the
90
112
` dex ` block.
91
113
92
114
```
93
- dex+: {
115
+ dex+: if $.master then {
94
116
users: [
95
117
$.dex.Password('[email protected] ', '$2y$10$i2.tSLkchjnpvnI73iSW/OPAVriV9BWbdfM6qemBM1buNRu81.ZG.'), // plaintext: secure
96
118
],
119
+ } else {
97
120
},
98
121
```
99
122
@@ -108,11 +131,12 @@ htpasswd -bnBC 10 "" MyVerySecurePassword | tr -d ':'
108
131
Dex also supports multiple 'connectors' that enable third party applications to
109
132
provide OAuth to it's system. For GitHub, this involves creating an 'OAuth App'.
110
133
The ` Authorization callback URL ` should be populated with the Dex callback URL, i.e.
111
- ` https://dex.gke.mydomain.company.net/callback ` .
134
+ ` https://dex.gke.mydomain.company.net/callback ` .
112
135
The resulting ` Client ID ` and ` Client Secret ` can then be used to populate the
113
136
configuration file:
137
+
114
138
```
115
- dex+: {
139
+ dex+: if $.master then {
116
140
connectors: [
117
141
$.dex.Connector('github', 'GitHub', 'github', {
118
142
clientID: 'myGithubAppClientID',
@@ -122,88 +146,19 @@ configuration file:
122
146
}],
123
147
}),
124
148
],
149
+ } else {
125
150
},
126
151
```
127
152
128
153
You can find more information on GitHub OAuth apps
129
154
[ here.] ( https://developer.github.com/v3/oauth/ )
130
155
131
- Finally, Dex needs to be configured to also accept the Gangway client in the EKS
132
- cluster. To do this, we add a ` dex.Client ` block in the configuration. We need to
133
- populate its redirect URL as well as the client ID and client secret using
134
- values that were created in the ` ./manifests/amazon-config.json ` by Terraform.
135
- The resulting block should would look like:
136
-
137
- ```
138
- eksClient: $.dex.Client('my_client_id_in_./manifests/amazon-config.json') + $.dex.metadata {
139
- secret: 'my_client_secret_in_./manifests/amazon-config.json',
140
- redirectURIs: [
141
- 'https://gangway.eks.mydomain.company.net/callback',
142
- ],
143
- },
144
- ```
145
-
146
- The resulting ` gke-config.jsonnet ` file should look similar to
147
-
148
- ```
149
- (import './manifests/main.jsonnet') {
150
- base_domain: 'gke.mydomain.company.net',
151
-
152
- cert_manager+: {
153
- letsencrypt_contact_email:: '[email protected] ',
154
- },
155
-
156
- dex+: {
157
- users: [
158
- $.dex.Password('[email protected] ', '$2y$10$i2.tSLkchjnpvnI73iSW/OPAVriV9BWbdfM6qemBM1buNRu81.ZG.'), // plaintext: secure
159
- ],
160
-
161
- connectors: [
162
- $.dex.Connector('github', 'GitHub', 'github', {
163
- clientID: 'myGithubAppClientID',
164
- clientSecret: 'myGithubAppClientSecret',
165
- orgs: [{
166
- name: 'company',
167
- }],
168
- }),
169
- ],
170
- },
171
-
172
- eksClient: $.dex.Client('my_client_id_in_./manifests/amazon-config.json') + $.dex.metadata {
173
- secret: 'my_client_secret_in_./manifests/amazon-config.json',
174
- redirectURIs: [
175
- 'https://gangway.eks.mydomain.company.net/callback',
176
- ],
177
- },
178
- }
179
- ```
180
-
181
- ### EKS
182
-
183
- The EKS cluster will not be hosting the dex server so only needs to be
184
- configured with its domain, Dex's domain and the Let's Encrypt contact email.
185
- The resuting ` eks-config.jsonnet ` file should look similar to:
186
-
187
- ```
188
- (import './manifests/main.jsonnet') {
189
- base_domain: 'eks.mydomain.company.net',
190
- dex_domain: 'dex.gke.mydomain.company.net',
191
- cert_manager+: {
192
- letsencrypt_contact_email:: '[email protected] ',
193
- },
194
- }
195
- ```
196
-
197
156
## Deployment
198
157
199
- Once the configuration files have been created the manifests can be deployed.
200
- Copy or create a symbolic link from the ` gke-config.jsonnet ` file to
201
- ` config.jsonnet ` and apply.
158
+ Once the configuration file has been created the manifests can be deployed.
202
159
203
160
```
204
- $ ln -s gke-config.jsonnet config.jsonnet
205
- $ export CLOUD=google
206
- $ make manifests_apply
161
+ $ CLOUD=google manifests_apply
207
162
```
208
163
209
164
You should then see the components deployed to the cluster in the ` auth `
@@ -219,6 +174,7 @@ gangway-77dfdb68d-x84hj 0/1 ContainerCreating 0 11s
219
174
```
220
175
221
176
Verify that the ingress has been configured to what you were expecting.
177
+
222
178
```
223
179
$ kubectl get ingressroutes -n auth
224
180
```
@@ -234,31 +190,17 @@ $ kubectl get -n auth secret
234
190
```
235
191
236
192
You can save these certifcates locally, and restore them any time using:
193
+
237
194
```
238
195
$ make manifests_backup_certificates
239
196
$ make manifests_restore_certificates
240
197
```
241
198
242
- An ` A ` record can now be created so that DNS can be resolve the Contour Load
243
- Balancer public IP address. Take a note of the external-IP address exposed:
244
-
245
- ```
246
- $ kubectl get svc contour -n auth
247
- ```
248
-
249
- Create a wildcard ` A ` record (matching all sub-domains), with some
250
- reasonable TTL pointing to the exposed IP address of the Contour Load Balancer.
251
-
252
- ```
253
- DNS name: *.gke.mydomain.company.net
254
- Record resource type: A
255
- IPv4 address: $CONTOUR_IP
256
- ```
257
-
258
199
You can check that the DNS record has been propagated by trying to resolve it
259
200
using:
201
+
260
202
```
261
- $ host https://gangway. gke.mydomain.company.net
203
+ $ host https://gangway- gke.mydomain.company.net
262
204
```
263
205
264
206
Once propagated, you can then visit the Gangway URL, follow the instructions and
@@ -267,28 +209,20 @@ kube-oidc-proxy. Trying the Kubeconfig, you should be greeted with an error
267
209
message that your OIDC username does not have enough RBAC permissions to access
268
210
that resource.
269
211
270
- The EKS cluster manifests can now be deployed using the ` eks-config.jsonnet ` .
212
+ The EKS and Digitalocean cluster manifests can now be deployed:
271
213
272
214
```
273
- $ rm config.jsonnet && ln -s eks-config.jsonnet config.jsonnet
274
- $ export CLOUD=amazon
275
- $ make manifests_apply
215
+ $ CLOUD=amazon manifests_apply
216
+ $ CLOUD=digitalocean manifests_apply
276
217
```
277
218
278
219
Get the AWS DNS URL for the Contour Load Balancer.
220
+
279
221
```
280
222
$ export KUBECONFIG=.kubeconfig-amazon
281
223
$ kubectl get svc -n auth
282
224
```
283
225
284
- Once the the Contour Load Balancer has an external URL, we need to create a ` CNAME `
285
- record:
286
- ```
287
- DNS name: *.eks.mydomain.company.net
288
- Record resource type: CNAME
289
- Canonical name: $CONTOUR_AWS_URL
290
- ```
291
-
292
226
When components have their TLS secrets, you will then be able to login to the
293
227
Gangway portal on EKS and download your Kubeconfig. Again, when trying this
294
228
Kubeconfig, you will initially be greeted with an "unauthorized" error message
0 commit comments