diff --git a/README.md b/README.md index 9322706..e76831e 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,28 @@ --- page_type: sample languages: -- csharp +- bash products: -- dotnet -description: "Add 150 character max description" -urlFragment: "update-this-to-unique-url-stub" +- azure, azure kubernetes service +description: "Application to demo AKS features" +urlFragment: "aks-demos" --- -# Official Microsoft Sample +# Set up an Azure Kubernetes Service cluster to test out new features - - -Give a short description for your sample here. What does it do and why is it important? +This samples shows you how to set up an Azure Kubernetes Cluster and enable features such as Azure Policy, Azure Security Center, Windows Containers for AKS, and Virtual Nodes. ## Contents -Outline the file contents of the repository. It helps users navigate the codebase, build configuration and any related assets. - | File/folder | Description | |-------------------|--------------------------------------------| -| `src` | Sample source code. | +| `azure-policy` | Sample code and instructions to set up a Kubernetes cluster and enable Azure Policy | +| `azure-security-center` | Sample code and instructions to set up a Kubernetes cluster and enable Azure Security Center | +| `private-clusters` | Sample code and instructions to set up a Kubernetes cluster and enable private clusters | +| `virtual-node-autoscale` | Sample code and instructions to set up a Kubernetes cluster and enable virtual node. | +| `windows-demo` | Sample code and instructions to set up a Kubernetes cluster and enable Windows containers for AKS | `.gitignore` | Define what to ignore at commit time. | | `CHANGELOG.md` | List of changes to the sample. | | `CONTRIBUTING.md` | Guidelines for contributing to the sample. | @@ -35,19 +31,7 @@ Outline the file contents of the repository. It helps users navigate the codebas ## Prerequisites -Outline the required components and tools that a user might need to have on their machine in order to run the sample. This can be anything from frameworks, SDKs, OS versions or IDE releases. - -## Setup - -Explain how to prepare the sample once the user clones or downloads the repository. The section should outline every step necessary to install dependencies and set up any settings (for example, API keys and output folders). - -## Running the sample - -Outline step-by-step instructions to execute the sample and see its output. Include steps for executing the sample from the IDE, starting specific services in the Azure portal or anything related to the overall launch of the code. - -## Key concepts - -Provide users with more context on the tools and services used in the sample. Explain some of the code that is being used and how services interact with each other. +The samples assume that you have an Azure subscription and a terminal to run the bash scripts for setup. Some samples have additional prequisites that are outline in their respective READMEs. ## Contributing diff --git a/azure-policy/Azure Policy for AKS.jpg b/azure-policy/Azure Policy for AKS.jpg new file mode 100644 index 0000000..a324dd4 Binary files /dev/null and b/azure-policy/Azure Policy for AKS.jpg differ diff --git a/azure-policy/README.md b/azure-policy/README.md new file mode 100644 index 0000000..acb822a --- /dev/null +++ b/azure-policy/README.md @@ -0,0 +1,52 @@ +**Azure Policy for Azure Kubernetes Service** + +:::image type="content" source="../../aks-demos/azure-policy/Azure Policy for AKS.jpg" alt-text="Azure Policy for AKS Diagram"::: + +**Setup** + +To setup the demo, you can run the setup.sh script in this folder (remember that the CLI commands for Azure Policy are in preview and aren't yet reliable), or you can use the azure-policy context in the provided KUBECONFIG. + +If you want to setup your own environment: +- Join the private preview +- Create an AKS cluster +- Create a policy assignment for "Do not allow privileged container in AKS" +- Enable policy add-on for your cluster +- Profit + +**Walkthrough** + +In this demo, we'll be going over enabling policy for an existing AKS cluster, and then trying to deploy a container that disobeys that policy. +Moving forward, this demo assumes you have an existing cluster and that you've been whitelisted for private preview. + +First, enable the azure-policy add-on for your cluster. You can do this through portal. Navigate to your AKS cluster, and select Policy from the right-hand toolbar. Now, hit 'Enable add-on'. (Note: you need to be anable for the private preview for Azure Policy for AKS and have your subscription whitelisted.) + +Now, navigate to Policy in Azure Portal. If you haven't joined preview, you can do so on this page. Click on definitions. Notice that here you can see all of the policy definitions so far in use in your subscription. Here you can see that I just have the basic assignments from my security center subscription. + +Now, we're going to go ahead and create a new policy assignment. We're going to filter by Kubernetes Service and take a look at all of the different built-definitions that we can apply. + +Let's go with 'Do not allow privileged containers in AKS. We're going to set the scope to be the resource group our AKS cluster resides in. Make sure that Azure Policy is going to enforce this policy in our cluster. And create! ***If you're running the live demo, just walk through the process. You've already creating the policy assignment through the demo setup*** + +Now, let's see what's going on in our cluster. + +``` +kubectl get pods -o wide --all-namespaces +``` + +You'll notice that we now have a Azure Policy pod running the cluster. This is what's going to enforce our policy definition in our cluster. To demonstrate this, I'm going to try to deploy a privileged container in the cluster. + +First, let's take a look at what's in here. + +``` +cat privileged-container.yaml +# or if you're using cmd +type privileged-container.yaml +``` + +Now, let's try to deploy it. +``` +kubectl create -f privileged-container.yaml +``` + +And you'll see that Azure Policy stops the operation from being carried through. + + diff --git a/azure-policy/privileged-container.yaml b/azure-policy/privileged-container.yaml new file mode 100644 index 0000000..a46352e --- /dev/null +++ b/azure-policy/privileged-container.yaml @@ -0,0 +1,13 @@ +# Privileged container +apiVersion: v1 +kind: Pod +metadata: + name: privileged-container + labels: + name: kube-system-container +spec: + containers: + - name: privileged-container + image: nginx + securityContext: + privileged: true \ No newline at end of file diff --git a/azure-policy/setup.sh b/azure-policy/setup.sh new file mode 100644 index 0000000..9af1175 --- /dev/null +++ b/azure-policy/setup.sh @@ -0,0 +1,22 @@ +# To set-up this demo, do the following: + +# Join preview for Azure Policy with AKS +# Create an AKS cluster +# Add a 'Do not allow privileged containers' policy on the cluster +# Wait for the policy to create (15 minutes) +# Enable Policy Add-on for the cluster + +# Creating resource group +az group create -g azure-policy-rg -l westus + +# Creating cluster +az aks create -n azure-policy -g azure-policy-rg --node-count 1 + +# Enable Azure Policy on this cluster +az aks enable-addons --addons azure-policy --name azure-policy --resource-group azure-policy-rg + +# Creating policy +subscription_id=$(az account show -o json --query id) +scope=/subscriptions/$subscription_id/resourceGroups/azure-policy-rg +az policy assignment create --name 'no-privileged-containers' --display-name '[Limited Preview]: Do not allow privileged containers in AKS' --scope scope --policy '/providers/Microsoft.Authorization/policyDefinitions/7ce7ac02-a5c6-45d6-8d1b-844feb1c1531"' +az aks enable-addons --addons azure-policy --name azure-policy --resource-group azure-policy-rg \ No newline at end of file diff --git a/azure-security-center/ASC-Trigger-AKS-Alerts.yaml b/azure-security-center/ASC-Trigger-AKS-Alerts.yaml new file mode 100644 index 0000000..14da60f --- /dev/null +++ b/azure-security-center/ASC-Trigger-AKS-Alerts.yaml @@ -0,0 +1,91 @@ +# This YAML triggers alerts for AKS detection in Azure Security Center + +# kube-system container +apiVersion: v1 +kind: Pod +metadata: + name: kube-system-container + namespace: kube-system + labels: + name: kube-system-container +spec: + containers: + - name: kube-system-container + image: nginx + +--- + +# Privileged container +apiVersion: v1 +kind: Pod +metadata: + name: privileged-container + labels: + name: kube-system-container +spec: + containers: + - name: privileged-container + image: nginx + securityContext: + privileged: true + +--- + +# Sensitive mounts +apiVersion: v1 +kind: Pod +metadata: + name: sensitive-mount-container + labels: + name: sensitive-mount-container +spec: + containers: + - name: sensitive-mount-container + image: nginx + volumeMounts: + - name: sensitivemount + mountPath: /sensitive + volumes: + - name: sensitivemount + hostPath: + path: /etc + +--- + +# High privileges role +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: high-privileges-role +rules: +- apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' + +--- + +# Create a new service account +apiVersion: v1 +kind: ServiceAccount +metadata: + name: for-binding-test + namespace: kube-system + +--- + +# cluster-admin binding +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: cluster-admin-binding +subjects: +- kind: ServiceAccount + name: for-binding-test + namespace: kube-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin \ No newline at end of file diff --git a/azure-security-center/README.md b/azure-security-center/README.md new file mode 100644 index 0000000..57e8d47 --- /dev/null +++ b/azure-security-center/README.md @@ -0,0 +1,66 @@ +**Setup** + +To begin this demo, you'll need a subscription that had been whitelisted by the Azure Security Center team, an AKS cluster in that subscription, and a standard Security Center subscription. + +For the container registry scanning, you'll need a container registry, which will be created for you in acr_setup.sh + +From the security recommendations and alerts, you'll need to create a cluster you can access in the portal. You can do that by running alerts_setup.sh + +**Azure Container Registry Scanning** + +First, we're going to demo Azure Container's Registry new container scanning. The registry scans images as they are pushed to check for vulnerability. + +We're going to login in to our container registry using + +``` +az acr login -n +```` + +Now, we're going to pull a vulnerable image and push it to our registry. + +``` +docker pull docker.io/vulnerables/web-dvw +docker tag .azurecr.io /:.azurecr.io/: Compute & Apps > Containers +Our registry should be listed here. Go ahead and click on the registry to view details. You should see a recommendation called "Vulnerabilities in Azure Container Registry images should be remediated (Preview)" +Click on the recommendation to review the ‘Description’, ‘General Information’, ‘Threats’ and ‘Remediation Steps’ + + +**Azure Security Center Integration with AKS** + +Now we're going to look at how Azure Security Center (ASC) is integrated with Azure Kubernetes Service (AKS). + +First, we need ASC to discover our new cluster (this can take a few hours). + +Once that's done, navigate to Azure Security Center > Compute & Apps > Containers, where we'll see our cluster listed. + +Click on the cluster, and let's review the security recommendations. + +Reccommendations are listed in both the 'Reccommendations' and 'Passed Assessments' tabs at the bottom of the window. + +Click on a Recommendation, and review the ‘Description’, ‘General Info’, ‘Threats’ and ‘Remediation Steps’. +Click on ‘Take Action’, and you will be directed to the AKS resource page to complete remediation. + +We can also see these recommendations in a different view. Click on the 'Recommendations' tab on the right-hand side of Azure Security Center. Filter the recommendations by typing in 'Kubernetes' into the search bar. Now you can view recommendations across all of the clusters in your subscription. + +**Security Alerts with AKS** + + To demonstrate security alerts with AKS, we're going to deploy some containers that will simulate malicious activity. Make sure your context to set to the right cluster. We don't want to expose any other clusters to these security risks. + + ``` + az aks get-credentials -n -g + kubectl config current-context + ``` + +Now, let's deploy the containers. +``` +kubectl create -f ASC-Trigger-AKS-Alerts.yaml +``` + +After waiting about an hour, security alerts should start to pop up in ASC. Head to Azure Security Center > Security Alerts. Here, you can filter by alerts in the last 24 hours, to see the alerts from the containers we deployed. + + +Thanks to Maya Herskovic and the ASC Team for providing some of the documentation for this demo. \ No newline at end of file diff --git a/azure-security-center/acr_setup.sh b/azure-security-center/acr_setup.sh new file mode 100644 index 0000000..3834746 --- /dev/null +++ b/azure-security-center/acr_setup.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +read -p "Enter a unique name for your Azure Container Registry: " acr_name +az group create --name ASC-demo --location eastus +az acr create -n $acr_name -g ASC-demo --sku Basic +az acr login --name $acr_name \ No newline at end of file diff --git a/azure-security-center/alerts_setup.sh b/azure-security-center/alerts_setup.sh new file mode 100644 index 0000000..eeac1bb --- /dev/null +++ b/azure-security-center/alerts_setup.sh @@ -0,0 +1,4 @@ +# SETUP before demo +az group create -g ASC-demo -l eastus +az aks create -n ASC-demo -g ASC-demo --kubernetes-version 1.10.12 --disable-rbac --node-count 1 +az aks get-credentials -n ASC-demo -g ASC-demo diff --git a/private-clusters/setup.sh b/private-clusters/setup.sh new file mode 100644 index 0000000..0795495 --- /dev/null +++ b/private-clusters/setup.sh @@ -0,0 +1,49 @@ +#!/bin/bash +<< COMMENT + +All this has to happen before the demo. +COMMENT +az group create --name privateCluster --location westus +az extension add --name aks-preview +az feature register --name AllowPrivateEndpoints --namespace Microsoft.ContainerService +az feature register --name AKSPrivateLinkPreview --namespace Microsoft.ContainerService +az feature register --name AKSAzureStandardLoadBalancer --namespace Microsoft.ContainerService +az provider register --namespace Microsoft.ContainerService +az aks create -n privateCluster -g privateCluster --load-balancer-sku standard --enable-private-cluster + +vnet=$(az network vnet list -g MC_privateCluster_privateCluster_westus -o json) +vnetName=$(echo $vnet | jq -r .[].name) +username=user +password=user@PASS123 +subnet=aks-subnet + +az vm create --resource-group privateCluster \ +--name myVM --location westus \ +--image UbuntuLTS \ +--vnet-name $vnetName \ +--subnet $subnet \ +--admin-username $username --admin-password $password \ +--size standard_DS1_v2 +<< COMMENT +create the cluster +create a VM in the same VNET as the cluster +Create permissions so that the port 22 is exposed to the internet +install the azure cli on the VM +All of this needs to happen on the VM before we can connect to the cluster: + +ssh to vm +curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash +az login +az account set +sudo az aks install-cli +az aks get-credentials -g privateCluster -n privateCluster + +Start by showing the creating process of a private cluster (--enable-private-cluster flag) +Show that this is indeed private by trying to access the cluster through the CLI (should get a 404 error) +Show that we have a VM created that is connected to the vnet of the cluster and has a public IP +Then we ssh into this VM, using the public IP and access the cluster + +To reset, just clear both of the terminals used. +To clean up, delete the resource group. +az group delete -g privateCluster +COMMENT diff --git a/private-clusters/vm_setup.sh b/private-clusters/vm_setup.sh new file mode 100644 index 0000000..dfb2440 --- /dev/null +++ b/private-clusters/vm_setup.sh @@ -0,0 +1,5 @@ +curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash +az login +az account set +sudo az aks install-cli +az aks get-credentials -g privateCluster -n privateCluster \ No newline at end of file diff --git a/virtual-node-autoscale/README.md b/virtual-node-autoscale/README.md new file mode 100644 index 0000000..debe1b3 --- /dev/null +++ b/virtual-node-autoscale/README.md @@ -0,0 +1,34 @@ +**Virtual Nodes** + +**Setup** + +To set up the environment for the live demo, run the setup.sh or if you're using the pre-made environment kubectl config use-context virtual-node-autoscale. Then, open up the following tabs: +- Contoso Store (http://store.13.90.60.80.nip.io/) +- Live Metrics Stream for App Insights for Contoso Store +- Grafana Dashboard (localhost:3000) + +**Walkthrough** + +First, walk through the portal experience of creating a cluster with virtual nodes enabled (Slider on Scaling Tab). + + +Then, navigate to the application we're running on the cluster (contoso-store). + + +Open the Live Metrics Stream tab to demonstrate the current low amount of traffic. + + +In a split-screen terminal, start the load event (bash ./loadtest.sh) + + +In another visible terminal, run watch ./kubectl-get-pods.sh + +Once you see the Live Metrics start responding to the increase in traffic, navigate to the Grafana dashboard. + +Go over the various metrics and explain the graphs (Request per pod, Requests per second. Response time, Number of container instances) + + +**Reset** + + The loadtest only runs for about 5 minutes, so no reset needed here, beyond clearing the terminals you're using. +No clean up! \ No newline at end of file diff --git a/virtual-node-autoscale/get_helm.sh b/virtual-node-autoscale/get_helm.sh new file mode 100644 index 0000000..3f645f8 --- /dev/null +++ b/virtual-node-autoscale/get_helm.sh @@ -0,0 +1,245 @@ +#!/usr/bin/env bash + +# Copyright The Helm Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# The install script is based off of the MIT-licensed script from glide, +# the package manager for Go: https://github.com/Masterminds/glide.sh/blob/master/get + +PROJECT_NAME="helm" +TILLER_NAME="tiller" + +: ${USE_SUDO:="true"} +: ${HELM_INSTALL_DIR:="/usr/local/bin"} + +# initArch discovers the architecture for this system. +initArch() { + ARCH=$(uname -m) + case $ARCH in + armv5*) ARCH="armv5";; + armv6*) ARCH="armv6";; + armv7*) ARCH="arm";; + aarch64) ARCH="arm64";; + x86) ARCH="386";; + x86_64) ARCH="amd64";; + i686) ARCH="386";; + i386) ARCH="386";; + esac +} + +# initOS discovers the operating system for this system. +initOS() { + OS=$(echo `uname`|tr '[:upper:]' '[:lower:]') + + case "$OS" in + # Minimalist GNU for Windows + mingw*) OS='windows';; + esac +} + +# runs the given command as root (detects if we are root already) +runAsRoot() { + local CMD="$*" + + if [ $EUID -ne 0 -a $USE_SUDO = "true" ]; then + CMD="sudo $CMD" + fi + + $CMD +} + +# verifySupported checks that the os/arch combination is supported for +# binary builds. +verifySupported() { + local supported="darwin-386\ndarwin-amd64\nlinux-386\nlinux-amd64\nlinux-arm\nlinux-arm64\nlinux-ppc64le\nwindows-386\nwindows-amd64" + if ! echo "${supported}" | grep -q "${OS}-${ARCH}"; then + echo "No prebuilt binary for ${OS}-${ARCH}." + echo "To build from source, go to https://github.com/helm/helm" + exit 1 + fi + + if ! type "curl" > /dev/null && ! type "wget" > /dev/null; then + echo "Either curl or wget is required" + exit 1 + fi +} + +# checkDesiredVersion checks if the desired version is available. +checkDesiredVersion() { + if [ "x$DESIRED_VERSION" == "x" ]; then + # Get tag from release URL + local latest_release_url="https://github.com/helm/helm/releases/latest" + if type "curl" > /dev/null; then + TAG=$(curl -Ls -o /dev/null -w %{url_effective} $latest_release_url | grep -oE "[^/]+$" ) + elif type "wget" > /dev/null; then + TAG=$(wget $latest_release_url --server-response -O /dev/null 2>&1 | awk '/^ Location: /{DEST=$2} END{ print DEST}' | grep -oE "[^/]+$") + fi + else + TAG=$DESIRED_VERSION + fi +} + +# checkHelmInstalledVersion checks which version of helm is installed and +# if it needs to be changed. +checkHelmInstalledVersion() { + if [[ -f "${HELM_INSTALL_DIR}/${PROJECT_NAME}" ]]; then + local version=$("${HELM_INSTALL_DIR}/${PROJECT_NAME}" version -c | grep '^Client' | cut -d'"' -f2) + if [[ "$version" == "$TAG" ]]; then + echo "Helm ${version} is already ${DESIRED_VERSION:-latest}" + return 0 + else + echo "Helm ${TAG} is available. Changing from version ${version}." + return 1 + fi + else + return 1 + fi +} + +# downloadFile downloads the latest binary package and also the checksum +# for that binary. +downloadFile() { + HELM_DIST="helm-$TAG-$OS-$ARCH.tar.gz" + DOWNLOAD_URL="https://get.helm.sh/$HELM_DIST" + CHECKSUM_URL="$DOWNLOAD_URL.sha256" + HELM_TMP_ROOT="$(mktemp -dt helm-installer-XXXXXX)" + HELM_TMP_FILE="$HELM_TMP_ROOT/$HELM_DIST" + HELM_SUM_FILE="$HELM_TMP_ROOT/$HELM_DIST.sha256" + echo "Downloading $DOWNLOAD_URL" + if type "curl" > /dev/null; then + curl -SsL "$CHECKSUM_URL" -o "$HELM_SUM_FILE" + elif type "wget" > /dev/null; then + wget -q -O "$HELM_SUM_FILE" "$CHECKSUM_URL" + fi + if type "curl" > /dev/null; then + curl -SsL "$DOWNLOAD_URL" -o "$HELM_TMP_FILE" + elif type "wget" > /dev/null; then + wget -q -O "$HELM_TMP_FILE" "$DOWNLOAD_URL" + fi +} + +# installFile verifies the SHA256 for the file, then unpacks and +# installs it. +installFile() { + HELM_TMP="$HELM_TMP_ROOT/$PROJECT_NAME" + local sum=$(openssl sha1 -sha256 ${HELM_TMP_FILE} | awk '{print $2}') + local expected_sum=$(cat ${HELM_SUM_FILE}) + if [ "$sum" != "$expected_sum" ]; then + echo "SHA sum of ${HELM_TMP_FILE} does not match. Aborting." + exit 1 + fi + + mkdir -p "$HELM_TMP" + tar xf "$HELM_TMP_FILE" -C "$HELM_TMP" + HELM_TMP_BIN="$HELM_TMP/$OS-$ARCH/$PROJECT_NAME" + TILLER_TMP_BIN="$HELM_TMP/$OS-$ARCH/$TILLER_NAME" + echo "Preparing to install $PROJECT_NAME and $TILLER_NAME into ${HELM_INSTALL_DIR}" + runAsRoot cp "$HELM_TMP_BIN" "$HELM_INSTALL_DIR" + echo "$PROJECT_NAME installed into $HELM_INSTALL_DIR/$PROJECT_NAME" + if [ -x "$TILLER_TMP_BIN" ]; then + runAsRoot cp "$TILLER_TMP_BIN" "$HELM_INSTALL_DIR" + echo "$TILLER_NAME installed into $HELM_INSTALL_DIR/$TILLER_NAME" + else + echo "info: $TILLER_NAME binary was not found in this release; skipping $TILLER_NAME installation" + fi +} + +# fail_trap is executed if an error occurs. +fail_trap() { + result=$? + if [ "$result" != "0" ]; then + if [[ -n "$INPUT_ARGUMENTS" ]]; then + echo "Failed to install $PROJECT_NAME with the arguments provided: $INPUT_ARGUMENTS" + help + else + echo "Failed to install $PROJECT_NAME" + fi + echo -e "\tFor support, go to https://github.com/helm/helm." + fi + cleanup + exit $result +} + +# testVersion tests the installed client to make sure it is working. +testVersion() { + set +e + HELM="$(which $PROJECT_NAME)" + if [ "$?" = "1" ]; then + echo "$PROJECT_NAME not found. Is $HELM_INSTALL_DIR on your "'$PATH?' + exit 1 + fi + set -e + echo "Run '$PROJECT_NAME init' to configure $PROJECT_NAME." +} + +# help provides possible cli installation arguments +help () { + echo "Accepted cli arguments are:" + echo -e "\t[--help|-h ] ->> prints this help" + echo -e "\t[--version|-v ] . When not defined it defaults to latest" + echo -e "\te.g. --version v2.4.0 or -v latest" + echo -e "\t[--no-sudo] ->> install without sudo" +} + +# cleanup temporary files to avoid https://github.com/helm/helm/issues/2977 +cleanup() { + if [[ -d "${HELM_TMP_ROOT:-}" ]]; then + rm -rf "$HELM_TMP_ROOT" + fi +} + +# Execution + +#Stop execution on any error +trap "fail_trap" EXIT +set -e + +# Parsing input arguments (if any) +export INPUT_ARGUMENTS="${@}" +set -u +while [[ $# -gt 0 ]]; do + case $1 in + '--version'|-v) + shift + if [[ $# -ne 0 ]]; then + export DESIRED_VERSION="${1}" + else + echo -e "Please provide the desired version. e.g. --version v2.4.0 or -v latest" + exit 0 + fi + ;; + '--no-sudo') + USE_SUDO="false" + ;; + '--help'|-h) + help + exit 0 + ;; + *) exit 1 + ;; + esac + shift +done +set +u + +initArch +initOS +verifySupported +checkDesiredVersion +if ! checkHelmInstalledVersion; then + downloadFile + installFile +fi +testVersion +cleanup diff --git a/virtual-node-autoscale/kubectl-get-pods.sh b/virtual-node-autoscale/kubectl-get-pods.sh new file mode 100644 index 0000000..8fd492c --- /dev/null +++ b/virtual-node-autoscale/kubectl-get-pods.sh @@ -0,0 +1 @@ +kubectl get pods -l app=online-store \ No newline at end of file diff --git a/virtual-node-autoscale/loadtest.sh b/virtual-node-autoscale/loadtest.sh new file mode 100644 index 0000000..430b78c --- /dev/null +++ b/virtual-node-autoscale/loadtest.sh @@ -0,0 +1,5 @@ +export GOPATH=~/go +export PATH=$GOPATH/bin:$PATH +go get -u github.com/rakyll/hey +# This URL might be different +hey -z 5m http://store.13.90.60.80.nip.io/ \ No newline at end of file diff --git a/virtual-node-autoscale/setup.sh b/virtual-node-autoscale/setup.sh new file mode 100644 index 0000000..34d38b1 --- /dev/null +++ b/virtual-node-autoscale/setup.sh @@ -0,0 +1,103 @@ +#!/bin/bash +<> +# Install the aks-preview extension +az extension add --name aks-preview + +# Update the extension to make sure you have the latest version installed +az extension update --name aks-preview +az feature register --name WindowsPreview --namespace Microsoft.ContainerService +az provider register --namespace Microsoft.ContainerService +az group create --name windowsDemo --location eastus +PASSWORD_WIN="P@ssw0rd1234" +git clone https://gist.github.com/8d869c43549f2a7a2c0579c565b7d9ef.git +mv 8d869c43549f2a7a2c0579c565b7d9ef windows-demo +cd window-demo +# ^^^^ OFF SCREEN + +# On screen for the video demo +az aks create \ + --resource-group demo \ + --name windowsDemo \ + --node-count 2 \ + --enable-addons monitoring \ + --kubernetes-version 1.14.6 \ + --generate-ssh-keys \ + --windows-admin-password $PASSWORD_WIN \ + --windows-admin-username azureuser \ + --enable-vmss \ + --network-plugin azure + +az aks nodepool add \ + --resource-group demo \ + --cluster-name windowsDemo \ + --os-type Windows \ + --name npwin \ + --node-count 2 \ + --kubernetes-version 1.14.6 +az aks get-credentials --resource-group demo --name windowsDemo + +# Now we're going to go ahead and taint the windows nodes. This will mean that linux workloads that aren't compatibile with running on these nodes will not be +# scheduled on these nodes. On the other hand, pods that have tolerations for the Windows nodes can be schedules on these nodes. This way we make sure that Windows and Linux workloads +# are scheduled with compatible nodes. +kubectl get nodes -l beta.kubernetes.io/os=windows -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}' | xargs -I XX kubectl taint nodes XX windows=true:NoSchedule + +# Give Helm the appropriate permissions to run within the cluster +kubectl apply -f helm-rbac.yaml +helm init --service-account=tiller +helm repo update + +# This is where the in-person demo starts +kubectl get nodes +# Show that there are windows and linux nodes running in the same cluster + +# Now we're going to go ahead and taint the windows nodes. This will mean that linux workloads that aren't compatibile with running on these nodes will not be +# scheduled on these nodes. On the other hand, pods that have tolerations for the Windows nodes can be schedules on these nodes. This way we make sure that Windows and Linux workloads +# are scheduled with compatible nodes. +kubectl get nodes -l beta.kubernetes.io/os=windows -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}' | xargs -I XX kubectl taint nodes XX windows=true:NoSchedule + +helm install stable/nginx-ingress +# This is a linux workload and we see that it runs on the linux nodes in the cluster +kubectl get pods -o wide +kubectl apply -f iis-svc-ingress.yaml +# We see that the windows workload runs on the windows nodes in the cluster +kubectl get pods -o wide +kubectl get svc # to get exposed IP +# Test in browser +# So here we see that we can use the linux and windows workloads together in the cluster, here using the Linux nginx server to expose the Windows application to the internet, thanks to Windows containers in AKS