2020/05/25 さくらのクラウド向けツールを使いこなす

4e842bca931f66f9cf29b3fdbd2cc4d8?s=47 kamijin_fanta
May 25, 2020
150

2020/05/25 さくらのクラウド向けツールを使いこなす

4e842bca931f66f9cf29b3fdbd2cc4d8?s=128

kamijin_fanta

May 25, 2020
Tweet

Transcript

  1. さくらのクラウド向けツールを使いこなす 2020/05/25 Tadahisa Kamijo

  2. 今⽇の内容 さくらのクラウドには組み合わせると便利になるツールが沢⼭あります。ツール郡と Ansible,Pulumi,Prometheusを組み合わせて、構成管理を省⼒化するテクニックを紹介 します。 今⽇紹介するのは、業務で実際に利⽤しているツール・フローです。

  3. さくらのクラウドの紹介 データ転送量無料 直感的な操作感のコントロールパネル 最⼩構成の料⾦: 1,980円 (1コア1GBサーバ+20GB SSD) ネットワーク関連サービスが豊富 VPS/専⽤サーバ/AWSとの接続 GSLB,

    L4/L7ロードバランサー 3キャリアに繋がるSIM (セキュアモバイルコネクト) 詳しくは: https://cloud.sakura.ad.jp/
  4. さくらのクラウドで利⽤可能なツール Terraform, Pulumi サーバ・ネットワークインフラの構成管理に利⽤ 例: 複数のサーバ作成・スイッチとサーバとの接続・ファイアウォール設定 Ansible ミドルウェア等の構成管理に利⽤ 例: Apache,nginx,Docker,監視エージェント

    等 今⽇はPulumi, Ansibleを使った構成管理を紹介
  5. Pulumi OSSのプロビジョニングツール インフラをTypeScript, Python, Go, C#で構築 無料で利⽤可能(有償プラン有り) 各種プロバイダ クラウド: AWS,

    Azure, GCP DB: MySQL, PostgreSQL さくらのクラウドもパッケージ追加で利⽤可能 https://github.com/sacloud/pulumi-sakuracloud 間違えやすい作業をコード化 何度実⾏しても状態が変わらないように記述可能 (冪等性)
  6. Pulumi - Install # pulumiのインストール $ curl -fsSL https://get.pulumi.com |

    sh # ステートをカレントディレクトリの .state ディレクトリに保存 $ pulumi login --local $ mkdir .state # とりあえずkubernetes-typescriptテンプレートで初期化 $ pulumi new kubernetes-typescript --force # k8s関連パッケージを削除 $ npm remove @pulumi/kubernetes @pulumi/kubernetesx # さくらのクラウドパッケージを導⼊ $ pulumi plugin install resource sakuracloud 0.3.0 --server https://github.com/sacloud/pulumi-sakuracloud/releases/download/0.3.0 $ npm install @sacloud/pulumi_sakuracloud # さくらのクラウドのAPIキーを⼊⼒ $ pulumi config set --secret sakuracloud:secret ****************** $ pulumi config set --plaintext sakuracloud:token 2fd7ba82-98d7-4fde-aac7-887ee8775734 $ pulumi config set --plaintext sakuracloud:zone tk1a
  7. Pulumi - 簡単な例 // index.ts import * as sakuracloud from

    '@sacloud/pulumi_sakuracloud'; // ディスクイメージのIDを取得 const ubuntu18archive = sakuracloud.getArchive({ filter: { tags: ['ubuntu-18.04-latest'], }, }); // 20GBのSSDを作成 const disk = new sakuracloud.Disk('example-disk', { plan: 'ssd', size: 20, sourceArchiveId: ubuntu18archive.id, }); // サーバを作成 const server = new sakuracloud.Server('example-server', { disks: [disk.id], });
  8. pulumi up # 作成 pulumi destroy # 削除

  9. Pulumi - 簡単な例2 ネットワークに繋げる・SSH鍵をサーバに⼊れる // SSH鍵を登録 const sshKey = new

    sakuracloud.SSHKey('ssh-key', { publicKey: 'ssh-rsa *************', }); // サーバを作成 const server = new sakuracloud.Server('example-server', { disks: [disk.id], networkInterfaces: [{ upstream: 'shared', }], diskEditParameter: { sshKeyIds: [sshKey.id], }, });
  10. Pulumi - Stackの切り替え $ pulumi stack ls NAME LAST UPDATE

    RESOURCE COUNT dev* 6 minutes ago 4 $ pulumi stack init prod # スタックprodを作成 $ pulumi stack select prod # スタックの切り替え $ pulumi up # 実⾏ import * as pulumi from '@pulumi/pulumi'; pulumi.getStack(); // 現在のStack名 dev/prod switch (pulumi.getStack()) { case 'dev': break; case 'prod': break; } 1つの構成ファイルから複数の環境にデプロイ出来る
  11. Pulumi - Secrets シークレット情報はパスワードで暗号化が可能・スタック毎に設定可能 $ pulumi config set --plaintext sakuracloud:zone

    tk1a $ pulumi config set --plaintext sakuracloud:token 2fd7ba82-98d7-4fde-aac7-887ee8775734 $ pulumi config set --secret sakuracloud:secret ****************** $ pulumi config KEY VALUE sakuracloud:secret [secret] sakuracloud:token 2fd7ba82-98d7-4fde-aac7-887ee8775734 sakuracloud:zone tk1a # パスワードの⼊⼒を省略する PULUMI_CONFIG_PASSPHRASE=encrypt-password
  12. Pulumi - リソース依存 const disk = new sakuracloud.Disk('disk'); const server

    = new sakuracloud.Server('server', { disks: [disk.id], }); diskのIDは、作成されるまで分からない Pulumiが⾃動的に依存関係を認識して作成順番を決める
  13. Pulumi - 既存リソースのimport const internalSwitch = new sakuracloud.Switch('internal-switch', { //

    options }, { import: '123456789012', // 既存のリソースIDを指定 })
  14. Pulumi - リファクタリング 第⼀引数に指定するリソース名が同じなら、同じリソースとして認識される const disk = new sakuracloud.Disk('example-disk'); const

    server = new sakuracloud.Server('example-server', { disks: [disk.id], }); 後から関数にまとめることも可能 function createBasicInstance (prefix: string) { const disk = new sakuracloud.Disk(prefix + '-disk'); const server = new sakuracloud.Server(prefix + '-server', { disks: [disk.id], }); return { disk, server }; } createBasicInstance('example');
  15. Pulumi - ファイル分割 ⾔語の機能を使って、別ファイルからのインポートも可能 // instanceTemplate.ts export function createBasicInstance (prefix:

    string) { const disk = new sakuracloud.Disk(prefix + '-disk'); const server = new sakuracloud.Server(prefix + '-server', { disks: [disk.id], }); return { disk, server }; } // index.ts import { createBasicInstance } from './instanceTemplate.ts'; createBasicInstance('example');
  16. Pulumi - Stateファイル State 現在のリソース状況を保持する複数のJSONファイル Pulumi上のリソース・クラウド上のリソース情報を紐付ける pulumi up 等がどこまで進んだかを保持 保存場所

    Pulumi Service: 1⼈なら無料・チームでの利⽤は有料 オブジェクトストレージ: AWS S3, Google Cloud Storage, Azure Blob ローカルファイル: GitHub等での管理
  17. Ansible OSSのプロビジョニングツール Yamlファイルに従って複数サーバ内の設定を⾃動的に⾏う Linuxマシンへは内部的にSSHで接続 (クラウド/VPS/Ubuntu/CentOSどれでもOK) 設定ファイルの設置・パッケージ導⼊など、属⼈化しがちな作業をコード化 何度実⾏しても状態が変わらないように記述可能 (冪等性) https://www.ansible.com/

  18. Ansible - 出来ること ⽤途ごとに多数のモジュールが⽤意されている file: シンボリックリンク・ディレクトリの作成 copy: ファイルをサーバに送信・設置 template: jinjaテンプレートで設定ファイル等を作成・設置

    apt,dnf: パッケージのインストール sysctl: Linuxカーネルパラメータの設定 systemd: サービスの有効・開始 3000モジュール以上提供 (特定クラウド・ミドルウェア向けのモジュールも多数含む)
  19. Ansible - 簡単な例 主に2つのファイルを使ってマシンへの操作を記述 # inventory.ini - サーバのホスト名・IPアドレス等を記述 [web] example-server

    ansible_host=163.43.192.*** # playbook.yml - どのホストに対して何を⾏うか記述 - hosts: - all # 対象ホスト web等のグループ名かallを記述 複数指定可能 tasks: # 実際にホスト上で⾏う操作 複数指定可能 - name: ping task # 操作の名前 実⾏ログに出る ping: # 何もしないモジュール
  20. 実⾏結果 $ ansible-playbook -i inventory.ini playbook.yml PLAY [all] ************************************************************************************************************************* TASK

    [Gathering Facts] ************************************************************************************************************* ok: [example-server] TASK [ping task] ******************************************************************************************************************* ok: [example-server] PLAY RECAP ************************************************************************************************************************* example-server : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
  21. Ansible - Inventoryファイル ホスト毎の変数・グループごとの変数を定義できる 変数は設定ファイルへの埋め込み・タスクの動作を変えることが出来る [web] web-01 ansible_host=***.***.***.*** web-02 ansible_host=***.***.***.***

    web-03 ansible_host=***.***.***.*** ansible_port=10022 [web:vars] http_port = 8080 # webグループの全てのホストに適⽤される [api] api-01 ansible_host=***.***.***.*** api-02 ansible_host=***.***.***.*** [db] db-01 ansible_host=***.***.***.*** db_master=True db-02 ansible_host=***.***.***.*** db_master=False
  22. Ansible - タスクでの変数の利⽤ - name: install packages apt: name: "{{

    package_name }}" # オプションに変数を渡す - name: install curl apt: name: curl when: "{{ curl_install }}" # Trueの場合のみタスクを実⾏ template モジュールを利⽤することで、設定ファイルに変数を埋め込むことも可能
  23. Ansible - Dynamic Inventory Inventoryを実⾏時にクラウドのAPIから収集する仕組み AWC EC2, GCP GCE等のマシン⼀覧からInventoryを作成 Inventoryを⼿書きする必要が無くなる

    $ ansible-playbook -i dynamic-inventory playbook.yml -i オプションでDynamic Inventoryの実⾏ファイルを渡す
  24. sacloud-ansible-inventory さくらのクラウド向けのDynamic Inventory 概要 Ansibleで管理したいマシンに __with_sacloud_inventory タグをセットする サーバのタグがAnsibleのグループへ⾃動登録 サーバの説明⽂にJSON⽂字列が⼊っていれば、ホスト変数にセット インスタンスのIPアドレスをAnsibleの接続先IPとしてセット

    https://github.com/sakura-internet/sacloud-ansible-inventory
  25. [web_server] example-server-be717a0 ansible_host=***.***.***.*** http_server_port=8080

  26. Pulumi+Ansibleのベストプラクティス Pulumiでサーバタグを設定すれば、Ansibleでグループとして扱える サーバ説明⽂にJSON⽂字を⼊れれば、Ansibleで変数として読める // ホストの収集対象に設定・stack_dev or stack_prodのグループに追加する const COMMON_SERVER_TAGS =

    ['__with_sacloud_inventory', 'stack_' + pulumi.getStack()]; const serverDesc = { sacloud_inventory: { hostname_type: 'nic0_ip', // ⾃動的に ansible_host=***.***.***.*** のように展開 host_vers: { http_server_port: '8080', // Ansible内で参照する変数を定義 }, }, }; const server = new sakuracloud.Server('web-server-01', { tags: [...COMMON_SERVER_TAGS, 'web_server'], // タグ description: JSON.stringify(serverDesc), // 説明⽂ });
  27. Prometheusでのサーバ監視 Pull型の監視ツール exporter(外部ツール)が出⼒したメトリクスを取得 内蔵の時系列DBへ蓄積 Grafana(外部ツール)等で可視化

  28. node_exporter マシン⾃体の状況をPrometheusへ提供する $ ./node_exporter # 0.0.0.0:9100でlisten $ curl localhost:9100/metrics #

    HELP node_load1 1m load average. # TYPE node_load1 gauge node_load1 0.7 # HELP node_load15 15m load average. # TYPE node_load15 gauge node_load15 0.53 # HELP node_load5 5m load average. # TYPE node_load5 gauge node_load5 0.69 ........ https://github.com/prometheus/node_exporter
  29. Prometheus scrape_configs # prometheus.yml scrape_configs: - job_name: 'node' static_configs: -

    targets: - '***.***.***.***:9100' - '***.***.***.***:9100' - '***.***.***.***:9100' - '***.***.***.***:9100' exporterのアドレスを指定・サーバを増やす度に増えてゆく
  30. sacloud-prometheus-sd さくらのクラウドから⾃動的にサーバの情報を収集 Prometheusの監視対象へ追加することが可能 https://github.com/sakura-internet/sacloud-prometheus-sd

  31. 設定例 1 sacloud_token: "" sacloud_token_secret: "" sacloud_zone: "1k1a" base_tags: -

    "__with_sacloud_inventory" targets: - service: "node" # Prometheus側に渡すサービス名 ignore_tags: ["sandbox"] # 指定されていれば無視するタグ・複数指定可能 ports: [9100] # exporterが動作しているTCPポート番号・複数指定可能 interface_index: 0 # IPアドレスを取得するNICのIndex番号・デフォルト0 - service: "api-server" tags: ["api"] # 対象とするタグ・複数指定可能 ports: [3000, 4000]
  32. 設定例 2 # /tmp/sacloud_prometheus_sd_generated.yml - targets: - ***.***.***.***:9100 labels: __meta_sacloud_instances_tags:

    ',stack_develop,web_server,__with_sacloud_inventory,' __meta_sacloud_zone: tk1a hostname: example-server-be717a0 service: node # prometheus.yml scrape_configs: - job_name: 'sacloud' file_sd_configs: - refresh_interval: 30s files: - /tmp/sacloud_prometheus_sd_generated.yml
  33. 最後に さくらのクラウドとツールを組み合わせると構成管理が省⼒化出来る Pulumiを使って複数台のサーバインフラを楽に管理できる Ansible,Prometheusのホスト⼀覧の管理を Pulumi(さくらのクラウド)に寄せることが出来る Pulumiはモダンなプログラミング⾔語を利⽤し、複雑な構成も記述が⾏いやすい さくらのクラウドのツールを作るために便利なCLI/Goライブラリが有る https://github.com/sacloud/usacloud

  34. 追加資料 Ansibleの概要

  35. モジュールの使い⽅ # playbook.yml - どのホストに対して何を⾏うか記述 - hosts: - all #

    対象ホスト web等のグループ名かallを記述 複数指定可能 tasks: # 実際にホスト上で⾏う操作 複数指定可能 - name: install curl # aptモジュールでcurlをインストールする apt: name: curl aptモジュール: https://docs.ansible.com/ansible/latest/modules/apt_module.html
  36. 設定ファイル さっきの動かすのには、これも実は必要 // ansible.cfg [defaults] transport=ssh remote_user=ubuntu [ssh_connection] pipelining =

    True [privilege_escalation] become = True become_user = root become_flags ='-H -S'
  37. Inventory書き⽅ ini/yamlで対象ホストの⼀覧を記述する ホストをグループ化することが可能 # inventory.ini - サーバのホスト名・IPアドレス等を記述 [web] web-01 ansible_host=***.***.***.***

    web-02 ansible_host=***.***.***.*** web-03 ansible_host=***.***.***.*** [api] api-01 ansible_host=***.***.***.*** api-02 ansible_host=***.***.***.*** [db] db-01 ansible_host=***.***.***.*** db-02 ansible_host=***.***.***.***
  38. Playbookのグループ化 Playbookには3つの粒度が有る: Play/Role/Task Roleを使うことで⽤途ごとに操作をグループ化できる Playから利⽤するRoleを指定 # common-playbook.yml - hosts: -

    all roles: - common # nginx-playbook.yml - hosts: - web - api roles: - nginx - nginx_monitoring
  39. Role # roles/common/tasks/main.yaml - ロール内で実⾏するタスクを記述 - name: install basic packages

    apt: name: - curl - vim - name: create authorized_keys copy: src=authorized_keys dest=/home/ubuntu/.ssh/authorized_keys owner=ubuntu group=ubuntu mode=0600 実⾏はPlay単位 $ ansible-playbook -i inventory.ini common-playbook.yml nginx-playbook.yml
  40. 変数 ⽤途: テンプレート・タスクの分岐・モジュールに渡す 主な変数の定義場所 Ansibleがデフォルトで提供 Inventoryファイルでの定義 group_vars/all group_vars/GROUP_NAME ファイルでの定義 host_vars/HOST_NAME

    ファイルでの定義 その他多数… 詳細: https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html
  41. 1. デフォルト変数 ホストから収集した変数 かなりの量あるので⼀部だけ紹介 ansible_architecture : "x86_64" ansible_distribution : "Ubuntu"

    ansible_distribution_major_version : "18" ansible_eth0.ipv4.address : " .. ." ansible_devices.xvda.size : "40.00 GB" Playbookを実⾏した時に出る Gathering Facts のタイミングで収集
  42. 2. Inventoryファイルでの定義 ホスト毎の変数・グループごとの変数を定義できる [web] web-01 ansible_host=***.***.***.*** web-02 ansible_host=***.***.***.*** web-03 ansible_host=***.***.***.***

    ansible_port=10022 [web:vars] http_port = 8080 # webグループの全てのホストに適⽤される [api] api-01 ansible_host=***.***.***.*** api-02 ansible_host=***.***.***.*** [db] db-01 ansible_host=***.***.***.*** db_master=True db-02 ansible_host=***.***.***.*** db_master=False
  43. 3. group_vars/* # group_vars/all.yml - 全てのホストに適⽤される default_user_password: 'PASSWORD' # group_vars/web.yml

    - グループ中全てのホストに適⽤される default_user_password: 'PASSWORD'
  44. A. タスクでの変数利⽤ jinjaテンプレートで指定可能 - name: install packages apt: name: "{{

    package_name }}" # オプションに変数を渡す - name: install curl apt: name: curl when: "{{ curl_install }}" # Trueの場合のみタスクを実⾏
  45. B. templateでの変数利⽤ 設定ファイルで変数展開を⾏うことが出来る # group_vars/all.yml github_username: "*****" github_personal_access_token: "*****" #

    roles/ROLE_NAME/template/FILE_NAME.yml github: username: "{{ github_username }}" token: "{{ github_personal_access_token }}" # roles/ROLE_NAME/tasks/main.yml - name: configure file template: src: FILE_NAME.yml dest: /path/to/remote/path/