ืชืจื ื’ื•ืœืช ืื• ื”ื‘ื™ืฆื”: ืคื™ืฆื•ืœ IaC

ืชืจื ื’ื•ืœืช ืื• ื”ื‘ื™ืฆื”: ืคื™ืฆื•ืœ IaC
ืžื” ื‘ื ืงื•ื“ื - ื”ืชืจื ื’ื•ืœืช ืื• ื”ื‘ื™ืฆื”? ื”ืชื—ืœื” ื“ื™ ืžื•ื–ืจื” ืœืžืืžืจ ืขืœ Infrastructure-as-Code, ืœื?

ืžื”ื™ ื‘ื™ืฆื”?

ืœืจื•ื‘, Infrastructure-as-Code (IaC) ื”ื™ื ื“ืจืš ื”ืฆื”ืจืชื™ืช ืœื™ื™ืฆื•ื’ ืชืฉืชื™ืช. ื‘ื• ืื ื• ืžืชืืจื™ื ืืช ื”ืžืฆื‘ ืฉืื ื• ืจื•ืฆื™ื ืœื”ืฉื™ื’, ื”ื—ืœ ืžื—ืœืง ื”ื—ื•ืžืจื” ื•ื›ืœื” ื‘ืชืฆื•ืจืช ื”ืชื•ื›ื ื”. ืœื›ืŸ IaC ืžืฉืžืฉ ืขื‘ื•ืจ:

  1. ืžืชืŸ ืžืฉืื‘ื™ื. ืืœื” ื”ื VMs, S3, VPC ื•ื›ื•'. ื›ืœื™ื ื‘ืกื™ืกื™ื™ื ืœืขื‘ื•ื“ื”: Terraform ะธ CloudFormation.
  2. ืชืฆื•ืจืช ืชื•ื›ื ื”. ื›ืœื™ื ื‘ืกื™ืกื™ื™ื: ื‘ืœืชื™ ืืคืฉืจื™,ืฉืฃ ื•ื›ื•'.

ื›ืœ ืงื•ื“ ื ืžืฆื ื‘-git repositories. ื•ื‘ืžื•ืงื“ื ืื• ื‘ืžืื•ื—ืจ ืจืืฉ ื”ืฆื•ื•ืช ื™ื—ืœื™ื˜ ืฉืฆืจื™ืš ืœืขืฉื•ืช ื‘ื”ื ืกื“ืจ. ื•ื”ื•ื ื™ืฉื—ื–ืจ. ื•ื–ื” ื™ืฆื•ืจ ืื™ื–ื” ืžื‘ื ื”. ื•ื”ื•ื ื™ืจืื” ืฉื–ื” ื˜ื•ื‘.

ื˜ื•ื‘ ื’ื ืฉื–ื” ื›ื‘ืจ ืงื™ื™ื GitLab ะธ GitHub-ืกืคืง ืขื‘ื•ืจ Terraform (ื•ื–ื• ืชืฆื•ืจืช ืชื•ื›ื ื”). ื‘ืขื–ืจืชื ืชื•ื›ืœื• ืœื ื”ืœ ืืช ื›ืœ ื”ืคืจื•ื™ืงื˜: ื—ื‘ืจื™ ืฆื•ื•ืช, CI/CD, git-flow ื•ื›ื•'.

ืžืื™ืคื” ื”ื‘ื™ืฆื”?

ืื– ืื ื—ื ื• ืžืชืงืจื‘ื™ื ื‘ื”ื“ืจื’ื” ืœืฉืืœื” ื”ืžืจื›ื–ื™ืช.

ืงื•ื“ื ื›ืœ, ืืชื” ืฆืจื™ืš ืœื”ืชื—ื™ืœ ืขื ืžืื’ืจ ืฉืžืชืืจ ืืช ื”ืžื‘ื ื” ืฉืœ ืžืื’ืจื™ื ืื—ืจื™ื, ื›ื•ืœืœ ืขืฆืžืš. ื•ื›ืžื•ื‘ืŸ, ื›ื—ืœืง ืž-GitOps, ืขืœื™ืš ืœื”ื•ืกื™ืฃ CI ื›ืš ืฉื”ืฉื™ื ื•ื™ื™ื ื™ื‘ื•ืฆืขื• ื‘ืื•ืคืŸ ืื•ื˜ื•ืžื˜ื™.

ืื Git ืขื“ื™ื™ืŸ ืœื ื ื•ืฆืจ?

  1. ืื™ืš ืœืื—ืกืŸ ืื•ืชื• ื‘-Git?
  2. ื›ื™ืฆื“ ืœื”ืชืงื™ืŸ CI?
  3. ืื ื ืคืจื•ืก ื’ื ืืช Gitlab ื‘ืืžืฆืขื•ืช IaC, ื•ืืคื™ืœื• ื‘-Kubernetes?
  4. ื•ื’ื GitLab Runner ื‘-Kubernetes?
  5. ืžื” ืœื’ื‘ื™ Kubernetes ื‘ืกืคืง ื”ืขื ืŸ?

ืžื” ื‘ื ืงื•ื“ื: GitLab ืฉื‘ื• ืื ื™ ืืขืœื” ืืช ื”ืงื•ื“ ืฉืœื™, ืื• ื”ืงื•ื“ ืฉืžืชืืจ ืื™ื–ื” ืกื•ื’ ืฉืœ GitLab ืื ื™ ืฆืจื™ืš?

ืขื•ืฃ ืขื ื‘ื™ืฆื™ื

ยซืื•ื™ืืงื•ื“ื•ืŸ3 ืขื ื“ื™ื ื•ื–ืื•ืจ" [src]

ื‘ื•ืื• ื ื ืกื” ืœื‘ืฉืœ ืžื ื” ื‘ืืžืฆืขื•ืช ื›ืกืคืง ืขื ืŸ ื ื™ื”ืœ ืืช Kubernetes Selectel.

TL; DR

ื”ืื ื ื™ืชืŸ ืœื”ืฆื˜ืจืฃ ืœืฆื•ื•ืช ืื—ื“ ื‘ื‘ืช ืื—ืช?

$ export MY_SELECTEL_TOKEN=<token>
$ curl https://gitlab.com/chicken-or-egg/mks/make/-/snippets/2002106/raw | bash

ืžืฆืจื›ื™ื:

  • ื—ืฉื‘ื•ืŸ ืž-my.selectel.ru;
  • ืืกื™ืžื•ืŸ ื—ืฉื‘ื•ืŸ;
  • ื›ื™ืฉื•ืจื™ Kubernetes;
  • ื›ื™ืฉื•ืจื™ ื”ื’ื”;
  • ืžื™ื•ืžื ื•ื™ื•ืช Terraform;
  • ืชืจืฉื™ื ื”ื’ื” GitLab;
  • ืชืจืฉื™ื ื”ื’ื” GitLab Runner.

ืžืชื›ื•ืŸ:

  1. ืงื‘ืœ ืืช MY_SELECTEL_TOKEN ืžื”ื—ืœื•ื ื™ืช my.selectel.ru.
  2. ืฆื•ืจ ืืฉื›ื•ืœ Kubernetes ืขืœ ื™ื“ื™ ื”ืขื‘ืจืช ืืกื™ืžื•ืŸ ื—ืฉื‘ื•ืŸ ืืœื™ื•.
  3. ืงื‘ืœ KUBECONFIG ืžื”ืืฉื›ื•ืœ ืฉื ื•ืฆืจ.
  4. ื”ืชืงืŸ ืืช GitLab ืขืœ Kubernetes.
  5. ืงื‘ืœ ืืช GitLab-token ืž-GitLab ืฉื ื•ืฆืจ ืขื‘ื•ืจ ื”ืžืฉืชืžืฉ ืฉื•ืจืฉ.
  6. ืฆื•ืจ ืžื‘ื ื” ืคืจื•ื™ืงื˜ ื‘-GitLab ื‘ืืžืฆืขื•ืช GitLab-token.
  7. ื“ื—ื•ืฃ ืืช ื”ืงื•ื“ ื”ืงื™ื™ื ืœ-GitLab.
  8. ???
  9. ืจื•ื•ื—!

ืฉืœื‘ 1. ืืช ื”ืืกื™ืžื•ืŸ ื ื™ืชืŸ ืœื”ืฉื™ื’ ื‘ืžื“ื•ืจ ืžืคืชื—ื•ืช API.

ืชืจื ื’ื•ืœืช ืื• ื”ื‘ื™ืฆื”: ืคื™ืฆื•ืœ IaCืฉืœื‘ 2. ืื ื• ืžื›ื™ื ื™ื ืืช ื”- Terraform ืฉืœื ื• ืœ"ืืคื™ื™ืช" ืืฉื›ื•ืœ ืฉืœ 2 ืฆืžืชื™ื. ืื ืืชื” ื‘ื˜ื•ื— ืฉื™ืฉ ืœืš ืžืกืคื™ืง ืžืฉืื‘ื™ื ืœื›ืœ ื“ื‘ืจ, ืืชื” ื™ื›ื•ืœ ืœื”ืคืขื™ืœ ืžื›ืกื•ืช ืื•ื˜ื•ืžื˜ื™ื•ืช:

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",
 }
}

ื”ื•ืกืฃ ืžืฉืชืžืฉ ืœืคืจื•ื™ืงื˜:

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
}

ื ืชื•ื ื™ ืคืœื˜:

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
}

ื‘ื•ืื• ื ืฉื™ืง:

$ 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

ืชืจื ื’ื•ืœืช ืื• ื”ื‘ื™ืฆื”: ืคื™ืฆื•ืœ IaC
ืฉืœื‘ 3. ืื ื—ื ื• ืžืงื‘ืœื™ื ืืช ื”-cubeconfig.

ื›ื“ื™ ืœื”ื•ืจื™ื“ ืืช KUBECONFIG ื‘ืื•ืคืŸ ืชื•ื›ื ื™ืชื™, ืืชื” ืฆืจื™ืš ืœืงื‘ืœ ืืกื™ืžื•ืŸ ืž-OpenStack:

openstack token issue -c id -f value > token

ื•ืขื ื”ืืกื™ืžื•ืŸ ื”ื–ื” ืฉืœื— ื‘ืงืฉื” ืœ-Managed Kubernetes Selectel API. k8s_id ื ื•ืชืŸ ื”ื—ื•ืฆื” ื˜ืจืคื”:

curl -XGET -H "x-auth-token: $(cat token)" "https://ru-3.mks.selcloud.ru/v1/clusters/$(cat k8s_id)/kubeconfig" -o kubeConfig.yaml

ื ื™ืชืŸ ืœื’ืฉืช ืœ-Cupconfig ื’ื ื“ืจืš ื”ืคืื ืœ.

ืชืจื ื’ื•ืœืช ืื• ื”ื‘ื™ืฆื”: ืคื™ืฆื•ืœ IaC
ืฉืœื‘ 4. ืœืื—ืจ ืฉื”ืืฉื›ื•ืœ ื ืืคื” ื•ื™ืฉ ืœื ื• ื’ื™ืฉื” ืืœื™ื•, ื ื•ื›ืœ ืœื”ื•ืกื™ืฃ ื™ืžืœ ืžืขืœ ืœืคื™ ื”ื˜ืขื.

ืื ื™ ืžืขื“ื™ืฃ ืœื”ื•ืกื™ืฃ:

  • ืžืจื—ื‘ ืฉืžื•ืช,
  • ืžื—ืœืงืช ืื—ืกื•ืŸ
  • ืžื“ื™ื ื™ื•ืช ืื‘ื˜ื—ืช ืชืจืžื™ืœื™ื ื•ื›ืŸ ื”ืœืื”.

ืžื—ืœืงืช ืื—ืกื•ืŸ ืขื‘ื•ืจ Selectel ื ื™ืชืŸ ืœืงื—ืช ืž ืžืื’ืจ ืจืฉืžื™.

ืžืื– ื‘ืชื—ื™ืœื” ื‘ื—ืจืชื™ ืืฉื›ื•ืœ ื‘ืื–ื•ืจ ru-3a, ืื– ืื ื™ ืฆืจื™ืš ืืช ืžื—ืœืงืช ื”ืื—ืกื•ืŸ ืžื”ืื–ื•ืจ ื”ื–ื”.

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

ืฉืœื‘ 5. ื”ืชืงืŸ ืžืื–ืŸ ืขื•ืžืกื™ื.

ืื ื• ื ืฉืชืžืฉ ื‘ืกื˜ื ื“ืจื˜ื™ ืขื‘ื•ืจ ืจื‘ื™ื nginx-ingress. ื™ืฉ ื›ื‘ืจ ื”ืจื‘ื” ื”ื•ืจืื•ืช ืœื”ืชืงื ืชื•, ืื– ืœื ื ืชืขื›ื‘ ืขืœ ื–ื”.

$ 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

ืื ื• ืžื—ื›ื™ื ืฉื”ื•ื ื™ืงื‘ืœ IP ื—ื™ืฆื•ื ื™ ื‘ืžืฉืš ื›-3-4 ื“ืงื•ืช:

ืชืจื ื’ื•ืœืช ืื• ื”ื‘ื™ืฆื”: ืคื™ืฆื•ืœ IaC
IP ื—ื™ืฆื•ื ื™ ืฉื”ืชืงื‘ืœ:

ืชืจื ื’ื•ืœืช ืื• ื”ื‘ื™ืฆื”: ืคื™ืฆื•ืœ IaC
ืฉืœื‘ 6. ื”ืชืงืŸ ืืช 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"

ืฉื•ื‘ ืื ื—ื ื• ืžื—ื›ื™ื ืฉื›ืœ ื”ืชืจืžื™ืœื™ื ื™ืขืœื•.

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

ื”ืชืจืžื™ืœื™ื ืขืœื•:

ืชืจื ื’ื•ืœืช ืื• ื”ื‘ื™ืฆื”: ืคื™ืฆื•ืœ IaC
ืฉืœื‘ 7. ืื ื—ื ื• ืžืงื‘ืœื™ื ืืช GitLab-token.

ืจืืฉื™ืช, ื’ืœื” ืืช ืกื™ืกืžืช ื”ื›ื ื™ืกื”:

kubectl get secret -n gitlab gitlab-gitlab-initial-root-password -o jsonpath='{.data.password}' | base64 --decode

ืขื›ืฉื™ื• ื‘ื•ืื• ื ื™ื›ื ืก ื•ื ืงื‘ืœ ืืกื™ืžื•ืŸ:

python3 get_gitlab_token.py root $GITLAB_PASSWORD http://gitlab.gitlab.$EXTERNAL_IP.nip.io

ืฉืœื‘ 8. ื”ื‘ืืช ืžืื’ืจื™ Git ืœื”ื™ืจืจื›ื™ื” ื”ื ื›ื•ื ื” ื‘ืืžืฆืขื•ืช ืกืคืง Gitlab.

cd ../internal/gitlab/hierarchy && terraform apply -input=false -auto-approve planfile

ืœืจื•ืข ื”ืžื–ืœ, ืœืกืคืง terraform GitLab ื™ืฉ ืฆืฃ ื—ืจืง. ืœืื—ืจ ืžื›ืŸ ืชืฆื˜ืจืš ืœืžื—ื•ืง ืืช ื”ืคืจื•ื™ืงื˜ื™ื ื”ืžืชื ื’ืฉื™ื ื‘ืื•ืคืŸ ื™ื“ื ื™ ืขืœ ืžื ืช ืฉ-tf.state ื™ืชื•ืงืŸ. ืœืื—ืจ ืžื›ืŸ ื”ืคืขืœ ืžื—ื“ืฉ ืืช ื”ืคืงื•ื“ื” `$make all`

ืฉืœื‘ 9. ืื ื• ืžืขื‘ื™ืจื™ื ืžืื’ืจื™ื ืžืงื•ืžื™ื™ื ืœืฉืจืช.

$ 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)

ื‘ื•ืฆืข:

ืชืจื ื’ื•ืœืช ืื• ื”ื‘ื™ืฆื”: ืคื™ืฆื•ืœ IaC
ืชืจื ื’ื•ืœืช ืื• ื”ื‘ื™ืฆื”: ืคื™ืฆื•ืœ IaC
ืชืจื ื’ื•ืœืช ืื• ื”ื‘ื™ืฆื”: ืคื™ืฆื•ืœ IaC

ืžืกืงื ื”

ื”ืฉื’ื ื• ืฉืื ื—ื ื• ื™ื›ื•ืœื™ื ืœื ื”ืœ ื”ื›ืœ ื‘ืฆื•ืจื” ื”ืฆื”ืจืชื™ืช ืžื”ืžื›ื•ื ื” ื”ืžืงื•ืžื™ืช ืฉืœื ื•. ืขื›ืฉื™ื• ืื ื™ ืจื•ืฆื” ืœื”ืขื‘ื™ืจ ืืช ื›ืœ ื”ืžืฉื™ืžื•ืช ื”ืืœื” ืœ-CI ื•ืคืฉื•ื˜ ืœืœื—ื•ืฅ ืขืœ ื›ืคืชื•ืจื™ื. ืœืฉื ื›ืš, ืขืœื™ื ื• ืœื”ืขื‘ื™ืจ ืืช ื”ืžื“ื™ื ื•ืช ื”ืžืงื•ืžื™ื•ืช ืฉืœื ื• (ืžื“ื™ื ืช Terraform) ืœ-CI. ืื™ืš ืœืขืฉื•ืช ื–ืืช ื‘ื—ืœืง ื”ื‘ื.

ื”ื™ืจืฉื ืœืžื ื•ื™ ืฉืœื ื• ื‘ืœื•ื’ื›ื“ื™ ืœื ืœืคืกืคืก ืืช ืคืจืกื•ื ื”ืžืืžืจื™ื ื”ื—ื“ืฉื™ื!

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”