はじめに
構成管理ツールとAPIを使ってIaaS環境にKubernetes環境一式を自動デプロイし、プライベート・クラウド環境を構築します。構成管理ツールは、Ansibleを使います。デプロイ先となるIaaSは、IBM Cloud IaaSとします。IBM Cloud IaaSは、APIが公開されていますので、SL API (SoftLayer API Python Client)を使ってIaaS部分の管理を自動化します。Kubernetesは、IBM版Kubernetesである、IBM Cloud Private(以下、ICP)のCommunity Edition(無料)を用います。ソースコードは、Githubの[Deploy IBM Cloud Private]
(https://github.com/IBM/deploy-ibm-cloud-private)をご確認ください。AnsibleだけでなくVagrant、Terrraformといったバージョンもあります。
IaaS構成
システム構成は下図のとおりです。MacbookをICPのBoot Node(Ansibleベースのインストーラー)として、IaaS側の4台の仮想サーバーにMaster node (icp-master01)、Proxy node (icp-proxy01)、Worker node (icp-worker01, icp-worker02)をオーダーした上でICPを自動デプロイしています。インバウンド/アウトバウンド通信については、セキュリティ・グループの機能で必要なIPアドレスとポート番号を許可しておきます。

事前準備
MacbookのターミナルにIBM Cloud Privateのリポジトリーをクローンします。
$ git clone https://github.com/IBM/deploy-ibm-cloud-private.git
クローンしたリポジトリーに移動します。
$ cd deploy-ibm-cloud-private
$ ls
Cachefile ansible.cfg extensions requirements.txt
LICENSE camQuick.sh hosts terraform
README.md cluster images
Vagrantfile docs playbooks
pipコマンドでSL CLIとAnsibleをセットアップします。
$ sudo pip install -r requirements.txt
$ cat requirements.txt
softlayer
ansible
SL CLIのバージョンは以下のとおりです。
$ slcli --version
slcli (SoftLayer Command-line), version 5.3.1
Ansibleのバージョンは以下のとおりです。
$ ansible --version
ansible 2.5.3
...
SL CLIに資格情報をセットアップします。対話形式で必要な項目を入力していきます。
$ slcli config setup
Username [XXXXX@XX.ibm.com]:
API Key or Password [XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX]:
Endpoint (public|private|custom) [public]:
Timeout [0]:
:..............:..................................................................:
: name : value :
:..............:..................................................................:
: Username : XXXXX@jp.ibm.com :
: API Key : XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX :
: Endpoint URL : https://api.softlayer.com/xmlrpc/v3.1/ :
: Timeout : not set :
:..............:..................................................................:
Are you sure you want to write settings to "/Users/asasaki/.softlayer"? [Y/n]:
仮想サーバーにパスワードなしでログインするためにSSH鍵を作成します。
$ ssh-keygen -f cluster/ssh_key -P ""
Generating public/private rsa key pair.
Overwrite (y/n)? y
Your identification has been saved in cluster/ssh_key
Your public key has been saved in cluster/ssh_key.pub
作成したSSH鍵をSoftLayerに追加します。
$ slcli sshkey add -f cluster/ssh_key.pub icp-key
icp-key
という名前のSSH鍵がIBM Cloud IaaSに登録されていることを確認します。
$ slcli sshkey list
:........:....................:.................................................:.......:
: id : label : fingerprint : notes :
:........:....................:.................................................:.......:
: XXXXXXX : icp-key : XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX : - :
:........:....................:.................................................:.......:
デプロイ先となるVLANのIDを確認します。
$ slcli vlan list
:.........:........:......................:..........:............:..........:.................:............:
: id : number : name : firewall : datacenter : hardware : virtual_servers : public_ips :
:.........:........:......................:..........:............:..........:.................:............:
: XXXXXXX : XXXX : : No : tok02 : 0 : 0 : 0 :
:.........:........:......................:..........:............:..........:.................:............:
Ansibleによる仮想サーバーのデプロイ
Ansibleでは、Playbookと呼ばれるYAML形式のテキスト・ファイルに実行したいタスクを記述します。それをAnsibleで実行させることにより、インフラの構成管理を自動化することができます。ここでは、AnsibleのPlaybookを使用して、ICPのデプロイ先となるIBM Cloud IaaSの仮想サーバーをデプロイします。
デプロイ先のデータセンター名(ここではtok02)とさきほど確認したVLANのIDを使用して、Ansibleで利用するYAMLファイルcluster/config.yaml
にsl_datacenter
とsl_vlan
の2つの変数を構成ファイルにセットします。
$ cat cluster/config.yaml
network_type: calico
network_cidr: 192.168.0.0/16
service_cluster_ip_range: 192.168.0.0/24
ingress_enabled: true
ansible_user: root
mesos_enabled: false
install_docker_py: true
sl_datacenter: tok02
sl_ssh_key: XXXXXXX
sl_vlan: XXXXXXX
sl_icp_masters:
- icp-master01
sl_icp_workers:
- icp-worker01
- icp-worker02
sl_icp_proxies:
- icp-proxy01
次に、実際に仮想サーバーを作成するPlaybookcreate_sl_vms.yml
の内容を確認します。内部的にさきほど設定したcluster/config.yaml
が呼び出されていることが分かります。cpus: 2
memory: 8192
disks: [100]
といった変数で、ICPを構成する各ノードのスペックを指定することができます。
$ cat playbooks/create_sl_vms.yml
---
- name: create servers
hosts: localhost
gather_facts: False
tasks:
- name: Include cluster vars
include_vars:
file: ../cluster/config.yaml
- name: create master
sl_vm:
hostname: "{{ item }}"
domain: example.com
datacenter: "{{ sl_datacenter|default('dal09') }}"
tags: "{{ item }},icp,master"
hourly: True
private: False
dedicated: False
local_disk: True
cpus: 2
memory: 8192
disks: [100]
os_code: UBUNTU_LATEST
private_vlan: "{{ sl_vlan|default(omit) }}"
wait: no
ssh_keys: "{{ sl_ssh_key|default(omit) }}"
with_items: " {{ sl_icp_masters }}"
- name: create workers
sl_vm:
hostname: "{{ item }}"
domain: example.com
datacenter: "{{ sl_datacenter|default('dal09') }}"
tags: "{{ item }},icp,worker"
hourly: True
private: False
dedicated: False
local_disk: True
cpus: 2
memory: 4096
disks: [100]
os_code: UBUNTU_LATEST
private_vlan: "{{ sl_vlan|default(omit) }}"
wait: no
ssh_keys: "{{ sl_ssh_key|default(omit) }}"
with_items: " {{ sl_icp_workers }}"
- name: create proxies
sl_vm:
hostname: "{{ item }}"
domain: example.com
datacenter: "{{ sl_datacenter|default('dal09') }}"
tags: "{{ item }},icp,proxy"
hourly: True
private: False
dedicated: False
local_disk: True
cpus: 2
memory: 4096
disks: [100]
os_code: UBUNTU_LATEST
private_vlan: "{{ sl_vlan|default(omit) }}"
wait: no
ssh_keys: "{{ sl_ssh_key|default(omit) }}"
with_items: " {{ sl_icp_proxies }}"
AnsibleからPlaybookplaybooks/create_sl_vms.yml
を実行してIBM Cloud IaaSに仮想サーバーをデプロイします。
$ ansible-playbook playbooks/create_sl_vms.yml
5-10分ほどで仮想サーバーのデプロイが完了します。
AnsibleによるOS構成
各仮想サーバーのOSにログインするためのSSH鍵を追加します。
$ ssh-add cluster/ssh_key
OSパラメータを設定するためのPlaybookprepare_sl_vms.yml
の内容を確認します。swapの無効化、Pythonなどのパッケージの追加、dnsmasq(プライベートDNSサーバ)の設定、Docker CEのインストールといったICPのインストールに必要な前提タスクが記述されていることを確認します。
$ cat playbooks/prepare_sl_vms.yml
---
- name: ensure connectivity to all nodes
hosts: all
gather_facts: false
pre_tasks:
- name: Include cluster vars
include_vars:
file: ../cluster/config.yaml
- name: check if python is installed
raw: test -e /usr/bin/python
register: python_installed
changed_when: false
failed_when: false
- name: check if debian based OS
raw: which apt-get
register: is_ubuntu
changed_when: false
failed_when: false
- name: install python
raw: (apt-get -y update && apt-get install -y python)
when: python_installed.rc != 0 and is_ubuntu.rc == 0
- name: install python
raw: (yum install -y python)
when: python_installed.rc != 0 and is_ubuntu.rc != 0
tasks:
- name: ansible setup
action: setup
tags: ['ping']
any_errors_fatal: true
max_fail_percentage: 0
- name: bootstrap nodes
hosts: all
gather_facts: true
tasks:
- name: Include cluster vars
include_vars:
file: ../cluster/config.yaml
- name: disable swap
command: swapoff -a
- name: install extra packages
yum:
name: "{{ item }}"
with_items: [dnsmasq,vim, yum-utils,python-pip]
when: ansible_os_family == 'RedHat'
- name: install extra packages
apt:
name: "{{ item }}"
with_items: [dnsmasq,vim,python-pip,nfs-common]
when: ansible_os_family == 'Debian'
- name: disable resolvconf updates
command: resolvconf --disable-updates
when: ansible_os_family == 'Debian'
- name: add alternative dnsmasq resolv.conf
lineinfile:
line: "resolv-file=/etc/dnsmasq_resolv.conf"
path: /etc/dnsmasq.conf
regexp: "^#resolv-file="
- name: add dns servers to /etc/dnsmasq_resolv.conf
lineinfile:
create: yes
line: "nameserver {{ item }}"
path: /etc/dnsmasq_resolv.conf
with_items: [10.0.80.11, 10.0.80.12]
- name: rewrite /var/run/resolvconf/resolv.conf
lineinfile:
create: yes
line: "nameserver {{ item }}"
path: /var/run/resolvconf/resolv.conf
regexp: "nameserver {{ item }}"
state: absent
with_items: [10.0.80.11, 10.0.80.12, 127.0.0.1]
- name: rewrite /var/run/resolvconf/resolv.conf
lineinfile:
line: "nameserver {{ primaryBackendIpAddress }}"
path: /var/run/resolvconf/resolv.conf
regexp: "nameserver {{ primaryBackendIpAddress }}"
- name: remove /etc/hosts
file:
dest: /etc/hosts
state: absent
- name: add localhost to /etc/hosts
lineinfile:
create: yes
line: 127.0.0.1 localhost
path: /etc/hosts
- name: add host to /etc/hosts
lineinfile:
line: "{{ hostvars[item]['primaryBackendIpAddress'] }} {{ hostvars[item]['hostname'] }} {{ hostvars[item]['ansible_fqdn'] }}"
path: /etc/hosts
with_items: "{{ groups['all'] }}"
- name: enable / start dnsmasq
service:
name: dnsmasq
state: started
enabled: true
- name: wait 60 seconds then restart dnsmasq
shell: sleep 60; systemctl restart dnsmasq
- block:
- name: get Docker CE repo
shell: yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
args:
creates: /etc/yum.repos.d/docker-ce.repo
- name: install Docker CE
yum:
name: docker-ce
when: ansible_os_family == "RedHat"
- block:
- name: Import Docker CE repository gpg key
apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
id: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88
- name: Add Docker CE repository
apt_repository:
repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
state: present
- name: Install Docker CE
apt:
name: docker-ce
state: present
update_cache: yes
when: ansible_os_family == "Debian"
any_errors_fatal: true
max_fail_percentage: 0
- name: install icp
hosts: master[0]
gather_facts: true
tasks:
- name: Include cluster vars
include_vars:
file: ../cluster/config.yaml
- name: create icp install dir
file:
dest: /root/cluster
state: directory
- name: Copy icp files up
copy:
src: ../cluster
dest: /root/
- name: set perms on hosts script
file:
dest: /root/cluster/hosts
mode: 0755
- name: Build installer image
command: docker build -t icp-on-sl /root/cluster
- name: Run the following command to deploy IBM Cloud Private
debug:
msg: "ssh {{ ansible_user }}@{{ hostvars[groups['master'][0]]['primaryIpAddress'] }} docker run -e SL_USERNAME=<SL_USERNAME> -e SL_API_KEY=<SL_API_KEY> -e LICENSE=accept --net=host --rm -t -v /root/cluster:/installer/cluster icp-on-sl install"
Playbook (prepare_sl_vms.yml)を実行します。
$ ansible-playbook -i hosts playbooks/prepare_sl_vms.yml
※dnsmasqが原因でエラーになることがありますが、Playbookを再度実行すると通常は解決されます。もしくはマスター・ノードでdnsmasqを再起動することで解決されることもあります。
ICPコンテナのインストール
仮想サーバーにログインして、Dockerコマンドを使いICPコンテナicp-on-sl
をインストールします。
$ cat ~/.softlayer
$ ssh root@XXX.XXX.XXX.XXX docker run -e SL_USERNAME=XXXXX -e SL_API_KEY=XXXXX -e LICENSE=accept --net=host \
--rm -t -v /root/cluster:/installer/cluster icp-on-sl install
...
10分ほどでICPコンテナのインストールが完了します。
ICPコンソールへのアクセス
ProxyノードのパブリックIPアドレスを確認し、ブラウザからhttps://<Proxy Node Public IP>:8443/
にアクセスしてコンソールが表示されることを確認します。
IBM Cloud Privateのコンソールが表示されることを確認します。
ICP初期設定
[Menu] > [Tools] > [Command line]をオープンします。右側にある[Download For Mac OS X]よりThe IBM Cloud Private CLIをダウンロードします。
MacbookでIBM Cloud CLI (bxコマンド)がインストールされていることを確認します。
$ bx --version
bx version 0.6.7+283a906f-2018-05-14T23:39:23+00:00
IBM Cloud CLIがインストールされていない場合は、こちらを参考に別途インストールしてください。
bx plugin install
コマンドでダウンロードしたicp-darwin-amd64
をインストールします。
$ bx plugin install /<path_to_installer>/icp-darwin-amd64
バイナリーをインストールしています...
OK
プラグイン 'icp 2.1.239' は /Users/asasaki/.bluemix/plugins/icp に正常にインストールされました。 'bx plugin show icp' を使用して詳細を表示してください。
The IBM Cloud Private CLI (以下、ICP CLI)がインストールされていることを確認します。
$ bx pr help
名前:
bx pr - IBM Cloud Private Service
使用法:
bx pr command [arguments...] [command options]
コマンド:
api View the API endpoint and API version for the service.
cluster-config Download the Kubernetes configuration and configure kubectl for a specified cluster.
cluster-get クラスターの詳細を表示します
clusters List all the clusters in your account.
...
デプロイしたICPのマスター・ノードにログインします。
$ bx pr login -a https://<master_ip_address>:8443 --skip-ssl-validation
Login method invokedAPI endpoint: https://169.56.28.254:8443
Username> admin
Password>
Authenticating...
OK
Select an account:
1. ICP Account (3c43bf7207a6932a043f2eabc6002d70)
Enter a number> 1
Targeted account: ICP Account (3c43bf7207a6932a043f2eabc6002d70)
MacbookのプラグインリストにICP CLIがインストールされていることを確認します。
$ bx plugin list
インストール済みプラグインをリストしています...
プラグイン名 バージョン
IBM-Containers 1.0.1028
container-registry 0.1.292
container-service 0.1.488
icp 2.1.239
サービスのAPIエンドポイントとAPIバージョンを表示します。
$ bx pr api
API エンドポイント: https://<Master Node IP Address>:8443/api
API バージョン: v1
SSL 検証のスキップ: tru
Kubernetes設定をダウンロードし、指定されたクラスタに対してkubectlを設定します。
$ bx pr cluster-config mycluster
Configuring kubectl: /Users/asasaki/.bluemix/plugins/icp/clusters/mycluster/kube-config
Cluster "master.cfc" set.
Context "master.cfc-context" modified.
User "master.cfc-user" set.
Context "master.cfc-context" modified.
Switched to context "master.cfc-context".
OK
Cluster mycluster configured successfully.
クラスタの詳細を表示します。
$ bx pr cluster-get mycluster
Retrieving cluster mycluster...
OK
Name: mycluster
ID: 00000000000000000000000000000001
State: deployed
Created: 2018-05-29T01:46:29+0000
Datacenter: default
Master URL: https://<Master Node IP Address>:8001
Masters: 1
Workers: 3
アカウント内のすべてのクラスタを一覧表示します。
$ bx pr clusters
OK
Name ID State Created Masters Workers Datacenter
mycluster 00000000000000000000000000000001 deployed 2018-05-29T01:46:29+0000 1 3 default
以上