minecraftサーバの実装を自動化しちゃいたい♡
Introduction - 自動化をしちゃいたい
お疲れ様です。皆様、最近のバズワード「自動化」をご存知でしょうか?
まぁ、自動化と言っても自分は特にIaC(Infrastructure as Code)というものに興味津々でございます。これでもインフラエンジニアの端くれらしいので...
で、話は少し逸れて先週ふと...「マイクラしてぇぇぇ(ゲスボイス)」と思い立ったのです。
マイクラを普通にインストールして遊ぶのもすごく楽しいですが、せっかくだしAWS上にインスタンスを用意して、マイクラサーバをデプロイして、みんなで遊んじゃいたいということです。
今回は、それをインフラ周りの構築からマイクラサーバのデプロイ、起動までを自動化してみたら勉強にもなるかしらと思い、キーボードを叩くことにしました。
まぁ、自動化ツールは自分の野望にも必要になってくるものではあるので、少しずつ慣れていければと思います。(まぁ、自動化ツールはあくまでツールであって、「構築・運用における銀の弾丸になりうる」とまでは思っていないというのが私の考えではありますが...)
環境のご説明
前置きが長くなりましたね...
環境のご説明をいたします。
- 環境
コードのご紹介
書いたものについて
書いたコードはここに置いておきます。
利用方法とかは、ちゃんと README書くので許して...
で、今回は主に初めて利用するAnsibleのコードについてご紹介していきたいと思います。
Ansibleについては、Google先生に聞くか、某大佐の本を購入するか、モクモクの会に出てみるか、調べる方法はいくらでもあるので、割愛。
少し言うなら、エンジニアの皆さんがここ数年、生暖かい目線を送って盛り上げてる自動化ツールかなというのが自分の中での印象です。
んで、最初にファイルのツリーをご開帳。
- ファイルのツリー
. ├── build_infra.yml ├── build_minecraft.yml ├── inventory │ ├── aws_ec2.yml │ └── inventory_file ├── key │ └── mykey.pem └── roles ├── make_games │ ├── files │ │ └── eula.txt │ └── tasks │ └── main.yml └── make_infra ├── infra_destroy.yml ├── tasks │ └── main.yml └── terraform ├── environment │ ├── instance │ │ ├── aws_ec2.tf │ │ ├── output.tf │ │ └── variables.tf │ ├── main.tf │ ├── network │ │ ├── aws_securitygroup.tf │ │ ├── aws_vpc.tf │ │ ├── output.tf │ │ └── variables.tf │ └── variables.tf ├── main.tf ├── terraform.tfstate ├── terraform.tfstate.backup ├── terraform.tfvars └── variables.tf
リソースの展開について
Ansibleについて文章書きたいって言ってるのに、半分以上がTerrforomなのは... ?
とまぁ、Terraformのご説明を簡単にすると、インフラストラクチャプロバイダなどのリソース設定をコード化できてしまうというものです。
今回は、わざと混合状態で挑むこととしました。(AWSのリソース設定をAnsibleでイチから書くのがめんどくさかったというのは内緒♡)
Terraformは主に、AWSの各リソースのデプロイに利用しています。
ここで、デプロイの準備を解説させていただくと、EC2とVPCの設定を各ディレクトリに配置しております。
実行する上で、./roles/make_infra/terraform/terraform.tfvars
にAWSで取得したIAMユーザのアクセスキーとシークレットキーを入力してください。記入後、下記コマンドを実行。
#編集してください。"./roles/make_infra/terraform/terraform.tfvars" /*provider-settings*/ aws_access_key = "XXXXXXXXXXXXXXXXXXXX" aws_secret_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
#Terraformの初期化
terraform init
これで、Terraform側が必要な情報を取得してくれます。
./roles/make_infra/terraform/
下にterraform.tfstate
やterraform.tfstate.backup
、.terraform/
が生成されるかと思います。
Terraform側はこれでOK
一応、以下のようなリソースを展開する準備ができています。
ネットワークのアドレスやインスタンスのタイプに関しては、./roles/make_infra/terraform/environment/variables.tf
で設定できます。(※プロジェクトネームはいろいろ連動しているので、変えないのが良きかも)
下に、プライベートサブネットができるのは過去に作ったものの流用なので、見逃してください...
#./roles/make_infra/terraform/environment/variables.tf /*aws-name-settings*/ variable "project-name" { default = "minecraft" } /*aws-network-settings*/ variable "vpc-cidr" { default = "192.168.32.0/24" } variable "az" { default = ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"] } variable "public-subnets" { default = ["192.168.32.0/25"] } variable "private-subnets" { default = ["192.168.32.128/25"] } /*aws-instance-settings*/ variable "ec2-config" { type = map(string) default = { ami = "ami-0ff21806645c5e492" instance_type = "t2.small" instance_key = "mykey" root_ebs_type = "gp2" root_ebs_size = "8" } }
Ansibleの利用
今回、Ansibleはroles
という機能を利用していきたいと思います。
roles
とは、
ロールは、既知のファイル構造に基づいて特定の vars_files、タスク、およびハンドラーを自動的に読み込む方法です。 ロールでコンテンツをグループ化すると、他のユーザーとのロールの共有が容易になります。
参考:ロール - Ansible Documentation
と、言う感じで、つらつらPlaybookを書くよりも、より可読性や共有性をアップできるということですね。
上から、./build_infra.yml
や./build_minecraft.yml
は各ロール内のtasks
のymlファイルを実行しています。
./build_infra.yml
は上のTerraformタスクを実行していて、./build_minecraft.yml
は展開されたインスタンスに対してminecraftの実装をしています。また、ここのversion
変数でminecraftのバージョンを指定できます。
#./build_infra.yml --- - name: build infra hosts: localhost become: false roles: - make_infra
#./build_minecraft.yml --- - name: build minecraft hosts: target become: yes vars: version: "1.12.2" password: passw0rd roles: - make_games
次にinventory
ディレクトリにある、./inventory/aws_ec2.yml
は展開されたEC2インスタンスの情報を引っ張ってきてくれています。
ここで、./inventory/aws_ec2.yml
のaws_access_key_id
とaws_secret_access_key
は、先程Terraformにも記入したアクセスキー、シークレットキーと同じテナントに紐付いているものとなります。(同じもので良いですよ)
./inventory/inventory_file
はインスタンスと22番接続する際に必要な情報が入ってます。
./inventory/inventory_file
内のansible_ssh_private_key_file
は接続に必要なキーペア
の名前を記入の上、ファイルを./key/
ディレクトリ下に保存してください。
#./inventory/aws_ec2.yml plugin: aws_ec2 aws_access_key_id: XXXXXXXXXXXXXXXXXXXX aws_secret_access_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx aws_security_token: regions: - ap-northeast-1 strict: no keyed_groups: - key: tags.Name prefix: tag_Name_ separator: "" groups: target: "tags.Name is match('^minecraft-')" compose: ansible_host: global_ip_address
#./inventory/inventory_file [target:vars] ansible_port=22 ansible_user=ec2-user ansible_ssh_private_key_file=key/mykey.pem
一応ここまでで実行はできちゃいますが、もう少しだけ続くんじゃ...
ここでは、各タスクについてご説明します。
./roles/make_infra/tasks/main.yml
は単純にTerraformを実行しています。正直、$ terraform apply
となんら変わりません。ただ、今回はAnsibleからTerraformを実行してみたいという試みなのです。
実際、TerraformからAnsibleを動かすか、AnsibleからTerraformを動かすかは状況に応じて異なるかと思います。
仮に、今回の件が業務に関わるなら、まずAnsibleで要件のOS、必要なパッケージを携えたイメージをローカル環境で作成して、それをAWS 上にAMIとしてアップロードする。(ここまで、自動化)
その後そのAMIを利用してTerraformを実行する。
という手法を取るかと思います。(これも臨機応変)
で、その下に120秒の待機があるのは、単純にインスタンスの起動を「ちょっと待ってー」という意味です。
# ./roles/make_infra/tasks/main.yml - name: make infra terraform terraform: project_path: 'roles/make_infra/terraform' state: present - name: pause pause: seconds: 120 register: result - name: show result debug: var: result
次に、minecraftサーバの実装です。
ファイルは、./roles/make_games/tasks/main.yml
になります。
しかし...まぁ...
ここが一番書くことがないですね...
ちなみに、ローカルからコピーしてきている、eula.txt
というファイルとは、マイクラサーバを起動する際に、「承諾する」という意味のファイルになります。(ファイルは承諾済み)
なので、これを実行したとき、すでに「承諾している」ということですね♡(ゲス顔)
ついでに、マイクラサーバのjarファイルをダウロードしてきているS3には最新版はなかったのであしからず...
# ./roles/make_games/tasks/main.yml - name: install java yum: name=java state=installed - name: install screen yum: name=screen state=installed - name: add a minecraft user user: name=minecraft password={{password}} state=present - name: settings sudo user minecraft lineinfile: "dest=/etc/sudoers backup=yes state=present regexp='^minecraft' line='minecraft ALL=(ALL) NOPASSWD: ALL'" - name: make minecraft directory file: path=/opt/minecraft state=directory owner=minecraft group=minecraft mode=0755 - name: get minecraft get_url: url="https://s3.amazonaws.com/Minecraft.Download/versions/{{version}}/minecraft_server.{{version}}.jar" dest=/opt/minecraft - name: create symbolic link file: src=/opt/minecraft/minecraft_server.{{version}}.jar dest=/opt/minecraft/server.jar state=link - name: copy eula.txt copy: src=eula.txt dest=/opt/minecraft/eula.txt - name: start minecraft shell: /usr/bin/java -Xmx1024M -Xms1024M -jar /opt/minecraft/server.jar nogui & args: chdir: /opt/minecraft/ async: 5 poll: 0
参考というか、ほぼほぼパクリ
実行
実行しちゃう
以上のように実装したコードを実行していきます。
基本的には、プロジェクトのルートディレクトリで実行。
# ./ で実行 ./ $ ansible-playbook build_infra.yml [WARNING]: No inventory was parsed, only implicit localhost is available [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' PLAY [build infra] ******************************************************************************************************************************************************************************************************************************************************************* TASK [Gathering Facts] *************************************************************************************************************************************************************************************************************************************************************** ok: [localhost] TASK [make_infra : make infra terraform] ********************************************************************************************************************************************************************************************************************************************* changed: [localhost] TASK [make_infra : pause] ************************************************************************************************************************************************************************************************************************************************************ Pausing for 120 seconds (ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort) ok: [localhost] TASK [make_infra : show result] ****************************************************************************************************************************************************************************************************************************************************** ok: [localhost] => { "result": { "changed": false, "delta": 120, "echo": true, "failed": false, "rc": 0, "start": "2020-09-12 03:54:11.657614", "stderr": "", "stdout": "Paused for 120.0 seconds", "stop": "2020-09-12 03:56:11.657858", "user_input": "" } } PLAY RECAP *************************************************************************************************************************************************************************************************************************************************************************** localhost : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
一応、インスタンスの確認。
./ $ ansible-inventory -i inventory --graph @all: |--@aws_ec2: | |--ec2-xx-xx-xx-xx9.ap-northeast-1.compute.amazonaws.com |--@tag_Name_minecraft_public_ap_northeast_1a: | |--ec2-xx-xx-xx-xx9.ap-northeast-1.compute.amazonaws.com |--@target: | |--ec2-xx-xx-xx-xx9.ap-northeast-1.compute.amazonaws.com |--@ungrouped:
インスタンスいますね。
最後に、マイクラサーバのサービス起動まで!
./ $ ansible-playbook -i inventory build_minecraft.yml PLAY [build minecraft] *************************************************************************************************************************************************************************************************************************************************************** TASK [Gathering Facts] *************************************************************************************************************************************************************************************************************************************************************** The authenticity of host 'ec2-xx-xx-xx-xx9.ap-northeast-1.compute.amazonaws.com (xx.xx.xx.xx9)' can't be established. ECDSA key fingerprint is SHA256:4zFNS8SaLRQtm08Hs87FOBqN1XPh2vEi3OPk9AWQDt0. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes [WARNING]: Platform linux on host ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change this. See https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information. ok: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com] TASK [make_games : install java] ***************************************************************************************************************************************************************************************************************************************************** changed: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com] TASK [make_games : install screen] *************************************************************************************************************************************************************************************************************************************************** ok: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com] TASK [make_games : add a minecraft user] ********************************************************************************************************************************************************************************************************************************************* [WARNING]: The input password appears not to have been hashed. The 'password' argument must be encrypted for this module to work properly. changed: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com] TASK [make_games : settings sudo user minecraft] ************************************************************************************************************************************************************************************************************************************* changed: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com] TASK [make_games : make minecraft directory] ***************************************************************************************************************************************************************************************************************************************** changed: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com] TASK [make_games : get minecraft] **************************************************************************************************************************************************************************************************************************************************** changed: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com] TASK [make_games : create symbolic link] ********************************************************************************************************************************************************************************************************************************************* changed: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com] TASK [make_games : copy eula.txt] **************************************************************************************************************************************************************************************************************************************************** changed: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com] TASK [make_games : start minecraft] ************************************************************************************************************************************************************************************************************************************************** changed: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com] PLAY RECAP *************************************************************************************************************************************************************************************************************************************************************************** ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com : ok=10 changed=8 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
はい、できました。
実行結果
マイクラ接続♡
できたわね!
ちなみに、インスタンスごと葬り去りたいときは...
# /roles/make_infra/
$ ansible-playbook infra_destroy.yml
で、お願いします。
あくまでAnsibleは運用の技術なので、全消しはあまり良くないかなーってことでひっそりと...(思想に支配されすぎてもだめだけどね)
Afterword
はい、お疲れ様です。
無事実装できましたね♪
しかし、まだまだ爪のあまい部分があるかと思います。(warningめっちゃ出てるし...)
これを読んで、おかしいと思うことやよくないわねって思うことは,