
Ce a apărut mai întâi — găina sau oul? O început destul de ciudat pentru un articol despre Infrastructure-as-Code, nu-i așa?
Ce este un ou?
Cel mai frecvent, Infrastructure-as-Code (IaC) este un mod declarativ de a reprezenta infrastructura. Aici descriem starea pe care dorim să o obținem, începând de la hardware și terminând cu configurația software-ului. Prin urmare, IaC este folosit pentru:
- Furnizarea de resurse. Acestea includ VMs, S3, VPC etc. Principalele instrumente utilizate sunt: și .
- . Principalele instrumente: , Chef etc.
Oricum, orice cod se află în repozitorii git. Și mai devreme sau mai târziu, liderul de echipă va decide că trebuie să facă ordine în ele. Și va face refactoring. Și va crea o anumită structură. Și va observa că este bine.
De asemenea, este bine că deja există și -un provider pentru Terraform (și aceasta este Configurarea software-ului). Cu ajutorul lor, putem gestiona întregul proiect: membri ai echipei, CI/CD, git-flow etc.
De unde a apărut oul?
Iată că ne apropiem treptat de întrebarea principală.
În primul rând, trebuie să începem cu repozitoriul care descrie structura altor repozitorii, inclusiv pe sine. Și, bineînțeles, în cadrul GitOps, trebuie să adăugăm CI pentru ca modificările să fie executate automat.
Dacă Git încă nu a fost creat?
- Cum îl stocăm în Git?
- Cum integrăm CI?
- Dacă desfășurăm și GitLab cu ajutorul IaC, și în plus, în Kubernetes?
- Și GitLab Runner în Kubernetes?
- Și Kubernetes într-un provider cloud?
Ce a apărut mai întâi: GitLab, în care voi încărca codul meu, sau codul care descrie cum trebuie să fie GitLab-ul meu?
O găină cu ouă
«3 cu un dinozaur» []
Să încercăm să preparăm un fel de mâncare, folosind drept provider cloud .
TL;DR
Se poate să fie toate într-o singură comandă?
$ export MY_SELECTEL_TOKEN=
$ curl https://gitlab.com/chicken-or-egg/mks/make/-/snippets/2002106/raw | bashIngrediente:
- Un cont de la my.selectel.ru;
- Tokenul de la cont;
- Abilități în Kubernetes;
- Abilități în Helm;
- Abilități în Terraform;
- Chart Helm pentru GitLab;
- Chart Helm pentru GitLab Runner.
Rețetă:
- Obțineți MY_SELECTEL_TOKEN din panou my.selectel.ru.
- Creează un cluster Kubernetes, trecând tokenul de la cont.
- Obțineți KUBECONFIG de la clusterul creat.
- Instalați GitLab în Kubernetes.
- Obțineți GitLab-token de la GitLab creat pentru utilizator root.
- Creează structura proiectelor în GitLab, folosind GitLab-token.
- Împingeți codul existent în GitLab.
- ???
- Profit!
Pasul 1. Tokenul poate fi obținut în secțiunea .
Pasul 2. Ne pregătim Terraform-ul pentru „coacerea” cluster-ului din 2 noduri. Dacă sunteți sigur că aveți suficiente resurse pentru toată lumea, atunci puteți activa auto-limitările:
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",
}
}Adăugăm utilizatorul în proiect:
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
}Ieșire:
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
}Întâi deschidem:
$ env
TF_VAR_region=ru-3
TF_VAR_username=diamon
TF_VAR_my_selectel_token=
terraform plan -out planfile
$ terraform apply -input=false -auto-approve planfile 
Pasul 3. Obținem kubecfg.
Pentru a descărca programatic KUBECONFIG, trebuie să obținem un token de la OpenStack:
openstack token issue -c id -f value > tokenȘi deja cu acest token să facem o cerere către API-ul Managed Kubernetes Selectel. k8s_id returnează terraform:
curl -XGET -H "x-auth-token: $(cat token)" "https://ru-3.mks.selcloud.ru/v1/clusters/$(cat k8s_id)/kubeconfig" -o kubeConfig.yamlKUBECONFIG poate fi obținut și prin panou.

Pasul 4. După ce clusterul s-a creat și avem acces la el, putem adăuga yaml după bunul plac.
Prefer să adaug:
- namespace,
- clasa de stocare,
- politica de securitate a podurilor și altele.
pentru Selectel se poate lua din .
Deoarece inițial am ales clusterul în zona ru-3a, atunci și Clasa de Stocare îmi trebuie din această zonă.
tip: 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: truePasul 5. Instalăm un balancer de încărcare.
Vom folosi standardul pentru mulți nginx-ingress. Există deja destule instrucțiuni pentru instalarea sa, așa că nu ne vom opri asupra acestui lucru.
$ 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.ymlAșteptăm să obținem IP-ul extern în aproximativ 3-4 minute:

Am obținut IP-ul extern:

Pasul 6. Instalăm 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"Așteptăm din nou ca toate podurile să se ridice.
kubectl get po -n gitlab
NUME 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
Așteptând gitlab
./wait_gitlab.sh ../internal/gitlab/gitlab/.pods
așteptând pod...
așteptând pod...
așteptând pod...Podurile s-au ridicat:

Pasul 7. Obținem GitLab-token.
Mai întâi aflăm parola de acces:
kubectl get secret -n gitlab gitlab-gitlab-initial-root-password -o jsonpath='{.data.password}' | base64 --decodeAcum ne autentificăm și obținem token-ul:
python3 get_gitlab_token.py root $GITLAB_PASSWORD http://gitlab.gitlab.$EXTERNAL_IP.nip.ioPasul 8. Organizăm repo-urile Git în ierarhia corectă cu ajutorul Gitlab Provider.
cd ../internal/gitlab/hierarchy && terraform apply -input=false -auto-approve planfileDin păcate, în providerul GitLab din terraform există un conflict . Apoi va trebui să ștergem manual proiectele în conflict pentru a repara tf.state. Apoi reporniți comanda `$ make all`
Pasul 9. Transferăm repo-urile locale pe server.
$ make push
[master (root-commit) b61d977] Commit inițial
3 fișiere modificate, 46 inserții(+)
create mode 100644 .gitignore
create mode 100644 values.yml
Enumerarea obiectelor: 5, finalizată.
Contorizarea obiectelor: 100% (5/5), finalizată.
Compresia delta folosind până la 8 thread-uri
Compresând obiecte: 100% (5/5), finalizată.
Scrierea obiectelor: 100% (5/5), 770 bytes | 770.00 KiB/s, finalizată.
Total 5 (delta 0), reutilizate 0 (delta 0)Gata:


Concluzie
Am reușit să gestionăm declarativ totul de pe mașina noastră locală. Acum vrem să transferăm toate aceste sarcini în CI și să apăsăm doar butoanele. Pentru aceasta, trebuie să transmitem starea noastră locală (Terraform state) în CI. Despre cum se face acest lucru, în partea următoare.
Abonați-vă la canalul nostru , pentru a nu rata publicațiile de articole noi!
Sursa: habr.com
