Sobre este codelab
1. Olá!
Agradecemos por participar do codelab do Istio Multi Cloud Burst do Google.Este codelab exige experiência prática de nível iniciante com Kubernetes, Node e Go. O que você vai precisar
|
O que você aprenderá
- Como criar um cluster do Kubernetes no GKE
- Como instalar o Istio em um cluster do Kubernetes com o Helm
- Como instalar o Istio Multicluster com o Helm
- Implantar um aplicativo da Web da origem para o Kubernetes
- Como gravar e aplicar regras de roteamento de tráfego ao Istio
- Métricas do Prometheus
- Criar e enviar imagens de contêineres em um cluster do Kubernetes
2. Etapas da configuração
É possível seguir este codelab em:
- Google Cloud Shell (recomendado): shell no navegador, vem com ferramentas instaladas
- seu laptop (siga as instruções abaixo)
Começar a usar o Google Cloud Platform
- Peça ao instrutor o cartão da conta de usuário sem custo financeiro se você não tiver uma conta do GCP.
- Acesse o console do Google Cloud e clique em "Selecionar um projeto":
- Anote o "ID" do projeto em algum lugar e clique nele para fazer a seleção:
Opção 1: usar o Google Cloud Shell (recomendado)
O Cloud Shell fornece um shell de linha de comando no navegador com as ferramentas necessárias instaladas e autenticadas automaticamente na sua conta do Google Cloud Platform. Se você não quiser executar este exercício no Cloud Shell, pule para a próxima seção.
Acesse o console do Cloud e clique em "Ativar o Cloud Shell" na barra de ferramentas no canto superior direito:
Adicionar ferramentas ao Cloud Shell
- Instale
kubectx
****: faça o download dos scripts do Bash aqui e salve em um local em $PATH. - Instale
helm
****: siga estas instruções.
Como alternativa, execute estes comandos para instalar os dois em ~/.bin
e adicionar ao $PATH:
mkdir -p ~/.bin && \
cd ~/.bin && \
curl -LO https://raw.githubusercontent.com/ahmetb/kubectx/master/kubectx && \
chmod +x kubectx && \
curl -LO https://raw.githubusercontent.com/ahmetb/kubectx/master/kubens && \
chmod +x kubens && \
curl -LO https://storage.googleapis.com/kubernetes-helm/helm-v2.12.0-linux-amd64.tar.gz && \
tar xzf helm-v2.12.0-linux-amd64.tar.gz && \
rm helm-v2.12.0-linux-amd64.tar.gz && \
mv linux-amd64/helm ./helm && \
rm -r linux-amd64 && \
export PATH=${HOME}/.bin:${PATH}
Confira algumas dicas rápidas para facilitar o uso do Cloud Shell:
1. Desconecte o shell em uma nova janela: | |
2. Usar o editor de arquivos : clique no ícone de lápis no canto superior direito para abrir um editor de arquivos no navegador. Isso será útil porque vamos copiar snippets de código para arquivos. | |
3. Iniciar novas guias:se você precisar de mais de uma solicitação de terminal. | |
4. Aumente o tamanho do texto : o tamanho padrão da fonte no Cloud Shell pode ser muito pequeno para ler. | Ctrl-+ no Linux/Windows⌘-+ no macOS. |
Opção 2: configurar o laptop (não recomendado)
Se você se sentir mais confortável usando seu próprio ambiente de estação de trabalho em vez do Cloud Shell, configure as seguintes ferramentas:
- Instalar
gcloud:
(pré-instalado no Cloud Shell). Siga as instruções para instalar ogcloud
na sua plataforma. Vamos usar isso para criar um cluster do Kubernetes. - Instalar
kubectl:
(pré-instalado no Cloud Shell). Execute o comando a seguir para instalar:
gcloud components install kubectl
Execute o comando a seguir para autenticar o gcloud. Você vai precisar fazer login com sua Conta do Google. Em seguida, escolha o projeto pré-criado (mostrado acima) como padrão. Você pode pular a configuração de uma zona do Compute:
gcloud init
- Instalar
curl:
Pré-instalado na maioria dos sistemas Linux/macOS. Você provavelmente já tem. Caso contrário, pesquise na Internet como fazer a instalação. - Instale
kubectx
****: faça o download dos scripts do Bash aqui e salve-os em um local em $PATH. - Instale
helm
****: siga estas instruções.
3. Configurar o projeto do GCP
Ative as APIs do Google Kubernetes Engine (GKE), do Google Container Registry (GCR) e do Google Cloud Build (GCB) no seu projeto:
gcloud services enable \ cloudapis.googleapis.com \ container.googleapis.com \ containerregistry.googleapis.com \ cloudbuild.googleapis.com
Configurar as variáveis de ambiente
Vamos trabalhar bastante com nosso projeto do Google Cloud durante a configuração. Vamos definir uma variável de ambiente para referência rápida
export GCLOUD_PROJECT=$(gcloud config get-value project)
Vamos criar alguns arquivos de código e configuração durante este workshop. Crie um diretório de projeto e mude para ele.
mkdir -p src/istio-burst && \ cd src/istio-burst && \ export proj=$(pwd)
4. Criar o cluster "principal" do Kubernetes
É possível criar clusters gerenciados do Kubernetes com facilidade usando o Google Kubernetes Engine (GKE).
O comando a seguir vai criar um cluster do Kubernetes:
- chamado "primary",
- na zona us-west1-a,
- A versão mais recente do Kubernetes disponível,
- com quatro nós iniciais
export cluster=primary
export zone=us-west1-a
gcloud container clusters create $cluster --zone $zone --username "admin" \
--cluster-version latest --machine-type "n1-standard-2" \
--image-type "COS" --disk-size "100" \
--scopes "https://www.googleapis.com/auth/compute",\
"https://www.googleapis.com/auth/devstorage.read_only",\
"https://www.googleapis.com/auth/logging.write",\
"https://www.googleapis.com/auth/monitoring",\
"https://www.googleapis.com/auth/servicecontrol",\
"https://www.googleapis.com/auth/service.management.readonly",\
"https://www.googleapis.com/auth/trace.append" \
--num-nodes "4" --network "default" \
--enable-cloud-logging --enable-cloud-monitoring --enable-ip-alias
Isso pode levar cerca de cinco minutos. É possível acompanhar a criação do cluster no Console do Cloud.
Depois que o cluster do Kubernetes é criado, o gcloud
configura o kubectl
com as credenciais que apontam para o cluster.
gcloud container clusters get-credentials $cluster --zone=$zone
Agora você pode usar kubectl
com seu novo cluster.
Execute o seguinte comando para listar os nós do Kubernetes do cluster (eles devem mostrar o status "Pronto"):
kubectl get nodes
Modificar os nomes do Kubeconfig para facilitar o uso
Vamos alternar entre os contextos com frequência, então é útil ter um alias curto para nossos clusters.
Esse comando renomeia a entrada kubeconfig que você acabou de criar para primary
.
kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}
Definir permissões:
Para implantar o Istio, você precisa ser um administrador do cluster. Esse comando define o e-mail associado à sua conta do Google Cloud como o administrador do cluster.
kubectl create clusterrolebinding cluster-admin-binding \ --clusterrole=cluster-admin \ --user=$(gcloud config get-value core/account)
5. Criar cluster "burst"
O comando a seguir vai criar um cluster do Kubernetes:
- chamado "burst",
- na zona us-west1-a,
- A versão mais recente do Kubernetes disponível,
- Com 1 nó inicial
- Escalonamento automático ativado para até cinco nós
export cluster=burst
export zone=us-west1-a
gcloud container clusters create $cluster --zone $zone --username "admin" \
--cluster-version latest --machine-type "n1-standard-2" \
--image-type "COS" --disk-size "100" \
--scopes "https://www.googleapis.com/auth/compute",\
"https://www.googleapis.com/auth/devstorage.read_only",\
"https://www.googleapis.com/auth/logging.write",\
"https://www.googleapis.com/auth/monitoring",\
"https://www.googleapis.com/auth/servicecontrol",\
"https://www.googleapis.com/auth/service.management.readonly",\
"https://www.googleapis.com/auth/trace.append" \
--num-nodes "1" --enable-autoscaling --min-nodes=1 --max-nodes=5 \
--network "default" \
--enable-cloud-logging --enable-cloud-monitoring --enable-ip-alias
Isso pode levar cerca de cinco minutos. É possível acompanhar a criação do cluster no Console do Cloud.
Depois que o cluster do Kubernetes é criado, o gcloud
configura o kubectl
com as credenciais que apontam para o cluster.
gcloud container clusters get-credentials $cluster --zone=$zone
Agora você pode usar kubectl
com seu novo cluster.
Execute o seguinte comando para listar os nós do Kubernetes do cluster (eles devem mostrar o status "Pronto"):
kubectl get nodes
Modificar os nomes do Kubeconfig para facilitar o uso
Esse comando vai modificar a entrada kubeconfig que você acabou de criar para burst
.
kubectx ${cluster}=gke_${GCLOUD_PROJECT}_${zone}_${cluster}
Definir permissões:
Para implantar o Istio Remote, você precisa ser um administrador do cluster. Esse comando define o e-mail associado à sua conta do Google Cloud como o administrador do cluster.
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin \
--user=$(gcloud config get-value core/account)
6. Aplicar regras de firewall
Para que os dois clusters se comuniquem, precisamos criar uma regra de firewall.
Execute os comandos a seguir para criar uma regra de firewall na Google Cloud Platform que permita a comunicação dos clusters
function join_by { local IFS="$1"; shift; echo "$*"; }
ALL_CLUSTER_CIDRS=$(gcloud container clusters list \
--filter="(name=burst OR name=primary) AND zone=$zone" \
--format='value(clusterIpv4Cidr)' | sort | uniq)
ALL_CLUSTER_CIDRS=$(join_by , $(echo "${ALL_CLUSTER_CIDRS}"))
ALL_CLUSTER_NETTAGS=$(gcloud compute instances list \
--filter="(metadata.cluster-name=burst OR metadata.cluster-name=primary) AND metadata.cluster-location=us-west1-a" \
--format='value(tags.items.[0])' | sort | uniq)
ALL_CLUSTER_NETTAGS=$(join_by , $(echo "${ALL_CLUSTER_NETTAGS}"))
gcloud compute firewall-rules create istio-multicluster-test-pods \
--allow=tcp,udp,icmp,esp,ah,sctp \
--direction=INGRESS \
--priority=900 \
--source-ranges="${ALL_CLUSTER_CIDRS}" \
--target-tags="${ALL_CLUSTER_NETTAGS}" --quiet
Os dois clusters estão configurados e prontos para implantar o aplicativo e o Istio neles.
7. Introdução ao Istio
O que é o Istio?
O Istio é um plano de controle de malha de serviço que tem como objetivo "conectar, proteger, controlar e observar serviços". Isso é feito de várias maneiras, mas principalmente sidecarizando um contêiner de proxy ( Envoy) em cada um dos pods do Kubernetes implantados. O contêiner de proxy controla toda a comunicação de rede entre microsserviços em conjunto com um hub de política e telemetria de uso geral ( Mixer).
Essas políticas podem ser aplicadas independentemente das implantações e dos serviços do Kubernetes, o que significa que o operador de rede pode observar a atividade de rede, restringir, redirecionar ou reescrever políticas de rede sem reinstalar os aplicativos associados.
Alguns dos recursos de gerenciamento de tráfego compatíveis com o Istio são:
- Disjuntores
- Divisão de tráfego baseada em porcentagem
- Regravação de URL
- término de TLS
- Verificações de integridade
- Balanceamento de carga
Para este workshop, vamos nos concentrar na divisão de tráfego com base em porcentagem.
Termos do Istio com que vamos trabalhar
VirtualService
Um VirtualService define um conjunto de regras de roteamento de tráfego a serem aplicadas quando um host é resolvido.
Gateway
Um gateway é um balanceador de carga que opera na borda da malha e recebe conexões HTTP/TCP de entrada ou saída. Os gateways podem especificar portas, configurações de SNI etc.
DestinationRule (em inglês)
Uma DestinationRule define políticas que se aplicam ao tráfego destinado a um serviço após o roteamento. Eles especificam a configuração para balanceamento de carga, o tamanho do pool de conexões do sidecar e as configurações de detecção de valores fora da curva.
Istio multicluster
Você pode ter notado, ao criar os dois clusters, que o cluster primary
tinha quatro nós sem escalonamento automático, e o cluster burst
tinha um nó com escalonamento automático de até cinco nós.
Há dois motivos para essa configuração.
Primeiro, queremos simular um cenário "on-prem" para a nuvem. Em um ambiente local, você não tem acesso a clusters de escalonamento automático, porque tem infraestrutura fixa.
Em segundo lugar, uma configuração de quatro nós (conforme definido acima) é o requisito mínimo para executar o Istio. Isso levanta a questão: se o Istio exige pelo menos quatro nós, como o cluster burst
pode executar o Istio com um nó? A resposta é que o Istio Multicluster instala um conjunto muito menor dos serviços do Istio e se comunica com a instalação do Istio no cluster principal para recuperar as regras de política e publicar informações de telemetria.
8. Visão geral da arquitetura do aplicativo
Visão geral dos componentes
Vamos implantar um aplicativo de três camadas usando NodeJS e Redis.
Worker
O aplicativo worker é escrito em NodeJS e detecta solicitações POST HTTP de entrada, realiza uma operação de hash nelas e, se uma variável de ambiente chamada PREFIX
estiver definida, ele vai inserir o hash com esse valor. Depois que o hash é calculado, o aplicativo envia o resultado no canal "calculation
" no servidor Redis especificado.
Usaremos a variável de ambiente PREFIX
mais adiante para demonstrar a funcionalidade de vários clusters.
Para referência: estes são os pacotes usados pelo aplicativo.
body-parser:
Permite analisar nossas solicitações HTTP.cors:
Permite o uso do compartilhamento de recursos entre origensdotenv:
Análise fácil de variáveis de ambienteexpress:
Hospedagem de sites fácilioredis:
Biblioteca de cliente para se comunicar com bancos de dados do Redismorgan:
Oferece um bom registro estruturado
Front-end
Nosso front-end também é um aplicativo NodeJS que hospeda uma página da Web usando express. Ele usa uma frequência inserida pelo usuário e envia solicitações para nosso aplicativo worker
nessa taxa. Esse aplicativo também se inscreve em mensagens em um canal Redis chamado "calculation
" e mostra os resultados em uma página da Web.
O aplicativo usa as seguintes dependências.
body-parser:
Permite analisar nossas solicitações HTTP.dotenv:
Análise fácil de variáveis de ambienteexpress:
Hospedagem de sites fácilioredis:
Biblioteca de cliente para se comunicar com bancos de dados do Redismorgan:
Oferece registros estruturados.request:
Permite fazer solicitações HTTPsocket.io:
Permite a comunicação bidirecional da página da Web para o servidor
Esta página da Web usa o Bootstrap para estilizar e, quando executada, tem a seguinte aparência:
Diagrama de arquitetura
Diagrama de implantação
Vamos implantar nosso aplicativo final nos dois clusters criados. O cluster primary
terá todos os componentes (frontend
, worker
e Redis) implantados, mas o cluster burst
terá apenas o aplicativo worker
implantado.
Confira um diagrama que descreve os dois clusters. As caixas em vermelho são serviços do Kubernetes, e as azuis são implantações do Kubernetes. As caixas amarelas indicam a instalação do Istio.
Observe como o cluster burst
ainda tem um serviço para Redis implantado, mesmo que não haja uma implantação para Redis no cluster. Precisamos ter esse serviço no cluster para que o DNS do Kubernetes possa resolver a solicitação, mas, quando a solicitação for realmente feita, o proxy Istio vai redirecionar a solicitação para a implantação do Redis no cluster primary
.
O aplicativo final terá uma implantação adicional em execução no cluster primary
com o nome istiowatcher.
. Isso nos permitirá redirecionar dinamicamente o tráfego para o burst
automaticamente quando o tráfego ultrapassar um determinado limite.
9. Criar arquivos de implantação do aplicativo
Precisamos criar um conjunto de manifestos do Kubernetes para implantar nosso aplicativo.
Mude para o diretório raiz do projeto e crie uma nova pasta chamada kubernetes
.
mkdir ${proj}/kubernetes && cd ${proj}/kubernetes
Escrever o frontend.yaml
Isso vai criar uma implantação e um serviço do Kubernetes para acessar nossa imagem de front-end.
Insira o seguinte em frontend.yaml
.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: frontend-deployment
labels:
app: frontend
spec:
replicas: 1
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: gcr.io/istio-burst-workshop/frontend
ports:
- containerPort: 8080
readinessProbe:
initialDelaySeconds: 10
httpGet:
path: "/_healthz"
port: 8080
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-readiness-probe"
livenessProbe:
initialDelaySeconds: 10
httpGet:
path: "/"
port: 8080
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-liveness-probe"
env:
- name: PORT
value: "8080"
- name: PROCESSOR_URL
value: "http://worker-service"
- name: REDIS_URL
value: "redis-cache-service:6379"
---
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
type: ClusterIP
selector:
app: frontend
ports:
- name: http
port: 80
targetPort: 8080
Pontos importantes a observar no Deployment
- Especificamos a porta em que o aplicativo será executado como
8080
- Definimos o endereço do worker como "
http://worker-service
" e vamos usar o recurso DNS integrado do Kubernetes para resolver o serviço resultante. - Definimos o endereço do
REDIS_URL
como "redis-cache-service:6379
" e vamos usar o recurso DNS integrado do Kubernetes para resolver os endereços IP resultantes. - Também definimos as sondagens
liveness
ereadiness
para o contêiner para ajudar a informar o Kubernetes quando o contêiner estiver ativo.
Escrever worker-service.yaml
Estamos escrevendo a definição do serviço do Kubernetes em um arquivo separado da definição de implantação, porque vamos reutilizar esse serviço em vários clusters, mas vamos escrever uma implantação diferente para cada cluster.
Insira o seguinte em worker-service.yaml
apiVersion: v1
kind: Service
metadata:
name: worker-service
spec:
type: ClusterIP
selector:
app: worker
ports:
- name: http
port: 80
targetPort: 8081
Escrever worker-primary.yaml
Essa será a implantação de worker
que vamos enviar para o cluster principal.
Insira o seguinte em worker-primary.yaml
.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: worker-deployment
labels:
app: worker
spec:
replicas: 1
selector:
matchLabels:
app: worker
template:
metadata:
labels:
app: worker
cluster-type: primary-cluster
spec:
containers:
- name: worker
image: gcr.io/istio-burst-workshop/worker
imagePullPolicy: Always
ports:
- containerPort: 8081
readinessProbe:
initialDelaySeconds: 10
httpGet:
path: "/_healthz"
port: 8081
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-readiness-probe"
livenessProbe:
initialDelaySeconds: 10
httpGet:
path: "/"
port: 8081
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-liveness-probe"
env:
- name: PORT
value: "8081"
- name: REDIS_URL
value: "redis-cache-service:6379"
Observe que estamos seguindo o mesmo padrão de fornecer sondas liveness
e readiness
, além de especificar as variáveis de ambiente PORT
e REDIS_URL
para uso do nosso aplicativo.
Outra coisa a notar nesta implantação é a falta da variável de ambiente PREFIX
. Isso significa que os resultados do cálculo serão hashes brutos (sem prefixo).
O ponto principal final dessa implantação é o rótulo cluster-type: primary-cluster
. Vamos usar isso mais tarde, quando fizermos o roteamento de tráfego no Istio Multicluster.
Escrever redis.yaml
A comunicação do worker para o front-end é feita por um canal Redis. Portanto, precisamos implantar um aplicativo Redis no cluster.
Insira o seguinte em redis.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: redis-cache
spec:
template:
metadata:
labels:
app: redis-cache
spec:
containers:
- name: redis
image: redis:alpine
ports:
- containerPort: 6379
readinessProbe:
periodSeconds: 5
tcpSocket:
port: 6379
livenessProbe:
periodSeconds: 5
tcpSocket:
port: 6379
volumeMounts:
- mountPath: /data
name: redis-data
resources:
limits:
memory: 256Mi
cpu: 125m
requests:
cpu: 70m
memory: 200Mi
volumes:
- name: redis-data
emptyDir: {}
Esta é uma implantação semipadrão de um aplicativo Redis. Ele cria um contêiner com base na imagem redis:alpine
, expõe as portas adequadas e define limites de recursos razoáveis.
Escrever redis-service.yaml
Precisamos de um serviço do Kubernetes para nos comunicarmos com nosso aplicativo Redis.
Insira o seguinte em redis-service.yaml
apiVersion: v1
kind: Service
metadata:
name: redis-cache-service
spec:
type: ClusterIP
selector:
app: redis-cache
ports:
- port: 6379
targetPort: 6379
Isso fornece o serviço chamado redis-cache-service
para acessar nossa implantação do Redis.
10. Implantar o aplicativo
Com as imagens enviadas para o GCR e os manifestos do Kubernetes escritos, é um bom momento para implantar o aplicativo e conferir como ele funciona.
Execute os comandos abaixo para implantar o aplicativo.
- Verificar se estamos no cluster certo
kubectx primary
- Implantar o cache do Redis
kubectl apply -f redis.yaml
- Implantar o serviço Redis
kubectl apply -f redis-service.yaml
- Implantar o front-end
kubectl apply -f frontend.yaml
- Implantar o worker
kubectl apply -f worker-primary.yaml
- Implantar o serviço do worker
kubectl apply -f worker-service.yaml
Implantamos nosso aplicativo no GKE. Parabéns!
Teste
Aguarde os pods ficarem on-line
kubectl get pods -w
Quando todos os pods estiverem "Running", pressione Ctrl + C.
NAME READY STATUS RESTARTS AGE frontend-deployment-695d95fbf7-76sd8 1/1 Running 0 2m redis-cache-7475999bf5-nxj8x 1/1 Running 0 2m worker-deployment-5b9cf9956d-g975p 1/1 Running 0 2m
Percebemos que não expomos nosso front-end por um LoadBalancer. Isso porque vamos acessar o aplicativo pelo Istio mais tarde. Para testar se tudo está funcionando, vamos usar kubectl port-forward.
. Execute o comando a seguir para encaminhar a porta 8080 na sua máquina local (ou no Cloud Shell) para a porta 8080 que executa a implantação frontend
.
kubectl port-forward \
$(kubectl get pods -l app=frontend -o jsonpath='{.items[0].metadata.name}') \
8080:8080
Se estiver executando localmente: abra um navegador da Web e acesse http://localhost:8080.
Se você estiver executando no Cloud Shell:clique no botão "Visualização da Web" e selecione "Visualizar na porta 8080".
O front-end vai aparecer. Se você inserir um número na caixa "Frequência", os hashes vão começar a aparecer.
Parabéns! Tudo está pronto.
Pressione Ctrl+C
para interromper o encaminhamento da porta.
11. Limpar o aplicativo implantado
Vamos aplicar o Istio ao cluster e reimplantar o aplicativo. Primeiro, vamos limpar o aplicativo atual.
Execute os comandos a seguir para excluir todas as implantações e serviços que você acabou de criar.
- Excluir
redis-cache-service
kubectl delete -f redis-service.yaml
- Excluir
redis
kubectl delete -f redis.yaml
- Excluir
frontend
kubectl delete -f frontend.yaml
- Excluir
worker
kubectl delete -f worker-primary.yaml
- Excluir
worker-service
kubectl delete -f worker-service.yaml
12. Instalar o Istio no cluster primário
Instalar o Istio
As versões do Istio são hospedadas no GitHub. Os comandos a seguir vão fazer o download e descompactar a versão 1.0.0 do Istio.
- Mude para a raiz do projeto
cd ${proj}
- Fazer o download do arquivo
curl -LO https://github.com/istio/istio/releases/download/1.0.0/istio-1.0.0-linux.tar.gz
- Extrair e remover o arquivo
tar xzf istio-1.0.0-linux.tar.gz && rm istio-1.0.0-linux.tar.gz
Criar modelo do Istio
A execução do comando Helm a seguir cria o modelo para instalar o Istio no cluster.
helm template istio-1.0.0/install/kubernetes/helm/istio \ --name istio --namespace istio-system \ --set prometheus.enabled=true \ --set servicegraph.enabled=true > istio-primary.yaml
Isso cria um arquivo chamado istio-primary.yaml
no diretório atual, que contém todas as definições e especificações necessárias para implantar e executar o Istio.
Observe os dois parâmetros --set
. Eles adicionam suporte ao Prometheus e ao ServiceGraph ao sistema Istio. Vamos usar o serviço Prometheus mais tarde no laboratório.
Implantar o Istio
Para implantar o Istio, primeiro precisamos criar um namespace chamado istio-system
em que as implantações e os serviços do Istio possam ser executados.
kubectl create namespace istio-system
E, por fim, aplique o arquivo istio-primary.yaml
que criamos com o Helm.
kubectl apply -f istio-primary.yaml
Marcar o namespace padrão
O Istio funciona injetando um serviço de proxy sidecar em cada uma das implantações. Isso é feito com base na ativação, então precisamos rotular o namespace default
com istio-injection=enabled
para que o Istio possa injetar automaticamente o sidecar.
kubectl label namespace default istio-injection=enabled
Parabéns! Temos um cluster em execução com o Istio pronto para implantar nosso aplicativo.
13. Implantar nosso aplicativo com o gerenciamento de tráfego do Istio
Criar arquivos de configuração do Istio Traffic Management
O Istio funciona de maneira semelhante ao Kubernetes, já que usa arquivos yaml para configuração. Nesse sentido, precisamos criar um conjunto de arquivos para informar ao Istio como expor e encaminhar nosso tráfego.
Crie um diretório com o nome istio-manifests
e mude para ele
mkdir ${proj}/istio-manifests && cd ${proj}/istio-manifests
Escrever frontend-gateway.yaml
Esse arquivo vai expor nosso cluster do Kubernetes de maneira semelhante a um LoadBalancer do GKE e rotear todo o tráfego de entrada para nosso serviço de front-end.
Crie um arquivo chamado frontend-gateway.yaml
e insira o seguinte.
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: frontend-gateway
spec:
selector:
istio: ingressgateway # use Istio default gateway implementation
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: frontend-ingress-virtual-service
spec:
hosts:
- "*"
gateways:
- frontend-gateway
http:
- route:
- destination:
host: frontend-service
port:
number: 80
Escrever redis-virtualservice.yaml
Crie um arquivo chamado redis-virtualservice.yaml
e insira o seguinte:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: redis-virtual-service
spec:
hosts:
- redis-cache-service
gateways:
- mesh
tcp:
- route:
- destination:
host: redis-cache-service.default.svc.cluster.local
Escrever worker-virtualservice.yaml
Crie um arquivo chamado worker-virtualservice.yaml
e insira o seguinte:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: worker-virtual-service
spec:
hosts:
- worker-service
gateways:
- mesh
http:
- route:
- destination:
host: worker-service.default.svc.cluster.local
port:
number: 80
Implantar políticas de gerenciamento de tráfego do Istio
A implantação das políticas do Istio é feita da mesma maneira que outros recursos do Kubernetes, com kubectl apply
- Aplicar nosso gateway
kubectl apply -f frontend-gateway.yaml
- Aplicar nosso VirtualService do Redis
kubectl apply -f redis-virtualservice.yaml
- Aplicar nosso VirtualService do worker
kubectl apply -f worker-virtualservice.yaml
Implantar o aplicativo
- Volte para o diretório
kubernetes
.
cd ${proj}/kubernetes
- Implantar o cache do Redis
kubectl apply -f redis.yaml
- Implantar o serviço Redis
kubectl apply -f redis-service.yaml
- Implantar o front-end
kubectl apply -f frontend.yaml
- Implantar o worker
kubectl apply -f worker-primary.yaml
- Implantar o serviço do worker
kubectl apply -f worker-service.yaml
Verificar
Neste ponto, reimplantamos nosso aplicativo em um cluster com o Istio e políticas de gerenciamento de tráfego.
Vamos aguardar todas as cargas de trabalho ficarem on-line
Quando todos estiverem on-line, acesse o IngressGateway que configuramos em frontend-ingressgateway.yaml
.
$ kubectl -n istio-system get svc istio-ingressgateway NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-ingressgateway LoadBalancer 10.36.3.112 35.199.158.10 80:31380/TCP,
Acesse o endereço <EXTERNAL-IP> ou faça um curl nele e o frontend vai aparecer.
$ curl 35.199.158.10 <!doctype html> <html> <head> <title>String Hashr</title> <!-- Bootstrap --> ...
14. Instalar o Istio no cluster "burst"
Estamos gastando muito tempo configurando e implantando no cluster primary
, mas temos outro cluster inteiro para implantar.
Nesta seção, vamos precisar coletar variáveis de configuração nos dois clusters. Portanto, preste atenção ao cluster para cada comando.
Criar o manifesto remoto do Istio
Assim como fizemos com a implantação do Istio no cluster primary
, vamos usar o Helm para criar um modelo de implantação do Istio remoto no cluster burst
. No entanto, antes disso, precisamos de algumas informações sobre o cluster primary
.
Coletar informações do cluster principal
Mudar para o cluster primary
kubectx primary
Os comandos a seguir recuperam os endereços IP de vários pods no cluster principal. Eles são usados pelo Istio Remote para se comunicar com o cluster principal.
export PILOT_POD_IP=$(kubectl -n istio-system get pod -l istio=pilot -o jsonpath='{.items[0].status.podIP}')
export POLICY_POD_IP=$(kubectl -n istio-system get pod -l istio-mixer-type=policy -o jsonpath='{.items[0].status.podIP}')
export STATSD_POD_IP=$(kubectl -n istio-system get pod -l istio=statsd-prom-bridge -o jsonpath='{.items[0].status.podIP}')
export TELEMETRY_POD_IP=$(kubectl -n istio-system get pod -l istio-mixer-type=telemetry -o jsonpath='{.items[0].status.podIP}')
export ZIPKIN_POD_IP=$(kubectl -n istio-system get pod -l app=jaeger -o jsonpath='{range .items[*]}{.status.podIP}{end}')
Criar modelo remoto
Agora vamos usar helm
para criar um arquivo chamado istio-remote-burst.yaml
, que pode ser implantado no cluster burst
.
Mudar para a raiz do projeto
cd $proj
helm template istio-1.0.0/install/kubernetes/helm/istio-remote --namespace istio-system \ --name istio-remote \ --set global.remotePilotAddress=${PILOT_POD_IP} \ --set global.remotePolicyAddress=${POLICY_POD_IP} \ --set global.remoteTelemetryAddress=${TELEMETRY_POD_IP} \ --set global.proxy.envoyStatsd.enabled=true \ --set global.proxy.envoyStatsd.host=${STATSD_POD_IP} \ --set global.remoteZipkinAddress=${ZIPKIN_POD_IP} > istio-remote-burst.yaml
Instalar o Istio Remote no cluster burst
Para instalar o Istio no cluster burst
, precisamos seguir as mesmas etapas da instalação no cluster primary
, mas usar o arquivo istio-remote-burst.yaml
.
Mudar o kubecontext para burst
kubectx burst
Criar o namespace istio-system
kubectl create ns istio-system
Aplicar istio-burst.yaml
kubectl apply -f istio-remote-burst.yaml
Namespace padrão do rótulo
Mais uma vez, precisamos rotular o namespace default
para que o proxy possa ser injetado automaticamente.
kubectl label namespace default istio-injection=enabled
Parabéns! Neste ponto, configuramos o Istio Remote no cluster burst
. No entanto, os clusters ainda não conseguem se comunicar. Precisamos gerar um arquivo kubeconfig para o cluster burst
que possa ser implantado no cluster primary
para vinculá-los.
Criar kubeconfig para cluster "burst"
Mudar para cluster de burst
kubectx burst
Configurar o ambiente
Precisamos coletar algumas informações sobre o cluster para criar um arquivo kubeconfig
.
- Conseguir o nome do cluster
CLUSTER_NAME=$(kubectl config view --minify=true -o "jsonpath={.clusters[].name}")
- Conseguir o nome do servidor do cluster
SERVER=$(kubectl config view --minify=true -o "jsonpath={.clusters[].cluster.server}")
- Receber o nome do secret da autoridade certificadora da conta de serviço
istio-multi
SECRET_NAME=$(kubectl get sa istio-multi -n istio-system -o jsonpath='{.secrets[].name}')
- Receber os dados da autoridade certificadora armazenados no segredo anterior
CA_DATA=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['ca\.crt']}")
- Receber o token armazenado no secret anterior
TOKEN=$(kubectl get secret ${SECRET_NAME} -n istio-system -o "jsonpath={.data['token']}" | base64 --decode)
Criar o arquivo kubeconfig
Com todas essas variáveis de ambiente definidas, precisamos criar o arquivo kubeconfig.
cat <<EOF > burst-kubeconfig apiVersion: v1 clusters: - cluster: certificate-authority-data: ${CA_DATA} server: ${SERVER} name: ${CLUSTER_NAME} contexts: - context: cluster: ${CLUSTER_NAME} user: ${CLUSTER_NAME} name: ${CLUSTER_NAME} current-context: ${CLUSTER_NAME} kind: Config preferences: {} users: - name: ${CLUSTER_NAME} user: token: ${TOKEN} EOF
Isso vai criar um novo arquivo chamado burst-kubeconfig
no diretório atual, que pode ser usado pelo cluster primary
para autenticar e gerenciar o cluster burst
.
Mudar de volta para o cluster principal
kubectx primary
Aplicar o kubeconfig para "burst", criando um secret e o rotulando
kubectl create secret generic burst-kubeconfig --from-file burst-kubeconfig -n istio-system
Rotule o segredo para que o Istio saiba usá-lo na autenticação de vários clusters
kubectl label secret burst-kubeconfig istio/multiCluster=true -n istio-system
Parabéns! Os dois clusters são autenticados e se comunicam entre si pelo Istio Multicluster. Vamos implantar o aplicativo entre clusters
15. Implantar um aplicativo entre clusters
Criar implantações
Altere para o diretório kubernetes
.
cd ${proj}/kubernetes
Criar a implantação do worker para o cluster "burst": worker-burst.yaml
Crie um arquivo chamado worker-burst.yaml
e insira o seguinte nele:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: worker-deployment
labels:
app: worker
spec:
replicas: 1
selector:
matchLabels:
app: worker
template:
metadata:
labels:
app: worker
cluster-type: burst-cluster
spec:
containers:
- name: worker
image: gcr.io/istio-burst-workshop/worker
imagePullPolicy: Always
ports:
- containerPort: 8081
readinessProbe:
initialDelaySeconds: 10
httpGet:
path: "/_healthz"
port: 8081
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-readiness-probe"
livenessProbe:
initialDelaySeconds: 10
httpGet:
path: "/"
port: 8081
httpHeaders:
- name: "Cookie"
value: "istio_session-id=x-liveness-probe"
env:
- name: PORT
value: "8081"
- name: REDIS_URL
value: "redis-cache-service:6379"
- name: PREFIX
value: "bursty-"
Observe que ele é quase idêntico ao worker-primary.yaml que criamos anteriormente. Há duas diferenças principais.
A primeira diferença importante é que adicionamos a variável de ambiente PREFIX
com o valor "bursty-
".
env:
- name: PORT
value: "8081"
- name: REDIS_URL
value: "redis-cache-service:6379"
- name: PREFIX
value: "bursty-"
Isso significa que o worker no cluster burst
vai prefixar todos os hashes enviados com "bursty-
". Podemos usar isso para saber se o aplicativo é realmente entre clusters.
A segunda diferença importante é que mudamos o rótulo cluster-type
dessa implantação de primary-cluster
para burst-cluster
.
labels:
app: worker
cluster-type: burst-cluster
Vamos usar esse rótulo mais tarde, quando atualizarmos o VirtualService.
Modificar os serviços do Istio
No momento, nossos serviços do Istio não estão aproveitando as duas implantações. 100% do nosso tráfego está sendo roteado para o cluster "principal". Vamos mudar isso.
Alterar para o diretório istio-manifests
cd ${proj}/istio-manifests
Editar worker-virtualservice.yaml para incluir DestinationRules
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: worker-virtual-service
spec:
hosts:
- worker-service
gateways:
- mesh
http:
- route:
- destination:
host: worker-service.default.svc.cluster.local
subset: primary
port:
number: 80
weight: 50
- destination:
host: worker-service.default.svc.cluster.local
subset: burst
port:
number: 80
weight: 50
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: worker-destination-rule
spec:
host: worker-service
trafficPolicy:
loadBalancer:
simple: RANDOM
subsets:
- name: primary
labels:
cluster-type: primary-cluster
- name: burst
labels:
cluster-type: burst-cluster
Adicionamos um segundo destino ao nosso VirtualService. Ele ainda faz referência ao mesmo host (worker-service.default.svc.cluster.local)
), mas 50% do tráfego está sendo roteado para o subconjunto primary
e os outros 50% para o subconjunto burst
.
Definimos o subconjunto primary
como implantações com o rótulo cluster-type: primary-cluster
e o subconjunto burst
como as implantações com o rótulo cluster-type: burst-cluster
.
Isso divide o tráfego 50/50 entre os dois clusters.
Implantar no cluster
Implantar redis-service.yaml no cluster de pico
Mudar para o kubeconfig burst
kubectx burst
Mudar para a raiz do projeto
cd ${proj}
Em seguida, implante
Implantar o redis-service.yaml no cluster de pico
kubectl apply -f kubernetes/redis-service.yaml
Implantar worker-burst.yaml no cluster de burst
kubectl apply -f kubernetes/worker-burst.yaml
Implantar worker-service.yaml no cluster de pico
kubectl apply -f kubernetes/worker-service.yaml
Aplicar serviços virtuais do Istio
Mudar para o kubeconfig primary
kubectx primary
Em seguida, implantar
kubectl apply -f istio-manifests/worker-virtualservice.yaml
Verificar se funciona
Para verificar se está funcionando, acesse o ponto de entrada do Istio e observe que cerca de 50% dos hashes têm o prefixo "burst-".
Isso significa que estamos conversando entre clusters. Tente mudar os pesos nos diferentes serviços e aplicar o arquivo worker-virtualservice.yaml
. Essa é uma ótima maneira de equilibrar o tráfego entre clusters, mas e se pudéssemos fazer isso automaticamente?
16. Como aproveitar as métricas do Prometheus
Introdução ao Prometheus
O Prometheus é um kit de ferramentas de monitoramento e alerta de sistemas de código aberto criado originalmente no SoundCloud. Ele mantém um modelo de dados multidimensional com dados de série temporal identificados pelo nome da métrica e pares de chave-valor.
Confira o diagrama da arquitetura do Prometheus:
Quando implantado com o Prometheus, o Istio informa automaticamente várias métricas para o servidor do Prometheus. Podemos usar essas métricas para gerenciar nossos clusters em tempo real.
Como usar as métricas do Prometheus
Para começar, precisamos expor a implantação do Prometheus.
Acesse a guia "Cargas de trabalho" no GKE e navegue até a carga de trabalho "prometheus".
Quando você estiver vendo os detalhes da implantação, acesse "Ações" -> "Expor".
Escolha encaminhar para a porta 9090
e digite "Balanceador de carga".
E escolha "Exposição".
Isso vai criar um serviço em um endereço IP acessível publicamente que pode ser usado para analisar as métricas do Prometheus.
Aguarde o endpoint ficar operacional e clique no endereço IP ao lado de "Endpoints externos".
Agora você deve estar vendo a interface do Prometheus.
O Prometheus fornece métricas suficientes para ser um workshop. Por enquanto, vamos começar analisando a métrica istio_requests_total
.
A execução dessa consulta retorna muitos dados. São métricas de todas as solicitações que passam pela malha de serviço do Istio, e são muitas. Vamos mudar a expressão para filtrar o que realmente nos interessa:
Solicitações em que o serviço de destino é worker-service.default.svc.cluster.local
e a origem é frontend-deployment
limitada aos últimos 15 segundos
Essa consulta é semelhante a esta:
istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s]
E nos fornece um conjunto de dados muito mais gerenciável para trabalhar
Mas ainda é um pouco densa. Queremos saber as solicitações por segundo, não todas as solicitações.
Para isso, podemos usar a função rate
integrada.
rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])
Isso está nos aproximando, mas precisamos reduzir essas métricas um pouco mais em um grupo lógico.
Para isso, podemos usar as palavras-chave sum
e by
para agrupar e somar nossos resultados.
sum(rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])) by (source_workload,
source_app, destination_service)
Perfeito! Podemos extrair as métricas exatas que precisamos do Prometheus.
Nossa consulta final do Prometheus
Com tudo o que aprendemos, a consulta final que precisamos fazer ao Prometheus é
sum(rate(istio_requests_total{reporter="destination",
destination_service="worker-service.default.svc.cluster.local",
source_workload="frontend-deployment"}[15s])) by (source_workload,
source_app, destination_service)
Agora podemos usar a API HTTP para acessar a métrica.
Podemos consultar a API com nossa consulta fazendo uma solicitação GET HTTP. Substitua <prometheus-ip-here>
curl http://<prometheus-ip-here>/api/v1/query?query=sum\(rate\(istio_requests_total%7Breporter%3D%22destination%22%2C%0Adestination_service%3D%22worker-service.default.svc.cluster.local%22%2C%0Asource_workload%3D%22frontend-deployment%22%7D%5B15s%5D\)\)%20by%20\(source_workload%2C%0Asource_app%2C%20destination_service\)
Confira um exemplo de resposta:
{
"status": "success",
"data": {
"resultType": "vector",
"result": [
{
"metric": {
"destination_service": "worker-service.default.svc.cluster.local",
"source_app": "frontend",
"source_workload": "frontend-deployment"
},
"value": [
1544404907.503,
"18.892886390062788"
]
}
]
}
}
Agora, podemos extrair o valor da métrica do JSON.
Limpeza
Precisamos excluir o serviço que acabamos de usar para expor o Prometheus. No Console do Google Cloud, acesse a parte de cima do serviço que acabamos de criar e clique em "Excluir".
Próximas etapas:
Depois de encontrar uma maneira de descobrir como o tráfego está se movendo pelo cluster e a que taxa, a próxima etapa é escrever um binário pequeno que consulta o Prometheus periodicamente. Se as solicitações por segundo para worker
excederem um determinado limite, aplique diferentes pesos de destino no serviço virtual do worker para enviar todo o tráfego ao cluster burst
. Quando as solicitações por segundo ficarem abaixo de um limite inferior, envie todo o tráfego de volta para primary
.
17. Criar um burst entre clusters
Configuração
Definir todo o tráfego do serviço do worker para o cluster principal
Vamos considerar que todo o tráfego destinado a worker-service
e roteado para o cluster primary
é o estado "padrão" do nosso aplicativo.
Edite $proj/istio-manifests/worker-virtualservice.yaml
para ficar assim:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: worker-virtual-service
spec:
hosts:
- worker-service
gateways:
- mesh
http:
- route:
- destination:
host: worker-service.default.svc.cluster.local
subset: primary
port:
number: 80
weight: 100
- destination:
host: worker-service.default.svc.cluster.local
subset: burst
port:
number: 80
weight: 0
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: worker-destination-rule
spec:
host: worker-service
trafficPolicy:
loadBalancer:
simple: RANDOM
subsets:
- name: primary
labels:
cluster-type: primary-cluster
- name: burst
labels:
cluster-type: burst-cluster
Verifique se você está conectado ao cluster primary
kubectx primary
Aplicar istio-manifests/worker-virtualservice.yaml
kubectl apply -f istio-manifests/worker-virtualservice.yaml
Escrever o daemon istiowatcher
Vamos usar o Go para criar esse serviço por causa da velocidade e da portabilidade. O fluxo geral do aplicativo será inicializar e, a cada segundo, consultar o Prometheus.
Crie um novo diretório em src com o nome istiowatcher
mkdir -p ${proj}/src/istiowatcher && cd ${proj}/src/istiowatcher
Vamos chamar istioctl
no contêiner para manipular o plano de controle do Istio no cluster.
Escrever istiowatcher.go
Crie um arquivo nesse diretório chamado istiowatcher.go
e insira o seguinte nele
package main
import (
"github.com/tidwall/gjson"
"io/ioutil"
"log"
"net/http"
"os/exec"
"time"
)
func main() {
//These are in requests per second
var targetLow float64 = 10
var targetHigh float64 = 15
// This is for the ticker in milliseconds
ticker := time.NewTicker(1000 * time.Millisecond)
isBurst := false
// Our prometheus query
reqQuery := `/api/v1/query?query=sum(rate(istio_requests_total{reporter="destination",destination_service="worker-service.default.svc.cluster.local",source_workload="frontend-deployment"}[15s]))by(source_workload,source_app,destination_service)`
for t := range ticker.C {
log.Printf("Checking Prometheus at %v", t)
// Check prometheus
// Note that b/c we are querying over the past 5 minutes, we are getting a very SLOW ramp of our reqs/second
// If we wanted this to be a little "snappier" we can scale it down to say 30s
resp, err := http.Get("http://prometheus.istio-system.svc.cluster.local:9090" + reqQuery)
if err != nil {
log.Printf("Error: %v", err)
continue
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
val := gjson.Get(string(body), "data.result.0.value.1")
log.Printf("Value: %v", val)
currentReqPerSecond := val.Float()
log.Printf("Reqs per second %f", currentReqPerSecond)
if currentReqPerSecond > targetHigh && !isBurst {
applyIstio("burst.yaml")
log.Println("Entering burst mode")
isBurst = true
} else if currentReqPerSecond < targetLow && isBurst {
applyIstio("natural.yaml")
log.Println("Returning to natural state.")
isBurst = false
}
}
}
func applyIstio(filename string) {
cmd := exec.Command("istioctl", "replace", "-f", filename)
if err := cmd.Run(); err != nil {
log.Printf("Error hit applying istio manifests: %v", err)
}
}
Escrever o Dockerfile
Crie um novo arquivo chamado Dockerfile
e insira o seguinte nele.
FROM golang:1.11.2-stretch as base
FROM base as builder
WORKDIR /workdir
RUN curl -LO https://github.com/istio/istio/releases/download/1.0.0/istio-1.0.0-linux.tar.gz
RUN tar xzf istio-1.0.0-linux.tar.gz
RUN cp istio-1.0.0/bin/istioctl ./istioctl
FROM base
WORKDIR /go/src/istiowatcher
COPY . .
COPY --from=builder /workdir/istioctl /usr/local/bin/istioctl
RUN go get -d -v ./...
RUN go install -v ./...
CMD ["istiowatcher"]
Esse Dockerfile com vários estágios faz o download e extrai a versão 1.0.0 do Istio no primeiro estágio. A segunda etapa copia tudo do nosso diretório para a imagem, depois copia istioctl
do estágio de build para /usr/local/bin
(para que possa ser chamado pelo nosso aplicativo), recebe as dependências, compila o código e define CMD
como "istiowatcher
".
Gravar burst.yaml
Esse é o arquivo que o istiowatcher
vai aplicar quando as solicitações/segundo para worker
de frontend
excederem 15.
Crie um novo arquivo chamado burst.yaml
e insira o seguinte nele.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: worker-virtual-service
spec:
hosts:
- worker-service
gateways:
- mesh
http:
- route:
- destination:
host: worker-service.default.svc.cluster.local
subset: primary
port:
number: 80
weight: 0
- destination:
host: worker-service.default.svc.cluster.local
subset: burst
port:
number: 80
weight: 100
Escrever natural.yaml
Consideraremos esse o estado "natural" para o qual voltamos quando as solicitações/segundo de frontend
para worker
caírem abaixo de 10. Nesse estado, 100% do tráfego está sendo roteado para o cluster primary
.
Crie um novo arquivo chamado natural.yaml
e insira o seguinte nele
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: worker-virtual-service
spec:
hosts:
- worker-service
gateways:
- mesh
http:
- route:
- destination:
host: worker-service.default.svc.cluster.local
subset: primary
port:
number: 80
weight: 100
- destination:
host: worker-service.default.svc.cluster.local
subset: burst
port:
number: 80
weight: 0
Build and Push istiowatcher
Execute o comando a seguir para enviar o diretório atual ao Google Cloud Build (GCB), que vai criar e marcar a imagem no GCR.
gcloud builds submit -t gcr.io/${GCLOUD_PROJECT}/istiowatcher
Implantar o istiowatcher
Mude para o diretório kubernetes
cd ${proj}/kubernetes/
Escrever um arquivo de implantação: istiowatcher.yaml
Crie um arquivo chamado istiowatcher.yaml e insira o seguinte (substitua <your-project-id>).
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: istiowatcher-deployment
labels:
app: istiowatcher
spec:
replicas: 1
selector:
matchLabels:
app: istiowatcher
template:
metadata:
labels:
app: istiowatcher
spec:
serviceAccountName: istio-pilot-service-account
automountServiceAccountToken: true
containers:
- name: istiowatcher
image: gcr.io/<your-project-id>/istiowatcher
imagePullPolicy: Always
Implantar
Executar no cluster principal
kubectx primary
Implante istiowatcher.yaml
no namespace istio-system
kubectl apply -n istio-system -f istiowatcher.yaml
É importante observar as diretivas serviceAccountName
e automountServiceAccountToken
no yaml. Isso nos dá as credenciais necessárias para executar istioctl
no cluster.
Também precisamos implantar isso no namespace istio-system
para garantir que temos as credenciais para o istio-pilot-service-account
. Ele não existe no namespace default
.
Observe o tráfego mudar automaticamente.
Agora, o momento mágico! Vamos ao front-end e aumentar a taxa de req/segundo para 20
Ele leva alguns segundos, mas aumenta e todos os hashes têm o prefixo "bursty-".
Isso ocorre porque estamos amostrando o Prometheus em um intervalo de 15s
, o que faz com que o tempo de resposta demore um pouco. Se quiséssemos uma faixa muito mais estreita, poderíamos mudar nossa consulta para prometheus para ser 5s.
18. A seguir
Limpeza
Não é necessário limpar se você estiver usando uma conta temporária fornecida para este workshop.
Você pode excluir seus clusters do Kubernetes, a regra de firewall e as imagens no GCR
gcloud container clusters delete primary --zone=us-west1-a
gcloud container clusters delete burst --zone=us-west1-a
gcloud compute firewall-rules delete istio-multicluster-test-pods
gcloud container images delete gcr.io/$GCLOUD_PROJECT/istiowatcher
O futuro
- Participe de algumas palestras do Istio.
- Obtenha o certificado: crie seu próximo app com o Kubernetes e o Istio
- Palestra: Kubernetes, Istio, Knative: o novo stack de nuvem aberta - Aparna Sinha, gerente de produto do grupo do Kubernetes, Google
- Tutorial: Como usar o Istio - Lee Calcote e Girish Ranganathan, SolarWinds
- Istio: o ponto de vista do pacote - Matt Turner, Tetrate
- O Istio é o firewall de última geração mais avançado já criado? - John Morello, Twistlock
- Leia a documentação do Istio.
- Participe dos grupos de trabalho do Istio.
- Siga @IstioMesh no Twitter