のぴぴのメモ

自分用のLinuxとかの技術メモ

AWS CloudFormationで、インスタンスのUserDataにクロススタックリファレンスの値を埋め込む方法

自分用のメモです。
こちらのAWS CloudFormationのヘルパーのコマンド実行文字列にクロススタックリファレンスの値を埋め込む方法 - のぴぴのメモの記事の応用です。

方法

Fn::Joinの文字列結合で、Fn::Sub(!Sub)や、Fn::ImportValueのクロススタックリファレンスを組み合わせる。
また改行コードは、"\n"で入力できる。

サンプル

      UserData:
        Fn::Base64:
          Fn::Join:
            - ""
            - - !Sub |
                #!/bin/bash -xe

                #set /etc/httpd/conf.d/ssl.conf
                cat > /etc/httpd/conf.d/ssl.conf << EOL
               
                  SSLProxyEngine On
                  SSLProxyCheckPeerCN off
                  SSLProxyCheckPeerExpire off

                  # Targets web server
              - "ProxyPass / https://"
              - Fn::ImportValue: !Sub ${Environment}-${Stack}-TargetUrl
              - "\nProxyPassReverse / https://"
              - Fn::ImportValue: !Sub ${Environment}-${Stack}-TargetUrl
              - "\n"
              - !Sub |
                </VirtualHost>

                # Application-B
                <VirtualHost _default_:1234>
                  ErrorLog logs/proxy_hogehoge_error_log
                <以下略>

オレオレ証明書をワンライナーで作る方法

自己署名証明書(オレオレ証明書)を作る時、コマンドを3回叩いたり、コマンド実行したら対話的に入力したりで簡単にバッチ化できないかなぁ〜と調べたメモです。
ほぼ、こちらの内容の抜粋です。
blog.hifumi.info

手順

(1)自己署名証明書

export URLNAME=hoge.com
openssl req -x509 -days 36500 -newkey rsa:2048 -nodes -out ${URLNAME}.crt -keyout ${URLNAME}.key -subj "/C=JP/ST=Tokyo/L=null/O=null/OU=null/CN=${URLNAME}/"

(2)作成した自己署名証明書の確認

openssl x509 -text -noout -in ${URLNAME}.crt

openssl reqのオプション

  • -x509 : 証明書要求の代わりに自己署名証明書を出力する
  • -days 日数:証明書の有効期間の日数(デフォルトは30日)
  • -newkey rsa:2048 : 新しい証明書署名要求と秘密鍵を作成する。形式は"rsa:2048"。
  • -nodes : 秘密鍵作成時にパスフレーズを要求しない(暗号化しない)
  • -out ${URLNAME}.crt :標準出力の出力先ファイルの指定(上記手順では、自己署名証明書が出力される)
  • -keyout ${URLNAME}.key :秘密鍵の出力先
  • -subj "/C=JP/ST=Tokyo/L=null/O=null/OU=null/CN=${URLNAME}/": 証明書作成時に対話で聞かれる内容を指定する
    • C=国(JPとか)*1
    • ST=州/都道府県
    • L=住所
    • O=組織
    • OU=組織部
    • CN=FQDNや個人名
    • 補足:C、ST、Lなどの略語は、”openssl x509 -text -noout -in ${URLNAME}.crt”で参照した時の"Issuer:"の略称と一致します。

openssl x509のオプション

  • text:テキスト表示
  • -noout:符号化されたデータ(自己署名証明書ファイルそのもの)は表示しない
  • -in ${URLNAME}.crt:入力ファイルの指定(ここでは自己署名証明書を指定)

*1:指定できるCountory codesはこちら

AWS CloudFormationのヘルパーのコマンド実行文字列にクロススタックリファレンスの値を埋め込む方法

自分用のメモです。
CloudFormationのヘルパーに埋め込む実行コマンドの文字列に、他のスタックで作成した値をクロススタックリファレンスで埋め込む方法が、なかなか分からなかったので。

方法

Fn::Joinの文字列結合とFn::ImportValueのクロススタックリファレンスを組み合わせる

サンプル

        Metadata:
            AWS::CloudFormation::Init:
                config:
                    packages:
                        yum:
                            awslogs: []
                    commands:
                        01_add_proxy_to_ecs_agent1:
                            command:
                                Fn::Join:
                                    - ""
                                    - - "echo HTTP_PROXY="
                                      - Fn::ImportValue: !Sub ${ProxyStack}-Proxy1PrivateDns
                                      - ":"
                                      - Fn::ImportValue: !Sub ${ProxyStack}-Proxy1PortNumber 
                                      - " >> /etc/ecs/ecs.config"
  • "01_add_proxy_to_ecs_agent1:"のブロックがその例
  • クロススタックリファレンスは下記の2つ
    • Fn::ImportValue: !Sub ${ProxyStack}-Proxy1PrivateDns
    • Fn::ImportValue: !Sub ${ProxyStack}-Proxy1PortNumber
  • 上記を含め Fn::Join:で文字列結合する

結果

完成するとこんな感じのコマンド実行用の文字列になる

  • "echo HTTP_PROXY=ip-10-203-64-147.ap-northeast-1.compute.internal:3128 >> /etc/ecs/ecs.config"

AWS 各リージョンのデフォルトVPCをまとめて削除するpythonスクリプト(boto3利用)

AWS SDK for Python (Boto3)の練習用に、各リージョンのデフォルトVPCをまとめて削除するpythonツールを作りました。
github.com

前提環境

利用方法

git clone https://github.com/Noppy/delete_default_vpc.git
  • (3)実行する
cd delete_default_vpc
./delete_default_vpc.py -a 'AWS_ACCESS_KEY_ID' -s 'AWS_SECRET_KEY_ID'
  • 引数でアクセスキー&シークレットキーを渡すのはセキュリティの観点から正直バットプラクティスなので、実用化する場合はセッション取得周りの実装を見直したほうが良いと思います。

蛇足

boto3の全体像が理解できなく、結構苦労し

vimの設定と操作時のTips

vimを利用する時の設定と操作時のメモです。

1. ~/.vimrc設定

" setting
set fenc=utf-8 "文字コードをUFT-8に設定
set nobackup   " バックアップファイルを作らない
set noswapfile " スワップファイルを作らない
set showcmd    " 入力中のコマンドをステータスに表示する

" 見た目系
set number           "行番号を表示
set smartindent      " インデントはスマートインデント
set visualbell       " ビープ音を可視化
set showmatch        " 括弧入力時の対応する括弧を表示
set laststatus=2     " ステータスラインを常に表示
set wildmode=list:longest " コマンドラインの補完
"set cursorline       " 現在の行を強調表示
"set cursorcolumn     " 現在の行を強調表示(縦)
:syntax on           "構文解析に基づいて色を付ける

" Tab系
set list listchars=tab:\▸\- " 不可視文字を可視化(タブが「▸-」と表示される)
set expandtab               " Tab文字を半角スペースにする
set tabstop=4               " 行頭以外のTab文字の表示幅(スペースいくつ分)
set shiftwidth=4            " 行頭でのTab文字の表示幅

" 検索系
set ignorecase  " 検索文字列が小文字の場合は大文字小文字を区別なく検索する
set smartcase   " 検索文字列に大文字が含まれている場合は区別して検索する
set incsearch   " 検索文字列入力時に順次対象文字列にヒットさせる
set wrapscan    " 検索時に最後まで行ったら最初に戻る
set hlsearch    " 検索語をハイライト表示
" ESC連打でハイライト解除 
nmap <Esc><Esc> :nohlsearch<CR><Esc>

多分こちらのページの内容をベースに多少カスタマイズしたものです。

2. vim操作のTips

2.1 カット&ペーストするとずれる問題

vimで、:a! を実行し挿入モードにしてから貼り付ける。*1

  • 手順
    • ESCを押してカーソルが最終行に移動したら、 ":a!"を入力
    • そのまま貼り付けたい内容をペーストする
    • 貼り付けが完了し、ESCでモード終了すると反映される

VPC 閉域空間でCloudFormationのcfnヘルパーを使うときは、CFnのEndpointがいる話

インターネット接続していないVPC環境で、CloudFormationのcfnヘルパーを使ってインスタンスの中のセットアップをしたら、インスタンスの作成がエラーになってハマった話です。

原因

cfnヘルパーでの設定完了を通知するcfn-signalがCloudFormationのエンドポイントと通信できず、完了通知ができなかったため

対処

VPCにCloudFormationのVPC Endpoint(Private Link)を設置する。


ちなみに、CloudFormationのPrivate Link(VPC EndpointのInterface型)がサポートされたのは、2018年8月22日でつい先日の話でした。

参考情報

Creating the VPC EndPoint for AWS CloudFormation

To create the VPC endpoint for the AWS CloudFormation service, use the Creating an Interface Endpoint procedure in the Amazon VPC User Guide to create the following endpoint:

com.amazonaws.region.cloudformation

region represents the region identifier for an AWS region supported by AWS CloudFormation, such as us-east-2 for the US East (Ohio) Region.

VPC閉塞網からyumリポジトリにアクセスする(Amazon Linux & RHEL)

はじめに

セキュリティなどの理由で、VPCからインターネットへの外の通信をさせないようにしている環境を想定した検証環境で、必要なパッケージ追加をしようとしてハマったのでまとめました。

  • 結論
    • Amazon Linux : S3のVPC Endpointを設ける
    • RHEL : ForwardProxy(URLフィルタリング)を利用する
  • 変更履歴
    • 2018.10.28 update: AL2の場合の設定がなかったので追記しました
    • 2020.9.20 update: RHELのRHUIのURLが変更されていたのでアップデートしました。
    • 2021.6.27 Amazon Linux2で、"arn:aws:s3:::amazonlinux-2-repos-/*"バケットへのアクセスも必要になっていたのでポリシーに追加しました。

Amazon Linux1&2の場合

概要

Amazon Linuxのyumリポジトリは、S3が利用されています。ですので、S3用のVPC Endpointを作ることでInternet Gatewayを介さずにyumリポジトリにアクセスすることができるようになります。


VPC Endpoint(S3)の設定

VPCに、S3用のVPC Endpointを作成して、yumリポジトリ用のS3バスケット(下記の2個)にからオプジェクトをGetできるようにします。

  • (AmazonLinux)yumリポジトリのS3バスケット
    • packages.Region Code.amazonaws.com/*",
    • repo.Region Code.amazonaws.com/*"
  • (AmazonLinux2)yumリポジトリのS3バスケット
    • amazonlinux.Region Code.amazonaws.com
    • amazonlinux-2-repos-Region Code ※2021.6頃以降はこちらに変更された模様

Endpointのポリシーには以下のような設定をします。より厳密にするためには、amazonの前の"*"を各リージョンのコード(例えば東京リージョンの場合、ap-northeast-1)とします。

{
  "Statement": [
    {
      "Sid": "Amazon Linux AMI Repository Access",
      "Principal": "*",
      "Action": [
        "s3:GetObject"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::packages.*.amazonaws.com/*",
        "arn:aws:s3:::repo.*.amazonaws.com/*",
        "arn:aws:s3:::amazonlinux.*.amazonaws.com/*",
        "arn:aws:s3:::amazonlinux-2-repos-<B>Region Code</B>/*""
      ]
    }
  ]
}

公式情報は、Amazon Linuxのよくある質問をご覧ください。

上記のVPCエンドポイントポリシーを作成するCloudFormationのサンプルです

  S3VpcEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcId:  !Ref Vpc
      ServiceName: !Sub com.amazonaws.${AWS::Region}.s3
      RouteTableIds:
        - !Ref RouteTable1
        - !Ref RouteTable2
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal: '*'
            Action:
              - 's3:*'
            Resource:
              # Allow connections to the Amazon Linux yum repositories
              - "arn:aws:s3:::packages.*.amazonaws.com/*"
              - "arn:aws:s3:::repo.*.amazonaws.com/*"
              # Allow connections to the Amazon Linux2 yum repositories
              - "arn:aws:s3:::amazonlinux.*.amazonaws.com/*"
              - Fn::Join:
                  - ""
                  - - "arn:aws:s3:::amazonlinux-2-repos-"
                    - !Sub "${AWS::Region}"
                    - "/*"

RHELの場合

概要

License includedなRHELを利用した場合のパッケージ管理は、Red Hat Update Infrastructure (RHUI) を利用します。

Q: Red Hat Enterprise Linux を実行中の Amazon EC2 インスタンス用に、更新や定期的なパッチを受け取るにはどのようにすればよいですか?

Red Hat Update Infrastructure (RHUI) が Red Hat によってそれぞれの AWS リージョンでメンテナンスされており、定期的なアップデートとパッチを利用できます。Red Hat Enterprise Linux インスタンスはリージョンごとのリポジトリにアクセスして差分更新を受信することができます。またすべては料金に含まれています。

AWSのRHUIの場合、パブリックなネットワーク上にRHUIサーバーがいるようで、どうしてもインターネットアクセスが必要になります。VPCに閉じることに拘らない場合は、NATGWをつけてしまえば良いですが、要件的にそれが難しい場合取りうる手段としては以下の2つが考えられると思います。

  • VPCの外に簡単に出れない環境でのRHUIアクセス方法
    1. ForwardProxy(URLフィルタで制限)を利用する
    2. RHUIのyumリポジトリのコピーをVPC内に設ける

ただ「yumリポジトリのコピーをVPC内に設ける」案は、(1)RHUIからのリポジトリコピーをどうやるかという技術的課題と、(2)コピーしたyumリポジトリ上のrpmパッケージのredhatライセンス上の解釈が判断つかない、という理由から今回は「RHUIのyumリポジトリのコピーをVPC内に設ける」方法を取っています。
具体的には、public subnetにproxyを構成して、RHELのyum設定(/etc/yum.conf)にプロキシ設定を追加しています。

Forward Proxy設定

フィルタリング対象URL

公式な情報はなさそうで、私が実機を確認した範囲の情報ですがRHELインスタンスの/etc/yum.repos.d/rhui-load-balancers.confを見ると、以下のURLにアクセスしているように見えます。

  • rhui2-cds01..aws.ce.redhat.com
  • rhui2-cds02..aws.ce.redhat.com

[2020.9.20追記]
詳細わかりませんが、最近動かしたらRHUIのURLが以下に変更されてたので追記します。(URLから推測するに、RHUI2からRHUI3にアップデートしたんですかね)

  • rhui3.REGION.aws.ce.redhat.com
Forward Proxy設定

今回は手っ取り早く、squidを利用しています。

  • (1) squidのrpmのインストール
sudo yum -y install squid
  • (2) squid設定
    • /etc/squid/squid.conf
# define ip address
acl localnet src 127.0.0.0/8
acl localnet src ::1/128

acl SSL_ports port 443
acl Safe_ports port 443		# https
acl CONNECT method CONNECT

# Deny CONNECT to other than secure SSL ports
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports

# Only allow cachemgr access from localhost
http_access allow localhost manager
http_access deny manager

# from where browsing should be allowed
http_access allow localnet

# include url white list
acl whitelist dstdomain "/etc/squid/whitelist"
http_access allow whitelist

# And finally deny all other access to this proxy
http_access deny all
#------------------------------------------
http_port 0.0.0.0:3128

# Leave coredumps in the first cache dir
coredump_dir /var/spool/squid

# anonymouse host name 
visible_hostname unknown

# change log format
logformat squid %tl %>a %Ss/%03>Hs %<st %rm %ru %[un %Sh/%<a %mt
    • /etc/squid/whitelist(東京リージョンの場合*1 )
#For RHUI2
rhui2-cds01.ap-northeast-1.aws.ce.redhat.com
rhui2-cds02.ap-northeast-1.aws.ce.redhat.com

#For RHUI3( Added on Sep. 20, 2020)
rhui3.ap-northeast-1.aws.ce.redhat.com
  • (3) squidの再起動
sudo systemctl restart squid
RHELのyumへのProxy設定
  • /etc/yum.conf (下記の設定を追記します。3128の部分は、squid.confのhttp_portの設定に従います)
proxy=http://<forward proxyのFQDNまたはIP>:3128

インスタンスのユーザデータや、CloudFormationのcnf-initヘルパーなどでこの設定を追加するようにしておくと便利だと思います。

*1:他リージョンは、ap-northeast-1を置き換えます

AWS 特定のAMIの各リージョンのImageID一覧を取得するシェル

1.概要

特定の種類のAMIについて、各リージョンのImageIDを取得し、CSV形式で出力するシェルスクリプトです。
例えば、SQL Server Web Editionが含まれているLicense-includeなwindowsインスタンスの各リージョンのImageIDを知りたいとかいうときに利用します。
作成したCSVフィルをExcelとかで開くとこんな感じで情報を確認できます。
f:id:nopipi:20180819201357p:plain:w800

2.使い方

2.1 前提

このツールは下記のコマンドが使えることが前提となります。

  • aws cli
  • シェル環境(bash, awk)
  • gitコマンド(セットアップに利用。なくてもなんとかはなる)

手元の環境ですが、Linux環境とMacOS環境で動くことは確認しています。

2.2 ソースコードの取得とセットアップ

ソースコードはこちらのgithubになります。
github.com

  • (1) GitHubからコードをcloneする
$ git clone https://github.com/Noppy/aws_list_amis.git
  • (2) 必要に応じて適切なフォルダにシェルをコピーする
$ cp aws_list_amis/list_amis.sh DEST_DIRECTORY_PATH

2.3 実行

  • (1)マネジメントコンソールなどで、取得したいAMIの名前を確認する
    • (a)「EC2」サービスに移動
    • (b)「インスタンスの作成」を押し、「コミュニティーAMI」を選択する
    • (c)検索などを利用し目的のAMIを見つけて、名前をコピーする

f:id:nopipi:20180819202725p:plain:w800

  • (2)シェルを実行する

取得したAMIの名前を引数にしてシェルを実行する。結果は標準出力に出力されるので、必要に応じてファイルにリダイレクトする。

./list_amis.sh "Windows_Server-2012-R2_RTM-English-64Bit-SQL_2016_SP1_Web-2018.07.11" > Win_SQL_WebEdition.csv

AWS リージョンのコードと名称の一覧を取得する

結論

例えば「”Asia Pacific (Tokyo)", "ap-northeast-1"」という感じに、リージョン名称とリージョンコードの一覧を取得するのは、下記のAWSのEC2ユーザーズガイドの"Regions and Availability Zones"のリージョン一覧表から取得するのが良さそう。(結局手作業ですが)
docs.aws.amazon.com

(補足)aws cliでのリージョン一覧取得

aws cliで、"aws ec2 describe-regions"でもリージョン一覧が取得できますが、リージョンコード(ap-northeast-1とか)と、EC2のエンドポイント (ec2.ap-south-1.amazonaws.comとか)しか取得できず、ap-northeast-1が”Asia Pacific (Tokyo)"というのは自動では取れないんですね。

aws cli取得例1 アジアのリージョンを取得する

aws ec2 describe-regions  --output json --filters 'Name=region-name, Values=ap-*'
{
    "Regions": [
        {
            "Endpoint": "ec2.ap-south-1.amazonaws.com", 
            "RegionName": "ap-south-1"
        }, 
        {
            "Endpoint": "ec2.ap-northeast-2.amazonaws.com", 
            "RegionName": "ap-northeast-2"
        }, 
        {
            "Endpoint": "ec2.ap-northeast-1.amazonaws.com", 
            "RegionName": "ap-northeast-1"
        }, 
        {
            "Endpoint": "ec2.ap-southeast-1.amazonaws.com", 
            "RegionName": "ap-southeast-1"
        }, 
        {
            "Endpoint": "ec2.ap-southeast-2.amazonaws.com", 
            "RegionName": "ap-southeast-2"
        }
    ]
}

取得例2 リージョンコード一覧を抜き出す

aws ec2 describe-regions --output text --query 'Regions[].{Name:RegionName}'
ap-south-1
eu-west-3
eu-west-2
eu-west-1
ap-northeast-2
ap-northeast-1
sa-east-1
ca-central-1
ap-southeast-1
ap-southeast-2
eu-central-1
us-east-1
us-east-2
us-west-1
us-west-2

取得例3 シェルで、抜き出したリージョンコード一覧をREGIONSという配列にセットする

declare -a REGIONS=( $(aws --output text ec2 describe-regions --query 'Regions[].{Name:RegionName}'|sort) )

取得したREGIONS配列を利用する例

for i in ${REGIONS[@]}; do echo "region code = $i";done
region code = ap-northeast-1
region code = ap-northeast-2
region code = ap-south-1
region code = ap-southeast-1
region code = ap-southeast-2
region code = ca-central-1
region code = eu-central-1
region code = eu-west-1
region code = eu-west-2
region code = eu-west-3
region code = sa-east-1
region code = us-east-1
region code = us-east-2
region code = us-west-1
region code = us-west-2

AWSのドキュメントリンク

個人用のメモです。

サービスに関する情報

RHEL7 on EC2にdockerをセットアップする手順

はじめに

RHEL7 on EC2(License Included)でのdockerセットアップ手順を記載します。
Amazon Linux2へのdockerセットアップ手順(下記)との違いは、RHUI*1のEPELレポジトリを有効化してそこからdockerをインストールするところです。
nopipi.hatenablog.com

手順

RHEL7 on EC2へのdockerインストール

基本的には、ECS agentガイドにある手順を参考にRHEL用に一部カスタマイズして進めます。

EPELレポジトリの登録

awsが提供するライセンス込みのRHELインスタンスにdockerをインストールする場合は、RHUI(Red Hat Update Infrastructure)*2のEPEL(Extra Packages for Enterprise Linux)から、dockerをダウンロードします。
EPELはデフォルトでは登録がないので、まずEPELの登録をします。(2020/11/10 RHUIの仕様が変わったようで、リポジトリ名が変わっていたのでそれに合わせてコマンドを変更しました)

sudo yum install yum-utils
sudo yum-config-manager --enable rhel-7-server-rhui-extras-rpms
Dockertインストール

RHEL全体のパッケージアップデートとdockerのインストールを行います。

sudo yum -y update
sudo yum -y install docker 

dockerの起動とOS起動ときの自動起動設定

sudo systemctl start docker
sudo systemctl enable docker

dockerコマンドをec2-userで実行するための設定

ec2-userのセカンダリグループに、dockerrootグループを追加します。dockerのグループが、dockerではなくdockerrootなので注意してください。
あとdockerdのsocketファイルの所有者が"root:root"なので、dockerrootグループがwriteできるよう所有者を"root:dockerroot"に変更します。(もっとスマートな方法があればいいのですが、ちょっと見つからなかったので)

sudo usermod -a -G dockerroot ec2-user
sudo chown root:dockerroot /var/run/docker.sock 

確認

dockerコマンドを実行して確認する。実行して、ClientとServerの両方の情報が表示されればOKです。

$ docker version
Client:
 Version:      18.03.1-ce
 API version:  1.37
 Go version:   go1.9.6
 Git commit:   3dfb8343b139d6342acfd9975d7f1068b5b1c3d3
 Built:        Fri Jun 15 23:15:12 2018
 OS/Arch:      linux/amd64
 Experimental: false
 Orchestrator: swarm

Server:
 Engine:
  Version:      18.03.1-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.6
  Git commit:   7390fc6/18.03.1-ce
  Built:        Fri Jun 15 23:17:24 2018
  OS/Arch:      linux/amd64
  Experimental: false

*1:Red Hat Update Infrastructure 2.0

*2:クラウドで提供されているRHEL(License IncludedなRHELのAMIを利用した場合が該当)ようにクラウド上で提供されている、RHELパッケージのレポジトリサービス。詳細は、こちらを参照

EC2(Amazon Linux2)にprivateなdocker registryの作るメモ

1.はじめに

検証用にプライベートなdocker registryをAWS EC2上のAmazon Linux2に作った時のメモです。レジストリを立てて、別のサーバからdockerイメージをpush/pullして確認するまでを記録しています。
内容は、こちらの記事を参考にしています。

2.セットアップ手順

2.1 前提環境

雑な絵ですが、こんな感じの構成を作ります。
f:id:nopipi:20180721192454p:plain
このメモの前提となる構成は以下の通りです。

  • OS:Amazon Linux2 (AMI ID: amzn2-ami-hvm-2.0.20180622.1-x86_64-gp2)
  • docker registryを動かすインスタンスのNW構成:
    • プライベートDNS: ip-10-203-64-60.ec2.internal
    • パブリックIPを付与またはNATGWでインターネットアクセスを可能にする
    • セキュリティグループで、tcp:443ポート(https)、tcp:22ポート(ssh作業用)の通信ができるよう設定する
  • key pairs

2.2 dockerのセットアップ

プライベートdocker registryをインストールするインスタンスsshログインして、下記の記事の手順でdockerをセットアップします。
nopipi.hatenablog.com

dockerレジストリ用のディレクトリ作成

レジストリ用に以下の構造のディレクトリを作成します。

/home/docker/
         └── registry
             ├── certs
             └── data

ディレクトリの作成と確認手順はこちらですl

sudo mkdir -p /home/docker/registry/{certs,data}
find /home/docker/

2.3 SSLの自己証明書(オレオレ証明書)の作成

検証用なのでオレオレ証明書で勘弁してもらいます。opensslコマンドの途中で聞かれる内容は、とりあえず全てデフォルト(リターン)とします。

openssl req -newkey rsa:4096 -nodes -sha256 -keyout domain.key -x509 -days 365 -out domain.crt
  • オプション説明
    • req : 証明書署名要求(CSR)の管理
      • "-newkey rsa:4096": 4096bitのRSA形式の秘密鍵を同時に作成する
      • "-nodes" : 秘密鍵を暗号化しない
      • "-sha256" :
      • "-keyout domain.key" : 秘密鍵のファイル名を、"domain.key"にする
      • "-x509" : x509の証明書を出力する
      • "-days 365" : 証明書の有効期間を365日にする。
      • "-out domain.crt”: 証明書のファイル名を、"domain.crt"にする。

作成した秘密鍵(domain.key)と、サーバ証明書(domain.crt)をレジストリディレクトリに移動します。

sudo mv domain.key /home/docker/registry/certs/
sudo mv domain.crt /home/docker/registry/certs/

2.4 dockerレジストリの起動

レジストリのイメージ登録とコンテナの実行を同時に行います。

cd /home/docker/registry
docker run -d \
 --restart=always \
 --name docregistry \
 -v `pwd`/certs:/certs \
 -v `pwd`/data:/var/lib/registry \
 -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
 -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
 -e REGISTRY_STORAGE_DELETE_ENABLED=True \
 -p 443:443 \
 registry:2
  • オプション説明
    • "-d": コンテナのバックグラウンド実行
    • "--restart=always" : 再起動ポリシー設定。コンテナダウン時は常にコンテナ再起動を試みる。
    • "--name" : コンテナ名称
    • "-v xxx" : コンテナのVolume機能の設定
    • "-e xxx" : コンテナ内の環境変数設定
    • "-p 443:443" : コンテナの公開ポート設定。コンテナの443portを外部の443portで見せる
    • "registry:2" : レジストリのimage。docker runの中で、docker hubからpullされる

dockerイメージを確認します。

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
registry            2                   b2b03e9146e1        2 weeks ago         33.3MB

registryコンテナが実行されているか確認します。

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                            NAMES
ddd75d47e43a        registry:2          "/entrypoint.sh /etc…"   16 seconds ago      Up 16 seconds       0.0.0.0:443->443/tcp, 5000/tcp   docregistry

3.クライアントからdockerイメージをpushしてみる

dockerのクライアントとなる別のサーバから、プライベートdocker registryへのimageのpush、pullを確認します。

3.1 httpsの接続確認

まずは素のhttpsで、クライアントから、プライベートdocker registryにアクセス可能かを確認します。

(1)サーバ証明書のコピー

プライベートdocker registry用に作成したサーバ証明書を、クライアントにコピーします。ssh ログインするときに"-A"オプションを利用するとsshの鍵を自動でforwardingしてくれるので、クライアントのインスタンス秘密鍵を置く必要がありません。(今回の話からは脱線するので、詳しくはこちらを参照)
MACの場合でデフォルトの秘密鍵を利用する場合は、こんな感じでログインします。

ssh -A ec2-user@[クライアントのDNS or IP]
scp ec2-user@ip-10-203-64-60.ec2.internal:/home/docker/registry/certs/domain.crt .
(2)https接続確認

curl でコピーしたサーバ証明書を指定して、プライベートdocker registryにアクセスしてエラーにならなければOKです。

$ curl --cacert domain.crt https://ip-10-203-64-60.ec2.internal/v2/_catalog

3.2 dockerへのサーバ証明書登録

コピーしたサーバ証明書をdockerの設定ディレクトリに格納します。
格納は、下記ルールに基づいて格納します。

この/etc/dockerディレクトリは、root権限がないと移動することもできないので、rootにチェンジして作業します。

$ sudo -i
# cd /etc/docker/
# mkdir certs.d
# cd certs.d/
# mkdir ip-10-203-64-60.ec2.internal
# cp /home/ec2-user/domain.crt /etc/docker/certs.d/ip-10-203-64-60.ec2.internal/ca.crt
# exit
$ 

サーバ証明書の登録方法は他にもあります。詳細は、公式ドキュメントまたはこちらのQiitaを参照してください。

3.3 プライベートレジストリへのイメージのpushとpull

動作確認として、docker hubからubuntuのコンテナイメージをpullしてきて、プライベートdockerレジストリに登録してみます。

(1)イメージのpullとtag作成

ubuntuのイメージをpullしてきて、プライベートdockerレジストリ登録用のtagを作成します。

docker pull ubuntu:16.04
docker tag ubuntu:16.04 ip-10-203-64-60.ec2.internal/my-ubuntu
docker images
REPOSITORY                               TAG                 IMAGE ID            CREATED             SIZE
ubuntu                                   16.04               e13f3d529b1a        4 days ago          115MB
ip-10-203-64-60.ec2.internal/my-ubuntu   latest              e13f3d529b1a        4 days ago          115MB
(2)イメージのpush

プライベートdocker registryにイメージをpushします。

docker push ip-10-203-64-60.ec2.internal/my-ubuntu
The push refers to repository [ip-10-203-64-60.ec2.internal/my-ubuntu]
709bdd00b1a4: Pushed 
07b9c3c04cbd: Pushed 
6eaddaf493f1: Pushed 
a0e188d0e278: Pushed 
711e4cb62f50: Pushed 
latest: digest: sha256:0d06090fff94c0a3640729c7ef7e6b36ad5b41bec600cc2be92739c90d204243 size: 1357

pushしたイメージが登録されているか、プライベートdocker registryのカタログを参照します。

[ec2-user@ip-10-203-128-109 ~]$ curl --cacert domain.crt https://ip-10-203-64-60.ec2.internal/v2/_catalog
{"repositories":["my-ubuntu"]}
(3)イメージのpull

まず確認のため、ローカルにあるdockerイメージを削除します。

$ docker images
REPOSITORY                               TAG                 IMAGE ID            CREATED             SIZE
ubuntu                                   16.04               e13f3d529b1a        4 days ago          115MB
ip-10-203-64-60.ec2.internal/my-ubuntu   latest              e13f3d529b1a        4 days ago          115MB

$ docker rmi e13f3d529b1a e13f3d529b1a

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

プライベートdocker registryから、イメージをpullして確認します。

$ docker pull ip-10-203-64-60.ec2.internal/my-ubuntu

$ docker images
REPOSITORY                               TAG                 IMAGE ID            CREATED             SIZE
ip-10-203-64-60.ec2.internal/my-ubuntu   latest              e13f3d529b1a        4 days ago          115MB

opensslコマンドのhelpを出す

opensslコマンドのメモです。

1.コマンドのSYNOPSIS

 openssl command [ command_opts ] [ command_args ]

2.コマンドのヘルプ表示方法

2.1 [command]一覧を出す

"help"というコマンドは無いが、”invalid command”エラーでコマンド一覧が表示される。コマンドの説明は"man openssl"で確認する。

openssl help

2.2 各コマンドのオプション

コマンドの後ろに"help"をつけると、"unknown option"となりオプション一覧が表示される。
例えばreqコマンドのオプションの場合は以下

openssl req help

またreqなどのスタンダードコマンドは、"man req"などmanでコマンド名を指定することで詳細なmanを参照できる。

man req
REQ(1)                                                                      OpenSSL                                                                     REQ(1)

NAME
       req - PKCS#10 certificate request and certificate generating utility.

SYNOPSIS
       openssl req [-inform PEM|DER] [-outform PEM|DER] [-in filename] [-passin arg] [-out filename] [-passout arg] [-text] [-pubkey] [-noout] [-verify]
       [-modulus] [-new] [-rand file(s)] [-newkey rsa:bits] [-newkey alg:file] [-nodes] [-key filename] [-keyform PEM|DER] [-keyout filename] [-keygen_engine
       id] [-[digest]] [-config filename] [-multivalue-rdn] [-x509] [-days n] [-set_serial n] [-asn1-kludge] [-no-asn1-kludge] [-newhdr] [-extensions section]
       [-reqexts section] [-utf8] [-nameopt] [-reqopt] [-subject] [-subj arg] [-batch] [-verbose] [-engine id]

DESCRIPTION
       The req command primarily creates and processes certificate requests in PKCS#10 format. It can additionally create self signed certificates for use as
       root CAs for example.
以下略

LinuxブロックデバイスとNFSとネットワークの関係性

会社でディスク(ブロックデバイス)とNFSの違いはという話題になったので、Linux kernelの中のブロクデバイスNFS(ファイルシステム)、ネットワークの関係をざっくりしたポンチ絵に落としてみました。(簡素化するため箸折っていたり、そもそも私の理解が曖昧な部分もあるので、マジマジ見ると色々気になるかもしれないです)

f:id:nopipi:20180712022708p:plain
Linuxカーネルのブロックデバイスファイルシステム、ネットワークの位置付け

  • 凡例
    • 青色:共通インターフェース
      • VFS(Virtual File system): ファイルシステムを抽象化している層
      • blk:正式な名称がわからないですが、ブロックデバイスを抽象化している層
      • socket:ソケット通信(networkは、ソケット通信で抽象化されている)
    • 緑色:ファイルシステム
    • 黄色:各プロトコル、またはハードに依存しない上位のデバイス
    • 橙色:ハードウェアデバイス、またはハードウェア

Amazon Linux2にdockerをセットアップする手順

Amazon Linux2上にdocker環境を作った時のメモです。

手順

インスタンスを立ち上げて、sshログインしてからの手順です。

(1)dockerのインストール

sudo yum -y update
sudo yum -y install docker

(2)dockerサービスの起動

最初の"start"でdockerサービスを開始(dockerデーモン起動)します。次のenableでOS起動時のサービス開始を有効化します。

sudo systemctl start docker.service
sudo systemctl enable docker.service

(3)ec2-userユーザへの権限付与

dockerコマンドでの操作を行うには、dockerグループに所属している必要があります。usermodコマンドで、ec2-userのセカンダリグループにdockerグループを追加します。

sudo usermod -a -G docker ec2-user

ログイン中のセッションには設定が反映されないため、一度ログアウト&ログインをおこない、idコマンドで設定を確認します。

ログアウト&ログイン後に、
$ id
uid=1000(ec2-user) gid=1000(ec2-user) groups=1000(ec2-user),4(adm),10(wheel),190(systemd-journal),994(docker)

(4)確認

dockerコマンドを実行して確認する。実行して、ClientとServerの両方の情報が表示されればOKです。

$ docker version
Client:
 Version:      18.03.1-ce
 API version:  1.37
 Go version:   go1.9.6
 Git commit:   3dfb8343b139d6342acfd9975d7f1068b5b1c3d3
 Built:        Fri Jun 15 23:15:12 2018
 OS/Arch:      linux/amd64
 Experimental: false
 Orchestrator: swarm

Server:
 Engine:
  Version:      18.03.1-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.6
  Git commit:   7390fc6/18.03.1-ce
  Built:        Fri Jun 15 23:17:24 2018
  OS/Arch:      linux/amd64
  Experimental: false
  • Server側のエラー
    • "Cannot connect to the Docker daemon...”: dockerデーモンが起動していない可能性。(2)とNW設定を見直し
    • "Got permission denied while trying to connect ":権限がない可能性。(3)を見直し