
O que veio primeiro - uma galinha ou um ovo? Um começo bastante estranho para um artigo sobre Infraestrutura como Código, não é?
O que é um ovo?
Na maioria das vezes, a infraestrutura como código (IaC) é uma forma declarativa de representar a infraestrutura. Nele descrevemos o estado que queremos obter, começando pela parte de ferro, terminando com a configuração do software. Portanto, IaC é usado para:
- Provisão de recursos. São VMs, S3, VPC, etc. Ferramentas básicas de trabalho: Terraform e CloudFormation .
- Configuração de software . Ferramentas básicas: Ansible , Chef, etc.
Qualquer código está em repositórios git. E mais cedo ou mais tarde o líder da equipe decidirá que seria necessário colocar as coisas em ordem. E vai refatorar. E criará alguma estrutura. E ele verá que está bom.
Também é bom que já exista um provedor GitLab e GitHub para Terraform (e isso é uma configuração de software). Com a ajuda deles, você pode gerenciar todo o projeto: membros da equipe, CI / CD, git-flow, etc.
De onde veio o ovo?
Assim, gradualmente chegamos à questão principal.
Primeiro de tudo, você precisa começar com um repositório que descreve a estrutura de outros repositórios, incluindo você. E, claro, dentro do GitOps, você precisa adicionar um CI para que as mudanças sejam executadas automaticamente.
Se o Git ainda não foi construído?
- Como faço para armazená-lo no Git?
- Como aparafusar o CI?
- Se também implantarmos o Gitlab usando IaC, e até mesmo no Kubernetes?
- E o GitLab Runner também está no Kubernetes?
- E o Kubernetes em um provedor de nuvem?
O que veio primeiro: GitLab, onde irei carregar meu código, ou código que descreve qual GitLab eu preciso?
Frango com ovos
" Dinossauro Oyakodon 3 » [ src ]
Vamos tentar cozinhar um prato usando Managed Kubernetes Selectel como um provedor de nuvem .
TL; DR
É possível imediatamente e em uma equipe?
$ export MY_SELECTEL_TOKEN=<token>
$ curl https://gitlab.com/chicken-or-egg/mks/make/-/snippets/2002106/raw | bash
Ingredientes:
- Conta de my.selectel.ru;
- Token da conta;
- Habilidades de Kubernetes;
- Habilidades de leme;
- Habilidades do Terraform;
- Helm chart GitLab;
- Executor GitLab do gráfico do Helm.
Receita:
- Obtenha MY_SELECTEL_TOKEN no painel my.selectel.ru .
- Crie um cluster Kubernetes transferindo o token da conta para ele.
- Obtenha KUBECONFIG do cluster criado.
- Instale o GitLab no Kubernetes.
- Obtenha o token GitLab do GitLab gerado para o usuário root .
- Crie uma estrutura de projeto no GitLab usando o token GitLab.
- Envie o código existente para o GitLab.
- ???
- Lucro!
Etapa 1 . O token pode ser obtido na seção Chaves de API .

provider "selectel" {
token = var.my_selectel_token
}
variable "my_selectel_token" {}
variable "username" {}
variable "region" {}
resource "selectel_vpc_project_v2" "my-k8s" {
name = "my-k8s-cluster"
theme = {
color = "269926"
}
quotas {
resource_name = "compute_cores"
resource_quotas {
region = var.region
zone = "${var.region}a"
value = 16
}
}
quotas {
resource_name = "network_floatingips"
resource_quotas {
region = var.region
value = 1
}
}
quotas {
resource_name = "load_balancers"
resource_quotas {
region = var.region
value = 1
}
}
quotas {
resource_name = "compute_ram"
resource_quotas {
region = var.region
zone = "${var.region}a"
value = 32768
}
}
quotas {
resource_name = "volume_gigabytes_fast"
resource_quotas {
region = var.region
zone = "${var.region}a"
# (20 * 2) + 50 + (8 * 3 + 10)
value = 130
}
}
}
resource "selectel_mks_cluster_v1" "k8s-cluster" {
name = "k8s-cluster"
project_id = selectel_vpc_project_v2.my-k8s.id
region = var.region
kube_version = "1.17.9"
}
resource "selectel_mks_nodegroup_v1" "nodegroup_1" {
cluster_id = selectel_mks_cluster_v1.k8s-cluster.id
project_id = selectel_mks_cluster_v1.k8s-cluster.project_id
region = selectel_mks_cluster_v1.k8s-cluster.region
availability_zone = "${var.region}a"
nodes_count = 2
cpus = 8
ram_mb = 16384
volume_gb = 15
volume_type = "fast.${var.region}a"
labels = {
"project": "my",
}
}
Adicione um usuário ao projeto:
resource "random_password" "my-k8s-user-pass" {
length = 16
special = true
override_special = "_%@"
}
resource "selectel_vpc_user_v2" "my-k8s-user" {
password = random_password.my-k8s-user-pass.result
name = var.username
enabled = true
}
resource "selectel_vpc_keypair_v2" "my-k8s-user-ssh" {
public_key = file("~/.ssh/id_rsa.pub")
user_id = selectel_vpc_user_v2.my-k8s-user.id
name = var.username
}
resource "selectel_vpc_role_v2" "my-k8s-role" {
project_id = selectel_vpc_project_v2.my-k8s.id
user_id = selectel_vpc_user_v2.my-k8s-user.id
}
Resultado:
output "project_id" {
value = selectel_vpc_project_v2.my-k8s.id
}
output "k8s_id" {
value = selectel_mks_cluster_v1.k8s-cluster.id
}
output "user_name" {
value = selectel_vpc_user_v2.my-k8s-user.name
}
output "user_pass" {
value = selectel_vpc_user_v2.my-k8s-user.password
}
Lançamento:
$ env \
TF_VAR_region=ru-3 \
TF_VAR_username=diamon \
TF_VAR_my_selectel_token=<token> \
terraform plan -out planfile
$ terraform apply -input=false -auto-approve planfile

Etapa 3 . Obtemos kubconfig.
Para baixar programaticamente o KUBECONFIG, você precisa obter um token do OpenStack:
openstack token issue -c id -f value > token
E com esse token, faça uma solicitação à API Managed Kubernetes Selectel. k8s_id produz terraform :
curl -XGET -H "x-auth-token: $(cat token)" "https://ru-3.mks.selcloud.ru/v1/clusters/$(cat k8s_id)/kubeconfig" -o kubeConfig.yaml
O Cubconfig também pode ser obtido por meio do painel.

Etapa 4 . Depois que o cluster estiver pronto e tivermos acesso a ele, podemos adicionar yaml por cima ao nosso gosto.
Prefiro acrescentar:
- namespace,
- classe de armazenamento,
- política de segurança do pod e muito mais.
A classe de armazenamento para Selectel pode ser obtida no repositório oficial .
Como inicialmente selecionei um cluster na zona ru-3a , também preciso de uma classe de armazenamento desta zona.
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: fast.ru-3a
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: cinder.csi.openstack.org
parameters:
type: fast.ru-3a
availability: ru-3a
allowVolumeExpansion: true
Etapa 5 . Instalamos um balanceador de carga.
Usaremos o ingresso nginx padrão para muitos . Já existem várias instruções para instalá-lo, então não vamos insistir nisso.
$ helm repo add nginx-stable https://helm.nginx.com/stable
$ helm upgrade nginx-ingress nginx-stable/nginx-ingress -n ingress --install -f ../internal/K8S-cluster/ingress/values.yml
Estamos esperando que ele receba um IP externo por cerca de 3-4 minutos:

IP externo recebido:

Etapa 6 . Instale o GitLab.
$ helm repo add gitlab https://charts.gitlab.io
$ helm upgrade gitlab gitlab/gitlab -n gitlab --install -f gitlab/values.yml --set "global.hosts.domain=gitlab.$EXTERNAL_IP.nip.io"
Estamos novamente esperando que todos os frutos subam.
kubectl get po -n gitlab
NAME READY STATUS RESTARTS AGE
gitlab-gitaly-0 0/1 Pending 0 0s
gitlab-gitlab-exporter-88f6cc8c4-fl52d 0/1 Pending 0 0s
gitlab-gitlab-runner-6b6867c5cf-hd9dp 0/1 Pending 0 0s
gitlab-gitlab-shell-55cb6ccdb-h5g8x 0/1 Init:0/2 0 0s
gitlab-migrations.1-2cg6n 0/1 Pending 0 0s
gitlab-minio-6dd7d96ddb-zd9j6 0/1 Pending 0 0s
gitlab-minio-create-buckets.1-bncdp 0/1 Pending 0 0s
gitlab-postgresql-0 0/2 Pending 0 0s
gitlab-prometheus-server-6cfb57f575-v8k6j 0/2 Pending 0 0s
gitlab-redis-master-0 0/2 Pending 0 0s
gitlab-registry-6bd77b4b8c-pb9v9 0/1 Pending 0 0s
gitlab-registry-6bd77b4b8c-zgb6r 0/1 Init:0/2 0 0s
gitlab-shared-secrets.1-pc7-5jgq4 0/1 Completed 0 20s
gitlab-sidekiq-all-in-1-v1-54dbcf7f5f-qbq67 0/1 Pending 0 0s
gitlab-task-runner-6fd6857db7-9x567 0/1 Pending 0 0s
gitlab-webservice-d9d4fcff8-hp8wl 0/2 Pending 0 0s
Waiting gitlab
./wait_gitlab.sh ../internal/gitlab/gitlab/.pods
waiting for pod...
waiting for pod...
waiting for pod...
Pods subiram:

Etapa 7 . Obtemos o token do GitLab.
Primeiro, descobrimos a senha para inserir:
kubectl get secret -n gitlab gitlab-gitlab-initial-root-password -o jsonpath='{.data.password}' | base64 --decode
Agora, vamos fazer login e obter o token:
python3 get_gitlab_token.py root $GITLAB_PASSWORD http://gitlab.gitlab.$EXTERNAL_IP.nip.io
Etapa 8 . Trazendo repositórios Git para a hierarquia correta usando o Provedor Gitlab.
cd ../internal/gitlab/hierarchy && terraform apply -input=false -auto-approve planfile
Infelizmente, o provedor terraform GitLab tem um bug flutuante . Em seguida, você deve remover os projetos conflitantes manualmente para que o tf.state seja corrigido. Então reinicie o comando `$ make all`
Etapa 9 . Transferimos repositórios locais para o servidor.
$ make push
[master (root-commit) b61d977] Initial commit
3 files changed, 46 insertions(+)
create mode 100644 .gitignore
create mode 100644 values.yml
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 770 bytes | 770.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0)
Feito:


Conclusão
Conseguimos que podemos gerenciar tudo declarativamente em nossa máquina local. Agora quero transferir todas essas tarefas para o CI e apenas pressionar os botões. Para fazer isso, precisamos passar nossos estados locais (estado Terraform) para CI. Como fazer isso na próxima parte.
Assine nosso blog para não perder nenhum artigo novo!