infrastructure
Docker
Ansible
kubernetes
ansible-container

Kubernetes x Ansible Container(ansible-containerの概要)

More than 1 year has passed since last update.

みなさま、クリスマスケーキの準備はできていますでしょうか?

本エントリーはKubernetes Advent Calendar 2016の23日目、クリスマス・イブ・イブの記事です。

今回は、Ansibleを利用してKubernetes上にコンテナを簡単にデプロイする方法について紹介したいと思います。

何で、Kubernetes Advent CalendarなのにAnsibleかといいますと。まぁ…。マイブームみたいなもんです。


Promotion!!

Ansibleってどうやって使うの?って方は、是非×2、こちらも見て頂けるとうれしいです。

Qiita 「Ansible実践ガイド」出版しました。

レビュー、感想お待ちしております。


概要

さて、今回はKubernetes環境をAnsibleで作ろうっ!!というタイトルではありません。

Ansibleを利用したKubernetes環境のセットアップは、Ansible-Galaxy上にも多数あります。また、以前は「kubespray」というプロジェクトがあったのですが、いつの間にか閉鎖されているため、現在は本家のGit上のプレイブックがおすすめです。

https://github.com/kubernetes/contrib/tree/master/ansible

ということで、今回はAnsible Containerを使って、Kubernetes上にコンテナをデプロイする操作を紹介します。Ansible Containerを使うと何が嬉しいのかというと、KubernetesのPodやReplicaSet、Deploymentに必要なYAML記法を覚えなくても、コンテナのライフサイクルが管理できるという点です。


Ansible Containerとは

Ansible Containerは、Dockerコンテナのビルド/展開/管理の自動化を、Ansibleのプレイブックから行えるオープンソースプロジェクトです。AnsibleのDockerモジュールでできる機能に加えて、コンテナアプリケーションのライフサイクル全体を自動化することができます。

たとえば、Ansibleだけでdocker buildを行おうとすると、Dockerfileを生成したあとに「docker_image」モジュールを利用します。その次にできたコンテナを元にpod.yamlなどを生成してから「kubernetes」モジュールを利用するといった流れが必要ですが、これらをansible-containerコマンドを利用すると、プレイブックだけで全てを管理することが可能になります。

(参照) Ansible Container Doc


Ansible Containerのインストール

論より証拠ということで、実際に手を動かしてみたほうが、感覚が掴みやすいかと思います。


システム要件

ansible-containerを利用するためには、以下があらかじめセットアップされている必要があります。


  • Python 2.7

  • pip

  • setuptools 20.0.0+

  • Docker Engine(Dockerデーモンへの接続)

  • Docker Repository(Kubernetes上に展開する場合)


インストール手順

ansible-containerは、pipから簡単にインストールできます。ただし現時点(2016末)では、まだ未成熟なプロダクトということもあるため、ソースからのインストールをおすすめします。

$ virtualenv venv

$ source ./venv/bin/activate
$ git clone https://github.com/ansible/ansible-container.git
$ cd ./ansible-container
$ python ./setup.py install
$ ansible-container version
Ansible Container, version 0.3.0-pre

今回使用したバージョンは、0.3.0開発版です。


Ansible Containerのコンポーネント

まずは、各コンポーネントを整理しておきましょう。


コマンドオプション

ansible-containerのオプションは、以下になります。Dockerコンテナのライフサイクルをコマンド一つで操作するため、それぞれどのファイルを利用して、何を行っているオプションなのかを理解しないと、始めは意外とわかりづらいです。

Option
プロジェクトファイル
動作

init
--
ansible-containerのプロジェクトファイル群を初期作成する。

run
container.yml
ビルドで作成した対象コンテナイメージを起動する。

install
--
Ansible-Galaxy上から特定プロジェクトをロードする。

push
container.yml
ビルドしたコンテナイメージを、リポジトリに保存する。

shipit
container.yml
リポジトリ上の対象コンテナイメージをオーケストレーションエンジンに配備するプレイブックの作成。

stop
container.yml
起動している対象コンテナを停止する。

restart
container.yml
起動している対象コンテナを再起動する。

build
container.yml main.yml requirements.txt
指定したコンテナイメージを利用して、コンテナの作成、ビルド、コミットを行う。


プロジェクトファイル

まず、プロジェクト名のフォルダを作成し、その中でinitを行うと以下のプロジェクトファイル群ができます。

$ mkdir -v ./k8s

$ cd ./k8s
$ ansible-container init
$ ls -la ./ansible
container.yml
main.yml
meta.yml
requirements.txt
requirements.yml
ansible.cfg

この中でも特に重要なのが、container.ymlmain.ymlです。


container.yml

Dockerfileや、Docker Composeのスキーマに近く、このファイルにコンテナの定義を行います。これを利用して、ビルドするイメージ、実行するコンテナ、そしてリポジトリに登録するイメージが決定されます。


container.yml

version: "2" ##固定

services:
web: ##イメージ名
image: "ubuntu:trusty" ##ベースイメージ
ports: ##ポートバインド
- "80:80"
command: ["/usr/bin/dumb-init", "/usr/sbin/apache2ctl", "-D", "FOREGROUND"] ##起動コマンド
dev_overrides: ##注釈(※1)
environment:
- "DEBUG=1"

※1. dev_overridesは、ローカルのコンテナエンジン上で動かす時など、開発環境の場合にのみ適応されるセクションです。

※2. サポートされている、細かなディレクティブは公式ページを参照ください。


main.yml

コンテナをビルドする際(ansible-container build)に、設定したい作業をプレイブック形式で定義します。この際、コンテナへの接続はSSHではなく、ビルド時に作成されるインベントリを元に、Docker Connection Pluginによって接続されます。

main.ymlにより、いままでDockerfileに記述していた「RUN command && \」のシェル芸作業を、全てプレイブック化することができます。もちろん、コンテナ内のタスクが肥大化するのはおすすめしませんが、roleを利用することも可能です。


requirement.txt

特定のAnsibleモジュールではPythonのライブラリを追加しないと、利用できないモジュールがあります。コンテナをビルドする際も同様に、main.ymlの中で使われているモジュールにおいて、他のPythonライブラリが必要なものは、事前にこのファイルにpip形式で記述しておくとインストールしてくれます。


Ansible Containerによるコンテナのライフサイクル管理

コンポーネントの要素を抑えた上で、ansible-containerで実現できる、コンテナのライフサイクルを抑えておきましょう。すべての工程がDocker環境上で作業が行われるため、DOCKER REMOTE API(Dockerエンジン)に接続できる状態にしておく必要があります。(DOCKER_HOST環境変数 or UNIXドメインソケット)


  1. コンテナのビルド

    「ansible-container build」を実行して、新しいイメージを作成しコミットします。この際、ベースとなるイメージは、container.ymlの情報をもとにし、main.ymlで定義した作業を実施してくれます。


  2. コンテナの起動

    「ansible-container run」を実行すると、1で作成したイメージを指定のDockerエンジン上で起動します。要するに、ライフサイクルでいうところのテスト環境へのデプロイです。


  3. コンテナイメージのレジストリ登録

    「ansible-container push」を実行して、container.ymlに記載されたレジストリにコンテナイメージを登録します。


  4. Kubernetesへの展開用プレイブックの作成

    「ansible-container shipit」を実行して、container.ymlに記載したレプリカ設定でイメージをデプロイするためのプレイブックを作成します。ただし、現状サポートされているオーケストレーションエンジンは、KubernetesとOpenShiftの2択です。


  5. Kubernetesへの展開 ※本テーマの主旨

    kubectlを使用して4で作成されたプレイブックをもとに、レジストリからイメージをPULLして展開します。ライフサイクルでいうところの本番環境へのデプロイです。



(補足)Kubernetes環境の準備

今回はRancherを利用して、Kubernetes環境を構築しました。Kubernetesの投稿なのに、Kubernetesの設定説明を端折ります。。。すいません。

※Rancher使ってるなら、UIからデプロイできるじゃん…って突っ込むところではないです。あくまでKubernetesのYAML設定を記述しなくてもOKなところが売り。

Rancherを使用した構築方法は、以下がおすすめです。

Helion OpenStackの上にRancherでKubernetesクラスタを構築してみる(その1)

ansible-containerをインストールしたホストに、kubectlコマンドとkubernetes APIへの接続ができるようにしておきましょう。

WS00000003.JPG


Ansible Containerの実装

長い×2、説明でしたが。。。ここまできてやっと本題です。

簡単なデモ実装により、Kubernetes環境にコンテナをデプロイしてみたいと思います。今回はKubernetes環境にnginxのコンテナをデプロイしてみます。


1. コンテナのビルド

まずcontainer.ymlを作成し、ベースイメージを作成します。今回はmain.ymlには特に何も設定しませんが、必要な設定を行って下さい。

# mkdir -v ./k8s && cd ./k8s

# ansible-container init
# vi ./ansible/container.yml
# vi ./ansible/main.yml ##必要な作業がある場合
# ansible-container build
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
k8s-web 20161222184749 ae8305383ae5 8 seconds ago 180.7 MB
k8s-web latest ae8305383ae5 8 seconds ago 180.7 MB


container.yml

version: "2"

services:
web:
image: "nginx:stable"
ports:
- 8080:80
command: ["nginx", "-g", "daemon off;"]
dev_overrides:
environment:
- "DEBUG=1"
options:
kube:
replicas: 2
registries:
docker_regist:
url: https://hub.docker.example.local
namespace: shingo.kitayama/test


2. コンテナの起動

この作業は必須ではありませんが、できたコンテナイメージの起動を行ってみましょう。インベントリなどは、指定する必要はありません。

# ansible-container run

Attaching to ansible_ansible-container_1
Cleaning up Ansible Container builder...
Attaching to ansible_web_1
....[CTL + C]
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ff70c14b54fb k8s-web:latest "nginx -g 'daemon off" 17 minutes ago Exited (0) 17 minutes ago ansible_web_1

今回、Nginxを起動しているため、コンテナを起動するとNginxのプロセスにAttachしてしまいます。実はansible-containerには、まだバックグラウンド起動(docker run -d)というオプションがありません。よって、一度プロセスを切ってみると、確かに起動していたことが確認できます。

※今後、機能追加されることを願っています。


3. コンテナイメージのレジストリ登録

コンテナイメージのレジストリ登録には、レジストリの認証情報が必要です。リポジトリ情報は、container.ymlのregistriesセクションで指定し、認証情報はコマンド上で指定してください。

その他の、細かな指定方法は公式ページも参考にしてください。

# ansible-container push --push-to docker_regist --username "shingo.kitayama" --password "kubernetes"


4. Kubernetesへの展開用プレイブックの作成

container.ymlから、Kubernetesへの展開情報を設定したプレイブックを作成します。「ansible-container shipit」では、コンテナオーケストレーションエンジンの指定を行う必要があります。

# ansible-container shipit kube --pull-from docker_regist --username "shingo.kitayama" --password "kubernetes"

Images will be pulled from hub.docker.example.local/shingo.kitayama/test
Attaching to ansible_ansible-container_1
Cleaning up Ansible Container builder...
Role k8s created.
# ls ./ansible/roles/k8s-kubernetes/ ## kubernetes専用のロール、モジュールが作成される。
defaults library meta README tasks test


./ansible/shipit-kubernetes.yml

- name: Deploy k8s to kubernetes

hosts: localhost
gather_facts: false
connection: local
roles:
- role: k8s-kubernetes
playbook_debug: false


./ansible/roles/k8s-kubernetes/tasks/main.yml

- kube_deployment:

labels:
app: k8s
service: web
deployment_name: web
containers:
- securityContext: {}
name: web
args:
- nginx
- -g
- daemon off;
image: hub.docker.example.local/shingo.kitayama/test/k8s-web:20161222184749
ports:
- 80
replace: true
replicas: 2
register: output

- debug: var=output
when: playbook_debug



5. Kubernetesへの展開

最後は、作成されたshipit-kubernetes.ymlをansible-playbookコマンドから実行すると、Pods / Replica Set / DeploymentsのYAMLを自動的に生成して、Podをデプロイしてくれます。

$ ansible-playbook ansible/shipit-kubernetes.yml

PLAY [Deploy k8s to kubernetes] ***********************************************

TASK [k8s-kubernetes : kube_deployment] ****************************************
changed: [localhost]

TASK [k8s-kubernetes : debug] **************************************************
skipping: [localhost]

PLAY RECAP *********************************************************************
localhost : ok=1 changed=1 unreachable=0 failed=0

WS00000004.JPG

ということで、Ansible ContainerによるKubernetesへのコンテナデプロイでした。


参照


最後に

ansible-containerのバージョン0.3.0でどんな機能が追加されるのかが、公式ブログに展開されています。

https://www.ansible.com/blog/ansible-container-0-3-0

まだ開発途中のプロダクトなので、サポートしきれていない動作に関しては、地道に待ちましょう。

Kubernetes Advent Calendar勢の中で、ちょっと息抜きな感じで仕上がりました。

明日はいよいよクリスマス・イブですねー。歌ってギターも弾けるエンジニア、@jyoshiseさんのご登壇になりますっ。お楽しみにねー。

ではみなさま、HappyXmas!!