├── .gitignore ├── 01-clusters └── main.tf ├── 02-karmada └── main.tf ├── 03-workers └── main.tf ├── 04-discovery └── main.tf ├── 05-dashboards └── main.tf ├── README.md ├── assets ├── preview.gif └── preview.mp4 ├── certs ├── cluster1 │ ├── ca-cert.pem │ ├── ca-key.pem │ ├── cert-chain.pem │ └── root-cert.pem ├── cluster2 │ ├── ca-cert.pem │ ├── ca-key.pem │ ├── cert-chain.pem │ └── root-cert.pem ├── cluster3 │ ├── ca-cert.pem │ ├── ca-key.pem │ ├── cert-chain.pem │ └── root-cert.pem ├── root-ca.conf ├── root-cert.csr ├── root-cert.pem └── root-key.pem ├── demo ├── dashboard.sh ├── hello.yaml ├── hello2.yaml ├── simple-policy.yaml ├── weighted-policy.yaml └── weighted-policy2.yaml ├── modules ├── cluster │ └── main.tf ├── dashboard │ └── main.tf ├── discovery │ └── main.tf ├── karmada-manager │ └── main.tf └── karmada-worker │ ├── expose.yaml │ └── main.tf ├── test.sh └── world-map ├── README.md ├── app.js ├── index.html └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | istio 2 | karmada 3 | terraform.tfstate 4 | terraform.tfstate.backup 5 | karmada-config 6 | kube-config-* 7 | kubeconfig-* 8 | node_ip.txt 9 | .terraform.lock.hcl 10 | terraform.tfstate.* 11 | .terraform 12 | .terraform.tfstate.lock.info 13 | -------------------------------------------------------------------------------- /01-clusters/main.tf: -------------------------------------------------------------------------------- 1 | module "cluster_manager" { 2 | source = "../modules/cluster" 3 | 4 | name = "cluster-manager" 5 | region = "us-west" 6 | } 7 | 8 | resource "local_file" "kubeconfig_cluster_manager" { 9 | filename = "../kubeconfig-cluster-manager" 10 | content = module.cluster_manager.kubeconfig 11 | } 12 | 13 | module "ap" { 14 | source = "../modules/cluster" 15 | 16 | name = "ap" 17 | region = "ap-south" 18 | } 19 | 20 | resource "local_file" "kubeconfig_ap" { 21 | filename = "../kubeconfig-ap" 22 | content = module.ap.kubeconfig 23 | } 24 | 25 | module "us" { 26 | source = "../modules/cluster" 27 | 28 | name = "us" 29 | region = "us-west" 30 | } 31 | 32 | resource "local_file" "kubeconfig_us" { 33 | filename = "../kubeconfig-us" 34 | content = module.us.kubeconfig 35 | } 36 | 37 | module "eu" { 38 | source = "../modules/cluster" 39 | 40 | name = "eu" 41 | region = "eu-west" 42 | } 43 | 44 | resource "local_file" "kubeconfig_eu" { 45 | filename = "../kubeconfig-eu" 46 | content = module.eu.kubeconfig 47 | } 48 | -------------------------------------------------------------------------------- /02-karmada/main.tf: -------------------------------------------------------------------------------- 1 | module "karmada" { 2 | source = "../modules/karmada-manager" 3 | 4 | kubeconfig_path = "../kubeconfig-cluster-manager" 5 | } 6 | 7 | resource "local_file" "karmada_config" { 8 | filename = "../karmada-config" 9 | content = module.karmada.karmada_config 10 | } -------------------------------------------------------------------------------- /03-workers/main.tf: -------------------------------------------------------------------------------- 1 | module "worker_ap" { 2 | source = "../modules/karmada-worker" 3 | 4 | cluster_name = "ap" 5 | kubeconfig_path = abspath("../kubeconfig-ap") 6 | certs = { 7 | "ca-cert.pem" = file("../certs/cluster1/ca-cert.pem") 8 | "ca-key.pem" = file("../certs/cluster1/ca-key.pem") 9 | "root-cert.pem" = file("../certs/cluster1/root-cert.pem") 10 | "cert-chain.pem" = file("../certs/cluster1/cert-chain.pem") 11 | } 12 | network_name = "network1" 13 | karmada_config = abspath("../karmada-config") 14 | } 15 | 16 | module "worker_us" { 17 | source = "../modules/karmada-worker" 18 | 19 | cluster_name = "us" 20 | kubeconfig_path = abspath("../kubeconfig-us") 21 | certs = { 22 | "ca-cert.pem" = file("../certs/cluster2/ca-cert.pem") 23 | "ca-key.pem" = file("../certs/cluster2/ca-key.pem") 24 | "root-cert.pem" = file("../certs/cluster2/root-cert.pem") 25 | "cert-chain.pem" = file("../certs/cluster2/cert-chain.pem") 26 | } 27 | network_name = "network2" 28 | karmada_config = abspath("../karmada-config") 29 | } 30 | 31 | module "worker_eu" { 32 | source = "../modules/karmada-worker" 33 | 34 | cluster_name = "eu" 35 | kubeconfig_path = abspath("../kubeconfig-eu") 36 | certs = { 37 | "ca-cert.pem" = file("../certs/cluster3/ca-cert.pem") 38 | "ca-key.pem" = file("../certs/cluster3/ca-key.pem") 39 | "root-cert.pem" = file("../certs/cluster3/root-cert.pem") 40 | "cert-chain.pem" = file("../certs/cluster3/cert-chain.pem") 41 | } 42 | network_name = "network3" 43 | karmada_config = abspath("../karmada-config") 44 | } 45 | -------------------------------------------------------------------------------- /04-discovery/main.tf: -------------------------------------------------------------------------------- 1 | module "worker_ap" { 2 | source = "../modules/discovery" 3 | 4 | cluster_name = "ap" 5 | kubeconfig_path = abspath("../kubeconfig-ap") 6 | cluster_discovery = { 7 | "us" = { cluster_name = "us", kubeconfig_path = abspath("../kubeconfig-us") } 8 | "eu" = { cluster_name = "eu", kubeconfig_path = abspath("../kubeconfig-eu") } 9 | } 10 | } 11 | 12 | module "worker_us" { 13 | source = "../modules/discovery" 14 | 15 | cluster_name = "us" 16 | kubeconfig_path = abspath("../kubeconfig-us") 17 | cluster_discovery = { 18 | "ap" = { cluster_name = "ap", kubeconfig_path = abspath("../kubeconfig-ap") } 19 | "eu" = { cluster_name = "eu", kubeconfig_path = abspath("../kubeconfig-eu") } 20 | } 21 | } 22 | 23 | module "worker_eu" { 24 | source = "../modules/discovery" 25 | 26 | cluster_name = "eu" 27 | kubeconfig_path = abspath("../kubeconfig-eu") 28 | cluster_discovery = { 29 | "ap" = { cluster_name = "ap", kubeconfig_path = abspath("../kubeconfig-ap") } 30 | "us" = { cluster_name = "us", kubeconfig_path = abspath("../kubeconfig-us") } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /05-dashboards/main.tf: -------------------------------------------------------------------------------- 1 | module "worker_ap" { 2 | source = "../modules/dashboard" 3 | 4 | cluster_name = "ap" 5 | kubeconfig_path = abspath("../kubeconfig-ap") 6 | } 7 | 8 | output "kiali_token_ap" { 9 | value = module.worker_ap.token 10 | } 11 | 12 | module "worker_us" { 13 | source = "../modules/dashboard" 14 | 15 | cluster_name = "us" 16 | kubeconfig_path = abspath("../kubeconfig-us") 17 | } 18 | 19 | output "kiali_token_us" { 20 | value = module.worker_us.token 21 | } 22 | 23 | module "worker_eu" { 24 | source = "../modules/dashboard" 25 | 26 | cluster_name = "eu" 27 | kubeconfig_path = abspath("../kubeconfig-eu") 28 | } 29 | 30 | output "kiali_token_eu" { 31 | value = module.worker_eu.token 32 | } 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Multi-cluster, multi-region, multi-cloud Kubernetes 2 | 3 | This project helps you bootstrap and orchestrate several Kubernetes clusters across different regions and clouds from a single control plane. 4 | 5 | ![Scaling Kubernetes clusters across regions and clouds](assets/preview.gif) 6 | 7 | The setup helps study: 8 | 9 | - High availability installation of Kubernetes. 10 | - Multi-region deployments. 11 | - Multi-cloud deployments. 12 | - Upgrading clusters and apps. 13 | 14 | ## Getting started 15 | 16 | You need to create a Linode token to access the API: 17 | 18 | ```bash 19 | linode-cli profile token-create 20 | export LINODE_TOKEN= 21 | ``` 22 | 23 | ```bash 24 | # Create the clusters 25 | terraform -chdir=01-clusters init 26 | terraform -chdir=01-clusters apply -auto-approve 27 | 28 | # Install Karmada in the cluster manager 29 | terraform -chdir=02-karmada init 30 | terraform -chdir=02-karmada apply -auto-approve 31 | 32 | # Configure the Karmada workers and install Istio 33 | terraform -chdir=03-workers init 34 | terraform -chdir=03-workers apply -auto-approve 35 | 36 | # Discover other Istio installations 37 | terraform -chdir=04-discovery init 38 | terraform -chdir=04-discovery apply -auto-approve 39 | 40 | # Install Kiali 41 | terraform -chdir=05-dashboards init 42 | terraform -chdir=05-dashboards apply -auto-approve 43 | 44 | # Clean up 45 | terraform -chdir=05-dashboards destroy -auto-approve 46 | terraform -chdir=04-discovery destroy -auto-approve 47 | terraform -chdir=03-workers destroy -auto-approve 48 | terraform -chdir=02-karmada destroy -auto-approve 49 | terraform -chdir=01-clusters destroy -auto-approve 50 | ``` 51 | 52 | ## Accessing the Kiali dashboard 53 | 54 | ```bash 55 | kubectl --kubeconfig=kubeconfig-ap port-forward svc/kiali 8081:20001 -n istio-system 56 | ``` 57 | 58 | ## Testing the code 59 | 60 | ```bash 61 | ./test.sh 62 | ``` 63 | 64 | The script will print the command you can use to launch the world map dashboard. 65 | 66 | ## Creating new certs 67 | 68 | ```bash 69 | $ git clone https://github.com/istio/istio 70 | ``` 71 | 72 | Create a `certs` folder and change to that directory: 73 | 74 | ```bash 75 | $ mkdir certs 76 | $ cd certs 77 | ``` 78 | 79 | Create the root certificate with: 80 | 81 | ```bash 82 | $ make -f ../istio/tools/certs/Makefile.selfsigned.mk root-ca 83 | ``` 84 | 85 | The command generated the following files: 86 | 87 | - `root-cert.pem`: the generated root certificate. 88 | - `root-key.pem`: the generated root key. 89 | - `root-ca.conf`: the configuration for OpenSSL to generate the root certificate. 90 | - `root-cert.csr`: the generated CSR for the root certificate. 91 | 92 | For each cluster, generate an intermediate certificate and key for the Istio Certificate Authority: 93 | 94 | ```bash 95 | $ make -f ../istio/tools/certs/Makefile.selfsigned.mk cluster1-cacerts 96 | $ make -f ../istio/tools/certs/Makefile.selfsigned.mk cluster2-cacerts 97 | $ make -f ../istio/tools/certs/Makefile.selfsigned.mk cluster3-cacerts 98 | ``` 99 | 100 | ## Notes 101 | 102 | - Sometimes, the EastWest gateway cannot be created because of a validation admission webhook. Since this is sporadic, I think it's related to a race condition. [More on this here.](https://github.com/istio/istio/issues/39205) 103 | - This Terraform files use the `null_resource` and `kubectl`. You should have `kubectl` installed locally. 104 | -------------------------------------------------------------------------------- /assets/preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/learnk8s/multi-cluster/844bc38b7f3539ad9130fe3151f02404a8eba6c4/assets/preview.gif -------------------------------------------------------------------------------- /assets/preview.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/learnk8s/multi-cluster/844bc38b7f3539ad9130fe3151f02404a8eba6c4/assets/preview.mp4 -------------------------------------------------------------------------------- /certs/cluster1/ca-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | Hlpbw7KSnmOFRqvrsg== 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /certs/cluster1/ca-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | uTupIQTXsU6vyfc1HzOS7bOIXiFU 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /certs/cluster1/cert-chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFeTCCA2GgAwIBAgIUXAPwOlSx6MIW6E+xzooJw0Evwu4wDQYJKoZIhvcNAQEL 3 | BQAwIjEOMAwGA1UECgwFSXN0aW8xEDAOBgNVBAMMB1Jvb3QgQ0EwHhcNMjIwODAz 4 | MDMxODQyWhcNMjQwODAyMDMxODQyWjA9MQ4wDAYDVQQKDAVJc3RpbzEYMBYGA1UE 5 | AwwPSW50ZXJtZWRpYXRlIENBMREwDwYDVQQHDAhjbHVzdGVyMTCCAiIwDQYJKoZI 6 | hvcNAQEBBQADggIPADCCAgoCggIBAKMtdP/1ho6vFvuQo9iCwyrWc2/KZNvY0h+R 7 | 9ht79qed1DxkykKdPJWwUudm10+MR/LbM8h4mtEviV8iYPVbfMhQuFKFUWM0n/+T 8 | Tpf04H/Mx6oYZN+FNvkdqkc5FFNaY4TGqU0T31qVWsl6FMXUEANFJPXa+W6guRvp 9 | dGA5rVqxTA7nyXkoL5z0tvSMkzEE6Dr07KR5g7vDs78WkQes8mPN7fZcmv/+duLj 10 | Rsl6UOw1+2cQjJlYgZt5+bxBdWejdSPBP4YpUwyrVBjbmrr3ZyO5UwQI8m3VIjeZ 11 | ns/6guNOmzMJ3VZ7Qy3xxFbCxQC03s7oOOvf7aUPtnSrj4eVaunU9KEYnaCZcB6H 12 | UrNqX3H6P+3wF4the74dd4j9ipEBOd1bVjXvqeJp5r3Uq6lUYUwoCYUOLzF7biYk 13 | E6KXA32PPDML5mi11A3VBnq0qOB+JVk1LOXw9t9x7KxAj7QlNJo5/ypt9CytSAkE 14 | bsJ37KFEqM4vEI3btTkFtadhoeWGXAawmCqkAXBMsNSFUfmUzRYhmtXvB/bdrJ/L 15 | t2NacaGDAEXEEVkGBhKbsp7gUyE1XxrigACPZfb1nZDoK5hWq5MiA71Pip40EcIa 16 | BC8Arj+gQWm6xdDpqn9trNiD/X1QlmCEo5ckc8dCztC4TkDKe03U/PFiVhTXutl6 17 | 0583pP89AgMBAAGjgYswgYgwHQYDVR0OBBYEFACZfOMcQkgvn+w8rRIgY/BjlgUy 18 | MBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgLkMCIGA1UdEQQbMBmC 19 | F2lzdGlvZC5pc3Rpby1zeXN0ZW0uc3ZjMB8GA1UdIwQYMBaAFDUAGPBhMOGkwsPa 20 | BScNt19wEWvmMA0GCSqGSIb3DQEBCwUAA4ICAQAGlXycA65OqC+STrXKlSffTySp 21 | B2fX6UxsxKYla9AiJXmJ16MspbKAt9cX/i/biokgdD2RJLHKN7pROhwIq9B8r2Dd 22 | Z7laZmOqczbnwojXTkKmEk2ynwj5PIGVCPnns34n7U2XGEppPBGFlCRXzsh7XLcL 23 | vfNH3SiptaBxSEaNnuu1+EP5rKtJlPzG9nBOZk8waWG+KzfEUbFpHzeI3usAVJcs 24 | 6G0xFOLZD19PUUowzGh4sNf7MX0kZEALaUy0MGhm7pSft1YWz2UV3LvN2h92cYxw 25 | hYFtIPipIVpuJGYWNZikDNJOX0+++Flx/zkvz0k3fG7o01TR4yf/G0x5CgDoHfP8 26 | 3YNZ/AIejPpEbLG+0ftz8tvbAr6rS6JA+6H2eMNF6j1sN9WpYDIjEJ8cRTz4rkUG 27 | gy7JeZLYdkWAYxuGm9HZ5IAXgR6JmHyglSiM3Es/ugJe0iPl4N6y0A7D169DChhh 28 | wjTEDnstM73ARLuLXfz5DQqUgl9rvAd+M0oX/VC6F2BFnGSz3b2NEeAUm5YDMEyV 29 | AciMTQl3nRZXBL0HS6jg4Axlmw8rNWwJjEDBoZ5Sp3u8XNN/q33Y26Ojag2ww2wX 30 | jRPpzXzykVnblHmfZYg36In9A7+pqhTAMCLj1NtN7+9c4Fk5lAAxHtAyBu7HAFv/ 31 | Hlpbw7KSnmOFRqvrsg== 32 | -----END CERTIFICATE----- 33 | -----BEGIN CERTIFICATE----- 34 | MIIFFDCCAvygAwIBAgIUY/8vm3/ORktKIUPKEc3RrWDd+2IwDQYJKoZIhvcNAQEL 35 | BQAwIjEOMAwGA1UECgwFSXN0aW8xEDAOBgNVBAMMB1Jvb3QgQ0EwHhcNMjIwODAz 36 | MDMxODM1WhcNMzIwNzMxMDMxODM1WjAiMQ4wDAYDVQQKDAVJc3RpbzEQMA4GA1UE 37 | AwwHUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOFy2Yfu 38 | Lfmh7rf4Gsx6pJB9UeNR4KtRGpUqJssPuQdVPDSgxeXZMVUuEVDl6YsoanbqLVf2 39 | uUAu+FAlPZTX5W7RXuwc/tl/0g5mP94StTJgLkcsfmq4/ajxYY6oiAcR+rKgK640 40 | C6ci8pFiAWRRnGjplCA/K4ijJ1anSxIdUJRRCMMjPdystnLp94d9Eie9KW9HfgWQ 41 | 2SJyAhvy/hAaEL0DGue6JcYikI7Pf5Hp0V364uULRWS6LZIgaUyykKOD83UgKH6R 42 | yg5hxEYGn2S/omh+xGefQltDd8zPuTOLnGob3NY/Zwq4XG4iEmMpXOgkGPawig+d 43 | QgXepTELADJ06qDxfA6hdC//uOQWWhawX6SKMMC0B0Vog31djd+3s5hXP6S3o8Vk 44 | kKg+RsvOlQNU1pCxLtfOEKv9kadFzE0r02TPJG/1LXWH27oVw0LE8rEmnsL3tC+x 45 | 2yGz8Sh4v2Hje7I9JLXwmVyTOPBVLKI4ounhbDUJxrnvjI79N6Ma6ol790+TgRDo 46 | W15Sj7miEnuPQMs5SYFTDsQWQj9fKax3EaMIRqQq0DZf4zyKVBtD9w+WJojemQf3 47 | 85Rc+EMju83LJgAVDdtgvxc5XD/+JJojads1SP6rNvZRMHFY1fJ7YtlEBzISw01u 48 | GigcQqa1dOql9rznUxqheJOfpWQv1lXzZh0pAgMBAAGjQjBAMB0GA1UdDgQWBBQ1 49 | ABjwYTDhpMLD2gUnDbdfcBFr5jAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE 50 | AwIC5DANBgkqhkiG9w0BAQsFAAOCAgEAHLnpXhtkE4H6W1i81cLTi+CiqFPC5yy0 51 | DvCAeSVZIyHD5Fyj+IkDra9CoLU1YkD6tOgWvEGfisIN+E9bI7E1h6Cpn54VF66W 52 | RYIX+3lPDp2sFc13fb8LkKqo9qTrnhw/Xu9ENN+q/bJT5ZYOALbZrtXCMNb05ps4 53 | 4jyvjGzvn2BeNGIXJSXBxGOn0AT73syKTUerJcXQXQYslDIVaTVSpHrHv3A/LsXK 54 | kg5pL2y7/fgOhixJ6cV1UomlrpVZNEaeO36hpa7l8D5vVK+kJ8scsGhe+s546EWK 55 | D7fdTlhAv2UkWleief4rZ9340xXhNrZy1QagC8+dw7H+oZI1n2Kqv4xyEpVEaRTR 56 | aMx/J1dk612uNYC8v+Iqog0bZHkTVzfoW+DCDkgPwxy7XcL8a7IcovFF/8jqhXzG 57 | FGzy5NDAEwpaffCL6+G0abxPabi/GYlKm4knbAxMuQyk+4FlRPWc9b5EquYrgatM 58 | iQI0zdhbzw1wTk175Mf4mAxeMFGg5vfM1XmiaGfM5/6+zNsuibEpuwTilPUhlLmh 59 | z+gGGkQYTjH36AaTlKn3SegtJFaaRK4Gt/gEqvLQIhsUTv3U2NprFqrdP4DnktBy 60 | 75mUh1n1Q0kX8BIHGIA3h7WHau0F0YO4gE48CsCIWk+pIy6VWEkTVrOdaO8TL1uj 61 | 7OLbGFrhAbQ= 62 | -----END CERTIFICATE----- 63 | -------------------------------------------------------------------------------- /certs/cluster1/root-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFFDCCAvygAwIBAgIUY/8vm3/ORktKIUPKEc3RrWDd+2IwDQYJKoZIhvcNAQEL 3 | BQAwIjEOMAwGA1UECgwFSXN0aW8xEDAOBgNVBAMMB1Jvb3QgQ0EwHhcNMjIwODAz 4 | MDMxODM1WhcNMzIwNzMxMDMxODM1WjAiMQ4wDAYDVQQKDAVJc3RpbzEQMA4GA1UE 5 | AwwHUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOFy2Yfu 6 | Lfmh7rf4Gsx6pJB9UeNR4KtRGpUqJssPuQdVPDSgxeXZMVUuEVDl6YsoanbqLVf2 7 | uUAu+FAlPZTX5W7RXuwc/tl/0g5mP94StTJgLkcsfmq4/ajxYY6oiAcR+rKgK640 8 | C6ci8pFiAWRRnGjplCA/K4ijJ1anSxIdUJRRCMMjPdystnLp94d9Eie9KW9HfgWQ 9 | 2SJyAhvy/hAaEL0DGue6JcYikI7Pf5Hp0V364uULRWS6LZIgaUyykKOD83UgKH6R 10 | yg5hxEYGn2S/omh+xGefQltDd8zPuTOLnGob3NY/Zwq4XG4iEmMpXOgkGPawig+d 11 | QgXepTELADJ06qDxfA6hdC//uOQWWhawX6SKMMC0B0Vog31djd+3s5hXP6S3o8Vk 12 | kKg+RsvOlQNU1pCxLtfOEKv9kadFzE0r02TPJG/1LXWH27oVw0LE8rEmnsL3tC+x 13 | 2yGz8Sh4v2Hje7I9JLXwmVyTOPBVLKI4ounhbDUJxrnvjI79N6Ma6ol790+TgRDo 14 | W15Sj7miEnuPQMs5SYFTDsQWQj9fKax3EaMIRqQq0DZf4zyKVBtD9w+WJojemQf3 15 | 85Rc+EMju83LJgAVDdtgvxc5XD/+JJojads1SP6rNvZRMHFY1fJ7YtlEBzISw01u 16 | GigcQqa1dOql9rznUxqheJOfpWQv1lXzZh0pAgMBAAGjQjBAMB0GA1UdDgQWBBQ1 17 | ABjwYTDhpMLD2gUnDbdfcBFr5jAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE 18 | AwIC5DANBgkqhkiG9w0BAQsFAAOCAgEAHLnpXhtkE4H6W1i81cLTi+CiqFPC5yy0 19 | DvCAeSVZIyHD5Fyj+IkDra9CoLU1YkD6tOgWvEGfisIN+E9bI7E1h6Cpn54VF66W 20 | RYIX+3lPDp2sFc13fb8LkKqo9qTrnhw/Xu9ENN+q/bJT5ZYOALbZrtXCMNb05ps4 21 | 4jyvjGzvn2BeNGIXJSXBxGOn0AT73syKTUerJcXQXQYslDIVaTVSpHrHv3A/LsXK 22 | kg5pL2y7/fgOhixJ6cV1UomlrpVZNEaeO36hpa7l8D5vVK+kJ8scsGhe+s546EWK 23 | D7fdTlhAv2UkWleief4rZ9340xXhNrZy1QagC8+dw7H+oZI1n2Kqv4xyEpVEaRTR 24 | aMx/J1dk612uNYC8v+Iqog0bZHkTVzfoW+DCDkgPwxy7XcL8a7IcovFF/8jqhXzG 25 | FGzy5NDAEwpaffCL6+G0abxPabi/GYlKm4knbAxMuQyk+4FlRPWc9b5EquYrgatM 26 | iQI0zdhbzw1wTk175Mf4mAxeMFGg5vfM1XmiaGfM5/6+zNsuibEpuwTilPUhlLmh 27 | z+gGGkQYTjH36AaTlKn3SegtJFaaRK4Gt/gEqvLQIhsUTv3U2NprFqrdP4DnktBy 28 | 75mUh1n1Q0kX8BIHGIA3h7WHau0F0YO4gE48CsCIWk+pIy6VWEkTVrOdaO8TL1uj 29 | 7OLbGFrhAbQ= 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /certs/cluster2/ca-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | K5M2DJHknRU1CN3LqA== 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /certs/cluster2/ca-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQCkSswjvOHd7mKS 3 | jojTsY9psD8dr8O+sKy8VCt9P/6vVkhfaNytfHRW4uH3o0AzbYP9+8Cmt+5JXIaC 4 | zNWvoOa98B8h32+1U7yQLGePuNWefwcnUNyO589MPIJMeZsIuxnB20/Q1xuCXuid 5 | rzDm+s9yBomcilFEsf75Evi2YpxpiV/mwW9d7zCIYcwexg2/lLk9Tkr/0x0V91oP 6 | dtnJN/lJRK5z7e54oG2Dbh9ZEvAemywuZqmFgAK7XkW9rMnriiOXvIfcMhfCVpTg 7 | 9omlj6H5kz8IqrLwqdphUgL8Oz7LVIiXEKnQyYI6MaDCwX8CQJXdxbxneSqyDUoZ 8 | zBeArTifnvv53Q3UwgkB/dA00hCyzZ9yo869cIfVncfOq+4zwxTiuxMLksx1smoZ 9 | mBfashf7Xnjjep5OO+Bnw68PV85XoRArv7EVXVV/xoFnM1nFEoKJLFMAIR6McPW8 10 | X9mu/uXrVNJ8dcr64VR+LYlrIJHzUEvbZQHAtLdYsZbh4LU8V3Q8Oi7yrOZ6juTG 11 | 925sRE/ENzZTetoCVGNp4xcqlvYreydYWmKHzxPYGHxjrSz1k7SlbhwCRUkmK7rh 12 | J0qfY7TYcpjVpfSlax6K9HEOX8kskYfSc4v4HRz1aBJqm8a9SxRyYnEacmPlluS4 13 | q4COM0o44Ch/D9niO+kwPbQCp4zEJQIDAQABAoICACl6gOOc8mF3qAdcWQspTw3d 14 | 43F5SLBCJro9feVXXNOjsw3ziZN7UlwFWAuPecwCIErlXpQ45745z/QCBwkaVGcr 15 | 0pBYuvlKtNapf1P31Gb5pzKz5Ztmxx12QWdRZGTl5/Dbj+EoDdfyYkQ9UNlgBTPC 16 | lseg3De9wKPduFFDwD2c40t9FsLeeqBUIJa8ZggyYjoqJCFGiZdcJa610PJOYW+w 17 | GWNHdOebiUqfaOayM1Fm19a3MKF12jq36F+k2i3PaIEMpjhfpUP5XAkX9VSJWNmL 18 | 5WQoxJiiKXJcpEhOJOJs6zdIi7ccyPYsRWwmMgy9hZjCLXjqTG87j7PHpT9lfF/Y 19 | yFfXrSqQFpXxUdNP/it6LhOvtgLcCyQYD2fsWshL5t1Nj+4ODGPv38fPKHHDd06C 20 | d+G/+RP7gpMHBYIEzv/MluoKnyBZbUMs0g7MjfVYtbAsjzyxfpLnKp7lFKhC3fIc 21 | Wy/TleSqFamFakUnZauQ1d80XKoNlxrcE6HPnMPGCjlw0545SeGUrh0TxoIHfIHR 22 | xquCvC2f04AoDP4A4fuj3QM45dFSLg+T42k01BhQw/Ebkrj1yBs9AaXmtFUI4plr 23 | VJbfNwVSuyfXiKFi/r5aURZV+puGeTtb+WyZZYX39DtZrkSUoURqyVyHBAy4nO/2 24 | ldgD+6eu1asB3aAhyccZAoIBAQDHLhmVIfpYDKz/ZpDtoiLzfsq5NpbQDpRl+KMv 25 | NshCz7okPgPWcMdYB6iUiFj4jZHEi2WPJCE7qKzIZzmjRcpG64fOklyuLOsvjhr7 26 | qyg7ectXOZjIoVOYR1zuceFvVmcQMrzVEqV4eeU3SeaG0ZukK4LGdKjl/hHAu5jH 27 | ib/VkCV5TNlvpvdD1TWTntN0+feTjnNX9Bb3Kz0QSHX5StSIgs5kPFunGaWPpVkr 28 | WQjUA3wXesqLZgBZpQxBgahf9ZmZcv/qjVFnvwHVEhY0RFwRxNChy7T+dsPMPGzC 29 | 7YAZu+mWpsieXR7HqTzVdzRsVUHzpAuNBcXy0EOGy7hBm3F7AoIBAQDTKN9x9WlD 30 | YXTmCEfOQMXf+540B3qL1X8uKZauVvz9RB5m6WW2kJCMxAs5dg51qfHh3dSwbFgw 31 | iy2awgRFZcrn+sNrTMg1pbVzcEFwg7nLEuCkAAqIfqOrUxZD1PPoZdHm58iPBj8x 32 | LjbiMxnBiFmNWIJMHkanIN7rbwuICI9e7JtFPtJVGrT7C1UU6Pla+i9Qv8Z+MBYw 33 | zB5pFbij+2oqnEKTNHcaR1g5o5Bt4TaJeV8QkzkEmcN+hc3WP1xeU26IuV93i4Y9 34 | OyrjJYXmQ5gyCfuNWaDk9TJNQcLDH71HOF0C+Cy2YmqoRvl+dLsGJl+NlYXk/PY3 35 | gBBGwaQ84Z7fAoIBABSLhMgFQTVj2VRe2AQq/T/wjCieoN/FITmDdBGirPV3R9QF 36 | MZAlAerqn1Dy33qD381OM6OYLnVg6LGjNCbLRBocoV2Fa1nr+DZnihD7jqLT5U2R 37 | +1h2i5Dhi4xs4rwBRZA+K4wu6DKNID+bt9OgO1Wrx0mBLwrKMjqXHyM16ju1Kqhg 38 | bO0/Y7HzhBs9/sHKJudpgixIWTYVl67eSoz0UwfhtjhQoYOS+ajffVsjS+3SjjI9 39 | 0Dagxth4VdNL9Hoxcy6I1izzdrok0aOQwgmSI40RqBOIV5sH1Rp0ASP6K4R8BZQs 40 | j/UF1e7yXfwG17l08eCXwzlApzJsmQqGaPMbfZECggEBAJe9XGyw9VbFVtLjCm6t 41 | 30QotbQf17Fa14zdt/lKa3y4kbxUZpI96pItYv+E1bk6SaaM2YV6JhmkOj5mw9j2 42 | 4Eu5yOp3f7wFe5IcDfqDvmSvCRzxJqCVmJnKGErgYfIUETWERHx6+bgmxKviGtUX 43 | XXsUKnX2n8ED/w1ie//iXtzQ3HdzQISFr55js11WWbJF7PBzD3moppmkZQoQ4OF+ 44 | DvnV1oWgAyKwODcbUfOUDrPVsznfAe9La8+k6ZjXaVIjVGAODguDCRFBTn1yfnlN 45 | A7aZs9oMmXFOvjoEUqgTS9o9J6G1o7Pgn1KTxkBYM/mkY7ADzfcSzQBvF8Mw7gwN 46 | +jMCggEAURxcBRTDv51H16gZWo2aEMqyG0Q2kuTry6asgLDx6lxUQP+SWMY3kxN9 47 | tR1m15ibitYttVVrLfcVFwHqoiUiOTlOOiBTcjDoLU5/4NZrokcO1vYMo3ru5Cbs 48 | 8hg4zR7ngjut2KcnXMMThySF04pticwYkyREWr/JPo9LGipXyLICEc+euPCx6Lsp 49 | 7Cp6WD2XH8bLKu90rsrXyxh+wLUzCrNdc+DLmQZtTpjuak5UHyGlJ8lYNYtMxADK 50 | ThH1Elzni4MInwmHKsHVBSjwPvxvssgokg5LqDDb8E2HjrBjyIki/NrmYLZUNNdO 51 | aCW8UHfmRI3mdq/mMyEpDGmwx/nP7Q== 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /certs/cluster2/cert-chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | K5M2DJHknRU1CN3LqA== 32 | -----END CERTIFICATE----- 33 | -----BEGIN CERTIFICATE----- 34 | MIIFFDCCAvygAwIBAgIUY/8vm3/ORktKIUPKEc3RrWDd+2IwDQYJKoZIhvcNAQEL 35 | BQAwIjEOMAwGA1UECgwFSXN0aW8xEDAOBgNVBAMMB1Jvb3QgQ0EwHhcNMjIwODAz 36 | MDMxODM1WhcNMzIwNzMxMDMxODM1WjAiMQ4wDAYDVQQKDAVJc3RpbzEQMA4GA1UE 37 | AwwHUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOFy2Yfu 38 | Lfmh7rf4Gsx6pJB9UeNR4KtRGpUqJssPuQdVPDSgxeXZMVUuEVDl6YsoanbqLVf2 39 | uUAu+FAlPZTX5W7RXuwc/tl/0g5mP94StTJgLkcsfmq4/ajxYY6oiAcR+rKgK640 40 | C6ci8pFiAWRRnGjplCA/K4ijJ1anSxIdUJRRCMMjPdystnLp94d9Eie9KW9HfgWQ 41 | 2SJyAhvy/hAaEL0DGue6JcYikI7Pf5Hp0V364uULRWS6LZIgaUyykKOD83UgKH6R 42 | yg5hxEYGn2S/omh+xGefQltDd8zPuTOLnGob3NY/Zwq4XG4iEmMpXOgkGPawig+d 43 | QgXepTELADJ06qDxfA6hdC//uOQWWhawX6SKMMC0B0Vog31djd+3s5hXP6S3o8Vk 44 | kKg+RsvOlQNU1pCxLtfOEKv9kadFzE0r02TPJG/1LXWH27oVw0LE8rEmnsL3tC+x 45 | 2yGz8Sh4v2Hje7I9JLXwmVyTOPBVLKI4ounhbDUJxrnvjI79N6Ma6ol790+TgRDo 46 | W15Sj7miEnuPQMs5SYFTDsQWQj9fKax3EaMIRqQq0DZf4zyKVBtD9w+WJojemQf3 47 | 85Rc+EMju83LJgAVDdtgvxc5XD/+JJojads1SP6rNvZRMHFY1fJ7YtlEBzISw01u 48 | GigcQqa1dOql9rznUxqheJOfpWQv1lXzZh0pAgMBAAGjQjBAMB0GA1UdDgQWBBQ1 49 | ABjwYTDhpMLD2gUnDbdfcBFr5jAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE 50 | AwIC5DANBgkqhkiG9w0BAQsFAAOCAgEAHLnpXhtkE4H6W1i81cLTi+CiqFPC5yy0 51 | DvCAeSVZIyHD5Fyj+IkDra9CoLU1YkD6tOgWvEGfisIN+E9bI7E1h6Cpn54VF66W 52 | RYIX+3lPDp2sFc13fb8LkKqo9qTrnhw/Xu9ENN+q/bJT5ZYOALbZrtXCMNb05ps4 53 | 4jyvjGzvn2BeNGIXJSXBxGOn0AT73syKTUerJcXQXQYslDIVaTVSpHrHv3A/LsXK 54 | kg5pL2y7/fgOhixJ6cV1UomlrpVZNEaeO36hpa7l8D5vVK+kJ8scsGhe+s546EWK 55 | D7fdTlhAv2UkWleief4rZ9340xXhNrZy1QagC8+dw7H+oZI1n2Kqv4xyEpVEaRTR 56 | aMx/J1dk612uNYC8v+Iqog0bZHkTVzfoW+DCDkgPwxy7XcL8a7IcovFF/8jqhXzG 57 | FGzy5NDAEwpaffCL6+G0abxPabi/GYlKm4knbAxMuQyk+4FlRPWc9b5EquYrgatM 58 | iQI0zdhbzw1wTk175Mf4mAxeMFGg5vfM1XmiaGfM5/6+zNsuibEpuwTilPUhlLmh 59 | z+gGGkQYTjH36AaTlKn3SegtJFaaRK4Gt/gEqvLQIhsUTv3U2NprFqrdP4DnktBy 60 | 75mUh1n1Q0kX8BIHGIA3h7WHau0F0YO4gE48CsCIWk+pIy6VWEkTVrOdaO8TL1uj 61 | 7OLbGFrhAbQ= 62 | -----END CERTIFICATE----- 63 | -------------------------------------------------------------------------------- /certs/cluster2/root-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFFDCCAvygAwIBAgIUY/8vm3/ORktKIUPKEc3RrWDd+2IwDQYJKoZIhvcNAQEL 3 | BQAwIjEOMAwGA1UECgwFSXN0aW8xEDAOBgNVBAMMB1Jvb3QgQ0EwHhcNMjIwODAz 4 | MDMxODM1WhcNMzIwNzMxMDMxODM1WjAiMQ4wDAYDVQQKDAVJc3RpbzEQMA4GA1UE 5 | AwwHUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOFy2Yfu 6 | Lfmh7rf4Gsx6pJB9UeNR4KtRGpUqJssPuQdVPDSgxeXZMVUuEVDl6YsoanbqLVf2 7 | uUAu+FAlPZTX5W7RXuwc/tl/0g5mP94StTJgLkcsfmq4/ajxYY6oiAcR+rKgK640 8 | C6ci8pFiAWRRnGjplCA/K4ijJ1anSxIdUJRRCMMjPdystnLp94d9Eie9KW9HfgWQ 9 | 2SJyAhvy/hAaEL0DGue6JcYikI7Pf5Hp0V364uULRWS6LZIgaUyykKOD83UgKH6R 10 | yg5hxEYGn2S/omh+xGefQltDd8zPuTOLnGob3NY/Zwq4XG4iEmMpXOgkGPawig+d 11 | QgXepTELADJ06qDxfA6hdC//uOQWWhawX6SKMMC0B0Vog31djd+3s5hXP6S3o8Vk 12 | kKg+RsvOlQNU1pCxLtfOEKv9kadFzE0r02TPJG/1LXWH27oVw0LE8rEmnsL3tC+x 13 | 2yGz8Sh4v2Hje7I9JLXwmVyTOPBVLKI4ounhbDUJxrnvjI79N6Ma6ol790+TgRDo 14 | W15Sj7miEnuPQMs5SYFTDsQWQj9fKax3EaMIRqQq0DZf4zyKVBtD9w+WJojemQf3 15 | 85Rc+EMju83LJgAVDdtgvxc5XD/+JJojads1SP6rNvZRMHFY1fJ7YtlEBzISw01u 16 | GigcQqa1dOql9rznUxqheJOfpWQv1lXzZh0pAgMBAAGjQjBAMB0GA1UdDgQWBBQ1 17 | ABjwYTDhpMLD2gUnDbdfcBFr5jAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE 18 | AwIC5DANBgkqhkiG9w0BAQsFAAOCAgEAHLnpXhtkE4H6W1i81cLTi+CiqFPC5yy0 19 | DvCAeSVZIyHD5Fyj+IkDra9CoLU1YkD6tOgWvEGfisIN+E9bI7E1h6Cpn54VF66W 20 | RYIX+3lPDp2sFc13fb8LkKqo9qTrnhw/Xu9ENN+q/bJT5ZYOALbZrtXCMNb05ps4 21 | 4jyvjGzvn2BeNGIXJSXBxGOn0AT73syKTUerJcXQXQYslDIVaTVSpHrHv3A/LsXK 22 | kg5pL2y7/fgOhixJ6cV1UomlrpVZNEaeO36hpa7l8D5vVK+kJ8scsGhe+s546EWK 23 | D7fdTlhAv2UkWleief4rZ9340xXhNrZy1QagC8+dw7H+oZI1n2Kqv4xyEpVEaRTR 24 | aMx/J1dk612uNYC8v+Iqog0bZHkTVzfoW+DCDkgPwxy7XcL8a7IcovFF/8jqhXzG 25 | FGzy5NDAEwpaffCL6+G0abxPabi/GYlKm4knbAxMuQyk+4FlRPWc9b5EquYrgatM 26 | iQI0zdhbzw1wTk175Mf4mAxeMFGg5vfM1XmiaGfM5/6+zNsuibEpuwTilPUhlLmh 27 | z+gGGkQYTjH36AaTlKn3SegtJFaaRK4Gt/gEqvLQIhsUTv3U2NprFqrdP4DnktBy 28 | 75mUh1n1Q0kX8BIHGIA3h7WHau0F0YO4gE48CsCIWk+pIy6VWEkTVrOdaO8TL1uj 29 | 7OLbGFrhAbQ= 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /certs/cluster3/ca-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | 52wMrbeNKlqc3J/9Rw== 32 | -----END CERTIFICATE----- 33 | -------------------------------------------------------------------------------- /certs/cluster3/ca-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | n03UlTFgGsvh9jLPn+6kjduBatqtEg== 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /certs/cluster3/cert-chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | 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 31 | 52wMrbeNKlqc3J/9Rw== 32 | -----END CERTIFICATE----- 33 | -----BEGIN CERTIFICATE----- 34 | MIIFFDCCAvygAwIBAgIUY/8vm3/ORktKIUPKEc3RrWDd+2IwDQYJKoZIhvcNAQEL 35 | BQAwIjEOMAwGA1UECgwFSXN0aW8xEDAOBgNVBAMMB1Jvb3QgQ0EwHhcNMjIwODAz 36 | MDMxODM1WhcNMzIwNzMxMDMxODM1WjAiMQ4wDAYDVQQKDAVJc3RpbzEQMA4GA1UE 37 | AwwHUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOFy2Yfu 38 | Lfmh7rf4Gsx6pJB9UeNR4KtRGpUqJssPuQdVPDSgxeXZMVUuEVDl6YsoanbqLVf2 39 | uUAu+FAlPZTX5W7RXuwc/tl/0g5mP94StTJgLkcsfmq4/ajxYY6oiAcR+rKgK640 40 | C6ci8pFiAWRRnGjplCA/K4ijJ1anSxIdUJRRCMMjPdystnLp94d9Eie9KW9HfgWQ 41 | 2SJyAhvy/hAaEL0DGue6JcYikI7Pf5Hp0V364uULRWS6LZIgaUyykKOD83UgKH6R 42 | yg5hxEYGn2S/omh+xGefQltDd8zPuTOLnGob3NY/Zwq4XG4iEmMpXOgkGPawig+d 43 | QgXepTELADJ06qDxfA6hdC//uOQWWhawX6SKMMC0B0Vog31djd+3s5hXP6S3o8Vk 44 | kKg+RsvOlQNU1pCxLtfOEKv9kadFzE0r02TPJG/1LXWH27oVw0LE8rEmnsL3tC+x 45 | 2yGz8Sh4v2Hje7I9JLXwmVyTOPBVLKI4ounhbDUJxrnvjI79N6Ma6ol790+TgRDo 46 | W15Sj7miEnuPQMs5SYFTDsQWQj9fKax3EaMIRqQq0DZf4zyKVBtD9w+WJojemQf3 47 | 85Rc+EMju83LJgAVDdtgvxc5XD/+JJojads1SP6rNvZRMHFY1fJ7YtlEBzISw01u 48 | GigcQqa1dOql9rznUxqheJOfpWQv1lXzZh0pAgMBAAGjQjBAMB0GA1UdDgQWBBQ1 49 | ABjwYTDhpMLD2gUnDbdfcBFr5jAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE 50 | AwIC5DANBgkqhkiG9w0BAQsFAAOCAgEAHLnpXhtkE4H6W1i81cLTi+CiqFPC5yy0 51 | DvCAeSVZIyHD5Fyj+IkDra9CoLU1YkD6tOgWvEGfisIN+E9bI7E1h6Cpn54VF66W 52 | RYIX+3lPDp2sFc13fb8LkKqo9qTrnhw/Xu9ENN+q/bJT5ZYOALbZrtXCMNb05ps4 53 | 4jyvjGzvn2BeNGIXJSXBxGOn0AT73syKTUerJcXQXQYslDIVaTVSpHrHv3A/LsXK 54 | kg5pL2y7/fgOhixJ6cV1UomlrpVZNEaeO36hpa7l8D5vVK+kJ8scsGhe+s546EWK 55 | D7fdTlhAv2UkWleief4rZ9340xXhNrZy1QagC8+dw7H+oZI1n2Kqv4xyEpVEaRTR 56 | aMx/J1dk612uNYC8v+Iqog0bZHkTVzfoW+DCDkgPwxy7XcL8a7IcovFF/8jqhXzG 57 | FGzy5NDAEwpaffCL6+G0abxPabi/GYlKm4knbAxMuQyk+4FlRPWc9b5EquYrgatM 58 | iQI0zdhbzw1wTk175Mf4mAxeMFGg5vfM1XmiaGfM5/6+zNsuibEpuwTilPUhlLmh 59 | z+gGGkQYTjH36AaTlKn3SegtJFaaRK4Gt/gEqvLQIhsUTv3U2NprFqrdP4DnktBy 60 | 75mUh1n1Q0kX8BIHGIA3h7WHau0F0YO4gE48CsCIWk+pIy6VWEkTVrOdaO8TL1uj 61 | 7OLbGFrhAbQ= 62 | -----END CERTIFICATE----- 63 | -------------------------------------------------------------------------------- /certs/cluster3/root-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFFDCCAvygAwIBAgIUY/8vm3/ORktKIUPKEc3RrWDd+2IwDQYJKoZIhvcNAQEL 3 | BQAwIjEOMAwGA1UECgwFSXN0aW8xEDAOBgNVBAMMB1Jvb3QgQ0EwHhcNMjIwODAz 4 | MDMxODM1WhcNMzIwNzMxMDMxODM1WjAiMQ4wDAYDVQQKDAVJc3RpbzEQMA4GA1UE 5 | AwwHUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOFy2Yfu 6 | Lfmh7rf4Gsx6pJB9UeNR4KtRGpUqJssPuQdVPDSgxeXZMVUuEVDl6YsoanbqLVf2 7 | uUAu+FAlPZTX5W7RXuwc/tl/0g5mP94StTJgLkcsfmq4/ajxYY6oiAcR+rKgK640 8 | C6ci8pFiAWRRnGjplCA/K4ijJ1anSxIdUJRRCMMjPdystnLp94d9Eie9KW9HfgWQ 9 | 2SJyAhvy/hAaEL0DGue6JcYikI7Pf5Hp0V364uULRWS6LZIgaUyykKOD83UgKH6R 10 | yg5hxEYGn2S/omh+xGefQltDd8zPuTOLnGob3NY/Zwq4XG4iEmMpXOgkGPawig+d 11 | QgXepTELADJ06qDxfA6hdC//uOQWWhawX6SKMMC0B0Vog31djd+3s5hXP6S3o8Vk 12 | kKg+RsvOlQNU1pCxLtfOEKv9kadFzE0r02TPJG/1LXWH27oVw0LE8rEmnsL3tC+x 13 | 2yGz8Sh4v2Hje7I9JLXwmVyTOPBVLKI4ounhbDUJxrnvjI79N6Ma6ol790+TgRDo 14 | W15Sj7miEnuPQMs5SYFTDsQWQj9fKax3EaMIRqQq0DZf4zyKVBtD9w+WJojemQf3 15 | 85Rc+EMju83LJgAVDdtgvxc5XD/+JJojads1SP6rNvZRMHFY1fJ7YtlEBzISw01u 16 | GigcQqa1dOql9rznUxqheJOfpWQv1lXzZh0pAgMBAAGjQjBAMB0GA1UdDgQWBBQ1 17 | ABjwYTDhpMLD2gUnDbdfcBFr5jAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE 18 | AwIC5DANBgkqhkiG9w0BAQsFAAOCAgEAHLnpXhtkE4H6W1i81cLTi+CiqFPC5yy0 19 | DvCAeSVZIyHD5Fyj+IkDra9CoLU1YkD6tOgWvEGfisIN+E9bI7E1h6Cpn54VF66W 20 | RYIX+3lPDp2sFc13fb8LkKqo9qTrnhw/Xu9ENN+q/bJT5ZYOALbZrtXCMNb05ps4 21 | 4jyvjGzvn2BeNGIXJSXBxGOn0AT73syKTUerJcXQXQYslDIVaTVSpHrHv3A/LsXK 22 | kg5pL2y7/fgOhixJ6cV1UomlrpVZNEaeO36hpa7l8D5vVK+kJ8scsGhe+s546EWK 23 | D7fdTlhAv2UkWleief4rZ9340xXhNrZy1QagC8+dw7H+oZI1n2Kqv4xyEpVEaRTR 24 | aMx/J1dk612uNYC8v+Iqog0bZHkTVzfoW+DCDkgPwxy7XcL8a7IcovFF/8jqhXzG 25 | FGzy5NDAEwpaffCL6+G0abxPabi/GYlKm4knbAxMuQyk+4FlRPWc9b5EquYrgatM 26 | iQI0zdhbzw1wTk175Mf4mAxeMFGg5vfM1XmiaGfM5/6+zNsuibEpuwTilPUhlLmh 27 | z+gGGkQYTjH36AaTlKn3SegtJFaaRK4Gt/gEqvLQIhsUTv3U2NprFqrdP4DnktBy 28 | 75mUh1n1Q0kX8BIHGIA3h7WHau0F0YO4gE48CsCIWk+pIy6VWEkTVrOdaO8TL1uj 29 | 7OLbGFrhAbQ= 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /certs/root-ca.conf: -------------------------------------------------------------------------------- 1 | [ req ] 2 | encrypt_key = no 3 | prompt = no 4 | utf8 = yes 5 | default_md = sha256 6 | default_bits = 4096 7 | req_extensions = req_ext 8 | x509_extensions = req_ext 9 | distinguished_name = req_dn 10 | [ req_ext ] 11 | subjectKeyIdentifier = hash 12 | basicConstraints = critical, CA:true 13 | keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, keyCertSign 14 | [ req_dn ] 15 | O = Istio 16 | CN = Root CA 17 | -------------------------------------------------------------------------------- /certs/root-cert.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIEuDCCAqACAQAwIjEOMAwGA1UECgwFSXN0aW8xEDAOBgNVBAMMB1Jvb3QgQ0Ew 3 | ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDhctmH7i35oe63+BrMeqSQ 4 | fVHjUeCrURqVKibLD7kHVTw0oMXl2TFVLhFQ5emLKGp26i1X9rlALvhQJT2U1+Vu 5 | 0V7sHP7Zf9IOZj/eErUyYC5HLH5quP2o8WGOqIgHEfqyoCuuNAunIvKRYgFkUZxo 6 | 6ZQgPyuIoydWp0sSHVCUUQjDIz3crLZy6feHfRInvSlvR34FkNkicgIb8v4QGhC9 7 | AxrnuiXGIpCOz3+R6dFd+uLlC0Vkui2SIGlMspCjg/N1ICh+kcoOYcRGBp9kv6Jo 8 | fsRnn0JbQ3fMz7kzi5xqG9zWP2cKuFxuIhJjKVzoJBj2sIoPnUIF3qUxCwAydOqg 9 | 8XwOoXQv/7jkFloWsF+kijDAtAdFaIN9XY3ft7OYVz+kt6PFZJCoPkbLzpUDVNaQ 10 | sS7XzhCr/ZGnRcxNK9NkzyRv9S11h9u6FcNCxPKxJp7C97Qvsdshs/EoeL9h43uy 11 | PSS18JlckzjwVSyiOKLp4Ww1Cca574yO/TejGuqJe/dPk4EQ6FteUo+5ohJ7j0DL 12 | OUmBUw7EFkI/XymsdxGjCEakKtA2X+M8ilQbQ/cPliaI3pkH9/OUXPhDI7vNyyYA 13 | FQ3bYL8XOVw//iSaI2nbNUj+qzb2UTBxWNXye2LZRAcyEsNNbhooHEKmtXTqpfa8 14 | 51MaoXiTn6VkL9ZV82YdKQIDAQABoFEwTwYJKoZIhvcNAQkOMUIwQDAdBgNVHQ4E 15 | FgQUNQAY8GEw4aTCw9oFJw23X3ARa+YwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B 16 | Af8EBAMCAuQwDQYJKoZIhvcNAQELBQADggIBAAQf0XBmcmZA4Wnpc5YWIy77kx0J 17 | KTX5pXIz33WGYhbYJoue9pTq2pLdwRSgjy5TXkqq/pDa2YtKrOhWPVygCKGtL8dZ 18 | agcwgP3Ea15/RNETYsDtacfh09Oh5TLxAzTCVjm2SC9nt35PR1VGOadMzciuhWMC 19 | umvmSihpoh9hS9PwGX9+u/Puup1bW5vaBCr36wDrimEkaD/nvfhCjxt0Bv/yi2/y 20 | hAK/V+XvvdfN69XPhuJWDNroEE0wAGVrUB+0PZICoqRegnZVDI8VciSgqp4tpXlV 21 | q3xagdLz13ggMAg9XROG/avr86vjGAhTihdbi13mVtqitx7ooTJ8CwXoCaqSz8+t 22 | jZQyMGkK+N80q3rI/KKlvjG62uzccfGQa8Cf0Pgp8h6kd2e8KBEqQ5semzhp46ow 23 | +070I4t6t2Fv79D5m1wVjxsQROTFzAQ83hGCMPbr1wwwPGMjEzjOf8k4nXSxDWl7 24 | iJtVwnEu+qe7UQBQe7UNDS+NrxykdZWqogZUPySgriw6/U2a4Av5GTn5NjgO8RxL 25 | 4cRXoReDzPQThUEU7AiQ2kPSmkAGgXub7/fOt/TKAygM7fJoqvv35hTUDhEKnold 26 | RNWkbbSEajbOE/6DoRaya+mv5QfN5cyecbKwpmr2Slc32AQauakHn0FvdXg7VGq8 27 | YJDBPaxawSERr8mk 28 | -----END CERTIFICATE REQUEST----- 29 | -------------------------------------------------------------------------------- /certs/root-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFFDCCAvygAwIBAgIUY/8vm3/ORktKIUPKEc3RrWDd+2IwDQYJKoZIhvcNAQEL 3 | BQAwIjEOMAwGA1UECgwFSXN0aW8xEDAOBgNVBAMMB1Jvb3QgQ0EwHhcNMjIwODAz 4 | MDMxODM1WhcNMzIwNzMxMDMxODM1WjAiMQ4wDAYDVQQKDAVJc3RpbzEQMA4GA1UE 5 | AwwHUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOFy2Yfu 6 | Lfmh7rf4Gsx6pJB9UeNR4KtRGpUqJssPuQdVPDSgxeXZMVUuEVDl6YsoanbqLVf2 7 | uUAu+FAlPZTX5W7RXuwc/tl/0g5mP94StTJgLkcsfmq4/ajxYY6oiAcR+rKgK640 8 | C6ci8pFiAWRRnGjplCA/K4ijJ1anSxIdUJRRCMMjPdystnLp94d9Eie9KW9HfgWQ 9 | 2SJyAhvy/hAaEL0DGue6JcYikI7Pf5Hp0V364uULRWS6LZIgaUyykKOD83UgKH6R 10 | yg5hxEYGn2S/omh+xGefQltDd8zPuTOLnGob3NY/Zwq4XG4iEmMpXOgkGPawig+d 11 | QgXepTELADJ06qDxfA6hdC//uOQWWhawX6SKMMC0B0Vog31djd+3s5hXP6S3o8Vk 12 | kKg+RsvOlQNU1pCxLtfOEKv9kadFzE0r02TPJG/1LXWH27oVw0LE8rEmnsL3tC+x 13 | 2yGz8Sh4v2Hje7I9JLXwmVyTOPBVLKI4ounhbDUJxrnvjI79N6Ma6ol790+TgRDo 14 | W15Sj7miEnuPQMs5SYFTDsQWQj9fKax3EaMIRqQq0DZf4zyKVBtD9w+WJojemQf3 15 | 85Rc+EMju83LJgAVDdtgvxc5XD/+JJojads1SP6rNvZRMHFY1fJ7YtlEBzISw01u 16 | GigcQqa1dOql9rznUxqheJOfpWQv1lXzZh0pAgMBAAGjQjBAMB0GA1UdDgQWBBQ1 17 | ABjwYTDhpMLD2gUnDbdfcBFr5jAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE 18 | AwIC5DANBgkqhkiG9w0BAQsFAAOCAgEAHLnpXhtkE4H6W1i81cLTi+CiqFPC5yy0 19 | DvCAeSVZIyHD5Fyj+IkDra9CoLU1YkD6tOgWvEGfisIN+E9bI7E1h6Cpn54VF66W 20 | RYIX+3lPDp2sFc13fb8LkKqo9qTrnhw/Xu9ENN+q/bJT5ZYOALbZrtXCMNb05ps4 21 | 4jyvjGzvn2BeNGIXJSXBxGOn0AT73syKTUerJcXQXQYslDIVaTVSpHrHv3A/LsXK 22 | kg5pL2y7/fgOhixJ6cV1UomlrpVZNEaeO36hpa7l8D5vVK+kJ8scsGhe+s546EWK 23 | D7fdTlhAv2UkWleief4rZ9340xXhNrZy1QagC8+dw7H+oZI1n2Kqv4xyEpVEaRTR 24 | aMx/J1dk612uNYC8v+Iqog0bZHkTVzfoW+DCDkgPwxy7XcL8a7IcovFF/8jqhXzG 25 | FGzy5NDAEwpaffCL6+G0abxPabi/GYlKm4knbAxMuQyk+4FlRPWc9b5EquYrgatM 26 | iQI0zdhbzw1wTk175Mf4mAxeMFGg5vfM1XmiaGfM5/6+zNsuibEpuwTilPUhlLmh 27 | z+gGGkQYTjH36AaTlKn3SegtJFaaRK4Gt/gEqvLQIhsUTv3U2NprFqrdP4DnktBy 28 | 75mUh1n1Q0kX8BIHGIA3h7WHau0F0YO4gE48CsCIWk+pIy6VWEkTVrOdaO8TL1uj 29 | 7OLbGFrhAbQ= 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /certs/root-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | 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 51 | VTAojBBrFeRgzFyKWrM6S77jVZ9zMg== 52 | -----END PRIVATE KEY----- 53 | -------------------------------------------------------------------------------- /demo/dashboard.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | LB_AP=$(kubectl --kubeconfig=../kubeconfig-ap get service -n istio-system -l app=istio-ingressgateway -o jsonpath="{.items[0].status.loadBalancer.ingress[0].ip}") 4 | LB_US=$(kubectl --kubeconfig=../kubeconfig-us get service -n istio-system -l app=istio-ingressgateway -o jsonpath="{.items[0].status.loadBalancer.ingress[0].ip}") 5 | LB_EU=$(kubectl --kubeconfig=../kubeconfig-eu get service -n istio-system -l app=istio-ingressgateway -o jsonpath="{.items[0].status.loadBalancer.ingress[0].ip}") 6 | echo "ready on localhost:8082" 7 | node ../world-map/index.js "{\"ap\":\"http://$LB_AP/env\",\"us\":\"http://$LB_US/env\",\"eu\":\"http://$LB_EU/env\"}" -------------------------------------------------------------------------------- /demo/hello.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: hello 5 | spec: 6 | replicas: 3 7 | selector: 8 | matchLabels: 9 | app: hello 10 | template: 11 | metadata: 12 | labels: 13 | app: hello 14 | spec: 15 | containers: 16 | - image: stefanprodan/podinfo 17 | name: hello 18 | env: 19 | - name: REGION 20 | valueFrom: 21 | configMapKeyRef: 22 | name: region 23 | key: name 24 | -------------------------------------------------------------------------------- /demo/hello2.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: hello 5 | spec: 6 | type: NodePort 7 | ports: 8 | - port: 5000 9 | targetPort: 9898 10 | nodePort: 32000 11 | selector: 12 | app: hello 13 | --- 14 | apiVersion: networking.k8s.io/v1 15 | kind: Ingress 16 | metadata: 17 | annotations: 18 | kubernetes.io/ingress.class: istio 19 | name: hello 20 | spec: 21 | rules: 22 | - http: 23 | paths: 24 | - path: / 25 | pathType: Prefix 26 | backend: 27 | service: 28 | name: hello 29 | port: 30 | number: 5000 31 | --- -------------------------------------------------------------------------------- /demo/simple-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.karmada.io/v1alpha1 2 | kind: PropagationPolicy 3 | metadata: 4 | name: simple-propagation 5 | spec: 6 | resourceSelectors: 7 | - apiVersion: apps/v1 8 | kind: Deployment 9 | name: hello 10 | placement: 11 | clusterAffinity: 12 | clusterNames: 13 | - eu 14 | - ap 15 | - us 16 | replicaScheduling: 17 | replicaSchedulingType: Duplicated -------------------------------------------------------------------------------- /demo/weighted-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.karmada.io/v1alpha1 2 | kind: PropagationPolicy 3 | metadata: 4 | name: weighted-propagation 5 | spec: 6 | resourceSelectors: 7 | - apiVersion: apps/v1 8 | kind: Deployment 9 | name: hello 10 | placement: 11 | clusterAffinity: 12 | clusterNames: 13 | - eu 14 | - ap 15 | - us 16 | replicaScheduling: 17 | replicaDivisionPreference: Weighted 18 | replicaSchedulingType: Divided 19 | weightPreference: 20 | staticWeightList: 21 | - targetCluster: 22 | clusterNames: 23 | - us 24 | weight: 4 25 | - targetCluster: 26 | clusterNames: 27 | - ap 28 | weight: 1 29 | - targetCluster: 30 | clusterNames: 31 | - eu 32 | weight: 1 33 | -------------------------------------------------------------------------------- /demo/weighted-policy2.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy.karmada.io/v1alpha1 2 | kind: PropagationPolicy 3 | metadata: 4 | name: weighted-propagation 5 | spec: 6 | resourceSelectors: 7 | - apiVersion: apps/v1 8 | kind: Deployment 9 | name: hello 10 | - apiVersion: networking.k8s.io/v1 11 | kind: Ingress 12 | name: hello 13 | - apiVersion: v1 14 | kind: Service 15 | name: hello 16 | placement: 17 | clusterAffinity: 18 | clusterNames: 19 | - eu 20 | - ap 21 | - us 22 | replicaScheduling: 23 | replicaDivisionPreference: Weighted 24 | replicaSchedulingType: Divided 25 | weightPreference: 26 | staticWeightList: 27 | - targetCluster: 28 | clusterNames: 29 | - us 30 | weight: 1 31 | - targetCluster: 32 | clusterNames: 33 | - ap 34 | weight: 1 35 | - targetCluster: 36 | clusterNames: 37 | - eu 38 | weight: 1 -------------------------------------------------------------------------------- /modules/cluster/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | linode = { 4 | source = "linode/linode" 5 | version = "1.28.0" 6 | } 7 | } 8 | } 9 | 10 | variable "name" { 11 | type = string 12 | } 13 | 14 | variable "region" { 15 | type = string 16 | } 17 | 18 | resource "linode_lke_cluster" "this" { 19 | label = var.name 20 | k8s_version = "1.25" 21 | region = var.region 22 | 23 | pool { 24 | type = "g6-standard-2" 25 | count = 1 26 | 27 | autoscaler { 28 | min = 1 29 | max = 10 30 | } 31 | } 32 | 33 | # Prevent the count field from overriding autoscaler-created nodes 34 | lifecycle { 35 | ignore_changes = [ 36 | pool.0.count 37 | ] 38 | } 39 | } 40 | 41 | output "kubeconfig" { 42 | value = base64decode(linode_lke_cluster.this.kubeconfig) 43 | sensitive = true 44 | } 45 | -------------------------------------------------------------------------------- /modules/dashboard/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | kubernetes = { 4 | source = "hashicorp/kubernetes" 5 | version = "2.12.1" 6 | } 7 | helm = { 8 | source = "hashicorp/helm" 9 | version = "2.6.0" 10 | } 11 | } 12 | } 13 | 14 | locals { 15 | istio_namespace = "istio-system" 16 | } 17 | 18 | provider "kubernetes" { 19 | config_path = var.kubeconfig_path 20 | } 21 | 22 | provider "helm" { 23 | kubernetes { 24 | config_path = var.kubeconfig_path 25 | } 26 | } 27 | 28 | variable "kubeconfig_path" { 29 | type = string 30 | } 31 | 32 | variable "cluster_name" { 33 | description = "The name for the cluster" 34 | type = string 35 | } 36 | 37 | resource "helm_release" "prometheus" { 38 | name = "prometheus" 39 | chart = "https://github.com/prometheus-community/helm-charts/releases/download/prometheus-15.11.0/prometheus-15.11.0.tgz" 40 | namespace = local.istio_namespace 41 | 42 | set { 43 | name = "server.global.scrape_interval" 44 | value = "10s" 45 | } 46 | 47 | set { 48 | name = "server.global.evaluation_interval" 49 | value = "10s" 50 | } 51 | } 52 | 53 | resource "helm_release" "kiali_server" { 54 | name = "kiali-server" 55 | chart = "https://kiali.org/helm-charts/kiali-server-1.54.0.tgz" 56 | namespace = local.istio_namespace 57 | depends_on = [ 58 | helm_release.prometheus 59 | ] 60 | 61 | set { 62 | name = "istio.root_namespace" 63 | value = local.istio_namespace 64 | } 65 | 66 | set { 67 | name = "auth.strategy" 68 | value = "anonymous" 69 | } 70 | 71 | set { 72 | name = "external_services.custom_dashboards.prometheus.url" 73 | value = "http://prometheus-server/" 74 | } 75 | 76 | set { 77 | name = "external_services.prometheus.url" 78 | value = "http://prometheus-server" 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /modules/discovery/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | kubernetes = { 4 | source = "hashicorp/kubernetes" 5 | version = "2.12.1" 6 | } 7 | } 8 | } 9 | 10 | provider "kubernetes" { 11 | config_path = var.kubeconfig_path 12 | } 13 | 14 | variable "istio_namespace" { 15 | type = string 16 | default = "istio-system" 17 | } 18 | 19 | variable "kubeconfig_path" { 20 | type = string 21 | } 22 | 23 | variable "cluster_name" { 24 | description = "The name for the cluster" 25 | type = string 26 | } 27 | 28 | variable "cluster_discovery" { 29 | type = map(object({ cluster_name = string, kubeconfig_path = string })) 30 | } 31 | 32 | resource "kubernetes_secret" "this" { 33 | for_each = var.cluster_discovery 34 | 35 | metadata { 36 | name = "istio-remote-secret-${each.value.cluster_name}" 37 | 38 | annotations = { 39 | "networking.istio.io/cluster" = each.value.cluster_name 40 | } 41 | 42 | labels = { 43 | "istio/multiCluster" = "true" 44 | } 45 | 46 | namespace = var.istio_namespace 47 | } 48 | 49 | data = { 50 | "${each.value.cluster_name}" = file(each.value.kubeconfig_path) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /modules/karmada-manager/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | helm = { 4 | source = "hashicorp/helm" 5 | version = "2.6.0" 6 | } 7 | } 8 | } 9 | 10 | variable "kubeconfig_path" { 11 | type = string 12 | } 13 | 14 | provider "helm" { 15 | kubernetes { 16 | config_path = var.kubeconfig_path 17 | } 18 | } 19 | 20 | locals { 21 | karmada_namespace = "karmada-system" 22 | cluster_domain = "cluster.local" 23 | hosts = [ 24 | "kubernetes.default.svc", 25 | "*.etcd.${local.karmada_namespace}.svc.${local.cluster_domain}", 26 | "*.${local.karmada_namespace}.svc.${local.cluster_domain}", 27 | "*.${local.karmada_namespace}.svc", 28 | "localhost", 29 | "127.0.0.1", 30 | data.local_file.node_ip.content, # <- add the IP address of the Node hosting the Karmada API server 31 | ] 32 | karmada_api_nodeport = 32443 33 | } 34 | 35 | resource "null_resource" "get_node_ip" { 36 | provisioner "local-exec" { 37 | command = "kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type==\"ExternalIP\")].address}' --kubeconfig=${var.kubeconfig_path} > node_ip.txt" 38 | } 39 | provisioner "local-exec" { 40 | command = "rm -f node_ip.txt" 41 | when = destroy 42 | } 43 | } 44 | 45 | data "local_file" "node_ip" { 46 | filename = "node_ip.txt" 47 | depends_on = [null_resource.get_node_ip] 48 | } 49 | 50 | resource "helm_release" "karmada" { 51 | name = "karmada" 52 | chart = "https://github.com/karmada-io/karmada/releases/download/v1.5.0/karmada-chart-v1.5.0.tgz" 53 | namespace = local.karmada_namespace 54 | create_namespace = true 55 | 56 | set { 57 | name = "apiServer.hostNetwork" 58 | value = "false" 59 | } 60 | 61 | set { 62 | name = "apiServer.serviceType" 63 | value = "NodePort" 64 | } 65 | 66 | set { 67 | name = "apiServer.nodePort" 68 | value = local.karmada_api_nodeport 69 | } 70 | 71 | dynamic "set" { 72 | for_each = local.hosts 73 | content { 74 | name = "certs.auto.hosts[${set.key}]" 75 | value = set.value 76 | } 77 | } 78 | } 79 | 80 | resource "null_resource" "karamada_kubeconfig" { 81 | provisioner "local-exec" { 82 | command = "kubectl get secret --kubeconfig=${var.kubeconfig_path} -n ${local.karmada_namespace} karmada-kubeconfig -o jsonpath={.data.kubeconfig} | base64 -d | sed -e 's/karmada-apiserver.${local.karmada_namespace}.svc.${local.cluster_domain}:5443/${data.local_file.node_ip.content}:${local.karmada_api_nodeport}/g' > karmada-config" 83 | } 84 | provisioner "local-exec" { 85 | command = "rm -f karmada-config" 86 | when = destroy 87 | } 88 | depends_on = [helm_release.karmada] 89 | } 90 | 91 | data "local_file" "karmada_config" { 92 | filename = "karmada-config" 93 | depends_on = [null_resource.karamada_kubeconfig] 94 | } 95 | 96 | output "node_ip" { 97 | value = data.local_file.node_ip.content 98 | } 99 | 100 | output "karmada_config" { 101 | value = data.local_file.karmada_config.content 102 | sensitive = true 103 | } 104 | -------------------------------------------------------------------------------- /modules/karmada-worker/expose.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: Gateway 3 | metadata: 4 | name: cross-network-gateway 5 | spec: 6 | selector: 7 | istio: eastwestgateway 8 | servers: 9 | - port: 10 | number: 15443 11 | name: tls 12 | protocol: TLS 13 | tls: 14 | mode: AUTO_PASSTHROUGH 15 | hosts: 16 | - "*.local" 17 | --- 18 | apiVersion: networking.istio.io/v1alpha3 19 | kind: Gateway 20 | metadata: 21 | name: ingress-gateway 22 | spec: 23 | selector: 24 | istio: ingressgateway 25 | servers: 26 | - port: 27 | number: 80 28 | name: http 29 | protocol: HTTP 30 | hosts: 31 | - "*" 32 | -------------------------------------------------------------------------------- /modules/karmada-worker/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | kubernetes = { 4 | source = "hashicorp/kubernetes" 5 | version = "2.12.1" 6 | } 7 | helm = { 8 | source = "hashicorp/helm" 9 | version = "2.6.0" 10 | } 11 | } 12 | } 13 | 14 | locals { 15 | istio_namespace = "istio-system" 16 | } 17 | 18 | provider "kubernetes" { 19 | config_path = var.kubeconfig_path 20 | } 21 | 22 | provider "helm" { 23 | kubernetes { 24 | config_path = var.kubeconfig_path 25 | } 26 | } 27 | 28 | variable "kubeconfig_path" { 29 | type = string 30 | } 31 | 32 | variable "cluster_name" { 33 | description = "The name for the cluster" 34 | type = string 35 | } 36 | 37 | variable "network_name" { 38 | description = "The network name" 39 | } 40 | 41 | variable "certs" { 42 | type = map(string) 43 | } 44 | 45 | variable "karmada_config" { 46 | type = string 47 | } 48 | 49 | resource "kubernetes_namespace" "istio" { 50 | metadata { 51 | name = local.istio_namespace 52 | 53 | labels = { 54 | "topology.istio.io/network" = var.network_name 55 | } 56 | } 57 | } 58 | 59 | resource "kubernetes_secret" "cacerts" { 60 | metadata { 61 | name = "cacerts" 62 | namespace = local.istio_namespace 63 | } 64 | 65 | data = var.certs 66 | } 67 | 68 | resource "helm_release" "istio_base" { 69 | depends_on = [kubernetes_secret.cacerts, kubernetes_namespace.istio] 70 | name = "istio-base" 71 | chart = "https://istio-release.storage.googleapis.com/charts/base-1.17.1.tgz" 72 | # chart = "istio/base" 73 | namespace = local.istio_namespace 74 | } 75 | 76 | resource "helm_release" "istiod" { 77 | depends_on = [kubernetes_secret.cacerts, kubernetes_namespace.istio] 78 | name = "istiod" 79 | chart = "https://istio-release.storage.googleapis.com/charts/istiod-1.17.1.tgz" 80 | # chart = "istio/istiod" 81 | namespace = local.istio_namespace 82 | 83 | set { 84 | name = "global.meshID" 85 | value = "mesh1" 86 | } 87 | 88 | set { 89 | name = "global.multiCluster.clusterName" 90 | value = var.cluster_name 91 | } 92 | 93 | set { 94 | name = "global.network" 95 | value = var.network_name 96 | } 97 | } 98 | 99 | # Wait for the mutating webhook to be available 100 | resource "time_sleep" "wait_for_webhook" { 101 | depends_on = [helm_release.istiod] 102 | 103 | create_duration = "30s" 104 | } 105 | 106 | resource "helm_release" "eastwest_gateway" { 107 | depends_on = [time_sleep.wait_for_webhook] 108 | name = "eastwest-gateway" 109 | chart = "https://istio-release.storage.googleapis.com/charts/gateway-1.17.1.tgz" 110 | # chart = "istio/gateway" 111 | namespace = local.istio_namespace 112 | 113 | set { 114 | name = "labels.istio" 115 | value = "eastwestgateway" 116 | } 117 | 118 | set { 119 | name = "labels.app" 120 | value = "istio-eastwestgateway" 121 | } 122 | 123 | set { 124 | name = "labels.topology\\.istio\\.io/network" 125 | value = var.network_name 126 | } 127 | 128 | set { 129 | name = "networkGateway" 130 | value = var.network_name 131 | } 132 | 133 | set { 134 | name = "service.ports[0].name" 135 | value = "status-port" 136 | } 137 | set { 138 | name = "service.ports[0].port" 139 | value = 15021 140 | } 141 | set { 142 | name = "service.ports[0].targetPort" 143 | value = 15021 144 | } 145 | 146 | set { 147 | name = "service.ports[1].name" 148 | value = "tls" 149 | } 150 | set { 151 | name = "service.ports[1].port" 152 | value = 15443 153 | } 154 | set { 155 | name = "service.ports[1].targetPort" 156 | value = 15443 157 | } 158 | 159 | set { 160 | name = "service.ports[2].name" 161 | value = "tls-istiod" 162 | } 163 | set { 164 | name = "service.ports[2].port" 165 | value = 15012 166 | } 167 | set { 168 | name = "service.ports[2].targetPort" 169 | value = 15012 170 | } 171 | 172 | set { 173 | name = "service.ports[3].name" 174 | value = "tls-webhook" 175 | } 176 | set { 177 | name = "service.ports[3].port" 178 | value = 15017 179 | } 180 | set { 181 | name = "service.ports[3].targetPort" 182 | value = 15017 183 | } 184 | } 185 | 186 | resource "helm_release" "ingress_gateway" { 187 | depends_on = [time_sleep.wait_for_webhook] 188 | name = "ingress-gateway" 189 | chart = "https://istio-release.storage.googleapis.com/charts/gateway-1.17.1.tgz" 190 | # chart = "istio/gateway" 191 | namespace = local.istio_namespace 192 | 193 | set { 194 | name = "labels.istio" 195 | value = "ingressgateway" 196 | } 197 | 198 | set { 199 | name = "labels.app" 200 | value = "istio-ingressgateway" 201 | } 202 | 203 | set { 204 | name = "labels.topology\\.istio\\.io/network" 205 | value = var.network_name 206 | } 207 | } 208 | 209 | resource "helm_release" "karmada" { 210 | name = "karmada" 211 | chart = "https://github.com/karmada-io/karmada/releases/download/v1.5.0/karmada-chart-v1.5.0.tgz" 212 | namespace = "karmada-system" 213 | create_namespace = true 214 | 215 | set { 216 | name = "installMode" 217 | value = "agent" 218 | } 219 | 220 | set { 221 | name = "agent.clusterName" 222 | value = var.cluster_name 223 | } 224 | 225 | set { 226 | name = "agent.kubeconfig.caCrt" 227 | value = base64decode(yamldecode(file(var.karmada_config)).clusters[0].cluster["certificate-authority-data"]) 228 | } 229 | 230 | set { 231 | name = "agent.kubeconfig.crt" 232 | value = base64decode(yamldecode(file(var.karmada_config)).users[0].user["client-certificate-data"]) 233 | } 234 | 235 | set { 236 | name = "agent.kubeconfig.key" 237 | value = base64decode(yamldecode(file(var.karmada_config)).users[0].user["client-key-data"]) 238 | } 239 | 240 | set { 241 | name = "agent.kubeconfig.server" 242 | value = yamldecode(file(var.karmada_config)).clusters[0].cluster.server 243 | } 244 | } 245 | 246 | resource "kubernetes_labels" "this" { 247 | api_version = "v1" 248 | kind = "Namespace" 249 | metadata { 250 | name = "default" 251 | } 252 | labels = { 253 | "istio-injection" = "enabled" 254 | } 255 | } 256 | 257 | # https://medium.com/@danieljimgarcia/dont-use-the-terraform-kubernetes-manifest-resource-6c7ff4fe629a 258 | resource "null_resource" "expose" { 259 | triggers = { 260 | invokes_me_everytime = uuid() 261 | kubeconfig_path = var.kubeconfig_path 262 | current_path = path.module 263 | istio_namespace = local.istio_namespace 264 | } 265 | 266 | provisioner "local-exec" { 267 | command = "kubectl apply --kubeconfig=${var.kubeconfig_path} -n ${local.istio_namespace} -f ${path.module}/expose.yaml" 268 | } 269 | 270 | # https://github.com/hashicorp/terraform/issues/23679#issuecomment-885063851 271 | provisioner "local-exec" { 272 | command = "kubectl delete --kubeconfig=${self.triggers.kubeconfig_path} -n ${self.triggers.istio_namespace} --ignore-not-found=true -f ${self.triggers.current_path}/expose.yaml" 273 | when = destroy 274 | } 275 | depends_on = [helm_release.eastwest_gateway, helm_release.ingress_gateway] 276 | } 277 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | cat <","us":"","ap":""}' 7 | ``` 8 | -------------------------------------------------------------------------------- /world-map/app.js: -------------------------------------------------------------------------------- 1 | const locationEu = document.querySelector("#location-eu"); 2 | const locationUs = document.querySelector("#location-us"); 3 | const locationAp = document.querySelector("#location-ap"); 4 | const Page = { 5 | eu: { 6 | links: { 7 | eu: document.querySelector("#eu-to-eu"), 8 | us: document.querySelector("#eu-to-us"), 9 | ap: document.querySelector("#eu-to-ap"), 10 | }, 11 | pin: document.querySelector("#pin-eu"), 12 | cluster: document.querySelector("#k8s-eu"), 13 | ingress: document.querySelector("#ingress-eu"), 14 | }, 15 | us: { 16 | links: { 17 | eu: document.querySelector("#us-to-eu"), 18 | us: document.querySelector("#us-to-us"), 19 | ap: document.querySelector("#us-to-ap"), 20 | }, 21 | pin: document.querySelector("#pin-us"), 22 | cluster: document.querySelector("#k8s-us"), 23 | ingress: document.querySelector("#ingress-us"), 24 | }, 25 | ap: { 26 | links: { 27 | eu: document.querySelector("#ap-to-eu"), 28 | us: document.querySelector("#ap-to-us"), 29 | ap: document.querySelector("#ap-to-ap"), 30 | }, 31 | pin: document.querySelector("#pin-ap"), 32 | cluster: document.querySelector("#k8s-ap"), 33 | ingress: document.querySelector("#ingress-ap"), 34 | }, 35 | }; 36 | 37 | resetLinks(); 38 | 39 | locationEu.addEventListener("change", (event) => { 40 | event.preventDefault(); 41 | store.dispatch(Action.setCurrentLocation("eu")); 42 | }); 43 | locationUs.addEventListener("change", (event) => { 44 | event.preventDefault(); 45 | store.dispatch(Action.setCurrentLocation("us")); 46 | }); 47 | locationAp.addEventListener("change", (event) => { 48 | event.preventDefault(); 49 | store.dispatch(Action.setCurrentLocation("ap")); 50 | }); 51 | 52 | const store = (window.store = createStore( 53 | function (state, action) { 54 | switch (action.type) { 55 | case "location/set": 56 | return { ...state, currentLocation: action.payload }; 57 | case "response/record": 58 | return { 59 | ...state, 60 | lastDestination: action.payload.locationName, 61 | lastResponseAt: action.payload.receviedAt, 62 | state: "idle", 63 | }; 64 | case "response/reset": { 65 | return { ...state, lastDestination: "unknown" }; 66 | } 67 | case "response/error": { 68 | return { ...state, state: "idle", lastDestination: "unknown" }; 69 | } 70 | case "request/start": 71 | return { ...state, state: "in-progress" }; 72 | default: 73 | return state; 74 | } 75 | }, 76 | { 77 | currentLocation: "unknown", 78 | state: "idle", 79 | lastDestination: "unknown", 80 | lastResponseAt: new Date().toISOString(), 81 | } 82 | )); 83 | 84 | function render(state, previousState) { 85 | if (previousState.currentLocation !== state.currentLocation) { 86 | switch (state.currentLocation) { 87 | case "eu": 88 | locationEu.setAttribute("checked", true); 89 | locationUs.removeAttribute("checked"); 90 | locationAp.removeAttribute("checked"); 91 | break; 92 | case "us": 93 | locationEu.removeAttribute("checked"); 94 | locationUs.setAttribute("checked", true); 95 | locationAp.removeAttribute("checked"); 96 | break; 97 | case "ap": 98 | locationEu.removeAttribute("checked"); 99 | locationUs.removeAttribute("checked"); 100 | locationAp.setAttribute("checked", true); 101 | default: 102 | locationEu.removeAttribute("checked"); 103 | locationUs.removeAttribute("checked"); 104 | locationAp.removeAttribute("checked"); 105 | break; 106 | } 107 | } 108 | if ( 109 | previousState.lastDestination !== state.lastDestination && 110 | Page[state.currentLocation]?.links?.[state.lastDestination] 111 | ) { 112 | Page[state.currentLocation].links[state.lastDestination].classList.remove( 113 | "dn" 114 | ); 115 | switch (state.lastDestination) { 116 | case "us": 117 | Page.us.cluster.style.fill = "#326CE5"; 118 | Page.eu.cluster.style.fill = "#BFBFBF"; 119 | Page.ap.cluster.style.fill = "#BFBFBF"; 120 | break; 121 | case "eu": 122 | Page.us.cluster.style.fill = "#BFBFBF"; 123 | Page.eu.cluster.style.fill = "#326CE5"; 124 | Page.ap.cluster.style.fill = "#BFBFBF"; 125 | break; 126 | case "ap": 127 | Page.us.cluster.style.fill = "#BFBFBF"; 128 | Page.eu.cluster.style.fill = "#BFBFBF"; 129 | Page.ap.cluster.style.fill = "#326CE5"; 130 | break; 131 | default: 132 | Page.us.cluster.style.fill = "#BFBFBF"; 133 | Page.eu.cluster.style.fill = "#BFBFBF"; 134 | Page.ap.cluster.style.fill = "#BFBFBF"; 135 | break; 136 | } 137 | } 138 | 139 | if (previousState.currentLocation !== state.currentLocation) { 140 | switch (state.currentLocation) { 141 | case "us": 142 | Page.us.pin.style.fill = "#C32826"; 143 | Page.eu.pin.style.fill = "#BFBFBF"; 144 | Page.ap.pin.style.fill = "#BFBFBF"; 145 | Page.us.ingress.classList.remove("dn"); 146 | Page.eu.ingress.classList.add("dn"); 147 | Page.ap.ingress.classList.add("dn"); 148 | break; 149 | case "eu": 150 | Page.us.pin.style.fill = "#BFBFBF"; 151 | Page.eu.pin.style.fill = "#C32826"; 152 | Page.ap.pin.style.fill = "#BFBFBF"; 153 | Page.us.ingress.classList.add("dn"); 154 | Page.eu.ingress.classList.remove("dn"); 155 | Page.ap.ingress.classList.add("dn"); 156 | break; 157 | case "ap": 158 | Page.us.pin.style.fill = "#BFBFBF"; 159 | Page.eu.pin.style.fill = "#BFBFBF"; 160 | Page.ap.pin.style.fill = "#C32826"; 161 | Page.us.ingress.classList.add("dn"); 162 | Page.eu.ingress.classList.add("dn"); 163 | Page.ap.ingress.classList.remove("dn"); 164 | break; 165 | default: 166 | Page.us.pin.style.fill = "#BFBFBF"; 167 | Page.eu.pin.style.fill = "#BFBFBF"; 168 | Page.ap.pin.style.fill = "#BFBFBF"; 169 | Page.us.ingress.classList.add("dn"); 170 | Page.eu.ingress.classList.add("dn"); 171 | Page.ap.ingress.classList.add("dn"); 172 | break; 173 | } 174 | } 175 | } 176 | 177 | const Action = { 178 | setCurrentLocation(locationName) { 179 | return { type: "location/set", payload: locationName }; 180 | }, 181 | recordResponse(locationName, receviedAt) { 182 | return { type: "response/record", payload: { locationName, receviedAt } }; 183 | }, 184 | startRequest() { 185 | return { type: "request/start" }; 186 | }, 187 | recordError() { 188 | return { type: "response/error" }; 189 | }, 190 | resetDestination() { 191 | return { type: "response/reset" }; 192 | }, 193 | }; 194 | 195 | const requestReply = RequestReplyWorker(2000); 196 | const reset = ResetLinksWorker(1500); 197 | let cache = { 198 | previousState: store.getState(), 199 | oldTimestamp: Date.now(), 200 | fps: 60, 201 | delta: 0, 202 | }; 203 | 204 | render(store.getState(), {}); 205 | Loop(Date.now()); 206 | store.dispatch(Action.setCurrentLocation("eu")); 207 | 208 | function Loop(timestamp) { 209 | cache.delta = timestamp - cache.oldTimestamp; 210 | cache.oldTimestamp = timestamp; 211 | cache.fps = Math.round(1 / (cache.delta / 1000)); 212 | const state = store.getState(); 213 | const previousState = cache.previousState; 214 | cache.previousState = state; 215 | 216 | requestReply(Date.now(), previousState); 217 | reset(Date.now(), previousState); 218 | 219 | render(state, previousState); 220 | requestAnimationFrame(Loop); 221 | } 222 | 223 | function RequestReplyWorker(ms = 5000) { 224 | let previousDate = Date.now(); 225 | let isInProgress = false; 226 | return (now = Date.now(), state) => { 227 | if (isInProgress) { 228 | return; 229 | } 230 | 231 | if (now - previousDate > ms) { 232 | previousDate = now; 233 | if (state.currentLocation !== "unknown") { 234 | store.dispatch(Action.startRequest()); 235 | isInProgress = true; 236 | fetch(`/${state.currentLocation}`) 237 | .then((response) => response.text()) 238 | .then((response) => { 239 | if (/Singapore/i.test(response)) { 240 | store.dispatch( 241 | Action.recordResponse("ap", new Date().toISOString()) 242 | ); 243 | } 244 | if (/London/i.test(response)) { 245 | store.dispatch( 246 | Action.recordResponse("eu", new Date().toISOString()) 247 | ); 248 | } 249 | if (/Fremont/i.test(response)) { 250 | store.dispatch( 251 | Action.recordResponse("us", new Date().toISOString()) 252 | ); 253 | } 254 | }) 255 | .catch((error) => { 256 | console.log(error); 257 | store.dispatch(Action.recordError()); 258 | }) 259 | .finally(() => { 260 | isInProgress = false; 261 | }); 262 | } 263 | } 264 | }; 265 | } 266 | 267 | function ResetLinksWorker(ms = 1000) { 268 | return (now = Date.now(), state) => { 269 | if ( 270 | state.lastDestination !== "unknown" && 271 | now - new Date(state.lastResponseAt).valueOf() > ms 272 | ) { 273 | resetLinks(); 274 | store.dispatch(Action.resetDestination()); 275 | } 276 | }; 277 | } 278 | 279 | function resetLinks() { 280 | for (const locationA of ["eu", "ap", "us"]) { 281 | for (const locationB of ["eu", "ap", "us"]) { 282 | Page[locationA].links[locationB].classList.add("dn"); 283 | } 284 | } 285 | } 286 | 287 | function createStore(reducer, initialState) { 288 | let currentState = initialState; 289 | let listeners = []; 290 | 291 | return { dispatch, getState, subscribe }; 292 | 293 | function dispatch(action) { 294 | currentState = reducer(currentState, action); 295 | console.log("dispatch", action, currentState); 296 | listeners.slice(0).forEach((it) => it(currentState)); 297 | } 298 | 299 | function subscribe(listener) { 300 | listeners.push(listener); 301 | } 302 | 303 | function getState() { 304 | return currentState; 305 | } 306 | } 307 | 308 | async function wait(ms = 1000) { 309 | return new Promise((resolve) => setTimeout(resolve, ms)); 310 | } 311 | -------------------------------------------------------------------------------- /world-map/index.js: -------------------------------------------------------------------------------- 1 | const http = require("http"); 2 | const { readFileSync } = require("fs"); 3 | 4 | const endpoints = JSON.parse(process.argv.slice(2)[0]); 5 | 6 | const requestListener = function (req, res) { 7 | switch (req.url) { 8 | case "/": { 9 | const html = readFileSync(__dirname + "/index.html", "utf-8"); 10 | res.setHeader("Content-Type", "text/html"); 11 | res.writeHead(200); 12 | res.end(html); 13 | break; 14 | } 15 | case "/app.js": { 16 | const js = readFileSync(__dirname + "/app.js", "utf-8"); 17 | res.setHeader("Content-Type", "text/javascript"); 18 | res.writeHead(200); 19 | res.end(js); 20 | break; 21 | } 22 | case "/eu": { 23 | http.get(endpoints.eu, function (response) { 24 | response.pipe(res, { end: true }); 25 | }); 26 | break; 27 | } 28 | case "/us": { 29 | http.get(endpoints.us, function (response) { 30 | response.pipe(res, { end: true }); 31 | }); 32 | break; 33 | } 34 | case "/ap": { 35 | http.get(endpoints.ap, function (response) { 36 | response.pipe(res, { end: true }); 37 | }); 38 | break; 39 | } 40 | default: 41 | res.writeHead(404); 42 | res.end(); 43 | break; 44 | } 45 | }; 46 | 47 | const server = http.createServer(requestListener); 48 | server.listen(8082); 49 | --------------------------------------------------------------------------------