One place for hosting & domains

      Introdução

      Introdução ao Kubernetes: Um Guia de Referência Rápida do kubectl


      Introdução

      O Kubectl é uma ferramenta de linha de comando projetada para gerenciar objetos e clusters Kubernetes. Ele fornece uma interface de linha de comando para executar operações comuns, como criar e escalar Deployments, alternar contextos e acessar um shell em um container em execução.

      Como Usar Este Guia:

      • Este guia está no formato de referência rápida com trechos de linha de comando independentes.
      • Ele não é uma lista exaustiva de comandos kubectl, mas contém muitas operações e casos de uso comuns. Para uma referência mais completa, consulte a Documentação de referência do Kubectl
      • Vá para qualquer seção que seja relevante para a tarefa que você está tentando concluir.

      Pré-requisitos

      • Para usar o kubectl, você precisará de um cluster Kubernetes disponível para você. Para aprender a criar um cluster Kubernetes do zero, você pode consultar Como Criar um Cluster Kubernetes 1.11 Usando Kubeadm no Ubuntu 18.04. Alternativamente, você pode provisionar um cluster Kubernetes gerenciado em minutos usando o DigitalOcean Kubernetes. Para começar a criar um cluster Kubernetes gerenciado na DigitalOcean, consulte How to Create Kubernetes Clusters Using the Control Panel.
      • Você também precisará de uma máquina remota na qual instalará e executará o kubectl. O kubectl pode ser executado em diversos sistemas operacionais.

      Deployment de Exemplo

      Para demonstrar algumas das operações e comandos nesta referência rápida, usaremos um exemplo de Deployment que executa duas réplicas do Nginx:

      nginx-deployment.yaml

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nginx-deployment
      spec:
        replicas: 2
        selector:
          matchLabels:
            app: nginx
        template:
          metadata:
            labels:
              app: nginx
          spec:
            containers:
            - name: nginx
              image: nginx
              ports:
              - containerPort: 80
      

      Copie e cole esse manifesto em um arquivo chamado nginx-deployment.yaml.

      Instalando o kubectl

      Nota: Esses comandos foram testados somente em uma máquina Ubuntu 18.04. Para aprender como instalar o kubectl em outros sistemas operacionais, consulte Install and Set Up kubectl da documentação do Kubernetes.

      Primeiro, atualize o índice local de pacotes e instale as dependências necessárias:

      • sudo apt-get update && sudo apt-get install -y apt-transport-https

      Em seguida, adicione a chave GPG do Google Cloud ao APT e disponibilize o pacote kubectl no seu sistema:

      • curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
      • echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list
      • sudo apt-get update

      Por fim, instale o kubectl:

      • sudo apt-get install -y kubectl

      Teste se a instalação foi bem-sucedida usando version:

      Configurando o Autocompletar no Shell

      Nota: Esses comandos foram testados somente em uma máquina Ubuntu 18.04. Para saber como configurar o Autocompletar em outros sistemas operacionais, consulte Install and Set Up kubectl da documentação do Kubernetes.

      O kubectl inclui um script de autocompletar no shell que você pode disponibilizar para o software de autocompletar do shell existente no sistema.

      Instalando o Autocompletar do kubectl

      Primeiro, verifique se você tem o bash-completion instalado:

      Você deve ver alguma saída do script.

      Em seguida, faça um source no script de autocompletar do kubectl em seu arquivo ~/.bashrc:

      • echo 'source <(kubectl completion bash)' >>~/.bashrc
      • . ~/.bashrc

      Alternativamente, você pode adicionar o script de autocompletar ao diretório /etc/bash_completion.d:

      • kubectl completion bash >/etc/bash_completion.d/kubectl

      Uso

      Para usar o recurso de autocompletar, pressione a tecla TAB para exibir os comandos kubectl disponíveis:

      Output

      annotate apply autoscale completion cordon delete drain explain kustomize options port-forward rollout set uncordon api-resources attach certificate config cp describe . . .

      Você também pode exibir os comandos disponíveis após digitar parcialmente um comando:

      Output

      delete describe diff drain

      Conectando, Configurando e Usando Contextos

      Conectando

      Para testar se o kubectl pode se autenticar e acessar seu cluster Kubernetes, use cluster-info:

      Se o kubectl puder se autenticar com sucesso no seu cluster, você deverá ver a seguinte saída:

      Output

      Kubernetes master is running at https://kubernetes_master_endpoint CoreDNS is running at https://coredns_endpoint To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

      O kubectl é configurado usando os arquivos de configuração kubeconfig. Por padrão, o kubectl procurará um arquivo chamado config no diretório $HOME/.kube. Para mudar isso, você pode definir a variável de ambiente $KUBECONFIG apontando para um arquivo kubeconfig personalizado ou passar o arquivo personalizado em tempo de execução usando a flag --kubeconfig:

      • kubectl cluster-info --kubeconfig=caminho_para_seu_arquivo_kubeconfig

      Nota: Se você estiver usando um cluster Kubernetes gerenciado, seu provedor de nuvem deverá ter disponibilizado seu arquivo kubeconfig.

      Se você não quiser usar a flag --kubeconfig com todos os comandos, e não existe o arquivo ~/.kube/config, crie um diretório chamado ~/.kube no seu diretório home, se ele ainda não existir, e copie o arquivo kubeconfig, renomeando-o para config:

      • mkdir ~/.kube
      • cp seu_arquivo_kubeconfig ~/.kube/config

      Agora, execute cluster-info novamente para testar sua conexão.

      Modificando Sua Configuração do kubectl

      Você também pode modificar sua configuração usando o conjunto de comandos kubectl config.

      Para visualizar sua configuração do kubectl, use o subcomando view:

      Output

      apiVersion: v1 clusters: - cluster: certificate-authority-data: DATA+OMITTED . . .

      Modificando Clusters

      Para buscar uma lista de clusters definidos no seu kubeconfig, use get-clusters:

      • kubectl config get-clusters

      Output

      NAME do-nyc1-sammy

      Para adicionar um cluster à sua configuração, use o subcomando set-cluster:

      • kubectl config set-cluster novo_cluster --server=endereço_do_servidor --certificate-authority=caminho_para_a_autoridade_de_certificação

      Para excluir um cluster da sua configuração, use delete-cluster:

      Nota: Isso exclui apenas o cluster da sua configuração e não exclui o cluster Kubernetes real.

      • kubectl config delete-cluster

      Modificando Usuários

      Você pode executar operações similares para usuários usando set-credentials:

      • kubectl config set-credentials username --client-certificate=/caminho/para/arquivo/certificado --client-key=/caminho/para/arquivo/chave

      Para excluir um usuário da sua configuração, você pode executar unset:

      • kubectl config unset users.username

      Contextos

      Um context ou contexto no Kubernetes é um objeto que contém um conjunto de parâmetros de acesso para o seu cluster. Ele consiste em uma tripla de cluster, namespace e user. Os contextos permitem alternar rapidamente entre diferentes conjuntos de configurações de cluster.

      Para ver seu contexto atual, você pode usar current-context:

      • kubectl config current-context

      Output

      do-nyc1-sammy

      Para ver uma lista de todos os contextos configurados, execute get-contexts:

      • kubectl config get-contexts

      Output

      CURRENT NAME CLUSTER AUTHINFO NAMESPACE * do-nyc1-sammy do-nyc1-sammy do-nyc1-sammy-admin

      Para definir um contexto, use set-context:

      • kubectl config set-context nome_do_contexto --cluster=nome_do_cluster --user=user_name --namespace=namespace

      Você pode alternar entre contextos com use-context:

      • kubectl config use-context nome_do_contexto

      Output

      Switched to context "do-nyc1-sammy"

      E você pode excluir um contexto com delete-context:

      • kubectl config delete-context nome_do_contexto

      Usando Namespaces

      Um Namespace no Kubernetes é uma abstração que lhe permite subdividir seu cluster em vários clusters virtuais. Usando Namespaces, você pode dividir os recursos do cluster entre várias equipes e objetos de escopo de maneira apropriada. Por exemplo, você pode ter um Namespace prod para cargas de trabalho de produção e um Namespace dev para cargas de trabalho de desenvolvimento e teste.

      Para buscar e imprimir uma lista de todos os Namespaces no cluster, use get namespace:

      Output

      NAME STATUS AGE default Active 2d21h kube-node-lease Active 2d21h kube-public Active 2d21h kube-system Active 2d21h

      Para definir um Namespace para o seu contexto atual, use set-context --current:

      • kubectl config set-context --current --namespace=nome_do_namespace

      Para criar um Namespace, use create namespace:

      • kubectl create namespace namespace_name

      Output

      namespace/sammy created

      De maneira similar, para excluir um Namespace, use delete namespace:

      Atenção: A exclusão de um Namespace excluirá tudo no Namespace, incluindo a execução de Deployments, Pods e outras cargas de trabalho. Execute este comando apenas se tiver certeza de que deseja eliminar o que está sendo executado no Namespace ou se estiver excluindo um Namespace vazio.

      • kubectl delete namespace nome_do_namespace

      Para buscar todos os Pods em um determinado Namespace ou para realizar outras operações nos recursos de um determinado Namespace, certifique-se de incluir a flag --namespace:

      • kubectl get pods --namespace=nome_do_namespace

      Gerenciando Recursos do Kubernetes

      Sintaxe Geral

      A sintaxe geral para a maioria dos comandos de gerenciamento do kubectl é:

      • kubectl command type name flags

      Onde

      • command é uma operação que você gostaria de executar, como create
      • type é o tipo de recurso do Kubernetes, como deployment
      • name é o nome do recurso, como app_frontend
      • flags são todas as flags opcionais que você gostaria de incluir

      Por exemplo, o comando a seguir recupera informações sobre um Deployment chamado app_frontend:

      • kubectl get deployment app_frontend

      Gestão Declarativa e kubectl apply

      A abordagem recomendada para gerenciar cargas de trabalho no Kubernetes é confiar no design declarativo do cluster o máximo possível. Isso significa que, em vez de executar uma série de comandos para criar, atualizar, excluir e reiniciar a execução de Pods, você deve definir as cargas de trabalho, serviços e sistemas que deseja executar nos arquivos de manifesto YAML e fornecer esses arquivos ao Kubernetes, que cuidará do resto.

      Na prática, isso significa usar o comando kubectl apply, que aplica uma configuração específica a um determinado recurso. Se o recurso de destino não existir, o Kubernetes criará o recurso. Se o recurso já existir, o Kubernetes salvará a revisão atual e atualizará o recurso de acordo com a nova configuração. Essa abordagem declarativa existe em contraste com a abordagem imperativa de executar o conjunto de comandos kubectl create, kubectl edit e kubectl scale para gerenciar recursos. Para saber mais sobre as diferentes maneiras de gerenciar os recursos do Kubernetes, consulte Gerenciamento de objetos do Kubernetes na documentação do Kubernetes.

      Lançando um Deployment

      Por exemplo, para fazer o deploy de exemplo do Nginx em seu cluster, use apply e forneça o caminho para o arquivo de manifesto nginx-deployment.yaml:

      • kubectl apply -f nginx-deployment.yaml

      Output

      deployment.apps/nginx-deployment created

      A flag -f é usada para especificar um nome de arquivo ou URL contendo uma configuração válida. Se você deseja aplicar todos os manifestos de um diretório, você pode usar a flag -k:

      • kubectl apply -k diretório_do_manifesto

      Você pode acompanhar o status do deployment usando rollout status:

      • kubectl rollout status deployment/nginx-deployment

      Output

      Waiting for deployment "nginx-deployment" rollout to finish: 1 of 2 updated replicas are available... deployment "nginx-deployment" successfully rolled out

      Um alternativa ao rollout status é o comando kubectl get, juntamente com a flag -w (watch):

      • kubectl get deployment -w

      Output

      NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 0/2 2 0 3s nginx-deployment 1/2 2 1 3s nginx-deployment 2/2 2 2 3s

      Usando rollout pause e rollout resume, você pode pausar e retomar o lançamento ou rollout de um Deployment:

      • kubectl rollout pause deployment/nginx-deployment

      Output

      deployment.extensions/nginx-deployment paused
      • kubectl rollout resume deployment/nginx-deployment

      Output

      deployment.extensions/nginx-deployment resumed

      Modificando um Deployment em Execução

      Se você quiser modificar um Deployment em execução, poderá fazer alterações no seu arquivo de manifesto e, em seguida, executar o kubectl apply novamente para aplicar a atualização. Por exemplo, vamos modificar o arquivo nginx-deployment.yaml para alterar o número de réplicas de 2 para 3:

      nginx-deployment.yaml

      . . .
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: nginx
      . . .
      

      O comando kubectl diff permite que você veja diferenças entre os recursos em execução no momento e as alterações propostas no arquivo de configuração fornecido:

      • kubectl diff -f nginx-deployment.yaml

      Agora permita que o Kubernetes execute a atualização usando apply:

      • kubectl apply -f nginx-deployment.yaml

      A execução de outro get deployment deve confirmar a adição de uma terceira réplica.

      Se você executar apply novamente sem modificar o arquivo de manifesto, o Kubernetes detectará que nenhuma alteração foi feita e não executará nenhuma ação.

      Usando o rollout history, você pode ver uma lista das revisões anteriores do Deployment:

      • kubectl rollout history deployment/nginx-deployment

      Output

      deployment.extensions/nginx-deployment REVISION CHANGE-CAUSE 1 <none>

      Com rollout undo, você pode reverter um Deployment para qualquer uma das revisões anteriores:

      • kubectl rollout undo deployment/nginx-deployment --to-revision=1

      Excluindo um Deployment

      Para excluir um deployment em execução, use kubectl delete:

      • kubectl delete -f nginx-deployment.yaml

      Output

      deployment.apps "nginx-deployment" deleted

      Gerenciamento Imperativo

      Você também pode usar um conjunto de comandos imperativos para manipular e gerenciar diretamente os recursos do Kubernetes.

      Criando um Deployment

      Use create para criar um objeto a partir de um arquivo, URL ou STDIN. Observe que, ao contrário de apply, se um objeto com o mesmo nome já existir, a operação irá falhar. A flag --dry-run lhe permite visualizar o resultado da operação sem realmente executá-la:

      • kubectl create -f nginx-deployment.yaml --dry-run

      Output

      deployment.apps/nginx-deployment created (dry-run)

      Agora podemos criar o objeto:

      • kubectl create -f nginx-deployment.yaml

      Output

      deployment.apps/nginx-deployment created

      Modificando um Deployment em Execução

      Use scale para escalar o número de réplicas para o Deployment de 2 para 4:

      • kubectl scale --replicas=4 deployment/nginx-deployment

      Output

      deployment.extensions/nginx-deployment scaled

      Você pode editar qualquer objeto localmente usando o kubectl edit. Isso abrirá o manifesto do objeto no seu editor padrão:

      • kubectl edit deployment/nginx-deployment

      Você deve ver o seguinte arquivo de manifesto em seu editor:

      nginx-deployment

      # Please edit the object below. Lines beginning with a "https://www.digitalocean.com/#" will be ignored,
      # and an empty file will abort the edit. If an error occurs while saving this file will be
      # reopened with the relevant failures.
      #
      apiVersion: extensions/v1beta1
      kind: Deployment
      . . . 
      spec:
        progressDeadlineSeconds: 600
        replicas: 4
        revisionHistoryLimit: 10
        selector:
          matchLabels:
      . . .
      

      Altere o valor das replicas de 4 para 2, depois salve e feche o arquivo.

      Agora execute um get para inspecionar as alterações:

      • kubectl get deployment/nginx-deployment

      Output

      NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 2/2 2 2 6m40s

      Escalamos o Deployment com êxito de volta para duas réplicas on-the-fly (ou seja, durante a operação). Você pode atualizar a maioria dos campos de um objeto do Kubernetes de maneira semelhante.

      Outro comando útil para modificar objetos localmente é o kubectl patch. Usando o patch, você pode atualizar os campos de um objeto on-the-fly, sem precisar abrir o seu editor. O patch também permite atualizações mais complexas com várias estratégias de mesclagem e correção. Para saber mais sobre isso, consulte Update API Objects in Place Using kubectl patch.

      O comando a seguir irá corrigir o objeto nginx-deployment para atualizar o campo replicas de 2 para 4; deploy é uma abreviação para o objeto deployment.

      • kubectl patch deploy nginx-deployment -p '{"spec": {"replicas": 4}}'

      Output

      deployment.extensions/nginx-deployment patched

      Agora podemos inspecionar as alterações:

      • kubectl get deployment/nginx-deployment

      Output

      NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 4/4 4 4 18m

      Você também pode criar um Deployment imperativamente usando o comando run. O run criará um Deployment usando uma imagem fornecida como parâmetro:

      • kubectl run nginx-deployment --image=nginx --port=80 --replicas=2

      O comando expose permite expor rapidamente um Deployment em execução como um Serviço Kubernetes, permitindo conexões de fora do seu cluster Kubernetes:

      • kubectl expose deploy nginx-deployment --type=LoadBalancer --port=80 --name=nginx-svc

      Output

      service/nginx-svc exposed

      Aqui, expusemos o Deployment nginx-deployment como um serviço LoadBalancer, abrindo a porta 80 para o tráfego externo e direcionando-a para a porta 80 do container. Nomeamos o serviço como nginx-svc. Usando o tipo de Serviço LoadBalancer, um balanceador de carga em nuvem é automaticamente provisionado e configurado pelo Kubernetes. Para obter o endereço IP externo do Serviço, use get:

      • kubectl get svc nginx-svc

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-svc LoadBalancer 10.245.26.242 203.0.113.0 80:30153/TCP 22m

      Você pode acessar os containers Nginx em execução indo até o EXTERNAL-IP no seu navegador web.

      Inspecionando Cargas de Trabalho e Debugando

      Existem vários comandos que você pode usar para obter mais informações sobre cargas de trabalho em execução no seu cluster.

      Inspecionando Recursos no Kubernetes

      O kubectl get busca um determinado recurso do Kubernetes e exibe algumas informações básicas associadas a ele:

      • kubectl get deployment -o wide

      Output

      NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR nginx-deployment 4/4 4 4 29m nginx nginx app=nginx

      Como não fornecemos um nome de Deployment ou um Namespace, o kubectl busca todos os Deployments no Namespace atual. A flag -o fornece informações adicionais como CONTAINERS e IMAGES.

      Além do get, você pode usar o describe para buscar uma descrição detalhada do recurso e dos recursos associados:

      • kubectl describe deploy nginx-deployment

      Output

      Name: nginx-deployment Namespace: default CreationTimestamp: Wed, 11 Sep 2019 12:53:42 -0400 Labels: run=nginx-deployment Annotations: deployment.kubernetes.io/revision: 1 Selector: run=nginx-deployment . . .

      O conjunto de informações apresentadas variará dependendo do tipo de recurso. Você também pode usar este comando sem especificar um nome de recurso; nesse caso, as informações serão fornecidas para todos os recursos desse tipo no Namespace atual.

      O explain permite que você puxe rapidamente campos configuráveis para um determinado tipo de recurso:

      • kubectl explain deployment.spec

      Ao acrescentar campos adicionais, você pode mergulhar mais fundo na hierarquia de campos:

      • kubectl explain deployment.spec.template.spec

      Obtendo Acesso ao Shell de um Container

      Para obter acesso ao shell de um container em execução, use exec. Primeiro, encontre o Pod que contém o container em execução ao qual você deseja acessar:

      Output

      nginx-deployment-8859878f8-7gfw9 1/1 Running 0 109m nginx-deployment-8859878f8-z7f9q 1/1 Running 0 109m

      Vamos fazer um exec para o primeiro Pod. Como este Pod possui apenas um container, não precisamos usar a flag -c para especificar em qual container gostaríamos de fazer o exec.

      • kubectl exec -i -t nginx-deployment-8859878f8-7gfw9 -- /bin/bash

      Output

      root@nginx-deployment-8859878f8-7gfw9:/#

      Agora você tem acesso ao shell do container Nginx. A flag -i passa o STDIN para o container e -t fornece um TTY interativo. O traço duplo -- atua como um separador para o comando kubectl e o comando que você deseja executar dentro do container. Neste caso, estamos executando o /bin/bash.

      Para executar comandos dentro do container sem abrir um shell completo, omita as flags -i e -t e substitua o comando que você deseja executar em vez de /bin/bash:

      • kubectl exec nginx-deployment-8859878f8-7gfw9 ls

      Output

      bin boot dev etc home lib lib64 media . . .

      Buscando Logs

      Outro comando útil é o logs, que imprime logs de Pods e containers, incluindo containers finalizados.

      Para transmitir logs para a saída do seu terminal, você pode usar a flag -f:

      • kubectl logs -f nginx-deployment-8859878f8-7gfw9

      Output

      10.244.2.1 - - [12/Sep/2019:17:21:33 +0000] "GET / HTTP/1.1" 200 612 "-" "203.0.113.0" "-" 2019/09/16 17:21:34 [error] 6#6: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 10.244.2.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "203.0.113.0", referrer: "http://203.0.113.0" . . .

      Este comando continuará sendo executado no seu terminal até ser interrompido com um CTRL+C. Você pode omitir a flag -f se quiser imprimir a saída do log e sair imediatamente.

      Você também pode usar a flag -p para buscar logs de um container terminado. Quando esta opção é usada dentro de um Pod que tinha uma instância anterior do container em execução, logs imprimirá a saída do container finalizado:

      • kubectl logs -p nginx-deployment-8859878f8-7gfw9

      A flag -c lhe permite especificar o container do qual você deseja buscar logs, se o Pod tiver vários containers. Você pode usar a flag --all-containers=true para buscar logs de todos os containers no Pod.

      Redirecionamento de Porta e Proxying

      Para obter acesso de rede a um Pod, você pode usar o port-forward:

      • sudo kubectl port-forward pod/nginx-deployment-8859878f8-7gfw9 80:80

      Output

      Forwarding from 127.0.0.1:80 -> 80 Forwarding from [::1]:80 -> 80

      Neste caso, usamos sudo porque a porta 80 local é uma porta protegida. Para a maioria das outras portas, você pode omitir o sudo e executar o comando kubectl como seu usuário do sistema.

      Aqui redirecionamos a porta 80 local (que antecede os dois pontos) para a porta 80 do container do Pod (após os dois pontos).

      Você também pode usar deploy/nginx-deployment como tipo e nome do recurso para o qual redirecionar. Se você fizer isso, a porta local será redirecionada para o Pod selecionado pelo Deployment.

      O comando proxy pode ser usado para acessar o servidor de API do Kubernetes localmente:

      • kubectl proxy --port=8080

      Output

      Starting to serve on 127.0.0.1:8080

      Em outro shell, use curl para explorar a API:

      • curl http://localhost:8080/api/

      Output

      { "kind": "APIVersions", "versions": [ "v1" ], "serverAddressByClientCIDRs": [ { "clientCIDR": "0.0.0.0/0", "serverAddress": "203.0.113.0:443" } ]

      Feche o proxy pressionando CTRL-C.

      Conclusão

      Este guia aborda alguns dos comandos mais comuns do kubectl que você pode usar ao gerenciar um cluster Kubernetes e as cargas de trabalho deployadas nele.

      Você pode aprender mais sobre o kubectl consultando a documentação de referência oficial do Kubernetes.

      Existem muitos outros comandos e variações que você pode achar úteis como parte do seu trabalho com o kubectl. Para saber mais sobre todas as suas opções disponíveis, você pode executar:



      Source link

      Uma Introdução aos Service Meshes


      Introdução

      Um service mesh é uma camada de infraestrutura que permite gerenciar a comunicação entre os microsserviços da sua aplicação. À medida que mais desenvolvedores trabalham com microsserviços, os service meshes evoluíram para tornar esse trabalho mais fácil e mais eficaz consolidando tarefas administrativas e de gerenciamento comuns em uma configuração distribuída.

      Aplicar uma abordagem de microsserviço à arquitetura de aplicações envolve dividir sua aplicação em uma coleção de serviços fracamente acoplados. Essa abordagem oferece certos benefícios: as equipes podem iterar projetos e escalar rapidamente, usando uma variedade maior de ferramentas e linguagens. Por outro lado, os microsserviços representam novos desafios para a complexidade operacional, consistência de dados e segurança.

      Service meshes são projetados para resolver alguns desses desafios, oferecendo um nível granular de controle sobre como os serviços se comunicam uns com os outros. Especificamente, eles oferecem aos desenvolvedores uma maneira de gerenciar:

      • Descoberta de serviço
      • Roteamento e configuração de tráfego
      • Criptografia e autenticação/autorização
      • Métricas e monitoramento

      Embora seja possível executar essas tarefas de forma nativa com orquestradores de containers como o Kubernetes, essa abordagem envolve uma maior quantidade de tomadas de decisão e administração antecipadas quando comparada com o que as soluções de service mesh como o Istio e o Linkerd oferecem por fora. Nesse sentido, service meshes podem agilizar e simplificar o processo de trabalho com componentes comuns em uma arquitetura de microsserviço. Em alguns casos, eles podem até ampliar a funcionalidade desses componentes.

      Por que Service Meshes?

      Service meshes são projetados para resolver alguns dos desafios inerentes às arquiteturas de aplicações distribuídas.

      Essas arquiteturas cresceram a partir do modelo de aplicação de três camadas, que dividia as aplicações em uma camada web, uma camada de aplicação e uma camada de banco de dados. Ao escalar, esse modelo se mostrou desafiador para organizações que experimentam um rápido crescimento. Bases de código de aplicações monolíticas podem se tornar bagunçadas, conhecidas como “big balls of mud”, impondo desafios para o desenvolvimento e o deployment.

      Em resposta a esse problema, organizações como Google, Netflix e Twitter desenvolveram bibliotecas “fat client” internas para padronizar as operações de runtime entre os serviços. Essas bibliotecas forneceram balanceamento de carga, circuit breaker , roteamento e telemetria — precursores para recursos de service mesh. No entanto, eles também impuseram limitações às linguagens que os desenvolvedores poderiam usar e exigiram mudanças nos serviços quando eles próprios foram atualizados ou alterados.

      Um design de microsserviço evita alguns desses problemas. Em vez de ter uma base de código grande e centralizada de aplicações, você tem uma coleção de serviços gerenciados discretamente que representam um recurso da sua aplicação. Os benefícios de uma abordagem de microsserviço incluem:

      • Maior agilidade no desenvolvimento e no deployment, já que as equipes podem trabalhar e fazer deploy de diferentes recursos de aplicações de forma independente.
      • Melhores opções para CI/CD, já que microsserviços individuais podem ser testados e terem deploys refeitos independentemente.
      • Mais opções para linguagens e ferramentas. Os desenvolvedores podem usar as melhores ferramentas para as tarefas em questão, em vez de se restringirem a uma determinada linguagem ou conjunto de ferramentas.
      • Facilidade de escalar.
      • Melhorias no tempo de atividade, experiência do usuário e estabilidade.

      Ao mesmo tempo, os microsserviços também criaram desafios:

      • Sistemas distribuídos exigem diferentes maneiras de pensar sobre latência, roteamento, fluxos de trabalho assíncronos e falhas.
      • As configurações de microsserviço podem não atender necessariamente aos mesmos requisitos de consistência de dados que as configurações monolíticas.
      • Níveis maiores de distribuição exigem designs operacionais mais complexos, particularmente quando se trata de comunicação de serviço a serviço.
      • A distribuição de serviços aumenta a área de superfície para vulnerabilidades de segurança.

      Service meshes são projetados para resolver esses problemas, oferecendo controle coordenado e granular sobre como os serviços se comunicam. Nas seções a seguir, veremos como service meshes facilitam a comunicação de serviço a serviço por meio da descoberta de serviços, roteamento e balanceamento interno de carga, configuração de tráfego, criptografia, autenticação e autorização, métricas e monitoramento. Vamos utilizar a aplicação de exemplo Bookinfo do Istio — quatro microsserviços que juntos exibem informações sobre determinados livros — como um exemplo concreto para ilustrar como os service meshes funcionam.

      Descoberta de Serviço

      Em um framework distribuído, é necessário saber como se conectar aos serviços e saber se eles estão ou não disponíveis. Os locais das instâncias de serviço são atribuídos dinamicamente na rede e as informações sobre eles estão em constante mudança, à medida que os containers são criados e destruídos por meio do escalonamento automático, upgrades e falhas.

      Historicamente, existiram algumas ferramentas para fazer a descoberta de serviços em uma estrutura de microsserviço. Repositórios de chave-valor como o etcd foram emparelhados com outras ferramentas como o Registrator para oferecer soluções de descoberta de serviços. Ferramentas como o Consul iteraram isso combinando um armazenamento de chave-valor com uma interface de DNS que permite aos usuários trabalhar diretamente com seu servidor ou nó DNS.

      Tomando uma abordagem semelhante, o Kubernetes oferece descoberta de serviço baseada em DNS por padrão. Com ele, você pode procurar serviços e portas de serviço e fazer pesquisas inversas de IP usando convenções comuns de nomenclatura de DNS. Em geral, um registro A para um serviço do Kubernetes corresponde a esse padrão: serviço.namespace.svc.cluster.local. Vamos ver como isso funciona no contexto do aplicativo Bookinfo. Se, por exemplo, você quisesse informações sobre o serviço details do aplicativo Bookinfo, poderia ver a entrada relevante no painel do Kubernetes:

      Details Service in Kubernetes Dash

      Isto lhe dará informações relevantes sobre o nome do serviço, namespace e ClusterIP, que você pode usar para se conectar ao seu serviço, mesmo que os containers individuais sejam destruídos e recriados.

      Um service mesh como o Istio também oferece recursos de descoberta de serviço. Para fazer a descoberta de serviços, o Istio confia na comunicação entre a API do Kubernetes, o próprio plano de controle do Istio, gerenciado pelo componente de gerenciamento de tráfego Pilot, e seu plano de dados, gerenciado pelos proxies sidecar Envoy. O Pilot interpreta os dados do servidor da API do Kubernetes para registrar as alterações nos locais do Pod. Em seguida, ele converte esses dados em uma representação canônica Istio e os encaminha para os proxies sidecar.

      Isso significa que a descoberta de serviço no Istio é independente de plataforma, o que podemos ver usando o add-on Grafana do Istio para olhar o serviço details novamente no painel de serviço do Istio:

      Details Service Istio Dash

      Nossa aplicação está sendo executada em um cluster Kubernetes, então, mais uma vez, podemos ver as informações relevantes do DNS sobre o Serviço details, juntamente com outros dados de desempenho.

      Em uma arquitetura distribuída, é importante ter informações atualizadas, precisas e fáceis de localizar sobre serviços. Tanto o Kubernetes quanto os service meshes, como o Istio, oferecem maneiras de obter essas informações usando convenções do DNS.

      Configuração de Roteamento e Tráfego

      Gerenciar o tráfego em uma estrutura distribuída significa controlar como o tráfego chega ao seu cluster e como ele é direcionado aos seus serviços. Quanto mais controle e especificidade você tiver na configuração do tráfego externo e interno, mais você poderá fazer com sua configuração. Por exemplo, nos casos em que você está trabalhando com deployments piloto (canary), migrando aplicativos para novas versões ou testando serviços específicos por meio de injeção de falhas, ter a capacidade de decidir quanto tráfego seus serviços estão obtendo e de onde ele vem será a chave para o sucesso de seus objetivos.

      O Kubernetes oferece diferentes ferramentas, objetos e serviços que permitem aos desenvolvedores controlar o tráfego externo para um cluster: kubectl proxy, NodePort, Load Balancers, e Ingress Controllers and Resources. O kubectl proxy e o NodePort permitem expor rapidamente seus serviços ao tráfego externo: O kubectl proxy cria um servidor proxy que permite acesso ao conteúdo estático com um caminho HTTP, enquanto o NodePort expõe uma porta designada aleatoriamente em cada node. Embora isso ofereça acesso rápido, as desvantagens incluem ter que executar o kubectl como um usuário autenticado, no caso do kubectl proxy, e a falta de flexibilidade nas portas e nos IPs do node, no caso do NodePort. E, embora um Balanceador de Carga otimize a flexibilidade ao se conectar a um serviço específico, cada serviço exige seu próprio Balanceador de Carga, o que pode custar caro.

      Um Ingress Resource e um Ingress Controller juntos oferecem um maior grau de flexibilidade e configuração em relação a essas outras opções. O uso de um Ingress Controller com um Ingress Resource permite rotear o tráfego externo para os serviços e configurar o roteamento interno e o balanceamento de carga. Para usar um Ingress Resource, você precisa configurar seus serviços, o Ingress Controller e o LoadBalancer e o próprio Ingress Resource, que especificará as rotas desejadas para os seus serviços. Atualmente, o Kubernetes suporta seu próprio Controlador Nginx, mas há outras opções que você pode escolher também, gerenciadas pelo Nginx, Kong, e outros.

      O Istio itera no padrão Controlador/Recurso do Kubernetes com Gateways do Istio e VirtualServices. Como um Ingress Controller, um gateway define como o tráfego de entrada deve ser tratado, especificando as portas e os protocolos expostos a serem usados. Ele funciona em conjunto com um VirtualService, que define rotas para serviços dentro da malha ou mesh. Ambos os recursos comunicam informações ao Pilot, que encaminha essas informações para os proxies Envoy. Embora sejam semelhantes ao Ingress Controllers and Resources, os Gateways e os VirtualServices oferecem um nível diferente de controle sobre o tráfego: em vez de combinar camadas e protocolos Open Systems Interconnection (OSI), Gateways e VirtualServices permitem diferenciar entre as camadas OSI nas suas configurações. Por exemplo, usando VirtualServices, as equipes que trabalham com especificações de camada de aplicação podem ter interesses diferenciados das equipes de operações de segurança que trabalham com diferentes especificações de camada. Os VirtualServices possibilitam separar o trabalho em recursos de aplicações distintos ou em diferentes domínios de confiança e podem ser usados para testes como canary, rollouts graduais, testes A/B, etc.

      Para visualizar a relação entre os serviços, você pode usar o add-on Servicegraph do Istio, que produz uma representação dinâmica da relação entre os serviços usando dados de tráfego em tempo real. A aplicação Bookinfo pode se parecer com isso sem qualquer roteamento personalizado aplicado:

      Bookinfo service graph

      Da mesma forma, você pode usar uma ferramenta de visualização como o Weave Scope para ver a relação entre seus serviços em um determinado momento. A aplicação Bookinfo sem roteamento avançado pode ter esta aparência:

      Weave Scope Service Map

      Ao configurar o tráfego de aplicações em uma estrutura distribuída, há várias soluções diferentes — de opções nativas do Kubernetes até service meshes como o Istio — que oferecem várias opções para determinar como o tráfego externo chegará até seus recursos de aplicação e como esses recursos se comunicarão entre si.

      Criptografia e Autenticação/Autorização

      Um framework distribuído apresenta oportunidades para vulnerabilidades de segurança. Em vez de se comunicarem por meio de chamadas internas locais, como aconteceria em uma configuração monolítica, os serviços em uma arquitetura de microsserviço transmitem informações, incluindo informações privilegiadas, pela rede. No geral, isso cria uma área de superfície maior para ataques.

      Proteger os clusters do Kubernetes envolve uma variedade de procedimentos; Vamos nos concentrar em autenticação, autorização e criptografia. O Kubernetes oferece abordagens nativas para cada um deles:

      • Autenticação: As solicitações de API no Kubernetes estão vinculadas a contas de usuário ou serviço, que precisam ser autenticadas. Existem várias maneiras diferentes de gerenciar as credenciais necessárias: Tokens estáticos, tokens de bootstrap, certificados de cliente X509 e ferramentas externas, como o OpenID Connect.
      • Autorização: O Kubernetes possui diferentes módulos de autorização que permitem determinar o acesso com base em funções como papéis, atributos e outras funções especializadas. Como todas as solicitações ao servidor da API são negadas por padrão, cada parte de uma solicitação da API deve ser definida por uma política de autorização.
      • Criptografia: Pode referir-se a qualquer um dos seguintes: conexões entre usuários finais e serviços, dados secretos, terminais no plano de controle do Kubernetes e comunicação entre componentes worker do cluster e componentes master. O Kubernetes tem diferentes soluções para cada um deles:

      A configuração de políticas e protocolos de segurança individuais no Kubernetes requer investimento administrativo. Um service mesh como o Istio pode consolidar algumas dessas atividades.

      O Istio foi projetado para automatizar parte do trabalho de proteção dos serviços. Seu plano de controle inclui vários componentes que lidam com segurança:

      • Citadel: gerencia chaves e certificados.
      • Pilot: supervisiona as políticas de autenticação e nomenclatura e compartilha essas informações com os proxies Envoy.
      • Mixer: gerencia autorização e auditoria.

      Por exemplo, quando você cria um serviço, o Citadel recebe essa informação do kube-apiserver e cria certificados e chaves SPIFFE para este serviço. Em seguida, ele transfere essas informações para Pods e sidecars Envoy para facilitar a comunicação entre os serviços.

      Você também pode implementar alguns recursos de segurança habilitando o TLS mútuo durante a instalação do Istio. Isso inclui identidades de serviço fortes para comunicação interna nos clusters e entre clusters, comunicação segura de serviço para serviço e de usuários para serviço, e um sistema de gerenciamento de chaves capaz de automatizar a criação, a distribuição e a rotação de chaves e certificados.

      Ao iterar em como o Kubernetes lida com autenticação, autorização e criptografia, service meshes como o Istio são capazes de consolidar e estender algumas das melhores práticas recomendadas para a execução de um cluster seguro do Kubernetes.

      Métricas e Monitoramento

      Ambientes distribuídos alteraram os requisitos para métricas e monitoramento. As ferramentas de monitoramento precisam ser adaptativas, respondendo por mudanças frequentes em serviços e endereços de rede, e abrangentes, permitindo a quantidade e o tipo de informações que passam entre os serviços.

      O Kubernetes inclui algumas ferramentas internas de monitoramento por padrão. Esses recursos pertencem ao seu pipeline de métricas de recursos, que garante que o cluster seja executado conforme o esperado. O componente cAdvisor coleta estatísticas de uso de rede, memória e CPU de containers e nodes individuais e passa essas informações para o kubelet; o kubelet, por sua vez, expõe essas informações por meio de uma API REST. O servidor de métricas obtém essas informações da API e as repassa para o kube-aggregator para formatação.

      Você pode estender essas ferramentas internas e monitorar os recursos com uma solução completa de métricas. Usando um serviço como o Prometheus como um agregador de métricas, você pode criar uma solução diretamente em cima do pipeline de métricas de recursos do Kubernetes. O Prometheus integra-se diretamente ao cAdvisor através de seus próprios agentes, localizados nos nodes. Seu principal serviço de agregação coleta e armazena dados dos nodes e os expõe através de painéis e APIs. Opções adicionais de armazenamento e visualização também estão disponíveis se você optar por integrar seu principal serviço de agregação com ferramentas de backend de armazenamento, registro e visualização, como InfluxDB, Grafana, ElasticSearch, Logstash, Kibana, e outros.

      Em um service mesh como o Istio, a estrutura do pipeline completo de métricas faz parte do design da malha. Os sidecars do Envoy operando no nível do Pod comunicam as métricas ao Mixer, que gerencia políticas e telemetria. Além disso, os serviços Prometheus e Grafana estão habilitados por padrão (embora se você estiver instalando o Istio com o Helm você precisará especificar granafa.enabled=true durante a instalação). Como no caso do pipeline completo de métricas, você também pode configurar outros serviços e deployments para opções de registro e visualização.

      Com essas ferramentas de métrica e visualização, você pode acessar informações atuais sobre serviços e cargas de trabalho em um local central. Por exemplo, uma visão global do aplicativo BookInfo pode ter esta aparência no painel Grafana do Istio:

      Bookinfo services from Grafana dash

      Ao replicar a estrutura de um pipeline completo de métricas do Kubernetes e simplificar o acesso a alguns de seus componentes comuns, service meshes como o Istio agilizam o processo de coleta e visualização de dados ao trabalhar com um cluster.

      Conclusão

      As arquiteturas de microsserviço são projetadas para tornar o desenvolvimento e o deployment de aplicações mais rápidos e confiáveis. No entanto, um aumento na comunicação entre serviços mudou as práticas recomendadas para determinadas tarefas administrativas. Este artigo discute algumas dessas tarefas, como elas são tratadas em um contexto nativo do Kubernetes e como elas podem ser gerenciadas usando service mesh – nesse caso, o Istio.

      Para obter mais informações sobre alguns dos tópicos do Kubernetes abordados aqui, consulte os seguintes recursos:

      Além disso, os hubs de documentação do Kubernetes e do Istio são ótimos lugares para encontrar informações detalhadas sobre os tópicos discutidos aqui.



      Source link

      Uma Introdução às consultas no MySQL


      Introdução

      Bancos de dados são um componente chave em muitos websites e aplicações, e estão no centro de como os dados são armazenados e trocados pela Internet. Um dos aspectos mais importantes do gerenciamento de banco de dados é a prática de recuperar dados de um banco de dados, seja em uma base ad hoc ou parte de um processo codificado em um aplicativo. Existem várias maneiras de recuperar informações de um banco de dados, mas um dos métodos mais utilizados é realizado através do envio de consultas pela linha de comandos.

      Em sistemas de gerenciamento de bancos de dados relacionais, uma consulta é qualquer comando usado para recuperar dados de uma tabela. Na Linguagem de Consulta Estruturada ou Structured Query Language (SQL), consultas são feitas quase sempre usando o comando SELECT.

      Neste guia, discutiremos a sintaxe básica das consultas SQL, bem como algumas das funções e operadores mais comumente empregados. Vamos também praticar a criação de consultas SQL usando alguns dados de amostra em um banco de dados MySQL.

      O MySQL é um sistema de gerenciamento de banco de dados relacional open-source. Sendo um dos bancos de dados SQL mais amplamente implantados, o MySQL prioriza velocidade, confiabilidade e usabilidade. Em geral, ele segue o padrão SQL ANSI, embora haja alguns casos em que o MySQL executa operações de maneira diferente do padrão reconhecido.

      Pré-requisitos

      Em geral, os comandos e conceitos apresentados neste guia podem ser usados em qualquer sistema operacional baseado em Linux executando qualquer software de banco de dados SQL. No entanto, ele foi escrito especificamente com um servidor Ubuntu 18.04 executando o MySQL em mente. Para configurar isso, você precisará do seguinte:

      Com esta configuração pronta, podemos começar o tutorial.

      Criando um Banco de Dados de Amostra

      Antes de começarmos a fazer consultas no SQL, vamos primeiro criar um banco de dados e algumas tabelas, em seguida, preencher essas tabelas com alguns dados de amostra. Isso permitirá que você ganhe experiência prática quando começar a fazer consultas mais tarde.

      Para o banco de dados de amostra que usaremos ao longo deste guia, imagine o seguinte cenário:

      Você e vários de seus amigos celebram seus aniversários juntos. Em cada ocasião, os membros do grupo vão para a pista de boliche local, participam de um torneio amistoso e, em seguida, todos vão para sua casa, onde você prepara a refeição favorita do aniversariante.

      Agora que essa tradição já dura algum tempo, você decidiu começar a acompanhar os registros desses torneios. Além disso, para tornar o planejamento das refeições mais fácil, você decide criar um registro dos aniversários dos seus amigos e de suas entradas, acompanhamentos e sobremesas favoritas. Em vez de manter essas informações em um livro físico, você decide exercitar suas habilidades de banco de dados gravando-as em um banco de dados MySQL.

      Para começar, abra um prompt de MySQL como seu usuário root do MySQL:

      Note: Se você seguiu o pré-requisito do tutorial sobre Como Instalar o MySQL no Ubuntu 18.04, você pode ter configurado seu usuário root para autenticar usando uma senha. Neste caso, você irá se conectar ao prompt do MySQL com o seguinte comando:

      Em seguida, crie o banco de dados executando:

      • CREATE DATABASE `aniversarios`;

      Depois, selecione este banco de dados digitando:

      A seguir, crie duas tabelas dentro desse banco de dados. Vamos utilizar a primeira tabela para acompanhar os registros dos seus amigos na pista de boliche. O seguinte comando criará uma tabela chamada torneios com colunas para o nome de cada um de seus amigos, o número de torneios que eles ganharam (vitorias), a melhor pontuação deles em todo o tempo, e que tamanho de sapato de boliche eles usam (tamanho):

      • CREATE TABLE torneios (
      • nome varchar(30),
      • vitorias real,
      • melhor real,
      • tamanho real
      • );

      Depois de executar o comando CREATE TABLE e preenchê-lo com títulos das colunas, você receberá a seguinte saída:

      Output

      Query OK, 0 rows affected (0.00 sec)

      Preencha a tabela torneios com alguns dados de amostra:

      • INSERT INTO torneios (nome, vitorias, melhor, tamanho)
      • VALUES ('Dolly', '7', '245', '8.5'),
      • ('Etta', '4', '283', '9'),
      • ('Irma', '9', '266', '7'),
      • ('Barbara', '2', '197', '7.5'),
      • ('Gladys', '13', '273', '8');

      Você receberá uma saída como esta:

      Output

      Query OK, 5 rows affected (0.01 sec) Records: 5 Duplicates: 0 Warnings: 0

      Depois disso, crie outra tabela dentro do mesmo banco de dados que usaremos para armazenar informações sobre as refeições de aniversário favoritas dos seus amigos. O seguinte comando cria uma tabela chamada refeicoes com colunas para o nome de cada um dos seus amigos, a data_nascimento, a entrada favorita de cada um, o acompanhamento preferido, e a sobremesa favorita:

      • CREATE TABLE refeicoes (
      • nome varchar(30),
      • data_nascimento date,
      • entrada varchar(30),
      • acompanhamento varchar(30),
      • sobremesa varchar(30)
      • );

      Da mesma forma, para esta tabela, você receberá um feedback confirmando que o comando foi executado com sucesso:

      Output

      Query OK, 0 rows affected (0.01 sec)

      Preencha esta tabela com alguns dados de amostra também:

      • INSERT INTO refeicoes (nome, data_nascimento, entrada, acompanhamento, sobremesa)
      • VALUES ('Dolly', '1946-01-19', 'steak', 'salad', 'cake'),
      • ('Etta', '1938-01-25', 'chicken', 'fries', 'ice cream'),
      • ('Irma', '1941-02-18', 'tofu', 'fries', 'cake'),
      • ('Barbara', '1948-12-25', 'tofu', 'salad', 'ice cream'),
      • ('Gladys', '1944-05-28', 'steak', 'fries', 'ice cream');

      Output

      Query OK, 5 rows affected (0.00 sec) Records: 5 Duplicates: 0 Warnings: 0

      Uma vez que esse comando tenha sido concluído com êxito, você acabou de configurar seu banco de dados. A seguir, vamos falar sobre a estrutura básica de comando das consultas SELECT.

      Entendendo Comandos SELECT

      Conforme mencionado na introdução, consultas SQL quase sempre começam com o comando SELECT. SELECT é usado em consultas para especificar quais colunas de uma tabela devem ser retornadas no conjunto de resultados ou result-set. As consultas também quase sempre incluem FROM, que é usado para especificar qual tabela o comando consultará.

      Geralmente, as consultas SQL seguem essa sintaxe:

      • SELECT coluna_a_selecionar FROM tabela_a_selecionar WHERE certas_condições_a_aplicar;

      A título de exemplo, o seguinte comando retornará a coluna nome inteira da tabela refeicoes:

      • SELECT nome FROM refeicoes;
      [seconday_label Output]
      +---------+
      | nome    |
      +---------+
      | Dolly   |
      | Etta    |
      | Irma    |
      | Barbara |
      | Gladys  |
      +---------+
      5 rows in set (0.00 sec)
      

      Você pode selecionar várias colunas da mesma tabela, separando seus nomes com uma vírgula, desta forma:

      • SELECT nome, data_nascimento FROM refeicoes;

      Output

      +---------+-----------------+ | nome | data_nascimento | +---------+-----------------+ | Dolly | 1946-01-19 | | Etta | 1938-01-25 | | Irma | 1941-02-18 | | Barbara | 1948-12-25 | | Gladys | 1944-05-28 | +---------+-----------------+ 5 rows in set (0.00 sec)

      Em vez de nomear uma coluna específica ou um conjunto de colunas, você pode seguir o operador SELECT com um asterisco (*) que serve como um curinga representando todas as colunas em uma tabela. O seguinte comando retorna todas as colunas da tabela torneios:

      Output

      +---------+----------+--------+---------+ | nome | vitorias | melhor | tamanho | +---------+----------+--------+---------+ | Dolly | 7 | 245 | 8.5 | | Etta | 4 | 283 | 9 | | Irma | 9 | 266 | 7 | | Barbara | 2 | 197 | 7.5 | | Gladys | 13 | 273 | 8 | +---------+----------+--------+---------+ 5 rows in set (0.00 sec)

      WHERE é usado em consultas para filtrar registros que atendem a uma condição especificada, e todas as linhas que não atendem a essa condição são eliminadas do resultado. Uma cláusula WHERE geralmente segue esta sintaxe:

      • . . . WHERE nome_da_coluna operador_de_comparação valor

      O operador de comparação em uma cláusula WHERE define como a coluna especificada deve ser comparada com o valor. Aqui estão alguns operadores comuns de comparação em SQL:

      OperadorO que ele faz
      =testa a igualdade
      !=testa a desigualdade
      <testa menor que
      >testa maior que
      <=testa menor que ou igual a
      >=testa maior que ou igual a
      BETWEENtesta se um valor está dentro de um determinado intervalo
      INtesta se o valor de uma linha está contido em um conjunto de valores especificados
      EXISTStesta se existem linhas, dadas as condições especificadas
      LIKEtesta se um valor corresponde a uma string especificada
      IS NULLtesta valores NULL
      IS NOT NULLtesta todos os valores que não sejam NULL

      Por exemplo, se você quiser encontrar o tamanho do sapato de Irma, use a seguinte consulta:

      • SELECT tamanho FROM torneios WHERE nome = 'Irma';

      Output

      +---------+ | tamanho | +---------+ | 7 | +---------+ 1 row in set (0.00 sec)

      O SQL permite o uso de caracteres curinga, e eles são especialmente úteis quando usados em cláusulas WHERE. Os sinais de porcentagem (%) representam zero ou mais caracteres desconhecidos, e os sublinhados ou underscores (_) representam um único caractere desconhecido. Eles são úteis se você estiver tentando encontrar uma informação específica em uma tabela, mas não tiver certeza de qual é exatamente essa informação. Para ilustrar, digamos que você tenha esquecido a entrada favorita de alguns de seus amigos, mas você está certo de que este prato principal começa com um "t". Você pode encontrar seu nome executando a seguinte consulta:

      • SELECT entrada FROM refeicoes WHERE entrada LIKE 't%';

      Output

      +---------+ | entrada | +---------+ | tofu | | tofu | +---------+ 2 rows in set (0.00 sec)

      Com base na saída acima, vemos que a entrada que esquecemos é tofu.

      Pode haver momentos em que você está trabalhando com bancos de dados que possuem colunas ou tabelas com nomes relativamente longos ou difíceis de ler. Nesses casos, você pode tornar esses nomes mais legíveis criando um alias ou apelido com a palavra-chave AS. Apelidos criados com AS são temporários e existem apenas durante a consulta para a qual eles foram criados:

      • SELECT nome AS n, data_nascimento AS d, sobremesa AS s FROM refeicoes;

      Output

      +---------+------------+-----------+ | n | d | s | +---------+------------+-----------+ | Dolly | 1946-01-19 | cake | | Etta | 1938-01-25 | ice cream | | Irma | 1941-02-18 | cake | | Barbara | 1948-12-25 | ice cream | | Gladys | 1944-05-28 | ice cream | +---------+------------+-----------+ 5 rows in set (0.00 sec)

      Aqui, dissemos ao SQL para exibir a coluna nome como n, a coluna data_nascimento como d e a coluna sobremesa como s.

      Os exemplos que mostramos até aqui incluem algumas das palavras-chave e cláusulas mais usadas em consultas SQL. Elas são úteis para consultas básicas, mas não são úteis se você estiver tentando realizar um cálculo ou derivar um valor escalar (um valor único, em oposição a um conjunto de vários valores diferentes) com base em seus dados. É aqui que as funções de agregação entram em ação.

      Funções de Agregação

      Muitas vezes, ao trabalhar com dados, você não necessariamente quer ver os dados em si. Em vez disso, você quer informações sobre os dados. A sintaxe SQL inclui várias funções que permitem interpretar ou executar cálculos em seus dados apenas emitindo uma consulta SELECT. Estas são conhecidas como funções de agregação.

      A função COUNT conta e retorna o número de linhas que correspondem a um determinado critério. Por exemplo, se você quiser saber quantos dos seus amigos preferem o tofu para a entrada de aniversário, você pode fazer essa consulta:

      • SELECT COUNT(entrada) FROM refeicoes WHERE entrada = 'tofu';

      Output

      +----------------+ | COUNT(entrada) | +----------------+ | 2 | +----------------+ 1 row in set (0.00 sec)

      A função AVG retorna o valor médio (média) de uma coluna. Usando nossa tabela de exemplo, você pode encontrar a melhor pontuação média entre seus amigos com esta consulta:

      • SELECT AVG(melhor) FROM torneios;

      Output

      +-------------+ | AVG(melhor) | +-------------+ | 252.8 | +-------------+ 1 row in set (0.00 sec)

      SUM é usado para encontrar a soma total de uma determinada coluna. Por exemplo, se você quiser ver quantos jogos você e seus amigos jogaram ao longo dos anos, você pode executar essa consulta:

      • SELECT SUM(vitorias) FROM torneios;

      Output

      +---------------+ | SUM(vitorias) | +---------------+ | 35 | +---------------+ 1 row in set (0.00 sec)

      Observe que as funções AVG eSUM só funcionarão corretamente quando usadas com dados numéricos. Se você tentar usá-los em dados não numéricos, isso resultará em um erro ou apenas 0, dependendo de qual SGBD você está usando:

      • SELECT SUM(entrada) FROM refeicoes;

      Output

      +--------------+ | SUM(entrada) | +--------------+ | 0 | +--------------+ 1 row in set, 5 warnings (0.00 sec)

      MIN é usado para encontrar o menor valor dentro de uma coluna especificada. Você poderia usar essa consulta para ver qual o pior registro geral de boliche até agora (em termos de número de vitórias):

      • SELECT MIN(vitorias) FROM torneios;
      [secondarylabel Output]
      +---------------+
      | MIN(vitorias) |
      +---------------+
      |             2 |
      +---------------+
      1 row in set (0.00 sec)
      

      Da mesma forma, MAX é usado para encontrar o maior valor numérico em uma determinada coluna. A consulta a seguir mostrará o melhor registro geral de boliche:

      • SELECT MAX(vitorias) FROM torneios;

      Output

      +---------------+ | MAX(vitorias) | +---------------+ | 13 | +---------------+ 1 row in set (0.00 sec)

      Ao contrário de SUM eAVG, as funções MIN eMAX podem ser usadas para tipos de dados numéricos e alfabéticos. Quando executado em uma coluna contendo valores de string, a função MIN mostrará o primeiro valor alfabeticamente:

      • SELECT MIN(nome) FROM refeicoes;

      Output

      +-----------+ | MIN(nome) | +-----------+ | Barbara | +-----------+ 1 row in set (0.00 sec)

      Da mesma forma, quando executado em uma coluna contendo valores de string, a função MAX mostrará o último valor em ordem alfabética:

      • SELECT MAX(nome) FROM refeicoes;

      Output

      +-----------+ | MAX(nome) | +-----------+ | Irma | +-----------+ 1 row in set (0.00 sec)

      As funções agregadas têm muitos usos além do que foi descrito nesta seção. Elas são particularmente úteis quando usadas com a cláusula GROUP BY, que é abordada na próxima seção junto com várias outras cláusulas de consulta que afetam como os result-sets são classificados.

      Manipulando Saídas da Consulta

      Além das cláusulas FROM eWHERE, existem várias outras cláusulas que são usadas para manipular os resultados de uma consulta SELECT. Nesta seção, explicaremos e forneceremos exemplos para algumas das cláusulas de consulta mais comumente usadas.

      Uma das cláusulas de consulta mais usadas, além de FROM e WHERE, é a cláusula GROUP BY. Ela é normalmente usada quando você está executando uma função de agregação em uma coluna, mas em relação aos valores correspondentes em outra.

      Por exemplo, digamos que você queria saber quantos de seus amigos preferem cada uma das três entradas que você faz. Você pode encontrar essa informação com a seguinte consulta:

      • SELECT COUNT(nome), entrada FROM refeicoes GROUP BY entrada;

      Output

      +-------------+----------+ | COUNT(nome) | entrada | +-------------+----------+ | 1 | chicken | | 2 | steak | | 2 | tofu | +-------------+----------+ 3 rows in set (0.00 sec)

      A cláusula ORDER BY é usada para classificar os resultados da consulta. Por padrão, os valores numéricos são classificados em ordem crescente e os valores de texto são classificados em ordem alfabética. Para ilustrar, a consulta a seguir lista as colunas nome e data_nascimento, mas classifica os resultados por data_nascimento:

      • SELECT nome, data_nascimento FROM refeicoes ORDER BY data_nascimento;

      Output

      +---------+-----------------+ | nome | data_nascimento | +---------+-----------------+ | Etta | 1938-01-25 | | Irma | 1941-02-18 | | Gladys | 1944-05-28 | | Dolly | 1946-01-19 | | Barbara | 1948-12-25 | +---------+-----------------+ 5 rows in set (0.00 sec)

      Observe que o comportamento padrão de ORDER BY é classificar o result-set em ordem crescente. Para reverter isso e ter o resultado classificado em ordem decrescente, feche a consulta com DESC:

      • SELECT nome, data_nascimento FROM refeicoes ORDER BY data_nascimento DESC;

      Output

      +---------+-----------------+ | nome | data_nascimento | +---------+-----------------+ | Barbara | 1948-12-25 | | Dolly | 1946-01-19 | | Gladys | 1944-05-28 | | Irma | 1941-02-18 | | Etta | 1938-01-25 | +---------+-----------------+ 5 rows in set (0.00 sec)

      Como mencionado anteriormente, a cláusula WHERE é usada para filtrar resultados com base em condições específicas. No entanto, se você usar a cláusula WHERE com uma função de agregação, ela retornará um erro, como é o caso da seguinte tentativa de encontrar quais acompanhamentos são os favoritos de pelo menos três de seus amigos:

      • SELECT COUNT(nome), acompanhamento FROM refeicoes WHERE COUNT(nome) >= 3;

      Output

      ERROR 1111 (HY000): Invalid use of group function

      A cláusula HAVING foi adicionada ao SQL para fornecer funcionalidade semelhante à da cláusula WHERE, além de ser compatível com funções de agregação. É útil pensar na diferença entre essas duas cláusulas como sendo que WHERE se aplica a registros individuais, enquantoHAVING se aplica a grupos de registros. Para este fim, sempre que você emitir uma cláusula HAVING, a cláusula GROUP BY também deve estar presente.

      O exemplo a seguir é outra tentativa de descobrir quais são os acompanhamentos favoritos de pelo menos três de seus amigos, embora este retorne um resultado sem erro:

      • SELECT COUNT(nome), acompanhamento FROM refeicoes GROUP BY acompanhamento HAVING COUNT(nome) >= 3;

      Output

      +-------------+----------------+ | COUNT(nome) | acompanhamento | +-------------+----------------+ | 3 | fries | +-------------+----------------+ 1 row in set (0.00 sec)

      As funções de agregação são úteis para resumir os resultados de uma determinada coluna em uma dada tabela. No entanto, há muitos casos em que é necessário consultar o conteúdo de mais de uma tabela. Na próxima seção analisaremos algumas maneiras de fazer isso.

      Consultando Várias Tabelas

      Mais frequentemente, um banco de dados contém várias tabelas, cada uma contendo diferentes conjuntos de dados. O SQL fornece algumas maneiras diferentes de executar uma única consulta em várias tabelas.

      A cláusula JOIN pode ser usada para combinar linhas de duas ou mais tabelas em um resultado de consulta. Ele faz isso localizando uma coluna relacionada entre as tabelas e classifica os resultados adequadamente na saída.

      Os comandos SELECT que incluem uma cláusula JOIN geralmente seguem esta sintaxe:

      • SELECT tabela1.coluna1, tabela2.coluna2
      • FROM tabela1
      • JOIN tabela2 ON tabela1.coluna_relacionada=tabela2.coluna_relacionada;

      Note que como cláusulas JOIN comparam o conteúdo de mais de uma tabela, o exemplo anterior especifica em qual tabela selecionar cada coluna, precedendo o nome da coluna com o nome da tabela e um ponto. Você pode especificar de qual tabela uma coluna deve ser selecionada para qualquer consulta, embora isso não seja necessário ao selecionar de uma única tabela, como fizemos nas seções anteriores. Vamos examinar um exemplo usando nossos dados de amostra.

      Imagine que você queria comprar para cada um de seus amigos um par de sapatos de boliche como presente de aniversário. Como as informações sobre datas de nascimento e tamanhos de calçados dos seus amigos são mantidas em tabelas separadas, você pode consultar as duas tabelas separadamente e comparar os resultados de cada uma delas. Com uma cláusula JOIN, no entanto, você pode encontrar todas as informações desejadas com uma única consulta:

      • SELECT torneios.nome, torneios.tamanho, refeicoes.data_nascimento
      • FROM torneios
      • JOIN refeicoes ON torneios.nome=refeicoes.nome;

      Output

      +---------+---------+------------------+ | nome | tamanho | data_nascimento | +---------+---------+------------------+ | Dolly | 8.5 | 1946-01-19 | | Etta | 9 | 1938-01-25 | | Irma | 7 | 1941-02-18 | | Barbara | 7.5 | 1948-12-25 | | Gladys | 8 | 1944-05-28 | +---------+---------+------------------+ 5 rows in set (0.00 sec)

      A cláusula JOIN usada neste exemplo, sem nenhum outro argumento, é uma cláusula inner JOIN. Isso significa que ela seleciona todos os registros que possuem valores correspondentes nas duas tabelas e os imprime no result-set, enquanto todos os registros que não tem correspondência são excluídos. Para ilustrar essa ideia, vamos adicionar uma nova linha a cada tabela que não tenha uma entrada correspondente na outra:

      • INSERT INTO torneios (nome, vitorias, melhor, tamanho)
      • VALUES ('Bettye', '0', '193', '9');
      • INSERT INTO refeicoes (nome, data_nascimento, entrada, acompanhamento, sobremesa)
      • VALUES ('Lesley', '1946-05-02', 'steak', 'salad', 'ice cream');

      Então, execute novamente a instrução SELECT anterior com a cláusula JOIN:

      • SELECT torneios.nome, torneios.tamanho, refeicoes.data_nascimento
      • FROM torneios
      • JOIN refeicoes ON torneios.nome=refeicoes.nome;

      Output

      +---------+---------+-----------------+ | nome | tamanho | data_nascimento | +---------+---------+-----------------+ | Dolly | 8.5 | 1946-01-19 | | Etta | 9 | 1938-01-25 | | Irma | 7 | 1941-02-18 | | Barbara | 7.5 | 1948-12-25 | | Gladys | 8 | 1944-05-28 | +---------+---------+-----------------+ 5 rows in set (0.00 sec)

      Observe que, como a tabela torneios não tem entrada para Lesley e a tabela refeicoes não tem entrada para Bettye, esses registros estão ausentes desta saída.

      É possível, no entanto, retornar todos os registros de uma das tabelas usando uma cláusula outer JOIN. No MySQL, as cláusulas JOIN são escritas como LEFT JOIN ou RIGHT JOIN.

      Uma cláusula LEFT JOIN retorna todos os registros da tabela da "esquerda" e apenas os registros correspondentes da tabela da direita. No contexto de outer joins, a tabela da esquerda é aquela referenciada pela cláusula FROM e a tabela da direita é qualquer outra tabela referenciada após o comando JOIN.

      Execute a consulta anterior novamente, mas desta vez use uma cláusula LEFT JOIN:

      • SELECT torneios.nome, torneios.tamanho, refeicoes.data_nascimento
      • FROM torneios
      • LEFT JOIN refeicoes ON torneios.nome=refeicoes.nome;

      Este comando retornará todos os registros da tabela da esquerda (neste caso, torneios), mesmo que não tenha um registro correspondente na tabela da direita. Toda vez que não houver um registro correspondente da tabela da direita, ele será retornado como NULL ou apenas como um valor em branco, dependendo do seu SGBD:

      Output

      +---------+---------+-----------------+ | nome | tamanho | data_nascimento | +---------+---------+-----------------+ | Dolly | 8.5 | 1946-01-19 | | Etta | 9 | 1938-01-25 | | Irma | 7 | 1941-02-18 | | Barbara | 7.5 | 1948-12-25 | | Gladys | 8 | 1944-05-28 | | Bettye | 9 | NULL | +---------+---------+-----------------+ 6 rows in set (0.00 sec)

      Agora execute a consulta novamente, desta vez com uma cláusula RIGHT JOIN:

      • SELECT torneios.nome, torneios.tamanho, refeicoes.data_nascimento
      • FROM torneios
      • RIGHT JOIN refeicoes ON torneios.nome=refeicoes.nome;

      Isso retornará todos os registros da tabela da direita (refeicoes). Como a data de nascimento de Lesley está registrada na tabela da direita, mas não há uma linha correspondente para ela na tabela da esquerda, as colunas nome e tamanho retornarão como valores NULL nessa linha:

      Output

      +---------+---------+-----------------+ | nome | tamanho | data_nascimento | +---------+---------+-----------------+ | Dolly | 8.5 | 1946-01-19 | | Etta | 9 | 1938-01-25 | | Irma | 7 | 1941-02-18 | | Barbara | 7.5 | 1948-12-25 | | Gladys | 8 | 1944-05-28 | | NULL | NULL | 1946-05-02 | +---------+---------+-----------------+ 6 rows in set (0.00 sec)

      Observe que joins à esquerda e à direita podem ser escritos como LEFT OUTER JOIN ou RIGHT OUTER JOIN, embora a parte OUTER da cláusula esteja implícita. Da mesma forma, especificar INNER JOIN produzirá o mesmo resultado que apenas escrever JOIN.

      Como uma alternativa ao uso de JOIN para consultar registros de várias tabelas, você pode usar a cláusula UNION.

      O operador UNION funciona de forma ligeiramente diferente de uma cláusula JOIN: em vez de imprimir resultados de várias tabelas como colunas únicas usando um único comando SELECT, o UNION combina os resultados de dois comandos SELECT em uma única coluna.

      Para ilustrar, execute a seguinte consulta:

      • SELECT nome FROM torneios UNION SELECT nome FROM refeicoes;

      Esta consulta removerá quaisquer entradas duplicadas, que é o comportamento padrão do operador UNION:

      Output

      +---------+ | nome | +---------+ | Dolly | | Etta | | Irma | | Barbara | | Gladys | | Bettye | | Lesley | +---------+ 7 rows in set (0.00 sec)

      Para retornar todas as entradas (incluindo as duplicadas), use o operador UNION ALL:

      • SELECT nome FROM torneios UNION ALL SELECT nome FROM refeicoes;

      Output

      +---------+ | nome | +---------+ | Dolly | | Etta | | Irma | | Barbara | | Gladys | | Bettye | | Dolly | | Etta | | Irma | | Barbara | | Gladys | | Lesley | +---------+ 12 rows in set (0.00 sec)

      Os nomes e números das colunas na tabela de resultados refletem o nome e o número de colunas consultadas pelo primeiro comando SELECT. Note que ao usar UNION para consultar múltiplas colunas de mais de uma tabela, cada comando SELECT deve consultar o mesmo número de colunas, as respectivas colunas devem ter tipos de dados similares, e as colunas em cada comando SELECT devem estar na mesma ordem. O exemplo a seguir mostra o que pode resultar se você usar uma cláusula UNION em dois comandos SELECT que consultam um número diferente de colunas:

      • SELECT nome FROM refeicoes UNION SELECT nome, vitorias FROM torneios;

      Output

      ERROR 1222 (21000): The used SELECT statements have a different number of columns

      Outra maneira de consultar várias tabelas é através do uso de subconsultas ou subqueries. As subqueries (também conhecidas como consultas internas ou aninhadas) são consultas incluídas em outra consulta. Elas são úteis nos casos em que você está tentando filtrar os resultados de uma consulta com base no resultado de uma função de agregação separada.

      Para ilustrar essa ideia, digamos que você queira saber quais dos seus amigos ganharam mais partidas do que Bárbara. Em vez de consultar quantos jogos Bárbara venceu e, em seguida, executar outra consulta para ver quem ganhou mais jogos do que isso, você pode calcular ambos com uma única consulta:

      • SELECT nome, vitorias FROM torneios
      • WHERE vitorias > (
      • SELECT vitorias FROM torneios WHERE nome = 'Barbara'
      • );

      Output

      +--------+----------+ | nome | vitorias | +--------+----------+ | Dolly | 7 | | Etta | 4 | | Irma | 9 | | Gladys | 13 | +--------+----------+ 4 rows in set (0.00 sec)

      A subquerie nesse comando foi executada apenas uma vez; ele só precisava encontrar o valor da coluna vitorias na mesma linha que Barbara na coluna nome, e os dados retornados pela subquerie e pela consulta externa são independentes um do outro. Existem casos, no entanto, em que a consulta externa deve primeiro ler todas as linhas de uma tabela e comparar esses valores com os dados retornados pela subquerie para retornar os dados desejados. Nesse caso, a subquerie é referida como uma subquerie correlacionada.

      O comando a seguir é um exemplo de uma subquerie correlacionada. Esta consulta procura descobrir quais dos seus amigos ganharam mais jogos do que a média para aqueles com o mesmo tamanho de calçado:

      • SELECT nome, tamanho FROM torneios AS t
      • WHERE vitorias > (
      • SELECT AVG(vitorias) FROM torneios WHERE tamanho = t.tamanho
      • );

      Para que a consulta seja concluída, ela deve primeiro coletar as colunas nome e tamanho da consulta externa. Em seguida, ele compara cada linha desse result-set com os resultados da consulta interna, que determina o número médio de vitórias para indivíduos com tamanhos de sapatos idênticos. Como você só tem dois amigos com o mesmo tamanho de calçado, só pode haver uma linha no result-set:

      Output

      +------+---------+ | nome | tamanho | +------+---------+ | Etta | 9 | +------+---------+ 1 row in set (0.00 sec)

      Conforme mencionado anteriormente, as subquerie podem ser usadas para consultar resultados de várias tabelas. Para ilustrar isso com um exemplo final, digamos que você queria fazer um jantar surpresa para o melhor jogador de todos os tempos do grupo. Você pode encontrar qual dos seus amigos tem o melhor registro de boliche e retornar sua refeição favorita com a seguinte consulta:

      • SELECT nome, entrada, acompanhamento, sobremesa
      • FROM refeicoes
      • WHERE nome = (SELECT nome FROM torneios
      • WHERE vitorias = (SELECT MAX(vitorias) FROM torneios));

      Output

      +--------+---------+-----------------+------------+ | nome | entrada | acompanhamento | sobremesa | +--------+---------+-----------------+------------+ | Gladys | steak | fries | ice cream | +--------+---------+-----------------+------------+ 1 row in set (0.00 sec)

      Observe que esse comando não inclui apenas uma subquerie, mas também contém uma subquerie dentro dessa subquerie.

      Conclusão

      A realização de consultas é uma das tarefas mais comuns no domínio do gerenciamento de banco de dados. Existem várias ferramentas de administração de banco de dados, como phpMyAdmin or pgAdmin, que permitem realizar consultas e visualizar os resultados, mas a execução de comandos SELECT a partir da linha de comando ainda é um fluxo de trabalho amplamente praticado que também pode fornecer maior controle.

      Se você é novato no trabalho com SQL, lhe encorajamos a usar nosso Guia de Consulta Rápida SQL como referência e a revisar a documentação oficial do MySQL. Além disso, se você quiser saber mais sobre bancos de dados relacionais e SQL, os seguintes tutoriais podem ser de seu interesse:

      Por Mark Drake



      Source link