SoftLayerの AdventCalener2015 としての記事になります。昨年東京データセンターが開設されてからまだ1年しか立っていないのですね。
目次
はじめに
様々なアーキテクチャのシステムが動くSoftLayerですがDockerを利用するケースも増えてきたのではないでしょうか。
Dockerも2014年から徐々に耳に聞こえて、2015年では本番で試されているお客様も多いのではないでしょうか。SoftLayerの特徴の1つであるベアメタルサーバはDockerで利用することによりそのパフォーマンスを最大限に活かすことが出来るのではないでしょうか。
実際に本番環境でDockerを利用する事を検討すると、そのままdocker engineだけでは考えること(不足してること)が結構あることに気がつくと思います。複数のサーバで動かす場合には、自社のRepositoryサーバはどこに立てるのか、ネットワークはどのようにするのか(ネットワークの話は常に悩ましいですね)、アプリケーションのデプロイはどうやってするのか、考えていくとまさにDockerの成り立ちであるようにPaaSとしての機能が必要になることに気が付きます。Dockerをよりよく動かすためにはDocker社謹製の各種ツールや、Google社のKubernetes、そして話題のMesosphe、またはDocker PaaSと呼ばれる種類のPaaS基盤まで様々あります。 2016年には、Dockerをより”上手”につかうこのような手段が本格的に利用が始まるのではないでしょうか。
今回は、RedHat社のDockerPaaSである「OpenShift」をSoftLayer上に構築してみます。サポートが必要なケースが多いと思いますが今回は気楽に試すためにOSS版である「OpenShift Origin」を利用します。
- OSSのためソースコードが日々更新されており若干不安定な時もあります。
- 製品版はOriginに比べてRedHat社の用意するDockerテンプレートが豊富に用意されています。
OpenShift とは
OpenShiftは、簡単に言えばDocker+Scheduler+UI+Registry+認証です(乱暴な表現ですが)。OpenShiftを利用することでユーザ管理機能やイメージを保管するRepositoryそして複数台のサーバで動かすことを制御することが出来るようになります。
https://docs.openshift.org/latest/architecture/index.html
- Docker Engine
- Kuberntes
- Docker Registry
- Web Console
などで構成されています。
構成
今回はSoftLayer上の仮想サーバで利用してみます。
必要となるスペックは、https://docs.openshift.org/latest/install_config/install/prerequisites.html に記載されています。
- Master (1台) 2vcpu, 8Gmem, 100Gdisk, RHELv7.1
- master.openshift.local
- Node(2台)1vcpu,8Gmem, 100Gdisk, 15Gdisk(secound) ,RHELv7.1,
- node1.openshift.local
- node2.openshift.local
でオーダーをします。
プロビジョニングスクリプト
手順としては、prerequisites に従い実施する必要があります。手順をそのままスクリプトに書き出すと以下の様になりますのでこの内容をサーバオーダのプロビジョニングスクリプトとして登録して利用します。3台のサーバ全て同じ内容になります。
- [https://bitbucket.org/snippets/tokida/8LgKG]
yum -y install wget git net-tools bind-utils iptables-services bridge-utils bash-completion
yum -y update
yum -y install \
https://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm
sed -i -e "s/^enabled=1/enabled=0/" /etc/yum.repos.d/epel.repo
yum -y --enablerepo=epel install ansible
cd ~
git clone https://github.com/openshift/openshift-ansible
cd openshift-ansible
yum -y install docker
sed -ie "s/enabled/enabled\ --insecure-registry\ 172.30.0.0\/16/" /etc/sysconfig/docker
cat <<EOF > /etc/sysconfig/docker-storage-setup
DEVS=/dev/xvdc
VG=docker-vg
EOF
docker-storage-setup
systemctl stop docker
rm -rf /var/lib/docker/*
systemctl restart docker
cp -p /usr/share/zoneinfo/Japan /etc/localtime
SoftLayerでオーダする際に上記のスクリプトをプロビジョニングスクリプトとして登録(インターネットでhttps経由でアクセスできる場所、Gist等)します。また導入にansibleを利用するためSSHキーも登録します。
SSHキーのコピー
masterから他のサーバにアクセスできるように rsaファイルを転送しておきます。これは先程のサーバのオーダ時に設定したキーに対応したファイル転送します。ここでは例として sl_rsa がローカルのPC上にあると仮定しています。以下のコマンドをPC上で実施します。
scp -i ~/.ssh/sl_rsa ~/.ssh/sl_rsa root@master.openshift.local:/root/.ssh/sl_rsa
起動後の事前処理
node1,node2上で名前解決のためのresolv.confを設定しておきます。
sed -i -e "s/10.0.80.11/10.160.143.35/" /etc/resolv.conf
ここからは master.openshift.local サーバ上で実施していきます。
以下の内容を /root/install.sh に保存して実行します。
#!/bin/bash
# resolv.confの変更
sed -i -e "s/10.0.80.11/10.160.143.35/" /etc/resolv.conf
openssl rsa -in ~/.ssh/sl_rsa -out ~/.ssh/sl_rsa
chmod 600 /root/.ssh/sl_rsa
cat <<EOF >> /etc/hosts
10.160.143.37 node1.openshift.local
10.160.143.38 node2.openshift.local
EOF
systemctl start dnsmasq
systemctl enable dnsmasq
yum -y install gcc libffi-devel python-devel openssl-devel
easy_install pip
#pip install cryptography
pip install pyopenssl
yum -y install httpd
cat <<EOF > /root/.ssh/config
Host master.openshift.local
HostName master.openshift.local
IdentityFile /root/.ssh/sl_rsa
User root
Port 22
Host node1.openshift.local
HostName node1.openshift.local
IdentityFile /root/.ssh/sl_rsa
User root
Port 22
Host node2.openshift.local
HostName node2.openshift.local
IdentityFile /root/.ssh/sl_rsa
User root
Port 22
EOF
cat <<EOF > /etc/ansible/hosts
# Create an OSEv3 group that contains the masters and nodes groups
[OSEv3:children]
masters
nodes
# Set variables common for all OSEv3 hosts
[OSEv3:vars]
# SSH user, this user should allow ssh based auth without requiring a password
ansible_ssh_user=root
# If ansible_ssh_user is not root, ansible_sudo must be set to true
#ansible_sudo=true
deployment_type=origin
# uncomment the following to enable htpasswd authentication; defaults to DenyAllPasswordIdentityProvider
#openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider', 'filename': '/etc/origin/htpasswd'}]
# host group for masters
[masters]
master.openshift.local
# host group for nodes, includes region info
[nodes]
master.openshift.local openshift_node_labels="{'region': 'infra', 'zone': 'default'}"
node1.openshift.local openshift_node_labels="{'region': 'primary', 'zone': 'east'}"
node2.openshift.local openshift_node_labels="{'region': 'primary', 'zone': 'west'}"
EOF
実行がおわったらいよいよOpenShfitを導入するAnsibleを実行します。
ansible-playbook ~/openshift-ansible/playbooks/byo/config.yml
実行結果
PLAY RECAP ********************************************************************
localhost : ok=13 changed=0 unreachable=0 failed=0
master.openshift.local : ok=216 changed=56 unreachable=0 failed=0
node1.openshift.local : ok=58 changed=19 unreachable=0 failed=0
node2.openshift.local : ok=58 changed=19 unreachable=0 failed=0
のようになれば終了です。実際に登録されているかを確認します。
[root@master ~]# oc get nodes
NAME LABELS STATUS AGE
master.openshift.local kubernetes.io/hostname=master.openshift.local,region=infra,zone=default Ready,SchedulingDisabled 2m
node1.openshift.local kubernetes.io/hostname=node1.openshift.local,region=primary,zone=east Ready 56s
node2.openshift.local kubernetes.io/hostname=node2.openshift.local,region=primary,zone=west Ready 48s
Registryの作成
次にこのシステム上でDockerのRegistryをデプロイします。OpenShiftでは全てOpenShiftによりコンテナが管理されるためたんに
docker run するわけにはいきません。
reguserにてポリシーを作ります。
htpasswd -c /etc/origin/openshift-htpasswd reguser
oadm policy add-role-to-user system:registry reguser
Registryを登録します。
[root@master ~]# oadm registry --config=/etc/origin/master/admin.kubeconfig --credentials=/etc/origin/master/openshift-registry.kubeconfig
DeploymentConfig "docker-registry" created
Service "docker-registry" created
上記でサービスとしてregistyrが起動します。
[root@master ~] # oc logs docker-registry-1-uwfy7
time="2015-12-03T16:54:37Z" level=info msg="version=v2.0.0+unknown"
time="2015-12-03T16:54:37Z" level=info msg="redis not configured" instance.id=d905f1de-307e-449a-a212-f4d07e53118b
time="2015-12-03T16:54:37Z" level=info msg="using inmemory layerinfo cache" instance.id=d905f1de-307e-449a-a212-f4d07e53118b
time="2015-12-03T16:54:37Z" level=info msg="Using Origin Auth handler"
time="2015-12-03T16:54:37Z" level=info msg="listening on :5000" instance.id=d905f1de-307e-449a-a212-f4d07e53118b
time="2015-12-03T16:54:37Z" level=info msg="Starting upload purge in 59m0s" instance.id=d905f1de-307e-449a-a212-f4d07e53118b
より詳細に情報が見たい場合には以下の describe コマンドで確認が出来ます。
oc describe pod docker-registry-1-uwfy7
この時点ではサービスは以下の様なものが稼働しています。
[root@master ~]# oc get service
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE
docker-registry 172.30.228.81 <none> 5000/TCP docker-registry=default 5m
kubernetes 172.30.0.1 <none> 443/TCP,53/UDP,53/TCP <none> 18m
Routerの作成
“Router”は、これから作成するアプリケーションなどをURIから正しいコンテナに接続するための機能です。この機能があると複数のノードのどこでコンテナが起動しても、そのリクエストされるURIから正しいノードにリクエストを転送する事ができます。OpenShiftではBIG-IPやHA_Proxyでこの機能を実現します。
[root@master ~]# oadm router router --credentials=/etc/origin/master//openshift-router.kubeconfig --service-account=router
password for stats user admin has been set to v1ek6STO5Q
DeploymentConfig "router" created
Service "router" created
ルータが稼働するとこのような状態になります
[root@master ~]# oc get service
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE
docker-registry 172.30.228.81 <none> 5000/TCP docker-registry=default 17m
kubernetes 172.30.0.1 <none> 443/TCP,53/UDP,53/TCP <none> 29m
router 172.30.201.22 <none> 80/TCP router=router 28s
[root@master ~]# oc get pods
NAME READY STATUS RESTARTS AGE
docker-registry-1-uwfy7 1/1 Running 0 16m
router-1-q3b8g 1/1 Running 0 29s
補足
- Routerを作成する際にマニュアルには色々書いていますが、ServiceAccountの作成のくだりはインストーラーで登録済みなので不要です。
- 最終的に外部に公開するアプリケーションの場合には、名前でアプリケーションにリクエストします。任意のアプリケーション名.ホスト名(FDQN)が利用可能ですが Routerが動くノードのIPアドレスとして解決できるようにします。
- 例えば,http://sample.openshif.localというアプリケーションをデプロイする場合には sample.openshift.localの名前解決が出来る筆お湯がありその際のIPアドレスは routerが動いいてるノードのIPアドレスになります。
- 公開するアプリケーションのドメインは /etc/origin/master/master-config.yaml の subdomain で定義されています。
- 公開されたアプリの名称も oc expose service hello –hostname=FDQN で変更することが出来ます。
アプリケーションを作る
ブラウザからコンソールにアクセスします。http://master.openshift.local:8443/console でアクセスします。ユーザはrootでログインしてみます。
プロジェクトが無いので新規に作成をする画面が表示されます。
必要な情報を記載します。
次にアプリケーションのテンプレートを選択する画面が表示されます。今回は PHP5.5を選択肢てみます。
アプリケーションの名前(samplephp)とGitRepositoryURLを指定します。
作成をクリックするとアプリケーションを利用するための情報が表示されます。
起動がおわると以下の画面が表示されます。
今回公開されているアプリケーション名が「samplephp-1st-application.router.default.svc.cluster.local 」になっているのでこれを変更します。
[root@master ~]# oc login
Authentication required for https://master.openshift.local:8443 (openshift)
Username: root
Password:
Login successful.
Using project "1st-application".
[root@master ~]# oc get route
NAME HOST/PORT PATH SERVICE LABELS INSECURE POLICY TLS TERMINATION
samplephp samplephp-1st-application.router.default.svc.cluster.local samplephp app=samplephp
変更にあたって既存のrouteを削除して追加します。
[root@master ~]# oc delete route samplephp
route "samplephp" deleted
[root@master ~]# oc expose service samplephp --hostname=sample.openshift.local
route "samplephp" exposed
[root@master ~]# oc get route
NAME HOST/PORT PATH SERVICE LABELS INSECURE POLICY TLS TERMINATION
samplephp sample.openshift.local samplephp app=samplephp
これでこのURLに対してブラウザでアクセスをしてみます。
無事に動いていればCakePHPの画面が表示されます。
備考
- 指定するカスタムのURIの宛先は routerが動いているNodeのIPアドレスです。Routerを高可用性を持たせるためには別途そのための構成を取る必要があります。動いているサーバを見つけるためには ,
oc get pods
でrouterのNAMEを取得します。そしてoc describe pod <NAME>
でNode: という項目に動いているノード情報が表示されます。
まとめ
今回は簡単に動かすところまでをおいました。最小限での構成としていますが実際には複数台のMaster構成やロケーションなどを考慮したノードの設計を作ることも可能なので、SoftLayerのデータセンタに合わせて場所別にリソースを定義した入りすることが出来そうです。
DockerやPaaSという環境は、アプリケーションをデプロイするための仕組みですのでどの様にDockerアプリケーションをBuildしてデプロイするのかを次の機会で書きたいと思います。