[
  {
    "path": ".gitignore",
    "content": ".DS_Store\n.id_key\n.master_ip\n.master_lb_ip\n\n# cli\ndcos\nkubectl\n\n# terraform\n.deploy\n.terraform\n/*.tf\n/*.tf.disabled\n*.tfstate\n*.tfstate.backup\nterraform.tfvars\n.terraform.tfstate.lock.info\nmodules/\ndesired_cluster_profile.tfvars.example\ndesired_cluster_profile\n\n"
  },
  {
    "path": "LICENSE",
    "content": "\n                              Apache License\n                        Version 2.0, January 2004\n                     http://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n   \"License\" shall mean the terms and conditions for use, reproduction,\n   and distribution as defined by Sections 1 through 9 of this document.\n\n   \"Licensor\" shall mean the copyright owner or entity authorized by\n   the copyright owner that is granting the License.\n\n   \"Legal Entity\" shall mean the union of the acting entity and all\n   other entities that control, are controlled by, or are under common\n   control with that entity. For the purposes of this definition,\n   \"control\" means (i) the power, direct or indirect, to cause the\n   direction or management of such entity, whether by contract or\n   otherwise, or (ii) ownership of fifty percent (50%) or more of the\n   outstanding shares, or (iii) beneficial ownership of such entity.\n\n   \"You\" (or \"Your\") shall mean an individual or Legal Entity\n   exercising permissions granted by this License.\n\n   \"Source\" form shall mean the preferred form for making modifications,\n   including but not limited to software source code, documentation\n   source, and configuration files.\n\n   \"Object\" form shall mean any form resulting from mechanical\n   transformation or translation of a Source form, including but\n   not limited to compiled object code, generated documentation,\n   and conversions to other media types.\n\n   \"Work\" shall mean the work of authorship, whether in Source or\n   Object form, made available under the License, as indicated by a\n   copyright notice that is included in or attached to the work\n   (an example is provided in the Appendix below).\n\n   \"Derivative Works\" shall mean any work, whether in Source or Object\n   form, that is based on (or derived from) the Work and for which the\n   editorial revisions, annotations, elaborations, or other modifications\n   represent, as a whole, an original work of authorship. For the purposes\n   of this License, Derivative Works shall not include works that remain\n   separable from, or merely link (or bind by name) to the interfaces of,\n   the Work and Derivative Works thereof.\n\n   \"Contribution\" shall mean any work of authorship, including\n   the original version of the Work and any modifications or additions\n   to that Work or Derivative Works thereof, that is intentionally\n   submitted to Licensor for inclusion in the Work by the copyright owner\n   or by an individual or Legal Entity authorized to submit on behalf of\n   the copyright owner. For the purposes of this definition, \"submitted\"\n   means any form of electronic, verbal, or written communication sent\n   to the Licensor or its representatives, including but not limited to\n   communication on electronic mailing lists, source code control systems,\n   and issue tracking systems that are managed by, or on behalf of, the\n   Licensor for the purpose of discussing and improving the Work, but\n   excluding communication that is conspicuously marked or otherwise\n   designated in writing by the copyright owner as \"Not a Contribution.\"\n\n   \"Contributor\" shall mean Licensor and any individual or Legal Entity\n   on behalf of whom a Contribution has been received by Licensor and\n   subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   copyright license to reproduce, prepare Derivative Works of,\n   publicly display, publicly perform, sublicense, and distribute the\n   Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   (except as stated in this section) patent license to make, have made,\n   use, offer to sell, sell, import, and otherwise transfer the Work,\n   where such license applies only to those patent claims licensable\n   by such Contributor that are necessarily infringed by their\n   Contribution(s) alone or by combination of their Contribution(s)\n   with the Work to which such Contribution(s) was submitted. If You\n   institute patent litigation against any entity (including a\n   cross-claim or counterclaim in a lawsuit) alleging that the Work\n   or a Contribution incorporated within the Work constitutes direct\n   or contributory patent infringement, then any patent licenses\n   granted to You under this License for that Work shall terminate\n   as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\n   Work or Derivative Works thereof in any medium, with or without\n   modifications, and in Source or Object form, provided that You\n   meet the following conditions:\n\n   (a) You must give any other recipients of the Work or\n       Derivative Works a copy of this License; and\n\n   (b) You must cause any modified files to carry prominent notices\n       stating that You changed the files; and\n\n   (c) You must retain, in the Source form of any Derivative Works\n       that You distribute, all copyright, patent, trademark, and\n       attribution notices from the Source form of the Work,\n       excluding those notices that do not pertain to any part of\n       the Derivative Works; and\n\n   (d) If the Work includes a \"NOTICE\" text file as part of its\n       distribution, then any Derivative Works that You distribute must\n       include a readable copy of the attribution notices contained\n       within such NOTICE file, excluding those notices that do not\n       pertain to any part of the Derivative Works, in at least one\n       of the following places: within a NOTICE text file distributed\n       as part of the Derivative Works; within the Source form or\n       documentation, if provided along with the Derivative Works; or,\n       within a display generated by the Derivative Works, if and\n       wherever such third-party notices normally appear. The contents\n       of the NOTICE file are for informational purposes only and\n       do not modify the License. You may add Your own attribution\n       notices within Derivative Works that You distribute, alongside\n       or as an addendum to the NOTICE text from the Work, provided\n       that such additional attribution notices cannot be construed\n       as modifying the License.\n\n   You may add Your own copyright statement to Your modifications and\n   may provide additional or different license terms and conditions\n   for use, reproduction, or distribution of Your modifications, or\n   for any such Derivative Works as a whole, provided Your use,\n   reproduction, and distribution of the Work otherwise complies with\n   the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\n   any Contribution intentionally submitted for inclusion in the Work\n   by You to the Licensor shall be under the terms and conditions of\n   this License, without any additional terms or conditions.\n   Notwithstanding the above, nothing herein shall supersede or modify\n   the terms of any separate license agreement you may have executed\n   with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\n   names, trademarks, service marks, or product names of the Licensor,\n   except as required for reasonable and customary use in describing the\n   origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\n   agreed to in writing, Licensor provides the Work (and each\n   Contributor provides its Contributions) on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n   implied, including, without limitation, any warranties or conditions\n   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n   PARTICULAR PURPOSE. You are solely responsible for determining the\n   appropriateness of using or redistributing the Work and assume any\n   risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\n   whether in tort (including negligence), contract, or otherwise,\n   unless required by applicable law (such as deliberate and grossly\n   negligent acts) or agreed to in writing, shall any Contributor be\n   liable to You for damages, including any direct, indirect, special,\n   incidental, or consequential damages of any character arising as a\n   result of this License or out of the use or inability to use the\n   Work (including but not limited to damages for loss of goodwill,\n   work stoppage, computer failure or malfunction, or any and all\n   other commercial damages or losses), even if such Contributor\n   has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\n   the Work or Derivative Works thereof, You may choose to offer,\n   and charge a fee for, acceptance of support, warranty, indemnity,\n   or other liability obligations and/or rights consistent with this\n   License. However, in accepting such obligations, You may act only\n   on Your own behalf and on Your sole responsibility, not on behalf\n   of any other Contributor, and only if You agree to indemnify,\n   defend, and hold each Contributor harmless for any liability\n   incurred by, or claims asserted against, such Contributor by reason\n   of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\n   To apply the Apache License to your work, attach the following\n   boilerplate notice, with the fields enclosed by brackets \"[]\"\n   replaced with your own identifying information. (Don't include\n   the brackets!)  The text should be enclosed in the appropriate\n   comment syntax for the file format. We also recommend that a\n   file or class name and description of purpose be included on the\n   same \"printed page\" as the copyright notice for easier\n   identification within third-party archives.\n\nCopyright 2016 Mesosphere\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "Makefile",
    "content": "\nRM := rm -f\nSSH_USER := core\nTERRAFORM_INSTALLER_URL := github.com/dcos/terraform-dcos\nDCOS_CLI_VERSION := 1.12\nCUSTOM_DCOS_DOWNLOAD_PATH := https://downloads.dcos.io/dcos/stable/1.12.3/dcos_generate_config.sh\nKUBERNETES_VERSION ?= 1.16.9\nKUBERNETES_FRAMEWORK_VERSION ?= 2.5.0-1.16.9\nKUBERNETES_STUB_URL ?=\nKUBERNETES_CLUSTER_STUB_URL ?=\n# PATH_TO_PACKAGE_OPTIONS holds the path to the package options file to be used\n# when installing DC/OS Kubernetes.\nPATH_TO_PACKAGE_OPTIONS ?= \"$(PWD)/.deploy/options.json\"\n\n# Set PATH (locally) to include local dir for locally downloaded binaries.\nFAKEPATH := \"$(PWD):$(PATH)\"\n\n# Get the path to relevant binaries.\nDCOS_CMD := $(shell PATH=$(FAKEPATH) command -v dcos 2> /dev/null)\nKUBECTL_CMD := $(shell PATH=$(FAKEPATH) command -v kubectl 2> /dev/null)\nTERRAFORM_CMD := $(shell PATH=$(FAKEPATH) command -v terraform 2> /dev/null)\nTERRAFORM_APPLY_ARGS ?=\nTERRAFORM_DESTROY_ARGS ?=\n\nUNAME := $(shell uname -s)\nifeq ($(UNAME),Linux)\nOPEN := xdg-open\nelse\nOPEN := open\nendif\n\n# Define a new line character to use in error strings.\ndefine n\n\n\nendef\n\n.PHONY: get-cli\nget-cli:\n\t$(eval export DCOS_CLI_VERSION)\n\t$(eval export KUBERNETES_VERSION)\n\tscripts/get_cli\n\n.PHONY: check-cli\ncheck-cli: check-terraform check-dcos check-kubectl\n\n.PHONY: check-terraform\ncheck-terraform:\nifndef TERRAFORM_CMD\n\t$(error \"$n$nNo terraform command in $(FAKEPATH).$n$nPlease install via 'brew install terraform' on MacOS, or download from https://www.terraform.io/downloads.html.$n$n\")\nendif\n\n.PHONY: check-dcos\ncheck-dcos:\nifndef DCOS_CMD\n\t$(error \"$n$nNo dcos command in $(FAKEPATH).$n$nPlease run 'make get-cli' to download required binaries.$n$n\")\nendif\n\n.PHONY: check-kubectl\ncheck-kubectl:\nifndef KUBECTL_CMD\n\t$(error \"$n$nNo kubectl command in $(FAKEPATH).$n$nPlease run 'make get-cli' to download required binaries.$n$n\")\nendif\n\n.PHONY: gcp aws\ngcp aws: clean check-terraform\n\tmkdir -p .deploy && \\\n\tcd .deploy && \\\n\tcp ../resources/main.$@.tf main.tf && \\\n\tcp ../resources/variables.$@.tf variables.tf && \\\n\t$(TERRAFORM_CMD) init && \\\n\tcp ../resources/desired_cluster_profile.$@.tfvars terraform.tfvars && \\\n\tcp ../resources/options.json . && \\\n\tcp ../resources/outputs.tf . && \\\n\tcp ../resources/kubeapi-proxy.json .\n\n.PHONY: get-master-lb-ip\nget-master-lb-ip: check-terraform\n\t$(call get_master_lb_ip)\n\t@echo $(MASTER_LB_IP)\n\ndefine get_master_lb_ip\n$(eval MASTER_LB_IP := $(shell $(TERRAFORM_CMD) output -state=.deploy/terraform.tfstate \"cluster-address\"))\nendef\n\n.PHONY: get-public-agent-ip\nget-public-agent-ip: check-terraform\n\t$(call get_public_agent_ip)\n\t@echo $(PUBLIC_AGENT_IP)\n\ndefine get_public_agent_ip\n$(eval PUBLIC_AGENT_IP := $(shell $(TERRAFORM_CMD) output -state=.deploy/terraform.tfstate  \"public-agents-loadbalancer\"))\nendef\n\n.PHONY: plan-dcos\nplan-dcos: check-terraform\n\t@cd .deploy; \\\n\t$(TERRAFORM_CMD) plan\n\n.PHONY: launch-dcos\nlaunch-dcos: check-terraform\n\t@cd .deploy; \\\n\t$(TERRAFORM_CMD) apply $(TERRAFORM_APPLY_ARGS)\n\n.PHONY: plan\nplan: plan-dcos\n\n.PHONY: deploy\ndeploy: check-cli launch-dcos setup-cli install\n\n.PHONY: setup-cli\nsetup-cli: check-dcos\n\t$(call get_master_lb_ip)\n\tfor i in {1..20}; do $(DCOS_CMD) cluster setup https://$(MASTER_LB_IP) --insecure && break || (sleep 3) ; done\n\t@scripts/poll_api.sh \"DC/OS Master\" $(MASTER_LB_IP) 443\n\n.PHONY: ui\nui:\n\t$(call get_master_lb_ip)\n\t$(OPEN) https://$(MASTER_LB_IP)\n\n.PHONY: install\ninstall: check-dcos add-stubs\n\t@echo \"Installing Mesosphere Kubernetes Engine...\"\n\t$(DCOS_CMD) package install --yes kubernetes --package-version=\"$(KUBERNETES_FRAMEWORK_VERSION)\"\n\t@echo \"Waiting for Mesosphere Kubernetes Engine to be up...\"\n\t@while [[ ! $$($(DCOS_CMD) kubernetes manager plan show deploy 2> /dev/null | head -n1 | grep COMPLETE ) ]]; do \\\n\t\tsleep 1; \\\n\tdone\n\t@echo \"Creating a Kubernetes cluster...\"\n\t$(DCOS_CMD) kubernetes cluster create --yes --options=\"$(PATH_TO_PACKAGE_OPTIONS)\" --package-version=\"$(KUBERNETES_FRAMEWORK_VERSION)\"\n\n.PHONY: add-stubs\nadd-stubs:\nifdef KUBERNETES_STUB_URL\n\t@echo \"Adding 'kubernetes' stub\"\n\t$(DCOS_CMD) package repo add --index=0 kubernetes-aws \"$(KUBERNETES_STUB_URL)\"\nendif\nifdef KUBERNETES_CLUSTER_STUB_URL\n\t@echo \"Adding 'kubernetes-cluster' stub\"\n\t$(DCOS_CMD) package repo add --index=0 kubernetes-cluster-aws \"$(KUBERNETES_CLUSTER_STUB_URL)\"\nendif\n\n.PHONY: marathon-lb\nmarathon-lb:\n\t$(DCOS_CMD) package install --yes marathon-lb\n\t@sleep 30\n\t$(DCOS_CMD) marathon app add \"$(PWD)/.deploy/kubeapi-proxy.json\"\n\n.PHONY: watch-kubernetes-cluster\nwatch-kubernetes-cluster:\n\twatch dcos kubernetes cluster debug --cluster-name=dev/kubernetes01 plan show deploy\n\n.PHONY: watch-kubernetes\nwatch-kubernetes:\n\twatch dcos kubernetes manager plan show deploy\n\n.PHONY: kubeconfig\nkubeconfig:\n\t$(call get_public_agent_ip)\n\t$(DCOS_CMD) kubernetes cluster kubeconfig --cluster-name dev/kubernetes01 --apiserver-url https://$(PUBLIC_AGENT_IP):6443 --context-name devkubernetes01 --insecure-skip-tls-verify\n\t@scripts/poll_api.sh \"Kubernetes API\" $(PUBLIC_AGENT_IP) 6443\n\n.PHONY: upgrade-infra\nupgrade-infra: launch-dcos\n\n.PHONY: uninstall\nuninstall: check-dcos\n\t$(DCOS_CMD) marathon app remove kubeapi-proxy\n\t$(DCOS_CMD) package uninstall marathon-lb --yes\n\t$(DCOS_CMD) kubernetes cluster delete --cluster-name dev/kubernetes01 --yes\n\tfor i in {1..8}; do ! $(DCOS_CMD) marathon app list --json | jq '.[].id' | grep '/dev/kubernetes01' >/dev/null && break || (echo \"Kubernetes Cluster is still uninstalling. Retrying in 15 seconds...\" && sleep 15) ; done\n\t$(DCOS_CMD) package uninstall kubernetes --yes\n\tfor i in {1..8}; do ! $(DCOS_CMD) marathon app list --json | jq '.[].id' | grep '/kubernetes' >/dev/null && break || (echo \"Mesosphere Kubernetes Engine is still uninstalling. Retrying in 15 seconds...\" && sleep 15) ; done\nifdef KUBERNETES_STUB_URL\n\t@echo \"Removing 'kubernetes' stub\"\n\t$(DCOS_CMD) package repo remove kubernetes-aws\nendif\nifdef KUBERNETES_CLUSTER_STUB_URL\n\t@echo \"Removing 'kubernetes-cluster' stub\"\n\t$(DCOS_CMD) package repo remove kubernetes-cluster-aws\nendif\n\n.PHONY: destroy\ndestroy: check-terraform\n\tcd .deploy; \\\n\t$(TERRAFORM_CMD) destroy $(TERRAFORM_DESTROY_ARGS)\n\n.PHONY: clean\nclean:\n\t$(RM) -r .deploy dcos kubectl\n\n.PHONY: kubectl-tunnel\nkubectl-tunnel:\n\t$(KUBECTL_CMD) config set-cluster dcos-k8s --server=http://localhost:9000\n\t$(KUBECTL_CMD) config set-context dcos-k8s --cluster=dcos-k8s --namespace=default\n\t$(KUBECTL_CMD) config use-context dcos-k8s\n\t$(call get_public_agent_ip)\n\tssh -4 -o \"UserKnownHostsFile=/dev/null\" -o \"StrictHostKeyChecking=no\" -o \"ServerAliveInterval=120\" \\\n\t\t-N -L 9000:apiserver-insecure.devkubernetes01.l4lb.thisdcos.directory:9000 \\\n\t\t$(SSH_USER)@$(PUBLIC_AGENT_IP)\n"
  },
  {
    "path": "README.md",
    "content": "# Kubernetes on DC/OS\n\nKubernetes is now available as a DC/OS package to quickly, and reliably run Kubernetes clusters on Mesosphere DC/OS.\n\n![](docs/assets/ui-install.gif)\n\n**NOTE:** The latest `dcos-kubernetes-quickstart` doesn't support any Kubernetes framework version before `2.0.0-1.12.1`. The reason is that now creating Kubernetes clusters requires the installation of the [Mesosphere Kubernetes Engine](https://docs.mesosphere.com/services/kubernetes/2.5.0-1.16.9/overview/#cluster-manager).\n\n## Known limitations\n\nBefore proceeding, please check the [current package limitations](https://docs.mesosphere.com/service-docs/kubernetes/2.5.0-1.16.9/limitations/).\n\n## Pre-Requisites\n\nCheck the requirements for running this quickstart:\n\n* Linux or MacOS\n* [Terraform 0.11.x](https://www.terraform.io/downloads.html). On MacOS, you can install with [brew](https://brew.sh/):\n  ```bash\n  $ brew install terraform\n  ```\n* [Google Cloud](docs/gcp.md) or [AWS](docs/aws.md) account with enough permissions to provide the\n  needed infrastructure\n\n## Quickstart\n\nOnce the pre-requisites are met, clone this repo:\n\n```bash\n$ git clone git@github.com:mesosphere/dcos-kubernetes-quickstart.git && cd dcos-kubernetes-quickstart\n```\n\n### Prepare infrastructure configuration\n\n**This quickstart defaults to Google Cloud**\n\nFirst, make sure you have have followed the [Google Cloud setup instructions](docs/gcp.md).\n\nThen, start by generating the default infrastructure configuration:\n\n```bash\n$ make gcp\n```\n\nThis will output sane defaults to `.deploy/terraform.tfvars`.\nNow, edit said file and set your `gcp_project` and the `ssh_public_key_file`\n(the SSH public key you will use to log-in into your new VMs later).\n\n**WARNING:** Please, do not set a smaller instance (VM) type on the risk of failing to\ninstall Kubernetes.\n\n```\ncluster_name = \"dcos-kubernetes\"\ncluster_name_random_string = true\n\ndcos_version = \"1.12.3\"\n\nnum_of_masters = \"1\"\nnum_of_private_agents = \"4\"\nnum_of_public_agents = \"1\"\n\nbootstrap_instance_type = \"n1-standard-1\"\nmaster_instance_type = \"n1-standard-8\"\nprivate_agent_instance_type = \"n1-standard-8\"\npublic_agent_instance_type = \"n1-standard-8\"\n\n# admin_ips = \"0.0.0.0/0\" # uncomment to access master from any IP\n\ngcp_project = \"YOUR_GCP_PROJECT\"\ngcp_region = \"us-central1\"\nssh_public_key_file = \"/PATH/YOUR_GCP_SSH_PUBLIC_KEY.pub\"\n#\n# If you want to use GCP service account key instead of GCP SDK\n# uncomment the line below and update it with the path to the key file\n# gcp_credentials = \"/PATH/YOUR_GCP_SERVICE_ACCOUNT_KEY.json\"\n#\n```\n\n**NOTE:** The current release of the DC/OS GCP Terraform module also requires the `GOOGLE_PROJECT`\nand `GOOGLE_REGION` environment variables to be set. Please set them with appropriates values for\nyour deployment:\n\n```\n$ export GOOGLE_PROJECT=\"YOUR_GCP_PROJECT\"\n$ export GOOGLE_REGION=\"us-central1\"\n```\n\n### Kubernetes configuration\n\n#### RBAC\n\n**NOTE:** This `quickstart` will provision a Kubernetes cluster with `RBAC` support.\n\nTo deploy a cluster with RBAC disabled [RBAC](https://docs.mesosphere.com/services/kubernetes/2.5.0-1.16.9/operations/authn-and-authz/#rbac) update `.deploy/options.json`:\n\n```\n{\n  \"service\": {\n    \"name\": \"dev/kubernetes01\"\n  },\n  \"kubernetes\": {\n    \"authorization_mode\": \"AlwaysAllow\"\n  }\n}\n```\n\nIf you want to give users access to the Kubernetes API check [documentation](https://docs.mesosphere.com/services/kubernetes/2.5.0-1.16.9/operations/authn-and-authz/#giving-users-access-to-the-kubernetes-api).\n\n**NOTE:** The authorization mode for a cluster must be chosen when installing the package. Changing the authorization mode after installing the package is not supported.\n\n#### HA Cluster\n\n**NOTE:** By default, it will provision a Kubernetes cluster with one (1) worker node, and\na single instance of every control plane component.\n\nTo deploy a **highly-available** cluster with three (3) private Kubernetes nodes update `.deploy/options.json`:\n\n```\n{\n  \"service\": {\n    \"name\": \"dev/kubernetes01\"\n  },\n  \"kubernetes\": {\n    \"high_availability\": true,\n    \"private_node_count\": 3\n  }\n}\n```\n\n### Download command-line tools\n\nIf you haven't already, please download DC/OS client, `dcos` and Kubernetes\nclient, `kubectl`:\n\n```bash\n$ make get-cli\n```\n\nThe `dcos` and `kubectl` binaries will be downloaded to the current workdir.\nIt's up to you to decided whether or not to copy or move them to another path,\ne.g. a path included in `PATH`.\n\n### Install\n\nYou are now ready to provision the DC/OS cluster and install the Kubernetes package:\n\n```bash\n$ make deploy\n```\n\nTerraform will now try and provision the infrastructure on your chosen cloud\nprovider, and then proceed to install DC/OS.\n\nWhen DC/OS is up and running, the Kubernetes package installation will take place.\n\nWait until all tasks are running before trying to access the Kubernetes API.\n\nYou can watch the progress what was deployed so far with:\n\n```bash\n$ make watch-kubernetes-cluster\n```\n\nBelow is an example of how it looks like when the install ran successfully:\n\n```\nUsing Kubernetes cluster: dev/kubernetes01\ndeploy (serial strategy) (COMPLETE)\n   etcd (serial strategy) (COMPLETE)\n      etcd-0:[peer] (COMPLETE)\n   control-plane (dependency strategy) (COMPLETE)\n      kube-control-plane-0:[instance] (COMPLETE)\n   mandatory-addons (serial strategy) (COMPLETE)\n      mandatory-addons-0:[instance] (COMPLETE)\n   node (dependency strategy) (COMPLETE)\n      kube-node-0:[kubelet] (COMPLETE)\n   public-node (dependency strategy) (COMPLETE)\n```\n\nYou can access DC/OS Dashboard and check Kubernetes package tasks under Services:\n\n```bash\n$ make ui\n```\n\n### Exposing the Kubernetes API\n\nCheck the [exposing Kubernetes API doc](docs/exposing_kubernetes_api.md) to understand how\nthe Kubernetes API gets exposed.\nTo actually expose the Kubernetes API for the new Kubernetes cluster using Marathon-LB, run:\n\n```bash\n$ make marathon-lb\n```\n\n**NOTE:** If you have changed in `.deploy/terraform.tfvars` file the number of\n`num_of_public_agents` to more than `1`, please scale `marathon-lb` service to the same number,\nso you can access Kubernetes API from any DC/OS public agent.\n\n### Accessing the Kubernetes API\n\nIn order to access the Kubernetes API from outside the DC/OS cluster, one needs\nto configure `kubectl`, the Kubernetes CLI tool:\n\n```bash\n$ make kubeconfig\n```\n\nLet's test accessing the Kubernetes API and list the Kubernetes cluster nodes:\n\n```bash\n$ ./kubectl --context devkubernetes01 get nodes\nNAME                                                  STATUS   ROLES    AGE     VERSION\nkube-control-plane-0-instance.devkubernetes01.mesos   Ready    master   5m18s   v1.16.9\nkube-node-0-kubelet.devkubernetes01.mesos             Ready    <none>   2m58s   v1.16.9\n```\n\nAnd now, let's check how the system Kubernetes pods are doing:\n\n```bash\n$ ./kubectl --context devkubernetes01 -n kube-system get pods\nNAME                                                                          READY   STATUS    RESTARTS   AGE\ncalico-node-s9828                                                             2/2     Running   0          3m21s\ncalico-node-zc8qw                                                             2/2     Running   0          3m38s\ncoredns-6c7669957f-rvz85                                                      1/1     Running   0          3m38s\nkube-apiserver-kube-control-plane-0-instance.devkubernetes01.mesos            1/1     Running   0          4m43s\nkube-controller-manager-kube-control-plane-0-instance.devkubernetes01.mesos   1/1     Running   0          4m42s\nkube-proxy-kube-control-plane-0-instance.devkubernetes01.mesos                1/1     Running   0          4m48s\nkube-proxy-kube-node-0-kubelet.devkubernetes01.mesos                          1/1     Running   0          3m21s\nkube-scheduler-kube-control-plane-0-instance.devkubernetes01.mesos            1/1     Running   0          4m26s\nkubernetes-dashboard-5cbf45898-nkjsm                                          1/1     Running   0          3m37s\nlocal-dns-dispatcher-kube-node-0-kubelet.devkubernetes01.mesos                1/1     Running   0          3m21s\nmetrics-server-594576c7d8-cb4pj                                               1/1     Running   0          3m35s\n```\n\n### Accessing the Kubernetes Dashboard\n\nYou will be able to access the Kubernetes Dashboard by running:\n\n```bash\n$ kubectl --context devkubernetes01 proxy\n```\n\nThen pointing your browser at:\n\n```\nhttp://127.0.0.1:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/\n```\n\nPlease note that you will have to sign-in into the [Kubernetes Dashboard](https://docs.mesosphere.com/services/kubernetes/2.5.0-1.16.9/operations/kubernetes-dashboard/#login-view-and-authorization) before being able to perform any action.\n\n## Uninstall Kubernetes\n\nTo uninstall the DC/OS Kubernetes package while leaving your DC/OS cluster up,\nrun:\n\n```bash\n$ make uninstall\n```\n\n**NOTE:** This will only uninstall Kubernetes. Make sure you destroy your DC/OS\ncluster using the instructions below when you finish testing, or otherwise you\nwill need to delete all cloud resources manually!\n\n## Destroy cluster\n\nTo destroy the whole deployment:\n\n```bash\n$ make destroy\n```\n\nLast, clean generated resources:\n```bash\n$ make clean\n```\n\n## Documentation\n\nFor more details, please see the [docs folder](docs) and as well check the official [service docs](https://docs.mesosphere.com/service-docs/kubernetes/2.5.0-1.16.9)\n\n## Community\nGet help and connect with other users on the [mailing list](https://groups.google.com/a/dcos.io/forum/#!forum/kubernetes) or on DC/OS community [Slack](http://chat.dcos.io/) in the #kubernetes channel.\n"
  },
  {
    "path": "docs/aws.md",
    "content": "# AWS\n\n**WARNING:** When running this quickstart, you might experience some issues\nwith cloud resource limits. Please, verify your [quotas](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-resource-limits.html)\nbefore proceeding.\n\n## Install AWS CLI\n\nMake sure to have previously installed [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/installing.html).\n\n## Setup access\n\nFirst, you will need to [retrieve your AWS credentials](http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html).\nThe default location is `$HOME/.aws/credentials` on Linux and OS X, or `\"%USERPROFILE%\\.aws\\credentials\"` for Windows users.\n\nBefore proceeding, we recommend you create a file with your AWS credentials,\nexposed as (the commonly) recognized environment variables, so you can [`source`](http://tldp.org/HOWTO/Bash-Prompt-HOWTO/x237.html)\nit later, in between shell sessions:\n\n```bash\n$ cat << EOF > ~/.aws/my_credentials\nexport AWS_ACCESS_KEY_ID=<YOUR ACCESS KEY>\nexport AWS_SECRET_ACCESS_KEY=<YOUR SECRET KEY>\nEOF\n```\n\nLast, set-up SSH keys as detailed in [the official documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html#how-to-generate-your-own-key-and-import-it-to-aws).\n\nDon't forget to add your new SSH private key to your session:\n\n```bash\n$ ssh-add ~/.ssh/path_to_your_new_key.pem\n```\n\n## Prepare infrastructure configuration\n\nMake sure Terraform knows where to find your AWS credentials:\n\n```bash\n$ source ~/.aws/my_credentials\n```\n\nNow, let's generate the default infrastructure configuration:\n\n```bash\n$ make aws\n```\n\nThis will output sane defaults to `.deploy/terraform.tfvars`.\nNow, edit said file and set `ssh_public_key_file`, the public SSH key you will use to\nlog-in into your new VMs later.\n\n**WARNING:** Please, do not set a smaller instance (VM) type on the risk of\nfailing to install Kubernetes.\n\n```\ncluster_name = \"dcos-kubernetes\"\ncluster_name_random_string = true\n\ndcos_version = \"1.12.3\"\ndcos_security = \"strict\" # valid values are strict, permissive, disabled\n\nnum_of_masters = \"1\"\nnum_of_private_agents = \"4\"\nnum_of_public_agents = \"1\"\n\ninstance_os = \"centos_7.5\"\nbootstrap_instance_type = \"m5.large\"\nmaster_instance_type = \"m5.2xlarge\"\nprivate_agent_instance_type = \"m5.2xlarge\"\npublic_agent_instance_type = \"m5.2xlarge\"\n\naws_region = \"us-west-2\"\n# ssh_public_key_file = \"\"\n# aws_key_name = \"default\" # uncomment to use an already defined AWS key\n# admin_ips = \"0.0.0.0/0\" # uncomment to access master from any IP\n\n```\n\n### Kubernetes configuration\n\n#### Highly Available cluster\n\n**NOTE:** By default, it will provision a Kubernetes cluster with one (1) worker node, and\na single instance of every control plane component.\n\nTo deploy a **highly-available** cluster with three (3) private Kubernetes nodes update `.deploy/options.json`:\n\n```\n{\n  \"service\": {\n    \"name\": \"dev/kubernetes01\"\n  },\n  \"kubernetes\": {\n    \"high_availability\": true,\n    \"private_node_count\": 3\n  }\n}\n```\n\nLet's continue with [Kubernetes cluster configuration](../README.md#kubernetes-configuration).\n"
  },
  {
    "path": "docs/cncf_conformance.md",
    "content": "# CNCF Conformance\n\n## Prerequisites\n\nThe following prerequisites apply to follow these instructions. You will need:\n\n* A Linux or MacOS machine with\n  [Terraform 0.11.x](https://www.terraform.io/downloads.html) installed.\n* A [Google Cloud](gcp.md), or [AWS](aws.md) account with enough permissions to provide the needed\n  infrastructure\n\n## Preparation\n\n**NOTE:** These instructions are targeted at a\n[Google Cloud Platform](gcp.md) deployment. To deploy in [AWS](aws.md),\nplease run `make aws` instead of\n`make gcp` in the step below, and edit the resulting file accordingly.\n\n**NOTE:** To install `dcos-kubernetes` in an existing cluster, please follow\n[these instructions](existing_cluster.md).\n\nFirst, clone this repository:\n\n```shell\n$ git clone git@github.com:mesosphere/dcos-kubernetes-quickstart.git\n$ cd dcos-kubernetes-quickstart\n```\n\nThen generate the default infrastructure configuration:\n\n```shell\n$ make gcp\n```\n\nThis will output sane defaults to `.deploy/terraform.tfvars`. Now, edit\nsaid file and set the `gcp_project` and the `ssh_public_key_file` variables.\nPlease, do not set a smaller instance (VM) type on the risk of failing to\ninstall Kubernetes. In the end, the `.deploy/terraform.tfvars` file\nshould look something like this:\n\n```\ncluster_name = \"dcos-kubernetes\"\ncluster_name_random_string = true\n\ndcos_version = \"1.12.3\"\n\nnum_of_masters = \"1\"\nnum_of_private_agents = \"4\"\nnum_of_public_agents = \"1\"\n\nbootstrap_instance_type = \"n1-standard-1\"\nmaster_instance_type = \"n1-standard-8\"\nprivate_agent_instance_type = \"n1-standard-8\"\npublic_agent_instance_type = \"n1-standard-8\"\n\n# admin_ips = \"0.0.0.0/0\" # uncomment to access master from any IP\n\ngcp_project = \"YOUR_GCP_PROJECT\"\ngcp_region = \"us-central1\"\nssh_public_key_file = \"/PATH/YOUR_GCP_SSH_PUBLIC_KEY.pub\"\n#\n# If you want to use GCP service account key instead of GCP SDK\n# uncomment the line below and update it with the path to the key file\n# gcp_credentials = \"/PATH/YOUR_GCP_SERVICE_ACCOUNT_KEY.json\"\n#\n```\n\nNow, launch the DC/OS cluster by running:\n\n```shell\n$ KUBERNETES_VERSION=1.16.9 make get-cli launch-dcos setup-cli\n```\n\nThis command will:\n\n1. Download the `dcos` CLI and `kubectl` to your machine.\n1. Provision the necessary infrastructure in GCP and install DC/OS.\n1. Setup the `dcos` CLI to access the newly created DC/OS cluster.\n\nAs part of the last step, your browser will open and ask you to login with\na Google, GitHub or Microsoft account. Choose an option and copy the resulting\nOpenID token to the shell where you ran the above mentioned command.\n\n## Installing Mesosphere Kubernetes Engine\n\nTo install Mesosphere Kuberentes Engine and create a Kubernetes cluster in the newly created DC/OS cluster run:\n\n```shell\n$ KUBERNETES_FRAMEWORK_VERSION=2.5.0-1.16.9 \\\n  PATH_TO_PACKAGE_OPTIONS=./resources/options-ha.json make install\n```\n\nWait until all tasks are running before proceeding.\nYou can track installation progress as follows:\n\n```shell\n$ make watch-kubernetes-cluster\n```\n\nWhen installation is successful you will see the following output:\n\n```\nUsing Kubernetes cluster: dev/kubernetes01\ndeploy (serial strategy) (COMPLETE)\n   etcd (serial strategy) (COMPLETE)\n      etcd-0:[peer] (COMPLETE)\n      etcd-1:[peer] (COMPLETE)\n      etcd-2:[peer] (COMPLETE)\n   control-plane (dependency strategy) (COMPLETE)\n      kube-control-plane-0:[instance] (COMPLETE)\n      kube-control-plane-1:[instance] (COMPLETE)\n      kube-control-plane-2:[instance] (COMPLETE)\n   mandatory-addons (serial strategy) (COMPLETE)\n      mandatory-addons-0:[instance] (COMPLETE)\n   node (dependency strategy) (COMPLETE)\n      kube-node-0:[kubelet] (COMPLETE)\n      kube-node-1:[kubelet] (COMPLETE)\n      kube-node-2:[kubelet] (COMPLETE)\n   public-node (dependency strategy) (COMPLETE)\n```\n\nWhen all tasks are in state `COMPLETE`, press `Ctrl-C` to terminate the `watch`\nprocess and proceed to access your Kubernetes cluster.\n\n## Accessing the Kubernetes API\n\nIn order to access the Kubernetes API from outside the DC/OS cluster, we must\nfirst be able to access it. This can be achieved by running the following\ncommand:\n\n```shell\n$ make marathon-lb kubeconfig\n```\n\nThis command will expose the Kubernetes API for our newly created Kubernetes cluster, and configure `kubectl` to access said Kubernetes cluster.\nLet's try and list this cluster's nodes:\n\n```shell\n$ ./kubectl --context devkubernetes01 get nodes\nNAME                                                  STATUS   ROLES    AGE     VERSION\nkube-control-plane-0-instance.devkubernetes01.mesos   Ready    master   5m18s   v1.16.9\nkube-control-plane-1-instance.devkubernetes01.mesos   Ready    master   5m12s   v1.16.9\nkube-control-plane-2-instance.devkubernetes01.mesos   Ready    master   5m11s   v1.16.9\nkube-node-0-kubelet.devkubernetes01.mesos             Ready    <none>   2m58s   v1.16.9\nkube-node-1-kubelet.devkubernetes01.mesos             Ready    <none>   2m42s   v1.16.9\nkube-node-2-kubelet.devkubernetes01.mesos             Ready    <none>   2m39s   v1.16.9\n```\n\nIf the output is similar to what is shown above, you're good to go and run the\nconformance test suite.\n\n## Running the test suite\n\nTo run the test suite and grab the results, follow the\n[official instructions](https://github.com/cncf/k8s-conformance/blob/master/instructions.md).\n\n## Destroy the infrastructure\n\nIn order to delete the DC/OS cluster created above, run:\n\n```shell\n$ make destroy\n```\n"
  },
  {
    "path": "docs/existing_cluster.md",
    "content": "# Existing Cluster\n\nIf you already have a DC/OS 1.11+ cluster, Kubernetes is publicly available in the Catalog.\n\nBefore proceeding, make sure your cluster fulfils the [Kubernetes package default requirements](https://docs.mesosphere.com/services/kubernetes/2.5.0-1.16.9/getting-started/install-basic/#prerequisites).\n\nThen, install is as easy as:\n\n```shell\n$ dcos package install kubernetes\n```\n\n## Kubernetes configuration\n\n**NOTE:** By default, it will provision a Kubernetes cluster with one (1) private worker node, and\na single instance of every control plane component.\n\nTo deploy a **highly-available** cluster with three (3) private and one (1) public workers node update, run:\n\n```shell\n$ dcos package install --options=./resources/options-ha.json kubernetes\n```\n"
  },
  {
    "path": "docs/exposing_kubernetes_api.md",
    "content": "# Exposing the Kubernetes API\n\nDC/OS Kubernetes doesn’t automatically expose the Kubernetes API outside of the DC/OS cluster.\nIt can be achieved using Marathon-LB and dummy marathon application.\n\n## Using Marathon-LB instance\n\nMarathon-LB instance and dummy `kubeapi-proxy` marathon application get installed as part of Kubernetes\nframework install. This allows to expose Kubernetes API via DC/OS public agent IP.\n\nThe dummy Marathon application `kubeapi-proxy` definition:\n\n```json\n{\n  \"id\": \"/kubeapi-proxy\",\n  \"instances\": 1,\n  \"cpus\": 0.001,\n  \"mem\": 16,\n  \"cmd\": \"tail -F /dev/null\",\n  \"container\": {\n    \"type\": \"MESOS\"\n  },\n  \"portDefinitions\": [\n    {\n      \"protocol\": \"tcp\",\n      \"port\": 0\n    }\n  ],\n  \"labels\": {\n    \"HAPROXY_GROUP\": \"external\",\n    \"HAPROXY_0_MODE\": \"http\",\n    \"HAPROXY_0_PORT\": \"6443\",\n    \"HAPROXY_0_SSL_CERT\": \"/etc/ssl/cert.pem\",\n    \"HAPROXY_0_BACKEND_SERVER_OPTIONS\": \"  timeout connect 10s\\n  timeout client 86400s\\n  timeout server 86400s\\n  timeout tunnel 86400s\\n  server kube-apiserver apiserver.devkubernetes01.l4lb.thisdcos.directory:6443 ssl verify none\\n\"   \n  }\n}\n```\n\nHere is how this works:\n1. Marathon-LB identifies that the application `kubeapi-proxy` has the `HAPROXY_GROUP` label set to `external` (change this if you're using a different `HAPROXY_GROUP` for your Marathon-LB configuration).\n1. The `instances`, `cpus`, `mem`, `cmd`, and `container` fields basically create a dummy container that takes up minimal space and performs no operation.\n1. The single port indicates that this application has one \"port\" (this information is used by Marathon-LB)\n1. `\"HAPROXY_0_MODE\": \"http\"` indicates to Marathon-LB that the frontend and backend configuration for this particular service should be configured with `http`.\n1. `\"HAPROXY_0_PORT\": \"6443\"` tells Marathon-LB to expose the service on port 6443 (rather than the randomly-generated service port, which is ignored)\n1. `\"HAPROXY_0_SSL_CERT\": \"/etc/ssl/cert.pem\"` tells Marathon-LB to expose the service with the self-signed Marathon-LB certificate (which has **no CN**)\n1. The last label `HAPROXY_0_BACKEND_SERVER_OPTIONS` indicates that Marathon-LB should forward traffic to the endpoint `apiserver.kubernetes.l4lb.thisdcos.directory:6443` rather than to the dummy application, and that the connection should be made using TLS without verification.\n\nFor more options of exposing Kubernetes API, please check the [documentation](https://docs.mesosphere.com/services/kubernetes/2.5.0-1.16.9/operations/exposing-the-kubernetes-api/).\n"
  },
  {
    "path": "docs/gcp.md",
    "content": "# Google Cloud\n\n**WARNING**: When running this quickstart, you might experience some issues\nwith cloud resource limits. Please, verify your [quotas](https://cloud.google.com/compute/quotas)\nbefore proceeding.\n\n## Install Google Cloud SDK\n\nMake sure to have previously installed [Google Cloud SDK](https://cloud.google.com/sdk/downloads).\n\n### Setup access\n\nFirst, you need to retrieve the credentials needed for Terraform to manage your\nGoogle Cloud resources:\n\n```bash\n$ gcloud auth login\n$ gcloud auth application-default login\n```\n\n## Google Cloud Service Account\n\nIf you want to use GCP Service Account key instead of GCP SDK, uncomment the line as shown below in `desired_cluster_profile` and update it with the path to the ssh key file:\n\n```\n...\ngcp_credentials_key_file = \"/PATH/YOUR_GCP_SERVICE_ACCOUNT_KEY.json\"\n...\n\n```\n\n## Setup SSH key\n\nNext, you need to setup SSH as per [official GCP documentation](https://cloud.google.com/compute/docs/instances/adding-removing-ssh-keys) if you setup Google Cloud SDK or Google Cloud Service Account.\n\nAdd the SSH private key:\n\n```bash\n$ ssh-add ~/.ssh/google_compute_engine\n```\n\nLater, you will be asked to add the SSH public key to the Terraform cluster profile.\n\n## Infrastructure configuration\n\nLet's  move on to [infrastructure configuration](../README.md#prepare-infrastructure-configuration).\n"
  },
  {
    "path": "examples/README.md",
    "content": "# Overview\n\nA collection of examples to run Kubernetes workloads on DC/OS.\n\n* [OS Detector](os-detector/os-detector.md)"
  },
  {
    "path": "examples/os-detector/cassandra-cql.json",
    "content": "{\n  \"id\": \"/cassandra-cql\",\n  \"instances\": 1,\n  \"portDefinitions\": [],\n  \"container\": {\n    \"type\": \"MESOS\",\n    \"volumes\": [],\n    \"docker\": {\n      \"image\": \"cassandra:3.0.13\"\n    }\n  },\n  \"cpus\": 0.1,\n  \"mem\": 256,\n  \"requirePorts\": false,\n  \"networks\": [],\n  \"healthChecks\": [],\n  \"fetch\": [],\n  \"constraints\": [],\n  \"cmd\": \"while true; do sleep 1000000; done\"\n}\n"
  },
  {
    "path": "examples/os-detector/cassandra.json",
    "content": "{\n    \"nodes\": {\n        \"count\": 3,\n        \"seeds\": 2\n    }\n}"
  },
  {
    "path": "examples/os-detector/os-detector.md",
    "content": "# Kubernetes + Cassandra\n\nThis sample application will walk through\n\n* Deploying a Cassandra cluster on DC/OS\n* Deploying a web application on Kubernetes, that reads/writes data in Cassandra, over the DC/OS network\n\n## Pre-Requisites\n\n* A DC/OS 1.11+ cluster, with at least 4 private nodes\n* Kubernetes running on DC/OS\n* [Configured kubectl](https://github.com/mesosphere/dcos-kubernetes-quickstart#installing-kubectl)\n\n## OS Detector\n\nWe are going to deploy a web application that counts the number of operating systems that visit the site.  First, deploy a 3 node Cassandra cluster onto DC/OS.\n\n```\n# TODO: CHANGE THE NAME ONCE THE NEW SDK PACKAGE GOES LIVE\ndcos package install cassandra\n```\n\nWe need to set up the Cassandra keyspace and table so let's start the `csql` terminal.\nDeploy the following marathon app definition (e.g., using `dcos marathon app add https://raw.githubusercontent.com/mesosphere/dcos-kubernetes-quickstart/master/examples/os-detector/cassandra-cql.json`).\n\n```json\n{\n  \"id\": \"/cassandra-cql\",\n  \"instances\": 1,\n  \"portDefinitions\": [],\n  \"container\": {\n    \"type\": \"MESOS\",\n    \"volumes\": [],\n    \"docker\": {\n      \"image\": \"cassandra:3.0.13\"\n    }\n  },\n  \"cpus\": 0.1,\n  \"mem\": 256,\n  \"requirePorts\": false,\n  \"networks\": [],\n  \"healthChecks\": [],\n  \"fetch\": [],\n  \"constraints\": [],\n  \"cmd\": \"while true; do sleep 1000000; done\"\n}\n```\n\nNext, let us connect to that container using the DC/OS CLI and connect to Cassandra:\n\n```bash\ndcos task exec -it cassandra-cql bash\n\ncqlsh node-0-server.cassandra.autoip.dcos.thisdcos.directory\n```\n\nOnce connected to Cassandra, create the keyspace and table\n\n```\nCREATE KEYSPACE browsers WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };\n\nCREATE TABLE browsers.browser_counts (\n  counter counter,\n  os varchar,\n  PRIMARY KEY (os)\n);\n```\n\nNow we are ready to deploy our application via Kubernetes.  The example manifest will create a deployment, as well as a `NodePort` service so we can access the application from outside the cluster.\n\n```\nkubectl apply -f https://raw.githubusercontent.com/mesosphere/dcos-kubernetes-quickstart/master/examples/os-detector/os-detector.yaml\n```\n\nFrom here, the application is deployed, and available at port `31000` on the nodes which Kubernetes is running.  Ensure your firewall is allowing traffic on that port, and you can navigate to your browser to interact with the app.\n\n![](../../docs/assets/os-detector.gif)\n"
  },
  {
    "path": "examples/os-detector/os-detector.yaml",
    "content": "apiVersion: apps/v1beta1\nkind: Deployment\nmetadata:\n  name: osdetect\nspec:\n  replicas: 10\n  template:\n    metadata:\n      name: osdetector\n      labels:\n        app: osdetector\n    spec:\n      containers:\n      - name: osdetector\n        image: smugcloud/osdetector:blue\n        imagePullPolicy: Always\n        args: [\"--cassandra-host\", \"node.cassandra.l4lb.thisdcos.directory:9042\"]\n        ports:\n        - containerPort: 8080\n---\n\nkind: Service\napiVersion: v1\nmetadata:\n  name: osdetect\nspec:\n  selector:\n    app: osdetector\n  ports:\n    - protocol: TCP\n      port: 80\n      targetPort: 8080\n      nodePort: 31000\n  type: NodePort"
  },
  {
    "path": "resources/desired_cluster_profile.aws.tfvars",
    "content": "cluster_name = \"dcos-kubernetes\"\ncluster_name_random_string = true\n\ndcos_version = \"1.12.3\"\ndcos_security = \"strict\" # valid values are strict, permissive, disabled\n\nnum_of_masters = \"1\"\nnum_of_private_agents = \"4\"\nnum_of_public_agents = \"1\"\n\nbootstrap_instance_type = \"m5.large\"\nmaster_instance_type = \"m5.2xlarge\"\nprivate_agent_instance_type = \"m5.2xlarge\"\npublic_agent_instance_type = \"m5.2xlarge\"\n\naws_region = \"us-west-2\"\n# ssh_public_key_file = \"\"\n# aws_key_name = \"default\" # uncomment to use an already defined AWS key\n# admin_ips = \"0.0.0.0/0\" # uncomment to access master from any IP\n"
  },
  {
    "path": "resources/desired_cluster_profile.gcp.tfvars",
    "content": "cluster_name = \"dcos-kubernetes\"\ncluster_name_random_string = true\n\ndcos_version = \"1.12.3\"\ndcos_security = \"strict\" # valid values are strict, permissive, disabled\n\nnum_of_masters = \"1\"\nnum_of_private_agents = \"4\"\nnum_of_public_agents = \"1\"\n\nbootstrap_instance_type = \"n1-standard-1\"\nmaster_instance_type = \"n1-standard-8\"\nprivate_agent_instance_type = \"n1-standard-8\"\npublic_agent_instance_type = \"n1-standard-8\"\n\n# admin_ips = \"0.0.0.0/0\" # uncomment to access master from any IP\n\ngcp_project = \"YOUR_GCP_PROJECT\"\ngcp_region = \"us-central1\"\nssh_public_key_file = \"/PATH/YOUR_GCP_SSH_PUBLIC_KEY.pub\"\n#\n# If you want to use GCP service account key instead of GCP SDK\n# uncomment the line below and update it with the path to the key file\n# gcp_credentials = \"/PATH/YOUR_GCP_SERVICE_ACCOUNT_KEY.json\"\n#\n"
  },
  {
    "path": "resources/kubeapi-proxy.json",
    "content": "{\n  \"id\": \"/kubeapi-proxy\",\n  \"instances\": 1,\n  \"cpus\": 0.001,\n  \"mem\": 16,\n  \"cmd\": \"tail -F /dev/null\",\n  \"container\": {\n    \"type\": \"MESOS\"\n  },\n  \"portDefinitions\": [\n    {\n      \"protocol\": \"tcp\",\n      \"port\": 0\n    }\n  ],\n  \"labels\": {\n    \"HAPROXY_0_MODE\": \"http\",\n    \"HAPROXY_GROUP\": \"external\",\n    \"HAPROXY_0_SSL_CERT\": \"/etc/ssl/cert.pem\",\n    \"HAPROXY_0_PORT\": \"6443\",\n    \"HAPROXY_0_BACKEND_SERVER_OPTIONS\": \"  timeout connect 10s\\n  timeout client 86400s\\n  timeout server 86400s\\n  timeout tunnel 86400s\\n  server kube-apiserver apiserver.devkubernetes01.l4lb.thisdcos.directory:6443 ssl verify none\\n\"\n  }\n}\n"
  },
  {
    "path": "resources/main.aws.tf",
    "content": "data \"http\" \"whatismyip\" {\n  url = \"http://whatismyip.akamai.com/\"\n}\n\nlocals {\n  dcos_admin_ips = \"${split(\" \", var.admin_ips == \"\" ? \"${data.http.whatismyip.body}/32\" : var.admin_ips)}\"\n}\n\nprovider \"aws\" {\n  region = \"${var.aws_region}\"\n}\n\nmodule \"dcos\" {\n  source  = \"dcos-terraform/dcos/aws\"\n  version = \"~> 0.2.0\"\n\n  providers = {\n    aws = \"aws\"\n  }\n\n  cluster_name = \"${var.cluster_name}\"\n  cluster_name_random_string = \"${var.cluster_name_random_string}\"\n\n  num_masters = \"${var.num_of_masters}\"\n  num_private_agents = \"${var.num_of_private_agents}\"\n  num_public_agents = \"${var.num_of_public_agents}\"\n\n  dcos_version = \"${var.dcos_version}\"\n  dcos_variant = \"open\"\n  dcos_security = \"${var.dcos_security}\"\n  dcos_instance_os = \"${var.instance_os}\"\n\n  bootstrap_instance_type = \"${var.bootstrap_instance_type}\"\n  masters_instance_type = \"${var.master_instance_type}\"\n  private_agents_instance_type = \"${var.private_agent_instance_type}\"\n  public_agents_instance_type = \"${var.public_agent_instance_type}\"\n\n  admin_ips = \"${local.dcos_admin_ips}\"\n  aws_key_name = \"${var.aws_key_name}\"\n  ssh_public_key_file = \"${var.ssh_public_key_file}\"\n\n  public_agents_additional_ports = [\"6443\"]\n}"
  },
  {
    "path": "resources/main.gcp.tf",
    "content": "data \"http\" \"whatismyip\" {\n  url = \"http://whatismyip.akamai.com/\"\n}\n\nlocals {\n  dcos_admin_ips = \"${split(\" \", var.admin_ips == \"\" ? \"${data.http.whatismyip.body}/32\" : var.admin_ips)}\"\n}\n\nprovider \"google\" {\n  version = \"~> 1.18.0\"\n\n  credentials = \"${var.gcp_credentials}\"\n  project = \"${var.gcp_project}\"\n  region = \"${var.gcp_region}\"\n  zone = \"${var.gcp_zone}\"\n}\n\nmodule \"dcos\" {\n  source  = \"dcos-terraform/dcos/gcp\"\n  version = \"~> 0.1.0\"\n\n  providers = {\n    google = \"google\"\n  }\n\n  cluster_name = \"${var.cluster_name}\"\n  cluster_name_random_string = \"${var.cluster_name_random_string}\"\n\n  num_masters = \"${var.num_of_masters}\"\n  num_private_agents = \"${var.num_of_private_agents}\"\n  num_public_agents = \"${var.num_of_public_agents}\"\n\n  dcos_version = \"${var.dcos_version}\"\n  dcos_variant = \"open\"\n  dcos_security = \"${var.dcos_security}\"\n  dcos_instance_os = \"${var.instance_os}\"\n\n  bootstrap_machine_type = \"${var.bootstrap_machine_type}\"\n  masters_machine_type = \"${var.master_machine_type}\"\n  private_agents_machine_type = \"${var.private_agent_machine_type}\"\n  public_agents_machine_type = \"${var.public_agent_machine_type}\"\n\n  admin_ips = \"${local.dcos_admin_ips}\"\n  ssh_public_key_file = \"${var.ssh_public_key_file}\"\n\n  public_agents_additional_ports = [\"6443\"]\n\n  dcos_resolvers = <<EOF\n# YAML\n  - 169.254.169.254\nEOF\n}"
  },
  {
    "path": "resources/options-ha.json",
    "content": "{\n  \"service\": {\n    \"name\": \"dev/kubernetes01\"\n  },\n  \"kubernetes\": {\n    \"authorization_mode\": \"RBAC\",\n    \"high_availability\": true,\n    \"private_node_count\": 3\n  }\n}\n"
  },
  {
    "path": "resources/options.json",
    "content": "{\n  \"service\": {\n    \"name\": \"dev/kubernetes01\"\n  },\n  \"kubernetes\": {\n    \"authorization_mode\": \"RBAC\"\n  }\n}"
  },
  {
    "path": "resources/outputs.tf",
    "content": "\noutput \"masters-ips\" {\n  value = \"${module.dcos.masters-ips}\"\n}\n\noutput \"cluster-address\" {\n  value = \"${module.dcos.masters-loadbalancer}\"\n}\n\noutput \"public-agents-loadbalancer\" {\n  value = \"${module.dcos.public-agents-loadbalancer}\"\n}"
  },
  {
    "path": "resources/variables.aws.tf",
    "content": "variable \"cluster_name\" {\n  description = \"Name of the DC/OS cluster\"\n  default     = \"dcos-kubernetes\"\n}\n\nvariable \"cluster_name_random_string\" {\n  description = \"Add a random string to the cluster name\"\n  default     = true\n}\n\nvariable \"ssh_public_key_file\" {\n  description = \"Path to SSH public key. This is mandatory.\"\n  default = \"\"\n}\n\nvariable \"aws_key_name\" {\n  description = \"Specify the aws ssh key to use. We assume its already loaded in your SSH agent.\"\n  default     = \"default\"\n}\n\nvariable \"aws_region\" {\n  description = \"Region to be used\"\n  default = \"us-west-2\"\n}\n\nvariable \"admin_ips\" {\n  description = \"List of CIDR admin IPs (space separated)\"\n  default     = \"\"\n}\n\nvariable \"dcos_version\" {\n  default     = \"1.12.3\"\n  description = \"specifies which dcos version instruction to use. Options: `1.9.0`, `1.8.8`, etc. _See [dcos_download_path](https://github.com/dcos/tf_dcos_core/blob/master/download-variables.tf) or [dcos_version](https://github.com/dcos/tf_dcos_core/tree/master/dcos-versions) tree for a full list._\"\n}\n\nvariable \"dcos_security\" {\n  default     = \"permissive\"\n  description = \"[Enterprise DC/OS] set the security level of DC/OS. Default is strict. (recommended)\"\n}\n\nvariable \"num_of_public_agents\" {\n  default = \"0\"\n}\n\nvariable \"num_of_private_agents\" {\n  default = \"4\"\n}\n\nvariable \"num_of_masters\" {\n  default     = \"1\"\n  description = \"set the num of master nodes (required with exhibitor_storage_backend set to aws_s3, azure, ZooKeeper)\"\n}\n\nvariable \"instance_os\" {\n  description = \"Operating system to use.\"\n  default = \"centos_7.5\"\n}\n\nvariable \"bootstrap_instance_type\" {\n  description = \"[BOOTSTRAP] Machine type\"\n  default     = \"m5.large\"\n}\n\nvariable \"master_instance_type\" {\n  description = \"[MASTERS] Machine type\"\n  default     = \"m5.2xlarge\"\n}\n\nvariable \"private_agent_instance_type\" {\n  description = \"[PRIVATE AGENTS] Machine type\"\n  default     = \"m5.2xlarge\"\n}\n\nvariable \"public_agent_instance_type\" {\n  description = \"[PUBLIC AGENTS] Machine type\"\n  default     = \"m5.2xlarge\"\n}\n"
  },
  {
    "path": "resources/variables.gcp.tf",
    "content": "variable \"cluster_name\" {\n  description = \"Name of the DC/OS cluster\"\n  default     = \"dcos-kubernetes\"\n}\n\nvariable \"cluster_name_random_string\" {\n  description = \"Add a random string to the cluster name\"\n  default     = true\n}\n\nvariable \"ssh_public_key_file\" {\n  description = \"Path to SSH public key. This is mandatory.\"\n  default = \"\"\n}\n\nvariable \"gcp_credentials\" {\n  description = \"Either the path to or the contents of a service account key file in JSON format. You can manage key files using the Cloud Console.\"\n  default = \"\"\n}\n\nvariable \"gcp_project\" {\n  description = \"The default project to manage resources in. If another project is specified on a resource, it will take precedence.\"\n  default = \"\"\n}\n\nvariable \"gcp_region\" {\n  description = \"The default region to manage resources in. If another region is specified on a regional resource, it will take precedence.\"\n  default = \"\"\n}\n\nvariable \"gcp_zone\" {\n  description = \"The default zone to manage resources in. Generally, this zone should be within the default region you specified. If another zone is specified on a zonal resource, it will take precedence.\"\n  default = \"\"\n}\n\nvariable \"admin_ips\" {\n  description = \"List of CIDR admin IPs (space separated)\"\n  default     = \"\"\n}\n\nvariable \"dcos_version\" {\n  default     = \"1.12.3\"\n  description = \"specifies which dcos version instruction to use. Options: `1.9.0`, `1.8.8`, etc. _See [dcos_download_path](https://github.com/dcos/tf_dcos_core/blob/master/download-variables.tf) or [dcos_version](https://github.com/dcos/tf_dcos_core/tree/master/dcos-versions) tree for a full list._\"\n}\n\nvariable \"dcos_security\" {\n  default     = \"permissive\"\n  description = \"[Enterprise DC/OS] set the security level of DC/OS. Default is strict. (recommended)\"\n}\n\nvariable \"num_of_public_agents\" {\n  default = \"0\"\n}\n\nvariable \"num_of_private_agents\" {\n  default = \"4\"\n}\n\nvariable \"num_of_masters\" {\n  default     = \"1\"\n  description = \"set the num of master nodes (required with exhibitor_storage_backend set to aws_s3, azure, ZooKeeper)\"\n}\n\nvariable \"instance_os\" {\n  description = \"Operating system to use.\"\n  default = \"centos_7.5\"\n}\n\nvariable \"bootstrap_machine_type\" {\n  description = \"[BOOTSTRAP] Machine type\"\n  default     = \"n1-standard-1\"\n}\n\nvariable \"master_machine_type\" {\n  description = \"[MASTERS] Machine type\"\n  default     = \"n1-standard-8\"\n}\n\nvariable \"private_agent_machine_type\" {\n  description = \"[PRIVATE AGENTS] Machine type\"\n  default     = \"n1-standard-8\"\n}\n\nvariable \"public_agent_machine_type\" {\n  description = \"[PUBLIC AGENTS] Machine type\"\n  default     = \"n1-standard-8\"\n}\n"
  },
  {
    "path": "scripts/get_cli",
    "content": "#!/bin/bash\n\n# download dcos and kubectl CLI tools\n\n# check OS version\nunamestr=`uname`\nif [[ \"$unamestr\" == \"Linux\" ]]\nthen\n  OS=\"linux\"\nelse\n  OS=\"darwin\"\nfi\n\n#\necho \"Downloading dcos v$DCOS_CLI_VERSION cli for $OS\"\ncurl -o dcos https://downloads.dcos.io/binaries/cli/$OS/x86-64/dcos-$DCOS_CLI_VERSION/dcos\nchmod +x dcos\necho\n#\necho \"Downloading kubectl $KUBERNETES_VERSION for $OS\"\ncurl -LO https://storage.googleapis.com/kubernetes-release/release/v$KUBERNETES_VERSION/bin/$OS/amd64/kubectl\nchmod +x kubectl\necho \"Download has finished !!!\"\necho\n"
  },
  {
    "path": "scripts/poll_api.sh",
    "content": "#!/bin/bash\n\nAPI_NAME=$1\nAPI_IP=$2\nAPI_PORT=$3\n\necho \" \"\necho \"Waiting for ${API_NAME} to be ready...\"\nif [[ \"${API_NAME}\" = \"Kubernetes API\" ]]\nthen\n  until curl -o /dev/null -skIf -w \"%{http_code}\" https://${API_IP}:${API_PORT} | grep -w \"401\\|403\" >/dev/null 2>&1; do sleep 1; done\nelse\n  until curl -o /dev/null -skIf https://${API_IP}:${API_PORT}; do sleep 1; done\nfi\necho\n"
  }
]