Vamos instalar o podinfo, uma aplicação de teste para ver as coisas funcionando.
Um detalhe aqui muito importante.
- como estamos usando o kind então o service de DNS do cluster é `kube-dns.kube-system.svc.cluster.local`, se estiver usando K8s Gerenciado por alguma cloud ou kubespray verifique o nome do service e edite o `configMap` do `multicluster/base/frontend.yml`
- atente-se se mudar o nome dos clusters, é necessário também mudar o nome das pastas em `multicluster/kind-demo`
Se for o caso faça um fork ou clone e mude os nomes e conteúdo, mas estude o repositório, veja o que ele faz, be curious.
for ctx in kind-demo kind-demo3; do
echo "Adding test services on cluster: ${ctx} ........."
kubectl --context=${ctx} create ns test
kubectl --context=${ctx} apply \
-n test -k "github.com/adonaicosta/linkerd-multicluster/multicluster/${ctx}/"
kubectl --context=${ctx} -n test \
rollout status deploy/podinfo || break
echo "-------------"
done
Verifique se os pods estão no ar:
for ctx in kind-demo kind-demo3; do
echo "Check pods on cluster: ${ctx} ........."
kubectl get pod -n test --context=${ctx}
done
Vamos acessar a aplicação e validar se o frontend consegue bater em ambos os pods, para cada cluster ainda separadamente, não estamos em multicluster ainda hein!
kubectl port-forward -n test svc/frontend 8080:8080 --context=kind-demo
Abra seu browser http://localhost:8080
Viu?!
Agora faça para o outro cluster
kubectl port-forward -n test svc/frontend 8080:8080 --context=kind-demo3
Abra seu browse http://localhost:8080
Viu?!
Chegou a hora de ver a função crosscluster funcionar
Para que os pods frontend em cada cluster consigam acessar os podinfo do outro cluster, é necessário espelhar o serviço de podinfo entre os clusters.
A aplicação frontend já faz a chamada para cada cluster, pois foi pré-configurada.
Então vamos etiquetar o serviço podinfo em cada cluster e depois criar um trafficsplit para cada um.
Etiquetando...
for ctx in kind-demo kind-demo3; do
echo -en "\n\nLabel svc podinfo on cluster: ${ctx} .........\n"
kubectl label svc -n test podinfo mirror.linkerd.io/exported=true --context=${ctx}
sleep 4
echo "Check services transConnected (if word exists )....on cluster ${ctx}"
kubectl get svc -n test --context=${ctx}
done
Agora em cada cluster vai existir um serviço podinfo-(CONTEXTO) que aponta para outro cluster no IP do serviço linkerd-multicluster/linkerd-gateway.
kubectl get svc --context=kind-demo -n linkerd-multicluster linkerd-gateway -o \
jsonpath='{.status.loadBalancer.ingress[0].ip}'
172.17.0.61
kubectl get endpoints --context=kind-demo3 -n test podinfo-kind-demo -o \
jsonpath='{.subsets[*].addresses[*].ip}'
172.17.0.61
São os mesmos certo? Isso diz que o endpoint do serviço test/podinfo-kind-demo3 aponta pro serviço LoadBalancer do linkerd-multicluster/linkerd-gateway do cluster kind-demo.
Faça o mesmo pro outro cluster:
kubectl get svc --context=kind-demo3 -n linkerd-multicluster linkerd-gateway -o \
jsonpath='{.status.loadBalancer.ingress[0].ip}'
172.17.0.71
kubectl get endpoints --context=kind-demo -n test podinfo-kind-demo3 -o \
jsonpath='{.subsets[*].addresses[*].ip}'
172.17.0.71
Distribuindo a carga entre os clusters
Criando o trafficsplit…
kubectl --context=kind-demo apply -f - <<EOF
apiVersion: split.smi-spec.io/v1alpha1
kind: TrafficSplit
metadata:
name: podinfo
namespace: test
spec:
service: podinfo
backends:
- service: podinfo
weight: 50
- service: podinfo-kind-demo3
weight: 50
EOF
kubectl --context=kind-demo3 apply -f - <<EOF
apiVersion: split.smi-spec.io/v1alpha1
kind: TrafficSplit
metadata:
name: podinfo
namespace: test
spec:
service: podinfo
backends:
- service: podinfo
weight: 50
- service: podinfo-kind-demo
weight: 50
EOF
Dividimos a carga do podinfo em 50% para cada cluster, para cada um, então temos um `cross access` entre eles.
Faça um port-forward novamente (se já cancelou anteriormente) para um frontend e acompanhe.
kubectl port-forward -n test --context=kind-demo svc/frontend 8080
Abra seu browser de novo http://localhost:8080
Voilá…
Se você fizer port-forward no mesmo serviço frontend do outro cluster o resultado vai ser o mesmo.
Parte 5 — BONUS
Instalando ingress controller, criando um ingress e simulando a vida real como ela é
Aqui podemos e vamos além dos clusters Kubernetes. Com um ingress em cada cluster podemos; em uma camada de DNS, por exemplo; distribuirmos as requisições entre os clusters que estarão balanceando as mesmas requisições entre si.
Em linhas gerais, isso significa que você pode balancear externamente, via DNS, as requisições entre os serviços que estarão cruzados, garantindo assim alta disponibilidade. Vamos a um desenho para explicar melhor:
Então agora vamos à prática e demonstração.
Instale o ingress-nginx em cada um dos clusters.
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
for ctx in kind-demo kind-demo3; do
echo "Instalando o ingress-nginx - ${ctx}"
helm install ingress-nginx -n ingress-nginx --create-namespace ingress-nginx/ingress-nginx --set controller.podAnnotations.linkerd.io/inject=enabled --kube-context=${ctx}
echo "Aguarde a instalação do ingress-nginx terminar, 30s, acho"
kubectl rollout status deploy -n ingress-nginx ingress-nginx-controller --context=${ctx}
echo "Criando um ingress para o podinfo - ${ctx}"
kubectl --context=${ctx} -n test create ingress frontend --class nginx --rule="frontend-${ctx}.domain.com/*=frontend:8080" -–annotation=”nginx.ingress.kubernetes.io/service-upstream=true”
done
Pegue o fqdn da sua aplicação pod info em cada cluster e adicione no seu /etc/hosts:
for ctx in kind-demo kind-demo3; do
echo "Adicione o hostname e IP no seu /etc/hosts e aguarde o ingress-nginx atribuir IP ao ingress, uns 30s"
kubectl --context=${ctx} get ingress -n test
done
> Não esqueca de colocar no seu /etc/hosts o IP host criados acima.
Conclusão
Vimos aqui que um multicluster com mesh, seguro, fácil e unplugged não tem muito segredo. Apenasmuitos passos para se atentar:
Verifique se o linkerd nos clusters têm a mesma chave TLS, criada com openssl
Instale o linkerd-multicluster para estabelecer conectividade entre eles
Instale o linkerd-smi para criar distribuição de tráfego
Crie objetos trafficsplit para distribuir esse acesso
Lembre-se, cada cluster no exemplo tem uma URL, é a hora de colocar seu DNS pra trabalhar não somente com roundrobin, mas com health-checks e failover.
O linkerd tem ainda uma extensão para multicluster failover, o que vai aumentar ainda mais a disponibilidade de aplicações entre clusters, que é o pretendido final.
Referências
**Getup:** https://blog.getup.io
**ServiceMesh:** https://smi-spec.io/
**A Really Service Mesh:** https://linkerd.io 😙