Skip to main content

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.