diff --git a/azure-cs-aks-helm/.gitignore b/azure-cs-aks-helm/.gitignore new file mode 100644 index 000000000..dfd2e7d2a --- /dev/null +++ b/azure-cs-aks-helm/.gitignore @@ -0,0 +1,356 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Visual Studio Code +.vscode diff --git a/azure-cs-aks-helm/MyCluster.cs b/azure-cs-aks-helm/MyCluster.cs new file mode 100644 index 000000000..15b699857 --- /dev/null +++ b/azure-cs-aks-helm/MyCluster.cs @@ -0,0 +1,105 @@ +// Copyright 2016-2021, Pulumi Corporation. All rights reserved. + +using System; +using System.Collections.Generic; +using System.Text; + +using Pulumi; +using Pulumi.AzureAD; +using Pulumi.AzureNative.ContainerService; +using Pulumi.AzureNative.ContainerService.Inputs; +using Pulumi.AzureNative.Resources; +using K8s = Pulumi.Kubernetes; + +class MyCluster +{ + public Output ClusterName { get; set; } + public Output Kubeconfig { get; set; } + + public K8s.Provider Provider { get; set; } + + public MyCluster(MyConfig cfg) + { + var resourceGroup = new ResourceGroup("rg"); + + var adApp = new Application("app"); + + var adSp = new ServicePrincipal("service-principal", new ServicePrincipalArgs + { + ApplicationId = adApp.ApplicationId + }); + + var adSpPassword = new ServicePrincipalPassword("sp-password", new ServicePrincipalPasswordArgs + { + ServicePrincipalId = adSp.Id, + Value = cfg.Password, + EndDate = "2099-01-01T00:00:00Z" + }); + + var k8sCluster = new ManagedCluster("cluster", new ManagedClusterArgs + { + ResourceGroupName = resourceGroup.Name, + AddonProfiles = + { + ["KubeDashboard"] = new ManagedClusterAddonProfileArgs { Enabled = true } + }, + AgentPoolProfiles = + { + new ManagedClusterAgentPoolProfileArgs + { + Count = cfg.NodeCount, + VmSize = cfg.NodeSize, + MaxPods = 110, + Mode = "System", + Name = "agentpool", + OsDiskSizeGB = 30, + OsType = "Linux", + Type = "VirtualMachineScaleSets" + } + }, + DnsPrefix = resourceGroup.Name, + EnableRBAC = true, + KubernetesVersion = cfg.K8SVersion, + LinuxProfile = new ContainerServiceLinuxProfileArgs + { + AdminUsername = cfg.AdminUserName, + Ssh = new ContainerServiceSshConfigurationArgs + { + PublicKeys = new ContainerServiceSshPublicKeyArgs + { + KeyData = cfg.SshPublicKey + } + } + }, + NodeResourceGroup = "node-resource-group", + ServicePrincipalProfile = new ManagedClusterServicePrincipalProfileArgs + { + ClientId = adApp.ApplicationId, + Secret = adSpPassword.Value + } + }); + + this.ClusterName = k8sCluster.Name; + + this.Kubeconfig = Output.Tuple(k8sCluster.Name, resourceGroup.Name) + .Apply(pair => + { + var k8sClusterName = pair.Item1; + var resourceGroupName = pair.Item2; + + return ListManagedClusterUserCredentials.InvokeAsync(new ListManagedClusterUserCredentialsArgs + { + ResourceGroupName = resourceGroupName, + ResourceName = k8sClusterName + }); + }) + .Apply(x => x.Kubeconfigs[0].Value) + .Apply(Convert.FromBase64String) + .Apply(Encoding.UTF8.GetString); + + this.Provider = new K8s.Provider("k8s-provider", new K8s.ProviderArgs + { + KubeConfig = Kubeconfig + }); + } +} diff --git a/azure-cs-aks-helm/MyConfig.cs b/azure-cs-aks-helm/MyConfig.cs new file mode 100644 index 000000000..46b340169 --- /dev/null +++ b/azure-cs-aks-helm/MyConfig.cs @@ -0,0 +1,68 @@ +// Copyright 2016-2021, Pulumi Corporation. All rights reserved. + +using Pulumi; +using Pulumi.Random; +using Pulumi.Tls; + +/// +/// Configures the example. If password and public key for connecting +/// to the cluster are not set with `pulumi config`, we generate a +/// random password and key pair. +/// +class MyConfig +{ + public string K8SVersion { get; set; } + public int NodeCount { get; set; } + public string NodeSize { get; set; } + public PrivateKey GeneratedKeyPair { get; set; } + public string AdminUserName { get; set; } + public Output Password { get; set; } + public Output SshPublicKey { get; set; } + + public MyConfig() + { + var cfg = new Config(); + + this.K8SVersion = cfg.Get("k8sVersion") ?? "1.18.14"; + this.NodeCount = cfg.GetInt32("nodeCount") ?? 2; + this.NodeSize = cfg.Get("nodeSize") ?? "Standard_D2_v2"; + + this.GeneratedKeyPair = new PrivateKey("ssh-key", new PrivateKeyArgs + { + Algorithm = "RSA", + RsaBits = 4096 + }); + + this.AdminUserName = cfg.Get("adminUserName") ?? "testuser"; + + var pw = cfg.Get("password"); + if (pw == null) + { + this.Password = this.GenerateRandomPassword(); + } + else + { + this.Password = Output.Create(pw); + } + + var sshPubKey = cfg.Get("sshPublicKey"); + if (sshPubKey == null) + { + this.SshPublicKey = this.GeneratedKeyPair.PublicKeyOpenssh; + } + else + { + this.SshPublicKey = Output.Create(sshPubKey); + } + } + + private Output GenerateRandomPassword() + { + var pw = new RandomPassword("pw", new RandomPasswordArgs + { + Length = 20, + Special = true + }); + return pw.Result; + } +} diff --git a/azure-cs-aks-helm/MyStack.cs b/azure-cs-aks-helm/MyStack.cs new file mode 100644 index 000000000..09a69b83d --- /dev/null +++ b/azure-cs-aks-helm/MyStack.cs @@ -0,0 +1,43 @@ +// Copyright 2016-2021, Pulumi Corporation. All rights reserved. + +using Pulumi; +using Pulumi.Kubernetes.Core.V1; +using Pulumi.Kubernetes.Helm; +using Pulumi.Kubernetes.Helm.V3; + +class MyStack : Stack +{ + [Output] + public Output ApacheServiceIP { get; set; } + + [Output] + public Output ClusterName { get; set; } + + [Output] + public Output Kubeconfig { get; set; } + + public MyStack() + { + var myConfig = new MyConfig(); + var myCluster = new MyCluster(myConfig); + + var chart = new Chart("apache-chart", new ChartArgs + { + Chart = "apache", + Version = "8.3.2", + FetchOptions = new ChartFetchArgs + { + Repo = "https://charts.bitnami.com/bitnami" + } + }, new ComponentResourceOptions + { + Provider = myCluster.Provider + }); + + this.ApacheServiceIP = chart.GetResource("apache-chart") + .Apply(svc => svc.Status.Apply(s => s.LoadBalancer.Ingress[0].Ip)); + + this.ClusterName = myCluster.ClusterName; + this.Kubeconfig = myCluster.Kubeconfig; + } +} diff --git a/azure-cs-aks-helm/Program.cs b/azure-cs-aks-helm/Program.cs new file mode 100644 index 000000000..665d44a76 --- /dev/null +++ b/azure-cs-aks-helm/Program.cs @@ -0,0 +1,9 @@ +// Copyright 2016-2021, Pulumi Corporation. All rights reserved. + +using System.Threading.Tasks; +using Pulumi; + +class Program +{ + static Task Main() => Deployment.RunAsync(); +} diff --git a/azure-cs-aks-helm/Pulumi.yaml b/azure-cs-aks-helm/Pulumi.yaml new file mode 100644 index 000000000..0c82d6c13 --- /dev/null +++ b/azure-cs-aks-helm/Pulumi.yaml @@ -0,0 +1,3 @@ +name: azure-cs-aks-helm +runtime: dotnet +description: Azure Native C# Pulumi example featuring Helm chart deployment to AKS diff --git a/azure-cs-aks-helm/README.md b/azure-cs-aks-helm/README.md new file mode 100644 index 000000000..5ba2235c2 --- /dev/null +++ b/azure-cs-aks-helm/README.md @@ -0,0 +1,109 @@ +[![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new) + +# Azure Kubernetes Service (AKS) Cluster and Helm Chart + +This example demonstrates creating an [Azure Kubernetes Service (AKS)](https://docs.microsoft.com/en-us/azure/aks/) +cluster and deploying a Helm Chart from [Bitnami Helm chart repository](https://github.com/bitnami/charts) +into this cluster, all in one Pulumi program. + +The example showcases the [native Azure provider for Pulumi](https://www.pulumi.com/docs/intro/cloud-providers/azure/). + + +## Prerequisites + +- Install [Pulumi](https://www.pulumi.com/docs/get-started/install/). + +- Install [.NET Core](https://dotnet.microsoft.com/download) + +- We will be deploying to Azure, so you will need an Azure account. If + you do not have an account, [sign up for free here](https://azure.microsoft.com/en-us/free/). + +- Setup and authenticate the [native Azure provider for Pulumi](https://www.pulumi.com/docs/intro/cloud-providers/azure/setup/). + + +## Running the Example + +In this example we will provision a Kubernetes cluster running a +public Apache web server, verify we can access it, and clean up when +done. + +1. Get the code: + + ```bash + $ git clone git@github.com:pulumi/examples.git + $ cd examples/azure-cs-aks-helm + ``` + +2. Restore dependencies and build: + + ```bash + $ dotnet build + ``` + +3. Create a new stack, which is an isolated deployment target for this example: + + ```bash + $ pulumi stack init + ``` + +4. Set the required configuration variables for this program: + + ```bash + $ pulumi config set azure-native:location westus2 + ``` + +5. Deploy everything with the `pulumi up` command. This provisions + all the Azure resources necessary, including an Active Directory + service principal, AKS cluster, and then deploys the Apache Helm + Chart, all in a single gesture (takes 5-10 min): + + ```bash + $ pulumi up + ``` + +6. Now your cluster and Apache server are ready. Several output + variables will be printed, including your cluster name + (`ClusterName`), Kubernetes config (`Kubeconfig`) and server IP + address (`ApacheServiceIP`). + + Using these output variables, you may access your Apache server: + + ```bash + $ curl $(pulumi stack output ApacheServiceIP) +

It works!

+ ``` + + And you may also configure your `kubectl` client using the + `Kubeconfig` configuration: + + ```bash + $ pulumi stack output Kubeconfig --show-secrets > kubeconfig.yaml + $ KUBECONFIG=./kubeconfig.yaml kubectl get service + + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + apache-chart LoadBalancer 10.0.58.153 20.51.80.30 80:32707/TCP,443:32495/TCP 3m23s + kubernetes ClusterIP 10.0.0.1 443/TCP 21m + ``` + +7. At this point, you have a running cluster. Feel free to modify + your program, and run `pulumi up` to redeploy changes. The Pulumi + CLI automatically detects what has changed and makes the minimal + edits necessary to accomplish these changes. This could be + altering the existing chart, adding new Azure or Kubernetes + resources, or anything, really. + + TIP: if you make changes to the example code outside of an IDE, + run the C# compiler after every change: + + ```bash + $ dotnet build + ``` + +8. Once you are done, you can destroy all of the resources, and the + stack: + + ```bash + $ pulumi destroy + $ pulumi stack rm + $ rm kubeconfig.yaml + ``` diff --git a/azure-cs-aks-helm/azure-cs-aks-helm.csproj b/azure-cs-aks-helm/azure-cs-aks-helm.csproj new file mode 100644 index 000000000..666343af0 --- /dev/null +++ b/azure-cs-aks-helm/azure-cs-aks-helm.csproj @@ -0,0 +1,17 @@ + + + + Exe + netcoreapp3.1 + enable + + + + + + + + + + + diff --git a/azure-go-aks-helm/Pulumi.yaml b/azure-go-aks-helm/Pulumi.yaml index e7bdb1d29..4dcb67bb7 100644 --- a/azure-go-aks-helm/Pulumi.yaml +++ b/azure-go-aks-helm/Pulumi.yaml @@ -1,3 +1,3 @@ -name: azure-ts-aks-helm +name: azure-go-aks-helm runtime: go description: Azure Native Go Pulumi example featuring Helm chart deployment to AKS diff --git a/azure-go-aks-helm/go.mod b/azure-go-aks-helm/go.mod index 330231c2f..3ffe062a2 100644 --- a/azure-go-aks-helm/go.mod +++ b/azure-go-aks-helm/go.mod @@ -1,4 +1,4 @@ -module go-ex +module azure-go-aks-helm go 1.15 diff --git a/azure-go-aks-helm/main.go b/azure-go-aks-helm/main.go index c5ce843f0..741859a96 100644 --- a/azure-go-aks-helm/main.go +++ b/azure-go-aks-helm/main.go @@ -28,7 +28,6 @@ func main() { } chartArgs := helm.ChartArgs{ - Repo: pulumi.String("bitnami"), Chart: pulumi.String("apache"), Version: pulumi.String("8.3.2"), FetchArgs: helm.FetchArgs{ diff --git a/azure-ts-aks-helm/index.ts b/azure-ts-aks-helm/index.ts index 1f76ae3db..a71ba63f3 100644 --- a/azure-ts-aks-helm/index.ts +++ b/azure-ts-aks-helm/index.ts @@ -11,7 +11,6 @@ export let kubeconfig = cluster.kubeconfig; const apache = new k8s.helm.v3.Chart( "apache-chart", { - repo: "bitnami", chart: "apache", version: "8.3.2", fetchOpts: {