今回はOpenstack-helmを使ってOpenstack環境を構築してみました。
公式ドキュメントを参照したのですが、現時点では上手く動作させられなかったので様々な情報を探しに探し、考えに考えて環境を構築してみました。インストールするコンポーネントなど基本的な流れは公式ドキュメントを参考にしています。
OSはUbuntu 20.04を使いました。理由は22.04ではLinux Bridgeが非推奨になったようでOVSが推奨になったようなのですが、OVSで壁に当たりすぎて結局Linux Bridgeでいったん構築してみようとなったためです。(一応22.04でも設定すればLinux Bridgeが使えるようになるのですが)
というわけで簡単な流れで解説していきますがやっていきます。
- 構築手順
- VM作成検証
- ダッシュボード確認
- 以上で完成です
構築手順
事前準備
まずなんでもよいので8コアとかスペックに余裕のある物理サーバーを準備します。そこにUbuntu20.04をインストールします。
ネットワークは疎通ができていたらなんでも良いです。ただVM用と管理用に分けておきます。
実際の設定とは違いますが、こんな感じです。eth1はインターネットに疎通できるという前提です。
network:
version: 2
renderer: networkd
ethernets:
eth1:
dhcp4: false
addresses:
- 192.168.0.10/24
gateway4: 192.168.0.1
nameservers:
addresses:
- 8.8.8.8
eth2:
dhcp4: false
link-local: []
そのあと、nfsをkubernetesで使用するため、以下をインストールします
apt -y install nfs-kernel-server
apt -y install nfs-common
Kubernetesクラスターの構築
OSをインストールしてネットワークの設定が済んだらKubernetesクラスターの構築をしていきます。
クラスターといっても初めはマスターノード(以降コントロールプレーン)だけとなります。
クラスターの構築はkubeadmを使います。公式ドキュメントや以下サイトを参考にして構築してみました。
kubeadm initしたあとのログは残しておきます。computeノードを追加するときにもう一台のサーバーをworkerノードとして追加する必要があるからです。しかし今はworkerノードは追加せずスキップしてください。
ちなみにコントロールプレーン名はホスト名と同一になります。
root@openstack-helm:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
openstack-helm Ready control-plane 6m57s v1.29.3
こうなっていればOKです。
Calicoだけ入れてPodは以下のようになります。
root@openstack-helm:~# kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system calico-kube-controllers-4dac4f45bc-tvsrx 1/1 Running 0 87s
kube-system calico-node-sxkxz 1/1 Running 0 87s
kube-system coredns-26fa5zx574-vqbf2 1/1 Running 0 7m41s
kube-system coredns-26fa5zx574-ck4w6 1/1 Running 0 7m41s
kube-system etcd-openstack-helm 1/1 Running 0 7m46s
kube-system kube-apiserver-openstack-helm 1/1 Running 0 7m49s
kube-system kube-controller-manager-openstack-helm 1/1 Running 0 7m46s
kube-system kube-proxy-2sfpp 1/1 Running 0 7m41s
kube-system kube-scheduler-openstack-helm 1/1 Running 0 7m46s
ここまで出来たら完了です。
コントロールプレーンにOpenstackのPodをデプロイする設定
デフォルトではコントロールプレーンにPodはデプロイできないので出来るように設定していきます。
kubectl taint nodes ホスト名 node-role.kubernetes.io/control-plane:NoSchedule-
#Taintの設定にマイナスをつけることでTaintを削除できます
#control-planeのところが以前はmasterとなっているバージョンもあります。(時代の流れ、、)
node/openstack-helm untaintedが表示されたら成功です。
Taintを消すところでエラーが起きたらkubectl describe node コントロールプレーン名でTaintを確認してみましょう
Helmのインストール
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
#以下動作確認
root@openstack-helm:~# helm version
version.BuildInfo{Version:"v3.14.3", GitCommit:"f03cc04caaa8f6d7c3e67cf918929150cf6f3f12", GitTreeState:"clean", GoVersion:"go1.21.7"}
これでHelmをインストールできました。
ラベルを貼る
コントロールプレーンにOpenstack、Computeノード、Linux BridgeのPodが作成されるようにlabelを設定しておきます。
kubectl label node コントロールプレーン名 openstack-control-plane=enabled;
kubectl label node コントロールプレーン名 openstack-compute-node=enabled;
kubectl label node コントロールプレーン名 linuxbridge=enabled;
必要なパッケージをインストールする
sudo apt-get install --no-install-recommends -y \
bc \
git \
jq \
make \
nmap \
python3-pip \
uuid-runtime
多くは既にインストールされているかもしれませんがこれを実行してインストールします。
DNS設定を行う
kubectl get pods -A -o wideでCoreDNSのpodを探し、そのIPアドレスを/etc/resolv.confに追加する。
kubectl get pods -A -o wide
echo "nameserver coreDNSのIP" | sudo tee -a /etc/resolv.conf
もしうまく動かない場合
後のkeystone構築などでDNSがうまく動いていないといわれることがあります。その場合は/etc/hostsに以下を突っ込んであげると解決します。
#192.168.0.10はコントロールプレーンのIPアドレスに置き換えてください
cat >>/etc/hosts<<EOF
192.168.0.10 keystone.openstack.svc.cluster.local
192.168.0.10 heat.openstack.svc.cluster.local
192.168.0.10 glance.openstack.svc.cluster.local
192.168.0.10 nova.openstack.svc.cluster.local
192.168.0.10 neutron.openstack.svc.cluster.local
EOF
openstack-helm構築準備
#最新のコミットではAnsibleで構築を前提としているようで、上手くいかなかったので
#Ansible構築前提以前のコミットを使います。またAnsibleのほうも検証してみます。
mkdir osh
cd osh
git clone https://opendev.org/openstack/openstack-helm.git
cd openstack-helm
git checkout 0943a9f774
cd ..
git clone https://opendev.org/openstack/openstack-helm-infra.git
cd openstack-helm-infra
git checkout d070774bfc
#環境変数で以下を入れておくことでOpenstack Yogaのバージョンでインストールされる
vi keystonerc
export OPENSTACK_RELEASE=yoga
export CONTAINER_DISTRO_NAME=ubuntu
export CONTAINER_DISTRO_VERSION=focal
#保存
source keystonerc
ネームスペースの追加・setup-clientのインストール
kubectl create ns openstack
kubectl create ns nfs
kubectl create ns ceph
cd ~/osh/openstack-helm
sudo apt-get install build-essential
sudo apt-get install python3.9-dev
./tools/deployment/developer/common/020-setup-client.sh
1 chart(s) linted, 0 chart(s) failed
と出力されていたらopenstack --versionと打って確認してみる
openstack 5.8.1と出たら成功
様々なバックエンドの構築
ingress、nfs provisioner、mariadb、rabbitmq、memcachedを構築します
nfs provisionerが構築に失敗しているとmariadbの構築でフリーズしますのでnfsの設定などを確認してください。
./tools/deployment/component/common/ingress.sh
./tools/deployment/developer/nfs/040-nfs-provisioner.sh
./tools/deployment/developer/nfs/050-mariadb.sh
./tools/deployment/developer/nfs/060-rabbitmq.sh
./tools/deployment/developer/nfs/070-memcached.sh
kubectl get pods -A -o wide
#すべてのPodが動作しているか確認してください。
Openstack Keystoneの構築
バックエンドなどの準備ができたのでOpenstackの最重要コンポーネントのKeystoneを入れていきます。
./tools/deployment/developer/nfs/080-keystone.sh
問題なく完了したら環境変数を入れたkeystonercファイルを作成します。
vi ~/keystonerc
export OS_PROJECT_DOMAIN_NAME=default
export OS_USER_DOMAIN_NAME=default
export OS_PROJECT_NAME=admin
export OS_USERNAME=admin
export OS_PASSWORD=password
export OS_AUTH_URL=http://keystone.openstack.svc.cluster.local/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
export PS1='\u@\h \W(keystone)\$ '
export OPENSTACK_RELEASE=yoga
export CONTAINER_DISTRO_NAME=ubuntu
export CONTAINER_DISTRO_VERSION=focal
sourceコマンドで環境変数を使えるようにします。
chmod 600 ~/keystonerc
source ~/keystonerc
echo "source ~/keystonerc " >> ~/.bashrc
openstack project listを入力して結果が帰ってきたらkeystoneの構築成功です。
openstack project list
root@openstack-helm ~(keystone)# openstack project list
+----------------------------------+-----------------+
| ID | Name |
+----------------------------------+-----------------+
| d4u8761a76kl3d649v1665521c4f1572 | admin |
+----------------------------------+-----------------+
Openstack Heatの構築
cd ~/osh/openstack-helm
./tools/deployment/developer/nfs/090-heat.sh
今回はVMが作れたら良いと思っているのでHeatは使わないと思いますが入れておきます。
完了したら以下で構築されているか確認しておきます。
heat --version
Openstack Horizonの構築
cd ~/osh/openstack-helm
./tools/deployment/developer/nfs/100-horizon.sh
問題なく構築すれば次に進みます(Horizonの動作確認はまた後でやります)
Openstack Glanceの構築
./tools/deployment/developer/nfs/120-glance.sh
openstack image listでCirrosのイメージがデプロイされていたら成功です。
Openstack-helmの設定変更
githubから持ってきたOpenstack-helmはOVS設定が標準となっているため、Linuxbridgeの設定に変更するなど設定が必要です。
Libvirt
openstack-helm-infra/libvirt/values.yamlを編集してovsからlinuxbridgeに変更しています。
#openstack-helm-infra/libvirt/values.yaml
###42行目:backendをlinuxbridgeに変更
network:
# provide what type of network wiring will be used
# possible options: openvswitch, linuxbridge, sriov
backend:
- linuxbridge
Neutron
neutronはLinuxbridgeを使うにあたって変更箇所が多いですが、全て必要な設定かというかそうとは限りません、、試行錯誤しているので必要ない設定もあると思います。ご了承ください
#openstack-helm/neutron/values.yaml
###106行目:backendをlinuxbridgeに
network:
# provide what type of network wiring will be used
backend:
- linuxbridge
# NOTE(Portdirect): Share network namespaces with the host,
# allowing agents to be restarted without packet loss and simpler
# debugging. This feature requires mount propagation support.
###228行目: pod: nullから以下のように変更
dhcp:
pod:
- requireSameNode: true
labels:
application: neutron
component: neutron-lb-agent
###261,285行目のl3とmetadataも同じようにpod: nullから変更
###1803行目:たぶん22.04でlinuxbridgeを動かそうとした名残と思われるが一応追加
neutron:
experimental:
linuxbridge: True
###1830行目: interface_driverをlinuxbridgeに変更
interface_driver: linuxbridge
###1945行目: mechanism_driverを以下のように変更
mechanism_drivers: linuxbridge, l2population
###1966行目:VMと物理NICの紐づけの部分をコメントアウト(例:eth3)
linuxbridge_agent:
physical_interface_mappings: "external:eth3"
# Or we can set the mapping between the network and bridge:
###1968行目:bridge_mappingsは使用しないのでコメントアウト
# bridge_mappings: "external:br-ex"
# The two above options are exclusive, do not use both of them at once
###1993行目:使用しない設定だがSR-IOVの物理NICとの紐づけを追加
sriov_nic:
physical_device_mappings: physnet2:eth3
###1997行目:interface_driverをlinuxbridgeに変更
dhcp_agent:
DEFAULT:
# (NOTE)portdirect: if unset this is populated dyanmicly from the value in
# 'network.backend' to sane defaults.
interface_driver: null
interface_driver: linuxbridge
###2025行目:interface_driverをlinuxbridgeに変更
DEFAULT:
# (NOTE)portdirect: if unset this is populated dyanmicly from the value in
# 'network.backend' to sane defaults.
interface_driver: null
interface_driver: linuxbridge
###2528行目: ovs_agentは使わないのでfalse
daemonset_ovs_agent: false
daemonsetでエラーを吐いていたので以下設定しました
#openstack-helm/neutron/templates/daemonset-lb-agent.yaml volumeMounts: - name: pod-tmp mountPath: /tmp ###152行目:pod-ebtablesを追加 - name: pod-ebtables mountPath: /var/lib/ebtables - name: pod-var-neutron mountPath: {{ .Values.conf.neutron.DEFAULT.state_path }} ###208行目:pod-ebtablesを追加 - name: pod-ebtables emptyDir: {} - name: pod-var-neutron emptyDir: {} - name: pod-shared
Nova
#openstack-helm/nova/values.yaml
###208行目:backendをlinuxbridgeに変更
backend:
- linuxbridge
構築スクリプト
placement,nova,neutronを動かすcompute-kit.shのneutronの部分を以下のように変更します
neutronのvalue.yamlに書けばよいのですが、修正が簡単なのと、デフォルトで入っていたのでここで変更しています。
#openstack-helm/tools/deployment/component/compute-kit/compute-kit.sh
###69行目:以下のように変更
#NOTE: Deploy neutron
tee /tmp/neutron.yaml << EOF
network:
backend:
- linuxbridge
conf:
neutron:
DEFAULT:
l3_ha: False
plugins:
ml2_conf:
ml2:
extension_drivers: port_security
mechanism_drivers: linuxbridge
type_drivers: flat,vlan,vxlan,local
ml2_type_flat:
flat_networks: "physnet1"
linuxbridge_agent:
linux_bridge:
physical_interface_mappings: "physnet1:eth2"
EOF
Libvirtの構築
./tools/deployment/developer/nfs/150-libvirt.sh
Libvirtをインストールします。
しかしインストールは止まると思います。Libvirtのインストールにneutron-lb-agentが必要だからです。止まっても次に進みます。
placement,nova,neutronの構築
./tools/deployment/developer/nfs/160-computekit.sh
placementとnova,neutronの構築ができます。
novaもlibvirtが動いていないので止まると思います。neutronの構築が次に進むので待っておきます。
しかしneutronの構築が終わってもnovaやlibvirtが動いていないときは
kubectl delete pod libvirt....
やnova-cellやnova-computeなどのpodを一度deleteしてみて再度構築されるのを待ちます。
すべてのpodが起きてきたらOpenstack-helmの基本的な構築は完了となります。
VM作成検証
VM用ネットワーク・サブネット作成
projectID=$(openstack project list | grep service | awk '{print $2}')
openstack network create --project $projectID \
--share --provider-network-type flat --provider-physical-network public oshvmnetwork
#お好みのサブネット・割り当てIPアドレスプールをここで設定
openstack subnet create oshvmsubnet --network oshvmnetwork \
--project $projectID --subnet-range 192.168.10.0/24 \
--allocation-pool start=192.168.10.10,end=192.168.10.249 \
--gateway 192.168.10.1 --dns-nameserver 8.8.8.8
VM作成
#お好みのイメージ・フレーバーのIDをコピーしておきます
openstack image list
openstack flavor list
#セキュリティグループを作成しておきます
openstack security group create secgroup01
#VM作成
netID=$(openstack network list | grep oshvmnetwork | awk '{ print $2 }')
#さきほどのイメージ・フレーバーIDを使います
openstack server create --flavor フレーバーID --image イメージID --security-group secgroup01 --nic net-id=$netID --key-name mykey oshtestvm
openstack server listでoshtestvmがACTIVEになっていればVM作成完了です。
ダッシュボード確認
kubectl get svc -n openstack
#horizon-intのTCPポート80:31000の後ろの部分がつながるポート
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
horizon ClusterIP 10.100.186.249 <none> 80/TCP,443/TCP 35m
horizon-int NodePort 10.101.83.136 <none> 80:31000/TCP 35m
この場合、ホストのIPアドレス:31000をブラウザで入力するとhorizonに接続できます。
以上で完成です
とりあえずとはなりますが、Openstack-helmを使ったOpenstack on Kubernetes環境が出来ました。
かなり難しかったのですが、いい勉強になりました。またCephとかも使ってみて構築してみたいなと思います。