鶏肉または卵:IaCの分割



鶏と卵のどちらが先に来ましたか?Infrastructure-as-Codeに関する記事の非常に奇妙なスタートですね。



卵とは何ですか?



ほとんどの場合、Infrastructure-as-Code(IaC)は、インフラストラクチャを表す宣言的な方法です。その中で、鉄の部分から始まり、ソフトウェア構成で終わる、取得したい状態について説明します。したがって、IaCは次の目的で使用されます。



  1. リソースの提供。これらはVM、S3、VPCなどです。作業用の基本ツール:TerraformおよびCloudFormation
  2. ソフトウェア構成基本的なツール: Ansible、Chefなど。


すべてのコードはgitリポジトリにあります。そして遅かれ早かれ、チームリーダーは物事を整理する必要があると判断するでしょう。そしてそれはリファクタリングします。そして、いくつかの構造を作成します。そして彼はそれが良いことを見るでしょう。Terraform用のGitLabおよびGitHubプロバイダー



がすでに存在することも良いことです(そしてそれはソフトウェア構成です)。彼らの助けを借りて、チームメンバー、CI / CD、git-flowなどのプロジェクト全体を管理できます。



卵はどこから来たのですか?



それで、私たちは徐々に主要な質問に行き着きます。



まず、自分自身を含む他のリポジトリの構造を説明するリポジトリから始める必要があります。そしてもちろん、GitOps内で、変更が自動的に実行されるようにCIを追加する必要があります。



Gitがまだ構築されていない場合は?



  1. Gitに保存するにはどうすればよいですか?
  2. CIをねじ込む方法は?
  3. IaCを使用してGitlabを展開した場合、さらにはKubernetesでも展開した場合はどうでしょうか。
  4. そして、GitLab RunnerもKubernetesにいますか?
  5. クラウドプロバイダーのKubernetesはどうですか?


どちらが最初に来ましたか:コードをアップロードするGitLab、または必要なGitLabの種類を説明するコード?


卵入りチキン



おやこどん3恐竜»[ src ]



Managed KubernetesSelectelを クラウドプロバイダーとして使用して料理を作ってみましょう



TL; DR



すぐに1つのチームで行うことは可能ですか?



$ 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ランナー。


レシピ:



  1. my.selectel.ruパネルからMY_SELECTEL_TOKENを取得します。
  2. アカウントからトークンにトークンを転送して、Kubernetesクラスターを作成します。
  3. 作成したクラスターからKUBECONFIGを取得します。
  4. KubernetesにGitLabをインストールします。
  5. ルートユーザー用に生成されたGitLabからGitLabトークンを取得します
  6. GitLabトークンを使用してGitLabでプロジェクト構造を作成します。
  7. 既存のコードをGitLabにプッシュします。
  8. ???
  9. 利益!


ステップ1トークンは、APIキーセクションで取得できます



ステップ22ノードのクラスターをベイクするためにTerraformを準備します。すべてに十分なリソースがあることが確実な場合は、自動クォータを有効にできます。



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




ステップ3kubconfigを取得します。



プログラムでKUB​​ECONFIGをダウンロードするには、OpenStackからトークンを取得する必要があります。



openstack token issue -c id -f value > token


そして、このトークンを使用して、Managed Kubernetes SelectelAPIにリクエストを送信します。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


Cubconfigは、パネルからも取得できます。





ステップ4クラスターがベイクされ、それにアクセスできるようになったら、好みに合わせてyamlを追加できます。



私は追加することを好みます:



  • 名前名、
  • ストレージクラス、
  • ポッドセキュリティポリシーなど。


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分間待っています。





受信した外部IP:





ステップ6GitLabをインストールします。



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


ポッドが上がった:





ステップ7GitLabトークンを取得します。



まず、入力用のパスワードを見つけます。



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


ステップ8Gitlabプロバイダーを使用して、Gitリポジトリを正しい階層に移動します。



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


残念ながら、terraformGitLabプロバイダーにはフローティングバグがあります。次に、tf.stateを修復するには、競合するプロジェクトを手動で削除する必要があります。次に、コマンド `$ makeall`を再起動します


ステップ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)


完了:











結論



ローカルマシンからすべてを宣言的に管理できることを達成しました。ここで、これらすべてのタスクをCIに転送し、ボタンを押すだけにします。これを行うには、ローカル状態(Terraform状態)をCIに渡す必要があります。次のパートでこれを行う方法。



新しい記事を見逃さないように私たちのブログを購読してください



All Articles