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

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

kamijin_fanta
May 25, 2020
230

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

kamijin_fanta

May 25, 2020
Tweet

Transcript

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

    View Slide

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

    View Slide

  3. さくらのクラウドの紹介
    データ転送量無料
    直感的な操作感のコントロールパネル
    最⼩構成の料⾦: 1,980円 (1コア1GBサーバ+20GB SSD)
    ネットワーク関連サービスが豊富
    VPS/専⽤サーバ/AWSとの接続
    GSLB, L4/L7ロードバランサー
    3キャリアに繋がるSIM (セキュアモバイルコネクト)
    詳しくは: https://cloud.sakura.ad.jp/

    View Slide

  4. さくらのクラウドで利⽤可能なツール
    Terraform, Pulumi
    サーバ・ネットワークインフラの構成管理に利⽤
    例: 複数のサーバ作成・スイッチとサーバとの接続・ファイアウォール設定
    Ansible
    ミドルウェア等の構成管理に利⽤
    例: Apache,nginx,Docker,監視エージェント 等
    今⽇はPulumi, Ansibleを使った構成管理を紹介

    View Slide

  5. Pulumi
    OSSのプロビジョニングツール
    インフラをTypeScript, Python, Go, C#で構築
    無料で利⽤可能(有償プラン有り)
    各種プロバイダ
    クラウド: AWS, Azure, GCP
    DB: MySQL, PostgreSQL
    さくらのクラウドもパッケージ追加で利⽤可能
    https://github.com/sacloud/pulumi-sakuracloud
    間違えやすい作業をコード化
    何度実⾏しても状態が変わらないように記述可能 (冪等性)

    View Slide

  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

    View Slide

  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],
    });

    View Slide

  8. pulumi up # 作成
    pulumi destroy # 削除

    View Slide

  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],
    },
    });

    View Slide

  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つの構成ファイルから複数の環境にデプロイ出来る

    View Slide

  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

    View Slide

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

    View Slide

  13. Pulumi - 既存リソースのimport
    const internalSwitch = new sakuracloud.Switch('internal-switch', {
    // options
    }, {
    import: '123456789012', // 既存のリソースIDを指定
    })

    View Slide

  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');

    View Slide

  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');

    View Slide

  16. Pulumi - Stateファイル
    State
    現在のリソース状況を保持する複数のJSONファイル
    Pulumi上のリソース・クラウド上のリソース情報を紐付ける
    pulumi up 等がどこまで進んだかを保持
    保存場所
    Pulumi Service: 1⼈なら無料・チームでの利⽤は有料
    オブジェクトストレージ: AWS S3, Google Cloud Storage, Azure Blob
    ローカルファイル: GitHub等での管理

    View Slide

  17. Ansible
    OSSのプロビジョニングツール
    Yamlファイルに従って複数サーバ内の設定を⾃動的に⾏う
    Linuxマシンへは内部的にSSHで接続
    (クラウド/VPS/Ubuntu/CentOSどれでもOK)
    設定ファイルの設置・パッケージ導⼊など、属⼈化しがちな作業をコード化
    何度実⾏しても状態が変わらないように記述可能 (冪等性)
    https://www.ansible.com/

    View Slide

  18. Ansible - 出来ること
    ⽤途ごとに多数のモジュールが⽤意されている
    file: シンボリックリンク・ディレクトリの作成
    copy: ファイルをサーバに送信・設置
    template: jinjaテンプレートで設定ファイル等を作成・設置
    apt,dnf: パッケージのインストール
    sysctl: Linuxカーネルパラメータの設定
    systemd: サービスの有効・開始
    3000モジュール以上提供
    (特定クラウド・ミドルウェア向けのモジュールも多数含む)

    View Slide

  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: # 何もしないモジュール

    View Slide

  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

    View Slide

  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

    View Slide

  22. Ansible - タスクでの変数の利⽤
    - name: install packages
    apt:
    name: "{{ package_name }}" # オプションに変数を渡す
    - name: install curl
    apt:
    name: curl
    when: "{{ curl_install }}" # Trueの場合のみタスクを実⾏
    template モジュールを利⽤することで、設定ファイルに変数を埋め込むことも可能

    View Slide

  23. Ansible - Dynamic Inventory
    Inventoryを実⾏時にクラウドのAPIから収集する仕組み
    AWC EC2, GCP GCE等のマシン⼀覧からInventoryを作成
    Inventoryを⼿書きする必要が無くなる
    $ ansible-playbook -i dynamic-inventory playbook.yml
    -i オプションでDynamic Inventoryの実⾏ファイルを渡す

    View Slide

  24. sacloud-ansible-inventory
    さくらのクラウド向けのDynamic Inventory
    概要
    Ansibleで管理したいマシンに __with_sacloud_inventory タグをセットする
    サーバのタグがAnsibleのグループへ⾃動登録
    サーバの説明⽂にJSON⽂字列が⼊っていれば、ホスト変数にセット
    インスタンスのIPアドレスをAnsibleの接続先IPとしてセット
    https://github.com/sakura-internet/sacloud-ansible-inventory

    View Slide

  25. [web_server]
    example-server-be717a0 ansible_host=***.***.***.*** http_server_port=8080

    View Slide

  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), // 説明⽂
    });

    View Slide

  27. Prometheusでのサーバ監視
    Pull型の監視ツール
    exporter(外部ツール)が出⼒したメトリクスを取得
    内蔵の時系列DBへ蓄積
    Grafana(外部ツール)等で可視化

    View Slide

  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

    View Slide

  29. Prometheus scrape_configs
    # prometheus.yml
    scrape_configs:
    - job_name: 'node'
    static_configs:
    - targets:
    - '***.***.***.***:9100'
    - '***.***.***.***:9100'
    - '***.***.***.***:9100'
    - '***.***.***.***:9100'
    exporterのアドレスを指定・サーバを増やす度に増えてゆく

    View Slide

  30. sacloud-prometheus-sd
    さくらのクラウドから⾃動的にサーバの情報を収集
    Prometheusの監視対象へ追加することが可能
    https://github.com/sakura-internet/sacloud-prometheus-sd

    View Slide

  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]

    View Slide

  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

    View Slide

  33. 最後に
    さくらのクラウドとツールを組み合わせると構成管理が省⼒化出来る
    Pulumiを使って複数台のサーバインフラを楽に管理できる
    Ansible,Prometheusのホスト⼀覧の管理を
    Pulumi(さくらのクラウド)に寄せることが出来る
    Pulumiはモダンなプログラミング⾔語を利⽤し、複雑な構成も記述が⾏いやすい
    さくらのクラウドのツールを作るために便利なCLI/Goライブラリが有る
    https://github.com/sacloud/usacloud

    View Slide

  34. 追加資料 Ansibleの概要

    View Slide

  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

    View Slide

  36. 設定ファイル
    さっきの動かすのには、これも実は必要
    // ansible.cfg
    [defaults]
    transport=ssh
    remote_user=ubuntu
    [ssh_connection]
    pipelining = True
    [privilege_escalation]
    become = True
    become_user = root
    become_flags ='-H -S'

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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 のタイミングで収集

    View Slide

  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

    View Slide

  43. 3. group_vars/*
    # group_vars/all.yml - 全てのホストに適⽤される
    default_user_password: 'PASSWORD'
    # group_vars/web.yml - グループ中全てのホストに適⽤される
    default_user_password: 'PASSWORD'

    View Slide

  44. A. タスクでの変数利⽤
    jinjaテンプレートで指定可能
    - name: install packages
    apt:
    name: "{{ package_name }}" # オプションに変数を渡す
    - name: install curl
    apt:
    name: curl
    when: "{{ curl_install }}" # Trueの場合のみタスクを実⾏

    View Slide

  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/

    View Slide