Poulet ou Ɠuf : dĂ©chiffrons l'IaC

Poulet ou Ɠuf : dĂ©chiffrons l'IaC
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 :

  1. Provisionnement des ressources. Il s'agit de VMs, S3, VPC, etc. Les principaux outils Ă  utiliser : Terraform et CloudFormation.
  2. Configuration logicielle. Les principaux outils : Ansible, 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à GitLab et GitHub-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éé ?

  1. Comment le conserver dans Git ?
  2. Comment ajouter CI ?
  3. Si nous déployons également GitLab à l'aide de IaC, et encore dans Kubernetes ?
  4. Et le GitLab Runner est-il aussi dans Kubernetes ?
  5. 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

«Oyakodon3 avec un dinosaure» [src]

Essayons de préparer un plat, en utilisant comme fournisseur de cloud Managed Kubernetes Selectel.

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 | bash

Ingré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 :

  1. Obtenez MY_SELECTEL_TOKEN depuis le tableau de bord my.selectel.ru.
  2. Créez un cluster Kubernetes en lui fournissant le token de compte.
  3. Obtenez le KUBECONFIG depuis le cluster créé.
  4. Installez GitLab dans Kubernetes.
  5. Obtenez le token GitLab du GitLab créé pour l'utilisateur root.
  6. Créez la structure des projets dans GitLab en utilisant le token GitLab.
  7. Poussez le code existant dans GitLab.
  8. ???
  9. Profit !

Étape 1. Le token peut ĂȘtre obtenu dans la section ClĂ©s API.

Poulet ou Ɠuf : dĂ©chiffrons l'IaCÉ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

Poulet ou Ɠuf : dĂ©chiffrons l'IaC
É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 > token

Et 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.yaml

Le kubeconfig peut aussi ĂȘtre obtenu via le panneau.

Poulet ou Ɠuf : dĂ©chiffrons l'IaC
É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.

Classe de Stockage pour Selectel on peut prendre du dépÎt officiel.

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.yml

Attendez qu'il obtienne une IP externe pendant environ 3-4 minutes :

Poulet ou Ɠuf : dĂ©chiffrons l'IaC
Nous avons obtenu une IP externe :

Poulet ou Ɠuf : dĂ©chiffrons l'IaC
É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 :

Poulet ou Ɠuf : dĂ©chiffrons l'IaC
É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 --decode

Maintenant, 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 planfile

Malheureusement, dans le fournisseur GitLab de terraform, il y a un flottement bug. 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 :

Poulet ou Ɠuf : dĂ©chiffrons l'IaC
Poulet ou Ɠuf : dĂ©chiffrons l'IaC
Poulet ou Ɠuf : dĂ©chiffrons l'IaC

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 blog, pour ne pas manquer la sortie de nouveaux articles !

Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster