
Was war zuerst da - ein Huhn oder ein Ei? Ein ziemlich seltsamer Anfang für einen Artikel über Infrastruktur als Code, nicht wahr?
Was ist ein Ei?
In den meisten Fällen ist Infrastructure-as-Code (IaC) eine deklarative Darstellung der Infrastruktur. Darin beschreiben wir den Zustand, den wir erhalten möchten, beginnend mit dem Eisenteil, der mit der Softwarekonfiguration endet. Daher wird IaC verwendet, um:
- Ressourcenbereitstellung. Dies sind VMs, S3, VPCs usw. Grundlegende Werkzeuge für die Arbeit: Terraform und CloudFormation .
- Softwarekonfiguration . Grundlegende Werkzeuge: Ansible , Chef, etc.
Jeder Code befindet sich in Git-Repositorys. Und früher oder später wird der Teamleiter entscheiden, dass es notwendig wäre, die Dinge in Ordnung zu bringen. Und es wird umgestalten. Und es wird eine Struktur schaffen. Und er wird sehen, dass es gut ist.
Es ist auch gut, dass GitLab und GitHub bereits für Terraform existieren (und das ist Softwarekonfiguration). Mit ihrer Hilfe können Sie das gesamte Projekt verwalten: Teammitglieder, CI / CD, Git-Flow usw.
Woher kam das Ei?
So kommen wir allmählich zur Hauptfrage.
Zunächst müssen Sie mit einem Repository beginnen, das die Struktur anderer Repositorys, einschließlich Ihrer selbst, beschreibt. Und natürlich müssen Sie in GitOps ein CI hinzufügen, damit die Änderungen automatisch ausgeführt werden.
Wenn Git noch nicht gebaut wurde?
- Wie speichere ich es in Git?
- Wie CI anschrauben?
- Wenn wir Gitlab auch über IaC und sogar in Kubernetes bereitstellen?
- Und GitLab Runner ist auch auf Kubernetes?
- Was ist mit Kubernetes in einem Cloud-Anbieter?
Was war zuerst da: GitLab, wo ich meinen Code hochladen werde, oder Code, der beschreibt, welches GitLab ich brauche?
Huhn mit Eiern
" Oyakodon 3 Dinosaurier» [ src ]
Versuchen wir, ein Gericht mit Managed Kubernetes Selectel als Cloud-Anbieter zuzubereiten .
TL; DR
Ist es möglich, sofort und in einem Team?
$ export MY_SELECTEL_TOKEN=<token>
$ curl https://gitlab.com/chicken-or-egg/mks/make/-/snippets/2002106/raw | bash
Zutaten:
- Konto von my.selectel.ru;
- Token vom Konto;
- Kubernetes Fähigkeiten;
- Helmfähigkeiten;
- Terraform-Fähigkeiten;
- Helmkarte GitLab;
- Helmkarte GitLab Runner.
Rezept:
- Rufen Sie MY_SELECTEL_TOKEN aus dem my.selectel.ru-Bereich ab .
- Erstellen Sie einen Kubernetes-Cluster, indem Sie das Token vom Konto auf das Konto übertragen.
- Holen Sie sich KUBECONFIG aus dem erstellten Cluster.
- Installieren Sie GitLab auf Kubernetes.
- Holen Sie sich das GitLab-Token aus dem generierten GitLab für den Root-Benutzer .
- Erstellen Sie eine Projektstruktur in GitLab mit GitLab-Token.
- Schieben Sie vorhandenen Code in GitLab.
- ???
- Profitieren!
Schritt 1 . Das Token erhalten Sie im Abschnitt API-Schlüssel .

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",
}
}
Fügen Sie dem Projekt einen Benutzer hinzu:
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
}
Ausgabe:
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
}
Starten:
$ 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

Schritt 3 . Wir bekommen Cubconfig.
Um KUBECONFIG programmgesteuert herunterzuladen, benötigen Sie ein Token von OpenStack:
openstack token issue -c id -f value > token
Stellen Sie mit diesem Token eine Anfrage an die Managed Kubernetes Selectel-API. k8s_id erzeugt Terraform :
curl -XGET -H "x-auth-token: $(cat token)" "https://ru-3.mks.selcloud.ru/v1/clusters/$(cat k8s_id)/kubeconfig" -o kubeConfig.yaml
Cubconfig kann auch über das Panel abgerufen werden.

Schritt 4 . Nachdem der Cluster gebacken ist und wir Zugriff darauf haben, können wir nach Belieben Yaml hinzufügen.
Ich füge lieber hinzu:
- Namespace,
- Speicherklasse,
- Pod-Sicherheitsrichtlinien und mehr.
Die Speicherklasse für Selectel kann aus dem offiziellen Repository entnommen werden .
Da ich ursprünglich einen Cluster in der Zone ru-3a ausgewählt habe , benötige ich auch eine Speicherklasse aus dieser 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
Schritt 5 . Wir installieren einen Load Balancer.
Wir werden für viele den Standard- Nginx-Ingress verwenden . Es gibt bereits viele Anweisungen für die Installation. Lassen Sie uns also nicht näher darauf eingehen.
$ 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
Wir warten ca. 3-4 Minuten darauf, dass es eine externe IP erhält:

Externe IP erhalten:

Schritt 6 . Installieren Sie 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"
Wir warten wieder darauf, dass alle Schoten steigen.
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 gingen hoch:

Schritt 7 . Wir bekommen das GitLab-Token.
Zuerst ermitteln wir das einzugebende Passwort:
kubectl get secret -n gitlab gitlab-gitlab-initial-root-password -o jsonpath='{.data.password}' | base64 --decode
Jetzt melden wir uns an und holen uns das Token:
python3 get_gitlab_token.py root $GITLAB_PASSWORD http://gitlab.gitlab.$EXTERNAL_IP.nip.io
Schritt 8 . Bringen Sie Git-Repositorys mithilfe des Gitlab-Anbieters in die richtige Hierarchie.
cd ../internal/gitlab/hierarchy && terraform apply -input=false -auto-approve planfile
Leider gibt es einen schwebenden Fehler im Terraform-GitLab-Anbieter . Dann müssen Sie widersprüchliche Projekte von Hand entfernen, damit tf.state behoben werden kann. Starten Sie dann den Befehl `$ make all` neu
Schritt 9 . Wir übertragen lokale Repositorys auf den Server.
$ 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)
Erledigt:


Fazit
Wir haben erreicht, dass wir alles deklarativ von unserem lokalen Computer aus verwalten können. Jetzt möchte ich alle diese Aufgaben auf CI übertragen und nur noch Tasten drücken. Dazu müssen wir unsere lokalen Bundesstaaten (Terraform-Status) an CI übergeben. Wie das geht im nächsten Teil.
Abonnieren Sie unseren Blog , um keine neuen Artikel zu verpassen!