├── LICENSE ├── README.md ├── azuredeploy.json ├── frankenetes ├── apply_defaults.sh ├── create_certs.sh ├── create_kubeconfigs.sh ├── defaults │ ├── ClusterRoleBinding.yml │ └── LimitRange.yml └── tls │ ├── admin-csr.json │ ├── ca-config.json │ ├── ca-csr.json │ ├── etcd-csr.json │ ├── kube-controller-manager-csr.json │ ├── kube-scheduler-csr.json │ ├── kubernetes-csr.json │ ├── virtual-kubelet-csr.json │ └── virtual-kubelet-win-csr.json └── parameters.sample.json /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Noel Bundick 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # frankenetes 2 | 3 | Serverless Kubernetes on Azure Container Instances 4 | 5 | Deploy to Azure 6 | 7 | ## Description 8 | 9 | This repo contains all the code needed to create a "virtual cluster" on top of Azure Container Instances. **This isn't production-grade** - think of it as a fun experiment and a reference on what's possible using Resource Manager Templates and ACI. 10 | 11 | Read more here: 12 | [https://www.noelbundick.com/2018/01/22/Frankenetes-Running-the-Kubernetes-control-plane-on-Azure-Container-Instances/](https://www.noelbundick.com/2018/01/22/Frankenetes-Running-the-Kubernetes-control-plane-on-Azure-Container-Instances/) 13 | 14 | ## Usage 15 | 16 | 1. Create a Service Principal for virtual-kubelet 17 | 18 | ```shell 19 | # Create a service principal 20 | # Tip: the following terms are synonymous: clientId<->appId, clientSecret<->password 21 | az ad sp create-for-rbac -n frankenetes --skip-assignment 22 | ``` 23 | 24 | 2. Create a virtual Kubernetes cluster 25 | 26 | ```shell 27 | az group create -n frankenetes -l eastus 28 | az group deployment create -g frankenetes --template-file ./azuredeploy.json --parameters servicePrincipalClientId= servicePrincipalClientSecret= servicePrincipalObjectId= --query 'properties.outputs.kubeconfig.value' -o tsv 29 | 30 | # Download the kubeconfig from Azure Files 31 | # The exact command to run is an output of the deployment 32 | az storage file download --account-name -s kubeconfigs -p admin.kubeconfig 33 | export KUBECONFIG=admin.kubeconfig 34 | ``` 35 | 36 | 3. Run something! 37 | 38 | Frankenetes runs two virtual-kubelets, so it's a hybrid-OS cluster! 39 | 40 | You can run Linux containers: 41 | 42 | ```shell 43 | # Run nginx 44 | kubectl run nginx --image=nginx --port 80 45 | 46 | # Hit the deployed pod 47 | NGINX_IP=`kubectl get pod -l run=nginx -o=jsonpath='{.items[0].status.podIP}'` 48 | curl $NGINX_IP 49 | ``` 50 | 51 | Or Windows containers: 52 | 53 | ```shell 54 | # Run IIS 55 | k run iis --image=microsoft/iis:nanoserver-sac2016 --port=80 56 | 57 | # Hit the deployed pod 58 | IIS_IP=`kubectl get pod -l run=iis -o=jsonpath='{.items[0].status.podIP}'` 59 | curl $IIS_IP 60 | ``` 61 | 62 | ## Cleanup 63 | 64 | To remove the cluster completely, delete the resource groups: 65 | 66 | ```shell 67 | az group delete -n frankenetes -y --no-wait 68 | ``` 69 | 70 | To stop all compute, but leave your cluster configuration intact, delete just your Azure Container Instances: 71 | 72 | ```shell 73 | for aci in `az container list -g frankenetes --query "[].name" -o tsv`; do az container delete -n $aci -g frankenetes -y; done 74 | ``` -------------------------------------------------------------------------------- /azuredeploy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "apiserverDnsNameLabel": { 6 | "type": "string", 7 | "defaultValue": "[toLower(concat('frankenetes-apiserver', take(uniqueString(resourceGroup().id), 6)))]" 8 | }, 9 | "etcdDnsNameLabel": { 10 | "type": "string", 11 | "defaultValue": "[toLower(concat('frankenetes-etcd', take(uniqueString(resourceGroup().id), 6)))]" 12 | }, 13 | "k8sVersion": { 14 | "type": "string", 15 | "defaultValue": "v1.9.2" 16 | }, 17 | "vkPodResourceGroupName": { 18 | "type": "string", 19 | "defaultValue": "[resourceGroup().name]" 20 | }, 21 | "servicePrincipalClientId": { 22 | "type": "string" 23 | }, 24 | "servicePrincipalClientSecret": { 25 | "type": "securestring" 26 | }, 27 | "servicePrincipalObjectId": { 28 | "type": "string" 29 | }, 30 | "storageAccountName": { 31 | "type": "string", 32 | "defaultValue": "[toLower(concat('frankenetes', take(uniqueString(resourceGroup().id), 6)))]" 33 | } 34 | }, 35 | "variables": { 36 | "contributorRole": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c')]", 37 | "etcdFQDN": "[concat(parameters('etcdDnsNameLabel'), '.', resourceGroup().location, '.azurecontainer.io')]", 38 | "apiserverFQDN": "[concat(parameters('apiserverDnsNameLabel'), '.', resourceGroup().location, '.azurecontainer.io')]", 39 | "sharesToCreate": "tls kubeconfigs etcd apiserver controller-manager scheduler virtual-kubelet", 40 | "vkConfig": "[concat('{\"clientId\": \"', parameters('servicePrincipalClientId'), '\",\"clientSecret\": \"', parameters('servicePrincipalClientSecret'), '\",\"subscriptionId\": \"', subscription().subscriptionId, '\",\"tenantId\": \"', subscription().tenantId, '\",\"activeDirectoryEndpointUrl\": \"https://login.microsoftonline.com/\",\"resourceManagerEndpointUrl\": \"https://management.azure.com/\",\"activeDirectoryGraphResourceId\": \"https://graph.windows.net/\",\"sqlManagementEndpointUrl\": \"database.windows.net\",\"galleryEndpointUrl\": \"https://gallery.azure.com/\",\"managementEndpointUrl\": \"https://management.core.windows.net/\"}')]", 41 | "storageApiVersion": "[providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]]" 42 | }, 43 | "resources": [ 44 | { 45 | "type": "Microsoft.Authorization/roleAssignments", 46 | "apiVersion": "2015-07-01", 47 | "name": "[guid(resourceGroup().id)]", 48 | "properties": { 49 | "principalId": "[parameters('servicePrincipalObjectId')]", 50 | "roleDefinitionId": "[variables('contributorRole')]", 51 | "scope": "[resourceGroup().id]" 52 | } 53 | }, 54 | { 55 | "type": "Microsoft.Storage/storageAccounts", 56 | "apiVersion": "2018-02-01", 57 | "location": "[resourceGroup().location]", 58 | "name": "[parameters('storageAccountName')]", 59 | "kind": "StorageV2", 60 | "sku": { 61 | "name": "Standard_LRS" 62 | }, 63 | "properties": { 64 | "encryption": { 65 | "keySource": "Microsoft.Storage", 66 | "services": { 67 | "blob": { 68 | "enabled": true 69 | }, 70 | "file": { 71 | "enabled": true 72 | } 73 | } 74 | }, 75 | "supportsHttpsTrafficOnly": true 76 | } 77 | }, 78 | { 79 | "type": "Microsoft.ContainerInstance/containerGroups", 80 | "apiVersion": "2018-06-01", 81 | "location": "[resourceGroup().location]", 82 | "dependsOn": [ 83 | "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]" 84 | ], 85 | "name": "setup", 86 | "properties": { 87 | "containers": [ 88 | { 89 | "name": "setup", 90 | "properties": { 91 | "command": [ 92 | "/bin/bash", 93 | "-c", 94 | "for i in $SHARES; do az storage share create -n $i; done" 95 | ], 96 | "environmentVariables": [ 97 | { 98 | "name": "AZURE_STORAGE_ACCOUNT", 99 | "value": "[parameters('storageAccountName')]" 100 | }, 101 | { 102 | "name": "AZURE_STORAGE_KEY", 103 | "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), variables('storageApiVersion')).keys[0].value]" 104 | }, 105 | { 106 | "name": "SHARES", 107 | "value": "[variables('sharesToCreate')]" 108 | } 109 | ], 110 | "image": "microsoft/azure-cli", 111 | "resources": { 112 | "requests": { 113 | "cpu": 1, 114 | "memoryInGB": 1.5 115 | } 116 | } 117 | } 118 | } 119 | ], 120 | "osType": "Linux", 121 | "restartPolicy": "OnFailure" 122 | } 123 | }, 124 | { 125 | "type": "Microsoft.ContainerInstance/containerGroups", 126 | "apiVersion": "2018-06-01", 127 | "location": "[resourceGroup().location]", 128 | "dependsOn": [ 129 | "[resourceId('Microsoft.ContainerInstance/containerGroups', 'setup')]" 130 | ], 131 | "name": "cfssl", 132 | "properties": { 133 | "containers": [ 134 | { 135 | "name": "cfssl", 136 | "properties": { 137 | "command": [ 138 | "/bin/sh", 139 | "-c", 140 | "[concat('chmod +x /frankenetes/frankenetes/create_certs.sh && /frankenetes/frankenetes/create_certs.sh ', variables('etcdFQDN'), ' ', variables('apiserverFQDN'), ' && cp /frankenetes/frankenetes/tls/*.pem /tls')]" 141 | ], 142 | "image": "cfssl/cfssl", 143 | "resources": { 144 | "requests": { 145 | "cpu": 1, 146 | "memoryInGB": 1.5 147 | } 148 | }, 149 | "volumeMounts": [ 150 | { 151 | "name": "scripts", 152 | "mountPath": "/frankenetes" 153 | }, 154 | { 155 | "name": "tls", 156 | "mountPath": "/tls" 157 | }, 158 | { 159 | "name": "etcd", 160 | "mountPath": "/etcd" 161 | }, 162 | { 163 | "name": "apiserver", 164 | "mountPath": "/apiserver" 165 | }, 166 | { 167 | "name": "controllermanager", 168 | "mountPath": "/controllermanager" 169 | } 170 | ] 171 | } 172 | } 173 | ], 174 | "osType": "Linux", 175 | "restartPolicy": "OnFailure", 176 | "volumes": [ 177 | { 178 | "name": "scripts", 179 | "gitRepo": { 180 | "repository": "https://github.com/noelbundick/frankenetes.git", 181 | "directory": "." 182 | } 183 | }, 184 | { 185 | "name": "tls", 186 | "azureFile": { 187 | "shareName": "tls", 188 | "storageAccountName": "[parameters('storageAccountName')]", 189 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), variables('storageApiVersion')).keys[0].value]" 190 | } 191 | }, 192 | { 193 | "name": "etcd", 194 | "azureFile": { 195 | "shareName": "etcd", 196 | "storageAccountName": "[parameters('storageAccountName')]", 197 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), variables('storageApiVersion')).keys[0].value]" 198 | } 199 | }, 200 | { 201 | "name": "apiserver", 202 | "azureFile": { 203 | "shareName": "apiserver", 204 | "storageAccountName": "[parameters('storageAccountName')]", 205 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), variables('storageApiVersion')).keys[0].value]" 206 | } 207 | }, 208 | { 209 | "name": "controllermanager", 210 | "azureFile": { 211 | "shareName": "controller-manager", 212 | "storageAccountName": "[parameters('storageAccountName')]", 213 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), variables('storageApiVersion')).keys[0].value]" 214 | } 215 | } 216 | ] 217 | } 218 | }, 219 | { 220 | "type": "Microsoft.ContainerInstance/containerGroups", 221 | "apiVersion": "2018-06-01", 222 | "location": "[resourceGroup().location]", 223 | "dependsOn": [ 224 | "[resourceId('Microsoft.ContainerInstance/containerGroups', 'cfssl')]" 225 | ], 226 | "name": "kubeconfig", 227 | "properties": { 228 | "containers": [ 229 | { 230 | "name": "kubeconfig", 231 | "properties": { 232 | "command": [ 233 | "/bin/sh", 234 | "-c", 235 | "[concat('chmod +x /frankenetes/frankenetes/create_kubeconfigs.sh && /frankenetes/frankenetes/create_kubeconfigs.sh ', variables('apiServerFQDN'), ' /tls /kubeconfigs')]" 236 | ], 237 | "image": "[concat('lachlanevenson/k8s-kubectl:', parameters('k8sVersion'))]", 238 | "resources": { 239 | "requests": { 240 | "cpu": 1, 241 | "memoryInGB": 1.5 242 | } 243 | }, 244 | "volumeMounts": [ 245 | { 246 | "name": "scripts", 247 | "mountPath": "/frankenetes" 248 | }, 249 | { 250 | "name": "tls", 251 | "mountPath": "/tls" 252 | }, 253 | { 254 | "name": "kubeconfigs", 255 | "mountPath": "/kubeconfigs" 256 | }, 257 | { 258 | "name": "controllermanager", 259 | "mountPath": "/controllermanager" 260 | }, 261 | { 262 | "name": "scheduler", 263 | "mountPath": "/scheduler" 264 | }, 265 | { 266 | "name": "virtualkubelet", 267 | "mountPath": "/virtualkubelet" 268 | } 269 | ] 270 | } 271 | } 272 | ], 273 | "osType": "Linux", 274 | "restartPolicy": "OnFailure", 275 | "volumes": [ 276 | { 277 | "name": "scripts", 278 | "gitRepo": { 279 | "repository": "https://github.com/noelbundick/frankenetes.git", 280 | "directory": "." 281 | } 282 | }, 283 | { 284 | "name": "tls", 285 | "azureFile": { 286 | "shareName": "tls", 287 | "storageAccountName": "[parameters('storageAccountName')]", 288 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), variables('storageApiVersion')).keys[0].value]" 289 | } 290 | }, 291 | { 292 | "name": "kubeconfigs", 293 | "azureFile": { 294 | "shareName": "kubeconfigs", 295 | "storageAccountName": "[parameters('storageAccountName')]", 296 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), variables('storageApiVersion')).keys[0].value]" 297 | } 298 | }, 299 | { 300 | "name": "controllermanager", 301 | "azureFile": { 302 | "shareName": "controller-manager", 303 | "storageAccountName": "[parameters('storageAccountName')]", 304 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), variables('storageApiVersion')).keys[0].value]" 305 | } 306 | }, 307 | { 308 | "name": "scheduler", 309 | "azureFile": { 310 | "shareName": "scheduler", 311 | "storageAccountName": "[parameters('storageAccountName')]", 312 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), variables('storageApiVersion')).keys[0].value]" 313 | } 314 | }, 315 | { 316 | "name": "virtualkubelet", 317 | "azureFile": { 318 | "shareName": "virtual-kubelet", 319 | "storageAccountName": "[parameters('storageAccountName')]", 320 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), variables('storageApiVersion')).keys[0].value]" 321 | } 322 | } 323 | ] 324 | } 325 | }, 326 | { 327 | "type": "Microsoft.ContainerInstance/containerGroups", 328 | "apiVersion": "2018-06-01", 329 | "location": "[resourceGroup().location]", 330 | "dependsOn": [ 331 | "[resourceId('Microsoft.ContainerInstance/containerGroups', 'kubeconfig')]" 332 | ], 333 | "name": "etcd", 334 | "properties": { 335 | "containers": [ 336 | { 337 | "name": "etcd", 338 | "properties": { 339 | "command": [ 340 | "/usr/local/bin/etcd", 341 | "--name=frankenetes-etcd-0", 342 | "--cert-file=/etcd/etcd.pem", 343 | "--key-file=/etcd/etcd-key.pem", 344 | "--trusted-ca-file=/etcd/ca.pem", 345 | "--client-cert-auth", 346 | "--listen-client-urls=https://0.0.0.0:2379", 347 | "[concat('--advertise-client-urls=https://', variables('etcdFQDN'), ':2379')]", 348 | "--data-dir=/etcd/data", 349 | "--wal-dir=/etcd-wal" 350 | ], 351 | "image": "quay.io/coreos/etcd:v3.2.8", 352 | "ports": [ 353 | { 354 | "port": 2379, 355 | "protocol": "TCP" 356 | }, 357 | { 358 | "port": 2380, 359 | "protocol": "TCP" 360 | } 361 | ], 362 | "resources": { 363 | "requests": { 364 | "cpu": 1, 365 | "memoryInGB": 1.5 366 | } 367 | }, 368 | "volumeMounts": [ 369 | { 370 | "name": "azurefile", 371 | "mountPath": "/etcd" 372 | } 373 | ] 374 | } 375 | } 376 | ], 377 | "ipAddress": { 378 | "dnsNameLabel": "[parameters('etcdDnsNameLabel')]", 379 | "type": "Public", 380 | "ports": [ 381 | { 382 | "port": 2379, 383 | "protocol": "TCP" 384 | }, 385 | { 386 | "port": 2380, 387 | "protocol": "TCP" 388 | } 389 | ] 390 | }, 391 | "osType": "Linux", 392 | "restartPolicy": "Always", 393 | "volumes": [ 394 | { 395 | "name": "azurefile", 396 | "azureFile": { 397 | "shareName": "etcd", 398 | "storageAccountName": "[parameters('storageAccountName')]", 399 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), variables('storageApiVersion')).keys[0].value]" 400 | } 401 | } 402 | ] 403 | } 404 | }, 405 | { 406 | "type": "Microsoft.ContainerInstance/containerGroups", 407 | "apiVersion": "2018-06-01", 408 | "location": "[resourceGroup().location]", 409 | "dependsOn": [ 410 | "[resourceId('Microsoft.ContainerInstance/containerGroups', 'kubeconfig')]" 411 | ], 412 | "name": "apiserver", 413 | "properties": { 414 | "containers": [ 415 | { 416 | "name": "apiserver", 417 | "properties": { 418 | "command": [ 419 | "/apiserver", 420 | "--admission-control=NamespaceLifecycle,LimitRanger,ResourceQuota", 421 | "--advertise-address=0.0.0.0", 422 | "--allow-privileged=false", 423 | "--apiserver-count=1", 424 | "--audit-log-maxage=30", 425 | "--audit-log-maxbackup=3", 426 | "--audit-log-maxsize=100", 427 | "--audit-log-path=/apisrv/log/audit.log", 428 | "--authorization-mode=Node,RBAC", 429 | "--bind-address=0.0.0.0", 430 | "--client-ca-file=/apisrv/ca.pem", 431 | "--enable-swagger-ui=true", 432 | "--etcd-cafile=/apisrv/ca.pem", 433 | "--etcd-certfile=/apisrv/etcd.pem", 434 | "--etcd-keyfile=/apisrv/etcd-key.pem", 435 | "[concat('--etcd-servers=https://', variables('etcdFQDN'), ':2379')]", 436 | "--event-ttl=1h", 437 | "--insecure-bind-address=127.0.0.1", 438 | "--kubelet-certificate-authority=/apisrv/ca.pem", 439 | "--kubelet-client-certificate=/apisrv/kubernetes.pem", 440 | "--kubelet-client-key=/apisrv/kubernetes-key.pem", 441 | "--kubelet-https=true", 442 | "--runtime-config=api/all", 443 | "--runtime-config=admissionregistration.k8s.io/v1alpha1", 444 | "--service-account-key-file=/apisrv/ca-key.pem", 445 | "--service-node-port-range=30000-32767", 446 | "--tls-ca-file=/apisrv/ca.pem", 447 | "--tls-cert-file=/apisrv/kubernetes.pem", 448 | "--tls-private-key-file=/apisrv/kubernetes-key.pem", 449 | "--v=2" 450 | ], 451 | "image": "[concat('gcr.io/google-containers/hyperkube-amd64:', parameters('k8sVersion'))]", 452 | "ports": [ 453 | { 454 | "port": 6443, 455 | "protocol": "TCP" 456 | } 457 | ], 458 | "resources": { 459 | "requests": { 460 | "cpu": 1, 461 | "memoryInGB": 1.5 462 | } 463 | }, 464 | "volumeMounts": [ 465 | { 466 | "name": "azurefile", 467 | "mountPath": "/apisrv" 468 | } 469 | ] 470 | } 471 | } 472 | ], 473 | "ipAddress": { 474 | "dnsNameLabel": "[parameters('apiserverDnsNameLabel')]", 475 | "type": "Public", 476 | "ports": [ 477 | { 478 | "port": 6443, 479 | "protocol": "TCP" 480 | } 481 | ] 482 | }, 483 | "osType": "Linux", 484 | "restartPolicy": "Always", 485 | "volumes": [ 486 | { 487 | "name": "azurefile", 488 | "azureFile": { 489 | "shareName": "apiserver", 490 | "storageAccountName": "[parameters('storageAccountName')]", 491 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), variables('storageApiVersion')).keys[0].value]" 492 | } 493 | } 494 | ] 495 | } 496 | }, 497 | { 498 | "type": "Microsoft.ContainerInstance/containerGroups", 499 | "apiVersion": "2018-06-01", 500 | "location": "[resourceGroup().location]", 501 | "dependsOn": [ 502 | "[resourceId('Microsoft.ContainerInstance/containerGroups', 'kubeconfig')]" 503 | ], 504 | "name": "controllermanager", 505 | "properties": { 506 | "containers": [ 507 | { 508 | "name": "controllermanager", 509 | "properties": { 510 | "command": [ 511 | "/controller-manager", 512 | "--address=0.0.0.0", 513 | "--cluster-cidr=10.200.0.0/16", 514 | "--cluster-name=kubernetes", 515 | "--cluster-signing-cert-file=/cm/ca.pem", 516 | "--cluster-signing-key-file=/cm/ca-key.pem", 517 | "--kubeconfig=/cm/controller-manager.kubeconfig", 518 | "--leader-elect=true", 519 | "--root-ca-file=/cm/ca.pem", 520 | "--service-account-private-key-file=/cm/ca-key.pem", 521 | "--use-service-account-credentials", 522 | "--v=2" 523 | ], 524 | "image": "[concat('gcr.io/google-containers/hyperkube-amd64:', parameters('k8sVersion'))]", 525 | "resources": { 526 | "requests": { 527 | "cpu": 1, 528 | "memoryInGB": 1.5 529 | } 530 | }, 531 | "volumeMounts": [ 532 | { 533 | "name": "azurefile", 534 | "mountPath": "/cm" 535 | } 536 | ] 537 | } 538 | } 539 | ], 540 | "osType": "Linux", 541 | "restartPolicy": "Always", 542 | "volumes": [ 543 | { 544 | "name": "azurefile", 545 | "azureFile": { 546 | "shareName": "controller-manager", 547 | "storageAccountName": "[parameters('storageAccountName')]", 548 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), variables('storageApiVersion')).keys[0].value]" 549 | } 550 | } 551 | ] 552 | } 553 | }, 554 | { 555 | "type": "Microsoft.ContainerInstance/containerGroups", 556 | "apiVersion": "2018-06-01", 557 | "location": "[resourceGroup().location]", 558 | "dependsOn": [ 559 | "[resourceId('Microsoft.ContainerInstance/containerGroups', 'kubeconfig')]" 560 | ], 561 | "name": "scheduler", 562 | "properties": { 563 | "containers": [ 564 | { 565 | "name": "scheduler", 566 | "properties": { 567 | "command": [ 568 | "/scheduler", 569 | "--kubeconfig=/sched/scheduler.kubeconfig", 570 | "--leader-elect=true", 571 | "--v=2" 572 | ], 573 | "image": "[concat('gcr.io/google-containers/hyperkube-amd64:', parameters('k8sVersion'))]", 574 | "resources": { 575 | "requests": { 576 | "cpu": 1, 577 | "memoryInGB": 1.5 578 | } 579 | }, 580 | "volumeMounts": [ 581 | { 582 | "name": "azurefile", 583 | "mountPath": "/sched" 584 | } 585 | ] 586 | } 587 | } 588 | ], 589 | "osType": "Linux", 590 | "restartPolicy": "Always", 591 | "volumes": [ 592 | { 593 | "name": "azurefile", 594 | "azureFile": { 595 | "shareName": "scheduler", 596 | "storageAccountName": "[parameters('storageAccountName')]", 597 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), variables('storageApiVersion')).keys[0].value]" 598 | } 599 | } 600 | ] 601 | } 602 | }, 603 | { 604 | "type": "Microsoft.ContainerInstance/containerGroups", 605 | "apiVersion": "2018-06-01", 606 | "location": "[resourceGroup().location]", 607 | "dependsOn": [ 608 | "[resourceId('Microsoft.ContainerInstance/containerGroups', 'apiserver')]" 609 | ], 610 | "name": "defaults", 611 | "properties": { 612 | "containers": [ 613 | { 614 | "name": "defaults", 615 | "properties": { 616 | "command": [ 617 | "/bin/sh", 618 | "-c", 619 | "chmod +x /frankenetes/frankenetes/apply_defaults.sh && /frankenetes/frankenetes/apply_defaults.sh /kubeconfigs/admin.kubeconfig" 620 | ], 621 | "image": "[concat('lachlanevenson/k8s-kubectl:', parameters('k8sVersion'))]", 622 | "resources": { 623 | "requests": { 624 | "cpu": 1, 625 | "memoryInGB": 1.5 626 | } 627 | }, 628 | "volumeMounts": [ 629 | { 630 | "name": "scripts", 631 | "mountPath": "/frankenetes" 632 | }, 633 | { 634 | "name": "kubeconfigs", 635 | "mountPath": "/kubeconfigs" 636 | } 637 | ] 638 | } 639 | } 640 | ], 641 | "osType": "Linux", 642 | "restartPolicy": "OnFailure", 643 | "volumes": [ 644 | { 645 | "name": "scripts", 646 | "gitRepo": { 647 | "repository": "https://github.com/noelbundick/frankenetes.git", 648 | "directory": "." 649 | } 650 | }, 651 | { 652 | "name": "kubeconfigs", 653 | "azureFile": { 654 | "shareName": "kubeconfigs", 655 | "storageAccountName": "[parameters('storageAccountName')]", 656 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), variables('storageApiVersion')).keys[0].value]" 657 | } 658 | } 659 | ] 660 | } 661 | }, 662 | { 663 | "type": "Microsoft.ContainerInstance/containerGroups", 664 | "apiVersion": "2018-06-01", 665 | "location": "[resourceGroup().location]", 666 | "dependsOn": [ 667 | "[resourceId('Microsoft.ContainerInstance/containerGroups', 'defaults')]" 668 | ], 669 | "name": "virtual-kubelet", 670 | "properties": { 671 | "containers": [ 672 | { 673 | "name": "virtual-kubelet", 674 | "properties": { 675 | "command": [ 676 | "/usr/bin/virtual-kubelet", 677 | "--kubeconfig", "/etc/virtual-kubelet/virtual-kubelet.kubeconfig", 678 | "--nodename", "virtual-kubelet", 679 | "--os", "Linux", 680 | "--provider", "azure" 681 | ], 682 | "environmentVariables": [ 683 | { 684 | "name": "AZURE_AUTH_LOCATION", 685 | "value": "/etc/virtual-kubelet/secret/credentials.json" 686 | }, 687 | { 688 | "name": "ACI_RESOURCE_GROUP", 689 | "value": "[parameters('vkPodResourceGroupName')]" 690 | }, 691 | { 692 | "name": "ACI_REGION", 693 | "value": "[resourceGroup().location]" 694 | } 695 | ], 696 | "image": "microsoft/virtual-kubelet", 697 | "resources": { 698 | "requests": { 699 | "cpu": 1, 700 | "memoryInGB": 1.5 701 | } 702 | }, 703 | "volumeMounts": [ 704 | { 705 | "name": "azurefile", 706 | "mountPath": "/etc/virtual-kubelet" 707 | }, 708 | { 709 | "name": "secret", 710 | "mountPath": "/etc/virtual-kubelet/secret" 711 | } 712 | ] 713 | } 714 | }, 715 | { 716 | "name": "virtual-kubelet-win", 717 | "properties": { 718 | "command": [ 719 | "/usr/bin/virtual-kubelet", 720 | "--kubeconfig", "/etc/virtual-kubelet/virtual-kubelet-win.kubeconfig", 721 | "--nodename", "virtual-kubelet-win", 722 | "--os", "Windows", 723 | "--provider", "azure" 724 | ], 725 | "environmentVariables": [ 726 | { 727 | "name": "AZURE_AUTH_LOCATION", 728 | "value": "/etc/virtual-kubelet/secret/credentials.json" 729 | }, 730 | { 731 | "name": "ACI_RESOURCE_GROUP", 732 | "value": "[parameters('vkPodResourceGroupName')]" 733 | }, 734 | { 735 | "name": "ACI_REGION", 736 | "value": "[resourceGroup().location]" 737 | } 738 | ], 739 | "image": "microsoft/virtual-kubelet", 740 | "resources": { 741 | "requests": { 742 | "cpu": 1, 743 | "memoryInGB": 1.5 744 | } 745 | }, 746 | "volumeMounts": [ 747 | { 748 | "name": "azurefile", 749 | "mountPath": "/etc/virtual-kubelet" 750 | }, 751 | { 752 | "name": "secret", 753 | "mountPath": "/etc/virtual-kubelet/secret" 754 | } 755 | ] 756 | } 757 | } 758 | ], 759 | "osType": "Linux", 760 | "restartPolicy": "Always", 761 | "volumes": [ 762 | { 763 | "name": "azurefile", 764 | "azureFile": { 765 | "shareName": "virtual-kubelet", 766 | "storageAccountName": "[parameters('storageAccountName')]", 767 | "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), variables('storageApiVersion')).keys[0].value]" 768 | } 769 | }, 770 | { 771 | "name": "secret", 772 | "secret": { 773 | "credentials.json": "[base64(variables('vkConfig'))]" 774 | } 775 | } 776 | ] 777 | } 778 | } 779 | ], 780 | "outputs": { 781 | "kubeconfig": { 782 | "type": "string", 783 | "value": "[concat('az storage file download --account-name ', parameters('storageAccountName'), ' -s kubeconfigs -p admin.kubeconfig')]" 784 | } 785 | } 786 | } -------------------------------------------------------------------------------- /frankenetes/apply_defaults.sh: -------------------------------------------------------------------------------- 1 | export KUBECONFIG=$1 2 | 3 | # Execute in the defaults directory 4 | cd `dirname $0`/defaults 5 | 6 | kubectl apply -f ClusterRoleBinding.yml 7 | kubectl apply -f LimitRange.yml 8 | -------------------------------------------------------------------------------- /frankenetes/create_certs.sh: -------------------------------------------------------------------------------- 1 | ETCD_FQDN=$1 2 | APISERVER_FQDN=$2 3 | 4 | # Execute in the tls directory 5 | cd `dirname $0`/tls 6 | 7 | # Create a new Certificate Authority 8 | cfssl gencert -initca ca-csr.json | cfssljson -bare ca 9 | 10 | # TODO: Use different CA's for etcd vs k8s 11 | # etcd 12 | cfssl gencert \ 13 | -ca=ca.pem \ 14 | -ca-key=ca-key.pem \ 15 | -config=ca-config.json \ 16 | -hostname=$ETCD_FQDN,127.0.0.1 \ 17 | -profile=kubernetes \ 18 | etcd-csr.json | cfssljson -bare etcd 19 | cp etcd.pem etcd-key.pem ca.pem /etcd 20 | 21 | # apiserver 22 | cfssl gencert \ 23 | -ca=ca.pem \ 24 | -ca-key=ca-key.pem \ 25 | -config=ca-config.json \ 26 | -hostname=$APISERVER_FQDN,127.0.0.1,kubernetes.default \ 27 | -profile=kubernetes \ 28 | kubernetes-csr.json | cfssljson -bare kubernetes 29 | cp kubernetes.pem kubernetes-key.pem etcd.pem etcd-key.pem ca.pem ca-key.pem /apiserver 30 | 31 | # Generate the admin client certificate 32 | cfssl gencert \ 33 | -ca=ca.pem \ 34 | -ca-key=ca-key.pem \ 35 | -config=ca-config.json \ 36 | -profile=kubernetes \ 37 | admin-csr.json | cfssljson -bare admin 38 | 39 | # kube-controller-manager 40 | cfssl gencert \ 41 | -ca=ca.pem \ 42 | -ca-key=ca-key.pem \ 43 | -config=ca-config.json \ 44 | -profile=kubernetes \ 45 | kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager 46 | cp ca.pem ca-key.pem /controllermanager 47 | 48 | # kube-scheduler 49 | cfssl gencert \ 50 | -ca=ca.pem \ 51 | -ca-key=ca-key.pem \ 52 | -config=ca-config.json \ 53 | -profile=kubernetes \ 54 | kube-scheduler-csr.json | cfssljson -bare kube-scheduler 55 | 56 | # virtual-kubelet node 57 | cfssl gencert \ 58 | -ca=ca.pem \ 59 | -ca-key=ca-key.pem \ 60 | -config=ca-config.json \ 61 | -hostname=virtual-kubelet \ 62 | -profile=kubernetes \ 63 | virtual-kubelet-csr.json | cfssljson -bare virtual-kubelet 64 | 65 | # virtual-kubelet-win node 66 | cfssl gencert \ 67 | -ca=ca.pem \ 68 | -ca-key=ca-key.pem \ 69 | -config=ca-config.json \ 70 | -hostname=virtual-kubelet-win \ 71 | -profile=kubernetes \ 72 | virtual-kubelet-win-csr.json | cfssljson -bare virtual-kubelet-win -------------------------------------------------------------------------------- /frankenetes/create_kubeconfigs.sh: -------------------------------------------------------------------------------- 1 | APISERVER_FQDN=$1 2 | CERTS_DIR=$2 3 | OUTPUT_DIR=$3 4 | 5 | ############ 6 | # create admin kubeconfig 7 | ############ 8 | ADMIN_KUBECONFIG=$OUTPUT_DIR/admin.kubeconfig 9 | 10 | kubectl config set-cluster frankenetes \ 11 | --certificate-authority=$CERTS_DIR/ca.pem \ 12 | --embed-certs=true \ 13 | --server="https://$APISERVER_FQDN:6443" \ 14 | --kubeconfig=$ADMIN_KUBECONFIG 15 | kubectl config set-credentials admin \ 16 | --client-certificate=$CERTS_DIR/admin.pem \ 17 | --client-key=$CERTS_DIR/admin-key.pem \ 18 | --embed-certs=true \ 19 | --kubeconfig=$ADMIN_KUBECONFIG 20 | kubectl config set-context frankenetes \ 21 | --cluster=frankenetes \ 22 | --user=admin \ 23 | --kubeconfig=$ADMIN_KUBECONFIG 24 | kubectl config use-context frankenetes \ 25 | --kubeconfig=$ADMIN_KUBECONFIG 26 | 27 | echo "admin kubeconfig created at $ADMIN_KUBECONFIG" 28 | 29 | ############ 30 | # create controller manager kubeconfig 31 | ############ 32 | CONTROLLER_MANAGER_KUBECONFIG=$OUTPUT_DIR/controller-manager.kubeconfig 33 | 34 | kubectl config set-cluster frankenetes \ 35 | --certificate-authority=$CERTS_DIR/ca.pem \ 36 | --embed-certs=true \ 37 | --server="https://$APISERVER_FQDN:6443" \ 38 | --kubeconfig=$CONTROLLER_MANAGER_KUBECONFIG 39 | kubectl config set-credentials controller-manager \ 40 | --client-certificate=$CERTS_DIR/kube-controller-manager.pem \ 41 | --client-key=$CERTS_DIR/kube-controller-manager-key.pem \ 42 | --embed-certs=true \ 43 | --kubeconfig=$CONTROLLER_MANAGER_KUBECONFIG 44 | kubectl config set-context frankenetes \ 45 | --cluster=frankenetes \ 46 | --user=controller-manager \ 47 | --kubeconfig=$CONTROLLER_MANAGER_KUBECONFIG 48 | kubectl config use-context frankenetes \ 49 | --kubeconfig=$CONTROLLER_MANAGER_KUBECONFIG 50 | 51 | echo "controller manager kubeconfig created at $CONTROLLER_MANAGER_KUBECONFIG" 52 | cp $CONTROLLER_MANAGER_KUBECONFIG /controllermanager/controller-manager.kubeconfig 53 | 54 | ############ 55 | # create scheduler kubeconfig 56 | ############ 57 | SCHEDULER_KUBECONFIG=$OUTPUT_DIR/scheduler.kubeconfig 58 | 59 | kubectl config set-cluster frankenetes \ 60 | --certificate-authority=$CERTS_DIR/ca.pem \ 61 | --embed-certs=true \ 62 | --server="https://$APISERVER_FQDN:6443" \ 63 | --kubeconfig=$SCHEDULER_KUBECONFIG 64 | kubectl config set-credentials scheduler \ 65 | --client-certificate=$CERTS_DIR/kube-scheduler.pem \ 66 | --client-key=$CERTS_DIR/kube-scheduler-key.pem \ 67 | --embed-certs=true \ 68 | --kubeconfig=$SCHEDULER_KUBECONFIG 69 | kubectl config set-context frankenetes \ 70 | --cluster=frankenetes \ 71 | --user=scheduler \ 72 | --kubeconfig=$SCHEDULER_KUBECONFIG 73 | kubectl config use-context frankenetes \ 74 | --kubeconfig=$SCHEDULER_KUBECONFIG 75 | 76 | echo "scheduler kubeconfig created at $SCHEDULER_KUBECONFIG" 77 | cp $SCHEDULER_KUBECONFIG /scheduler/scheduler.kubeconfig 78 | 79 | ############ 80 | # create virtual-kubelet kubeconfig 81 | ############ 82 | VK_KUBECONFIG=$OUTPUT_DIR/virtual-kubelet.kubeconfig 83 | 84 | kubectl config set-cluster frankenetes \ 85 | --certificate-authority=$CERTS_DIR/ca.pem \ 86 | --embed-certs=true \ 87 | --server="https://$APISERVER_FQDN:6443" \ 88 | --kubeconfig=$VK_KUBECONFIG 89 | kubectl config set-credentials system:node:virtual-kubelet \ 90 | --client-certificate=$CERTS_DIR/virtual-kubelet.pem \ 91 | --client-key=$CERTS_DIR/virtual-kubelet-key.pem \ 92 | --embed-certs=true \ 93 | --kubeconfig=$VK_KUBECONFIG 94 | kubectl config set-context frankenetes \ 95 | --cluster=frankenetes \ 96 | --user=system:node:virtual-kubelet \ 97 | --kubeconfig=$VK_KUBECONFIG 98 | kubectl config use-context frankenetes \ 99 | --kubeconfig=$VK_KUBECONFIG 100 | 101 | echo "virtual-kubelet kubeconfig created at $VK_KUBECONFIG" 102 | cp $VK_KUBECONFIG /virtualkubelet/virtual-kubelet.kubeconfig 103 | 104 | ############ 105 | # create virtual-kubelet-win kubeconfig 106 | ############ 107 | VK_WIN_KUBECONFIG=$OUTPUT_DIR/virtual-kubelet-win.kubeconfig 108 | 109 | kubectl config set-cluster frankenetes \ 110 | --certificate-authority=$CERTS_DIR/ca.pem \ 111 | --embed-certs=true \ 112 | --server="https://$APISERVER_FQDN:6443" \ 113 | --kubeconfig=$VK_WIN_KUBECONFIG 114 | kubectl config set-credentials system:node:virtual-kubelet-win \ 115 | --client-certificate=$CERTS_DIR/virtual-kubelet-win.pem \ 116 | --client-key=$CERTS_DIR/virtual-kubelet-win-key.pem \ 117 | --embed-certs=true \ 118 | --kubeconfig=$VK_WIN_KUBECONFIG 119 | kubectl config set-context frankenetes \ 120 | --cluster=frankenetes \ 121 | --user=system:node:virtual-kubelet-win \ 122 | --kubeconfig=$VK_WIN_KUBECONFIG 123 | kubectl config use-context frankenetes \ 124 | --kubeconfig=$VK_WIN_KUBECONFIG 125 | 126 | echo "virtual-kubelet-win kubeconfig created at $VK_WIN_KUBECONFIG" 127 | cp $VK_WIN_KUBECONFIG /virtualkubelet/virtual-kubelet-win.kubeconfig -------------------------------------------------------------------------------- /frankenetes/defaults/ClusterRoleBinding.yml: -------------------------------------------------------------------------------- 1 | # See https://github.com/virtual-kubelet/virtual-kubelet/issues/210 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRoleBinding 4 | metadata: 5 | name: virtual-kubelet 6 | roleRef: 7 | apiGroup: rbac.authorization.k8s.io 8 | kind: ClusterRole 9 | name: cluster-admin 10 | subjects: 11 | - apiGroup: rbac.authorization.k8s.io 12 | kind: User 13 | name: system:node:virtual-kubelet 14 | - apiGroup: rbac.authorization.k8s.io 15 | kind: User 16 | name: system:node:virtual-kubelet-win -------------------------------------------------------------------------------- /frankenetes/defaults/LimitRange.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: LimitRange 3 | metadata: 4 | name: vk-default-request 5 | namespace: kube-system 6 | spec: 7 | limits: 8 | - defaultRequest: 9 | cpu: 1 10 | memory: 1G 11 | type: Container 12 | --- 13 | apiVersion: v1 14 | kind: LimitRange 15 | metadata: 16 | name: vk-default-request 17 | namespace: kube-public 18 | spec: 19 | limits: 20 | - defaultRequest: 21 | cpu: 1 22 | memory: 1G 23 | type: Container 24 | --- 25 | apiVersion: v1 26 | kind: LimitRange 27 | metadata: 28 | name: vk-default-request 29 | namespace: default 30 | spec: 31 | limits: 32 | - defaultRequest: 33 | cpu: 1 34 | memory: 1G 35 | type: Container -------------------------------------------------------------------------------- /frankenetes/tls/admin-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "admin", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "US", 10 | "L": "Redmond", 11 | "O": "system:masters", 12 | "OU": "Frankenetes", 13 | "ST": "Washington" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /frankenetes/tls/ca-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "signing": { 3 | "default": { 4 | "expiry": "8760h" 5 | }, 6 | "profiles": { 7 | "kubernetes": { 8 | "usages": ["signing", "key encipherment", "server auth", "client auth"], 9 | "expiry": "8760h" 10 | } 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /frankenetes/tls/ca-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "Kubernetes", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "US", 10 | "L": "Redmond", 11 | "O": "Kubernetes", 12 | "OU": "CA", 13 | "ST": "Washington" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /frankenetes/tls/etcd-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "etcd", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "US", 10 | "L": "Redmond", 11 | "O": "Kubernetes", 12 | "OU": "Frankenetes", 13 | "ST": "Washington" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /frankenetes/tls/kube-controller-manager-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "system:kube-controller-manager", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "US", 10 | "L": "Redmond", 11 | "O": "system:kube-controller-manager", 12 | "OU": "Frankenetes", 13 | "ST": "Washington" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /frankenetes/tls/kube-scheduler-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "system:kube-scheduler", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "US", 10 | "L": "Redmond", 11 | "O": "system:kube-scheduler", 12 | "OU": "Frankenetes", 13 | "ST": "Washington" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /frankenetes/tls/kubernetes-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "kubernetes", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "US", 10 | "L": "Redmond", 11 | "O": "Kubernetes", 12 | "OU": "Frankenetes", 13 | "ST": "Washington" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /frankenetes/tls/virtual-kubelet-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "system:node:virtual-kubelet", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "US", 10 | "L": "Redmond", 11 | "O": "system:nodes", 12 | "OU": "Frankenetes", 13 | "ST": "Washington" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /frankenetes/tls/virtual-kubelet-win-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "system:node:virtual-kubelet-win", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "US", 10 | "L": "Redmond", 11 | "O": "system:nodes", 12 | "OU": "Frankenetes", 13 | "ST": "Washington" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /parameters.sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "servicePrincipalClientId": { 6 | "value": "d191834b-851f-4428-9612-817c8ad351b7" 7 | }, 8 | "servicePrincipalObjectId": { 9 | "value": "b569938f-9689-4aa0-b434-43ae2d5c5ccb" 10 | }, 11 | "servicePrincipalClientSecret": { 12 | "value": "dcf7b153-7599-4fc8-9d98-2782612d097e" 13 | } 14 | } 15 | } --------------------------------------------------------------------------------