Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

kamijin_fanta
May 25, 2020
270

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

kamijin_fanta

May 25, 2020
Tweet

Transcript

  1. Pulumi OSSのプロビジョニングツール インフラをTypeScript, Python, Go, C#で構築 無料で利⽤可能(有償プラン有り) 各種プロバイダ クラウド: AWS,

    Azure, GCP DB: MySQL, PostgreSQL さくらのクラウドもパッケージ追加で利⽤可能 https://github.com/sacloud/pulumi-sakuracloud 間違えやすい作業をコード化 何度実⾏しても状態が変わらないように記述可能 (冪等性)
  2. 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
  3. 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], });
  4. 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], }, });
  5. 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つの構成ファイルから複数の環境にデプロイ出来る
  6. 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
  7. Pulumi - リソース依存 const disk = new sakuracloud.Disk('disk'); const server

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

    options }, { import: '123456789012', // 既存のリソースIDを指定 })
  9. 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');
  10. 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');
  11. Pulumi - Stateファイル State 現在のリソース状況を保持する複数のJSONファイル Pulumi上のリソース・クラウド上のリソース情報を紐付ける pulumi up 等がどこまで進んだかを保持 保存場所

    Pulumi Service: 1⼈なら無料・チームでの利⽤は有料 オブジェクトストレージ: AWS S3, Google Cloud Storage, Azure Blob ローカルファイル: GitHub等での管理
  12. Ansible - 出来ること ⽤途ごとに多数のモジュールが⽤意されている file: シンボリックリンク・ディレクトリの作成 copy: ファイルをサーバに送信・設置 template: jinjaテンプレートで設定ファイル等を作成・設置

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

    ansible_host=163.43.192.*** # playbook.yml - どのホストに対して何を⾏うか記述 - hosts: - all # 対象ホスト web等のグループ名かallを記述 複数指定可能 tasks: # 実際にホスト上で⾏う操作 複数指定可能 - name: ping task # 操作の名前 実⾏ログに出る ping: # 何もしないモジュール
  14. 実⾏結果 $ 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
  15. 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
  16. Ansible - タスクでの変数の利⽤ - name: install packages apt: name: "{{

    package_name }}" # オプションに変数を渡す - name: install curl apt: name: curl when: "{{ curl_install }}" # Trueの場合のみタスクを実⾏ template モジュールを利⽤することで、設定ファイルに変数を埋め込むことも可能
  17. 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), // 説明⽂ });
  18. 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
  19. Prometheus scrape_configs # prometheus.yml scrape_configs: - job_name: 'node' static_configs: -

    targets: - '***.***.***.***:9100' - '***.***.***.***:9100' - '***.***.***.***:9100' - '***.***.***.***:9100' exporterのアドレスを指定・サーバを増やす度に増えてゆく
  20. 設定例 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]
  21. 設定例 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
  22. モジュールの使い⽅ # 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
  23. 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=***.***.***.***
  24. 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
  25. 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 のタイミングで収集
  26. 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
  27. 3. group_vars/* # group_vars/all.yml - 全てのホストに適⽤される default_user_password: 'PASSWORD' # group_vars/web.yml

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

    package_name }}" # オプションに変数を渡す - name: install curl apt: name: curl when: "{{ curl_install }}" # Trueの場合のみタスクを実⾏
  29. 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/