IDP Lab
Depois de tudo que leu sobre IDP precisamos montar um cenário pré produtivo para tentar nossas experiências.
Todo esse cenário será utilizado no estudo do Backstage. Podemos aproveitar o mesmo cenários para estudo do Port, mas vou fazer algumas ressalvas durante s instalação então fique atento.
- Instale o docker pois será necessário para rodar o kind depois.
- Instale o kubectl pois é necessário para rodar o kind e aplicar manifestos no cluster.
- Instale o helm pois vamos usar charts prontos para instalação de ferramentas.
- Instale o Kind pois será utilizado criar um cluster local.
- Instale o argocd cli. Será usado para gerar os tokens e password para o argocd.
Para o kind particulamente gosto de ter 3 nodes disponíveis para eventuais teste de ferramentas que utilizam replicas sem pontos nodes separados. Para isolar o ingress controller vamo colocá-lo em um node separado. Teremos um total de 5 nodes.
- 1 control-plane
- 1 worker para o ingress
- 3 workers para o aplicações
Criando o Cluster
############## KIND LOCAL CLUSTER ##################
### Criando o config para o kind
cat <<EOF > lab-kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: study
networking:
ipFamily: ipv4
# disableDefaultCNI: true
kubeProxyMode: "ipvs"
podSubnet: "10.244.0.0/16"
serviceSubnet: "10.96.0.0/12"
apiServerAddress: "127.0.0.1"
apiServerPort: 6443
nodes:
- role: control-plane
extraMounts:
- hostPath: /dev
containerPath: /dev
- hostPath: /var/run/docker.sock
containerPath: /var/run/docker.sock
- role: worker
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
extraMounts:
- hostPath: /dev
containerPath: /dev
- hostPath: /var/run/docker.sock
containerPath: /var/run/docker.sock
- role: worker
extraMounts:
- hostPath: /dev
containerPath: /dev
- hostPath: /var/run/docker.sock
containerPath: /var/run/docker.sock
- role: worker
extraMounts:
- hostPath: /dev
containerPath: /dev
- hostPath: /var/run/docker.sock
containerPath: /var/run/docker.sock
- role: worker
extraMounts:
- hostPath: /dev
containerPath: /dev
- hostPath: /var/run/docker.sock
containerPath: /var/run/docker.sock
EOF
# Criando o cluster com a configuração acima
kind create cluster --config lab-kind-config.yaml
Para que tenhamos um ingress local na máquina vamos instalar o nginx ingress. Nosso localhost será o nosso domínio.
############## NGINX INGRESS ##################
# Baixando os manifestos e alterando o nodeSelector para deployar no node study-worker, o primeiro node que vamos dedicar ao ingress exclusivamente
curl -s https://kind.sigs.k8s.io/examples/ingress/deploy-ingress-nginx.yaml | sed 's/kubernetes.io\/os: linux/kubernetes.io\/hostname: study-worker/g' > deploy-ingress-nginx.yaml
# Instalando o ingress com o yaml criando acima.
kubectl apply -f deploy-ingress-nginx.yaml
Deployando o ArgoCD no Cluster
Agora vamos instalar o ArgoCD no cluster. Para não precisar gerar tokens para cada repositório, vamos criar um token nas contas do github e gitlab para permitir o argocd ler todos os repositórios das contas. Deixe os tokens exportados como variáveis de ambiente para rodar os comandos abaixo.
export GITHUB_ACCOUNT_TOKEN=ghp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
export GITLAB_ACCOUNT_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx
Faça o mesmo para a sua conta.
export GITHUB_ACCOUNT=davidpuziol
export GITLAB_ACCOUNT=davidpuziol
############## ARGOCD ##################
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
# Esta sera a senha utilizada no argocd para o usuário admin. Ela precisa ser gerada através do bcript.
export ARGO_PWD=devsecops
ARGO_PWD_BCRIPT=$(argocd account bcrypt --password $ARGO_PWD | tr -d ':\n' | sed 's/$2y/$2a/')
## No próprio momento do deployment vamos criar uma conta chamada backstage que somente tem acesso usando api e colocar algumas roles.
## Adicionei também um usuário para o Port somente para aproveitar o lab.
## Vamos definir os repositórios do github que o argocd irá ter. Para evitar que fiquemos fazendo token repo a repo podemos criar um token geral para acesso a todos os repositórios e criar um template.
# Um detalhe importante: Estamos dando muita permissão para essa conta, uma vez que o plugin padrão do argocd somente precisa de acesso a leitura. Porém gostaria no futuro de construir alguns plugins que pudessem fazer mais do que somente mostrar um card do argocd no backstage.
cat <<EOF > argo-values.yaml
global:
domain: argo.localhost
server:
ingress:
enabled: true
ingressClassName: nginx
hostname: argo.localhost
path: /
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
configs:
secret:
argocdServerAdminPassword: "$ARGO_PWD_BCRIPT"
params:
server.insecure: true
credentialTemplates:
github-$GITLAB_ACCOUNT:
url: https://github.com/davidpuziol
password: "$GITHUB_TOKEN_ARGOCD"
username: "$GITHUB_ACCOUNT"
gitlab-$GITLAB_ACCOUNT:
url: https://gitlab.com/davidpuziol
password: "$GITLAB_TOKEN_ARGOCD"
username: "$GITLAB_ACCOUNT"
cm:
accounts.backstage: "apiKey"
accounts.crossplane: "apiKey"
accounts.port: "apiKey"
rbac:
policy.csv: |
p, backstage, applications, get, */*, allow
p, backstage, applications, create, */*, allow
p, backstage, applications, update, */*, allow
p, backstage, applications, delete, */*, allow
p, backstage, clusters, get, *, allow
p, backstage, clusters, create, *, allow
p, backstage, clusters, update, *, allow
p, backstage, clusters, delete, *, allow
p, port, applications, get, */*, allow
p, port, applications, create, */*, allow
p, port, applications, update, */*, allow
p, port, applications, delete, */*, allow
p, port, clusters, get, *, allow
p, port, clusters, create, *, allow
p, port, clusters, update, *, allow
p, port, clusters, delete, *, allow
p, crossplane, applications, get, */*, allow
p, crossplane, applications, create, */*, allow
p, crossplane, applications, update, */*, allow
p, crossplane, applications, delete, */*, allow
p, crossplane, clusters, get, *, allow
p, crossplane, clusters, create, *, allow
p, crossplane, clusters, update, *, allow
p, crossplane, clusters, delete, *, allow
EOF
helm install argocd argo/argo-cd --namespace argocd --create-namespace -f argo-values.yaml
Se estiver fazendo o lab para o backstage então precisamos do token para a conta do backstage, mas se somente for utilizar o Port pode ignorar essa etapa.
argocd login argo.localhost --username admin --password devsecops --insecure --grpc-web
# Salvando o token que vamos usar depois na integração com o backstage.
argocd account generate-token --account backstage > argocd-backstage-token
O plugin do argocd no backstage pede para adicionar antes do token **argocd.token=**seutoken.
export ARGOCD_AUTH_TOKEN_BACKSTAGE="argocd.token=$(cat argocd-backstage-token)
Exemplo de como ficaria no terminal. Coloque no seu shell como variável de ambiente.
ARGOCD_AUTH_TOKEN_BACKSTAGE=argocd.token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhcmdvY2QiLCJzdWIiOiJiYWNrc3RhZ2U6YXBpS2V5IiwibmJmIjoxNzMzMTY5MjIyLCJpYXQiOjE3MzMxNjkyMjIsImp0aSI6IjA3YWEyZmVkLTI1NmQtNGIyNi04NTUyLWMxYzgyNjU3ZTI1OCJ9.yWQ6LKg3T_4WJSrW3CYuBKATpkB_qHADVUppW3gu3Cw
Já vamos aproveitar e deixar um token para o Crossplane criado. O motivo de deixar uma conta para o crossplane no argocd é que depois de entender a ferramenta Backstage e o Port faremos o uso do Crossplane em ambas as ferramentas.
argocd login argo.localhost --username admin --password devsecops --insecure --grpc-web
# Salvando o token que vamos usar depois na integração com o crossplane.
argocd account generate-token --account crossplane > argocd-crossplane-token
# Adicione no seu terminal para evitar esquecer, pois não vamos usar agora.
export ARGOCD_AUTH_TOKEN_CROSSPLANE="$(cat argocd-crossplane-token)
Se for utilizar o lab para estudo do Port então já vamos aproveitar e deixar um token para o Port criado.
argocd login argo.localhost --username admin --password devsecops --insecure --grpc-web
# Salvando o token que vamos usar depois na integração com o crossplane.
argocd account generate-token --account port > argocd-port-token
# Adicione no seu terminal para evitar esquecer, pois não vamos usar agora.
export ARGOCD_AUTH_TOKEN_PORT="$(cat argocd-port-token)
Criando uma Service Account no Cluster para o Backstage
Se estiver usando o Lab para estudo do Port não execute esta etapa
No futuro iremos deployar o backstage no kubernetes e vamos deixar o namespace criado, apesar de que poderíamos criar em um segundo momento. Criar agora nos possibilitará fazer testes com o kubernetes antes mesmo de deployar o backstage no kubernetes, que será a última etapa do processo.
Para que o backstage acesse um cluster kubernetes ele precisa de acesso e permissão. O Backstage poderia acessar cluster em qualquer lugar não necessariamente naquele que ele estiver deployado no futuro. Para representar isso vamos criar uma service account no cluter para o backstage imaginando que esse cluster poderia ser qualquer outro. Mesmo ele estando deployado na ultima etapa no cluster, ele usará esta service account.
######################## BACKSTAGE ##############################
# Criando um namespace para o backstage e um service account com permissão adquada.
kubectl create namespace backstage
kubectl create sa backstage-sa -n backstage
cat <<EOF > backstage-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: backstage-role
rules:
- apiGroups:
- '*'
resources:
- configmaps
- services
- deployments
- replicasets
- horizontalpodautoscalers
- ingresses
- statefulsets
- limitranges
- resourcequotas
- daemonsets
verbs:
- get
- list
- watch
- apiGroups:
- '*'
resources:
- pods
verbs:
- get
- list
- watch
- delete
- apiGroups:
- batch
resources:
- jobs
- cronjobs
verbs:
- get
- list
- watch
- apiGroups:
- metrics.k8s.io
resources:
- pods
verbs:
- get
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: backstage-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: backstage-role
subjects:
- kind: ServiceAccount
name: backstage-sa
namespace: backstage
EOF
kubectl create -n backstage clusterrolebinding rolebinding-backstage --clusterrole admin --serviceaccount backstage:backstage-sa
# Vamos criar um token para essa account para ser usada pelo backstage
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
name: backstage-sa-token
namespace: backstage
annotations:
kubernetes.io/service-account.name: "backstage-sa"
type: kubernetes.io/service-account-token
EOF
kubectl get secret backstage-sa-token -n backstage -o jsonpath='{.data.token}' | base64 --decode > backstage_token
Banco de Dados para o Backstage
Se estiver usando o Lab para estudo do Port não execute esta etapa
Quando o Backstage for produtivo precisamos de um database postgres. A melhor coisa a se fazer estando de uma cloud é terceirizar o banco para cloud ao invés de deployar dentro do kubernetes. Eu não gosto muito dessa aborgagem, mas se for criar então que utilizemos um método eficiente. Gosto de deployar o Postgres utilizando o chart da bitnami que possui bastante configuração para escalabilidade.
############## POSTGREE ##################
# O Postgree sera usado para o Backstage. Vamos instalar dentro do namespace backstage e somente usá-lo para esse propósito.
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
cat <<EOF > postgres-values.yaml
global:
postgresql:
auth:
postgresPassword: "devsecops"
username: admin
password: devsecops
database: backstage
primary:
persistence:
enabled: true
size: 5Gi
service:
type: ClusterIP
EOF
helm install backstage-postgres bitnami/postgresql -f postgres-values.yaml --namespace backstage
kubectl port-forward --namespace backstage svc/backstage-postgres-postgresql 5432:5432 &
Para ter acesso a este banco caso queira usar em desenvolvimento é necessaŕio fazer o port-forward acima. Todo o processo de desenvolvimento irá utilizar um banco em memória logo, a cada restart da aplicação perderemos os dados.
Kubernetes Dashboard (Opcional)
Se estiver usando o Lab para o Port não execute esta etapa
Para gerenciar o cluster visualmente podemos instalar o Kubernetes Dashboard. A idéia é conseguir utilizando um iframe ver esse dashboard dentro do próprio Backstage.
cat <<EOF > dashboard-values.yaml
app:
ingress:
enabled: true
hosts:
- dash.localhost
ingressClassName: nginx
EOF
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
helm repo update
helm install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard --create-namespace --namespace kubernetes-dashboard -f dashboard-values.yaml
Utilize o mesmo token do backstage-sa para acessar.