HTTPS
docker-compose
rancher
nginx-proxy
letsencrypt

rancherをdocker-composeでhttpsでたてた

More than 1 year has passed since last update.

Rancherをたててそれで社内の色々を勉強がてら移行してみてねとタスクをふられ、とりあえずdocker runでたてたもののhttpだとアクセスコントロールの設定をAzureAD連携できねえな(そもそも認証が平文て危ないよね!)と思ってせっかくだからdocker-composeでnginx-proxyとletsencryptでhttpsにしてみた話です。
別にhttpsにするとこはコンテナでやらなくても良かったんですがまあそこはやってみたかっただけっすね(楽しかったです)。

なんかコンテナとか普段使ってなくてよく知らなかったので調べたりマニュアル読むのに超時間がかかりました(そしてまだ理解度は低めです)がやってみると短時間でできるのでファー!ってなりました。

インスタンスの準備はAzureのCloudShellとTerraformでやりました(サービスプリンシパル不要らしいCloudShell使ってみたかっただけ)。
画面からポチポチやる方法はここに書いてあったので参考にどうぞ。

で、dockerいれるとこはAnsibleをつかいました。なんかdocker-ceだと17が入るんだけどrancherがk8sサポートしてるらしいのがdocker-engine1.12らしくバージョン下げるときにdockerのデータディレクトリ(/var/lib/docker)を消し去らないとストレージドライバのエラーが出ててdocker.ioを入れて消したらデータディレクトリが消えてくれました。この辺のdockerの種類の相関関係もちょっとよくわかっていません。 書いてる人がいた→docker-engine、docker-ce、docker.ioの違い - よくある日記

Rancherとは

カタログを作っとくか既存のカタログを使うと手軽にコンテナの構成を作れるGUIのコンテナ管理(オーケストレーション)ツール
という理解でうれしいことについては使い倒してなくて腑に落ちきってないのですが以下のあたりが参考になりました。
Rancher と GitLab を使う3つの理由
Rancherとは – WebARENA backstage
rancherでコンテナベースのサーバ運用を始めた話 - Aqutras Members' Blog

ホストの構成やRancherの推奨スペックなど

とりあえずVM一台の上にコンテナたてただけでmysqlはマウントしただけで外部接続にしてないのでHAでないです。
HAには外部のMySQLクラスタへの接続、外部LBのセットアップ、クラスタ間での必要ポートの解放などが要る模様

推奨要件

Ubuntu 16.04
64-bit
kernel of 3.10+
1GB Memory
Docker 1.10.3+

letsencryptでhttpsにするにあたり気にするところとしては、事前にドメインレコード登録して名前解決できるようにしておくということと、クラウドプロバイダがデフォルトで提供するようなドメインだとDDoS扱いというか週に1つのドメイン20個までしか登録できない的な制限に引っかかるので独自のを用意する必要がある、など。(あとAzureAD連携的にはテナントに許可されてるドメインじゃないと通らないとかはあるかと思いますが今のところそっちはうまくいってない(テナント管理者アカウント設定してMFA無効とアクセス権の変更あたりが要るっぽいあたりがアレで))

HA構築方法はこちらに書いてくださっているのがありました。(2台のホストにそれぞれマスタとスレーブのコンテナ立てておりGTIDは有効っぽくてCHANGE_MASTERにバイナリログのポジション指定要らない感じでmysqlfailoverとかはしてないので手動切り替え)

こちらにもHA記事あったので追記。これはDBはコンテナじゃなくてpacemakerですね。
(SSHがコンテナでは使えないのでコンテナ上でMHAやpacemakerはなんか無理ぽい)

サービスレベル的に夜間休日に自動切り替わりしてほしい等でないなら手動でいいかも。
呼び出される可能性があるなら自動にしたほうが幸せかも。

Docker入れるAnsibleタスク

dockerengine_versionは'docker-engine=1.12.6-0~ubuntu-xenial'と指定しました

role/docker/tasks/main.yml
# install docker
- name: Check kernel version.
  fail: msg="Kernel {{ ansible_kernel }} is not supported."
  when: "ansible_kernel | version_compare('3.10', '<')"
- block:
  - name: apt-get install packages
    apt: pkg={{ item }} state=present update_cache=yes
    with_items:
      - apt-transport-https
      - ca-certificates
      - curl
      - linux-image-extra-virtual
      - linux-image-extra-{{ ansible_kernel }}
      - software-properties-common
  - name: Check docker gpg key.
    shell: apt-key fingerprint 0EBFCD88 | grep 0EBFCD88
    register: docker_gpg
    ignore_errors: True
    changed_when: False
  - name: Add Docker’s official GPG key
    shell: curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
    when: docker_gpg | failed
  - name: set up the stable repository
    shell: add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
  - name: Install docker-ce.
    apt: 
      name: "{{ item }}"
      state: present
      update_cache: yes
    with_items:
      - docker-ce=1.12*
      - docker-compose
    notify:
      - docker-restart
    when:
      - kind_of_docker == "docker-ce"
  - name: Install docker-engine
    apt:
      name: "{{ item }}"
      state: present
      update_cache: yes
    with_items:
      - "{{ dockerengine_version }}"
      - docker-compose
    when:
      - kind_of_docker == "docker-engine" 
  when:
    - ansible_distribution == "Ubuntu"
    - ansible_lsb.major_release > 14
docker-compose.ymlの内容と解説
docker-compose.yml
# cat docker-compose.yml 
version: '2'
services:
  rancher-server:
    image: rancher/server:stable
    container_name: "rancher"
    environment:
      VIRTUAL_PORT: 8080
      VIRTUAL_HOST: <server-name>
      LETSENCRYPT_HOST: <server-name>
      LETSENCRYPT_EMAIL: <my-email>
    volumes:
      - '/home/docker/rancher-server/mysql:/var/lib/mysql:rw'
  nginx-proxy:
    image: jwilder/nginx-proxy:latest
    container_name: "nginx-proxy"
    depends_on:
      - rancher-server
    ports:
     - "80:80"
     - "443:443"
    volumes:
      - '/home/docker/nginx-proxy/ssl:/etc/nginx/certs:ro'
      - '/etc/nginx/vhost.d'
      - '/usr/share/nginx/html'
      - '/var/run/docker.sock:/tmp/docker.sock:ro'
    logging:
      driver: syslog
  letsencrypt-nginx-proxy-companion:
    image: jrcs/letsencrypt-nginx-proxy-companion:latest
    container_name: "letsencrypt"
    depends_on:
      - rancher-server
      - nginx-proxy
    volumes_from:
      - nginx-proxy
    volumes:
      - '/home/docker/nginx-proxy/ssl:/etc/nginx/certs:rw'
      - '/var/run/docker.sock:/var/run/docker.sock:ro'
networks:
  default:
    external:
      name: common_link

ググったら出てきたものを参考に若干変えただけです。

servicesでそれぞれのコンテナのサービスを定義、
(上から順にコンテナが起動するためrancherを上にしないとletsencryptでエラー出る) →depens_onで後から起動するサービス側に先に起動させたいサービスを定義するとよさそうでversion2ではlinksは自動的に行われるので不要
imageで利用するイメージを指定(rancherはstableをpreviewにすると2.0が入る模様)、
container_nameでコンテナの名前を定義(atattchとかコンテナ間で名前で接続するのにつかう)
environmentはどうやら指定しておくと勝手に検知してnginx-proxyがリバースプロキシ設定してくれたりletsencryptが証明書作ってくれたりするものらしい(スゲー)
portsでホストポート:コンテナポートのフォワーディング指定でホストポートは自動的に公開
volumesでhost_volume:container_volumeという感じにマウントしてる
 host_volumeの指定がないのはvolumes_fromでnginx-proxyからletsencryptにコンテナ間で連携する用ぽい
 rwは読み書きする、roは読むだけ
 dockerのソケットはホストのdockerの終了をコンテナ側で検知するためのもの
 mysqlrancherが内部的に利用してるらしくデータディレクトリをホストにマウントすることでデータの消失を免れるようにしてる
 クラウドならRDBMSはマネージドのやつに外だしするのが正しいかもしれない(外部指定オプションが存在する
loggingでコンテナのサービスのログをドライバsyslogでホストのsyslogに転送
 これやるとrancher側で表示できなくなるのでrancherで確認したい場合は他のやり方考えたほうがよさげ
 改ざん防止他かBlueGreenで入れ替えるのに備えてどっかに飛ばしたい場合はfluentdで飛ばすとかもできるぽい
networksでブリッジネットワークを作成してコンテナ間はコンテナ名で自在に行き来できる用にした

docker-compose upだけだとctrl+cで抜けるとdockerコンテナが勝手にstopするので-dつける必要がある

rancherに限っては--helpオプションでどんなオプションが使えるか出る感じになってたのでだいぶ親切だなあと思いました

docker run rancher/server --help

実施したコマンドなど
## 必要そうなディレクトリとymlを準備
 mkdir -p /home/docker/{rancher-server,nginx-proxy}
 cd /home/docker/rancher-server/
 mkdir mysql
 vi docker-compose.yml 
 mkdir ../nginx-proxy/ssl
 mkdir -p /etc/nginx/vhost.d
 mkdir -p /usr/share/nginx/html

## dockerあがってるよな確認
 ls /var/run/docker.sock

## networkを作っておく
 docker network create --driver bridge common_link

## コンテナを起動して確認
 docker-compose up -d
 docker ps
 docker images
 docker run rancher/server --help

## 起動したコンテナが紐づけられてるネットワーク情報を確認
 docker network ls
 docker network inspect common_link

## データディレクトリがマウントされてて証明書が作成されてることを確認
 ll mysql
 ll /home/docker/nginx-proxy/ssl

少し待つとhttpsでサイトにアクセスできるようになりました。

docker-composeの上げ下げ方法は--helpうつと出てくる感じでした。
よく考えずにうっかりdown打つと跡形もなく消えるので注意が必要なことがわかりました。

rancher/agentを入れてrancherにホスト登録する

とりあえずrancher/server入れたホスト本体にrancher/agent入れてホストをrancherに認識さしたところ上がってるコンテナ情報を勝手に取ってきてくれてました。
(1.6だとCattleがデフォだけどDockerがKubernetesネイティブサポートとかの関係でEnvironment追加してtemplateをKubernetesにしてからホストにagent追加したほうがいいのかもしれないなーとおもったのですが2.0からの話な模様)
Investigating of kubernetes Platform
Kubernetes etc.. & rancher 2.0 technical preview “Let’s import GKE/Bluemix/AKS K8S Clusters !!” Multi Containers “K8S”

INFRASTRUCTURE>Hosts>AddHost>Custom>5のコピペ>ホスト上で実行しrancher/agentのコンテナ起動さす
すると1分くらいでホスト情報が画面に表示されます

5のコピペ参考コマンド
sudo docker run -e CATTLE_AGENT_IP="<ホストのGlobalIP>"  -e CATTLE_HOST_LABELS='Name=<ホスト名>' \
 --rm --privileged -v /var/run/docker.sock:/var/run/docker.sock \
 -v /var/lib/rancher:/var/lib/rancher rancher/agent:v1.2.6 https://<ホストのURL>/v1/scripts/...

ホスト内に表示されたコンテナそれぞれポインタするとそこからrestartとか停止とかログ見たりなど自在にできる感じでした。これだけでもだいぶ便利かもしれないですねー。cattleのSTACKSとCATALOGも便利らしいのであとで。。

rancher-container-mng.png

INFRASTRUCTURE>Containersからコンテナのイメージ名とか打ったコマンドとか全部見られる感じでした。
(docker psでみれるやつかなー)
間違って打ったdockerコマンドが停止状態で表示されててそういうのは消せばよさげでしたね。

rancher-containers.png

とりあえずこんなところで失礼します。

他に要りそうだなと思っているのは
・ホストを何台か追加(載ってるクラウド的に可用性のゾーン分ける)
・HA化(要、外部のMySQLクラスタへの接続、外部LBのセットアップ、クラスタ間での必要ポートの解放)
・ホストとコンテナ間で連携するための外部ストレージの用意
・kubernetesとDockerとrancherとdocker-composeそのものに対する仕組みと操作の理解を深める
 コンテナ内の設定ファイル操作して更新する方法とかあんまりわかってないので調べる
 etcdとか分散システムについて全く知らないのをもうちょっと理解する
・Gitlab、Gitlab-runner(CI)、コンテナレジストリを準備する(runnerは、複数コンテナ相乗りだとリソースを食い合いそうかなー)
・ログを飛ばして一括管理することについて検討する
・バックアップとレストアをどこまでどうやればよさそうか調べてやってみる
・アラート監視とグラフ監視についてどうやってやんのかを調べてやってみる
ってところですかね。。

参考サイト

クイックスタートガイド
Installing Rancher Server with SSL
Docker × Nginx × Let'sEncrypt | 俺の考えた最強のサーバー構築方法! | Hackers Log
Docker-compose for rancher, nginx and let's encrypt
network コマンドを使う — Docker-docs-ja 17.06.Beta ドキュメント
Compose を始めましょう — Docker-docs-ja 17.06.Beta ドキュメント
サービスの拡張と Compose ファイル — Docker-docs-ja 17.06.Beta ドキュメント
Compose の起動順番を制御 — Docker-docs-ja 17.06.Beta ドキュメント
DockerコンテナにNginxリバースプロキシを導入
【Docker】RancherOSで本格的な自宅サーバーを構築しよう(2) ~ rancher-serverをインストール ~ - Qiita
nginxを使ったリバースプロキシ on Docker - Qiita
Setting up Rancher to authenticate with AzureAD | Marius Sandbu
Check! Rancher のホストとして Azure を登録してみよう! - Qiita
How to Run GitLab in Rancher
Rancher/Kubernetes入門ハンズオン資料~第2回さくらとコンテナの夕べ #さくらの夕べ 番外編
Rancher プライベートカタログとCompose
Investigating of kubernetes Platform
Kubernetes etc.. & rancher 2.0 technical preview “Let’s import GKE/Bluemix/AKS K8S Clusters !!” Multi Containers “K8S”

余談ですがdockerのドキュメントサイトは英語の方が情報が多い気がしました。(気のせいかもしれない)
日本語サイトみてても.jpを.comに変えて.htmlを/にすると英語ページが出てくる感じでした。