kolla-kubernetes+Ubuntu is 動いた

# はじめに

OpenStackプロジェクトの1つである kolla-kubernetesを使って OpenStack環境構築を目指します。kolla-kubernetesを選んだ理由は以下です：

* OpenStack知ってる
* Kolla知ってるけど使ったことがない
* k8sは Kubernetesの略称ということは知っているが使ったことがない

結論からいうと、 **2017/12/18時点の公式ドキュメントを参考に動かしてもまともに動きません。**色々試行錯誤して5回試したのですが、5回とも詰みました。詰んでは最初からやり直し、という詰み戻りを繰り返して運命に抗います。

この**詰み戻り知識**を糧に、本記事ではkolla-kubernetesによるOpenStack環境の構築手順を紹介します。

# NOTE(2018/8/11追記)

**2018/5/14** 以降、kolla-kubernetesのプロジェクト活動は停止してしまいました。
現在は、 [openstack-helm](https://github.com/openstack/openstack-helm) というプロジェクトに統合されて活動を続けています。

# Kollaとは？

OpenStack環境をコンテナでデプロイする機能を提供するOpenStackプロジェクトです。
現在OpenStackコミュニティでは運用の簡易化が注目されており、コンテナによる環境のデプロイはそのアプローチの一つです。

* https://docs.openstack.org/kolla/latest/

# Kolla-kubernetesとは？

Kollaのバックエンドに kubernetesを用意したものです。デプロイには `helm`、定義ファイルのコピーには `ansible`を使っています。ではkolla-kubernetesは何をするのか？それは kollaが用意しているコンテナの定義をkubernetes上で使えるようにするための **configmap** を生成してくれています。

(2018/8/10追記)
前述の通り、**2018/5/14** 以降、kolla-kubernetesの[プロジェクト活動は停止しております](http://lists.openstack.org/pipermail/openstack-dev/2018-March/128822.html)。
[openstack-helm](https://github.com/openstack/openstack-helm) にて、OpenStack環境をKubernetes上にデプロイする仕組みが提供されています。

# 環境構築

基本的に、kolla-kubernetesの[deployment-guide](https://docs.openstack.org/kolla-kubernetes/latest/deployment-guide.html)を見ながら、適宜修正を加えつつ構築を進めていきます。

## 基盤環境構築

まず、本セクション以降での表現について説明します：

|表示内容   | 説明                 |
|---------:|:----------------------|
|`command` | 実行コマンド          |
|表示なし  | 上記コマンドの出力結果。結果が長い場合は `..(snip)..` をつけて省略しています|

以下の条件を満たすマシンを作成します。今回は以下の **VM(1台)** を用意しました：

* OS: **Ubuntu 16.04.3 LTS**
* 2 network interfaces(ens3, ens4)
* 8GB RAM
* 40GB DISK

    > The host machine must satisfy the following minimum requirements:
    >  - 2 network interfaces
    >  - 8GB main memory
    >  - 40GB disk space
    > Dependencies:
    >   - docker == 1.12.6
    >   - helm >= 2.4.1
    >   - kubectl >= 1.8.0
    >   - kubeadm >= 1.8.0
    >   - kubelet >= 1.8.0
    >   - kubernetes-cni >= 0.5.1

### Kubernetes, Docker のインストール

1. firewalldの停止

    ```bash:command
sudo systemctl stop firewalld; sudo systemctl disable firewalld
    ```

    ```bash
Failed to stop firewalld.service: Unit firewalld.service not loaded.
Failed to execute operation: No such file or directory
    ```
    * 入っていなかったため、次へ進みます
1. kubernetes用リポジトリの追加

    ```bash:command
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo -E apt-key add -
cat <<EOF > kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
    ```

    ```bash
OK
    ```

    ```bash:command
sudo cp -aR kubernetes.list /etc/apt/sources.list.d/kubernetes.list
sudo apt update
sudo apt install --no-install-recommends apt-transport-https curl software-properties-common
sudo apt install -y --no-install-recommends linux-image-extra-$(uname -r) linux-image-extra-virtual
    ```

    ```bash
..(snip)..
Get:1 http://jp.archive.ubuntu.com/ubuntu xenial-updates/main amd64 linux-image-extra-virtual amd64 4.4.0.104.109 [1,772 B]
Fetched 1,772 B in 0s (15.1 kB/s)
Selecting previously unselected package linux-image-extra-virtual.
(Reading database ... 212811 files and directories currently installed.)
Preparing to unpack .../linux-image-extra-virtual_4.4.0.104.109_amd64.deb ...
Unpacking linux-image-extra-virtual (4.4.0.104.109) ...
Setting up linux-image-extra-virtual (4.4.0.104.109) ...
    ```
1. docker v.1.12用リポジトリ追加

    ```bash:command
curl -fsSL 'https://sks-keyservers.net/pks/lookup?op=get&search=0xee6d536cf7dc86e2d7d56f59a178ac6c6238f52e' | sudo apt-key add -
sudo add-apt-repository "deb https://packages.docker.com/1.12/apt/repo/ ubuntu-$(lsb_release -cs) main"
sudo apt update
    ```

    ```bash
OK
Hit:1 http://jp.archive.ubuntu.com/ubuntu xenial InRelease
Hit:3 http://jp.archive.ubuntu.com/ubuntu xenial-updates InRelease
Hit:4 http://jp.archive.ubuntu.com/ubuntu xenial-backports InRelease
..(snip)..
All packages are up to date.
    ```
1. パッケージのインストール
        
    ```bash:command(現時点で最新のv1.9.0を使う場合)
sudo apt install -y docker-engine kubelet kubeadm kubectl kubernetes-cni
    ```

    ```bash:command(v1.8.5を使う場合)
sudo apt install -y docker-engine=1.8.5-00 kubelet=1.8.5-00 kubeadm=1.8.5-00 kubectl=1.8.5-00 kubernetes-cni=0.5.1-00
    ```

    ```bash
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  aufs-tools cgroupfs-mount ebtables socat
The following NEW packages will be installed:
  aufs-tools cgroupfs-mount docker-engine ebtables kubeadm kubectl kubelet kubernetes-cni socat
0 upgraded, 9 newly installed, 0 to remove and 0 not upgraded.
Need to get 76.6 MB of archives.
..(snip)..
Setting up socat (1.7.3.1-1) ...
Setting up kubelet (1.9.0-00) ...
Setting up kubectl (1.9.0-00) ...
Setting up kubeadm (1.9.0-00) ...
Processing triggers for libc-bin (2.23-0ubuntu9) ...
Processing triggers for systemd (229-4ubuntu21) ...
Processing triggers for ureadahead (0.100.0-19) ...
    ```
    * **詰み戻り知識**
        * 公式ドキュメントの方法だと、docker v1.13(>1.12)がインストールされます
        * 記事編集中(2017/12/16)にkubernetes v1.9.0がリリースされるというミラクルが起きたため
          デフォルトは **v1.9.0** です
        * v1.8.5を使う場合は、kubernetes-cniは **0.5.1-00** を使う必要があります
            * v0.6.0を使うと、`kubelet`が起動しなくなりました
    * 一番風呂に入ろうじゃないか、ということで本記事では v1.9.0を使います
1. kubernetesのPodの作成状況を監視
    * 別ターミナルか、`screen`コマンドで別窓を用意して作業すると楽です

    ```bash:command
watch -d kubectl get pods --all-namespaces -o wide
    ```

    ```bash
Every 2.0s: kubectl get pods --all-namespaces -o wide      Sat Dec 16 12:00:16 2017
The connection to the server localhost:8080 was refused - did you specify the right host or port?
    ```
    * 現時点ではこんな表示ですが、気にせず先に進みます
1. docker サービスの自動起動設定

    ```bash:command
sudo systemctl enable docker; sudo systemctl start docker
    ```

    ```bash
Synchronizing state of docker.service with SysV init with /lib/systemd/systemd-sysv-install...
Executing /lib/systemd/systemd-sysv-install enable docker
    ```
1. CGROUPの設定

    ```bash:command
CGROUP_DRIVER=$(sudo docker info | grep "Cgroup Driver" | awk '{print $3}')
echo $CGROUP_DRIVER
sudo sed -i "s|KUBELET_KUBECONFIG_ARGS=|KUBELET_KUBECONFIG_ARGS=--cgroup-driver=$CGROUP_DRIVER |g" /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
    ```

    ```bash
cgroupfs
    ```
1. DNS server 用のservice CIDR変更、`kubelet`の起動用引数を追加

    ```bash:command
sudo sed -i 's/10.96.0.10/10.3.3.10/g' /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
sudo sed -i "/^\[Service\]$/a Environment=\"KUBELET_EXTRA_ARGS=--fail-swap-on=false\"" /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
    ```
    * **詰み戻り知識**: `Environment="KUBELET_EXTRA_ARGS=--fail-swap-on=false"`がないと、`kubelet`が起動しません
1. daemon-reload後、 `kubelet`を起動

    ```bash:command
sudo systemctl daemon-reload; sudo systemctl stop kubelet
sudo systemctl enable kubelet; sudo systemctl start kubelet
    ```
1. Kubernetes のデプロイ

    ```bash:command(kubernetes_v1.9.0の場合)
sudo kubeadm init --pod-network-cidr=10.1.0.0/16 --service-cidr=10.3.3.0/24 --ignore-preflight-errors=all
    ```

    ```bash:command(kubernetes_v1.8.5の場合)
sudo kubeadm init --pod-network-cidr=10.1.0.0/16 --service-cidr=10.3.3.0/24 --skip-preflight-checks
    ```

    ```bash:出力結果(kubernetes_v1.9.0の場合)
..(snip)..
Your Kubernetes master has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
    mkdir -p $HOME/.kube
    sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
    https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of machines by running the following on each node
as root:
     kubeadm join --token ecb8cd.2b3d25192d8476e2 192.168.122.244:6443 --discovery-token-ca-cert-hash sha256:8d02e68e763ce01a698518322418103b3eaeb67031396c651e9b409f0938b27b
    ```
    * **詰み戻り知識**:
        * kubernetes v1.9.0の場合、`--ignore-preflight-errors=all` がないと失敗します

            ```bash:エラー出力
[init] Using Kubernetes version: v1.9.0
[init] Using Authorization modes: [Node RBAC]
[preflight] Running pre-flight checks.
        [WARNING FileExisting-crictl]: crictl not found in system path
[preflight] Some fatal errors occurred:
        [ERROR Swap]: running with swap on is not supported. Please disable swap
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
            ```
        * kubernetes v1.8.5の場合、`--skip-preflight-checks` がないと失敗します

1. `kubeadm` によるKubernetesのデプロイ(設定ファイルの読み込み)

    ```bash:command
mkdir -p $HOME/.kube
sudo -H cp /etc/kubernetes/admin.conf $HOME/.kube/config
sudo -H chown $(id -u):$(id -g) $HOME/.kube/config
    ```
    * 上記コマンド実行後、監視用のプロンプトからPodが見えるようになります
1. Canal CNI driver のデプロイ
    * [Canal](https://github.com/projectcalico/canal)は, Calico + flannel networkを簡単にデプロイするアプリケーションのようです
    * CNIとは、the **C**ontainer **N**etwork **I**nterfaceの略で、コンテナ用ネットワークのライブラリのようです。
    * きっとコンテナ同士を接続するためのネットワークを作っているんだと理解しました
        * 今回は詳しく調査していません

    ```bash:command
curl -L https://raw.githubusercontent.com/projectcalico/canal/master/k8s-install/1.7/rbac.yaml -o rbac.yaml
kubectl apply -f rbac.yaml
curl -L https://raw.githubusercontent.com/projectcalico/canal/master/k8s-install/1.7/canal.yaml -o canal.yaml
sed -i "s@10.244.0.0/16@10.1.0.0/16@" canal.yaml
kubectl apply -f canal.yaml
    ```

    ```bash
configmap "canal-config" created
daemonset "canal" created
customresourcedefinition "globalfelixconfigs.crd.projectcalico.org" created
customresourcedefinition "globalbgpconfigs.crd.projectcalico.org" created
customresourcedefinition "ippools.crd.projectcalico.org" created
customresourcedefinition "globalnetworkpolicies.crd.projectcalico.org" created
serviceaccount "canal" created
    ```
    * **詰み戻り知識**: 公式に書いてある **1.6** だと canal-*というPodが永久に起動しませんでした
    * `canal-*` のPodが起動するのに数分かかります
1. スケジューリングのための node 確保

    ```bash:command
kubectl taint nodes --all=true  node-role.kubernetes.io/master:NoSchedule-
    ```

    ```bash
node "kolla" untainted
    ```

    > Canal CNI appears to **untaint** the master node in later versions. This is a reported bug:https://github.com/projectcalico/canal/issues/77
    > Kubernetes must start completely before verification will function properly.
    > In your watch terminal, confirm that Kubernetes has completed initialization by observing that the **dns pod is in 3/3 Running state**. If you fail to wait, Step 2 will fail.
    * **untaint** と表示されるのは既知のバグらしいので無視して進みます。
    * この時点で DNS pod が **3/3 Running** になるまで監視してね、だそうです

    ```bash:stdout(monitoring)
NAMESPACE     NAME                            READY     STATUS    RESTARTS   AGE       IP                NODE
kube-system   canal-z6jtw                     3/3       Running   0          4m        192.168.122.244   kolla
kube-system   etcd-kolla                      1/1       Running   0          4m        192.168.122.244   kolla
kube-system   kube-apiserver-kolla            1/1       Running   0          4m        192.168.122.244   kolla
kube-system   kube-controller-manager-kolla   1/1       Running   0          4m        192.168.122.244   kolla
kube-system   kube-dns-6f4fd4bdf-xnq8v        3/3       Running   0          5m        10.1.0.2          kolla
kube-system   kube-proxy-jxzmx                1/1       Running   0          5m        192.168.122.244   kolla
kube-system   kube-scheduler-kolla            1/1       Running   0          4m        192.168.122.244   kolla
    ```
    * kube-dns-6f4fd4bdf-xnq8v が *Running* になったので先に進みます

### Kubernetes上のDNSの動作検証

1. 以下のコマンドを実行して `busybox` のイメージを起動
    * コマンドプロンプト (**/ #**) が表示されると成功です

    ```bash:command
kubectl run -i -t $(uuidgen) --image=busybox --restart=Never
    ```

    ```
If you don't see a command prompt, try pressing enter.
/ #
    ```
1. 1. で起動したコンテナ内で、DNS が正常に動作しているか確認

    ```bash:command
nslookup kubernetes
exit
    ```

    ```bash
Server:    10.3.3.10
Address 1: 10.3.3.10 kube-dns.kube-system.svc.cluster.local
Name:      kubernetes
Address 1: 10.3.3.1 kubernetes.default.svc.cluster.local
    ```
    * `exit` すると、自動的にコンテナも消滅します

### Kolla-kubernetes のインストール(ソースから)

1. RBACの設定を以下で上書きします

    ```bash:command
kubectl apply -f <(cat <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
      name: cluster-admin
roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster-admin
subjects:
- kind: Group
      name: system:masters
- kind: Group
      name: system:authenticated
- kind: Group
      name: system:unauthenticated
EOF
)
    ```

    ```bash
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
clusterrolebinding "cluster-admin" configured
    ```
    * **詰み戻り知識**:
        * `kubectl` のサブコマンドは `update` ではなく、`apply`が正しいです
        * 公式ドキュメントでは ``apiVersion: rbac.authorization.k8s.io/v1alpha1``ですが、正しくは
          ``apiVersion: rbac.authorization.k8s.io/v1``のようです。
        * 公式ドキュメントやり方だとエラーが出ますが `--validate=false`をつけると先に進めます。が、終盤(Podの起動)で詰みます
1. `helm` のインストールと初期設定

    ```bash:command
curl -L https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.sh
chmod 700 get_helm.sh
./get_helm.sh
    ```

    ```bash
Downloading https://kubernetes-helm.storage.googleapis.com/helm-v2.7.2-linux-amd64.tar.gz
Preparing to install into /usr/local/bin
helm installed into /usr/local/bin/helm
Run 'helm init' to configure helm.
    ```
1. `helm`の初期設定(Tillerのデプロイ)

    ```bash:command
helm init
    ```

    ```bash
Creating /home/stack/.helm
Creating /home/stack/.helm/repository
Creating /home/stack/.helm/repository/cache
Creating /home/stack/.helm/repository/local
Creating /home/stack/.helm/plugins
Creating /home/stack/.helm/starters
Creating /home/stack/.helm/cache/archive
Creating /home/stack/.helm/repository/repositories.yaml
Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com
Adding local repo with URL: http://127.0.0.1:8879/charts
$HELM_HOME has been configured at /home/stack/.helm.
Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.
Happy Helming!
    ```
    * **Happy Helming!** が表示されると成功です
    * これを契機に、 `tiller-deploy-5b9d65c7f-zzhxg` というPodが稼働します
    * 必要なサービスが全てインストールされたので、バージョンの確認を行います。

    |Packages       | Required | Installed   |
    |--------------:|---------:|------------:|
    |docker         | =  1.12.6| 1.12.6-cs13 |
    |helm           | >  2.4.1 | v2.7.2      |
    |kubectl        | >  1.8.0 | v1.9.0-00   |
    |kubeadm        | >  1.8.0 | v1.9.0-00   |
    |kubelet        | >  1.8.0 | v1.9.0-00   |
    |kubernetes-cni | >= 0.5.1 | v0.6.0-00   |
    * マイクロバージョンまで揃っているので、dockerは成功したとみなします(無理やり)
    * 以下のコマンドでバージョン確認を行いました:

      ```bash:command
sudo apt list --installed | grep -e "kube.*" -e docker
      ```

      ```bash:stdout
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
docker-engine/ubuntu-xenial,now 1.12.6~cs13-0~ubuntu-xenial amd64 [installed]
kubeadm/kubernetes-xenial,now 1.9.0-00 amd64 [installed]
kubectl/kubernetes-xenial,now 1.9.0-00 amd64 [installed]
kubelet/kubernetes-xenial,now 1.9.0-00 amd64 [installed]
kubernetes-cni/kubernetes-xenial,now 0.6.0-00 amd64 [installed]
      ```
1. `python`, `ansible`, `pip` のインストール
    * 明らかにこれらのパッケージが必要なのですが、公式ドキュメントにはUbuntuの場合のコマンドが記載されていません。
    * [ansibleの公式ページ](http://docs.ansible.com/ansible/latest/intro_installation.html#latest-releases-via-apt-ubuntu)などを参考に以下のコマンドでインストールしてみます

    ```bash:command
sudo apt-get update; sudo apt-get install software-properties-common
sudo apt-add-repository ppa:ansible/ansible
    ```

    ```bash
Hit:1 http://jp.archive.ubuntu.com/ubuntu xenial InRelease
Hit:2 http://jp.archive.ubuntu.com/ubuntu xenial-updates InRelease
Hit:3 http://jp.archive.ubuntu.com/ubuntu xenial-backports InRelease
..(snip)..
 Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy. Avoid writing scripts or custom code to deploy and update your applications— automate in a language that approaches plain English, using SSH, with no agents to install on remote systems.
http://ansible.com/
   More info: https://launchpad.net/~ansible/+archive/ubuntu/ansible
Press [ENTER] to continue or ctrl-c to cancel adding it
gpg: keyring `/tmp/tmpgtjfahxw/secring.gpg' created
gpg: keyring `/tmp/tmpgtjfahxw/pubring.gpg' created
gpg: requesting key 7BB9C367 from hkp server keyserver.ubuntu.com
gpg: /tmp/tmpgtjfahxw/trustdb.gpg: trustdb created
gpg: key 7BB9C367: public key "Launchpad PPA for Ansible, Inc." imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
OK
    ```
    * `ansible` のリポジトリを追加する場合は対話式のため、ENTERキーを押す必要があります。

    ```bash:command
sudo apt update; sudo apt install -y ansible python-pip python-dev
    ```

    ```bash
The following additional packages will be installed:
    libexpat1-dev libpython-all-dev libpython-dev libpython2.7-dev python-all python-all-dev python-cffi-backend python-crypto python-cryptography python-ecdsa python-enum34 python-httplib2 python-idna
  python-ipaddress python-jinja2 python-markupsafe python-paramiko python-pip-whl python-pkg-resources python-pyasn1 python-setuptools python-six python-wheel python-yaml python2.7-dev sshpass
Suggested packages:
    python-crypto-dbg python-crypto-doc python-cryptography-doc python-cryptography-vectors python-enum34-doc python-jinja2-doc python-setuptools-doc
The following NEW packages will be installed:
  ansible libexpat1-dev libpython-all-dev libpython-dev libpython2.7-dev python-all python-all-dev python-cffi-backend python-crypto python-cryptography python-dev python-ecdsa python-enum34
  python-httplib2 python-idna python-ipaddress python-jinja2 python-markupsafe python-paramiko python-pip python-pip-whl python-pkg-resources python-pyasn1 python-setuptools python-six python-wheel
  python-yaml python2.7-dev sshpass
0 upgraded, 29 newly installed, 0 to remove and 0 not upgraded.
..(snip)..
    ```
    * **詰み戻り知識**:
        * パッケージのインストールは必須でした

    ```bash:command
sudo pip install pip --upgrade
pip --version; ansible --version
    ```

    ```bash
..(snip)..
pip 9.0.1 from /usr/local/lib/python2.7/dist-packages (python 2.7)
ansible 2.4.2.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/stack/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.12 (default, Nov 20 2017, 18:23:56) [GCC 5.4.0 20160609]
    ```
    * `pip` は若干古いので最新版にアップグレードしておきます
        * Warningメッセージが目障りなだけなので、しなくてもOKです
1. 作業用ディレクトリの作成と移動

    ```bash:command
mkdir kolla-bringup; cd kolla-bringup
    ```
1. kolla-ansible と kolla-kubernetes のインストール

    ```bash:command
git clone http://github.com/openstack/kolla-ansible; git clone http://github.com/openstack/kolla-kubernetes
sudo pip install -U ./kolla-ansible/; sudo pip install -U ./kolla-kubernetes/
    ```

    ```bash
Cloning into 'kolla-ansible'...
..(snip)..
Cloning into 'kolla-kubernetes'...
..(snip)..
  Running setup.py install for kolla-ansible ... done
Successfully installed Babel-2.5.1 Jinja2-2.10 MarkupSafe-1.0 PyYAML-3.12 asn1crypto-0.24.0 backports.ssl-match-hostname-3.5.0.1 certifi-2017.11.5 cffi-1.11.2 chardet-3.0.4 cryptography-2.1.4 debtcollector-1.19.0 docker-2.6.1 docker-pycreds-0.2.1 enum34-1.1.6 funcsigs-1.0.2 idna-2.6 ipaddress-1.0.18 iso8601-0.1.12 kolla-ansible-6.0.0.0b3.dev43 monotonic-1.4 netaddr-0.7.19 netifaces-0.10.6 oslo.config-5.1.0 oslo.i18n-3.19.0 oslo.utils-3.33.0 pbr-3.1.1 pycparser-2.18 pyparsing-2.2.0 pytz-2017.3 requests-2.18.4 rfc3986-1.1.0 setuptools-38.2.4 six-1.11.0 stevedore-1.28.0 urllib3-1.22 websocket-client-0.44.0 wrapt-1.10.11
..(snip)..
  Found existing installation: websocket-client 0.44.0
    Uninstalling websocket-client-0.44.0:
      Successfully uninstalled websocket-client-0.44.0
  Running setup.py install for websocket-client ... done
  Running setup.py install for kolla-kubernetes ... done
Successfully installed PrettyTable-0.7.2 cachetools-2.0.1 cliff-2.9.1 cmd2-0.7.8 google-auth-1.2.1 kolla-kubernetes-0.6.1.dev160 kubernetes-4.0.0 msgpack-python-0.4.8 oauthlib-2.0.6 oslo.context-2.19.3 oslo.log-3.35.0 oslo.serialization-2.22.0 pyasn1-0.4.2 pyasn1-modules-0.2.1 pyinotify-0.9.6 pyperclip-1.6.0 python-dateutil-2.6.1 requests-oauthlib-0.8.0 rsa-3.4.2 unicodecsv-0.14.1 websocket-client-0.40.0
    ```
    * **詰み戻り知識**:
        * 公式ドキュメントの `sudo pip install -U kolla-ansible/ kolla-kubernetes/` と実行すると、kolla-ansible が依存している websocket-clientのバージョン(0.44)が入ってしまいkolla-kubernetesお抱えのCLI `kollakube` がまともに動かなくなります。
        * また `-U` がない場合、 `ContextualVersionConflict: (pyasn1 0.1.9 (/usr/lib/python2.7/dist-packages), Requirement.parse('pyasn1<0.5.0,>=0.4.1'), set(['pyasn1-modules']))` が発生します
1. 設定ファイルをコピー

    ```bash:command
sudo cp -aR /usr/local/share/kolla-ansible/etc_examples/kolla /etc
sudo cp -aR kolla-kubernetes/etc/kolla-kubernetes /etc
    ```
    * **詰み戻り知識**: 公式ドキュメントでは `/usr/share/kolla-ansible/etc_examples/kolla`
      とありますが、そんなディレクトリはなかったぜ！
1. kolla-kubernetes の default のパスワードを生成(レスポンスに3秒程度かかります）

    ```bash:command
sudo kolla-kubernetes-genpwd
    ```
1. kolla用の namespaceを生成

    ```bash:command
kubectl create namespace kolla
    ```

    ```bash
namespace "kolla" created
    ```
1. AIO(All-In-One) Node用の設定（今回はAIOですので設定します）

    ```bash:command
kubectl label node $(hostname) kolla_compute=true; kubectl label node $(hostname) kolla_controller=true
    ```

    ```bash
node "kolla" labeled
node "kolla" labeled
    ```
1. `/etc/kolla/globals.yml`に以下の定義を追加
    * `network_interface` には外部から参照可能なIPが振られているNICを指定します
    * `neutron_external_interface` には適当なI/Fを指定します

    ```diff:/etc/kolla/globals.yml
+network_interface: "ens3"
+neutron_external_interface: "ens4"
    ```
    * ワンライナーでできるようにしたかった
    * 今回、All-in-one Nodeでの実施ですので、上記に加えて以下も追加します

    ```diff:/etc/kolla/globals.yml
-kolla_internal_vip_address: "10.10.10.254"
+kolla_internal_vip_address: "192.168.122.244"
-#enable_haproxy: "yes"
+enable_haproxy: "no"
    ```
    * **詰み戻り知識**: `kolla_internal_vip_address`を外部からアクセス可能なアドレスに設定しない場合
      VMインスタンスへの `novnc` 接続に失敗します。

1. `/etc/kolla/globals.yml`に更に以下の定義を追加

    ```bash:command
cat <<EOF > add-to-globals.yml
kolla_install_type: "source"
tempest_image_alt_id: "{{ tempest_image_id }}"
tempest_flavor_ref_alt_id: "{{ tempest_flavor_ref_id }}"
neutron_plugin_agent: "openvswitch"
api_interface_address: 0.0.0.0
tunnel_interface_address: 0.0.0.0
orchestration_engine: KUBERNETES
memcached_servers: "memcached"
keystone_admin_url: "http://keystone-admin:35357/v3"
keystone_internal_url: "http://keystone-internal:5000/v3"
keystone_public_url: "http://keystone-public:5000/v3"
glance_registry_host: "glance-registry"
neutron_host: "neutron"
keystone_database_address: "mariadb"
glance_database_address: "mariadb"
nova_database_address: "mariadb"
nova_api_database_address: "mariadb"
neutron_database_address: "mariadb"
cinder_database_address: "mariadb"
ironic_database_address: "mariadb"
placement_database_address: "mariadb"
rabbitmq_servers: "rabbitmq"
openstack_logging_debug: "True"
enable_heat: "no"
enable_cinder: "yes"
enable_cinder_backend_lvm: "yes"
enable_cinder_backend_iscsi: "yes"
enable_cinder_backend_rbd: "no"
enable_ceph: "no"
enable_elasticsearch: "no"
enable_kibana: "no"
glance_backend_ceph: "no"
cinder_backend_ceph: "no"
nova_backend_ceph: "no"
EOF
cat ./add-to-globals.yml | sudo tee -a /etc/kolla/globals.yml
    ```

    ```bash
kolla_install_type: "source"
tempest_image_alt_id: "{{ tempest_image_id }}"
tempest_flavor_ref_alt_id: "{{ tempest_flavor_ref_id }}"
neutron_plugin_agent: "openvswitch"
api_interface_address: 0.0.0.0
tunnel_interface_address: 0.0.0.0
orchestration_engine: KUBERNETES
memcached_servers: "memcached"
keystone_admin_url: "http://keystone-admin:35357/v3"
keystone_internal_url: "http://keystone-internal:5000/v3"
keystone_public_url: "http://keystone-public:5000/v3"
glance_registry_host: "glance-registry"
neutron_host: "neutron"
keystone_database_address: "mariadb"
glance_database_address: "mariadb"
nova_database_address: "mariadb"
nova_api_database_address: "mariadb"
neutron_database_address: "mariadb"
cinder_database_address: "mariadb"
ironic_database_address: "mariadb"
placement_database_address: "mariadb"
rabbitmq_servers: "rabbitmq"
openstack_logging_debug: "True"
enable_heat: "no"
enable_cinder: "yes"
enable_cinder_backend_lvm: "yes"
enable_cinder_backend_iscsi: "yes"
enable_cinder_backend_rbd: "no"
enable_ceph: "no"
enable_elasticsearch: "no"
enable_kibana: "no"
glance_backend_ceph: "no"
cinder_backend_ceph: "no"
nova_backend_ceph: "no"
    ```
1. `libvirt`の設定

    ```bash:command
sudo mkdir /etc/kolla/config
sudo tee /etc/kolla/config/nova.conf<<EOF
[libvirt]
virt_type=qemu
cpu_mode=none
EOF
    ```

    ```bash
[libvirt]
virt_type=qemu
cpu_mode=none
    ```
1. kollaのデフォルトのConfigurationを生成（ansibleが動くため、1分程度かかります）

    ```bash:command
pushd /usr/local/share/kolla-kubernetes/
sudo ansible-playbook -e ansible_python_interpreter=/usr/bin/python \
-e @/etc/kolla/globals.yml -e @/etc/kolla/passwords.yml \
-e CONFIG_DIR=/etc/kolla ./ansible/site.yml
popd
    ```

    ```bash
TASK [ironic : Check if policies shall be overwritten] *****************************************************************************************************************************************************
ok: [localhost -> localhost]
TASK [ironic : Copying over existing policy.json] **********************************************************************************************************************************************************
skipping: [localhost] => (item=ironic-api)
skipping: [localhost] => (item=ironic-conductor)
skipping: [localhost] => (item=ironic-inspector)
skipping: [localhost] => (item=ironic-inspector-tftp)
PLAY RECAP *************************************************************************************************************************************************************************************************
localhost                  : ok=67   changed=57   unreachable=0    failed=0
    ```
    * **詰み戻り知識**:
        * 公式ドキュメントには `kolla-ansible genconfig`と書いてありますが、こちらを使います
        * 公式のドキュメントに書いてあるとおりに `kolla-ansible genconfig`を叩くと
          以下で実行する `kollakube` コマンドが異常終了します。詳しくは **トラブルシューティング**参照。
1. kolla-kubernetes の秘密鍵を生成

    ```bash:command
kolla-kubernetes/tools/secret-generator.py create
    ```

    ```bash
..(snip)..
secret "cinder-rbd-secret-uuid" created
secret "freezer-database-password" created
secret "horizon-secret-key" created
secret "barbican-keystone-password" created
secret "nova-database-password" created
secret "congress-database-password" created
secret "panko-database-password" created
    ```
1. `kollakube`コマンドを使って、 kubernetes 上の `configmap` を生成
    * ようやくkolla-kubernetesが仕事をします。configmapを生成することで、`helm`経由でOpenStackコンポーネントのPodがガシガシ起動できるはずです。

    ```bash:command
kollakube res create configmap \
    mariadb keystone horizon rabbitmq memcached nova-api nova-conductor \
    nova-scheduler glance-api-haproxy glance-registry-haproxy glance-api \
    glance-registry neutron-server neutron-dhcp-agent neutron-l3-agent \
    neutron-metadata-agent neutron-openvswitch-agent openvswitch-db-server \
    openvswitch-vswitchd nova-libvirt nova-compute nova-consoleauth \
    nova-novncproxy nova-novncproxy-haproxy neutron-server-haproxy \
    nova-api-haproxy cinder-api cinder-api-haproxy cinder-backup \
    cinder-scheduler cinder-volume iscsid tgtd keepalived \
    placement-api placement-api-haproxy
    ```

    ```bash
configmap "mariadb" created
configmap "keystone" created
configmap "horizon" created
..(snip)..
configmap "placement-api" created
configmap "placement-api-haproxy" created
    ```
1. `Helm microcharts`, `service charts`, `metacharts` をビルド

    ```bash:command
kolla-kubernetes/tools/helm_build_all.sh .
    ```

    ```bash
Processing   1/175 Saving 1 charts
Deleting outdated charts
Processing   2/175 Saving 1 charts
Deleting outdated charts
..(snip)..
Saving 13 charts
Deleting outdated charts
Successfully packaged chart and saved it to: /home/stack/kolla-bringup/compute-kit-0.7.0-1.tgz
~/kolla-bringup ~/kolla-bringup
Successfully packaged chart and saved it to: /home/stack/kolla-bringup/compute-kit-0.7.0-1.tgz
~/kolla-bringup
Hang tight while we grab the latest from your chart repositories...
...Skip local chart repository
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈ Happy Helming!⎈
    ```
    * やっぱり **Happy Helming!**
1. **150** 以上の Helm のイメージが作成されたことを確認（謎の確認）
 
    ```bash
ls | grep ".tgz" | wc -l
    ```

    ```bash
195
    ```
1. `charts` 用の cloud.yaml を生成（`yaml` か `yml` って統一してほしい！）

    ```bash:command
cat <<EOF > cloud.yaml
global:
      kolla:
        all:
          docker_registry: docker.io
          image_tag: "4.0.0"
          kube_logger: false
          external_vip: "192.168.7.105"
          base_distro: "centos"
          install_type: "source"
          tunnel_interface: "docker0"
        keystone:
          all:
            admin_port_external: "true"
            dns_name: "192.168.7.105"
            port: 5000
          public:
            all:
              port_external: "true"
        rabbitmq:
          all:
            cookie: 67
        glance:
          api:
            all:
              port_external: "true"
        cinder:
          api:
            all:
              port_external: "true"
        volume_lvm:
          all:
            element_name: cinder-volume
          daemonset:
            lvm_backends:
            - '192.168.7.105': 'cinder-volumes'
        ironic:
          conductor:
            daemonset:
              selector_key: "kolla_conductor"
        nova:
          placement_api:
            all:
              port_external: true
          novncproxy:
            all:
              port: 6080
              port_external: true
        openvswitch:
          all:
            add_port: true
            ext_bridge_name: br-ex
            ext_interface_name: enp1s0f1
            setup_bridge: true
        horizon:
          all:
            port_external: true
EOF
    ```
    * 公式のドキュメント内の `cloud.yaml`だと、Keystoneのポート番号(5000)が抜けています
        * これがないとKeystoneが正常に動作しませんでした。
    * markdownの挿入機能って書いたとおりにネストされないんですね
        * これに気付けないまま、変なインデントになった cloud.yamlを使っていました(どんかん！)
        * 当然、`helm install` コマンドで作られたPodは全てコケました
1. ちょっと複雑な copy&paste
    * 公式ドキュメントに以下の記載がありました：

        > The next operations are not a simple copy and paste as the rest of this document is structured.

    ```bash:DONOT_EXECUTE
このように書いてあります。 **これはそのまま実行しません!!**
sed -i "s@192.168.7.105@YOUR_NETWORK_INTERFACE_ADDRESS_FROM_GLOBALS.YML@g" ./cloud.yaml
sed -i "s@enp1s0f1@YOUR_NEUTRON_INTERFACE_NAME_FROM_GLOBALS.YML@g" ./cloud.yaml
sed -i "s@docker0@YOUR_NETWORK_INTERFACE_NAME_FROM_GLOBALS.YML@g" ./cloud.yaml
    ```
    * 以下の**3つ**の部分を置換したものを実行します：
        1. YOUR_NETWORK_INTERFACE_ADDRESS_FROM_GLOBALS.YML: `network_interface` に指定したインターフェースに割り当てられたIPアドレス
            * 今回は `192.168.122.244`
        2.  YOUR_NETWORK_INTERFACE_NAME_FROM_GLOBALS.YML: `network_interface`に指定したインターフェース
            * 今回は ``ens3``
        3. YOUR_NEUTRON_INTERFACE_NAME_FROM_GLOBALS.YML: `neutron_external_interface`に指定したインターフェース
            * 今回は `ens4`
    * 置換した以下のコマンドを実行します：

    ```bash:command
sed -i "s@192.168.7.105@192.168.122.244@g" ./cloud.yaml
sed -i "s@enp1s0f1@ens4@g" ./cloud.yaml
sed -i "s@docker0@ens3@g" ./cloud.yaml
    ```

## OpenStack構築

1. `mariadb`の起動

    ```bash:command
helm install --debug kolla-kubernetes/helm/service/mariadb --namespace kolla --name mariadb --values ./cloud.yaml
    ```

    ```bash
..(snip)..
RESOURCES:
==> v1/Job
NAME                  DESIRED  SUCCESSFUL  AGE
mariadb-init-element  1        0           1s
==> v1/Pod(related)
NAME                        READY  STATUS             RESTARTS  AGE
mariadb-init-element-h8lxz  0/1    ContainerCreating  0         1s
==> v1/PersistentVolume
NAME     CAPACITY  ACCESS MODES  RECLAIM POLICY  STATUS     CLAIM  STORAGECLASS  REASON  AGE
mariadb  10Gi      RWO           Retain          Available  1s
==> v1/PersistentVolumeClaim
NAME     STATUS   VOLUME  CAPACITY  ACCESS MODES  STORAGECLASS  AGE
mariadb  Pending  1s
==> v1/Service
NAME     TYPE       CLUSTER-IP  EXTERNAL-IP  PORT(S)   AGE
mariadb  ClusterIP  10.3.3.186  <none>       3306/TCP  1s
==> v1beta1/StatefulSet
NAME     DESIRED  CURRENT  AGE
mariadb  1        1        1s
    ```
    * Podのstatus が *Running* になるまで待ちます

    ```bashj:command
kubectl get pods --all-namespaces
    ```

    ```bash
NAMESPACE     NAME                            READY     STATUS    RESTARTS   AGE
kolla         mariadb-0                       1/1       Running   0          30m
kube-system   canal-2tnc6                     3/3       Running   0          1h
kube-system   etcd-kolla                      1/1       Running   0          1h
kube-system   kube-apiserver-kolla            1/1       Running   0          1h
kube-system   kube-controller-manager-kolla   1/1       Running   0          1h
kube-system   kube-dns-545bc4bfd4-s5qd4       3/3       Running   0          1h
kube-system   kube-proxy-fqn9b                1/1       Running   0          1h
kube-system   kube-scheduler-kolla            1/1       Running   0          1h
kube-system   tiller-deploy-5b9d65c7f-bsjll   1/1       Running   0          1h
    ```
    * 無事に *Running* してくれました
1. その他OpenStackサービスの起動
    * 調子にのって一気に起動してみます

    ```bash:command
helm install --debug kolla-kubernetes/helm/service/rabbitmq --namespace kolla --name rabbitmq --values ./cloud.yaml
helm install --debug kolla-kubernetes/helm/service/memcached --namespace kolla --name memcached --values ./cloud.yaml
helm install --debug kolla-kubernetes/helm/service/keystone --namespace kolla --name keystone --values ./cloud.yaml
helm install --debug kolla-kubernetes/helm/service/glance --namespace kolla --name glance --values ./cloud.yaml
helm install --debug kolla-kubernetes/helm/service/cinder-control --namespace kolla --name cinder-control --values ./cloud.yaml
helm install --debug kolla-kubernetes/helm/service/horizon --namespace kolla --name horizon --values ./cloud.yaml
helm install --debug kolla-kubernetes/helm/service/openvswitch --namespace kolla --name openvswitch --values ./cloud.yaml
helm install --debug kolla-kubernetes/helm/service/neutron --namespace kolla --name neutron --values ./cloud.yaml
helm install --debug kolla-kubernetes/helm/service/nova-control --namespace kolla --name nova-control --values ./cloud.yaml
helm install --debug kolla-kubernetes/helm/service/nova-compute --namespace kolla --name nova-compute --values ./cloud.yaml
    ```
    * 出力結果は長いので省略します。全て起動するのに1時間弱かかります

1. サービス起動確認

    ```bash:command
kubectl get pods --all-namespaces -o wide
    ```

    ```bash
NAMESPACE     NAME                                      READY     STATUS    RESTARTS   AGE       IP                NODE
kolla         cinder-api-7f44bf94b7-j8mk5               3/3       Running   0          1h        10.1.0.32         kolla
kolla         cinder-scheduler-0                        1/1       Running   0          1h        10.1.0.29         kolla
kolla         glance-api-6fc449456d-qt65f               1/1       Running   0          1h        10.1.0.20         kolla
kolla         glance-registry-59cbb7495c-vhhhk          3/3       Running   0          1h        10.1.0.12         kolla
kolla         horizon-6d99dcf4fd-5kz2r                  1/1       Running   0          1h        10.1.0.34         kolla
kolla         keystone-6b75955498-7p5mw                 1/1       Running   0          1h        10.1.0.64         kolla
kolla         mariadb-0                                 1/1       Running   0          1h        10.1.0.5          kolla
kolla         memcached-5d944846f-pwt8h                 2/2       Running   0          1h        10.1.0.8          kolla
kolla         neutron-dhcp-agent-pq6qx                  1/1       Running   0          1h        192.168.122.244   kolla
kolla         neutron-l3-agent-network-2tm2p            1/1       Running   0          1h        192.168.122.244   kolla
kolla         neutron-metadata-agent-network-t5559      1/1       Running   0          1h        192.168.122.244   kolla
kolla         neutron-openvswitch-agent-network-dhsbw   1/1       Running   0          1h        192.168.122.244   kolla
kolla         neutron-server-785d44d968-rqngv           3/3       Running   0          1h        10.1.0.40         kolla
kolla         nova-api-78969dd97b-5nffm                 3/3       Running   0          1h        10.1.0.43         kolla
kolla         nova-compute-qjhrc                        1/1       Running   0          3m        192.168.122.244   kolla
kolla         nova-conductor-0                          1/1       Running   0          1h        10.1.0.46         kolla
kolla         nova-consoleauth-0                        1/1       Running   0          1h        10.1.0.49         kolla
kolla         nova-libvirt-248cm                        1/1       Running   0          3m        192.168.122.244   kolla
kolla         nova-novncproxy-6fdd7fbc69-szcp5          3/3       Running   0          1h        10.1.0.44         kolla
kolla         nova-scheduler-0                          1/1       Running   0          1h        10.1.0.53         kolla
kolla         openvswitch-ovsdb-network-ptnfc           1/1       Running   0          1h        192.168.122.244   kolla
kolla         openvswitch-vswitchd-network-pzxlp        1/1       Running   0          1h        192.168.122.244   kolla
kolla         placement-api-64d549bc7b-m5lct            1/1       Running   0          1h        10.1.0.47         kolla
kolla         rabbitmq-0                                1/1       Running   0          1h        10.1.0.6          kolla
kube-system   canal-5htn8                               3/3       Running   0          2h        192.168.122.244   kolla
kube-system   etcd-kolla                                1/1       Running   0          2h        192.168.122.244   kolla
kube-system   kube-apiserver-kolla                      1/1       Running   0          2h        192.168.122.244   kolla
kube-system   kube-controller-manager-kolla             1/1       Running   0          2h        192.168.122.244   kolla
kube-system   kube-dns-6f4fd4bdf-b46ph                  3/3       Running   0          2h        10.1.0.2          kolla
kube-system   kube-proxy-fxb9h                          1/1       Running   0          2h        192.168.122.244   kolla
kube-system   kube-scheduler-kolla                      1/1       Running   0          2h        192.168.122.244   kolla
kube-system   tiller-deploy-587df449fb-r5jn4            1/1       Running   0          2h        10.1.0.3          kolla
    ```
    * 全てのサービスが *Running* しました。OpenStack環境の構築完了です！

1. keystone_admin の作成

    ```bash:command
kolla-kubernetes/tools/build_local_admin_keystonerc.sh ext
source ~/keystonerc_admin
    ```
    * admin パスワードは  `env | grep OS_` の **OS_PASSWORD** に格納されています
1. Horizon(dashboard)へアクセスするための情報取得

    ```bash:command
kubectl get svc horizon --namespace=kolla
    ```

    ```bash
NAME      TYPE        CLUSTER-IP   EXTERNAL-IP       PORT(S)   AGE
horizon   ClusterIP   10.3.3.129   192.168.122.244   80/TCP    27m
    ```
    * `EXTERNAL-IP` つまりホストIP:80にアクセスすればOKです
1. Horizonへアクセス

![horizon.png](https://qiita-image-store.s3.amazonaws.com/0/152668/b2b21c09-c4fc-94d2-2bb2-774e17b45330.png)

(｀・ω・´)＜ヨカッタ

## 簡単な動作確認

IaaS基盤は作るだけで終わりではありません。使い倒すことに意味があります。
とか言いつつ、今回は簡単な動作確認を行いました。

1. python-openstackclientのインストール
   公式ドキュメントに従って、以下の3つをインストールします

    ```bash:command
sudo pip install "python-openstackclient"
sudo pip install "python-neutronclient"
sudo pip install "python-cinderclient"
    ```

    ```
..(snip)..
Successfully installed appdirs-1.4.3 deprecation-1.0.1 functools32-3.2.3.post2 jsonpatch-1.20 jsonpointer-1.14 jsonschema-2.6.0 keystoneauth1-3.3.0 openstacksdk-0.9.19 os-client-config-1.28.0 osc-lib-1.8.0 pyOpenSSL-17.5.0 python-cinderclient-3.3.0 python-glanceclient-2.8.0 python-keystoneclient-3.14.0 python-novaclient-9.1.1 python-openstackclient-3.13.0 requestsexceptions-1.3.0 simplejson-3.13.2 warlock-1.2.0
..(snip)..
Installing collected packages: python-neutronclient
Successfully installed python-neutronclient-6.6.0
..(snip)..
    ```
1. VM配備用のリソース登録
   kolla-kubernetes経由で作成されたOpenStack上には、アカウント以外のリソースは一切ありません。
   そこで、下記のコマンドを使ってリソースを作成・登録していきます。

    ```bash:command
source ~/keystonerc_admin
kolla-ansible/tools/init-runonce
    ```

    ```bash
Downloading glance image.
..(snip)..
Configuring neutron.
..(snip)..
Generating ssh key.
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
..(snip)..
Configuring nova public key and quotas.
..(snip)..
Done.
To deploy a demo instance, run:
openstack server create \
    --image cirros \
    --flavor m1.tiny \
    --key-name mykey \
    --nic net-id=ba003a06-3707-4cc9-b3aa-85c1f15e0624 \
    demo1
    ```
    * 途中で `ssh-keygen`が動くようなのでパスワードが聞かれます
    * ここで kolla-ansibleを使うんですね。なぜインストールするのか疑問でしたが解決しました
    * このコマンドでVMインスタンスが作れまっせ、と教えてもらっているので素直に実行します
1. VMインスタンスの作成

    ```bash:command
openstack server create \
    --image cirros \
    --flavor m1.tiny \
    --key-name mykey \
    --nic net-id=ba003a06-3707-4cc9-b3aa-85c1f15e0624 \
    demo1
openstack server list
    ```

    ```bash
+--------------------------------------+-------+--------+-------------------+--------+---------+
| ID                                   | Name  | Status | Networks          | Image  | Flavor  |
+--------------------------------------+-------+--------+-------------------+--------+---------+
| 4bf79ad9-f9bc-4721-97f7-dacfec49ee07 | demo1 | ACTIVE | demo-net=10.0.0.6 | cirros | m1.tiny |
+--------------------------------------+-------+--------+-------------------+--------+---------+
    ```
    * 僕の環境だとVM起動まで30秒弱くらいでした
    * cirrosはデフォルトでパスワード認証ですので、keypairの指定はなくても良いです
1. 出来上がったネットワーク構成の確認
   ![topology2.png](https://qiita-image-store.s3.amazonaws.com/0/152668/63c0ca12-dd20-67b8-99a8-77a13de0abcf.png)
    * 以下のリソースが生成されました:
        1. network(internal)
        1. network(external)
        1. subnet(internal)
        1. subnet(external)
        1. router(internalとexternalとを接続)
        1. DHCP server(internal用)
        1. flavor(m1.tiny)
        1. image(cirros)
        1. keypair
1. 作成したVMにログイン(コンソール経由)
   ![console.png](https://qiita-image-store.s3.amazonaws.com/0/152668/e4570c0d-02ca-9ad4-3dc4-73971e3f53fd.png)
    * router, DHCP共に問題なく通信できました。
    * **詰み戻り知識**: `kolla_internal_vip_address` を書き換えないままここに来た場合、Horizon経由でコンソール画面にアクセスできません

        ```bash:command
openstack console url show demo1
        ```

        ```bash
+-------+--------------------------------------------------------------------------------------+
| Field | Value                                                                                |
+-------+--------------------------------------------------------------------------------------+
| type  | novnc                                                                                |
| url   | http://10.10.10.254:6080/vnc_auto.html?token=cc3df474-dffd-4d2d-9491-d37667fab837    |
+-------+--------------------------------------------------------------------------------------+
        ```
        * 原因: `kolla_internal_vip_address` の値は `/etc/kolla/nova-novncproxy/nova.conf` の `novncproxy_base_url` に割り当たるため
        * 回避策: `10.10.10.254` の部分を `network_interface`に設定しているIP に書き換えることでアクセスできます
    * **個人的に気になっていたこと**
        * Q: neutronの router/dhcp(network namespace)はどうやって確認するの？
            * A: dhcp-agent, l3-agent用のコンテナへ rootログインを実施後
              `ip netns exec <namespace> bash` で確認可能
                * network namespaceはホスト上に作られているように見えていますが、ホストからは中に入れないという構成でした。
        * 以下、network namespaceの入り方のメモです。

    ```bash:command
ip netns
    ```

    ```bash
qrouter-cba0487c-ede0-4169-82c9-067020dbc7ec
qdhcp-1f2987de-c742-4660-8cf0-a80a4f81525b
    ```

    ```bash:command
sudo ip netns exec qdhcp-1f2987de-c742-4660-8cf0-a80a4f81525b ip a
    ```

    ```bash
RTNETLINK answers: Invalid argument
RTNETLINK answers: Invalid argument
setting the network namespace "qdhcp-1f2987de-c742-4660-8cf0-a80a4f81525b" failed: Invalid argument
    ```
    * namespaceはホスト上から見えているのにログインできませんでした
    * neutron-dhcp-agentのコンテナの中から入れるかどうか試してみます

    ```bash:command
kubectl exec -it `kubectl get pods -n kolla | grep neutron-dhcp-agent | awk '{print $1}'` -n kolla /bin/bash
sudo ip netns exec qdhcp-1f2987de-c742-4660-8cf0-a80a4f81525b ip a
    ```

    ```bash
[sudo] password for neutron:
Sorry, try again.
[sudo] password for neutron:
Sorry, try again.
[sudo] password for neutron:
Sorry, try again.
sudo: 3 incorrect password attempts
tput: No value for $TERM and no -T specified
tput: No value for $TERM and no -T specified
()[neutron@kolla /]$
    ```
    * え、パスワード知らない
    * `kubectl` を使って root ログインは無理そうですが、`docker`なら可能です
    * というわけで試してみます

    ```bash:command
sudo docker exec -it -u root `sudo docker ps | grep neutron-dhcp-agent | grep k8s_main | awk '{print $10}'` /bin/bash
sudo ip netns exec qdhcp-1f2987de-c742-4660-8cf0-a80a4f81525b ip a
    ```

    ```bash
tput: No value for $TERM and no -T specified
tput: No value for $TERM and no -T specified
tput: No value for $TERM and no -T specified
tput: No value for $TERM and no -T specified
()[root@kolla /]# sudo ip netns exec qdhcp-1f2987de-c742-4660-8cf0-a80a4f81525b ip a
RTNETLINK answers: Invalid argument
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
78: tap20115e25-aa: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN qlen 1
    link/ether fa:16:3e:78:db:26 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.2/24 brd 10.0.0.255 scope global tap20115e25-aa
       valid_lft forever preferred_lft forever
    inet 169.254.169.254/16 brd 169.254.255.255 scope global tap20115e25-aa
       valid_lft forever preferred_lft forever
    inet6 fe80::f816:3eff:fe78:db26/64 scope link
       valid_lft forever preferred_lft forever
()[root@kolla /]#
    ```
    * dhcp-agent, l3-agent, それぞれのコンテナの中からでないと確認できないようです
    * routerの namespaceを確認したい場合は以下のコマンドを実施後、 `ip netns exec ...` を実施します

    ```bash:command
sudo docker exec -it -u root `sudo docker ps | grep neutron-l3-agent-network | grep k8s_main | awk '{print $10}'` /bin/bash
    ```

以上で動作確認完了です。

# まとめ

* kolla-kubernetesは kollaと組み合わせてkubernetes上にOpenStackコンテナをデプロイする機能を持つ
    * kubernetes v1.8.5と v1.9.0(現状最新版)で利用可能
* 基礎環境構築が複雑すぎる！自動化しないと精神がすり減ります
    * と思ったら kolla-kubernetesは **ko.py** という自動デプロイスクリプトを持っていました
    * **このスクリプトの使い方こそ公式ドキュメントでしっかり説明しろよ！** とツッコミを入れたい
    * ko.pyも今回検出したバグに合わせ治すところが結構あるので今は使えません
* 一旦構築してしまうとサービスごとの配備/撤去もコマンド一つなのでとても楽でした
* 1台のVM(Ubuntu16.04)でも試すことができるため、味見のハードルは割りと低いです

コンテナ＋CoE(Container Orchestration Engine）でOpenStack環境を構築するというアプローチは素敵なので
今後はkolla-kubernetesを使える環境のデプロイを簡易化して欲しいです。

# 役に立ったコマンド達

* Pod削除(helm経由)

    ```bash:command
helm delete <config> --purge
    ```
* Podのログ参照(見える内容は`docker logs`と同じっぽいです)

    ```bash:command
kubectl logs <pod> -n <namespace> 
    ```
* なんか色々ログを見たい

    ```bash:command
sudo journalctl -xef
    ```
* kubernetesコンテナ内へログイン

    ```bash:command
kubectl exec -it <pod> -n <namespace> /bin/bash
    ```

#トラブルシューティング

`kollakube` コマンドでエラーが返ってきた件を例に、どうやってバグを見つけたのかを
残しておきます

1. 普通にコマンドを叩いてみる

    ```bash:command
kollakube res create configmap \
>     mariadb keystone horizon rabbitmq memcached nova-api nova-conductor \
>     nova-scheduler glance-api-haproxy glance-registry-haproxy glance-api \
>     glance-registry neutron-server neutron-dhcp-agent neutron-l3-agent \
>     neutron-metadata-agent neutron-openvswitch-agent openvswitch-db-server \
>     openvswitch-vswitchd nova-libvirt nova-compute nova-consoleauth \
>     nova-novncproxy nova-novncproxy-haproxy neutron-server-haproxy \
>     nova-api-haproxy cinder-api cinder-api-haproxy cinder-backup \
>     cinder-scheduler cinder-volume iscsid tgtd keepalived \
>     placement-api placement-api-haproxy
    ```

    ```bash:stdout
..(snip)..
Traceback (most recent call last):
  File "/usr/local/bin/kollakube", line 10, in <module>
    sys.exit(main_kube())
  File "/usr/local/lib/python2.7/dist-packages/kolla_kubernetes/app.py", line 123, in main_kube
    return kks.run(argv)
  File "/usr/local/lib/python2.7/dist-packages/cliff/app.py", line 279, in run
    result = self.run_subcommand(remainder)
  File "/usr/local/lib/python2.7/dist-packages/cliff/app.py", line 400, in run_subcommand
    result = cmd.run(parsed_args)
  File "/usr/local/lib/python2.7/dist-packages/cliff/command.py", line 184, in run
    return_code = self.take_action(parsed_args) or 0
  File "/usr/local/lib/python2.7/dist-packages/kolla_kubernetes/commands/cmd_resource.py", line 332, in take_action
    tmpl = super(Resource, self).take_action(args, skip_and_return=True)
  File "/usr/local/lib/python2.7/dist-packages/kolla_kubernetes/commands/cmd_resource.py", line 170, in take_action
    resource_name):
  File "/usr/local/lib/python2.7/dist-packages/kolla_kubernetes/pathfinder.py", line 58, in find_config_files
    return PathFinder._list_dir_files(path)
  File "/usr/local/lib/python2.7/dist-packages/kolla_kubernetes/pathfinder.py", line 87, in _list_dir_files
    paths = [os.path.join(path, fn) for fn in next(os.walk(path))[2]]
StopIteration
    ```
    * エラー発生(´・ω・｀)

1. /usr/local/lib/python2.7/dist-packages/kolla_kubernetes/pathfinder.py", line 87を開いてみる
    * 以下のメソッドが例外を起こしていました

    ```python:/usr/local/lib/python2.7/dist-packages/kolla_kubernetes/pathfinder.py
def _list_dir_files(path):
        paths = [os.path.join(path, fn) for fn in next(os.walk(path))[2]]
        return paths
    ```
    * `os.walk(path)`の戻り値(generator)に `next()`をかましています。これ自体は問題無いですが、戻り値がgeneratorではない場合の考慮が抜けているため、`StopIteration`が発生しています
    * ということでちょろっとソースを書き換えてみます

    ```python:/usr/local/lib/python2.7/dist-packages/kolla_kubernetes/pathfinder.py
def _list_dir_files(path):
        try:
            return [os.path.join(path, fn) for fn in next(os.walk(path))[2]]
        except StopIteration:
            print("Skip: path=%s" % path)
        return []
    ```
1. 再実行

    ```bash:command
kollakube --debug res create configmap \
    mariadb keystone horizon rabbitmq memcached nova-api nova-conductor \
    nova-scheduler glance-api-haproxy glance-registry-haproxy glance-api \
    glance-registry neutron-server neutron-dhcp-agent neutron-l3-agent \
    neutron-metadata-agent neutron-openvswitch-agent openvswitch-db-server \
    openvswitch-vswitchd nova-libvirt nova-compute nova-consoleauth \
    nova-novncproxy nova-novncproxy-haproxy neutron-server-haproxy \
    nova-api-haproxy cinder-api cinder-api-haproxy cinder-backup \
    cinder-scheduler cinder-volume iscsid tgtd keepalived \
    placement-api placement-api-haproxy --log-file res_configmap.log
    ```
    * エラーなく終了したので、kubectlに登録されている configmapを確認します

    ```bash:command
kubectl get configmap --all-namespaces
    ```

    ```bash:stdout
NAMESPACE     NAME                                 DATA      AGE
..(snip)..
kolla         cinder-api                           3         9m
kolla         mariadb                              0         9m
    ```
    * `cinder-api`は3つのデータを登録しているのに `mariadb`は未登録の状態
    * 実行結果である `res_configmap.log` を調査してみたところ、/etc/kolla配下
      の `NAME`のディレクトリ内のファイルを検索していました
    * 次に、/etc/kolla配下のディレクトリを見てみます

    ```bash
sudo ls -la /etc/kolla
--
drwxr-xr-x   2 root root  4096 12月 11 23:53 cinder-api/
..(snip)..
drwxrwx---   2 root root  4096 12月 11 23:53 mariadb/
    ```
    * 違いとしては、`other`の実行権限でした
        * 成功した cinder-api/ のパーミッション: 7 5 5
        * 失敗した mariadb/ のパーミッション: 7  5 **0**
1. ディレクトリのパーミッションを変更後、再度実行してみます

    ```bash:command
sudo chmod -R 755 /etc/kolla/
    ```

    ```bash:command
kollakube --debug res delete configmap \
    mariadb keystone horizon rabbitmq memcached nova-api nova-conductor \
    nova-scheduler glance-api-haproxy glance-registry-haproxy glance-api \
    glance-registry neutron-server neutron-dhcp-agent neutron-l3-agent \
    neutron-metadata-agent neutron-openvswitch-agent openvswitch-db-server \
    openvswitch-vswitchd nova-libvirt nova-compute nova-consoleauth \
    nova-novncproxy nova-novncproxy-haproxy neutron-server-haproxy \
    nova-api-haproxy cinder-api cinder-api-haproxy cinder-backup \
    cinder-scheduler cinder-volume iscsid tgtd keepalived \
    placement-api placement-api-haproxy
kollakube --debug res create configmap \
    mariadb keystone horizon rabbitmq memcached nova-api nova-conductor \
    nova-scheduler glance-api-haproxy glance-registry-haproxy glance-api \
    glance-registry neutron-server neutron-dhcp-agent neutron-l3-agent \
    neutron-metadata-agent neutron-openvswitch-agent openvswitch-db-server \
    openvswitch-vswitchd nova-libvirt nova-compute nova-consoleauth \
    nova-novncproxy nova-novncproxy-haproxy neutron-server-haproxy \
    nova-api-haproxy cinder-api cinder-api-haproxy cinder-backup \
    cinder-scheduler cinder-volume iscsid tgtd keepalived \
    placement-api placement-api-haproxy --log-file res_configmap2.log
    ```

    ```bash:stdout
..(snip)..
configmap "tgtd" created
configmap "keepalived" created
configmap "placement-api" created
configmap "placement-api-haproxy" created
    ```
    * おお、登録できました。ということでディレクトリのパーミッションが問題だったようです

# 参考

* docker公式のUbuntuへのインストール手順
    * https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu
* docker v1.12 のインストール
    * https://docs.docker.com/cs-engine/1.12/
* helm
    * https://github.com/kubernetes/helm/blob/master/docs/install.md
    * https://docs.helm.sh/using_helm/#installing-helm
* kubernetes
    * https://kubernetes.io/
* Minikube
    * https://kubernetes.io/docs/tasks/tools/install-minikube/