kubernetes+ansibleでつくる最新linuxディストリビューション開発環境
TRANSCRIPT
Kubernetes+Ansibleでつくる最新Linuxディストリビュー
ション開発環境
日本アイ・ビー・エム株式会社
アドバンスド・コンピューティング
佐藤 和茂
自己紹介
名前:佐藤 和茂
インフラSEです
2009年入社以来、ハイパフォーマンス・コンピューティング(HPC)とクラウド(IaaS)をメインにインフラ構築・運用などをやっています
学生時代は競技プログラミングに熱中
ライト・プランが使えるようになりました• Kubernetes Clusterが利用できます
• 無料枠があるのに遊ばせておくのはもったいない!
Kubernetes環境の使い方
• 一般的な使い方• コンテナー・ネイティブなアプリケーションを開発• レジストリーにイメージを登録• 開発したアプリケーションをクラスターにデプロイ
• 今回の使い方最新のLinuxディストリビューションが使える開発環境が欲しい!
• 汎用的なDockerイメージをデプロイして、開発環境として利用• 使い慣れた構成管理ツールで開発環境を整備• 無料枠をめいっぱい活用
Dockerイメージの起動方法
• 通常のDockerで汎用的なOSイメージ(ubuntu, fedora, etc.)を起動するときのおまじない• run /sbin/init
• /sbin/initは最近のOSではシンボリックリンクになっていて、systemdが起動
• 起動時の実行コマンドに指定することでsystemdが常駐するのでsystemctlによるサービス起動・停止などの操作が可能
• 夏頃まではKubernetesでも問題なく利用できた
Kubernetesバージョンアップ
• 9月下旬にIBM CloudのKubernetesが1.4から1.7にバージョンアップ
• アップグレード後にKubernetesで/sbin/initを起動すると・・・
• ログには/sbin/initが起動できないというメッセージが出ているようにみえる
問題判別
• いろいろ試すと、他のコマンドは普通に実行できるが、/sbin/initだけが実行できないことがわかる
• 同じイメージを使って、Kubernetesではなく手元のDockerでrun /sbin/initを実行すると普通に動く
• 問題判別のためにsleepを実行して、kubectl exec –it /bin/bashでログインしてみた
• こいつだ!
pauseコンテナー
• Pod上のコンテナーが死んでしまったときに、Podのネットワークが削除されてしまうのを防ぐ(何もしない)コンテナー
• KubernetesはDockerのバージョンが1.13.1以上の場合、Pod間でPIDの名前空間を共有する
Enable shared PID namespace by default for docker pods #45236
(https://github.com/kubernetes/kubernetes/pull/45236)
• /pauseプロセスが、デプロイされたコンテナー内でPID=1を占有していたため、/sbin/init(=systemd)プロセス(通常PID=1で起動)を起動させることができなかった
回避策
• 回避策:systemdを1以外のPIDで起動させる• デプロイ時に指定するコマンドを、/sbin/initか
ら”/usr/lib/systemd/systemd --system”に変更
→ “--system“ : PIDが1でない場合でもsystemモードで起動させるsystemdにはsystemモードとuserモードの2つのモードがあり、通常はPIDが1かどうかで起動すべきモードが切り替わる
• “SYSTEMD_IGNORE_CHROOT=1”の環境変数を設定
→ chroot環境でも、システム関連の操作を実行できるようにする
PID=5で起動した!
各種最新Linux OSの起動方法
• Docker Hubにある各種Linux OSの公式イメージをそのままBluemixKubernetesで起動させるためのパラメータ• fedora:26(*), centos:7.4.1708, etc.
• 実行コマンド:/usr/lib/systemd/systemd• 引数:--system• 環境変数: SYSTEMD_IGNORE_CHROOT=1
• ubuntu:zesty(17.04), etc.• 実行コマンド:/bin/sh• 引数(**):-c apt-get update&&apt-get -y install
systemd&&SYSTEMD_IGNORE_CHROOT=1 /lib/systemd/systemd --system
(*) 11月に公開されたfedora:27では最初からsystemdが1以外のPIDで起動できるようにイメージが作成されていることを確認(=実行コマンドに/sbin/initを指定するだけで起動可)
(**) KubernetesのDashboardでデプロイメントを作成する場合はYAMLの編集が必要(GUIでは引数が1つしか指定できないため)
できるようになったこと
• コンテナーにkubectl exec –it /bin/bashなどで接続して、たとえば次のようなことができます(ubuntuの場合)
apt-get install vim sudo ssh gnome-core vnc4serversystemctl start gdmapt-get install ubuntu-mate-desktopadduser user1visudosu – user1vncserver• だいたいのことはできます
• Kubernetesのサービスと組み合わせることでNATネットワークに接続しているVMのように利用可能
構成管理ツールによる自動構成
• sshでログインできるようになったので、rsyncでファイルを送り込んだり、AnsibleやChef(Knife-Zero)などの構成管理ツールで好きな環境に自動構成することが可能
• 別環境で利用しているPlaybook/Recipeをそのまま活用可能
• ポートは変更されているが、sshのセキュリティには注意• rootログイン禁止• 鍵認証• fail2banなどの導入• リモートログインが不要なときはsshdを停止したり、Kubernetes側の
サービスを削除
開発環境をさらに充実させよう
• 隣でjenkinsやredmine、wekanなどのコンテナーを動かす• DockerHubの公式イメージをデプロイするだけ
• コンテナー1つ動かすだけではストレージ永続化はできないので注意
• たまにコンテナーに入ってObject Storage等にファイルをバックアップすることはできる
• httpなのはちょっと嫌
• https化は真面目にnginxなどを立ててもいいが、その場合ポート番号は選べない
• CFアプリで簡易リバースプロキシを作ってSSLオフロードをさせるほうがmybluemix.netのドメインも使えて便利
CFアプリでつくる簡易リバースプロキシ
• Python Flaskで簡易的なリバースプロキシを作ってみます• あくまでテスト用(本格利用を想定したものではありません)
• Getting Started with Python on IBM Cloud (https://github.com/IBM-Bluemix/get-started-python)をcloneして、hello.pyを書き換え(次ページのスライドを参照)
• 「host =」の行にKubernetesのワーカー・ノードのグローバルIPとサービスで外部にexposeしたポートを記載
• httpで来た場合、httpsにリダイレクトさせる
• POSTしたときなど、リダイレクト先がKubernetesのIPで返ってくるので、レスポンスヘッダーのLocationも書き換える
(https://gist.github.com/k-sat/0305f2627c4eca24fafff442a22b7ef6)
Redmineのコンテナーを動かした例
from flask import Flask, request, redirect, Responseimport cf_deployment_trackerimport osimport requests
host = ‘xxx.xxx.xxx.xxx:yyy'cf_host = 'k8s-proxy.au-syd.mybluemix.net'
port = int(os.getenv('PORT', 8000))cf_deployment_tracker.track()app = Flask(__name__)
@app.before_requestdef before_request_handler():
if 'X-Forwarded-Proto' in request.headers:if request.headers['X-Forwarded-Proto'] != 'https':
url = request.url.replace('http://', 'https://', 1)return redirect(url, code=301)
@app.route('/', defaults={'url': ''})@app.route('/<path:url>', methods=['GET', 'POST'])def cfproxy(url):
resp = requests.request(method=request.method, url="http://{}/{}".format(host, url),headers={k: v for (k, v) in request.headers if k != 'Host'},data=request.get_data(), cookies=request.cookies,allow_redirects=False)
exclude = ['connection', 'content-encoding','content-length', 'transfer-encoding']
headers = []for key, value in resp.raw.headers.items():
if key.lower() == 'location':value = value.replace(host, cf_host)
if key.lower() not in exclude:headers.append((key, value))
return Response(resp.content, resp.status_code, headers)
if __name__ == '__main__':app.run(host='0.0.0.0', port=port, debug=True)
簡易リバースプロキシの構成
HTTP
Kubernetes
IBM Cloud(Sydney)
Cloud Foundry
Kubernetesサービスhttp://xxx.xxx.xxx.xxx:yyy
https://k8s-proxy.au-syd.mybluemix.netにアクセス
インターネットCFアプリhttps://k8s-proxy.au-
syd.mybluemix.net
URL書き換えrequests.request()
redmine:latesthttp://10.zzz.zzz.zzz:3000
応用事例紹介
Kitchen-Ansiblepushを利用したPlaybook開発例• 社内ではコンテナー技術を活かした自動テストを実施
• GitHubにpush
• Travis CIの自動ビルドによりVM上にChefDK, Ansible, Kitchen-Docker, Kitchen-Ansiblepush導入
• Test-Kitchenが自動テスト開始• Kitchen-DockerがDockerイメージを起動
• Kitchen-AnsiblepushがDockerコンテナにSSH経由でAnsible実行
• InSpecでVerify
• Kitchen-Ansibleではなく、Kitchen-Ansiblepushを使って開発しておいたことで、今回のようなSSHが使える環境でそのまま適用できた.travis.ymlサンプル(https://gist.github.com/k-sat/0c8e4fb5c9df60f658e236227cdd4028).kitchen.ymlサンプル(https://gist.github.com/k-sat/214ce8422ebfe9761398f47304737ecc)
この資料に含まれる情報は可能な限り正確を期しておりますが、日本アイ・ビー・エム株式会社の正式なレビューを受けておらず、当資料に記載された内容に関して日本アイ・ビー・エムは何ら保証するものではありません。
ワークショップ、セッション、および資料は、IBMまたはセッション発表者によって準備され、それぞれ独自の見解を反映したものです。それらは情報提供の目的のみで提供されており、いかなる参加者に対しても法律的またはその他の指導や助言を意図したものではなく、またそのような結果を生むものでもありません。本講演資料に含まれている情報については、完全性と正確性を期するよう努力しましたが、「現状のまま」提供され、明示または暗示にかかわらずいかなる保証も伴わないものとします。本講演資料またはその他の資料の使用によって、あるいはその他の関連によって、いかなる損害が生じた場合も、IBMは責任を負わないものとします。本講演資料に含まれている内容は、IBMまたはそのサプライヤーやライセンス交付者からいかなる保証または表明を引きだすことを意図したものでも、IBM ソフトウェアの使用を規定する適用ライセンス契約の条項を変更することを意図したものでもなく、またそのような結果を生むものでもありません。
本講演資料でIBM製品、プログラム、またはサービスに言及していても、IBMが営業活動を行っているすべての国でそれらが使用可能であることを暗示するものではありません。本講演資料で言及している製品リリース日付や製品機能は、市場機会またはその他の要因に基づいてIBM独自の決定権をもっていつでも変更できるものとし、いかなる方法においても将来の製品または機能が使用可能になると確約することを意図したものではありません。本講演資料に含まれている内容は、参加者が開始する活動によって特定の販売、売上高の向上、またはその他の結果が生じると述べる、または暗示することを意図したものでも、またそのような結果を生むものでもありません。パフォーマンスは、管理された環境において標準的なIBMベンチマークを使用した測定と予測に基づいています。ユーザーが経験する実際のスループットやパフォーマンスは、ユーザーのジョブ・ストリームにおけるマルチプログラミングの量、入出力構成、ストレージ構成、および処理されるワークロードなどの考慮事項を含む、数多くの要因に応じて変化します。したがって、個々のユーザーがここで述べられているものと同様の結果を得られると確約するものではありません。
記述されているすべてのお客様事例は、それらのお客様がどのようにIBM製品を使用したか、またそれらのお客様が達成した結果の実例として示されたものです。実際の環境コストおよびパフォーマンス特性は、お客様ごとに異なる場合があります。
IBM, IBM ロゴ、ibm.com, は、世界の多くの国で登録されたInternational Business Machines Corporationの商標です。
他の製品名およびサービス名等は、それぞれIBMまたは各社の商標である場合があります。
現時点でのIBM の商標リストについては、www.ibm.com/legal/copytrade.shtmlをご覧ください。