投稿者: sumito.tsukada

  • ERROR 1045 (28000): Access denied for user ‘root’@’localhost’ (using password: YES)

    ERROR 1045 (28000): Access denied for user ‘root’@’localhost’ (using password: YES)

    はじめに

    kusanagiを使いインスタンスを増やそうとすると、上記のようなエラーに遭う事がある。

    原因

    kusanagiに登録されているmysqlのrootパスワードと、実際のmysqlのrootパスワードに違いがある。

    kusanagiに登録されているrootパスワードを変えるには?

    /etc/kusanagi.d ディレクトリあたりにあるかとおもったら、全く違う所にあった。

    /root/.my.cnf だ。

    [mysqladmin]
    password = "**********"
    user = root

    このpasswordを実際のパスワードに変更する事で、解決することができる。

     

     

     

  • CloudStorageへAPI経由でファイルをuploadする

    CloudStorageへAPI経由でファイルをuploadする

    はじめに

    Google Cloud StorageへAPI経由でファイルをuploadする。

    Introduction to APIs in Google を受講して、基本的な使い方を覚えたのでメモを残す

    https://www.qwiklabs.com/focuses/3473?catalog_rank=%7B%22rank%22%3A15%2C%22num_filters%22%3A0%2C%22has_search%22%3Atrue%7D&locale=ja&parent=catalog&search_id=2013206

    前準備

    OAuthのアクセストークンを生成する

    https://developers.google.com/oauthplayground/

     

     

    バケットの作成

    頻繁に使うので認証を環境変数に入れる

    export OAUTH2_TOKEN=<YOUR_TOKEN>

    プロジェクトIDも入れる

    export PROJECT_ID=<YOUR_PROJECT_ID>

    バケット生成の定義のjsonファイルを作成、読み込む

    {  "name": "<YOUR_BUCKET_NAME>",
       "location": "us",
       "storageClass": "multi_regional"
    }
    
    
    curl -X POST --data-binary @values.json \
        -H "Authorization: Bearer $OAUTH2_TOKEN" \
        -H "Content-Type: application/json" \
        "https://www.googleapis.com/storage/v1/b?project=$PROJECT_ID"

    画像をuploadする

    wget https://gcpstaging-qwiklab-website-prod.s3.amazonaws.com/bundles/assets/138f92c75d08d0705e3853c1d790453f37fdfff38afad7fb4b431b9fa690f1fc.png
    mv 138f92c75d08d0705e3853c1d790453f37fdfff38afad7fb4b431b9fa690f1fc.png demo-image.png

    フルパスを確認する

    realpath demo-image.png

    結果を環境変数に入れる

    export OBJECT=<DEMO_IMAGE_PATH>

    バケット名を環境変数に入れる
    (先ほど作成したやつ)

    export BUCKET_NAME=<YOUR_BUCKET>

    cloud storageにuploadする

    curl -X POST --data-binary @$OBJECT \
        -H "Authorization: Bearer $OAUTH2_TOKEN" \
        -H "Content-Type: image/png" \
        "https://www.googleapis.com/upload/storage/v1/b/$BUCKET_NAME/o?uploadType=media&name=demo-image"

     

    参考情報

    JSONの構文チェックに便利なサイト

    https://jsonlint.com/

     

    Cloud StorageのAPIリファレンス(英語)

    https://cloud.google.com/storage/docs/json_api/v1/

     

  • postgresのシーケンス一覧を取得ならびに変更する

    postgresのシーケンス一覧を取得ならびに変更する

    はじめに

    redashの内部のDBはpostgresだが、version upを繰り返すうちにDB構成がバグってしまった。具体的には外部キーや、Indexなのが外れてしまった。

    根本対応としては再度イチからredashを作り、そこにデータを一個一個転送することになるとおもうが、なかなかその対応にたどり着けず、一時対応でとりあえず問題を先送りしている。

    ちなみにusersテーブルの場合、以下の部分がごっそり無くなっていた

    Indexes:
        "users_pkey" PRIMARY KEY, btree (id)
        "users_api_key_key" UNIQUE CONSTRAINT, btree (api_key)
        "users_org_id_email" UNIQUE, btree (org_id, email)
    Foreign-key constraints:
        "users_org_id_fkey" FOREIGN KEY (org_id) REFERENCES organizations(id)
    Referenced by:
        TABLE "access_permissions" CONSTRAINT "access_permissions_grantee_id_fkey" FOREIGN KEY (grantee_id) REFERENCES users(id)
        TABLE "access_permissions" CONSTRAINT "access_permissions_grantor_id_fkey" FOREIGN KEY (grantor_id) REFERENCES users(id)
        TABLE "alert_subscriptions" CONSTRAINT "alert_subscriptions_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id)
        TABLE "alerts" CONSTRAINT "alerts_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id)
        TABLE "api_keys" CONSTRAINT "api_keys_created_by_id_fkey" FOREIGN KEY (created_by_id) REFERENCES users(id)
        TABLE "changes" CONSTRAINT "changes_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id)
        TABLE "dashboards" CONSTRAINT "dashboards_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id)
        TABLE "events" CONSTRAINT "events_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id)
        TABLE "favorites" CONSTRAINT "favorites_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id)
        TABLE "notification_destinations" CONSTRAINT "notification_destinations_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id)
        TABLE "queries" CONSTRAINT "queries_last_modified_by_id_fkey" FOREIGN KEY (last_modified_by_id) REFERENCES users(id)
        TABLE "queries" CONSTRAINT "queries_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id)
        TABLE "query_snippets" CONSTRAINT "query_snippets_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id)
    

    その結果、Edit Visualizationで保存ができなくなった。

    コンテナのログを見たら、本来1つしかないはずが2つ以上ヒットするよ。とエラーになっているのが原因だとわかった。

    シーケンスで指している数字が、すでにレコードとして存在していたのが問題だ。

    今回はシーケンスを変更することで対処した。

    Postgresのシーケンス一覧を表示する

    “` SELECT c.relname FROM pg_class c LEFT join pg_user u ON c.relowner = u.usesysid WHERE c.relkind = ‘S’; relname  “` で表示できる。

    redashに限らず、どのPostgresでも対応可能。

    postgres=# SELECT c.relname FROM pg_class c LEFT join pg_user u ON c.relowner = u.usesysid WHERE c.relkind = 'S';
                 relname              
    ----------------------------------
     access_permissions_id_seq
     alert_subscriptions_id_seq
     alerts_id_seq
     api_keys_id_seq
     changes_id_seq
     dashboards_id_seq
     data_source_groups_id_seq
     data_sources_id_seq
     events_id_seq
     favorites_id_seq
     groups_id_seq
     notification_destinations_id_seq
     organizations_id_seq
     queries_id_seq
     query_results_id_seq
     query_snippets_id_seq
     users_id_seq
     visualizations_id_seq
     widgets_id_seq
    (19 rows)
    
    postgres=#

    シーケンスの値を確認する

    postgres=# select nextval('visualizations_id_seq');                                                                                                                                                                  nextval 
    ---------
          56
    (1 row)

    56ということがわかる

    シーケンスの値を変更する

    ALTER SEQUENCEコマンドで変更が可能

    postgres=# ALTER SEQUENCE visualizations_id_seq RESTART WITH 251;
    ALTER SEQUENCE

     

    結果、redashが正常に動くようになった。

    おそらくversion upを繰り返しているうちに、どこかでDBスキーマが壊れてしまった可能性がある。

     

    関連記事

    https://tsukada.sumito.jp/2018/10/11/redash_all-queries_loading/

    redash を専門に扱っている唯一の本

  • Kubernetesでスケールアップ・ローリングアップデートを行う

    Kubernetesでスケールアップ・ローリングアップデートを行う

    はじめに

    Kubernetesはバズワードになりつつあるが、スケールアップ・ローリングアップデートを含む運用のノウハウはまだまだそれほど多くないのでまとめる。

    Node.js サーバーを作成する

    var http = require('http');
    var handleRequest = function(request, response) {
      response.writeHead(200);
      response.end("Hello World!");
    }
    var www = http.createServer(handleRequest);
    www.listen(8080);

    起動

    node server.js

    Docker コンテナ イメージを作成する

    FROM node:6.9.2
    EXPOSE 8080
    COPY server.js .
    CMD node server.js

    docker hubからnodeのversion 6.9.2をダウンロード。
    8080ポートを外部に公開、
    先ほど作ったserver.jsをdocker内にコピー、
    nodeコマンドでserver.jsを起動する。と言った内容。

    Dockerイメージをビルドする

    docker build -t gcr.io/PROJECT_ID/hello-node:v1 .

    動作確認

    docker run -d -p 8080:8080 gcr.io/PROJECT_ID/hello-node:v1

    curlで自身に接続し接続確認をする

    curl http://localhost:8080

    非公開リポジトリ Google Container Registry にpushする

    gcloud docker -- push gcr.io/PROJECT_ID/hello-node:v1

    Kubernetesのクラスタを作成する

    クラスタはGCPで用意する。

    gcloud config set project PROJECT_ID

    2 つの n1-standard-1 ノードのあるクラスタ

    gcloud container clusters create hello-world \
                    --num-nodes 2 \
                    --machine-type n1-standard-1 \
                    --zone us-central1-a

    ポッドを作成する

    こちらは先ほど作ったクラスタの中につくられる。

    Kubernetesのコマンドkubectlを使って作っていく。

    kubectl run hello-node \
        --image=gcr.io/PROJECT_ID/hello-node:v1 \
        --port=8080

    デプロイメントオブジェクトが作成される。

    確認のコマンドはこちら

    kubectl get deployments

    デプロイメントによって作成されたポッドは以下のコマンドで確認

    kubectl get pods

    Kubernetesの状態を確認するコマンド

    kubectl cluster-info
    
    kubectl config view
    
    kubectl get events
    
    kubectl logs <pod-name>
    
    

    外部トラフィックを許可する

    デフォルトではポッドにはクラスタ内部IPからしかアクセスできないようになっている。kubectl exposeコマンドと –type=”LoadBalancer”で公開する事ができる。

    kubectl expose deployment hello-node --type="LoadBalancer"

    (ポッドを直接公開する手順ではなく、デプロイメントを公開の手順)

    公開IPを確認

    kubectl get services

    サービスのスケールアップ

    今までは2つのレプリカを用意していたが、それをさらに増やしたい場合以下のコマンドでスケールアップする事が可能

    kubectl scale deployment hello-node --replicas=4

    確認

    kubectl get deployment

    podの状態を確認

    kubectl get pods

    新しいコンテナをデプロイする

    再度nodeで作ったserver.jsを適当に編集し、保存する。

    その後buildしてpush

    docker build -t gcr.io/PROJECT_ID/hello-node:v2 .
    gcloud docker -- push gcr.io/PROJECT_ID/hello-node:v2

    その後、kubectlコマンドでデプロイするコンテナイメージのタグを変更する

    kubectl edit deployment hello-node

    変更するフィールドは

    spec.template.spec.containers.image

          containers:
          - image: gcr.io/PROJECT_ID/hello-node:v1 

    をv1からv2へ変更する

    kubectl get deployments

    を行うと順次ポッドがローリングアップデートされる。

    古いポッドは削除されてしまうので注意。

    管理画面を見る

    gcloud container clusters get-credentials hello-world \
        --zone us-central1-a --project <PROJECT_ID>

    トークンを取得する

    kubectl -n kube-system describe $(kubectl -n kube-system \
       get secret -n kube-system -o name | grep namespace) | grep token:

    8081ポートを使うことにする(どこでもよい)

    kubectl proxy --port 8081

    コンソール画面でchange portをクリックし、8081ポートに変更する。

    ?authuser=0を削除し、以下のとおり/uiに変更する

    例: 

    https://8081-dot-6387619-dot-devshell.appspot.com/ui

    参考情報

    https://google.qwiklabs.com/focuses/564?locale=ja&parent=catalog

  • RDSをawsコマンドで削除する

    RDSをawsコマンドで削除する

    はじめに

    RDSをaws cliで削除したいことがある。認証さえ登録されていれば1行でできる。

    コマンド

    普通にdatabaseが消えるので要注意。

    aws rds delete-db-instance --db-instance-identifier [インスタンス名] --skip-final-snapshot

    確認

    作業前

    作業後

  • Vimでインデントを整形する

    Vimでインデントを整形する

    はじめに

    vimでフォーマット(インデント)を自動で整えたい時があるので、その方法を紹介。

    gg=G

      gg でファイルの先頭に移動
    =  がインデント修正
    G  で最後まで実施する

    という意味になる

  • route 53をCLIで登録する

    route 53をCLIで登録する

    はじめに

    route 53の登録をコマンドで実行したい時がある。

    コマンドをまとめる。

    準備

    jsonファイルを作成

    {
     "Changes": [
     {
      "Action": "UPSERT",
      "ResourceRecordSet": {
       "Name": "server-original.stg.rds.sumito.jp",
       "TTL": 300,
       "Type": "CNAME",
       "ResourceRecords": [
       {
        "Value": "server-original-stg-rds.aaaddcda.ap-northeast-1.rds.amazonaws.com"
       }
       ]
       }
      }
      ]
    }

    aws route53コマンドで読み込ませる

    #変数登録
    DB_JSON=create_db.json
    HOST_ZONE_ID=`aws --profile staging route53 list-hosted-zones | jq -r '.[][] | select (.Name == "stg.rds.sumito.jp.") | .Id'`
    
    SDBM_ID=`aws --profile staging route53 change-resource-record-sets --hosted-zone-id ${HOST_ZONE_ID} --change-batch file://${DB_JSON} `

    ステータス確認

    echo $SDBM_ID | jq -r '.ChangeInfo.Status'
    PENDING

     

     

     

  • datadog,Google Stackdriver,New Relicを比較した

    datadog,Google Stackdriver,New Relicを比較した

    はじめに

    マルチクラウド時代、監視はVPCごとに作らなければならなくなりがち。そのため、マルチクラウドに対応した監視を導入すべく、datadogが候補に上がった。

    Google Stackdriver,New Relicとも比較した。

    特徴

    integrationを自社開発している。

    eventの取得頻度は10分/1回、RDSはもっと頻繁、かたや課金は4時間ごとにみている。agentを入れると15sごとになる。

    agentいれても、cloudwatchでも。2018年末時点では1台でxxxx円という料金形態。

    リソースの保存は15ヶ月。
    ログは料金に応じて。S3に出力して、athenaなどで解析も可能

    監視対象サーバの追加について

    OS毎にテンプレートを作って、それを自動で割り当てることはできない。

    複数同じ設定をする際は、terraformでimport & exportが必要

    https://www.terraform.io/docs/providers/datadog/index.html

    GCPについて

    GCPの場合、プロジェクト毎にdatadog用のService account keyを作らなければならない。

    特定ユーザのみ公開

    「ある画面をAさんには見せ、Bさんには見せない。」というような制御はできない。

    IP制限によるアクセス制御

    サポートに連絡することで可能

    証明書監視について

    SSL期限の監視などはできない。

    ニューレリックとの比較

    ニューレリックのメリット

    APMの設定が楽、agentいれてトレーサー知れるだけでよい。

    ニューレリックのデメリット

    ニューレリックはコミュニティーベースのサポートになる
    agentがオープンソースではないので、トラブルシュートが難しい。
    logやAPMを統合させようとするとニューレリックインサイトというのを買わないといけない。
    監視の設定がやや複雑。

    stackdriverとの比較

    stackdriverのメリット

    BigQueryとの連携が強い(Googleなので)

    stackdriverのデメリット

    cloudwatch同様の使い方
    2018年9月くらいから料金が高くなった

  • ERROR 1396 (HY000): Operation DROP USER failed for

    ERROR 1396 (HY000): Operation DROP USER failed for

    はじめに

    mysqlのuser登録でhostを制限したいということはよくある。

    その際よく使うワイルドカードは%(パーセント)だ。

    しかし、うっかり/(スラッシュ)16のようにネットワークアドレスをそのまま入れてしまった際の対処を紹介。

    現在の状況

    思いっきり/16で登録してしまった

    +-----------------+----------------+
    | user            | host           |
    +-----------------+----------------+
    | root            | %              |
    | sample          | 172.40.0.0/16  |
    +-----------------+----------------+

    あるべき姿はこちら

    +-----------------+----------------+
    | user            | host           |
    +-----------------+----------------+
    | root            | %              |
    | sample          | 172.40.%       |
    +-----------------+----------------+

     

    普通に消そうとおもったら、

    “` ERROR 1396 (HY000): Operation DROP USER failed for “`

    というエラーになってしまった。

    mysql> DROP USER  ‘sample’@"172.40.0.0/16";
    ERROR 1396 (HY000): Operation DROP USER failed for '‘sample’'@'172.40.0.0/16'

    対処

    バッククォートで囲んでコマンドを実行する

    mysql> DROP USER `sample`@`172.40.0.0/16`;
    Query OK, 0 rows affected (0.00 sec)

    地味にハマるので注意。

     

  • sftpサーバを構築する

    sftpサーバを構築する

    はじめに

    sftpサーバを立てる手順を明記する。

    権限まわりがシビアなのでハマるのできちんと整理する

    前提

    ftpuserというユーザーを作り、uploadというディレクトリに対してファイルを置く設定とする。

    設定

    usermod -aG sftp ftpuser
    
    ls -l/home/ftpuser/upload/
    chmod 750 /home/ftpuser/upload
    
    sshd -t
    service sshd reload
    
    vi /etc/ssh/sshd_config 

    sshd_configは以下の通り

    HostKey /etc/ssh/ssh_host_rsa_key
    HostKey /etc/ssh/ssh_host_ecdsa_key
    HostKey /etc/ssh/ssh_host_ed25519_key
    SyslogFacility AUTHPRIV
    PermitRootLogin no
    PubkeyAuthentication yes
    AuthorizedKeysFile .ssh/authorized_keys
    PasswordAuthentication no
    ChallengeResponseAuthentication no
    UsePAM yes
    X11Forwarding yes
    PrintLastLog yes
    UsePrivilegeSeparation sandbox
    AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
    AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
    AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
    AcceptEnv XMODIFIERS
    Subsystem sftp internal-sftp
    Match group sftp
        #ChrootDirectory /home/ftpuser/upload
        ChrootDirectory /home/ftpuser
        ForceCommand internal-sftp

    権限を適切にすること

     

    # ls -ld /home/ftpuser/
    drwxr-xr-x 4 root root 4096 May 29 15:29 /home/ftpuser/
    
    # ls -ld /home/ftpuser/upload/
    drwxr-x--- 2 ftpuser ftpuser 4096 May 29 16:00 /home/ftpuser/upload/
    

    上記権限になっていないと、以下のような権限エラーになることがある

    Permission denied (publickey).
    This service allows sftp connections only.

    /var/log/secureには以下のような記載がある

    fatal: bad ownership or modes for chroot directory "/home/ftpuser" [postauth]
    pam_unix(sshd:session): session closed for user ftpuser
    

    ftpの場合(おまけ)

    Comment Edit
    yum install vsftpd -y
    
    cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.org
    
    Elastic_IP=`curl http://169.254.169.254/latest/meta-data/public-ipv4`
    
    cat << EOF >> /etc/vsftpd/vsftpd.conf
    pasv_enable=YES
    pasv_addr_resolve=YES
    pasv_address=${Elastic_IP}
    pasv_min_port=60001
    pasv_max_port=60010
    use_localtime=YES
    force_dot_files=YES
    EOF
    
    sed -i -e "/^anonymous_enable/s/YES/NO/g" /etc/vsftpd/vsftpd.conf
    sed -i -e "/^dirmessage_enable/s/YES/NO/g" /etc/vsftpd/vsftpd.conf
    sed -i -e "/^#ascii_upload_enable/s/#//g" /etc/vsftpd/vsftpd.conf
    sed -i -e "/^#ascii_download_enable/s/#//g" /etc/vsftpd/vsftpd.conf
    sed -i -e "/^#chroot_local_user/s/#//g" /etc/vsftpd/vsftpd.conf
    sed -i -e "/^#chroot_list_enable/s/#//g" /etc/vsftpd/vsftpd.conf
    sed -i -e "/^tcp_wrappers/s/YES/NO/g" /etc/vsftpd/vsftpd.conf
    sed -i -e "/^connect_from_port_20/s/YES/NO/g" /etc/vsftpd/vsftpd.conf
    sed -i -e "/^xferlog_std_format/s/YES/NO/g" /etc/vsftpd/vsftpd.conf
    echo "user_config_dir=/etc/vsftpd/user_conf" >> /etc/vsftpd/vsftpd.conf
    echo "ftpuser" > /etc/vsftpd/chroot_list
    
    service vsftpd start
    chkconfig vsftpd on
    
    sudo su
    useradd ftpuser
    passwd ftpuser

    上記手順をコピペで。