One place for hosting & domains

      Pulumi

      Como gerenciar a infraestrutura DigitalOcean e o Kubernetes com o Pulumi


      O autor escolheu a Diversity in Tech Fund para receber uma doação como parte do programa Write for DOnations.

      Introdução

      O Pulumi é uma ferramenta para criar, implantar e gerenciar infraestrutura usando código escrito em linguagens de programação de uso geral. Ele suporta a automação de todos os serviços gerenciados da DigitalOcean, como Droplets, bancos de dados gerenciados, registros DNS e clusters Kubernetes, além da configuração de aplicações. Os deployments são realizados a partir de uma interface de linha de comando fácil de usar que também se integra a uma ampla variedade de sistemas populares de CI/CD.

      O Pulumi suporta várias linguagens, mas neste tutorial você usará TypeScript, uma versão de tipagem estática do JavaScript que utiliza o runtime Node.js. Isso significa que você obterá suporte a IDE e checagem em tempo de compilação que o ajudarão a garantir que você configurou os recursos certos, usou slugs corretos etc., enquanto continua podendo acessar qualquer módulo NPM para tarefas utilitárias.

      Neste tutorial, você provisionará um cluster Kubernetes na DigitalOcean, uma aplicação Kubernetes com balanceamento de carga e um domínio DNS da DigitalOcean que disponibiliza seu aplicativo em um nome de domínio estável de sua escolha. Tudo isso pode ser provisionado em 60 linhas de infraestrutura como código e em uma única execução de linha de comando pulumi up. Após este tutorial, você estará pronto para criar com produtividade, arquiteturas poderosas de nuvem usando a infraestrutura como código do Pulumi que aproveita toda a área de serviços DigitalOcean e Kubernetes.

      Pré-requisitos

      Para seguir este tutorial, você precisará de:

      • Uma conta na DigitalOcean na qual fazer o deployment dos recursos. Se você ainda não possui uma, cadastre-se aqui.
      • Um token de API da DigitalOcean para executar deployments automatizados. Gere um token de acesso pessoal aqui e mantenha-o à mão, pois você o usará no Passo 2.
      • Como você criará e usará um cluster Kubernetes, precisará instalar o kubectl. Não se preocupe em configurá-lo ainda, pois você fará isso mais tarde.
      • Você escreverá sua infraestrutura como código no TypeScript e precisará do Node.js 8 ou posterior. Faça o download aqui ou instale-o usando o gerenciador de pacotes do seu sistema.
      • Você usará o Pulumi para fazer o deploy da infraestrutura, por isso precisará instalar o SDK do Pulumi open source.
      • Para executar o Passo 5 opcional, você precisará de um nome de domínio configurado para usar os servidores de nomes da DigitalOcean. Este guia explica como fazer isso para o registrador de sua escolha.

      Passo 1 — Estruturando um Novo Projeto

      O primeiro passo é criar um diretório que irá armazenar seu projeto Pulumi. Esse diretório conterá o código-fonte para suas definições de infraestrutura, além dos arquivos de metadados que descrevem o projeto e suas dependências NPM.

      Primeiro, crie o diretório:

      Em seguida, vá para o diretório recém-criado:

      A partir de agora, execute comandos a partir do seu diretório do-k8s recém-criado.

      Em seguida, crie um novo projeto Pulumi. Existem diferentes maneiras de fazer isso, mas a maneira mais fácil é usar o comando pulumi new com o modelo de projeto typescript. Este comando primeiro solicitará que você efetue login no Pulumi para que seu projeto e o estado do deployment sejam salvos e, em seguida, criará um projeto TypeScript simples no diretório atual:

      Aqui você passou a opção -y para o comando new, que diz a ele para aceitar as opções padrão do projeto. Por exemplo, o nome do projeto é retirado do nome do diretório atual e, portanto, será do-k8s. Se você quiser usar opções diferentes para o nome do seu projeto, simplesmente elimine o -y.

      Após executar o comando, liste o conteúdo do diretório com ls:

      Os seguintes arquivos estarão agora presentes:

      Output

      Pulumi.yaml index.ts node_modules package-lock.json package.json tsconfig.json

      O arquivo principal que você estará editando é index.ts. Embora este tutorial use apenas esse arquivo único, você pode organizar seu projeto da maneira que achar melhor usando os módulos Node.js. Este tutorial também descreve uma etapa de cada vez, aproveitando o fato de que o Pulumi pode detectar e deployar de forma incremental apenas o que mudou. Se preferir, você pode simplesmente preencher o programa inteiro e fazer o deploy de uma só vez usando o pulumi up.

      Agora que você estruturou seu novo projeto, está pronto para adicionar as dependências necessárias para seguir o tutorial.

      Passo 2 — Adicionando Dependências

      O próximo passo é instalar e adicionar dependências nos pacotes DigitalOcean e Kubernetes. Primeiro, instale-os usando o NPM:

      Isso fará o download dos pacotes NPM, plug-ins do Pulumi e os salvará como dependências.

      Em seguida, abra o arquivo index.ts com seu editor favorito. Este tutorial usará o nano:

      Substitua o conteúdo do seu index.ts pelo seguinte:

      index.ts

      import * as digitalocean from "@pulumi/digitalocean";
      import * as kubernetes from "@pulumi/kubernetes";
      

      Isso disponibiliza todo o conteúdo desses pacotes para o seu programa. Se você digitar "digitalocean." usando um IDE que entenda TypeScript e Node.js, você deverá ver uma lista dos recursos da DigitalOcean suportados por este pacote, por exemplo.

      Salve e feche o arquivo após adicionar o conteúdo.

      Nota: Usaremos um subconjunto do que está disponível nesses pacotes. Para obter a documentação completa dos recursos, propriedades e APIs associadas, consulte a documentação relevante da API para os pacotes @pulumi/digitalocean e @pulumi/kubernetes.

      Em seguida, você configurará seu token DigitalOcean para que o Pulumi possa provisionar recursos em sua conta:

      • pulumi config set digitalocean:token SEU_TOKEN_AQUI --secret

      Observe a flag --secret, que usa o serviço de criptografia do Pulumi para criptografar seu token, garantindo que ele seja armazenado em texto cifrado. Se preferir, você pode usar a variável de ambiente DIGITALOCEAN_TOKEN, mas você vai precisar lembrar-se de defini-la sempre que atualizar seu programa, enquanto o uso da configuração armazena e o utiliza automaticamente para o seu projeto.

      Nesta etapa, você adicionou as dependências necessárias e configurou seu token de API com o Pulumi para poder provisionar seu cluster Kubernetes.

      Passo 3 — Provisionando um Cluster Kubernetes

      Agora você está pronto para criar um cluster Kubernetes na DigitalOcean. Comece reabrindo o arquivo index.ts:

      Adicione estas linhas no final do seu arquivo index.ts:

      index.ts

      ...
      const cluster = new digitalocean.KubernetesCluster("do-cluster", {
          region: digitalocean.Regions.SFO2,
          version: "latest",
          nodePool: {
              name: "default",
              size: digitalocean.DropletSlugs.DropletS2VPCU2GB,
              nodeCount: 3,
          },
      });
      
      export const kubeconfig = cluster.kubeConfigs[0].rawConfig;
      

      Este novo código aloca uma instância do digitalocean.KubernetesCluster e define várias propriedades nele. Isso inclui o uso da sfo2 como slug da região, a versão mais recente, latest, do Kubernetes, o s-2vcpu-2gb slug de tamanho do Droplet, e indica a contagem desejada de três instâncias do Droplet. Sinta-se à vontade para alterar qualquer uma dessas opções, mas lembre-se de que o Kubernetes da DigitalOcean está disponível apenas em determinadas regiões no momento em que este artigo foi escrito. Você pode consultar a documentação do produto para obter informações atualizadas sobre a disponibilidade da região.

      Para obter uma lista completa das propriedades que você pode configurar no seu cluster, consulte a documentação da API do KubernetesCluster.

      A linha final nesse trecho de código exporta o aqruivo kubeconfig resultante do cluster Kubernetes para que seja fácil de usar. As variáveis exportadas são impressas no console e também acessíveis às ferramentas. Você usará isso momentaneamente para acessar nosso cluster a partir de ferramentas padrão como o kubectl.

      Agora você está pronto para implantar seu cluster. Para fazer isso, execute pulumi up:

      Este comando pega o programa, gera um plano para criar a infraestrutura descrita e executa uma série de etapas para deployar essas alterações. Isso funciona para a criação inicial da infraestrutura, além de poder diferenciar e atualizar sua infraestrutura quando as atualizações subsequentes são feitas. Nesse caso, a saída será mais ou menos assim:

      Output

      Previewing update (dev): Type Name Plan + pulumi:pulumi:Stack do-k8s-dev create + └─ digitalocean:index:KubernetesCluster do-cluster create Resources: + 2 to create Do you want to perform this update? yes > no details

      Isso indica que prosseguindo com a atualização será criado um único cluster Kubernetes chamado do-cluster. O prompt yes/no/details permite confirmar que este é o resultado desejado antes que quaisquer alterações sejam realmente feitas. Se você selecionar details, uma lista completa de recursos e suas propriedades serão mostrados. Escolha yes para iniciar o deployment:

      Output

      Updating (dev): Type Name Status + pulumi:pulumi:Stack do-k8s-dev created + └─ digitalocean:index:KubernetesCluster do-cluster created Outputs: kubeconfig: "..." Resources: + 2 created Duration: 6m5s Permalink: https://app.pulumi.com/.../do-k8s/dev/updates/1

      Leva alguns minutos para criar o cluster, mas depois ele estará em funcionamento e o kubeconfig completo será impresso no console. Salve o kubeconfig em um arquivo:

      • pulumi stack output kubeconfig > kubeconfig.yml

      E então use-o com o kubectl para executar qualquer comando do Kubernetes:

      • KUBECONFIG=./kubeconfig.yml kubectl get nodes

      Você receberá uma saída semelhante à seguinte:

      Output

      NAME STATUS ROLES AGE VERSION default-o4sj Ready <none> 4m5s v1.14.2 default-o4so Ready <none> 4m3s v1.14.2 default-o4sx Ready <none> 3m37s v1.14.2

      Nesse ponto, você configurou a infraestrutura como código e tem uma maneira repetível de ativar e configurar novos clusters Kubernetes na DigitalOcean . No próximo passo, você trabalhará em cima disso para definir a infraestrutura do Kubernetes no código e aprender como fazer o deploy e gerenciá-la da mesma forma.

      Passo 4 — Fazendo o Deploy de uma Aplicação no seu Cluster

      A seguir, você descreverá a configuração de uma aplicação Kubernetes usando infraestrutura como código. Isso consistirá em três partes:

      1. Um objeto Provider, que diz ao Pulumi para deployar recursos do Kubernetes no cluster da DigitalOcean, em vez do padrão que qualquer kubectl esteja configurado para usar.
      2. Um Deployment de Kubernetes, que é a maneira padrão do Kubernetes de deployar uma imagem de container Docker que é replicada em qualquer número de Pods.
      3. Um Serviço Kubernetes, que é a maneira padrão para dizer ao Kubernetes para balancear o acesso entre um conjunto alvo de Pods (neste caso, o Deployment acima).

      Essa é uma arquitetura de referência razoavelmente padrão para iniciar e executar um serviço com balanceamento de carga no Kubernetes.

      Para implantar todos os três, abra o arquivo index.ts novamente:

      Depois de abrir o arquivo, acrescente este código ao final dele:

      index.ts

      ...
      const provider = new kubernetes.Provider("do-k8s", { kubeconfig })
      
      const appLabels = { "app": "app-nginx" };
      const app = new kubernetes.apps.v1.Deployment("do-app-dep", {
          spec: {
              selector: { matchLabels: appLabels },
              replicas: 5,
              template: {
                  metadata: { labels: appLabels },
                  spec: {
                      containers: [{
                          name: "nginx",
                          image: "nginx",
                      }],
                  },
              },
          },
      }, { provider });
      const appService = new kubernetes.core.v1.Service("do-app-svc", {
          spec: {
              type: "LoadBalancer",
              selector: app.spec.template.metadata.labels,
              ports: [{ port: 80 }],
          },
      }, { provider });
      
      export const ingressIp = appService.status.loadBalancer.ingress[0].ip;
      

      Esse código é semelhante à configuração padrão do Kubernetes, e o comportamento dos objetos e suas propriedades é equivalente, exceto que ele está escrito em TypeScript ao lado de suas outras declarações de infraestrutura.

      Salve e feche o arquivo depois de fazer as alterações.

      Assim como antes, execute pulumi up para visualizar e deployar as alterações:

      Depois de selecionar yes para prosseguir, a CLI imprimirá atualizações de status detalhadas, incluindo diagnósticos sobre disponibilidade de Pod, alocação de endereço IP e muito mais. Isso ajudará você a entender por que seu deployment pode levar algum tempo para ser concluído ou ficar travado.

      A saída completa será mais ou menos assim:

      Output

      Updating (dev): Type Name Status pulumi:pulumi:Stack do-k8s-dev + ├─ pulumi:providers:kubernetes do-k8s created + ├─ kubernetes:apps:Deployment do-app-dep created + └─ kubernetes:core:Service do-app-svc created Outputs: + ingressIp : "157.230.199.202" Resources: + 3 created 2 unchanged Duration: 2m52s Permalink: https://app.pulumi.com/.../do-k8s/dev/updates/2

      Após a conclusão, observe que o número desejado de Pods está em execução:

      • KUBECONFIG=./kubeconfig.yml kubectl get pods

      Output

      NAME READY STATUS RESTARTS AGE do-app-dep-vyf8k78z-758486ff68-5z8hk 1/1 Running 0 1m do-app-dep-vyf8k78z-758486ff68-8982s 1/1 Running 0 1m do-app-dep-vyf8k78z-758486ff68-94k7b 1/1 Running 0 1m do-app-dep-vyf8k78z-758486ff68-cqm4c 1/1 Running 0 1m do-app-dep-vyf8k78z-758486ff68-lx2d7 1/1 Running 0 1m

      Similar à maneira como o programa exporta o arquivo kubeconfig do cluster, este programa também exporta o endereço IP do balanceador de carga resultante do serviço Kubernetes. Use isto para fazer um curl no endpoint e verifique se ele está funcionando:

      • curl $(pulumi stack output ingressIp)

      Output

      <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>

      A partir daqui, você pode editar e re-deployar facilmente sua infraestrutura de aplicações. Por exemplo, tente alterar a linha replicas: 5 para digamos replicas: 7 e, em seguida, execute novamente pulumi up:

      Observe que ele apenas mostra o que mudou e que ao selecionar detalhes, exibe a diferença precisa:

      Output

      Previewing update (dev): Type Name Plan Info pulumi:pulumi:Stack do-k8s-dev ~ └─ kubernetes:apps:Deployment do-app-dep update [diff: ~spec] Resources: ~ 1 to update 4 unchanged Do you want to perform this update? details pulumi:pulumi:Stack: (same) [urn=urn:pulumi:dev::do-k8s::pulumi:pulumi:Stack::do-k8s-dev] ~ kubernetes:apps/v1:Deployment: (update) [id=default/do-app-dep-vyf8k78z] [urn=urn:pulumi:dev::do-k8s::kubernetes:apps/v1:Deployment::do-app-dep] [provider=urn:pulumi:dev::do-k8s::pulumi:providers:kubernetes::do-k8s::80f36105-337f-451f-a191-5835823df9be] ~ spec: { ~ replicas: 5 => 7 }

      Agora você tem um cluster Kubernetes em plena operação e uma aplicação em funcionamento. Com a aplicação em funcionamento, você pode querer configurar um domínio personalizado para usar com ela. O próximo passo o guiará na configuração do DNS com o Pulumi.

      Passo 5 — Criando um Domínio DNS (Opcional)

      Embora o cluster e a aplicação Kubernetes estejam em funcionamento, o endereço da aplicação é dependente dos caprichos da atribuição automática de endereços IP pelo seu cluster. Conforme você ajusta e reimplementa as coisas, esse endereço pode mudar. Neste passo, você verá como atribuir um nome DNS personalizado ao endereço IP do balanceador de carga, para que fique estável, mesmo que você altere sua infraestrutura posteriormente.

      Nota: Para concluir este passo, garanta que você possui um domínio usando os servidores de nomes DNS da DigitalOcean, ns1.digitalocean.com, ns2.digitalocean.com e ns3.digitalocean.com. Instruções para configurar isso estão disponíveis na seção Pré-requisitos.

      Para configurar o DNS, abra o arquivo index.ts e acrescente o seguinte código ao final do arquivo:

      index.ts

      ...
      const domain = new digitalocean.Domain("do-domain", {
          name: "seu_domínio",
          ipAddress: ingressIp,
      });
      

      Este código cria uma nova entrada DNS com um registro A que se refere ao endereço IP do seu serviço Kubernetes. Substitua seu_domínio neste trecho pelo nome de domínio escolhido.

      É comum querer subdomínios adicionais, como www, apontando para a aplicação web. É fácil conseguir isso usando um registro DNS da DigitalOcean. Para tornar este exemplo mais interessante, adicione também um registro CNAME que aponte www.seu_domínio.com para seu_domínio.com:

      index.ts

      ...
      const cnameRecord = new digitalocean.DnsRecord("do-domain-cname", {
          domain: domain.name,
          type: "CNAME",
          name: "www",
          value: "@",
      });
      

      Salve e feche o arquivo depois de fazer essas alterações.

      Por fim, execute pulumi up para fazer o deploy das alterações no DNS para apontar para a aplicação e o cluster existentes:

      Output

      Updating (dev): Type Name Status pulumi:pulumi:Stack do-k8s-dev + ├─ digitalocean:index:Domain do-domain created + └─ digitalocean:index:DnsRecord do-domain-cname created Resources: + 2 created 5 unchanged Duration: 6s Permalink: https://app.pulumi.com/.../do-k8s/dev/updates/3

      Após a propagação das alterações no DNS, você poderá acessar seu conteúdo em seu domínio personalizado:

      • curl www.seu_domínio.com

      Você receberá uma saída semelhante à seguinte:

      Output

      <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>

      Com isso, você configurou com êxito um novo cluster Kubernetes na DigitalOcean, fez o deploy de uma aplicação Kubernetes com balanceamento de carga e deu ao balanceador de carga dessa aplicação um nome de domínio estável usando o DNS da DigitalOcean, tudo em 60 linhas de código e um comando pulumi up .

      A próximo passo o guiará na remoção dos recursos, se você não precisar mais deles.

      Passo 6 — Removendo os Recursos (Opcional)

      Antes de concluir o tutorial, você pode querer destruir todos os recursos criados acima. Isso garantirá que você não seja cobrado pelos recursos que não estão sendo usados. Se você preferir manter sua aplicação em funcionamento, fique à vontade para pular esta etapa.

      Execute o seguinte comando para destruir os recursos. Cuidado ao usar isso, pois não pode ser desfeito!

      Assim como no comando up, destroy exibe uma visualização e um prompt antes de executar uma ação:

      Output

      Previewing destroy (dev): Type Name Plan - pulumi:pulumi:Stack do-k8s-dev delete - ├─ digitalocean:index:DnsRecord do-domain-cname delete - ├─ digitalocean:index:Domain do-domain delete - ├─ kubernetes:core:Service do-app-svc delete - ├─ kubernetes:apps:Deployment do-app-dep delete - ├─ pulumi:providers:kubernetes do-k8s delete - └─ digitalocean:index:KubernetesCluster do-cluster delete Resources: - 7 to delete Do you want to perform this destroy? yes > no details

      Supondo que é isso que você deseja, selecione yes e observe as exclusões:

      Output

      Destroying (dev): Type Name Status - pulumi:pulumi:Stack do-k8s-dev deleted - ├─ digitalocean:index:DnsRecord do-domain-cname deleted - ├─ digitalocean:index:Domain do-domain deleted - ├─ kubernetes:core:Service do-app-svc deleted - ├─ kubernetes:apps:Deployment do-app-dep deleted - ├─ pulumi:providers:kubernetes do-k8s deleted - └─ digitalocean:index:KubernetesCluster do-cluster deleted Resources: - 7 deleted Duration: 7s Permalink: https://app.pulumi.com/.../do-k8s/dev/updates/4

      Nesse momento, nada mais resta: as entradas de DNS desaparecem e o cluster Kubernetes — juntamente com a aplicação em execução nele — também desaparece. O link permanente, permalink, ainda está disponível, para que você possa voltar e ver o histórico completo de atualizações para essa pilha. Isso pode ajudá-lo a se recuperar se a destruição for um erro, uma vez que o serviço mantém um histórico completo do estado de todos os recursos.

      Se você gostaria de destruir o seu projeto na sua totalidade, remova a pilha:

      Você receberá uma saída pedindo para confirmar a exclusão digitando o nome da pilha:

      Output

      This will permanently remove the 'dev' stack! Please confirm that this is what you'd like to do by typing ("dev"):

      Ao contrário do comando destroy, que exclui os recursos de infraestrutura em nuvem, a remoção de uma pilha apaga totalmente o histórico completo da sua pilha do alcance do Pulumi.

      Conclusão

      Neste tutorial, você fez o deploy dos recursos de infraestrutura na DigitalOcean — um cluster Kubernetes e um domínio DNS com registros A e CNAME — além da configuração da aplicação Kubernetes que usa esse cluster. Você fez isso usando infraestrutura como código escrita em uma linguagem de programação familiar, TypeScript, que trabalha com editores, ferramentas e bibliotecas existentes e aproveita as comunidades e pacotes existentes. Você fez tudo isso usando um único fluxo de trabalho de linha de comando para realizar deployments que abrangem sua aplicação e a infraestrutura.

      A partir daqui, há uma série de próximos passos que você pode dar:

      O exemplo completo deste tutorial está disponível no GitHub. Para obter maiores detalhes sobre como usar a infraestrutura como código do Pulumi em seus próprios projetos hoje, consulte a Documentação do Pulumi, Tutorials, ou os guias Getting Started. O Pulumi é open source e é livre para usar.



      Source link

      How to Manage DigitalOcean and Kubernetes Infrastructure with Pulumi


      The author selected the Diversity in Tech Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      Pulumi is a tool for creating, deploying, and managing infrastructure using code written in general purpose programming languages. It supports automating all of DigitalOcean’s managed services—such as Droplets, managed databases, DNS records, and Kubernetes clusters—in addition to application configuration. Deployments are performed from an easy-to-use command-line interface that also integrates with a wide variety of popular CI/CD systems.

      Pulumi supports multiple languages but in this tutorial you will use TypeScript, a statically typed version of JavaScript that uses the Node.js runtime. This means you will get IDE support and compile-time checking that will help to ensure you’ve configured the right resources, used correct slugs, etc., while still being able to access any NPM modules for utility tasks.

      In this tutorial, you will provision a DigitalOcean Kubernetes cluster, a load balanced Kubernetes application, and a DigitalOcean DNS domain that makes your application available at a stable domain name of your choosing. This can all be provisioned in 60 lines of infrastructure-as-code and a single pulumi up command-line gesture. After this tutorial, you’ll be ready to productively build powerful cloud architectures using Pulumi infrastructure-as-code that leverages the full surface area of DigitalOcean and Kubernetes.

      Prerequisites

      To follow this tutorial, you will need:

      • A DigitalOcean Account to deploy resources to. If you do not already have one, register here.
      • A DigitalOcean API Token to perform automated deployments. Generate a personal access token here and keep it handy as you’ll use it in Step 2.
      • Because you’ll be creating and using a Kubernetes cluster, you’ll need to install kubectl. Don’t worry about configuring it further — you’ll do that later.
      • You will write your infrastructure-as-code in TypeScript, so you will need Node.js 8 or later. Download it here or install it using your system’s package manager.
      • You’ll use Pulumi to deploy infrastructure, so you’ll need to install the open source Pulumi SDK.
      • To perform the optional Step 5, you will need a domain name configured to use DigitalOcean nameservers. This guide explains how to do this for your registrar of choice.

      Step 1 — Scaffolding a New Project

      The first step is to create a directory that will store your Pulumi project. This directory will contain the source code for your infrastructure definitions, in addition to metadata files describing the project and its NPM dependencies.

      First, create the directory:

      Next, move in to the newly created directory:

      From now on, run commands from your newly created do-k8s directory.

      Next, create a new Pulumi project. There are different ways to accomplish this, but the easiest way is to use the pulumi new command with the typescript project template. This command will first prompt you to log in to Pulumi so that your project and deployment state are saved, and will then create a simple TypeScript project in the current directory:

      Here you have passed the -y option to the new command which tells it to accept default project options. For example, the project name is taken from the current directory’s name, and so will be do-k8s. If you’d like to use different options for your project name, simply elide the -y.

      After running the command, list the contents of the directory with ls:

      The following files will now be present:

      Output

      Pulumi.yaml index.ts node_modules package-lock.json package.json tsconfig.json

      The primary file you’ll be editing is index.ts. Although this tutorial only uses this single file, you can organize your project any way you see fit using Node.js modules. This tutorial also describes one step at a time, leveraging the fact that Pulumi can detect and incrementally deploy only what has changed. If you prefer, you can just populate the entire program, and deploy it all in one go using pulumi up.

      Now that you’ve scaffolded your new project, you are ready to add the dependencies needed to follow the tutorial.

      Step 2 — Adding Dependencies

      The next step is to install and add dependencies on the DigitalOcean and Kubernetes packages. First, install them using NPM:

      This will download the NPM packages, Pulumi plugins, and save them as dependencies.

      Next, open the index.ts file with your favorite editor. This tutorial will use nano:

      Replace the contents of your index.ts with the following:

      index.ts

      import * as digitalocean from "@pulumi/digitalocean";
      import * as kubernetes from "@pulumi/kubernetes";
      

      This makes the full contents of these packages available to your program. If you type "digitalocean." using an IDE that understands TypeScript and Node.js, you should see a list of DigitalOcean resources supported by this package, for instance.

      Save and close the file after adding the content.

      Note: We will be using a subset of what’s available in those packages. For complete documentation of resources, properties, and associated APIs, please refer to the relevant API documentation for the @pulumi/digitalocean and @pulumi/kubernetes packages.

      Next, you will configure your DigitalOcean token so that Pulumi can provision resources in your account:

      • pulumi config set digitalocean:token YOUR_TOKEN_HERE --secret

      Notice the --secret flag, which uses Pulumi’s encryption service to encrypt your token, ensuring that it is stored in cyphertext. If you prefer, you can use the DIGITALOCEAN_TOKEN environment variable instead, but you’ll need to remember to set it every time you update your program, whereas using configuration automatically stores and uses it for your project.

      In this step you added the necessary dependencies and configured your API token with Pulumi so that you can provision your Kubernetes cluster.

      Step 3 — Provisioning a Kubernetes Cluster

      Now you’re ready to create a DigitalOcean Kubernetes cluster. Get started by reopening the index.ts file:

      Add these lines at the end of your index.ts file:

      index.ts

      …
      const cluster = new digitalocean.KubernetesCluster("do-cluster", {
          region: digitalocean.Regions.SFO2,
          version: "latest",
          nodePool: {
              name: "default",
              size: digitalocean.DropletSlugs.DropletS2VPCU2GB,
              nodeCount: 3,
          },
      });
      
      export const kubeconfig = cluster.kubeConfigs[0].rawConfig;
      

      This new code allocates an instance of digitalocean.KubernetesCluster and sets a number of properties on it. This includes using the sfo2 region slug, the latest supported version of Kubernetes, the s-2vcpu-2gb Droplet size slug, and states your desired count of three Droplet instances. Feel free to change any of these, but be aware that DigitalOcean Kubernetes is only available in certain regions at the time of this writing. You can refer to the product documentation for updated information about region availability.

      For a complete list of properties you can configure on your cluster, please refer to the KubernetesCluster API documentation.

      The final line in that code snippet exports the resulting Kubernetes cluster’s kubeconfig file so that it’s easy to use. Exported variables are printed to the console and also accessible to tools. You will use this momentarily to access our cluster from standard tools like kubectl.

      Now you’re ready to deploy your cluster. To do so, run pulumi up:

      This command takes the program, generates a plan for creating the infrastructure described, and carries out a series of steps to deploy those changes. This works for the initial creation of infrastructure in addition to being able to diff and update your infrastructure when subsequent updates are made. In this case, the output will look something like this:

      Output

      Previewing update (dev): Type Name Plan + pulumi:pulumi:Stack do-k8s-dev create + └─ digitalocean:index:KubernetesCluster do-cluster create Resources: + 2 to create Do you want to perform this update? yes > no details

      This says that proceeding with the update will create a single Kubernetes cluster named do-cluster. The yes/no/details prompt allows us to confirm that this is the desired outcome before any changes are actually made. If you select details, a full list of resources and their properties will be shown. Choose yes to begin the deployment:

      Output

      Updating (dev): Type Name Status + pulumi:pulumi:Stack do-k8s-dev created + └─ digitalocean:index:KubernetesCluster do-cluster created Outputs: kubeconfig: "…" Resources: + 2 created Duration: 6m5s Permalink: https://app.pulumi.com/…/do-k8s/dev/updates/1

      It takes a few minutes to create the cluster, but then it will be up and running, and the full kubeconfig will be printed out to the console. Save the kubeconfig to a file:

      • pulumi stack output kubeconfig > kubeconfig.yml

      And then use it with kubectl to perform any Kubernetes command:

      • KUBECONFIG=./kubeconfig.yml kubectl get nodes

      You will receive output similar to the following:

      Output

      NAME STATUS ROLES AGE VERSION default-o4sj Ready <none> 4m5s v1.14.2 default-o4so Ready <none> 4m3s v1.14.2 default-o4sx Ready <none> 3m37s v1.14.2

      At this point you’ve set up infrastructure-as-code and have a repeatable way to bring up and configure new DigitalOcean Kubernetes clusters. In the next step, you will build on top of this to define the Kubernetes infrastructure in code and learn how to deploy and manage them similarly.

      Step 4 — Deploying an Application to Your Cluster

      Next, you will describe a Kubernetes application’s configuration using infrastructure-as-code. This will consist of three parts:

      1. A Provider object, which tells Pulumi to deploy Kubernetes resources to the DigitalOcean cluster, rather than the default of whatever kubectl is configured to use.
      2. A Kubernetes Deployment, which is the standard Kubernetes way of deploying a Docker container image that is replicated across any number of Pods.
      3. A Kubernetes Service, which is the standard way to tell Kubernetes to load balance access across a target set of Pods (in this case, the Deployment above).

      This is a fairly standard reference architecture for getting up and running with a load balanced service in Kubernetes.

      To deploy all three of these, open your index.ts file again:

      Once the file is open, append this code to the end of the file:

      index.ts

      …
      const provider = new kubernetes.Provider("do-k8s", { kubeconfig })
      
      const appLabels = { "app": "app-nginx" };
      const app = new kubernetes.apps.v1.Deployment("do-app-dep", {
          spec: {
              selector: { matchLabels: appLabels },
              replicas: 5,
              template: {
                  metadata: { labels: appLabels },
                  spec: {
                      containers: [{
                          name: "nginx",
                          image: "nginx",
                      }],
                  },
              },
          },
      }, { provider });
      const appService = new kubernetes.core.v1.Service("do-app-svc", {
          spec: {
              type: "LoadBalancer",
              selector: app.spec.template.metadata.labels,
              ports: [{ port: 80 }],
          },
      }, { provider });
      
      export const ingressIp = appService.status.loadBalancer.ingress[0].ip;
      

      This code is similar to standard Kubernetes configuration, and the behavior of objects and their properties is equivalent, except that it’s written in TypeScript alongside your other infrastructure declarations.

      Save and close the file after making the changes.

      Just like before, run pulumi up to preview and then deploy the changes:

      After selecting yes to proceed, the CLI will print out detailed status updates, including diagnostics around Pod availability, IP address allocation, and more. This will help you understand why your deployment might be taking time to complete or getting stuck.

      The full output will look something like this:

      Output

      Updating (dev): Type Name Status pulumi:pulumi:Stack do-k8s-dev + ├─ pulumi:providers:kubernetes do-k8s created + ├─ kubernetes:apps:Deployment do-app-dep created + └─ kubernetes:core:Service do-app-svc created Outputs: + ingressIp : "157.230.199.202" Resources: + 3 created 2 unchanged Duration: 2m52s Permalink: https://app.pulumi.com/…/do-k8s/dev/updates/2

      After this completes, notice that the desired number of Pods are running:

      • KUBECONFIG=./kubeconfig.yml kubectl get pods

      Output

      NAME READY STATUS RESTARTS AGE do-app-dep-vyf8k78z-758486ff68-5z8hk 1/1 Running 0 1m do-app-dep-vyf8k78z-758486ff68-8982s 1/1 Running 0 1m do-app-dep-vyf8k78z-758486ff68-94k7b 1/1 Running 0 1m do-app-dep-vyf8k78z-758486ff68-cqm4c 1/1 Running 0 1m do-app-dep-vyf8k78z-758486ff68-lx2d7 1/1 Running 0 1m

      Similar to how the program exports the cluster’s kubeconfig file, this program also exports the Kubernetes service’s resulting load balancer’s IP address. Use this to curl the endpoint and see that it is up and running:

      • curl $(pulumi stack output ingressIp)

      Output

      <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>

      From here, you can easily edit and redeploy your application infrastructure. For example, try changing the replicas: 5 line to say replicas: 7, and then rerun pulumi up:

      Notice that it just shows what has changed, and that selecting details displays the precise diff:

      Output

      Previewing update (dev): Type Name Plan Info pulumi:pulumi:Stack do-k8s-dev ~ └─ kubernetes:apps:Deployment do-app-dep update [diff: ~spec] Resources: ~ 1 to update 4 unchanged Do you want to perform this update? details pulumi:pulumi:Stack: (same) [urn=urn:pulumi:dev::do-k8s::pulumi:pulumi:Stack::do-k8s-dev] ~ kubernetes:apps/v1:Deployment: (update) [id=default/do-app-dep-vyf8k78z] [urn=urn:pulumi:dev::do-k8s::kubernetes:apps/v1:Deployment::do-app-dep] [provider=urn:pulumi:dev::do-k8s::pulumi:providers:kubernetes::do-k8s::80f36105-337f-451f-a191-5835823df9be] ~ spec: { ~ replicas: 5 => 7 }

      Now you have both a fully functioning Kubernetes cluster and a working application. With your application up and running, you may want to configure a custom domain to use with your application. The next step will guide you through configuring DNS with Pulumi.

      Step 5 — Creating a DNS Domain (Optional)

      Although the Kubernetes cluster and application are up and running, the application’s address is dependent upon the whims of automatic IP address assignment by your cluster. As you adjust and redeploy things, this address might change. In this step, you will see how to assign a custom DNS name to the load balancer IP address so that it’s stable even as you subsequently change your infrastructure.

      Note: To complete this step, ensure you have a domain using DigitalOcean’s DNS nameservers, ns1.digitalocean.com, ns2.digitalocean.com, and ns3.digitalocean.com. Instructions to configure this are available in the Prerequisites section.

      To configure DNS, open the index.ts file and append the following code to the end of the file:

      index.ts

      …
      const domain = new digitalocean.Domain("do-domain", {
          name: "your_domain",
          ipAddress: ingressIp,
      });
      

      This code creates a new DNS entry with an A record that refers to your Kubernetes service’s IP address. Replace your_domain in this snippet with your chosen domain name.

      It is common to want additional sub-domains, like www, to point at the web application. This is easy to accomplish using a DigitalOcean DNS record. To make this example more interesting, also add a CNAME record that points www.your_domain.com to your_domain.com:

      index.ts

      …
      const cnameRecord = new digitalocean.DnsRecord("do-domain-cname", {
          domain: domain.name,
          type: "CNAME",
          name: "www",
          value: "@",
      });
      

      Save and close the file after making these changes.

      Finally, run pulumi up to deploy the DNS changes to point at your existing application and cluster:

      Output

      Updating (dev): Type Name Status pulumi:pulumi:Stack do-k8s-dev + ├─ digitalocean:index:Domain do-domain created + └─ digitalocean:index:DnsRecord do-domain-cname created Resources: + 2 created 5 unchanged Duration: 6s Permalink: https://app.pulumi.com/…/do-k8s/dev/updates/3

      After the DNS changes have propagated, you will be able to access your content at your custom domain:

      You will receive output similar to the following:

      Output

      <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>

      With that, you have successfully set up a new DigitalOcean Kubernetes cluster, deployed a load balanced Kubernetes application to it, and given that application’s load balancer a stable domain name using DigitalOcean DNS, all in 60 lines of code and a pulumi up command.

      The next step will guide you through removing the resources if you no longer need them.

      Step 6 — Removing the Resources (Optional)

      Before concluding the tutorial, you may want to destroy all of the resources created above. This will ensure you don’t get charged for resources that aren’t being used. If you prefer to keep your application up and running, feel free to skip this step.

      Run the following command to destroy the resources. Be careful using this, as it cannot be undone!

      Just as with the up command, destroy displays a preview and prompt before taking action:

      Output

      Previewing destroy (dev): Type Name Plan - pulumi:pulumi:Stack do-k8s-dev delete - ├─ digitalocean:index:DnsRecord do-domain-cname delete - ├─ digitalocean:index:Domain do-domain delete - ├─ kubernetes:core:Service do-app-svc delete - ├─ kubernetes:apps:Deployment do-app-dep delete - ├─ pulumi:providers:kubernetes do-k8s delete - └─ digitalocean:index:KubernetesCluster do-cluster delete Resources: - 7 to delete Do you want to perform this destroy? yes > no details

      Assuming this is what you want, select yes and watch the deletions occur:

      Output

      Destroying (dev): Type Name Status - pulumi:pulumi:Stack do-k8s-dev deleted - ├─ digitalocean:index:DnsRecord do-domain-cname deleted - ├─ digitalocean:index:Domain do-domain deleted - ├─ kubernetes:core:Service do-app-svc deleted - ├─ kubernetes:apps:Deployment do-app-dep deleted - ├─ pulumi:providers:kubernetes do-k8s deleted - └─ digitalocean:index:KubernetesCluster do-cluster deleted Resources: - 7 deleted Duration: 7s Permalink: https://app.pulumi.com/…/do-k8s/dev/updates/4

      At this point, nothing remains: the DNS entries are gone and the Kubernetes cluster—along with the application running inside of it—are gone. The permalink is still available, so you can still go back and see the full history of updates for this stack. This could help you recover if the destruction was a mistake, since the service keeps full state history for all resources.

      If you’d like to destroy your project in its entirety, remove the stack:

      You will receive output asking you to confirm the deletion by typing in the stack’s name:

      Output

      This will permanently remove the 'dev' stack! Please confirm that this is what you'd like to do by typing ("dev"):

      Unlike the destroy command, which deletes the cloud infrastructure resources, the removal of a stack erases completely the full history of your stack from Pulumi’s purview.

      Conclusion

      In this tutorial, you’ve deployed DigitalOcean infrastructure resources—a Kubernetes cluster and a DNS domain with A and CNAME records—in addition to the Kubernetes application configuration that uses this cluster. You have done so using infrastructure-as-code written in a familiar programming language, TypeScript, that works with existing editors, tools, and libraries, and leverages existing communities and packages. You’ve done it all using a single command line workflow for doing deployments that span your application and infrastructure.

      From here, there are a number of next steps you might take:

      The entire sample from this tutorial is available on GitHub. For extensive details about how to use Pulumi infrastructure-as-code in your own projects today, check out the Pulumi Documentation, Tutorials, or Getting Started guides. Pulumi is open source and free to use.



      Source link

      Getting Started with Pulumi


      Updated by Linode Written by Linode

      What is Pulumi?

      Pulumi is a development tool that allows you to write computer programs which deploy cloud resources–a practice referred to as infrastructure as code (IaC). Pulumi integrates with multiple cloud platforms, and Pulumi programs can be authored in a number of common programming languages.

      With Pulumi’s Linode integration, you can manage your Linode resources as you would with our API or CLI, but in a language you may already be familiar with. This guide will present examples written in JavaScript, but Pulumi is also compatible with Go, Python, and TypeScript.

      Pulumi also comes with a CLI interface for running the cloud infrastructure programs that you write. Once you’ve written a program, you can create your cloud resources with a single command:

      pulumi up
      

      In this guide you will learn how to:

      Before You Begin

      1. If you haven’t yet, create a Linode API token.

      2. Create a free Pulumi account.

      3. Create a new Debian 9 Linode. Follow our Getting Started guide to deploy the Linode, and then follow the Securing Your Server guide. Be sure to create a limited Linux user with sudo privileges on your server. All commands in this guide are to be run from a sudo user.

      4. Install Pulumi on your Linode using their installation script:

        curl -fsSL https://get.pulumi.com | sh
        
      5. To start using the Pulumi CLI:

        • Restart your shell session, or

        • Add /home/username/.pulumi/bin to your $PATH variable in your current session. Replace username with the name of your limited Linux user:

          PATH=$PATH:/home/username/.pulumi/bin
          
      6. Install Node.js and npm:

        sudo apt-get install curl software-properties-common
        curl -sL https://deb.nodesource.com/setup_12.x | sudo bash -
        sudo apt-get install -y nodejs
        

      Generate a Pulumi Access Token

      Once you have a Pulumi account, you will need to create an access token to use later.

      Why do I need a Pulumi access token?

      When Pulumi interprets the infrastructure programs that you write, it determines what cloud resources it needs to create in order to satisfy your program. Every time you run your program, Pulumi stores the state of these resources in a persistent backend. In subsequent updates to your infrastructure, Pulumi will compare your program with the recorded state so that it can determine which changes need to be made.

      By default, Pulumi securely stores this state information on a web backend hosted at https://app.pulumi.com. This service is free to start and offers paid tiers for teams and enterprises.

      It is possible to opt-out of using the default web backend and use a filesystem-based backend instead. Review Pulumi’s documentation for instructions.

      1. Log into your Pulumi account. After you’ve logged in, click on the avatar graphic to the top right of the Pulumi dashboard, then click on the Settings option in the dropdown menu that appears:

        Location of Pulumi Settings option

      2. Select the Access Tokens item in the sidebar to the left of the page that appears:

        Location of Pulumi Access Token page

      3. Click on the New Access Token button towards the top right of the following page and follow the prompts to create your new token. Make sure you save this in a secure location, similar to your Linode API token.

      Create a Linode

      Set up your Pulumi Project

      Now that you have everything you need to begin using Pulumi, you can create a new Pulumi project.

      Note

      A Pulumi project is the folder structure which contains your Pulumi programs. Specifically, a project is any folder which contains a Pulumi.yaml metadata file.
      1. Pulumi requires an empty directory for each new project, so first you’ll need to create one and make it your working directory:

        cd ~/ && mkdir pulumi && cd pulumi
        
      2. Now that you’re inside of your new empty working directory, create a new project:

        pulumi new
        
      3. From here, you’ll see several prompts:

        • Enter your Pulumi access token if prompted. If you’ve already entered it at any point following the installation of Pulumi, you will not be prompted again and can skip this step.
        • Use your arrow keys to highlight the linode-javascript option.
        • Enter a project name of your choice, or leave blank to use the default option.

        • Enter a project description, or leave blank to use the default option.

        • Enter a stack name of your choice, or leave blank to use the default option.

          What’s a stack?

          Multiple instances of your Pulumi programs can be created. For example, you may want to have separate instances for the development, staging, and production environments of your service. Or, you may create multiple instances of your service if you’re offering it to different business clients. In Pulumi, these instances are referred to as stacks.
        • Enter your Linode API token.

      4. Once the installation is successful, you will see a Your new project is ready to go! message. The pulumi new command scaffolds a collection of default configuration files in your project’s directory. The default configuration will give you everything you need to get started. Enter the ls command to ensure that the files are present:

        ls
        
          
        index.js      package.json	 Pulumi.pulumi.yaml
        node_modules  package-lock.json  Pulumi.yaml
        
        

        The contents of these files were defined according to our responses to each prompt after entering pulumi new. In particular:

        • index.js contains the JavaScript Pulumi will run
        • package.json defines the dependencies we can use and the file path Pulumi will be reading our code from.

      Inspect the Default Configuration

      Let’s take a look at the contents of our index.js file:

      index.js
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      
      "use strict";
      const pulumi = require("@pulumi/pulumi");
      const linode = require("@pulumi/linode");
      
      // Create a Linode resource (Linode Instance)
      const instance = new linode.Instance("my-instance", {
          type: "g6-nanode-1",
          region: "us-east",
          image: "linode/ubuntu18.04",
      });
      
      // Export the Instance label of the instance
      exports.instanceLabel = instance.label;
      

      The file requires two JavaScript modules unique to Pulumi: Pulumi’s SDK, and Pulumi’s Linode integration. Pulumi’s API Reference Documentation serves as a reference for the JavaScript you’ll see here. It also includes a library of several additional options that enable you to create configurations more specific to your use case.

      In this case, your file is only creating a single Nanode instance in the Newark data center running Ubuntu 18.04.

      Create and Destroy Resources

      • Use Pulumi’s preview command to test your code and make sure it’s successfully able to create resources under your account.

        pulumi preview
        

        The output of the command will list the operations Pulumi will perform once you deploy your program:

        Previewing update (dev):
        
            Type                      Name                   Plan
        +   pulumi:pulumi:Stack       my-pulumi-project-dev  create
        +   └─ linode:index:Instance  my-instance            create
        
        Resources:
            + 2 to create
        
      • Use Pulumi’s up command to deploy your code to your Linode account:

        pulumi up
        

        Note

        This will create a new billable resource on your account.

        From here, you will be prompted to confirm the resource creation. Use your arrow keys to choose the yes option, hit enter, and you will see your resources being created. Once the process is completed, the Linode Label of your new Linode will be displayed. If you check your account manually through the Cloud Manager, you can confirm that this Linode has been successfully created.

      • Since this Linode was only created as a test, you can safely delete it by entering Pulumi’s destroy command:

        pulumi destroy
        

        Follow the prompts, and you’ll be able to see the resources being removed, similar to how we could see them being created.

        Note

        Many Pulumi commands will be logged on your Pulumi account. You can see this under the Activity tab of your project’s stack in Pulumi’s Application Page.

      Create and Configure a NodeBalancer

      To better demonstrate the power of Pulumi code, we’ll create a new index.js file. This will define everything we need to create a functioning NodeBalancer which is pre-configured with two backend Linodes running NGINX.

      1. Replace the contents of your index.js file with the following:

        index.js
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        52
        53
        54
        55
        56
        57
        58
        59
        60
        61
        62
        63
        64
        65
        66
        67
        68
        69
        70
        71
        72
        73
        74
        75
        
        const pulumi = require("@pulumi/pulumi");
        const linode = require("@pulumi/linode");
        
        // Create two new Nanodes using a StackScript to configure them internally.
        // The StackScript referenced will install and enable NGINX.
        
        // "linode1" (the first argument passed to the Linode instance constructor function) is the Pulumi-allocated Unique Resource Name (URN) for this resource
        const linode1 = new linode.Instance("linode1", {
                // "PulumiNode1" is the Linode's label that appears in the Cloud Manager. Linode labels must be unique on your Linode account
                label: "PulumiNode1",
                region: "us-east",
                image: "linode/debian9",
                privateIp: true,
                stackscriptData: {
                        hostname: "PulumiNode1",
                    },
                stackscriptId: 526246,
                type:"g6-nanode-1",
        });
        
        const linode2 = new linode.Instance("linode2", {
                label: "PulumiNode2",
                region: "us-east",
                image: "linode/debian9",
                privateIp: true,
                stackscriptData: {
                    hostname: "PulumiNode2",
                    },
                stackscriptId: 526246,
                type:"g6-nanode-1",
        });
        
        // Create and configure your NodeBalancer
        
        const nodeBalancer = new linode.NodeBalancer("nodeBalancer", {
                clientConnThrottle: 20,
                label: "PulumiNodeBalancer",
                region: "us-east",
        });
        
        const nodeBalancerConfig = new linode.NodeBalancerConfig("nodeBalancerConfig", {
                algorithm: "source",
                check: "http",
                checkAttempts: 3,
                checkTimeout: 30,
                checkInterval: 40,
                checkPath: "/",
                nodebalancerId: nodeBalancer.id,
                port: 8088,
                protocol: "http",
                stickiness: "http_cookie",
        });
        
        // Assign your Linodes to the NodeBalancer
        
        const balancerNode1 = new linode.NodeBalancerNode("balancerNode1", {
                address: pulumi.concat(linode1.privateIpAddress, ":80"),
                configId: nodeBalancerConfig.id,
                label: "PulumiBalancerNode1",
                nodebalancerId: nodeBalancer.id,
                weight: 50,
        });
        
        const balancerNode2 = new linode.NodeBalancerNode("balancerNode2", {
                address: pulumi.concat(linode2.privateIpAddress, ":80"),
                configId: nodeBalancerConfig.id,
                label: "PulumiBalancerNode2",
                nodebalancerId: nodeBalancer.id,
                weight: 50,
        });
        
        //Output your NodeBalancer's Public IPV4 address and the port we configured to access it
        exports.nodeBalancerIP = nodeBalancer.ipv4;
        exports.nodeBalancerPort = nodeBalancerConfig.port;
        

        Note

        In our index.js file we’ve created and configured two Linodes using an existing StackScript which installs NGINX. Pulumi’s Linode integration allows for the creation of entirely new StackScripts directly in code, which can help you to automate your deployments even further.

        If you’re interested in seeing how this StackScript works, you can view it here.

      2. Now that you’ve successfully prepared your JavaScript code, let’s bring up our configuration:

        pulumi up
        

        As before, select yes when prompted and wait for a few moments as your resources are created, configured, and brought online.

      3. Once the process is completed, you’ll see your NodeBalancer’s IP address and the port you configured earlier displayed as part of the output:

        Outputs:
        + nodeBalancerIP  : "192.0.2.3"
        + nodeBalancerPort: 8088
        

        Enter this IP address and port into your web browser, and you will see the Hello World-style page that the StackScript configured:

        curl http://192.0.2.3:8088/
        
          
        Hello from PulumiNode1
        
        

        Note

        If you do not see this page right away, you should wait a few additional moments. NodeBalancers can sometimes require a little extra time to fully apply a new configuration.

      4. Once you’re finished with your NodeBalancer, you can remove and delete everything you added by entering pulumi destroy as before.

      Next Steps

      Pulumi is a powerful tool with a vast number of possible configurations that can be applied. From here you can:

      • Look at Pulumi’s examples for more ideas regarding the things you can do with Pulumi.

      • Try using Pulumi with different languages like Python or TypeScript

      • Import Node.js tools like Express for even more elasticity with your code.

      • Use Pulumi for Serverless Computing

      More Information

      You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.

      Find answers, ask questions, and help others.

      This guide is published under a CC BY-ND 4.0 license.



      Source link