One place for hosting & domains

      DigitalOcean

      How To Set Up the Eclipse Theia Cloud IDE Platform on DigitalOcean Kubernetes


      The author selected the Free and Open Source Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      With developer tools moving to the cloud, creation and adoption of cloud IDE (Integrated Development Environment) platforms is growing. Cloud IDEs are accessible from every type of modern device through web browsers, and they offer numerous advantages for real-time collaboration scenarios. Working in a cloud IDE provides a unified development and testing environment for you and your team, while minimizing platform incompatibilities. Because they are natively based on cloud technologies, they are able to make use of the cluster to achieve tasks, which can greatly exceed the power and reliability of a single development computer.

      Eclipse Theia is an extensible cloud IDE running on a remote server and accessible from a web browser. Visually, it’s designed to look and behave similarly to Microsoft Visual Studio Code, which means that it supports many programming languages, has a flexible layout, and has an integrated terminal. What separates Eclipse Theia from other cloud IDE software is its extensibility; it can be modified using custom extensions, which allow you to craft a cloud IDE suited to your needs.

      In this tutorial, you will set up the default version of the Eclipse Theia cloud IDE platform on your DigitalOcean Kubernetes cluster and expose it at your domain, secured with Let’s Encrypt certificates and requiring the visitor to authenticate. In the end, you’ll have Eclipse Theia running on your Kubernetes cluster available via HTTPS and requiring the visitor to log in.

      Prerequisites

      • A DigitalOcean Kubernetes cluster with your connection configured as the kubectl default. Instructions on how to configure kubectl are shown in the Connect to your Cluster step when you create your cluster. To create a Kubernetes cluster on DigitalOcean, see Kubernetes Quickstart.

      • The Helm package manager installed on your local machine, and Tiller installed on your cluster. To do this, complete Steps 1 and 2 of the How To Install Software on Kubernetes Clusters with the Helm Package Manager tutorial.

      • The Nginx Ingress Controller and Cert Manager installed on your cluster using Helm in order to expose Eclipse Theia using Ingress Resources. To do this, follow How to Set Up an Nginx Ingress on DigitalOcean Kubernetes Using Helm.

      • A fully registered domain name to host Eclipse Theia. This tutorial will use theia.your_domain throughout. You can purchase a domain name on Namecheap, get one for free on Freenom, or use the domain registrar of your choice.

      Step 1 — Installing and Exposing Eclipse Theia

      To begin you’ll install Eclipse Theia to your DigitalOcean Kubernetes cluster. Then, you will expose it at your desired domain using an Nginx Ingress.

      Since you created two example deployments and a resource as part of the prerequisites, you can freely delete them by running the following commands:

      • kubectl delete -f hello-kubernetes-ingress.yaml
      • kubectl delete -f hello-kubernetes-first.yaml
      • kubectl delete -f hello-kubernetes-second.yaml

      For this tutorial, you’ll store the deployment configuration on your local machine, in a file named eclipse-theia.yaml. Create it using the following command:

      Add the following lines to the file:

      eclipse-theia.yaml

      apiVersion: v1
      kind: Namespace
      metadata:
        name: theia
      ---
      apiVersion: networking.k8s.io/v1beta1
      kind: Ingress
      metadata:
        name: theia-next
        namespace: theia
        annotations:
          kubernetes.io/ingress.class: nginx
      spec:
        rules:
        - host: theia.your_domain
          http:
            paths:
            - backend:
                serviceName: theia-next
                servicePort: 80
      ---
      apiVersion: v1
      kind: Service
      metadata:
       name: theia-next
       namespace: theia
      spec:
       ports:
       - port: 80
         targetPort: 3000
       selector:
         app: theia-next
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        labels:
          app: theia-next
        name: theia-next
        namespace: theia
      spec:
        selector:
          matchLabels:
            app: theia-next
        replicas: 1
        template:
          metadata:
            labels:
              app: theia-next
          spec:
            containers:
            - image: theiaide/theia:next
              imagePullPolicy: Always
              name: theia-next
              ports:
              - containerPort: 3000
      

      This configuration defines a Namespace, a Deployment, a Service, and an Ingress. The Namespace is called theia and will contain all Kubernetes objects related to Eclipse Theia, separated from the rest of the cluster. The Deployment consists of one instance of the theiaide/theia:next Docker image with the port 3000 exposed on the container. The Service looks for the Deployment and remaps the container port to the usual HTTP port, 80, allowing in-cluster access to Eclipse Theia.

      The Ingress contains a rule to serve the Service at port 80 externally at your desired domain. In its annotations, you specify that the Nginx Ingress Controller should be used for request processing. Remember to replace theia.your_domain with your desired domain that you’ve pointed to your cluster’s Load Balancer, then save and close the file.

      Save and exit the file.

      Then, create the configuration in Kubernetes by running the following command:

      • kubectl create -f eclipse-theia.yaml

      You’ll see the following output:

      Output

      namespace/theia created ingress.networking.k8s.io/theia-next created service/theia-next created deployment.apps/theia-next created

      You can watch the Eclipse Theia pod creation by running:

      • kubectl get pods -w -n theia

      The output will look like this:

      Output

      NAME READY STATUS RESTARTS AGE theia-next-847d8c8b49-jt9bc 0/1 ContainerCreating 0 22s

      After some time, the status will turn to RUNNING, which means you’ve successfully installed Eclipse Theia to your cluster.

      Navigate to your domain in your browser. You’ll see the default Eclipse Theia editor GUI.

      The default Eclipse Theia editor GUI

      You’ve deployed Eclipse Theia to your DigitalOcean Kubernetes cluster and exposed it at your desired domain with an Ingress. Next, you’ll secure access to your Eclipse Theia deployment by enabling login authentication.

      Step 2 — Enabling Login Authentication For Your Domain

      In this step, you’ll enable username and password authentication for your Eclipse Theia deployment. You’ll achieve this by first curating a list of valid login combinations using the htpasswd utility. Then, you’ll create a Kubernetes secret containing that list and configure the Ingress to authenticate visitors according to it. In the end, your domain will only be accessible when the visitor inputs a valid username and password combination. This will prevent guests and other unwanted visitors from accessing Eclipse Theia.

      The htpasswd utility comes from the Apache web server and is used for creating files that store lists of login combinations. The format of htpasswd files is one username:hashed_password combination per line, which is the format the Nginx Ingress Controller expects the list to conform to.

      Start by installing htpasswd on your system by running the following command:

      • sudo apt install apache2-utils -y

      You’ll store the list in a file called auth. Create it by running:

      This file needs to be named auth because the Nginx Ingress Controller expects the secret to contain a key called data.auth. If it’s missing, the controller will return HTTP 503 Service Unavailable status.

      Add a username and password combination to auth by running the following command:

      Remember to replace username with your desired username. You’ll be asked for an accompanying password and the combination will be added into the auth file. You can repeat this command for as many users as you wish to add.

      Note: If the system you are working on does not have htpasswd installed, you can use a Dockerized version instead.

      You’ll need to have Docker installed on your machine. For instructions on how to do so, visit the official docs.

      Run the following command to run a dockerized version:

      • docker run --rm -it httpd htpasswd -n <username>

      Remember to replace <username> with the username you want to use. You’ll be asked for a password. The hashed login combination will be written out on the console, and you’ll need to manually add it to the end of the auth file. Repeat this process for as many logins as you wish to add.

      When you are done, create a new secret in Kubernetes with the contents of the file by running the following command:

      • kubectl create secret generic theia-basic-auth --from-file=auth -n theia

      You can see the secret with:

      • kubectl get secret theia-basic-auth -o yaml -n theia

      The output will look like:

      Output

      apiVersion: v1 data: auth: c2FtbXk6JGFwcjEkVFMuSDdyRWwkaFNSNWxPbkc0OEhncmpGZVFyMzEyLgo= kind: Secret metadata: creationTimestamp: "..." name: theia-basic-auth namespace: default resourceVersion: "10900" selfLink: /api/v1/namespaces/default/secrets/theia-basic-auth uid: 050767b9-8823-4fd3-b498-5f11074f768b type: Opaque

      Next, you’ll need to edit the Ingress to make it use the secret. Open the deployment configuration for editing:

      Add the highlighted lines to your file:

      eclipse-theia.yaml

      apiVersion: v1
      kind: Namespace
      metadata:
        name: theia
      ---
      apiVersion: networking.k8s.io/v1beta1
      kind: Ingress
      metadata:
        name: theia-next
        namespace: theia
        annotations:
          kubernetes.io/ingress.class: nginx
          nginx.ingress.kubernetes.io/auth-type: basic
          nginx.ingress.kubernetes.io/auth-secret: theia-basic-auth
          nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - Eclipse Theia'
      spec:
        rules:
        - host: theia.your_domain
          http:
            paths:
            - backend:
                serviceName: theia-next
                servicePort: 80
      ...
      

      First, in the auth-type annotation, you specify that the authentication type is basic. This means that Nginx will require the user to type in a username and password. Then, in auth-secret, you specify that the secret that contains the list of valid combinations is theia-basic-auth, which you’ve just created. The remaining auth-realm annotation specifies a message that will be shown to the user as an explanation of why authentication is required. You can change the message contained in this field to your liking.

      Save and close the file.

      To propagate the changes to your cluster, run the following command:

      • kubectl apply -f eclipse-theia.yaml

      You’ll see the output:

      Output

      namespace/theia unchanged ingress.networking.k8s.io/theia-next configured service/theia-next unchanged deployment.apps/theia-next unchanged

      Navigate to your domain in your browser, where you’ll now be asked to log in.

      You’ve enabled basic login authentication on your Ingress by configuring it to use the secret containing the hashed username and password combinations. In the next step, you’ll secure access further by adding TLS certificates, so that the traffic between you and your Eclipse Theia deployment stays encrypted.

      Step 3 — Applying Let’s Encrypt HTTPS Certificates

      Next you will secure your Eclipse Theia installation by applying Let’s Encrypt certificates to your Ingress, which Cert-Manager will automatically provision. After completing this step, your Eclipse Theia installation will be accessible via HTTPS.

      Open eclipse-theia.yaml for editing:

      Add the highlighted lines to your file, making sure to replace the placeholder domain with your own:

      eclipse-theia.yaml

      apiVersion: v1
      kind: Namespace
      metadata:
        name: theia
      ---
      apiVersion: networking.k8s.io/v1beta1
      kind: Ingress
      metadata:
        name: theia-next
        namespace: theia
        annotations:
          kubernetes.io/ingress.class: nginx
          nginx.ingress.kubernetes.io/auth-type: basic
          nginx.ingress.kubernetes.io/auth-secret: theia-basic-auth
          nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - Eclipse Theia'
          cert-manager.io/cluster-issuer: letsencrypt-prod
      spec:
        tls:
        - hosts:
          - theia.your_domain
          secretName: theia-prod
        rules:
        - host: theia.your_domain
          http:
            paths:
            - backend:
                serviceName: theia-next
                servicePort: 80
      ...
      

      First, you specify the letsencrypt-prod ClusterIssuer you created as part of the prerequisites as the issuer that will be used to provision certificates for this Ingress. Then, in the tls section, you specify the exact domain that should be secured, as well as a name for a secret that will be holding those certificates.

      Save and exit the file.

      Apply the changes to your cluster by running the following command:

      • kubectl apply -f eclipse-theia.yaml

      The output will look like:

      Output

      namespace/theia unchanged ingress.networking.k8s.io/theia-next configured service/theia-next unchanged deployment.apps/theia-next unchanged

      It will take a few minutes for the certificates to be provisioned and fully applied. You can track the progress by observing the output of the following command:

      • kubectl describe certificate theia-prod -n theia

      When it finishes, the end of the output will look similar to this:

      Output

      ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal GeneratedKey 42m cert-manager Generated a new private key Normal Requested 42m cert-manager Created new CertificateRequest resource "theia-prod-3785736528" Normal Issued 42m cert-manager Certificate issued successfully

      Refresh your domain in your browser. You’ll see a green padlock shown on the leftmost side of the address bar signifying that the connection is secure.

      You’ve configured the Ingress to use Let’s Encrypt certificates thus making your Eclipse Theia deployment more secure. Now you can review the default Eclipse Theia user interface.

      Step 4 — Using the Eclipse Theia Interface

      In this section, you’ll explore some of the features of the Eclipse Theia interface.

      On the left-hand side of the IDE, there is a vertical row of four buttons opening the most commonly used features in a side panel.

      Eclipse Theia GUI - Sidepanel

      This bar is customizable so you can move these views to a different order or remove them from the bar. By default, the first view opens the Explorer panel that provides tree-like navigation of the project’s structure. You can manage your folders and files here—creating, deleting, moving, and renaming them as necessary.

      After creating a new file through the File menu, you’ll see an empty file open in a new tab. Once saved, you can view the file’s name in Explorer side panel. To create folders right click on the Explorer sidebar and click on New Folder. You can expand a folder by clicking on its name as well as dragging and dropping files and folders to upper parts of the hierarchy to move them to a new location.

      Eclipse Theia GUI - New Folder

      The next two options provide access to search and replace functionality. Following it, the next one provides a view of source control systems that you may be using, such as Git.

      The final view is the debugger option, which provides all the common actions for debugging in the panel. You can save debugging configurations in the launch.json file.

      Debugger View with launch.json open

      The central part of the GUI is your editor, which you can separate by tabs for your code editing. You can change your editing view to a grid system or to side-by-side files. Like all modern IDEs, Eclipse Theia supports syntax highlighting for your code.

      Editor Grid View

      You can gain access to a terminal by typing CTRL+SHIFT+`, or by clicking on Terminal in the upper menu, and selecting New Terminal. The terminal will open in a lower panel and its working directory will be set to the project’s workspace, which contains the files and folders shown in the Explorer side panel.

      Terminal open

      You’ve explored a high-level overview of the Eclipse Theia interface and reviewed some of the most commonly used features.

      Conclusion

      You now have Eclipse Theia, a versatile cloud IDE, installed on your DigitalOcean Kubernetes cluster. You’ve secured it with a free Let’s Encrypt TLS certificate and set up the instance to require a login from the visitor. You can work on your source code and documents with it individually or collaborate with your team. You can also try building your own version of Eclipse Theia if you need additional functionality. For further information on how to do that, visit the Theia docs.



      Source link

      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

      Getting Started with Containers and Kubernetes: A DigitalOcean Meetup Kit


      Getting Started with Containers and Kubernetes Meetup Kit Materials

      This meetup kit is designed to help a technical audience become familiar with core Kubernetes concepts and practices.

      The aim is to provide a complete set of resources for a speaker to host an event and deliver an introductory talk on containers and Kubernetes. It includes:

      This tutorial is intended to supplement the talk demo with additional detail and elucidation. It also serves as a reference for readers seeking to get a minimal containerized Flask app up and running on DigitalOcean Kubernetes.

      Introduction

      In the past decade, containerized applications and container clusters have rapidly replaced the old paradigm of scaling applications using virtual machines. Containers offer the same process isolation, but are generally more lightweight, portable, and performant than full virtualization. Container clusters, which can be used to manage thousands of running containers across a set of physical machines, abstract away much of the work of rolling out new versions of applications, scaling them, and efficiently scheduling workloads. Out of these, Kubernetes has emerged as a mature, production-ready system. It provides a rich set of features like rolling deployments, health checking, self-monitoring, workload autoscaling, and much, much more.

      This tutorial, designed to accompany the Slides and speaker notes for the Getting Started with Kubernetes Meetup Kit, will show you how to harness these technologies and deploy the “Hello World” Flask app onto a DigitalOcean Kubernetes cluster.

      Prerequisites

      To follow this tutorial, you will need:

      • A Kubernetes 1.10+ cluster with role-based access control (RBAC) enabled. This setup will use a DigitalOcean Kubernetes cluster
      • The kubectl command-line tool installed on your local machine or development server and configured to connect to your cluster. You can read more about installing kubectl in the official documentation.
      • Docker installed on your local machine or development server. If you are working with Ubuntu 18.04, follow Steps 1 and 2 of How To Install and Use Docker on Ubuntu 18.04; otherwise, follow the official documentation for information about installing on other operating systems. Be sure to add your non-root user to the docker group, as described in Step 2 of the linked tutorial.
      • A Docker Hub account (optional). For an overview of how to set this up, refer to this introduction to Docker Hub. You’ll only need a Docker Hub account if you plan on modifying the Flask Docker image described in this tutorial.

      Step 1 — Cloning the App Repository and Building the Flask Image

      To begin, clone the demo Flask app repo onto your machine, navigate into the directory, and list the directory contents:

      • git clone https://github.com/do-community/k8s-intro-meetup-kit.git
      • cd k8s-intro-meetup-kit
      • ls

      Output

      LICENSE README.md app k8s

      The app directory contains the Flask demo app code, as well as the Dockerfile for building its container image. The k8s directory contains Kubernetes manifest files for a Pod, Deployment, and Service. To learn more about these Kubernetes objects, consult the slide deck or An Introduction to Kubernetes.

      Navigate into the app directory and print out the contents of the app.py file:

      Output

      from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello, World!' if __name__ == "__main__": app.run(debug=True, host='0.0.0.0')

      This code defines a single default route that will print “Hello World.” Additionally, the apps runs in debug mode to enable verbose output.

      In a similar fashion, cat out the contents of the app’s Dockerfile:

      Output

      FROM python:3-alpine WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . EXPOSE 5000 CMD ["python", "app.py"]

      This Dockerfile first sources a lightweight Alpine Linux Python parent image. It then copies in the Python requirements file, installs Flask, copies the app code into the container image, defines port 5000 as the container port, and finally sets the default command to python app.py.

      Next, build the app image:

      • cd app
      • docker build -t flask_demo:v0 .

      We give the image a name, flask_demo, and tag, v0 using the -t option.

      After Docker finishes the build, run the container using run:

      • docker run -p 5000:5000 flask:v0

      This command runs a container using the flask:v0 image, and forwards local port 5000 to container port 5000.

      If you’re running Docker on your local machine, navigate to http://localhost:5000 in your web browser. You should see “Hello World,” generated by the dockerized Flask app.

      If you’re running Docker on a dev server, navigate instead to http://dev_server_external_IP:5000. If you’re running a firewall like UFW, be sure to allow external access on port 5000. To learn more about doing this with UFW, consult UFW Essentials: Common Firewall Rules and Commands.

      At this point you can experiment with Docker commands like docker ps, docker top, and docker images to practice working with images and containers on your system.

      In the next step, we’ll deploy this demo app to your Kubernetes cluster. We’ll use a prebuilt image shared publicly on Docker Hub. If you’d like to customize the Flask app and use your own image, you should create a Docker Hub account and follow the steps in this introduction to push your image to a public repository. From there, Kubernetes will be able to pull and deploy the container image into your cluster.

      Step 2 — Deploying the Flask App on Kubernetes

      The app and Docker image described in the previous step have already been built and made publicly available in the flask-helloworld Docker Hub repository. You can optionally create your own repository for the app and substitute it for flask-helloworld throughout this step.

      We’ll first deploy this demo “Hello World” app into our cluster as a standalone Pod, then as a multi-pod Deployment, which we’ll finally expose as a LoadBalancer Service. At the end of this tutorial, the “Hello World” app will be publicly accessible from outside of the Kubernetes cluster.

      Before we launch any workloads into the cluster, we’ll create a Namespace in which the objects will run. Namespaces allow you to segment your cluster and limit scope for running workloads.

      Create a Namespace called flask:

      • kubectl create namespace flask

      Now, list all the Namespaces in your cluster:

      You should see your new Namespace as well as some default Namespaces like kube-system and default. In this tutorial, we are going to exclusively work within the flask Namespace.

      Navigate back out to the k8s directory in the demo repo:

      In this directory, you’ll see three Kubernetes manifest files:

      • flask-pod.yaml: The app Pod manifest
      • flask-deployment.yaml: The app Deployment manifest
      • flask-service.yaml: The app LoadBalancer Service manifest

      Let’s take a look at the Pod manifest:

      Output

      apiVersion: v1 kind: Pod metadata: name: flask-pod labels: app: flask-helloworld spec: containers: - name: flask image: hjdo/flask-helloworld:latest ports: - containerPort: 5000

      Here, we define a minimal Pod called flask-pod and label it with the app: flask-helloworld key-value pair.

      We then name the single container flask and set the image to flask-helloworld:latest from the hjdo/flask-helloworld Docker Hub repository. If you’re using an image stored in a different Docker Hub repo, you can reference it using the image field here. Finally, we open up port 5000 to accept incoming connections.

      Deploy this Pod into the flask Namespace using kubectl apply -f and the -n Namespace flag:

      • kubectl apply -f flask-pod.yaml -n flask

      After ten or so seconds, the Pod should be up and running in your cluster:

      Output

      NAME READY STATUS RESTARTS AGE flask-pod 1/1 Running 0 4s

      Since this Pod is running inside of the Kubernetes cluster, we need to forward a local port to the Pod’s containerPort to access the running app locally:

      • kubectl port-forward pods/flask-pod -n flask 5000:5000

      Here we use port-forward to forward local port 5000 to the Pod’s containerPort 5000.

      Navigate to http://localhost:5000, where you should once again see the “Hello World” text generated by the Flask app. If you’re running kubectl on a remote dev server, replace localhost with your dev server’s external IP address.

      Feel free to play around with kubectl commands like kubectl describe to explore the Pod resource. When you’re done, delete the Pod using delete:

      • kubectl delete pod flask-pod -n flask

      Next, we’ll roll out this Pod in a scalable fashion using the Deployment resource. Print out the contents of the flask-deployment.yaml manifest file:

      • cat flask-deployment.yaml

      Output

      apiVersion: apps/v1 kind: Deployment metadata: name: flask-dep labels: app: flask-helloworld spec: replicas: 2 selector: matchLabels: app: flask-helloworld template: metadata: labels: app: flask-helloworld spec: containers: - name: flask image: hjdo/flask-helloworld:latest ports: - containerPort: 5000

      Here, we define a Deployment called flask-dep with an app: flask-helloworld Label. Next, we request 2 replicas of a Pod template identical to the template we previously used to deploy the Flask app Pod. The selector field matches the app: flask-helloworld Pod template to the Deployment.

      Roll out the Deployment using kubectl apply -f:

      • kubectl apply -f flask-deployment.yaml -n flask

      After a brief moment, the Deployment should be up and running in your cluster:

      • kubectl get deploy -n flask

      Output

      NAME READY UP-TO-DATE AVAILABLE AGE flask-dep 2/2 2 2 5s

      You can also pull up the individual Pods that are managed by the Deployment controller:

      Output

      NAME READY STATUS RESTARTS AGE flask-dep-876bd7677-bl4lg 1/1 Running 0 76s flask-dep-876bd7677-jbfpb 1/1 Running 0 76s

      To access the app, we have to forward a port inside of the cluster:

      • kubectl port-forward deployment/flask-dep -n flask 5000:5000

      This will forward local port 5000 to containerPort 5000 on one of the running Pods.

      You should be able to access the app at http://localhost:5000. If you’re running kubectl on a remote dev server, replace localhost with your dev server’s external IP address.

      At this point you can play around with commands like kubectl rollout and kubectl scale to experiment with rolling back Deployments and scaling them. To learn more about these and other kubectl commands, consult a kubectl Cheat Sheet.

      In the final step, we’ll expose this app to outside users using the LoadBalancer Service type, which will automatically provision a DigitalOcean cloud Load Balancer for the Flask app Service.

      Step 3 — Creating the App Service

      A Kubernetes Deployment allows the operator to flexibly scale a Pod template up or down, as well as manage rollouts and template updates. To create a stable network endpoint for this set of running Pod replicas, you can create a Kubernetes Service, which we’ll do here.

      Begin by inspecting the Service manifest file:

      Output

      apiVersion: v1 kind: Service metadata: name: flask-svc labels: app: flask-helloworld spec: type: LoadBalancer ports: - port: 80 targetPort: 5000 protocol: TCP selector: app: flask-helloworld

      This manifest defines a Service called flask-svc. We set the type to LoadBalancer to provision a DigitalOcean cloud Load Balancer that will route traffic to the Deployment Pods. To select the already running Deployment, the selector field is set to the Deployment’s app: flask-helloworld Label. Finally, we open up port 80 on the Load Balancer and instruct it to route traffic to the Pods’ containerPort 5000.

      To create the Service, use kubectl apply -f:

      • kubectl apply -f flask-service.yaml -n flask

      It may take a bit of time for Kubernetes to provision the cloud Load Balancer. You can track progress using the -w watch flag:

      Once you see an external IP for the flask-svc Service, navigate to it using your web browser. You should see the “Hello World” Flask app page.

      Conclusion

      This brief tutorial demonstrates how to containerize a minimal Flask app and deploy it to a Kubernetes cluster. It accompanies the meetup kit’s slides and speaker notes and GitHub repository.



      Source link