
Qu'est-ce qui est apparu en premier, le poulet ou l'Ćuf ? Un dĂ©but assez Ă©trange pour un article sur l'Infrastructure-as-Code, non ?
Qu'est-ce qu'un Ćuf ?
Le plus souvent, l'Infrastructure-as-Code (IaC) est une méthode déclarative pour représenter l'infrastructure. Nous décrivons l'état que nous voulons atteindre, allant du matériel jusqu'à la configuration logicielle. C'est pourquoi l'IaC est utilisée pour :
- Provisionnement des ressources. Il s'agit de VMs, S3, VPC, etc. Les principaux outils Ă utiliser : et .
- . Les principaux outils : , Chef, etc.
Tout code réside dans des dépÎts git. TÎt ou tard, le chef de l'équipe décidera de faire un peu de rangement dans ces derniers. Il procédera alors à un refactoring et créera une certaine structure. Et il réalisera que c'est une bonne chose.
Il est également bon qu'il existe déjà et -un fournisseur pour Terraform (et c'est la configuration logicielle). Grùce à eux, il est possible de gérer l'ensemble du projet : les membres de l'équipe, CI/CD, git-flow, etc.
D'oĂč vient l'Ćuf ?
Nous commençons à approcher la question principale.
Tout d'abord, il faut commencer par un dĂ©pĂŽt qui dĂ©crit la structure des autres dĂ©pĂŽts, y compris lui-mĂȘme. Bien sĂ»r, dans le cadre de GitOps, il faut ajouter CI pour que les modifications s'exĂ©cutent automatiquement.
Que faire si Git n'est pas encore créé ?
- Comment le conserver dans Git ?
- Comment ajouter CI ?
- Si nous déployons également GitLab à l'aide de IaC, et encore dans Kubernetes ?
- Et le GitLab Runner est-il aussi dans Kubernetes ?
- Et Kubernetes chez un fournisseur de cloud ?
Qu'est-ce qui est apparu en premier : GitLab, sur lequel je vais charger mon code, ou le code décrivant le GitLab dont j'ai besoin ?
Le poulet avec les Ćufs
«3 avec un dinosaure» []
Essayons de préparer un plat, en utilisant comme fournisseur de cloud .
TL;DR
Est-il possible de tout faire en une seule commande ?
$ export MY_SELECTEL_TOKEN=
$ curl https://gitlab.com/chicken-or-egg/mks/make/-/snippets/2002106/raw | bashIngrédients :
- Un compte sur my.selectel.ru ;
- Un token de compte ;
- Compétences Kubernetes ;
- Compétences Helm ;
- Compétences Terraform ;
- Helm chart GitLab ;
- Helm chart GitLab Runner.
Recette :
- Obtenez MY_SELECTEL_TOKEN depuis le tableau de bord my.selectel.ru.
- Créez un cluster Kubernetes en lui fournissant le token de compte.
- Obtenez le KUBECONFIG depuis le cluster créé.
- Installez GitLab dans Kubernetes.
- Obtenez le token GitLab du GitLab créé pour l'utilisateur root.
- Créez la structure des projets dans GitLab en utilisant le token GitLab.
- Poussez le code existant dans GitLab.
- ???
- Profit !
Ătape 1. Le token peut ĂȘtre obtenu dans la section .
Ătape 2. PrĂ©parons notre Terraform pour 'cuire' un cluster de 2 nĆuds. Si vous ĂȘtes sĂ»r d'avoir assez de ressources pour tout, vous pouvez activer l'auto-quotas :
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",
}
}Ajout d'un utilisateur au projet :
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
}Sortie :
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
}Lancement :
$ 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 
Ătape 3. Obtention du kubeconfig.
Pour télécharger le KUBECONFIG par programme, il faut obtenir un jeton d'OpenStack :
openstack token issue -c id -f value > tokenEt avec ce jeton, faire une requĂȘte Ă l'API Kubernetes Managed de Selectel. k8s_id renvoie terraform:
curl -XGET -H "x-auth-token: $(cat token)" "https://ru-3.mks.selcloud.ru/v1/clusters/$(cat k8s_id)/kubeconfig" -o kubeConfig.yamlLe kubeconfig peut aussi ĂȘtre obtenu via le panneau.

Ătape 4. Une fois que le cluster est dĂ©ployĂ© et que nous avons accĂšs, nous pouvons ajouter ci-dessus du yaml selon nos prĂ©fĂ©rences.
Je préfÚre ajouter :
- namespace,
- classe de stockage,
- politique de sécurité des pods, etc.
pour Selectel on peut prendre du .
Puisque j'ai initialement choisi un cluster dans la zone ru-3a, la classe de stockage dont j'ai besoin doit également provenir de cette zone.
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Ătape 5. Nous mettons en place un rĂ©partiteur de charge.
Nous allons utiliser le standard pour beaucoup de nginx-ingress. Il existe déjà de nombreuses instructions pour son installation, donc nous ne nous attarderons pas là -dessus.
$ 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.ymlAttendez qu'il obtienne une IP externe pendant environ 3-4 minutes :

Nous avons obtenu une IP externe :

Ătape 6. Nous installons 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"Nous attendons Ă nouveau que tous les pods se lĂšvent.
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
En attendant gitlab
./wait_gitlab.sh ../internal/gitlab/gitlab/.pods
attente du pod...
attente du pod...
attente du pod...Les pods sont en cours d'élévation :

Ătape 7. Nous obtenons le jeton GitLab.
D'abord, découvrons le mot de passe de connexion :
kubectl get secret -n gitlab gitlab-gitlab-initial-root-password -o jsonpath='{.data.password}' | base64 --decodeMaintenant, nous nous authentifions et obtenons le jeton :
python3 get_gitlab_token.py root $GITLAB_PASSWORD http://gitlab.gitlab.$EXTERNAL_IP.nip.ioĂtape 8. Mettons les dĂ©pĂŽts Git dans la bonne hiĂ©rarchie avec le fournisseur Gitlab.
cd ../internal/gitlab/hierarchy && terraform apply -input=false -auto-approve planfileMalheureusement, dans le fournisseur GitLab de terraform, il y a un flottement . Dans ce cas, il faudra supprimer manuellement les projets en conflit pour que tf.state soit réparé. Ensuite, redémarrez la commande `$ make all`
Ătape 9. TransfĂ©rons les dĂ©pĂŽts locaux sur le serveur.
$ make push
[master (root-commit) b61d977] Commit initial
3 fichiers modifiés, 46 insertions(+)
mode de création 100644 .gitignore
mode de création 100644 values.yml
ĂnumĂ©ration des objets : 5, fait.
Comptage des objets : 100% (5/5), fait.
Compression de delta utilisant jusqu'Ă 8 threads
Compression des objets : 100% (5/5), fait.
Ăcriture des objets : 100% (5/5), 770 octets | 770.00 KiB/s, fait.
Total 5 (delta 0), réutilisé 0 (delta 0)Fait :


Conclusion
Nous avons réussi à gérer tout de maniÚre déclarative depuis notre machine locale. Maintenant, nous voulons transférer toutes ces tùches dans le CI et simplement appuyer sur des boutons. Pour cela, nous devons transmettre nos états locaux (Terraform state) au CI. Sur la façon de procéder, dans la prochaine partie.
Abonnez-vous Ă notre , pour ne pas manquer la sortie de nouveaux articles !
Source : habr.com
