20220110のRubyに関する記事は16件です。

変数の後ろにカンマがついている

変数の後ろにカンマがついている問題があったので備忘録として記しておきます main.rb #変数の後ろにカンマを付ける a, = (1..5).partition(&:odd?) p a => [1, 3, 5] #カンマを付けない b = (1..5).partition(&:odd?) p b => [[1, 3, 5], [2, 4]] カンマを後ろに付けることで多重代入になる。今回の問題でいうとカンマを付けることで2個目の変数の枠が用意されるが2個目の変数を宣言していないことによって[2, 4]の配列がなくなり、[1, 3, 5]が表示される。 partitionメソッドは指定した条件に一致するか否かで配列を分割します。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby】二重ハッシュ

※初心者向け ※アウトプット練習の為 開発環境 rails 6.1.4.1 ruby 2.6.5 問題内容 配列の内部に、複数のユーザーの情報をハッシュとして持つ変数user_dataがあります。 user_data = [ {user: {profile: {name: 'George'}}}, {user: {profile: {name: 'Alice'}}}, {user: {profile: {name: 'Taro'}}}, ] user_dataを利用して、全てのユーザーの名前だけが出力されるようにRubyでコーディングしてください。 ただし、出力結果は次のようになるものとします。 George Alice Taro 解答 user_data.each do |u| puts u[:user][:profile][:name] end あるいは user_data.each{ |u| puts u.dig(:user, :profile, :name) } 解説 ハッシュから特定の値を取得する場合は、その値に対応するキーを指定します。以下の書き方で取得ができます。 ハッシュ[取得したい値のキー] また、二重ハッシュから特定の値を取得する場合は、取得したい値のキーまで連続して指定すると取得できます。 ハッシュ[取得したい値のキー][取得したい値のキー] 今回取得したい値は、George, Alice, Taroという値です。 よって、取得したい値に対応するキーはnameというキーだということが分かります。 そのため、nameというキーまで連続して指定すると、George, Alice, Taroという値を取得できます。 ハッシュ[:user][:profile][:name] また、今回は配列の中にハッシュが格納されています。 そのため、each文でハッシュの1つ1つを取り出した上で、上記の記述を行うことが必要です。 user_data.each do |u| puts u[:user][:profile][:name] end 発展的な別解として、digメソッドを用いても取得できます。digメソッドはRubyに標準で組み込まれているメソッドで、多重階層にあるハッシュの値をまとめて取得できます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ローカルリポジトリからインストールした際、Ruby関連ファイルのみ「モジュールメタデータは利用不可です」と表示された件

オフライン環境のRHEL8.4にパッケージ導入時したときの話。 環境 OS:RHEL8.4 オンライン環境:Aサーバ オフライン環境:Bサーバ ※ともにGUIインストールしただけの状態。 初めに AサーバにてRPMパッケージを、Ruby含めざっくり90ファイルほどダウンロードしてローカルレポジトリを作成。 作成したリポジトリをzip圧縮してBサーバに展開。 /etc/yum.repos.d/にrepoファイルを作成後、dnf repolistに登録がある事を確認。 ターミナルから下記コマンドを実行 dnf --disablerepo=* --enablerepo=***_repo install [パッケージ名] 下記のようなエラーが出でました。 ※見やすいようにエラーMSGは成形してます。 モジュラーパッケージ 'ruby-2.5.9-107.module+el8.4.0+10822+fe4fffb1.x86_64' のモジュラーメタデータは利用不可です モジュラーパッケージ 'ruby-irb-2.5.9-107.module+el8.4.0+10822+fe4fffb1.noarch' のモジュラーメタデータは利用不です モジュラーパッケージ 'ruby-libs-2.5.9-107.module+el8.4.0+10822+fe4fffb1.x86_64' のモジュラーメタデータは利用不可です モジュラーパッケージ 'rubygem-bigdecimal-1.3.4-107.module+el8.4.0+10822+fe4fffb1.x86_64' のモジュラーメタデータは利用不可です モジュラーパッケージ 'rubygem-did_you_mean-1.2.0-107.module+el8.4.0+10822+fe4fffb1.noarch' のモジュラーメタデー モジュラーパッケージ 'rubygem-io-console-0.4.6-107.module+el8.4.0+10822+fe4fffb1.x86_64' のモジュラーメタデータはデータは利用不可です モジュラーパッケージ 'rubygem-json-2.1.0-107.module+el8.4.0+10822+fe4fffb1.x86_64' のモジュラーメタデータは利用不可です モジュラーパッケージ 'rubygem-openssl-2.1.2-107.module+el8.4.0+10822+fe4fffb1.x86_64' のモジュラーメタデータは利用不可です モジュラーパッケージ 'rubygem-psych-3.0.2-107.module+el8.4.0+10822+fe4fffb1.x86_64' のモジュラーメタデータは利用不可です モジュラーパッケージ 'rubygem-rdoc-6.0.1.1-107.module+el8.4.0+10822+fe4fffb1.noarch' のモジュラーメタデータはデータは利用不可です モジュラーパッケージ 'rubygems-2.7.6.3-107.module+el8.4.0+10822+fe4fffb1.noarch' のモジュラーメタデータは利用不可です 原因 RHEL8のmodule管理にメタデータが含まれていて、リポジトリ作成時にはひと手間かかる、メタデータはYAML形式のファイルで作成される。また主にRuby関連ファイルのみメッセージが発生している。 参考サイト 調べたところ ruby-2.5.9-107はRHEL8.4でデフォルトインストールされるバージョンと判明、 そのほかのRuby関連ファイルもインストール時に一緒に導入されるものとわかる。 なぜRubyのみエラーとなるのかまでは調べておりません。 どなたか教えてくださいませ。。。 調査時に利用したコマンド dnf module list ruby dnf module install ruby:2.5/common そこで ruby関連ファイルでエラーとなっているので先にRubyをインストールし、後にパッケージ関連をインストールする作戦に変更 実際にはAサーバで下記手順を実行 Aサーバ作業 dnf install modulemd-tools mkdir -p ruby_repo/Packages cd /usr/local/src/ruby_repo/Packages dnf download --resolve ruby cd .. ls Packages #Packagesフォルダがある階層でcreaterepo_cを実行 createrepo_c . #メタデータ作成 repo2module -s stable . modules.yaml modules.yamlに追記 data: arch: x86_64 profiles: default: description: ruby package #modules.yamlの情報をrepodataに追加 modifyrepo_c --mdtype=modules modules.yaml repodata/ ls repodata/ | grep modules →*****modules.yaml.gzファイルがあることを確認する あとはレポジトリのフォルダをzip圧縮。zipファイルをBサーバの適切なフォルダに持っていきunzip. Bサーバ作業 /etc/yum.repos.d/ruby_repo.repoファイルを作成 vim /etc/yum.repos.d/ruby_repo.repo [ruby_repo] name=RubyRepo baseurl=file:///usr/local/src/ruby_repo enabled=1 gpgcheck=0 dnf repolistを実行してrepolistに表示があることを確認 #レポジトリを指定してインストール dnf --disablerepo=* --enablerepo=ha_repo install ruby 無事にインストールできました。 パッケージも同じ手順にてインストールできました。 感想 冷静に考えれば。。。。 パッケージはGUIの画面があって、GUIにRubyを利用しているのね。。。 今後は言語とパッケージは別々にインストールです。 まぜるな危険!です。 これだけの事ですが、3日ほど悩みました。 だれかの参考になれば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsで複数レコードを更新する書き方メモ

はじめに Railsで複数レコードを作成、更新する際にActiveRecord::Base.transactionをどのように用いるかを調べた際のメモです。 主に以下を参考にさせていただきました。 https://qiita.com/aba0312/items/8b29cafe6b505b6a7a4f https://www.youtube.com/watch?v=jFBvEQhApKQ 例 例えば、ユーザーのバルクインサートを行う際に全てのインサートが成功しなければロールバックするという想定をします。 User.rb class User < ApplicationRecord def self.bulk_create(users) all_valid = true transaction(join_table: false, requires_new: true) do users.each do |user| # 何らかの処理 all_valid &= user.save end unless all_valid raise ActiveRecord::Rollback end end all_valid end end transactionの引数である、join_tableやrequires_newはこちらを参考にしました。 https://qiita.com/jnchito/items/930575c18679a5dbe1a0 この書き方をすることによって、システムエラー(プログラムのバグにより起こるエラー)が起きればその時点でロールバックがされますし、業務エラー(ユーザーの操作によるエラー)が起きればRollbacを明示的にするようにしています。 users_controller.rb class UsersController < ApplicationContoller def create if User.bulk_create(@users) redirect_to :index else # エラー通知 render :new end end end おわりに おかしい部分があるかもしれません。ご指摘あればよろしくお願い致します。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby &=

# +=や*=と同様に考えれば&演算子の意味がわかれば理解できる foo &= bar # これは foo = foo & bar を意味する &演算子 積集合を意味する # Arrayの積集合 [1, 1, 2, 3] & [3, 1, 4] => [1, 3] # TrueClass, FalseClassにも利用できる true & true => true true & false => false false & false => false nil & true => false nil & false => false
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】form_withとは?

form_withとは? form_withは、htmlのformタグを生成するためのメソッド。 どうなるの? 「生成する」というのは少し難しい表現ですが、「置き換わる」と考えても問題ありません。 つまり、form_withのところに、<form action=~というhtmlのタグが置き換わります。 へー!すごいね! このようにhtmlを生成するメソッドをビューヘルパーと呼んでいます。 ちなみに... ・link_toとは:<a href=~というaタグに置き換わる。ビューヘルパーの一つです。 ・f.number_fieldとは:inputタグに置き換わる。ビューヘルパーの一つです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby attr_reader, attr_writer, attr_accessorについて

結論 attr_readerを用いるとアトリビュートを読み取るメソッドが定義される。 attr_writerを用いるとアトリビュートを書き込むメソッドが定義される。 attr_accessorを用いるとアトリビュートを読み取るメソッドと書き込むメソッドの両方が定義される。 公式リファレンス attr_reader https://docs.ruby-lang.org/ja/latest/method/Module/i/attr_reader.html attr_writer https://docs.ruby-lang.org/ja/latest/method/Module/i/attr_writer.html attr_accessor https://docs.ruby-lang.org/ja/latest/method/Module/i/attr_accessor.html attr_reader class User attr_reader :id, :name def initialize(id, name) @id = id @name = name end end この表記で以下のメソッドが定義されます。 def id @id end def name @name end これによりインスタンスを作成した後、アトリビュートを以下のように読み取ることができます。 user = User.new(1, 'kot') => #<User:0x00007fd644997218 @name="kot", @id=1> user.id => 1 user.name => "kot" attr_writer class User attr_writer :id, :name def initialize(id, name) @id = id @name = name end end この表記で以下のメソッドが定義されます。 def id=(id) @id = id end def name=(name) @name = name end これによりインスタンスを作成した後、アトリビュートを書き込むことができます。 user = User.new(1, 'kot') => #<User:0x00007fa0678aaea8 @id=1, @name="kot"> user.name = 'kotkot' => "kotkot" 読み取りはできないので以下のように両者(attr_reader, attr_writer)を表記することで読み取りと書き込みができるようになります。 class User attr_reader :id, :name attr_writer :id, :name def initialize(id, name) @id = id @name = name end end user = User.new(1, 'kot') => #<User:0x00007fa0678aaea8 @id=1, @name="kot"> user.name => "kot" user.name = 'kotkot' => "kotkot" attr_accessor attr_readerやattr_writerを記述するだけで以下のように簡単にメソッドが定義されます。 def hoge @hoge end def hoge=(hoge) @hoge = hoge end しかし両方を用いること場合にはattr_accessorを用いることでさらに簡単にメソッド定義できます。 class User attr_accessor :id, :name def initialize(id, name) @id = id @name = name end end 補足 各アトリビュートの読み取りメソッドが定義されるので以下のようにnameメソッドを他のメソッド内で用いることもできます。 class User attr_accessor :name def initialize(name) @name = name end def greet "Hello #{name}" end end user = User.new('kot') => #<User:0x00007fa0648e9d18 @name="kot"> user.greet => "Hello kot" おわりに 学び始めたときはなんとなくで書いていましたが、それぞれのメソッドが何をしているのかを公式リファレンス見ながら一つずつ理解することが定着への近道だと改めて感じました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails memberとcollectionの違い

結論 memberを用いることでidを用いて特定のリソースに対してアクションを実行することができ、collectionを用いることで全てのリソースに対してアクションを実行することができる。 公式API member https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Resources.html#method-i-member collection https://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Resources.html#method-i-collection member routes.rb resources :users do member do get :hoge end end memberを使うとルーティングは以下のようになります。 idを指定することができるので特定のUserに対してhogeアクションを行いたい場合に用いることができます。 collection routes.rb resources :users do collection do get :piyo end end collectionを用いるとルーティングは以下のようになります。 memberを用いた場合とは異なり、idを指定しないので全てのUserに対してpiyoアクションを行いたい場合に用いることができます。 おわりに 特定のリソースに対してアクションを実行するか、全てのリソースに対してアクションを実行するかによってmemberとcollectionを使い分けることが必要です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Ruby]Stringクラスのsliceメソッド

学習したことのアウトプットとして sliceメソッド rubyの組み込みライブラリ 配列や文字列から指定した要素を取り出すことができるメソッド 取り出したとしても、配列や文字列はもとのまま 例) # 配列を作成します array = [0,1,2,3,4,5,6] # 配列から引数で指定した要素を取得します ele1 = array.slice(1) puts ele1 #=> 1 # 配列番号-4から4つ分の要素をsliceします ele2 = array.slice(-4,4) puts ele2 #=> 3, 4, 5, 6 # 配列はもとのままです puts array #=> [0,1,2,3,4,5,6] slice!(破壊的メソッド)だとオブジェクト自身の内容は変更される 例) string = "this is a string" string.slice!(2) #=> "i" string.slice!(3..6) #=> " is " string.slice!(/s.*t/) #=> "sa st" string.slice!("r") #=> "r" string #=> "thing" ※補足等ありましたらコメントいただけると幸いです
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】ajax化とは

ajax化とは Asynchronous JavaScript + XML の略で、非同期通信と呼ばれる通信方法のこと。 Webブラウザ上で非同期通信を行い、ページ全体の再読み込み無しにページを更新する。 同期通信、非同期通信とは? ◆同期通信 クライアントとサーバー間の通信においては、通常、同期通信と呼ばれる方法が用いられ、一瞬画面が白くなった後、画面が切り替わるような通信は、全てこの同期通信となる。 ページが一瞬真っ白になってから表示されるまでの間は、ユーザーは他の操作を何もする事が出来ない。また、同期通信はページ全体を1から作成して表示させているので、どうしても表示までの時間がかかる。 ◆非同期通信 一方、非同期通信では、クライアントからのリクエスト送信後、サーバーの処理中にも、ページ遷移無しに他の作業を行うことができる。 Railsにおけるajax化の方法 非同期通信の方法は2種類あり、 ①remote:true形式 ②ajax関数を使った形式 の2パターンが存在するが、今回はremote:true形式を記載。 例として、掲示板のお気に入り(いいね)ボタンを押した時に、お気に入りの登録、解除を行うという仕組みをajax化していく。 1.コントローラーの設定 redirect先の指定をコメントアウト。 bookmarks_controller.rb class BookmarksController < ApplicationController def create @board = Board.find(params[:board_id]) current_user.bookmark(@board) # redirect_back fallback_location: root_path,success: t('user_sessions.boards.bookmarks.create.success') end def destroy @board = current_user.bookmarks.find(params[:id]).board current_user.unbookmark(@board) # redirect_back fallback_location: root_path,success: t('user_sessions.boards.bookmarks.destroy.success') end end 2.ブックマークボタンをajax化 ブックマークボタンのコードを記載している app/views/boards/_bookmark.html.erb app/views/boards/_unbookmark.html.erb この2つのコード内の<%= link_to ~ %>にremote: trueを追加。 remote: trueを指定することによって、AjaxでHTTPリクエストを送信するように設定される。 更に、html.erbファイルではなくjs.erbファイルをレンダリングしてくれる。 3.ブックマークボタンの切り替え処理を追加 指定したid属性を持つ部分を置き換える。それぞれブックマーク登録・解除に置き換えるよう記述。 $(置換対象).replaceWith(置換後の要素) replaceWithは要素を置換するメソッド。 app/views/bookmarks/create.js.erb $("#js-bookmark-button-for-board-<%= @board.id %>").replaceWith("<%= j(render('bookmarks/unbookmark', board: @board)) %>"); app/views/bookmarks/destroy.js.erb $("#js-bookmark-button-for-board-<%= @board.id %>").replaceWith("<%= j(render('bookmarks/bookmark', board: @board)) %>"); 参考記事 ⭐️ブックマークボタンのajax化 【Rails】remote:true形式でAjax通信を行う(お気に入り登録機能のajax化) 【IT用語】 Ajaxとは?初心者向けに豊富な画像で仕組みを解説
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

インフラ素人が3週間で、Webサービスのインフラを0から構築して起きた変化

目次 1. インフラ設計 2. ネットワーク構築 3. サーバ・DB構築 4. Lambdaによる自動化 5. Amazon SES・SNS 6. 開発環境構築(docker) 7. jenkins・phpmyadminなど開発ツール設定 8. VPN接続 9. 起きた変化 10. おまけ はじめに インフラ素人同然レベルだった私が実務において、Webアプリケーションのインフラを0から構築することになりました。 期間は約3週間、インフラ設計から行い、構築したインフラ上でWebサービスが稼働できる状態まで持っていくことがゴールになります。  約3週間の間、AWSやミドルウェア周りの技術に触れ、今まで考えてもみなかった知識の習得や、多くのつまづきを通して貴重な経験をすることができました。 チームメンバーと分担しながら進めたので、あくまで自分のやったことベースにはなりますが、3週間どんなことをやったのか、特につまづいたことを中心に書いていきたいと思います。 ※基本的なインフラ構成はほぼ全てAWSのリソースを使用しました。 【使用技術】 ・ AWS(EC2, RDS, VPC, Route53, Lambda, IAM, SES, SNS, ACM, CloudWatch, etc.) ・ docker ・ Nginx(Webサーバ) ・ Puma(アプリケーションサーバ) ・ Ruby on Rails 開始前の筆者のレベルを3行で! ・自社開発エンジニア歴5ヶ月の駆け出しエンジニア ・AWS Cloud Practitionerの資格は持っているが実務でのインフラ(AWS)経験は無し ・ミドルウェア周りの知識はほぼゼロ(Webサーバとアプリケーションサーバってどう違うの?レベル) 1. インフラ設計 まずやったこととして、Webサービスを稼働させる上でどのようなインフラ環境が必要か理解し、可視化することです。 今回、実装するのは、Web開発では基本となる開発環境(development)、ステージング環境(staging)、本番環境(production)からなる構成です。 なんとなくの理解だったので、各環境の役割について、改めて理解するのに良い記事があったので共有します。 事前学習 とはいっても、 VPCってなんぞや? サブネットの切り方ってどうするの? NATゲートウェイとは? ALBとロードバランサーなにが違うの? など、私にとってネットワーク設計やサーバ構築が初めての経験だったので、知識の習得のため最初の数日はとにかくインプット量を意識して手を動かしながら学習しました。 VPC構築、サブネットの設定、EC2構築など実際にAWSマネジメントコンソール上でポチポチやりながら、「こことここが繋がるのか〜」「こうすれば良いのね」といった感じで、体系的にAWSのリソースを理解しながら、知識を蓄えていったところが大きいです。 一部、以下AWSCloudTechのサービスを使ったりなんかもしました。 実装するインフラ構成を図に落とし込む 理解が少し曖昧なところがありながらもなんとか、今回実装するインフラ構成を図に落とし込みました。 ここまででおおよそ3日です。 Webサーバはアクセスを考慮して、現時点では冗長構成にせず単一のインスタンスのみで運用を行い、batchサーバの役割も持たせます。 本番環境では、バウンスメール等はSES,SNSを使用し、通知を行いレートの管理をします。 他ネットワークからのアクセスも可能にするため、AWSClientVPNを使用したVPN接続も実装する予定です。 Excelにインフラ設計情報の詳細をドキュメント化 インフラ設計情報として、開発する上で必要になってくる細かな設定に関しては、都度Excelに記載し、後ほど忘れないためにドキュメント化し管理しました。 ・RDSの詳細設定 ・各インスタンスの詳細設定 ・pemキー情報、IAM情報、各種ログイン情報  ・ssh接続コマンドチートシート などなど 2. ネットワーク構築  ここから実際に手を動かしていきます。上記インフラ構成を実現するためにまずは、サーバを設置する箱となるネットワークの構築(VPC)から始めました。 ざっくり手順は以下のとおり実現しました。 1.VPC設定 2.VPC内にサブネット構築 3.インターネットゲートウェイの設置 4.NATゲートウェイの設置 5.VPC間のピアリング接続の設定 6.サブネットのルートテーブルの設定 具体的な設定についてここでは詳細省きますが、これでおおよそ必要なるネットワーク構成は出来あがります。 1つ注意点として、 VPCやサブネットを作成する際のIPv4CIDRブロックは、以下のプライベートIPアドレスの範囲内で作成する必要があります。 プライベートアドレスは以下のように範囲が定められており、この範囲外のIPアドレスはグローバルアドレスとなってしまうからです。 クラス 範囲 ネットワーク数 クラスA 10.0.0.0 ~ 10.255.255.255 (10.0.0.0/8) 1 クラスB 172.16.0.0 ~ 172.31.255.255 (172.16.0.0/12) 16 クラスC 192.168.0.0 ~ 192.168.255.255 (192.168.0.0/16) 256 パブリックサブネットとプラベートサブネット 自分も勉強していく中で、パブリックサブネットとプライベートサブネットってどう違うのと疑問に思っていました。 サブネット作成のコンソール画面でもパブリック/プライベートの選択などなかったはずです。 【結論】 サブネットのルートテーブルの記述内容で変わる パブリックサブネット すべてのIPアドレス宛のターゲットがインターネットゲートウェイに向いているもの。 送信先 ターゲット 0.0.0.0/0 インターネットゲートウェイ  プライベートサブネット すべてのIPアドレス宛のターゲットがNATゲートウェイに向いているもの。 プライベートサブネットがインターネットと通信するためには、NATゲートウェイのルートテーブルに0.0.0.0/0がインターネットゲートウェイに向かうように設定する必要があります。 送信先 ターゲット 0.0.0.0/0 NATゲートウェイ  3. サーバ・DB構築  サブネット内に必要となるEC2インスタンス、またはRDSを作成していきます。 (EC2,RDSの詳細な作成設定については記述を省略します) パブリックサブネットに配置するインスタンスには、インターネットに接続するため、ElasticIPを関連づける必要があります。 パブリックサブネットに配置したインスタンスは通常、パブリックIPv4アドレスが割り当てられます。 しかし、これだとインスタンスの起動停止のたびに毎回IPアドレスが変わってしまいます。 それでは大変なので、EIPを取得し、インスタンスと関連づけることでEIPを固定のパブリックIPアドレスとして使用することができます。 EC2インスタンス作成とNginxインストール 必要となるEC2インスタンスを作成します。 アプリケーションを動かすインスタンスには、RailsアプリケーションサーバであるPumaと通信するためのWebサーバ(Nginx)を事前にインストールします。 アプリケーションデプロイ後には、NginxとPumaを通信させる必要があります。 EIPの上限はデフォルトだと5個な話 インスタンスにEIPを割り当てるときに、画像のようなエラーがでてきました。 これはEIPの数が制限に達したという警告です。 EIPは、サポートプランにも寄りますが、Developerプランではデフォルトでは5個までしか使用できません。(デフォルトVPC内に2つ使用されているので、実質3個) 5個以上使用する場合には、Service Quatasのダッシュボードから申請を行う必要があります。 https://ap-northeast-1.console.aws.amazon.com/servicequotas なお、一気に20個とか申請すると、「申請する理由を詳しく教えてください」などとAWS側から怒られてしまうので、まずは5個ぐらいから始めると良いと思います。(※申請は全て英語です) 私は、デフォルトVPCに関連づいているEIP2個を外したのと、追加申請5個で足りました。 RDSのフェイルオーバー設定 RDSを作成していきます。 RDSの詳細設定に関しては、各自RDS使用用途によって異なるかと思うので、詳細は省きます。 障害時にはRDSを他AZで起動させるフェイルオーバーをさせる必要があります。 RDSのダッシュボードからサブネットグループの作成を行い、フェイルオーバーす先となるAZをグルーピングします。 フェイルオーバーの確認については、以下記事を参考にテストしてみました。 EC2-RDS間の疎通確認 アプリケーションが動く、EC2インスタンスからRDSへ接続ができることを確認します。 RDSのエンジンとしてMySQLを選択していた場合、EC2インスタンス上で以下コマンドでRDS内のMySQLと接続ができます。 RDSに設定しているセキュリグループのインバウンドルールに接続元EC2からのMySQL通信(3306番ポート)の許可を忘れずに! 接続元ec2 $ mysql -u マスターユーザー名 -pパスワード -h エンドポイント マスターユーザー名,パスワードは、それぞれRDS作成時に決定したものです。エンドポイントはRDS作成後に確認できます。 ALBの使用 一台のEC2ならロードバランサーは使用しなくても良いのでは思ったのですが、単なる負荷分散以外の機能もAWSのロードバランサーは提供してくれるので、そちらのメリットを加味してALBを使用します。 またALBには、Amazon Certificate Manager(ACM)からSSL証明書を取得し、HTTPSでの通信を設定します 4. Lambdaによる自動化 Lambda,EventBridge, CloudWatch, AWSChatBot, SNS このあたりのサービスを使用して開発する上で管理しやすくなる自動化を行いました。 Lambda✖︎EventBridgeによるEC2インスタンス起動・停止の自動化 開発ツール系のインスタンスや使用頻度の高いインスタンスについは起動・停止を自動化すると便利です。 ↓記事を参考に、実装しました。 環境ごとのEC2・RDSの停止忘れ防止 staging環境、production環境(運用開始まで)に属するインスタンス、RDSについては毎日↑のLambdaの停止スクリプトのみを実行し、停止忘れ防止策をこうじました。 AWS ChatbotによるSlack通知 Lambdaの実行結果は、CloudWatchLogsに蓄積されます。 インスタンスの停止スクリプトなどはエラー通知を即座に把握したいため、実務のコミュニケーションツールとして使用しているSlackに通知するように設定しました。 すごく便利!! 5. Amazon SES,SNS  本番環境や開発環境において、AWSからメールを送信するにはAmazon SimpleEmailService(SES)を使用します。 ここでもざっくりと手順を説明すると以下になります。 1.メール送信権限付きIAMユーザー作成後、アクセスキーを取得 2.Railsアプリコード内の ~アプリ名/config/environments/development.rb, staging.rb, production.rb配下にアクセスキーを記載 3.SESでドメイン、メールアドレスの認証 4.認証したドメイン・アドレスからのメール送信の確認 5.SNSでメール通知設定 メール送信権限付きユーザーのアクセスキーを取得 メール送信権限を持つIAMユーザーを作成します。(既存のユーザーでも大丈夫です) アタッチするポリシーは、AmazonSesSendingAccessというデフォルトポリシーがあるのでそれをユーザーにアタッチすれば大丈夫です。 AmazonSesSendingAccess { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "ses:SendRawEmail", "Resource": "*" } ] } テストメール送信 ドメイン・メールアドレスの認証を行います。 認証からテストメールの送信の仕方までは↓記事が参考になります。 ※ドメインに関しては、Route53のほうで事前に認証済みのドメインでないとSES上で認証されないので注意が必要です。(経験あり?) バウンスメールのテストについては、上記テストメールの送信先をbounce@simulator.amazonses.comに設定してあげると、バウンスレートを上げることなくバウンスメールのテストを行なってくれます。 その他、通常の成功メールや苦情メールも同様で↓に記載のテスト用アドレスを使用するとレートとは無関係にテストができます。 バウンスメール・苦情メール等については、SNSとSESを連携させて通知設定を行います。 これも↓記事が参考になるので、簡単に設定できます。 ここまでだいたい2週間ぐらいでした。 6. 開発環境構築(docker)  ローカルの開発環境と検証用のdevelopment環境はdockerで構築を行いました。 Dockerfile, docker-compose.ymlを作成し、シェルスクリプトとして開発環境構築用のスクリプトを用意しました。 このスクリプトを叩くだけで、dockerでの開発環境ができあがります。 合わせて、初期データとして必要なrakeタスクも実装しました。 ざっと内容を紹介 setup.sh #!/bin/bash # 作業用ディレクトリ作成 if [ ! -d ./workspace ]; then mkdir workspace fi # 作業用dir配下にプロジェクトをclone git clone git@~~ # キャッシュを使用せず、imageをbuild docker-compose build --no-cache # 必要な初期rakeタスクを流す docker-compose run web bundle exec rake rakeタスク # 停止済みのコンテナを削除 docker container prune -f ridgepole導入時にハマったこと 今回、アプリケーションはmigrationファイルでの管理ではなくridgepoleを使用します。 私自身初めてのridgepole導入だったので少し苦戦しました。 後ほどridgepole導入時にハマったことは詳細をQiitaに投稿しようと思っています。 ridgepoleとは↓・・・ 7. jenkins・phpmyadminなど開発ツール設定  開発ツール用のインスタンスにjenkins, phpmyadminをそれぞれインストールします。 それぞれのインスタンスには、EC2FullAccessなどのポリシーを持ったアクセスキーを配置する必要があります。 jenkinsインスタンス # 認証情報を設定 $ aws configure # 4つ聞かれるのでそれぞれ入力 1. アクセスキー 2. パスワード 3. region 4. output形式 # この配下に認証情報(アクセスキー等がある) $ cd ~/.aws $ ls -la => config, credentials jenkinsのジョブが失敗する アクセスキーの設置が終わり、jenkinsのジョブを作成し実行たところ、エラーになりました。。。 jenkisnのコンソール出力を見ると以下のようなエラーメッセージが unable to locate credentials. you can configure credentials by running "aws configure". おいおい、アクセスキーはちゃんと配置したはずだぞ? 設定を確認してもきちんと登録されているはず・・・ # アクセスキー設定情報を確認 aws configure list => aws_access_key_id = ***************** => aws_secret_access_key = ***************** 【結論】 jenkinsのジョブを実行しているのは、ec2の中のjenkinsユーザー だからjenkinsユーザーに認証情報を設定してあげる必要がある(これまでは、ec2ユーザーとrootユーザーに設定していた) # rootユーザーになる $ sudo su # jenkinsユーザーになる $ su - jenkins # 認証情報が確認すると・・・なにも設定されていなかった $ aws configure list => aws_access_key_id => aws_secret_access_key # 再度認証情報を設定 $ aws configure 無事、ジョブが成功した! 余談ですが、画面上で作成したjenkinsのジョブはサーバ内jenkinsユーザーの以下に格納されているので、確認できます。 jenkinsインスタンス # rootユーザーになる sudo su # jenkinstユーザーになる su - jenkins cd workspace ls -la => 作成したjenkinsジョブ一覧が表示 8. VPN接続  別のネットワークから、この環境へのアクセスを可能にするためAWSClientVPNを使用し、VPN接続を試みます。 パブリックサブネット内のNATゲートウェイにアタッチしたEIPを固定IPアドレスとして、インターネットに接続できることをゴールとします。 ↓記事を参考にするとできるかと思います。 が、私がハマったことで一つ注意点! ClientVPVEndpointと関連づけるサブネットはプライベートサブネットでないといけない これに気づかず、数時間ハマりました。。。 また、VPN接続するときに作成されるENIは、接続のたびに新しいものが作成されます。 ENIに割り当てられるパブリックIPアドレスは接続のたびに毎回変わりますが、それをNATゲートウェイのEIPで固定化するというイメージです。 9. 起きた変化 以上作業を約3週間で行いました。 インフラにほとんど触ったことの無かった素人が3週間のインフラ構築を通して、どのような変化があったのか、技術的な側面と価値観・考え方の側面から感じたことを書いていきたいと思います。 技術面 【AWS】 ・AWSを使用して、迷わず基本的なアーキテクチャの設計ができるようになった ・AWS上のサービスをドキュメントを読むだけで使いこなせるようになった ・AWSリソースの管理能力が向上した 【docker】 ・dockerを使用して、開発環境の構築ができるようになった ・Dockerfile, docker-compose.ymlなど記述内容を理解し、自分の実装したいように改修できるようになった 【その他】 ・Webサーバやアプリケーションサーバのどのレイヤーに対してエラーが発生しているのか感覚的にわかるようになった ・ログを見る習慣/ログからエラーの原因を特定する力がついた ・Linuxサーバ内のディレクトリ構造や必要ファイルなどが把握し、行いたい修正を加えられるようになった ・Webの3層構造を体系的に理解することができた ざっとこんな感じになります。 特に自分として変化を感じたことは、基本的なアーキテクチャ設計をする際のAWSリソースに対して「わからない・これどうやるんだ」という感情がなくなったことです。 今までは、事前知識としてなかったのはもちろんですがどこかAWSを気軽に触れないものだと思っていました。 ですが、毎日AWSを触りながら理解していくことで、AWSに対するハードルが低くなっていくのを強く感じました。 今では、初めて使用するAWS上のサービスでも「まずは触ってみる」ということを大切にし、ドキュメントや参考記事を読めばだいたいのことはなんとかなるようになったと思います。 わずか3週間ですが、自分のエンジニアとしての知識・技術が3週間前と比較し格段に上がったのを感じました! 価値観・考え方 インフラ構築を経験してみることで、インフラの楽しさを感じたのと同時に、改めて、AWSの素晴らしさに感動しました。 マネジメントコンソールをいじるだけでサーバ・ネットワークを作れたり、あらゆるサービスを連携することでできることの無限さを感じました。 インフラというのはどこか、モヤに隠れた分かりづらいものという意識があった中、自分で0から設計し図を書き、それを実際に構築するという経験のおかげで構造的にインフラを捉えられるようになりました。 AWSを理解するにはまず図を書いてみる とよく聞きますが、これは本当にそうだと思います。 図を書きながら、「これってどうやって通信する」「この部分にはどういう制御が必要なんじゃないか」と頭の中で考え、それを実際に手を動かしてみることで必要な処理や構成が感覚的に理解できるようになってきます。 この経験をきっかけとして、これからもインフラに関する知識・技術を勉強し、今後はSAA,さらにはその上のSAPの取得を目指していきたいと思います。 そして、実務としてこのような素晴らしい挑戦の機会をいただけたことに感謝し、これからも成長できるように頑張っていきたいと思います。 10. おまけ 約3週間インフラ構築をする上で、ミドルウェアの操作についてはコマンドラインが主となるので、自然とコマンドを使う機会が多くなりました。 そこで備忘録がてら、よく使用したコマンドを残していきたいと思います。 よく使ったコマンドたち ■ コマンド # ファイル削除 rm -rf ディレクトリ # 検索 grep -r 正規表現 # プロセス確認 ps aux | grep XXX # 環境変数確認 env ■ systemctl # start, stop, restart, statusなど # Nginxの起動状態確認 systemctl nginx status # MySQLの起動状態確認 systemctl mysql status ■ crontab # サーバの初期設定をするcrontabの内容確認 crontab -l ■ Git # 接続先のremoteリポジトリを確認 git remote -v # remoteリポジトリを設定 git remote set-url origin git@~~~ ■ ssh ssh -i ~/.ssh/キー.pem ec2-user@IPアドレス
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

インフラ素人が3週間でWebサービスのインフラを0から構築するためにやったこと

目次 1. インフラ設計 2. ネットワーク構築 3. サーバ・DB構築 4. Lambdaによる自動化 5. Amazon SES・SNS 6. 開発環境構築(docker) 7. jenkins・phpmyadminなど開発ツール設定 8. VPN接続 9. 起きた変化 10. おまけ はじめに インフラ素人同然レベルだった私が実務において、Webアプリケーションのインフラを0から構築することになりました。 期間は約3週間、インフラ設計から行い、構築したインフラ上でWebサービスが稼働できる状態まで持っていくことがゴールになります。  約3週間の間、AWSやミドルウェア周りの技術に触れ、今まで考えてもみなかった知識の習得や、多くのつまづきを通して貴重な経験をすることができました。 チームメンバーと分担しながら進めたので、あくまで自分のやったことベースにはなりますが、3週間どんなことをやったのか、特につまづいたことを中心に書いていきたいと思います。 ※基本的なインフラ構成はほぼ全てAWSのリソースを使用しました。 【使用技術】 ・ AWS(EC2, RDS, VPC, Route53, Lambda, IAM, SES, SNS, ACM, CloudWatch, etc.) ・ docker ・ Nginx(Webサーバ) ・ Puma(アプリケーションサーバ) ・ Ruby on Rails 開始前の筆者のレベルを3行で! ・自社開発エンジニア歴5ヶ月の駆け出しエンジニア ・AWS Cloud Practitionerの資格は持っているが実務でのインフラ(AWS)経験は無し ・ミドルウェア周りの知識はほぼゼロ(Webサーバとアプリケーションサーバってどう違うの?レベル) 1. インフラ設計 まずやったこととして、Webサービスを稼働させる上でどのようなインフラ環境が必要か理解し、可視化することです。 今回、実装するのは、Web開発では基本となる開発環境(development)、ステージング環境(staging)、本番環境(production)からなる構成です。 なんとなくの理解だったので、各環境の役割について、改めて理解するのに良い記事があったので共有します。 事前学習 とはいっても、 VPCってなんぞや? サブネットの切り方ってどうするの? NATゲートウェイとは? ALBとロードバランサーなにが違うの? など、私にとってネットワーク設計やサーバ構築が初めての経験だったので、知識の習得のため最初の数日はとにかくインプット量を意識して手を動かしながら学習しました。 VPC構築、サブネットの設定、EC2構築など実際にAWSマネジメントコンソール上でポチポチやりながら、「こことここが繋がるのか〜」「こうすれば良いのね」といった感じで、体系的にAWSのリソースを理解しながら、知識を蓄えていったところが大きいです。 一部、以下AWSCloudTechのサービスを使ったりなんかもしました。 実装するインフラ構成を図に落とし込む 理解が少し曖昧なところがありながらもなんとか、今回実装するインフラ構成を図に落とし込みました。 ここまででおおよそ3日です。 Webサーバはアクセスを考慮して、現時点では冗長構成にせず単一のインスタンスのみで運用を行い、batchサーバの役割も持たせます。 本番環境では、バウンスメール等はSES,SNSを使用し、通知を行いレートの管理をします。 他ネットワークからのアクセスも可能にするため、AWSClientVPNを使用したVPN接続も実装する予定です。 Excelにインフラ設計情報の詳細をドキュメント化 インフラ設計情報として、開発する上で必要になってくる細かな設定に関しては、都度Excelに記載し、後ほど忘れないためにドキュメント化し管理しました。 ・RDSの詳細設定 ・各インスタンスの詳細設定 ・pemキー情報、IAM情報、各種ログイン情報  ・ssh接続コマンドチートシート などなど 2. ネットワーク構築  ここから実際に手を動かしていきます。上記インフラ構成を実現するためにまずは、サーバを設置する箱となるネットワークの構築(VPC)から始めました。 ざっくり手順は以下のとおり実現しました。 1.VPC設定 2.VPC内にサブネット構築 3.インターネットゲートウェイの設置 4.NATゲートウェイの設置 5.VPC間のピアリング接続の設定 6.サブネットのルートテーブルの設定 具体的な設定についてここでは詳細省きますが、これでおおよそ必要なるネットワーク構成は出来あがります。 1つ注意点として、 VPCやサブネットを作成する際のIPv4CIDRブロックは、以下のプライベートIPアドレスの範囲内で作成する必要があります。 プライベートアドレスは以下のように範囲が定められており、この範囲外のIPアドレスはグローバルアドレスとなってしまうからです。 クラス 範囲 ネットワーク数 クラスA 10.0.0.0 ~ 10.255.255.255 (10.0.0.0/8) 1 クラスB 172.16.0.0 ~ 172.31.255.255 (172.16.0.0/12) 16 クラスC 192.168.0.0 ~ 192.168.255.255 (192.168.0.0/16) 256 パブリックサブネットとプラベートサブネット 自分も勉強していく中で、パブリックサブネットとプライベートサブネットってどう違うのと疑問に思っていました。 サブネット作成のコンソール画面でもパブリック/プライベートの選択などなかったはずです。 【結論】 サブネットのルートテーブルの記述内容で変わる パブリックサブネット すべてのIPアドレス宛のターゲットがインターネットゲートウェイに向いているもの。 送信先 ターゲット 0.0.0.0/0 インターネットゲートウェイ  プライベートサブネット すべてのIPアドレス宛のターゲットがNATゲートウェイに向いているもの。 プライベートサブネットがインターネットと通信するためには、NATゲートウェイのルートテーブルに0.0.0.0/0がインターネットゲートウェイに向かうように設定する必要があります。 送信先 ターゲット 0.0.0.0/0 NATゲートウェイ  3. サーバ・DB構築  サブネット内に必要となるEC2インスタンス、またはRDSを作成していきます。 (EC2,RDSの詳細な作成設定については記述を省略します) パブリックサブネットに配置するインスタンスには、インターネットに接続するため、ElasticIPを関連づける必要があります。 パブリックサブネットに配置したインスタンスは通常、パブリックIPv4アドレスが割り当てられます。 しかし、これだとインスタンスの起動停止のたびに毎回IPアドレスが変わってしまいます。 それでは大変なので、EIPを取得し、インスタンスと関連づけることでEIPを固定のパブリックIPアドレスとして使用することができます。 EC2インスタンス作成とNginxインストール 必要となるEC2インスタンスを作成します。 アプリケーションを動かすインスタンスには、RailsアプリケーションサーバであるPumaと通信するためのWebサーバ(Nginx)を事前にインストールします。 アプリケーションデプロイ後には、NginxとPumaを通信させる必要があります。 EIPの上限はデフォルトだと5個な話 インスタンスにEIPを割り当てるときに、画像のようなエラーがでてきました。 これはEIPの数が制限に達したという警告です。 EIPは、サポートプランにも寄りますが、Developerプランではデフォルトでは5個までしか使用できません。(デフォルトVPC内に2つ使用されているので、実質3個) 5個以上使用する場合には、Service Quatasのダッシュボードから申請を行う必要があります。 https://ap-northeast-1.console.aws.amazon.com/servicequotas なお、一気に20個とか申請すると、「申請する理由を詳しく教えてください」などとAWS側から怒られてしまうので、まずは5個ぐらいから始めると良いと思います。(※申請は全て英語です) 私は、デフォルトVPCに関連づいているEIP2個を外したのと、追加申請5個で足りました。 RDSのフェイルオーバー設定 RDSを作成していきます。 RDSの詳細設定に関しては、各自RDS使用用途によって異なるかと思うので、詳細は省きます。 障害時にはRDSを他AZで起動させるフェイルオーバーをさせる必要があります。 RDSのダッシュボードからサブネットグループの作成を行い、フェイルオーバーす先となるAZをグルーピングします。 フェイルオーバーの確認については、以下記事を参考にテストしてみました。 EC2-RDS間の疎通確認 アプリケーションが動く、EC2インスタンスからRDSへ接続ができることを確認します。 RDSのエンジンとしてMySQLを選択していた場合、EC2インスタンス上で以下コマンドでRDS内のMySQLと接続ができます。 RDSに設定しているセキュリグループのインバウンドルールに接続元EC2からのMySQL通信(3306番ポート)の許可を忘れずに! 接続元ec2 $ mysql -u マスターユーザー名 -pパスワード -h エンドポイント マスターユーザー名,パスワードは、それぞれRDS作成時に決定したものです。エンドポイントはRDS作成後に確認できます。 ALBの使用 一台のEC2ならロードバランサーは使用しなくても良いのでは思ったのですが、単なる負荷分散以外の機能もAWSのロードバランサーは提供してくれるので、そちらのメリットを加味してALBを使用します。 またALBには、Amazon Certificate Manager(ACM)からSSL証明書を取得し、HTTPSでの通信を設定します 4. Lambdaによる自動化 Lambda,EventBridge, CloudWatch, AWSChatBot, SNS このあたりのサービスを使用して開発する上で管理しやすくなる自動化を行いました。 Lambda✖︎EventBridgeによるEC2インスタンス起動・停止の自動化 開発ツール系のインスタンスや使用頻度の高いインスタンスについは起動・停止を自動化すると便利です。 ↓記事を参考に、実装しました。 環境ごとのEC2・RDSの停止忘れ防止 staging環境、production環境(運用開始まで)に属するインスタンス、RDSについては毎日↑のLambdaの停止スクリプトのみを実行し、停止忘れ防止策をこうじました。 AWS ChatbotによるSlack通知 Lambdaの実行結果は、CloudWatchLogsに蓄積されます。 インスタンスの停止スクリプトなどはエラー通知を即座に把握したいため、実務のコミュニケーションツールとして使用しているSlackに通知するように設定しました。 すごく便利!! 5. Amazon SES,SNS  本番環境や開発環境において、AWSからメールを送信するにはAmazon SimpleEmailService(SES)を使用します。 ここでもざっくりと手順を説明すると以下になります。 1.メール送信権限付きIAMユーザー作成後、アクセスキーを取得 2.Railsアプリコード内の ~アプリ名/config/environments/development.rb, staging.rb, production.rb配下にアクセスキーを記載 3.SESでドメイン、メールアドレスの認証 4.認証したドメイン・アドレスからのメール送信の確認 5.SNSでメール通知設定 メール送信権限付きユーザーのアクセスキーを取得 メール送信権限を持つIAMユーザーを作成します。(既存のユーザーでも大丈夫です) アタッチするポリシーは、AmazonSesSendingAccessというデフォルトポリシーがあるのでそれをユーザーにアタッチすれば大丈夫です。 AmazonSesSendingAccess { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "ses:SendRawEmail", "Resource": "*" } ] } テストメール送信 ドメイン・メールアドレスの認証を行います。 認証からテストメールの送信の仕方までは↓記事が参考になります。 ※ドメインに関しては、Route53のほうで事前に認証済みのドメインでないとSES上で認証されないので注意が必要です。(経験あり?) バウンスメールのテストについては、上記テストメールの送信先をbounce@simulator.amazonses.comに設定してあげると、バウンスレートを上げることなくバウンスメールのテストを行なってくれます。 その他、通常の成功メールや苦情メールも同様で↓に記載のテスト用アドレスを使用するとレートとは無関係にテストができます。 バウンスメール・苦情メール等については、SNSとSESを連携させて通知設定を行います。 これも↓記事が参考になるので、簡単に設定できます。 ここまでだいたい2週間ぐらいでした。 6. 開発環境構築(docker)  ローカルの開発環境と検証用のdevelopment環境はdockerで構築を行いました。 Dockerfile, docker-compose.ymlを作成し、シェルスクリプトとして開発環境構築用のスクリプトを用意しました。 このスクリプトを叩くだけで、dockerでの開発環境ができあがります。 合わせて、初期データとして必要なrakeタスクも実装しました。 ざっと内容を紹介 setup.sh #!/bin/bash # 作業用ディレクトリ作成 if [ ! -d ./workspace ]; then mkdir workspace fi # 作業用dir配下にプロジェクトをclone git clone git@~~ # キャッシュを使用せず、imageをbuild docker-compose build --no-cache # 必要な初期rakeタスクを流す docker-compose run web bundle exec rake rakeタスク # 停止済みのコンテナを削除 docker container prune -f ridgepole導入時にハマったこと 今回、アプリケーションはmigrationファイルでの管理ではなくridgepoleを使用します。 私自身初めてのridgepole導入だったので少し苦戦しました。 後ほどridgepole導入時にハマったことは詳細をQiitaに投稿しようと思っています。 ridgepoleとは↓・・・ 7. jenkins・phpmyadminなど開発ツール設定  開発ツール用のインスタンスにjenkins, phpmyadminをそれぞれインストールします。 それぞれのインスタンスには、EC2FullAccessなどのポリシーを持ったアクセスキーを配置する必要があります。 jenkinsインスタンス # 認証情報を設定 $ aws configure # 4つ聞かれるのでそれぞれ入力 1. アクセスキー 2. パスワード 3. region 4. output形式 # この配下に認証情報(アクセスキー等がある) $ cd ~/.aws $ ls -la => config, credentials jenkinsのジョブが失敗する アクセスキーの設置が終わり、jenkinsのジョブを作成し実行たところ、エラーになりました。。。 jenkisnのコンソール出力を見ると以下のようなエラーメッセージが unable to locate credentials. you can configure credentials by running "aws configure". おいおい、アクセスキーはちゃんと配置したはずだぞ? 設定を確認してもきちんと登録されているはず・・・ # アクセスキー設定情報を確認 aws configure list => aws_access_key_id = ***************** => aws_secret_access_key = ***************** 【結論】 jenkinsのジョブを実行しているのは、ec2の中のjenkinsユーザー だからjenkinsユーザーに認証情報を設定してあげる必要がある(これまでは、ec2ユーザーとrootユーザーに設定していた) # rootユーザーになる $ sudo su # jenkinsユーザーになる $ su - jenkins # 認証情報が確認すると・・・なにも設定されていなかった $ aws configure list => aws_access_key_id => aws_secret_access_key # 再度認証情報を設定 $ aws configure 無事、ジョブが成功した! 余談ですが、画面上で作成したjenkinsのジョブはサーバ内jenkinsユーザーの以下に格納されているので、確認できます。 jenkinsインスタンス # rootユーザーになる sudo su # jenkinstユーザーになる su - jenkins cd workspace ls -la => 作成したjenkinsジョブ一覧が表示 8. VPN接続  別のネットワークから、この環境へのアクセスを可能にするためAWSClientVPNを使用し、VPN接続を試みます。 パブリックサブネット内のNATゲートウェイにアタッチしたEIPを固定IPアドレスとして、インターネットに接続できることをゴールとします。 ↓記事を参考にするとできるかと思います。 が、私がハマったことで一つ注意点! ClientVPVEndpointと関連づけるサブネットはプライベートサブネットでないといけない これに気づかず、数時間ハマりました。。。 また、VPN接続するときに作成されるENIは、接続のたびに新しいものが作成されます。 ENIに割り当てられるパブリックIPアドレスは接続のたびに毎回変わりますが、それをNATゲートウェイのEIPで固定化するというイメージです。 9. 起きた変化 以上作業を約3週間で行いました。 インフラにほとんど触ったことの無かった素人が3週間のインフラ構築を通して、どのような変化があったのか、技術的な側面と価値観・考え方の側面から感じたことを書いていきたいと思います。 技術面 【AWS】 ・AWSを使用して、迷わず基本的なアーキテクチャの設計ができるようになった ・AWS上のサービスをドキュメントを読むだけで使いこなせるようになった ・AWSリソースの管理能力が向上した 【docker】 ・dockerを使用して、開発環境の構築ができるようになった ・Dockerfile, docker-compose.ymlなど記述内容を理解し、自分の実装したいように改修できるようになった 【その他】 ・Webサーバやアプリケーションサーバのどのレイヤーに対してエラーが発生しているのか感覚的にわかるようになった ・ログを見る習慣/ログからエラーの原因を特定する力がついた ・Linuxサーバ内のディレクトリ構造や必要ファイルなどが把握し、行いたい修正を加えられるようになった ・Webの3層構造を体系的に理解することができた ざっとこんな感じになります。 特に自分として変化を感じたことは、基本的なアーキテクチャ設計をする際のAWSリソースに対して「わからない・これどうやるんだ」という感情がなくなったことです。 今までは、事前知識としてなかったのはもちろんですがどこかAWSを気軽に触れないものだと思っていました。 ですが、毎日AWSを触りながら理解していくことで、AWSに対するハードルが低くなっていくのを強く感じました。 今では、初めて使用するAWS上のサービスでも「まずは触ってみる」ということを大切にし、ドキュメントや参考記事を読めばだいたいのことはなんとかなるようになったと思います。 わずか3週間ですが、自分のエンジニアとしての知識・技術が3週間前と比較し格段に上がったのを感じました! 価値観・考え方 インフラ構築を経験してみることで、インフラの楽しさを感じたのと同時に、改めて、AWSの素晴らしさに感動しました。 マネジメントコンソールをいじるだけでサーバ・ネットワークを作れたり、あらゆるサービスを連携することでできることの無限さを感じました。 インフラというのはどこか、モヤに隠れた分かりづらいものという意識があった中、自分で0から設計し図を書き、それを実際に構築するという経験のおかげで構造的にインフラを捉えられるようになりました。 AWSを理解するにはまず図を書いてみる とよく聞きますが、これは本当にそうだと思います。 図を書きながら、「これってどうやって通信する」「この部分にはどういう制御が必要なんじゃないか」と頭の中で考え、それを実際に手を動かしてみることで必要な処理や構成が感覚的に理解できるようになってきます。 この経験をきっかけとして、これからもインフラに関する知識・技術を勉強し、今後はSAA,さらにはその上のSAPの取得を目指していきたいと思います。 そして、実務としてこのような素晴らしい挑戦の機会をいただけたことに感謝し、これからも成長できるように頑張っていきたいと思います。 10. おまけ 約3週間インフラ構築をする上で、ミドルウェアの操作についてはコマンドラインが主となるので、自然とコマンドを使う機会が多くなりました。 そこで備忘録がてら、よく使用したコマンドを残していきたいと思います。 よく使ったコマンドたち ■ コマンド # ファイル削除 rm -rf ディレクトリ # 検索 grep -r 正規表現 # プロセス確認 ps aux | grep XXX # 環境変数確認 env ■ systemctl # start, stop, restart, statusなど # Nginxの起動状態確認 systemctl nginx status # MySQLの起動状態確認 systemctl mysql status ■ crontab # サーバの初期設定をするcrontabの内容確認 crontab -l ■ Git # 接続先のremoteリポジトリを確認 git remote -v # remoteリポジトリを設定 git remote set-url origin git@~~~ ■ ssh ssh -i ~/.ssh/キー.pem ec2-user@IPアドレス
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Ruby] irbを使ってこなかった、自称エンジニア

はじめに プログラミングスクールに通い、3ヶ月が経ちました。 学習中はirbやrails cなどを使い学んできたが、実際にオリジナルアプリを作る時に全く使っていない。。。 このままでは自称ミュージシャン、自称芸人と並んで自称エンジニアになる気がしたので、「irb」について記事にしました。 irbってなんなんだ? REPL(Read-eval-printloop、対話型評価環境) つまりREPLとは プログラミング言語の実行環境の一つで、利用者が入力欄にキーボードなどから式や文を一行入力すると、即座に解釈・実行して結果を返し、再び入力可能になるもの。インタプリタの一種。 Rubyに用意されているirbと呼ばれるREPL どのような時に使うのか ・動作確認に使われる その他動作確認では、 〇〇.rbとファイルを作り      ↓ テキストエディタでコードを記述し      ↓ ターミナルで%ruby 〇〇.rb と打ち込むと確認できます。 が、手間がかかりますよね? irbでは簡単に動作確認ができます ・手を動かして学習できる 学習の定着率には 本や資料を読むことによるインプットより 体験したり実践するアウトプットの方が定着率が良いため 私のような自称エンジニアは、積極的に使うべきである。 使い方 ターミナルからirbと入力すれば、irbが起動する % irb ←3字を打ち込むと irb(main):001:0> ←このように起動される 1+1のような計算を行なってみます。 irb(main):001:0> 1+1//←1+1を打ち込む => 2//←結果 irb(main):002:0> 変数に適当な文字列を代入してみます。 変数aに「お腹すいた」と入れてみます。 irb(main):002:0> a ="お腹すいた"//変数aに「お腹すいた」を代入 => "お腹すいた" 次に変数aのみを入力して、中身を確認します。 irb(main):003:0> a//変数aを入力 => "お腹すいた"//変数aの中身である、「お腹すいた」が出力されます exitと入力すればirbを終了できます irb(main):004:0> exit 簡単ではありますが使い方については以上です。 おわりに アウトプットをすることが大事なんだとプログラミングを学習してから何度も思いますが、 実際に行動するとなると慣れがない私には難易度が高く感じています。 ですがハードルを低くしてアウトプットを習慣化することで楽しみながら学べるようになってきたと思います。 お粗末な文章、記事だったと思いますが、 最後まで見てくれた方、ありがとうございます。 何かご教授いただければ嬉しいです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【devise】暗号化前後のパスワードが一致しているか判定するメソッド

実現したいこと Railsでdevise gemを使っている環境にて、暗号化前のパスワードが暗号化後のパスワードと一致しているか確認したい。 例えば、以下のようなケースです。 「このパスワードで設定したはずだがログインできず、パスワードがちゃんと設定されてるか確認してほしい」という問い合わせに対して調査する場合 有効期限を持たせた複数のパスワードを、過去履歴を含めてDBに保持しており、古いパスワードが入力された場合に「それは古いパスワードです」とアラートを出したい場合 deviseでは、パスワードは暗号化されDBに保存されているため、DBのレコードを参照するだけだと、元のパスワードがどんなものだったかわかりません。 解決方法 「入力されたパスワードを自力で暗号化したものでDBを検索する」という方法もありますが、そこまでしなくても一発でわかるvalid_password?メソッドがdeviseで用意されています。 レシーバにはActiveRecordインスタンス(パスワードが保存されたレコード)、引数に暗号化前のパスワードを指定します。 基本例 # ユーザが入力した"hogehoge"というパスワードが、id=1234のユーザのパスワードと一致するか確認したい場合 User.find(1234).valid_password?("hogehoge") # => 戻り値はboolean # paramsで渡ってきたpassword(暗号化前)が、id=1234のユーザに設定されたパスワードと一致するか確認したい場合 User.find(1234).valid_password?(params[:password]) 応用例 ちょっと発展させた例です。 例えば、有効期限を持たせた複数のパスワードを、過去履歴を含めてUserPasswordモデルに保持しており、 古いパスワードが入力された場合に「それは古いパスワードです」とアラートを出したい場合 def old_password?(input_password) old_passwords = UserPassword.find(1234).where.not(expired_at: nil) old_passwords.any? {|old_pw| old_pw.valid_password?(input_password) } end redirect_to new_session_path, alert: "入力されたパスワードは有効期限が切れています" if old_password?(params[:password]) 参考サイト devise gemでは以下で定義されているようです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Title testing

This is testing
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Ruby] Stringクラスのinclude?メソッド

学習したことのアウトプットとして include?メソッド Rubyの組み込みライブラリ 指定した値が含まれているかを判定するメソッド 指定した値が含まれている場合はtrueを、含まれていない場合はfalseを返り値として返す Arrayのinclude?メソッドを使用する場合 指定した値が、配列中に含まれているかを判定する a = [ "a", "b", "c" ] a.include?("b") #=> true a.include?("z") #=> false Stringのinclude?メソッドを使用する場合 文字列中に部分文字列が含まれていれば真を返す "hello".include? "lo" #=> true "hello".include? "ol" #=> false "hello".include? ?h #=> true ※補足等がありましたらコメントいただけると幸いです
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む