From 1a885ddd1fdf7aa4dbec6a1ebe98152c032184c4 Mon Sep 17 00:00:00 2001 From: Vladimir Kozhukalov <kozhukalov@gmail.com> Date: Mon, 25 Sep 2023 21:34:52 -0500 Subject: [PATCH] Update deployment documentation Recently we updated our test jobs so that all of them use the `deploy-env` Ansible role which utilizes the Kubeadm to deploy the test Kubernetes cluster. The role works for both multi-node and single-node environments. Although the deployment of Kubernetes itself is out of scope of Openstack-Helm, we recommen using this role to deploy test and development Kubernetes clusters. So at the moment there is no need to provide different sets of tools single-node and multi-node test envs. Now this is a matter of the Ansible inventory file. Also the deployment procedure of OpenStack on top of Kubernetes using Helm is the same for multi-node and single-node clusters because it only relies on the Kubernetes API. We will be improving the `deploy-env` role even futher and we will be cleaning up the deployment scripts and the documentation so to provide a clear experience for the Openstack-Helm users. Change-Id: I70236c4a2b870b52d2b01f65b1ef9b9518646964 --- CONTRIBUTING.rst | 26 -- README.rst | 114 ++++-- doc/source/conf.py | 2 +- doc/source/contributor/contributing.rst | 108 ------ doc/source/gates.rst | 145 -------- doc/source/index.rst | 16 +- doc/source/install/before_deployment.rst | 34 ++ doc/source/install/common-requirements.rst | 70 ---- doc/source/install/deploy_ceph.rst | 52 +++ .../install/deploy_ingress_controller.rst | 52 +++ doc/source/install/deploy_kubernetes.rst | 143 ++++++++ doc/source/install/deploy_openstack.rst | 116 ++++++ .../install/deploy_openstack_backend.rst | 54 +++ .../install/developer/cleaning-deployment.rst | 92 ----- .../install/developer/deploy-ovs-dpdk.rst | 185 ---------- .../install/developer/deploy-with-ceph.rst | 222 ------------ .../install/developer/deploy-with-nfs.rst | 163 --------- .../developer/deploy-with-tungsten-fabric.rst | 147 -------- .../install/developer/exercise-the-cloud.rst | 90 ----- doc/source/install/developer/index.rst | 16 - .../developer/kubernetes-and-common-setup.rst | 135 ------- .../requirements-and-host-config.rst | 100 ------ doc/source/install/ext-dns-fqdn.rst | 244 ------------- doc/source/install/index.rst | 17 +- doc/source/install/kubernetes-gate.rst | 143 -------- doc/source/install/multinode.rst | 331 ----------------- ...deploy-tap-as-a-service-neutron-plugin.rst | 339 ------------------ .../plugins/figures/taas-architecture.png | Bin 98682 -> 0 bytes doc/source/install/plugins/index.rst | 9 - doc/source/install/prepare_kubernetes.rst | 28 ++ doc/source/install/setup_openstack_client.rst | 35 ++ 31 files changed, 611 insertions(+), 2617 deletions(-) delete mode 100644 CONTRIBUTING.rst delete mode 100644 doc/source/contributor/contributing.rst delete mode 100644 doc/source/gates.rst create mode 100644 doc/source/install/before_deployment.rst delete mode 100644 doc/source/install/common-requirements.rst create mode 100644 doc/source/install/deploy_ceph.rst create mode 100644 doc/source/install/deploy_ingress_controller.rst create mode 100644 doc/source/install/deploy_kubernetes.rst create mode 100644 doc/source/install/deploy_openstack.rst create mode 100644 doc/source/install/deploy_openstack_backend.rst delete mode 100644 doc/source/install/developer/cleaning-deployment.rst delete mode 100644 doc/source/install/developer/deploy-ovs-dpdk.rst delete mode 100644 doc/source/install/developer/deploy-with-ceph.rst delete mode 100644 doc/source/install/developer/deploy-with-nfs.rst delete mode 100644 doc/source/install/developer/deploy-with-tungsten-fabric.rst delete mode 100644 doc/source/install/developer/exercise-the-cloud.rst delete mode 100644 doc/source/install/developer/index.rst delete mode 100644 doc/source/install/developer/kubernetes-and-common-setup.rst delete mode 100644 doc/source/install/developer/requirements-and-host-config.rst delete mode 100644 doc/source/install/ext-dns-fqdn.rst delete mode 100644 doc/source/install/kubernetes-gate.rst delete mode 100644 doc/source/install/multinode.rst delete mode 100644 doc/source/install/plugins/deploy-tap-as-a-service-neutron-plugin.rst delete mode 100644 doc/source/install/plugins/figures/taas-architecture.png delete mode 100644 doc/source/install/plugins/index.rst create mode 100644 doc/source/install/prepare_kubernetes.rst create mode 100644 doc/source/install/setup_openstack_client.rst diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst deleted file mode 100644 index 65ff7812a9..0000000000 --- a/CONTRIBUTING.rst +++ /dev/null @@ -1,26 +0,0 @@ -The source repository for this project can be found at: - - https://opendev.org/openstack/openstack-helm - -Pull requests submitted through GitHub are not monitored. - -To start contributing to OpenStack, follow the steps in the contribution guide -to set up and use Gerrit: - - https://docs.openstack.org/contributors/code-and-documentation/quick-start.html - -Bugs should be filed on StoryBoard: - - https://storyboard.openstack.org/#!/project/openstack/openstack-helm - -For more specific information about contributing to this repository, see the -openstack-helm contributor guide: - - https://docs.openstack.org/openstack-helm/latest/contributor/contributing.html - -Chart tarballs are published and can be found at the respective sub folder under - - https://tarballs.opendev.org/openstack/ - -Versioning and release notes for each chart update are now required in order to -better support the evolving nature of the OpenStack platform. diff --git a/README.rst b/README.rst index 331c3d3404..90ea4377ab 100644 --- a/README.rst +++ b/README.rst @@ -9,55 +9,99 @@ The goal of OpenStack-Helm is to provide a collection of Helm charts that simply, resiliently, and flexibly deploy OpenStack and related services on Kubernetes. +Versions supported +------------------ + +The table below shows the combinations of the Openstack/Platform/Kubernetes versions +that are tested and proved to work. + +.. list-table:: + :widths: 30 30 30 30 + :header-rows: 1 + + * - Openstack version + - Host OS + - Image OS + - Kubernetes version + * - Victoria + - Ubuntu Focal + - Ubuntu Focal + - >=1.24,<=1.26 + * - Wallaby + - Ubuntu Focal + - Ubuntu Focal + - >=1.24,<=1.26 + * - Xena + - Ubuntu Focal + - Ubuntu Focal + - >=1.24,<=1.26 + * - Yoga + - Ubuntu Focal + - Ubuntu Focal + - >=1.24,<=1.26 + * - Zed + - Ubuntu Focal + - Ubuntu Focal + - >=1.24,<=1.26 + * - Zed + - Ubuntu Jammy + - Ubuntu Jammy + - >=1.24,<=1.26 + * - 2023.1 (Antelope) + - Ubuntu Focal + - Ubuntu Focal + - >=1.24,<=1.26 + * - 2023.1 (Antelope) + - Ubuntu Jammy + - Ubuntu Jammy + - >=1.24,<=1.26 + * - 2023.2 (Bobcat) + - Ubuntu Jammy + - Ubuntu Jammy + - >=1.24,<=1.26 + Communication ------------- * Join us on `IRC <irc://chat.oftc.net/openstack-helm>`_: - #openstack-helm on oftc -* Community `IRC Meetings - <http://eavesdrop.openstack.org/#OpenStack-Helm_Team_Meeting>`_: - [Every Tuesday @ 1500 UTC], #openstack-helm in IRC (OFTC) -* Meeting Agenda Items: `Agenda - <https://etherpad.openstack.org/p/openstack-helm-meeting-agenda>`_ + ``#openstack-helm`` on oftc * Join us on `Slack <https://kubernetes.slack.com/messages/C3WERB7DE/>`_ - - #openstack-helm + (this is preferable way of communication): ``#openstack-helm`` +* Join us on `Openstack-discuss <https://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-discuss>`_ + mailing list (use subject prefix ``[openstack-helm]``) + +The list of Openstack-Helm core team members is available here +`openstack-helm-core <https://review.opendev.org/#/admin/groups/1749,members>`_. Storyboard ---------- -Bugs and enhancements are tracked via OpenStack-Helm's +You found an issue and want to make sure we are aware of it? You can do so on our `Storyboard <https://storyboard.openstack.org/#!/project_group/64>`_. -Installation and Development ----------------------------- +Bugs should be filed as stories in Storyboard, not GitHub. -Please review our -`documentation <https://docs.openstack.org/openstack-helm/latest/>`_. -For quick installation, evaluation, and convenience, we have a minikube -based all-in-one solution that runs in a Docker container. The set up -can be found -`here <https://docs.openstack.org/openstack-helm/latest/install/developer/index.html>`_. +Please be as much specific as possible while describing an issue. Usually having +more context in the bug description means less efforts for a developer to +reproduce the bug and understand how to fix it. + +Also before filing a bug to the Openstack-Helm `Storyboard <https://storyboard.openstack.org/#!/project_group/64>`_ +please try to identify if the issue is indeed related to the deployment +process and not to the deployable software. + +Other links +----------- + +Our documentation is available `here <https://docs.openstack.org/openstack-helm/latest/>`_. This project is under active development. We encourage anyone interested in -OpenStack-Helm to review our -`Installation <https://docs.openstack.org/openstack-helm/latest/install/index.html>`_ -documentation. Feel free to ask questions or check out our current -`Storyboard backlog <https://storyboard.openstack.org/#!/project_group/64>`_. +OpenStack-Helm to review the `code changes <https://review.opendev.org/q/(project:openstack/openstack-helm+OR+project:openstack/openstack-helm-infra+OR+project:openstack/openstack-helm-images+OR+project:openstack/loci)+AND+-is:abandoned>`_ -To evaluate a multinode installation, follow the -`Bare Metal <https://docs.openstack.org/openstack-helm/latest/install/multinode.html>`_ -install guide. +Our repositories: -Repository ----------- +* OpenStack charts `openstack-helm <https://opendev.org/openstack/openstack-helm.git>`_ +* Infra charts `openstack-helm-infra <https://opendev.org/openstack/openstack-helm-infra.git>`_ +* Building images `openstack-helm-images <https://opendev.org/openstack/openstack-helm-images.git>`_ +* Building Openstack images framework `loci <https://opendev.org/openstack/loci.git>`_ -Developers wishing to work on the OpenStack-Helm project should always base -their work on the latest code, available from the OpenStack-Helm git repository. - -`OpenStack-Helm git repository <https://opendev.org/openstack/openstack-helm/>`_ - -Contributing ------------- - -We welcome contributions. Check out `this <CONTRIBUTING.rst>`_ document if -you would like to get involved. +We welcome contributions in any form: code review, code changes, usage feedback, updating documentation. diff --git a/doc/source/conf.py b/doc/source/conf.py index 9c973ace2c..f337d608a3 100755 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -42,7 +42,7 @@ master_doc = 'index' # General information about the project. project = 'openstack-helm' -copyright = '2016-2022, OpenStack Foundation' +copyright = '2016-2023, OpenStack Foundation' # If true, '()' will be appended to :func: etc. cross-reference text. add_function_parentheses = True diff --git a/doc/source/contributor/contributing.rst b/doc/source/contributor/contributing.rst deleted file mode 100644 index cb08bc95b8..0000000000 --- a/doc/source/contributor/contributing.rst +++ /dev/null @@ -1,108 +0,0 @@ -============================ -So You Want to Contribute... -============================ - -For general information on contributing to OpenStack, please check out the -`contributor guide <https://docs.openstack.org/contributors/>`_ to get started. -It covers all the basics that are common to all OpenStack projects: the accounts -you need, the basics of interacting with our Gerrit review system, how we -communicate as a community, etc. - -Additional information could be found in -`OpenDev Developer's Guide -<https://docs.opendev.org/opendev/infra-manual/latest/developers.html>`_. - -Below will cover the more project specific information you need to get started -with OpenStack-Helm. - -Communication -~~~~~~~~~~~~~ -.. This would be a good place to put the channel you chat in as a project; when/ - where your meeting is, the tags you prepend to your ML threads, etc. - -* Join us on `IRC <irc://chat.oftc.net/openstack-helm>`_: - #openstack-helm on oftc -* Join us on `Slack <https://kubernetes.slack.com/messages/C3WERB7DE/>`_ - (this is preferable way of communication): #openstack-helm - -Contacting the Core Team -~~~~~~~~~~~~~~~~~~~~~~~~ -.. This section should list the core team, their irc nicks, emails, timezones - etc. If all this info is maintained elsewhere (i.e. a wiki), you can link to - that instead of enumerating everyone here. - -Project's Core Team could be contacted via IRC or Slack. List of current core reviewers -could be found here `openstack-helm-core <https://review.opendev.org/#/admin/groups/1749,members>`_. - -New Feature Planning -~~~~~~~~~~~~~~~~~~~~ -.. This section is for talking about the process to get a new feature in. Some - projects use blueprints, some want specs, some want both! Some projects - stick to a strict schedule when selecting what new features will be reviewed - for a release. - -New features are planned and implemented trough the process described in -`Project Specifications <../specs/index.html>`_ section of this document. - -Task Tracking -~~~~~~~~~~~~~ -.. This section is about where you track tasks- launchpad? storyboard? is there - more than one launchpad project? what's the name of the project group in - storyboard? - -We track our tasks on our StoryBoard_. - -If you're looking for some smaller, easier work item to pick up and get started -on, search for the 'low-hanging-fruit' tag. - -.. NOTE: If your tag is not 'low-hanging-fruit' please change the text above. - -Other OpenStack-Helm component's tasks could be found on the `group Storyboard`_. - -Reporting a Bug -~~~~~~~~~~~~~~~ -.. Pretty self explanatory section, link directly to where people should report - bugs for your project. - -You found an issue and want to make sure we are aware of it? You can do so on our -Storyboard_. - -If an issue is on one of other OpenStack-Helm components, report it to the -appropriate `group Storyboard`_. - -Bugs should be filed as stories in Storyboard, not GitHub. - -Please be as much specific as possible while describing an issue. Usually having -more context in the bug description means less efforts for a developer to -reproduce the bug and understand how to fix it. - -Also before filing a bug to the Openstack-Helm `_Storyboard` please try to identify -if the issue is indeed related to the deployment process and not to the deployable -software. - -Getting Your Patch Merged -~~~~~~~~~~~~~~~~~~~~~~~~~ -.. This section should have info about what it takes to get something merged. Do - you require one or two +2's before +W? Do some of your repos require unit - test changes with all patches? etc. - -We require two Code-Review +2's from reviewers, before getting your patch merged -with giving Workforce +1. Trivial patches (e.g. typos) could be merged with one -Code-Review +2. - -Changes affecting code base often require CI tests and documentation to be added -in the same patch set. - -Pull requests submitted through GitHub will be ignored. - -Project Team Lead Duties -~~~~~~~~~~~~~~~~~~~~~~~~ -.. this section is where you can put PTL specific duties not already listed in - the common PTL guide (linked below), or if you already have them written - up elsewhere you can link to that doc here. - -All common PTL duties are enumerated in the `PTL guide -<https://docs.openstack.org/project-team-guide/ptl.html>`_. - -.. _Storyboard: https://storyboard.openstack.org/#!/project/openstack/openstack-helm -.. _group Storyboard: https://storyboard.openstack.org/#!/project_group/64 diff --git a/doc/source/gates.rst b/doc/source/gates.rst deleted file mode 100644 index 70e5146ea2..0000000000 --- a/doc/source/gates.rst +++ /dev/null @@ -1,145 +0,0 @@ -==================== -OpenStack-Helm Gates -==================== - -To facilitate ease of testing and debugging, information regarding gates and -their functionality can be found here. - -OpenStack-Helm's single node and multinode gates leverage the kubeadm-aio -environment created and maintained for use as a development environment. All -information regarding the kubeadm-aio environment can be found here_. - -.. _here: https://docs.openstack.org/openstack-helm/latest/install/developer/index.html - -Gate Checks ------------ - -OpenStack-Helm currently checks the following scenarios: - -- Testing any documentation changes and impacts. -- Running Make on each chart, which lints and packages the charts. This gate - does not stand up a Kubernetes cluster. -- Provisioning a single node cluster and deploying the OpenStack services. This - check is provided for: Ubuntu-1604, CentOS-7, and Fedora-25. -- Provisioning a multi-node Ubuntu-1604 cluster and deploying the OpenStack - services. This check is provided for both a two node cluster and a three - node cluster. - - -Gate Functions --------------- - -To provide reusable components for gate functionality, functions have been -provided in the gates/funcs directory. These functions include: - -- Functions for common host preparation operations, found in common.sh -- Functions for Helm specific operations, found in helm.sh. These functions - include: installing Helm, serving a Helm repository locally, linting and - building all Helm charts, running Helm tests on a release, installing the - helm template plugin, and running the helm template plugin against a chart. -- Functions for Kubernetes specific operations, found in kube.sh. These - functions include: waiting for pods in a specific namespace to register as - ready, waiting for all nodes to register as ready, install the requirements - for the kubeadm-aio container used in the gates, building the kubeadm-aio - container, launching the kubeadm-aio container, and replacing the - kube-controller-manager with a specific image necessary for ceph functionality. -- Functions for network specific operations, found in network.sh. These - functions include: creating a backup of the host's resolv.conf file before - deploying the kubeadm environments, restoring the original resolv.conf - settings, creating a backup of the host's /etc/hosts file before adding the - hosts interface and address, and restoring the original /etc/hosts file. -- Functions for OpenStack specific operations, found in openstack.sh. These - functions include: waiting for a successful ping, and waiting for a booted - virtual machine's status to return as ACTIVE. - -Any additional functions required for testing new charts or improving the gate -workflow should be placed in the appropriate location. - - -Gate Output ------------ - -To provide meaningful output from the gates, all information pertaining to the -components of the cluster and workflow are output to the logs directory inside -each gate. The contents of the log directory are as follows: - -- The dry-runs directory contains the rendered output of Helm dry-run installs - on each of the OpenStack service charts. This gives visibility into the - manifests created by the templates with the supplied values. When the dry-run - gate fails, the reason should be apparent in the dry-runs output. The logs - found here are helpful in identifying issues resulting from using helm-toolkit - functions incorrectly or other rendering issues with gotpl. -- The K8s directory contains the logs and output of the Kubernetes objects. It - includes: pods, nodes, secrets, services, namespaces, configmaps, deployments, - daemonsets, and statefulsets. Descriptions for the state of all resources - during execution are found here, and this information can prove valuable when - debugging issues raised during a check. When a single node or multi-node - check fails, this is the first place to look. The logs found here are helpful - when the templates render correctly, but the services are not functioning - correctly, whether due to service configuration issues or issues with the - pods themselves. -- The nodes directory contains information about the node the gate tests are - running on in openstack-infra. This includes: the network interfaces, the - contents of iptables, the host's resolv.conf, and the kernel IP routing table. - These logs can be helpful when trying to identify issues with host networking - or other issues at the node level. - - -Adding Services ---------------- - -As charts for additional services are added to OpenStack-Helm, they should be -included in the gates. Adding new services to the gates allows a chart -developer and the review team to identify any potential issues associated with -a new service. All services are currently launched in the gate via -a series of launch scripts of the format ``NNN-service-name.sh`` where ``NNN`` -dictates the order these scripts are launched. The script should contain -an installation command like: - -:: - - helm install --namespace=openstack ${WORK_DIR}/mistral --name=mistral - -Some services in the gate require specific overrides to the default values in -the chart's values.yaml file. If a service requires multiple overrides to -function in the gate, the service should include a separate values.yaml file -placed in the tools/overrides/mvp directory. The <service>.yaml MVP files -provide a configuration file to use for overriding default configuration values -in the chart's values.yaml as an alternative to overriding individual values -during installation. A chart that requires a MVP overrides file -requires the following format: - -:: - - helm install --namespace=openstack ${WORK_DIR}/cinder --name=cinder \ - --values=${WORK_DIR}/tools/overrides/mvp/cinder.yaml - - -Adding Tests ------------- - -As new charts are developed and the services are added to the gate, an -associated Helm test should be introduced to the gates. The appropriate place -for executing these tests is in the respective service's launch script, and -must be placed after the entry for installing the service and any associated -overrides. Any tests that use the Rally testing framework should leverage the -helm_test_deployment function in the aforementioned funcs/helm.sh file. For -example, a Helm test for Mistral might look like: - -:: - - helm_test_deployment mistral 600 - -This results in the gate running the following: - -:: - - helm test --timeout 600 mistral - mkdir -p logs/rally - kubectl logs -n openstack mistral-rally-test > logs/rally/mistral - kubectl delete -n openstack pod mistral-rally-test - -Any tests that do not use the Rally testing framework would need to be handled -in the appropriate manner in launch script. This would ideally result in new -functions that could be reused, or expansion of the gate scripts to include -scenarios beyond basic service launches. diff --git a/doc/source/index.rst b/doc/source/index.rst index 4d41927f22..3d819a169e 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -4,16 +4,14 @@ Welcome to OpenStack-Helm's documentation! Contents: .. toctree:: - :maxdepth: 2 + :maxdepth: 2 - contributor/contributing - devref/index - gates - install/index - readme - specs/index - testing/index - troubleshooting/index + readme + install/index + devref/index + testing/index + troubleshooting/index + specs/index Indices and Tables ================== diff --git a/doc/source/install/before_deployment.rst b/doc/source/install/before_deployment.rst new file mode 100644 index 0000000000..eb8f8df06e --- /dev/null +++ b/doc/source/install/before_deployment.rst @@ -0,0 +1,34 @@ +Before deployment +================= + +Before proceeding with the steps outlined in the following +sections and executing the actions detailed therein, it is +imperative that you clone the essential Git repositories +containing all the required Helm charts, deployment scripts, +and Ansible roles. This preliminary step will ensure that +you have access to the necessary assets for a seamless +deployment process. + +.. code-block:: bash + + mkdir ~/osh + cd ~/osh + git clone https://opendev.org/openstack/openstack-helm.git + git clone https://opendev.org/openstack/openstack-helm-infra.git + + +All further steps assume these two repositories are cloned into the +`~/osh` directory. + +Also before deploying the OpenStack cluster you have to specify the +OpenStack and the operating system version that you would like to use +for deployment. For doing this export the following environment variables + +.. code-block:: bash + + export OPENSTACK_RELEASE=2023.2 + export CONTAINER_DISTRO_NAME=ubuntu + export CONTAINER_DISTRO_VERSION=jammy + +.. note:: + The list of supported versions can be found :doc:`here </readme>`. diff --git a/doc/source/install/common-requirements.rst b/doc/source/install/common-requirements.rst deleted file mode 100644 index 0bb175d2ac..0000000000 --- a/doc/source/install/common-requirements.rst +++ /dev/null @@ -1,70 +0,0 @@ -============================== -Common Deployment Requirements -============================== - -Passwordless Sudo -================= - -Throughout this guide the assumption is that the user is: -``ubuntu``. Because this user has to execute root level commands -remotely to other nodes, it is advised to add the following lines -to ``/etc/sudoers`` for each node: - -.. code-block:: shell - - root ALL=(ALL) NOPASSWD: ALL - ubuntu ALL=(ALL) NOPASSWD: ALL - -Latest Version Installs -======================= - -On the host or master node, install the latest versions of Git, CA Certs & Make if necessary - -.. literalinclude:: ../../../tools/deployment/developer/common/000-install-packages.sh - :language: shell - :lines: 1,17- - -Proxy Configuration -=================== - -.. note:: This guide assumes that users wishing to deploy behind a proxy have already - defined the conventional proxy environment variables ``http_proxy``, - ``https_proxy``, and ``no_proxy``. - -In order to deploy OpenStack-Helm behind corporate proxy servers, add the -following entries to ``openstack-helm-infra/tools/gate/devel/local-vars.yaml``. - -.. code-block:: yaml - - proxy: - http: http://username:password@host:port - https: https://username:password@host:port - noproxy: 127.0.0.1,localhost,172.17.0.1,.svc.cluster.local - -.. note:: The ``.svc.cluster.local`` address is required to allow the OpenStack - client to communicate without being routed through proxy servers. The IP - address ``172.17.0.1`` is the advertised IP address for the Kubernetes API - server. Replace the addresses if your configuration does not match the - one defined above. - -Add the address of the Kubernetes API, ``172.17.0.1``, and -``.svc.cluster.local`` to your ``no_proxy`` and ``NO_PROXY`` environment -variables. - -.. code-block:: bash - - export no_proxy=${no_proxy},172.17.0.1,.svc.cluster.local - export NO_PROXY=${NO_PROXY},172.17.0.1,.svc.cluster.local - -By default, this installation will use Google DNS Server IPs (8.8.8.8, 8.8.4.4) -and will update resolv.conf as a result. If those IPs are blocked by the proxy, -this will overwrite the original DNS entries and result in the inability to -connect to anything on the network behind the proxy. These DNS nameserver entries -can be changed by updating the ``external_dns_nameservers`` entry in this file: - -.. code-block:: bash - - openstack-helm-infra/tools/images/kubeadm-aio/assets/opt/playbooks/vars.yaml - -It is recommended to add your own existing DNS nameserver entries to avoid -losing connection. diff --git a/doc/source/install/deploy_ceph.rst b/doc/source/install/deploy_ceph.rst new file mode 100644 index 0000000000..23f2a424bb --- /dev/null +++ b/doc/source/install/deploy_ceph.rst @@ -0,0 +1,52 @@ +Deploy Ceph +=========== + +Ceph is a highly scalable and fault-tolerant distributed storage +system designed to store vast amounts of data across a cluster of +commodity hardware. It offers object storage, block storage, and +file storage capabilities, making it a versatile solution for +various storage needs. Ceph's architecture is based on a distributed +object store, where data is divided into objects, each with its +unique identifier, and distributed across multiple storage nodes. +It uses a CRUSH algorithm to ensure data resilience and efficient +data placement, even as the cluster scales. Ceph is widely used +in cloud computing environments and provides a cost-effective and +flexible storage solution for organizations managing large volumes of data. + +Kubernetes introduced the CSI standard to allow storage providers +like Ceph to implement their drivers as plugins. Kubernetes can +use the CSI driver for Ceph to provision and manage volumes +directly. By means of CSI stateful applications deployed on top +of Kubernetes can use Ceph to store their data. + +At the same time, Ceph provides the RBD API, which applications +can utilize to create and mount block devices distributed across +the Ceph cluster. The OpenStack Cinder service utilizes this Ceph +capability to offer persistent block devices to virtual machines +managed by the OpenStack Nova. + +The recommended way to deploy Ceph on top of Kubernetes is by means +of `Rook`_ operator. Rook provides Helm charts to deploy the operator +itself which extends the Kubernetes API adding CRDs that enable +managing Ceph clusters via Kuberntes custom objects. For details please +refer to the `Rook`_ documentation. + +To deploy the Rook Ceph operator and a Ceph cluster you can use the script +`ceph.sh`_. Then to generate the client secrets to interface with the Ceph +RBD API use this script `ceph_secrets.sh` + +.. code-block:: bash + + cd ~/osh/openstack-helm-infra + ./tools/deployment/openstack-support-rook/020-ceph.sh + ./tools/deployment/openstack-support-rook/025-ceph-ns-activate.sh + +.. note:: + Please keep in mind that these are the deployment scripts that we + use for testing. For example we place Ceph OSD data object on loop devices + which are slow and are not recommended to use in production. + + +.. _Rook: https://rook.io/ +.. _ceph.sh: https://opendev.org/openstack/openstack-helm-infra/src/branch/master/tools/deployment/openstack-support-rook/020-ceph.sh +.. _ceph-ns-activate.sh: https://opendev.org/openstack/openstack-helm-infra/src/branch/master/tools/deployment/openstack-support-rook/025-ceph-ns-activate.sh diff --git a/doc/source/install/deploy_ingress_controller.rst b/doc/source/install/deploy_ingress_controller.rst new file mode 100644 index 0000000000..069382384d --- /dev/null +++ b/doc/source/install/deploy_ingress_controller.rst @@ -0,0 +1,52 @@ +Deploy ingress controller +========================= + +Deploying an ingress controller when deploying OpenStack on Kubernetes +is essential to ensure proper external access and SSL termination +for your OpenStack services. + +In the OpenStack-Helm project, we utilize multiple ingress controllers +to optimize traffic routing. Specifically, we deploy three independent +instances of the Nginx ingress controller for distinct purposes: + +External Traffic Routing +~~~~~~~~~~~~~~~~~~~~~~~~ + +* ``Namespace``: kube-system +* ``Functionality``: This instance monitors ingress objects across all + namespaces, primarily focusing on routing external traffic into the + OpenStack environment. + +Internal Traffic Routing within OpenStack +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* ``Namespace``: openstack +* ``Functionality``: Designed to handle traffic exclusively within the + OpenStack namespace, this instance plays a crucial role in SSL + termination for enhanced security among OpenStack services. + +Traffic Routing to Ceph Rados Gateway Service +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* ``Namespace``: ceph +* ``Functionality``: Dedicated to routing traffic specifically to the + Ceph Rados Gateway service, ensuring efficient communication with + Ceph storage resources. + +By deploying these three distinct ingress controller instances in their +respective namespaces, we optimize traffic management and security within +the OpenStack-Helm environment. + +To deploy these three ingress controller instances use the script `ingress.sh`_ + +.. code-block:: bash + + cd ~/osh/openstack-helm + ./tools/deployment/component/common/ingress.sh + +.. note:: + These script uses Helm chart from the `openstack-helm-infra`_ repository. We assume + this repo is cloned to the `~/osh` directory. See this :doc:`section </install/before_deployment>`. + +.. _ingress.sh: https://opendev.org/openstack/openstack-helm/src/branch/master/tools/deployment/component/common/ingress.sh +.. _openstack-helm-infra: https://opendev.org/openstack/openstack-helm-infra.git diff --git a/doc/source/install/deploy_kubernetes.rst b/doc/source/install/deploy_kubernetes.rst new file mode 100644 index 0000000000..2132d3461c --- /dev/null +++ b/doc/source/install/deploy_kubernetes.rst @@ -0,0 +1,143 @@ +Deploy Kubernetes +================= + +OpenStack-Helm provides charts that can be deployed on any Kubernetes cluster if it meets +the supported version requirements. However, deploying the Kubernetes cluster itself is beyond +the scope of OpenStack-Helm. + +You can use any Kubernetes deployment tool for this purpose. In this guide, we detail how to set up +a Kubernetes cluster using Kubeadm and Ansible. While not production-ready, this cluster is ideal +as a starting point for lab or proof-of-concept environments. + +All OpenStack projects test their code through an infrastructure managed by the CI +tool, Zuul, which executes Ansible playbooks on one or more test nodes. Therefore, we employ Ansible +roles/playbooks to install required packages, deploy Kubernetes, and then execute tests on it. + +To establish a test environment, the Ansible role deploy-env_ is employed. This role establishes +a basic single/multi-node Kubernetes cluster, ensuring the functionality of commonly used +deployment configurations. The role is compatible with Ubuntu Focal and Ubuntu Jammy distributions. + +Install Ansible +--------------- + +.. code-block:: bash + + pip install ansible + +Prepare Ansible roles +--------------------- + +Here is the Ansible `playbook`_ that is used to deploy Kubernetes. The roles used in this playbook +are defined in different repositories. So in addition to OpenStack-Helm repositories +that we assume have already been cloned to the `~/osh` directory you have to clone +yet another one + +.. code-block:: bash + + cd ~/osh + git clone https://opendev.org/zuul/zuul-jobs.git + +Now let's set the environment variable ``ANSIBLE_ROLES_PATH`` which specifies +where Ansible will lookup roles + +.. code-block:: bash + + export ANSIBLE_ROLES_PATH=~/osh/openstack-helm-infra/roles:~/osh/zuul-jobs/roles + +To avoid setting it every time when you start a new terminal instance you can define this +in the Ansible configuration file. Please see the Ansible documentation. + +Prepare Ansible inventory +------------------------- + +We assume you have three nodes, usually VMs. Those nodes must be available via +SSH using the public key authentication and a ssh user (let say `ubuntu`) +must have passwordless sudo on the nodes. + +Create the Ansible inventory file using the following command + +.. code-block:: bash + + cat > ~/osh/inventory.yaml <<EOF + all: + vars: + kubectl: + user: ubuntu + group: ubuntu + calico_version: "v3.25" + crictl_version: "v1.26.1" + helm_version: "v3.6.3" + kube_version: "1.26.3-00" + yq_version: "v4.6.0" + children: + primary: + hosts: + primary: + ansible_port: 22 + ansible_host: 10.10.10.10 + ansible_user: ubuntu + ansible_ssh_private_key_file: ~/.ssh/id_rsa + ansible_ssh_extra_args: -o StrictHostKeyChecking=no + nodes: + hosts: + node-1: + ansible_port: 22 + ansible_host: 10.10.10.11 + ansible_user: ubuntu + ansible_ssh_private_key_file: ~/.ssh/id_rsa + ansible_ssh_extra_args: -o StrictHostKeyChecking=no + node-2: + ansible_port: 22 + ansible_host: 10.10.10.12 + ansible_user: ubuntu + ansible_ssh_private_key_file: ~/.ssh/id_rsa + ansible_ssh_extra_args: -o StrictHostKeyChecking=no + EOF + +If you have just one node then it must be `primary` in the file above. + +.. note:: + If you would like to set up a Kubernetes cluster on the local host, + configure the Ansible inventory to designate the `primary` node as the local host. + For further guidance, please refer to the Ansible documentation. + +Deploy Kubernetes +----------------- + +.. code-block:: bash + + cd ~/osh + ansible-playbook -i inventory.yaml ~/osh/openstack-helm/tools/gate/playbooks/deploy-env.yaml + +The playbook only changes the state of the nodes listed in the Ansible inventory. + +It installs necessary packages, deploys and configures Containerd and Kubernetes. For +details please refer to the role `deploy-env`_ and other roles (`ensure-python`_, `ensure-pip`_, `clear-firewall`_) +used in the playbook. + +.. note:: + The role `deploy-env`_ by default will use Google DNS servers, 8.8.8.8 or 8.8.4.4 + and update `/etc/resolv.conf` on the nodes. These DNS nameserver entries can be changed by + updating the file ``~/osh/openstack-helm-infra/roles/deploy-env/files/resolv.conf``. + + It also configures internal Kubernetes DNS server (Coredns) to work as a recursive DNS server + and adds its IP address (10.96.0.10 by default) to the `/etc/resolv.conf` file. + + Programs running on those nodes will be able to resolve names in the + default Kubernetes domain `.svc.cluster.local`. E.g. if you run OpenStack command line + client on one of those nodes it will be able to access OpenStack API services via + these names. + +.. note:: + The role `deploy-env`_ installs and confiugres Kubectl and Helm on the `primary` node. + You can login to it via SSH, clone `openstack-helm`_ and `openstack-helm-infra`_ repositories + and then run the OpenStack-Helm deployment scipts which employ Kubectl and Helm to deploy + OpenStack. + +.. _deploy-env: https://opendev.org/openstack/openstack-helm-infra/src/branch/master/roles/deploy-env +.. _ensure-python: https://opendev.org/zuul/zuul-jobs/src/branch/master/roles/ensure-python +.. _ensure-pip: https://opendev.org/zuul/zuul-jobs/src/branch/master/roles/ensure-pip +.. _clear-firewall: https://opendev.org/zuul/zuul-jobs/src/branch/master/roles/clear-firewall +.. _openstack-helm: https://opendev.org/openstack/openstack-helm.git +.. _openstack-helm-infra: https://opendev.org/openstack/openstack-helm-infra.git +.. _playbook: https://opendev.org/openstack/openstack-helm/src/branch/master/tools/gate/playbooks/deploy-env.yaml diff --git a/doc/source/install/deploy_openstack.rst b/doc/source/install/deploy_openstack.rst new file mode 100644 index 0000000000..b7dd7e898f --- /dev/null +++ b/doc/source/install/deploy_openstack.rst @@ -0,0 +1,116 @@ +Deploy OpenStack +================ + +Now we are ready for the deployment of OpenStack components. +Some of them are mandatory while others are optional. + +Keystone +-------- + +OpenStack Keystone is the identity and authentication service +for the OpenStack cloud computing platform. It serves as the +central point of authentication and authorization, managing user +identities, roles, and access to OpenStack resources. Keystone +ensures secure and controlled access to various OpenStack services, +making it an integral component for user management and security +in OpenStack deployments. + +This is a ``mandatory`` component of any OpenStack cluster. + +To deploy the Keystone service run the script `keystone.sh`_ + +.. code-block:: bash + + cd ~/osh/openstack-helm + ./tools/deployment/component/keystone/keystone.sh + + +Heat +---- + +OpenStack Heat is an orchestration service that provides templates +and automation for deploying and managing cloud resources. It enables +users to define infrastructure as code, making it easier to create +and manage complex environments in OpenStack through templates and +automation scripts. + +Here is the script `heat.sh`_ for the deployment of Heat service. + +.. code-block:: bash + + cd ~/osh/openstack-helm + ./tools/deployment/component/heat/heat.sh + +Glance +------ + +OpenStack Glance is the image service component of OpenStack. +It manages and catalogs virtual machine images, such as operating +system images and snapshots, making them available for use in +OpenStack compute instances. + +This is a ``mandatory`` component. + +The Glance deployment script is here `glance.sh`_. + +.. code-block:: bash + + cd ~/osh/openstack-helm + ./tools/deployment/component/glance/glance.sh + +Placement, Nova, Neutron +------------------------ + +OpenStack Placement is a service that helps manage and allocate +resources in an OpenStack cloud environment. It helps Nova (compute) +find and allocate the right resources (CPU, memory, etc.) +for virtual machine instances. + +OpenStack Nova is the compute service responsible for managing +and orchestrating virtual machines in an OpenStack cloud. +It provisions and schedules instances, handles their lifecycle, +and interacts with underlying hypervisors. + +OpenStack Neutron is the networking service that provides network +connectivity and enables users to create and manage network resources +for their virtual machines and other services. + +These three services are ``mandatory`` and together constitue +so-called ``compute kit``. + +To set up the compute service, the first step involves deploying the +hypervisor backend using the `libvirt.sh`_ script. By default, the +networking service is deployed with OpenvSwitch as the networking +backend, and the deployment script for OpenvSwitch can be found +here: `openvswitch.sh`_. And finally the deployment script for +Placement, Nova and Neutron is here: `compute-kit.sh`_. + +.. code-block:: bash + + cd ~/osh/openstack-helm + ./tools/deployment/component/compute-kit/openvswitch.sh + ./tools/deployment/component/compute-kit/libvirt.sh + ./tools/deployment/component/compute-kit/compute-kit.sh + +Cinder +------ + +OpenStack Cinder is the block storage service component of the +OpenStack cloud computing platform. It manages and provides persistent +block storage to virtual machines, enabling users to attach and detach +persistent storage volumes to their VMs as needed. + +To deploy the OpenStack Cinder service use the script `cinder.sh`_ + +.. code-block:: bash + + cd ~/osh/openstack-helm + ./tools/deployment/component/cinder/cinder.sh + +.. _keystone.sh: https://opendev.org/openstack/openstack-helm/src/branch/master/tools/deployment/component/keystone/keystone.sh +.. _heat.sh: https://opendev.org/openstack/openstack-helm/src/branch/master/tools/deployment/component/heat/heat.sh +.. _glance.sh: https://opendev.org/openstack/openstack-helm/src/branch/master/tools/deployment/component/glance/glance.sh +.. _libvirt.sh: https://opendev.org/openstack/openstack-helm/src/branch/master/tools/deployment/component/compute-kit/libvirt.sh +.. _openvswitch.sh: https://opendev.org/openstack/openstack-helm/src/branch/master/tools/deployment/component/compute-kit/openvswitch.sh +.. _compute-kit.sh: https://opendev.org/openstack/openstack-helm/src/branch/master/tools/deployment/component/compute-kit/compute-kit.sh +.. _cinder.sh: https://opendev.org/openstack/openstack-helm/src/branch/master/tools/deployment/component/cinder/cinder.sh diff --git a/doc/source/install/deploy_openstack_backend.rst b/doc/source/install/deploy_openstack_backend.rst new file mode 100644 index 0000000000..2028749d86 --- /dev/null +++ b/doc/source/install/deploy_openstack_backend.rst @@ -0,0 +1,54 @@ +Deploy OpenStack backend +======================== + +OpenStack is a cloud computing platform that consists of a variety of +services, and many of these services rely on backend services like RabbitMQ, +MariaDB, and Memcached for their proper functioning. These backend services +play crucial roles in OpenStack's architecture. + +RabbitMQ +~~~~~~~~ +RabbitMQ is a message broker that is often used in OpenStack to handle +messaging between different components and services. It helps in managing +communication and coordination between various parts of the OpenStack +infrastructure. Services like Nova (compute), Neutron (networking), and +Cinder (block storage) use RabbitMQ to exchange messages and ensure +proper orchestration. + +MariaDB +~~~~~~~ +Database services like MariaDB are used as the backend database for several +OpenStack services. These databases store critical information such as user +credentials, service configurations, and data related to instances, networks, +and volumes. Services like Keystone (identity), Nova, Glance (image), and +Cinder rely on MariaDB for data storage. + +Memcached +~~~~~~~~~ +Memcached is a distributed memory object caching system that is often used +in OpenStack to improve performance and reduce database load. OpenStack +services cache frequently accessed data in Memcached, which helps in faster +data retrieval and reduces the load on the database backend. Services like +Keystone and Nova can benefit from Memcached for caching. + +Deployment +---------- + +The following scripts `rabbitmq.sh`_, `mariadb.sh`_, `memcached.sh`_ can be used to +deploy the backend services. + +.. code-block:: bash + + cd ~/osh/openstack-helm + ./tools/deployment/component/common/rabbitmq.sh + ./tools/deployment/component/common/mariadb.sh + ./tools/deployment/component/common/memcached.sh + +.. note:: + These scripts use Helm charts from the `openstack-helm-infra`_ repository. We assume + this repo is cloned to the `~/osh` directory. See this :doc:`section </install/before_deployment>`. + +.. _rabbitmq.sh: https://opendev.org/openstack/openstack-helm/src/branch/master/tools/deployment/component/common/rabbitmq.sh +.. _mariadb.sh: https://opendev.org/openstack/openstack-helm/src/branch/master/tools/deployment/component/common/mariadb.sh +.. _memcached.sh: https://opendev.org/openstack/openstack-helm/src/branch/master/tools/deployment/component/common/memcached.sh +.. _openstack-helm-infra: https://opendev.org/openstack/openstack-helm-infra.git diff --git a/doc/source/install/developer/cleaning-deployment.rst b/doc/source/install/developer/cleaning-deployment.rst deleted file mode 100644 index 00811b7b22..0000000000 --- a/doc/source/install/developer/cleaning-deployment.rst +++ /dev/null @@ -1,92 +0,0 @@ -======================= -Cleaning the Deployment -======================= - -Removing Helm Charts -==================== - -To delete an installed helm chart, use the following command: - -.. code-block:: shell - - helm delete ${RELEASE_NAME} --purge - -This will delete all Kubernetes resources generated when the chart was -instantiated. However for OpenStack charts, by default, this will not delete -the database and database users that were created when the chart was installed. -All OpenStack projects can be configured such that upon deletion, their database -will also be removed. To delete the database when the chart is deleted the -database drop job must be enabled before installing the chart. There are two -ways to enable the job, set the job_db_drop value to true in the chart's -``values.yaml`` file, or override the value using the helm install command as -follows: - -.. code-block:: shell - - helm install ${RELEASE_NAME} --set manifests.job_db_drop=true - - -Environment tear-down -===================== - -To tear-down, the development environment charts should be removed first from -the 'openstack' namespace and then the 'ceph' namespace using the commands from -the `Removing Helm Charts` section. Additionally charts should be removed from -the 'nfs' and 'libvirt' namespaces if deploying with NFS backing or bare metal -development support. You can run the following commands to loop through and -delete the charts, then stop the kubelet systemd unit and remove all the -containers before removing the directories used on the host by pods. - -.. code-block:: shell - - for NS in openstack ceph nfs libvirt; do - helm ls --namespace $NS --short | xargs -r -L1 -P2 helm delete --purge - done - - sudo systemctl stop kubelet - sudo systemctl disable kubelet - - sudo docker ps -aq | xargs -r -L1 -P16 sudo docker rm -f - - sudo rm -rf /var/lib/openstack-helm/* - - # NOTE(portdirect): These directories are used by nova and libvirt - sudo rm -rf /var/lib/nova/* - sudo rm -rf /var/lib/libvirt/* - sudo rm -rf /etc/libvirt/qemu/* - #NOTE(chinasubbareddy) cleanup LVM volume groups in case of disk backed ceph osd deployments - for VG in `vgs|grep -v VG|grep -i ceph|awk '{print $1}'`; do - echo $VG - vgremove -y $VG - done - # lets delete loopback devices setup for ceph, if the device names are different in your case, - # please update them here as environmental variables as shown below. - : "${CEPH_OSD_DATA_DEVICE:=/dev/loop0}" - : "${CEPH_OSD_DB_WAL_DEVICE:=/dev/loop1}" - if [ ! -z "$CEPH_OSD_DATA_DEVICE" ]; then - ceph_osd_disk_name=`basename "$CEPH_OSD_DATA_DEVICE"` - if losetup -a|grep $ceph_osd_disk_name; then - losetup -d "$CEPH_OSD_DATA_DEVICE" - fi - fi - if [ ! -z "$CEPH_OSD_DB_WAL_DEVICE" ]; then - ceph_db_wal_disk_name=`basename "$CEPH_OSD_DB_WAL_DEVICE"` - if losetup -a|grep $ceph_db_wal_disk_name; then - losetup -d "$CEPH_OSD_DB_WAL_DEVICE" - fi - fi - echo "let's disable the service" - sudo systemctl disable loops-setup - echo "let's remove the service to setup loopback devices" - if [ -f "/etc/systemd/system/loops-setup.service" ]; then - rm /etc/systemd/system/loops-setup.service - fi - - # NOTE(portdirect): Clean up mounts left behind by kubernetes pods - sudo findmnt --raw | awk '/^\/var\/lib\/kubelet\/pods/ { print $1 }' | xargs -r -L1 -P16 sudo umount -f -l - - -These commands will restore the environment back to a clean Kubernetes -deployment, that can either be manually removed or over-written by -restarting the deployment process. It is recommended to restart the host before -doing so to ensure any residual state, eg. Network interfaces are removed. diff --git a/doc/source/install/developer/deploy-ovs-dpdk.rst b/doc/source/install/developer/deploy-ovs-dpdk.rst deleted file mode 100644 index fccb4f6e0e..0000000000 --- a/doc/source/install/developer/deploy-ovs-dpdk.rst +++ /dev/null @@ -1,185 +0,0 @@ -=============== -Deploy OVS-DPDK -=============== - -Requirements -============ - -A correct DPDK configuration depends heavily on the specific hardware resources -and its configuration. Before deploying Openvswitch with DPDK, check the amount -and type of available hugepages on the host OS. - -.. code-block:: shell - - cat /proc/meminfo | grep Huge - AnonHugePages: 0 kB - ShmemHugePages: 0 kB - HugePages_Total: 8 - HugePages_Free: 6 - HugePages_Rsvd: 0 - HugePages_Surp: 0 - Hugepagesize: 1048576 kB - -In this example, 8 hugepages of 1G size have been allocated. 2 of those are -being used and 6 are still available. - -More information on how to allocate and configure hugepages on the host OS can -be found in the `Openvswitch documentation -<http://docs.openvswitch.org/en/latest/intro/install/dpdk/>`_. - -In order to allow OVS inside a pod to make use of hugepages, the corresponding -type and amount of hugepages must be specified in the resource section of the -OVS chart's values.yaml: - -.. code-block:: yaml - - resources: - enabled: true - ovs: - db: - requests: - memory: "128Mi" - cpu: "100m" - limits: - memory: "1024Mi" - cpu: "2000m" - vswitchd: - requests: - memory: "128Mi" - cpu: "100m" - limits: - memory: "1024Mi" - cpu: "2000m" - # set resources to enabled and specify one of the following when using dpdk - hugepages-1Gi: "1Gi" - # hugepages-2Mi: "512Mi" - -Additionally, the default configuration of the neutron chart must be adapted according -to the underlying hardware. The corresponding configuration parameter is labeled with -"CHANGE-ME" in the script "values_overrides/dpdk.yaml". Specifically, the "ovs_dpdk" -configuration section should list all NICs which should be bound to DPDK with -their corresponding PCI-IDs. Moreover, the name of each NIC needs to be unique, -e.g., dpdk0, dpdk1, etc. - -.. code-block:: yaml - - network: - interface: - tunnel: br-phy - conf: - ovs_dpdk: - enabled: true - driver: uio_pci_generic - nics: - - name: dpdk0 - # CHANGE-ME: modify pci_id according to hardware - pci_id: '0000:05:00.0' - bridge: br-phy - migrate_ip: true - bridges: - - name: br-phy - bonds: [] - -In the example above, bonding isn't used and hence an empty list is passed in the "bonds" -section. - -Deployment -========== - -Once the above requirements are met, start deploying Openstack Helm using the deployment -scripts under the dpdk directory in an increasing order - -.. code-block:: shell - - ./tools/deployment/developer/dpdk/<script-name> - -One can also specify the name of Openstack release and container OS distribution as -overrides before running the deployment scripts, for instance, - -.. code-block:: shell - - export OPENSTACK_RELEASE=wallaby - export CONTAINER_DISTRO_NAME=ubuntu - export CONTAINER_DISTRO_VERSION=focal - -Troubleshooting -=============== - -OVS startup failure -------------------- - -If OVS fails to start up because of no hugepages are available, check the -configuration of the OVS daemonset. Older versions of helm-toolkit were not -able to render hugepage configuration into the Kubernetes manifest and just -removed the hugepage attributes. If no hugepage configuration is defined for -the OVS daemonset, consider using a newer version of helm-toolkit. - -.. code-block:: shell - - kubectl get daemonset openvswitch-vswitchd -n openstack -o yaml - [...] - resources: - limits: - cpu: "2" - hugepages-1Gi: 1Gi - memory: 1Gi - requests: - cpu: 100m - memory: 128Mi - [...] - -Adding a DPDK port to Openvswitch fails ---------------------------------------- - -When adding a DPDK port (a NIC bound to DPDK) to OVS fails, one source of error -is related to an incorrect configuration with regards to the NUMA topology of -the underlying hardware. Every NIC is connected to one specific NUMA socket. In -order to use a NIC as DPDK port in OVS, the OVS configurations regarding -hugepage(s) and PMD thread(s) need to match the NUMA topology. - -The NUMA socket a given NIC is connected to can be found in the ovs-vswitchd log: - -.. code-block:: - - kubectl logs -n openstack openvswitch-vswitchd-6h928 - [...] - 2019-07-02T13:42:06Z|00016|dpdk|INFO|EAL: PCI device 0000:00:04.0 on NUMA socket 1 - 2019-07-02T13:42:06Z|00018|dpdk|INFO|EAL: probe driver: 1af4:1000 net_virtio - [...] - -In this example, the NIC with PCI-ID 0000:00:04.0 is connected to NUMA socket -1. As a result, this NIC can only be used by OVS if - -1. hugepages have been allocated on NUMA socket 1 by OVS, and -2. PMD threads have been assigned to NUMA socket 1. - -To allocate hugepages to NUMA sockets in OVS, ensure that the -``socket_memory`` attribute in values.yaml specifies a value for the -corresponding NUMA socket. In the following example, OVS will use one 1G -hugepage for NUMA socket 0 and socket 1. - -.. code-block:: - - socket_memory: 1024,1024 - - -To allocate PMD threads to NUMA sockets in OVS, ensure that the ``pmd_cpu_mask`` -attribute in values.yaml includes CPU sockets on the corresponding NUMA socket. -In the example below, the mask of 0xf covers the first 4 CPU cores which are -distributed across NUMA sockets 0 and 1. - -.. code-block:: - - pmd_cpu_mask: 0xf - -The mapping of CPU cores to NUMA sockets can be determined by means of ``lspci``, for instance: - -.. code-block:: shell - - lspci | grep NUMA - NUMA node(s): 2 - NUMA node0 CPU(s): 0,2,4,6,8,10,12,14 - NUMA node1 CPU(s): 1,3,5,7,9,11,13,15 - -More information can be found in the `Openvswitch documentation -<http://docs.openvswitch.org/en/latest/intro/install/dpdk/>`_. diff --git a/doc/source/install/developer/deploy-with-ceph.rst b/doc/source/install/developer/deploy-with-ceph.rst deleted file mode 100644 index 08923187c8..0000000000 --- a/doc/source/install/developer/deploy-with-ceph.rst +++ /dev/null @@ -1,222 +0,0 @@ -==================== -Deployment With Ceph -==================== - -.. note:: - For other deployment options, select appropriate ``Deployment with ...`` - option from `Index <../developer/index.html>`__ page. - -Deploy Ceph -^^^^^^^^^^^ - -We are going to install Ceph OSDs backed by loopback devices as this will -help us not to attach extra disks, in case if you have enough disks -on the node then feel free to skip creating loopback devices by exporting -CREATE_LOOPBACK_DEVICES_FOR_CEPH to false and export the block devices names -as environment variables(CEPH_OSD_DATA_DEVICE and CEPH_OSD_DB_WAL_DEVICE). - -We are also going to separate Ceph metadata and data onto a different devices -to replicate the ideal scenario of fast disks for metadata and slow disks to store data. -You can change this as per your design by referring to the documentation explained in -../openstack-helm-infra/ceph-osd/values.yaml - -This script will create two loopback devices for Ceph as one disk for OSD data -and other disk for block DB and block WAL. If default devices (loop0 and loop1) are busy in -your case, feel free to change them by exporting environment variables(CEPH_OSD_DATA_DEVICE -and CEPH_OSD_DB_WAL_DEVICE). - -.. note:: - if you are rerunning the below script then make sure to skip the loopback device creation - by exporting CREATE_LOOPBACK_DEVICES_FOR_CEPH to false. - -.. literalinclude:: ../../../../tools/deployment/developer/ceph/040-ceph.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/ceph/040-ceph.sh - -Activate the OpenStack namespace to be able to use Ceph -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/ceph/045-ceph-ns-activate.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/ceph/045-ceph-ns-activate.sh - -Deploy MariaDB -^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/ceph/050-mariadb.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/ceph/050-mariadb.sh - -Deploy RabbitMQ -^^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/ceph/060-rabbitmq.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/ceph/060-rabbitmq.sh - -Deploy Memcached -^^^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/ceph/070-memcached.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/ceph/070-memcached.sh - -Deploy Keystone -^^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/ceph/080-keystone.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/ceph/080-keystone.sh - -Deploy Heat -^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/ceph/090-heat.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/ceph/090-heat.sh - -Deploy Horizon -^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/ceph/100-horizon.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/ceph/100-horizon.sh - -Deploy Rados Gateway for object store -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/ceph/110-ceph-radosgateway.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/ceph/110-ceph-radosgateway.sh - -Deploy Glance -^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/ceph/120-glance.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/ceph/120-glance.sh - -Deploy Cinder -^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/ceph/130-cinder.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/ceph/130-cinder.sh - -Deploy OpenvSwitch -^^^^^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/ceph/140-openvswitch.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/ceph/140-openvswitch.sh - -Deploy Libvirt -^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/ceph/150-libvirt.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/ceph/150-libvirt.sh - -Deploy Compute Kit (Nova and Neutron) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/ceph/160-compute-kit.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/ceph/160-compute-kit.sh - -Setup the gateway to the public network -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/ceph/170-setup-gateway.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/ceph/170-setup-gateway.sh diff --git a/doc/source/install/developer/deploy-with-nfs.rst b/doc/source/install/developer/deploy-with-nfs.rst deleted file mode 100644 index 0b2f5a5945..0000000000 --- a/doc/source/install/developer/deploy-with-nfs.rst +++ /dev/null @@ -1,163 +0,0 @@ -=================== -Deployment With NFS -=================== - -.. note:: - For other deployment options, select appropriate ``Deployment with ...`` - option from `Index <../developer/index.html>`__ page. - -Deploy NFS Provisioner -^^^^^^^^^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/nfs/040-nfs-provisioner.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/nfs/040-nfs-provisioner.sh - -Deploy MariaDB -^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/nfs/050-mariadb.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/nfs/050-mariadb.sh - -Deploy RabbitMQ -^^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/nfs/060-rabbitmq.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/nfs/060-rabbitmq.sh - -Deploy Memcached -^^^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/nfs/070-memcached.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/nfs/070-memcached.sh - -Deploy Keystone -^^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/nfs/080-keystone.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/nfs/080-keystone.sh - -Deploy Heat -^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/nfs/090-heat.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/nfs/090-heat.sh - -Deploy Horizon -^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/nfs/100-horizon.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/nfs/100-horizon.sh - -Deploy Glance -^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/nfs/120-glance.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/nfs/120-glance.sh - -Deploy OpenvSwitch -^^^^^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/nfs/140-openvswitch.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/nfs/140-openvswitch.sh - -Deploy Libvirt -^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/nfs/150-libvirt.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/nfs/150-libvirt.sh - -Deploy Compute Kit (Nova and Neutron) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/nfs/160-compute-kit.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/nfs/160-compute-kit.sh - -Setup the gateway to the public network -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/developer/nfs/170-setup-gateway.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/nfs/170-setup-gateway.sh diff --git a/doc/source/install/developer/deploy-with-tungsten-fabric.rst b/doc/source/install/developer/deploy-with-tungsten-fabric.rst deleted file mode 100644 index bca1aa13f9..0000000000 --- a/doc/source/install/developer/deploy-with-tungsten-fabric.rst +++ /dev/null @@ -1,147 +0,0 @@ -=============================== -Deployment with Tungsten Fabric -=============================== - -Intro -^^^^^ - -Tungsten Fabric is the multicloud and multistack network solution which you can -use for your OpenStack as a network plugin. This document decribes how you can deploy -a single node Open Stack based on Tungsten Fabric using openstack helm for development purpose. - -Prepare host -^^^^^^^^^^^^ - -First you have to set up OpenStack and Linux versions and install needed packages - -.. code-block:: shell - - export OPENSTACK_RELEASE=train - export CONTAINER_DISTRO_NAME=ubuntu - export CONTAINER_DISTRO_VERSION=bionic - sudo apt update -y - sudo apt install -y resolvconf - cd ~/openstack-helm - -Install OpenStack packages -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: shell - - ./tools/deployment/common/install-packages.sh - -Install k8s Minikube -^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: shell - - ./tools/deployment/common/deploy-k8s.sh - -Setup DNS for use cluster DNS -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: shell - - dns_cluster_ip=`kubectl get svc kube-dns -n kube-system --no-headers -o custom-columns=":spec.clusterIP"` - echo "nameserver ${dns_cluster_ip}" | sudo tee -a /etc/resolvconf/resolv.conf.d/head > /dev/null - sudo dpkg-reconfigure --force resolvconf - sudo systemctl restart resolvconf - - -Setup env for apply values_overrides -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: shell - - export FEATURE_GATES=tf - -Setup OpenStack client -^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: shell - - ./tools/deployment/common/setup-client.sh - -Setup Ingress -^^^^^^^^^^^^^ - -.. code-block:: shell - - ./tools/deployment/component/common/ingress.sh - -Setup MariaDB -^^^^^^^^^^^^^ - -.. code-block:: shell - - ./tools/deployment/component/common/mariadb.sh - -Setup Memcached -^^^^^^^^^^^^^^^ - -.. code-block:: shell - - ./tools/deployment/component/common/memcached.sh - -Setup RabbitMQ -^^^^^^^^^^^^^^ - -.. code-block:: shell - - ./tools/deployment/component/common/rabbitmq.sh - -Setup NFS -^^^^^^^^^ - -.. code-block:: shell - - ./tools/deployment/component/nfs-provisioner/nfs-provisioner.sh - -Setup Keystone -^^^^^^^^^^^^^^ - -.. code-block:: shell - - ./tools/deployment/component/keystone/keystone.sh - -Setup Heat -^^^^^^^^^^ - -.. code-block:: shell - - ./tools/deployment/component/heat/heat.sh - -Setup Glance -^^^^^^^^^^^^ - -.. code-block:: shell - - ./tools/deployment/component/glance/glance.sh - -Prepare host and openstack helm for tf -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: shell - - ./tools/deployment/component/compute-kit/tungsten-fabric.sh prepare - -Setup libvirt -^^^^^^^^^^^^^ - -.. code-block:: shell - - ./tools/deployment/component/compute-kit/libvirt.sh - -Setup Neutron and Nova -^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: shell - - ./tools/deployment/component/compute-kit/compute-kit.sh - -Setup Tungsten Fabric -^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: shell - - ./tools/deployment/component/compute-kit/tungsten-fabric.sh deploy \ No newline at end of file diff --git a/doc/source/install/developer/exercise-the-cloud.rst b/doc/source/install/developer/exercise-the-cloud.rst deleted file mode 100644 index 594de60c37..0000000000 --- a/doc/source/install/developer/exercise-the-cloud.rst +++ /dev/null @@ -1,90 +0,0 @@ -================== -Exercise the Cloud -================== - -Once OpenStack-Helm has been deployed, the cloud can be exercised either with -the OpenStack client, or the same heat templates that are used in the validation -gates. - -.. literalinclude:: ../../../../tools/deployment/developer/common/900-use-it.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/common/900-use-it.sh - -To run further commands from the CLI manually, execute the following to -set up authentication credentials:: - - export OS_CLOUD=openstack_helm - -Note that this command will only enable you to auth successfully using the -``python-openstackclient`` CLI. To use legacy clients like the -``python-novaclient`` from the CLI, reference the auth values in -``/etc/openstack/clouds.yaml`` and run:: - - export OS_USERNAME='admin' - export OS_PASSWORD='password' - export OS_PROJECT_NAME='admin' - export OS_PROJECT_DOMAIN_NAME='default' - export OS_USER_DOMAIN_NAME='default' - export OS_AUTH_URL='http://keystone.openstack.svc.cluster.local/v3' - -The example above uses the default values used by ``openstack-helm-infra``. - --------------------------------- -Subsequent Runs & Post Clean-up --------------------------------- - -Execution of the **900-use-it.sh** script results in the creation of 4 heat stacks and a unique -keypair enabling access to a newly created VM. Subsequent runs of the **900-use-it.sh** script -requires deletion of the stacks, a keypair, and key files, generated during the initial script -execution. - -The following steps serve as a guide to clean-up the client environment by deleting stacks and -respective artifacts created during the **900-use-it.sh** script: - -1. List the stacks created during script execution which will need to be deleted:: - - sudo openstack --os-cloud openstack_helm stack list - # Sample results returned for *Stack Name* include: - # - heat-vm-volume-attach - # - heat-basic-vm-deployment - # - heat-subnet-pool-deployment - # - heat-public-net-deployment - -2. Delete the stacks returned from the *openstack helm stack list* command above:: - - sudo openstack --os-cloud openstack_helm stack delete heat-vm-volume-attach - sudo openstack --os-cloud openstack_helm stack delete heat-basic-vm-deployment - sudo openstack --os-cloud openstack_helm stack delete heat-subnet-pool-deployment - sudo openstack --os-cloud openstack_helm stack delete heat-public-net-deployment - -3. List the keypair(s) generated during the script execution:: - - sudo openstack --os-cloud openstack_helm keypair list - # Sample Results returned for “Name” include: - # - heat-vm-key - -4. Delete the keypair(s) returned from the list command above:: - - sudo openstack --os-cloud openstack_helm keypair delete heat-vm-key - -5. Manually remove the keypair directories created from the script in the ~/.ssh directory:: - - cd ~/.ssh - rm osh_key - rm known_hosts - -6. As a final validation step, re-run the **openstack helm stack list** and - **openstack helm keypair list** commands and confirm the returned results are shown as empty.:: - - sudo openstack --os-cloud openstack_helm stack list - sudo openstack --os-cloud openstack_helm keypair list - -Alternatively, these steps can be performed by running the script directly:: - -./tools/deployment/developer/common/910-clean-it.sh \ No newline at end of file diff --git a/doc/source/install/developer/index.rst b/doc/source/install/developer/index.rst deleted file mode 100644 index 36981ff495..0000000000 --- a/doc/source/install/developer/index.rst +++ /dev/null @@ -1,16 +0,0 @@ -Deployment -========== - -Contents: - -.. toctree:: - :maxdepth: 2 - - requirements-and-host-config - kubernetes-and-common-setup - deploy-with-nfs - deploy-with-tungsten-fabric - deploy-with-ceph - deploy-ovs-dpdk.rst - exercise-the-cloud - cleaning-deployment diff --git a/doc/source/install/developer/kubernetes-and-common-setup.rst b/doc/source/install/developer/kubernetes-and-common-setup.rst deleted file mode 100644 index 0ff12f006d..0000000000 --- a/doc/source/install/developer/kubernetes-and-common-setup.rst +++ /dev/null @@ -1,135 +0,0 @@ -=========================== -Kubernetes and Common Setup -=========================== - -Install Basic Utilities -^^^^^^^^^^^^^^^^^^^^^^^ - -To get started with OSH, we will need ``git``, ``curl`` and ``make``. - -.. code-block:: shell - - sudo apt install git curl make - -Clone the OpenStack-Helm Repos -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Once the host has been configured the repos containing the OpenStack-Helm charts -should be cloned: - -.. code-block:: shell - - #!/bin/bash - set -xe - - git clone https://opendev.org/openstack/openstack-helm-infra.git - git clone https://opendev.org/openstack/openstack-helm.git - -OSH Proxy & DNS Configuration -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. note:: - - If you are not deploying OSH behind a proxy, skip this step and - continue with "Deploy Kubernetes & Helm". - -In order to deploy OSH behind a proxy, add the following entries to -``openstack-helm-infra/tools/gate/devel/local-vars.yaml``: - -.. code-block:: shell - - proxy: - http: http://PROXY_URL:PORT - https: https://PROXY_URL:PORT - noproxy: 127.0.0.1,localhost,172.17.0.1,.svc.cluster.local - -.. note:: - Depending on your specific proxy, https_proxy may be the same as http_proxy. - Refer to your specific proxy documentation. - -By default OSH will use Google DNS Server IPs (8.8.8.8, 8.8.4.4) and will -update resolv.conf as a result. If those IPs are blocked by your proxy, running -the OSH scripts will result in the inability to connect to anything on the -network. These DNS nameserver entries can be changed by updating the -external_dns_nameservers entry in the file -``openstack-helm-infra/tools/images/kubeadm-aio/assets/opt/playbooks/vars.yaml``. - -.. code-block:: shell - - external_dns_nameservers: - - YOUR_PROXY_DNS_IP - - ALT_PROXY_DNS_IP - -These values can be retrieved by running: - -.. code-block:: shell - - systemd-resolve --status - -Deploy Kubernetes & Helm -^^^^^^^^^^^^^^^^^^^^^^^^ - -You may now deploy kubernetes, and helm onto your machine, first move into the -``openstack-helm`` directory and then run the following: - -.. literalinclude:: ../../../../tools/deployment/developer/common/010-deploy-k8s.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/common/010-deploy-k8s.sh - -This command will deploy a single node minikube cluster. This will use the -parameters in ``${OSH_INFRA_PATH}/playbooks/vars.yaml`` to control the -deployment, which can be over-ridden by adding entries to -``${OSH_INFRA_PATH}/tools/gate/devel/local-vars.yaml``. - -Helm Chart Installation -======================= - -Using the Helm packages previously pushed to the local Helm repository, run the -following commands to instruct tiller to create an instance of the given chart. -During installation, the helm client will print useful information about -resources created, the state of the Helm releases, and whether any additional -configuration steps are necessary. - -Install OpenStack-Helm ----------------------- - -.. note:: The following commands all assume that they are run from the - ``openstack-helm`` directory and the repos have been cloned as above. - -Setup Clients on the host and assemble the charts -================================================= - -The OpenStack clients and Kubernetes RBAC rules, along with assembly of the -charts can be performed by running the following commands: - -.. literalinclude:: ../../../../tools/deployment/developer/common/020-setup-client.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/developer/common/020-setup-client.sh - -Deploy the ingress controller -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. literalinclude:: ../../../../tools/deployment/component/common/ingress.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/component/common/ingress.sh - -To continue to deploy OpenStack on Kubernetes via OSH, see -:doc:`Deploy NFS<./deploy-with-nfs>` or :doc:`Deploy Ceph<./deploy-with-ceph>`. diff --git a/doc/source/install/developer/requirements-and-host-config.rst b/doc/source/install/developer/requirements-and-host-config.rst deleted file mode 100644 index 59e1492e06..0000000000 --- a/doc/source/install/developer/requirements-and-host-config.rst +++ /dev/null @@ -1,100 +0,0 @@ -=================================== -Requirements and Host Configuration -=================================== - -Overview -======== - -Below are some instructions and suggestions to help you get started with a -Kubeadm All-in-One environment on Ubuntu 18.04. -Other supported versions of Linux can also be used, with the appropriate changes -to package installation. - -Requirements -============ - -System Requirements -------------------- - -The recommended minimum system requirements for a full deployment are: - -- 16GB of RAM -- 8 Cores -- 48GB HDD - -For a deployment without cinder and horizon the system requirements are: - -- 8GB of RAM -- 4 Cores -- 48GB HDD - -This guide covers the minimum number of requirements to get started. - -All commands below should be run as a normal user, not as root. -Appropriate versions of Docker, Kubernetes, and Helm will be installed -by the playbooks used below, so there's no need to install them ahead of time. - -.. warning:: By default the Calico CNI will use ``192.168.0.0/16`` and - Kubernetes services will use ``10.96.0.0/16`` as the CIDR for services. Check - that these CIDRs are not in use on the development node before proceeding, or - adjust as required. - -Host Configuration ------------------- - -OpenStack-Helm uses the hosts networking namespace for many pods including, -Ceph, Neutron and Nova components. For this, to function, as expected pods need -to be able to resolve DNS requests correctly. Ubuntu Desktop and some other -distributions make use of ``mdns4_minimal`` which does not operate as Kubernetes -expects with its default TLD of ``.local``. To operate at expected either -change the ``hosts`` line in the ``/etc/nsswitch.conf``, or confirm that it -matches: - -.. code-block:: ini - - hosts: files dns - -Host Proxy & DNS Configuration ------------------------------- - -.. note:: - - If you are not deploying OSH behind a proxy, skip this step. - -Set your local environment variables to use the proxy information. This -involves adding or setting the following values in ``/etc/environment``: - -.. code-block:: shell - - export http_proxy="YOUR_PROXY_ADDRESS:PORT" - export https_proxy="YOUR_PROXY_ADDRESS:PORT" - export ftp_proxy="YOUR_PROXY_ADDRESS:PORT" - export no_proxy="localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,172.17.0.1,.svc.cluster.local,$YOUR_ACTUAL_IP" - export HTTP_PROXY="YOUR_PROXY_ADDRESS:PORT" - export HTTPS_PROXY="YOUR_PROXY_ADDRESS:PORT" - export FTP_PROXY="YOUR_PROXY_ADDRESS:PORT" - export NO_PROXY="localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,172.17.0.1,.svc.cluster.local,$YOUR_ACTUAL_IP" - - -.. note:: - Depending on your specific proxy, https_proxy may be the same as http_proxy. - Refer to your specific proxy documentation. - -Your changes to `/etc/environment` will not be applied until you source them: - -.. code-block:: shell - - source /etc/environment - -OSH runs updates for local apt packages, so we will need to set the proxy for -apt as well by adding these lines to `/etc/apt/apt.conf`: - -.. code-block:: shell - - Acquire::http::proxy "YOUR_PROXY_ADDRESS:PORT"; - Acquire::https::proxy "YOUR_PROXY_ADDRESS:PORT"; - Acquire::ftp::proxy "YOUR_PROXY_ADDRESS:PORT"; - -.. note:: - Depending on your specific proxy, https_proxy may be the same as http_proxy. - Refer to your specific proxy documentation. diff --git a/doc/source/install/ext-dns-fqdn.rst b/doc/source/install/ext-dns-fqdn.rst deleted file mode 100644 index 8008c53ac1..0000000000 --- a/doc/source/install/ext-dns-fqdn.rst +++ /dev/null @@ -1,244 +0,0 @@ -============================ -External DNS to FQDN/Ingress -============================ - -Overview -======== - -In order to access your OpenStack deployment on Kubernetes we can use the Ingress Controller -or NodePorts to provide a pathway in. A background on Ingress, OpenStack-Helm fully qualified -domain name (FQDN) overrides, installation, examples, and troubleshooting will be discussed here. - - -Ingress -======= - -OpenStack-Helm utilizes the `Kubernetes Ingress Controller -<https://kubernetes.io/docs/concepts/services-networking/ingress/>`__ - -An Ingress is a collection of rules that allow inbound connections to reach the cluster services. - -:: - - internet - | - [ Ingress ] - --|-----|-- - [ Services ] - - -It can be configured to give services externally-reachable URLs, load balance traffic, -terminate SSL, offer name based virtual hosting, and more. - -Essentially the use of Ingress for OpenStack-Helm is an Nginx proxy service. Ingress (Nginx) is -accessible by your cluster public IP - e.g. the IP associated with -``kubectl get pods -o wide --all-namespaces | grep ingress-api`` -Ingress/Nginx will be listening for server name requests of "keystone" or "keystone.openstack" -and will route those requests to the proper internal K8s Services. -These public listeners in Ingress must match the external DNS that you will set up to access -your OpenStack deployment. Note each rule also has a Service that directs Ingress Controllers -allow access to the endpoints from within the cluster. - - -External DNS and FQDN -===================== - -Prepare ahead of time your FQDN and DNS layouts. There are a handful of OpenStack endpoints -you will want to expose for API and Dashboard access. - -Update your lab/environment DNS server with your appropriate host values creating A Records -for the edge node IP's and various FQDN's. Alternatively you can test these settings locally by -editing your ``/etc/hosts``. Below is an example with a dummy domain ``os.foo.org`` and -dummy Ingress IP ``1.2.3.4``. - -:: - - A Records - - 1.2.3.4 horizon.os.foo.org - 1.2.3.4 neutron.os.foo.org - 1.2.3.4 keystone.os.foo.org - 1.2.3.4 nova.os.foo.org - 1.2.3.4 metadata.os.foo.org - 1.2.3.4 glance.os.foo.org - - -The default FQDN's for OpenStack-Helm are - -:: - - horizon.openstack.svc.cluster.local - neutron.openstack.svc.cluster.local - keystone.openstack.svc.cluster.local - nova.openstack.svc.cluster.local - metadata.openstack.svc.cluster.local - glance.openstack.svc.cluster.local - -We want to change the **public** configurations to match our DNS layouts above. In each Chart -``values.yaml`` is a ``endpoints`` configuration that has ``host_fqdn_override``'s for each API -that the Chart either produces or is dependent on. `Read more about how Endpoints are developed -<https://docs.openstack.org/openstack-helm/latest/devref/endpoints.html>`__. -Note while Glance Registry is listening on a Ingress http endpoint, you will not need to expose -the registry for external services. - - -Installation -============ - -Implementing the FQDN overrides **must** be done at install time. If you run these as helm upgrades, -Ingress will notice the updates though none of the endpoint build-out jobs will run again, -unless they are cleaned up manually or using a tool like Armada. - -Two similar options exist to set the FQDN overrides for External DNS mapping. - -**First**, edit the ``values.yaml`` for Neutron, Glance, Horizon, Keystone, and Nova. - -Using Horizon as an example, find the ``endpoints`` config. - -For ``identity`` and ``dashboard`` at ``host_fdqn_override.public`` replace ``null`` with the -value as ``keystone.os.foo.org`` and ``horizon.os.foo.org`` - -.. code:: bash - - endpoints: - cluster_domain_suffix: cluster.local - identity: - name: keystone - hosts: - default: keystone-api - public: keystone - host_fqdn_override: - default: null - public: keystone.os.foo.org - . - . - dashboard: - name: horizon - hosts: - default: horizon-int - public: horizon - host_fqdn_override: - default: null - public: horizon.os.foo.org - - -After making the configuration changes, run a ``make`` and then install as you would from -AIO or MultiNode instructions. - -**Second** option would be as ``--set`` flags when calling ``helm install`` - -Add to the Install steps these flags - also adding a shell environment variable to save on -repeat code. - -.. code-block:: shell - - export FQDN=os.foo.org - - helm install --name=horizon ./horizon --namespace=openstack \ - --set network.node_port.enabled=true \ - --set endpoints.dashboard.host_fqdn_override.public=horizon.$FQDN \ - --set endpoints.identity.host_fqdn_override.public=keystone.$FQDN - - - -Note if you need to make a DNS change, you will have to do uninstall (``helm delete <chart>``) -and install again. - -Once installed, access the API's or Dashboard at `http://horizon.os.foo.org` - - -Examples -======== - -Code examples below. - -If doing an `AIO install -<https://docs.openstack.org/openstack-helm/latest/install/developer/index.html>`__, -all the ``--set`` flags - -.. code-block:: shell - - export FQDN=os.foo.org - - helm install --name=keystone local/keystone --namespace=openstack \ - --set endpoints.identity.host_fqdn_override.public=keystone.$FQDN - - helm install --name=glance local/glance --namespace=openstack \ - --set storage=pvc \ - --set endpoints.image.host_fqdn_override.public=glance.$FQDN \ - --set endpoints.identity.host_fqdn_override.public=keystone.$FQDN - - helm install --name=nova local/nova --namespace=openstack \ - --values=./tools/overrides/mvp/nova.yaml \ - --set conf.nova.libvirt.virt_type=qemu \ - --set conf.nova.libvirt.cpu_mode=none \ - --set endpoints.compute.host_fqdn_override.public=nova.$FQDN \ - --set endpoints.compute_metadata.host_fqdn_override.public=metadata.$FQDN \ - --set endpoints.image.host_fqdn_override.public=glance.$FQDN \ - --set endpoints.network.host_fqdn_override.public=neutron.$FQDN \ - --set endpoints.identity.host_fqdn_override.public=keystone.$FQDN - - helm install --name=neutron local/neutron \ - --namespace=openstack --values=./tools/overrides/mvp/neutron-ovs.yaml \ - --set endpoints.network.host_fqdn_override.public=neutron.$FQDN \ - --set endpoints.compute.host_fqdn_override.public=nova.$FQDN \ - --set endpoints.identity.host_fqdn_override.public=keystone.$FQDN - - helm install --name=horizon local/horizon --namespace=openstack \ - --set=network.node_port.enabled=true \ - --set endpoints.dashboard.host_fqdn_override.public=horizon.$FQDN \ - --set endpoints.identity.host_fqdn_override.public=keystone.$FQDN - - - -Troubleshooting -=============== - -**Review the Ingress configuration.** - -Get the Nginx configuration from the Ingress Pod: - -.. code-block:: shell - - kubectl exec -it ingress-api-2210976527-92cq0 -n openstack -- cat /etc/nginx/nginx.conf - - -Look for *server* configuration with a *server_name* matching your desired FQDN - -:: - - server { - server_name nova.os.foo.org; - listen [::]:80; - set $proxy_upstream_name "-"; - location / { - set $proxy_upstream_name "openstack-nova-api-n-api"; - . - . - } - - - -**Check Chart Status** - -Get the ``helm status`` of your chart. - -.. code-block:: shell - - helm status keystone - - -Verify the *v1beta1/Ingress* resource has a Host with your FQDN value - -:: - - LAST DEPLOYED: Thu Sep 28 20:00:49 2017 - NAMESPACE: openstack - STATUS: DEPLOYED - - RESOURCES: - ==> v1beta1/Ingress - NAME HOSTS ADDRESS PORTS AGE - keystone keystone,keystone.os.foo.org 1.2.3.4 80 35m - - diff --git a/doc/source/install/index.rst b/doc/source/install/index.rst index d23689e5fe..d684e0e0d3 100644 --- a/doc/source/install/index.rst +++ b/doc/source/install/index.rst @@ -4,11 +4,14 @@ Installation Contents: .. toctree:: - :maxdepth: 2 + :maxdepth: 2 + + before_deployment + deploy_kubernetes + prepare_kubernetes + deploy_ceph + setup_openstack_client + deploy_ingress_controller + deploy_openstack_backend + deploy_openstack - common-requirements - developer/index - multinode - kubernetes-gate - ext-dns-fqdn - plugins/index diff --git a/doc/source/install/kubernetes-gate.rst b/doc/source/install/kubernetes-gate.rst deleted file mode 100644 index 3335a2d61e..0000000000 --- a/doc/source/install/kubernetes-gate.rst +++ /dev/null @@ -1,143 +0,0 @@ -===================== -Gate-Based Kubernetes -===================== - -Overview -======== - -You can use any Kubernetes deployment tool to bring up a working Kubernetes -cluster for use with OpenStack-Helm. This guide describes how to simply stand -up a multinode Kubernetes cluster via the OpenStack-Helm gate scripts, -which use KubeADM and Ansible. Although this cluster won't be -production-grade, it will serve as a quick starting point in a lab or -proof-of-concept environment. - -OpenStack-Helm-Infra KubeADM deployment -======================================= - -On the worker nodes: - -.. code-block:: shell - - #!/bin/bash - set -xe - sudo apt-get update - sudo apt-get install --no-install-recommends -y git - - -SSH-Key preparation -------------------- - -Create an ssh-key on the master node, and add the public key to each node that -you intend to join the cluster. - -.. note:: - 1. To generate the key you can use ``ssh-keygen -t rsa`` - 2. To copy the ssh key to each node, this can be accomplished with - the ``ssh-copy-id`` command, for example: *ssh-copy-id - ubuntu@192.168.122.178* - 3. Copy the key: ``sudo cp ~/.ssh/id_rsa /etc/openstack-helm/deploy-key.pem`` - 4. Set correct ownership: ``sudo chown ubuntu - /etc/openstack-helm/deploy-key.pem`` - - Test this by ssh'ing to a node and then executing a command with - 'sudo'. Neither operation should require a password. - -Clone the OpenStack-Helm Repos ------------------------------- - -Once the host has been configured the repos containing the OpenStack-Helm charts -should be cloned onto each node in the cluster: - -.. code-block:: shell - - #!/bin/bash - set -xe - - sudo chown -R ubuntu: /opt - git clone https://opendev.org/openstack/openstack-helm-infra.git /opt/openstack-helm-infra - git clone https://opendev.org/openstack/openstack-helm.git /opt/openstack-helm - - -Create an inventory file ------------------------- - -On the master node create an inventory file for the cluster: - -.. note:: - node_one, node_two and node_three below are all worker nodes, - children of the master node that the commands below are executed on. - -.. code-block:: shell - - #!/bin/bash - set -xe - cat > /opt/openstack-helm-infra/tools/gate/devel/multinode-inventory.yaml <<EOF - all: - children: - primary: - hosts: - node_one: - ansible_port: 22 - ansible_host: $node_one_ip - ansible_user: ubuntu - ansible_ssh_private_key_file: /etc/openstack-helm/deploy-key.pem - ansible_ssh_extra_args: -o StrictHostKeyChecking=no - nodes: - hosts: - node_two: - ansible_port: 22 - ansible_host: $node_two_ip - ansible_user: ubuntu - ansible_ssh_private_key_file: /etc/openstack-helm/deploy-key.pem - ansible_ssh_extra_args: -o StrictHostKeyChecking=no - node_three: - ansible_port: 22 - ansible_host: $node_three_ip - ansible_user: ubuntu - ansible_ssh_private_key_file: /etc/openstack-helm/deploy-key.pem - ansible_ssh_extra_args: -o StrictHostKeyChecking=no - EOF - -Create an environment file --------------------------- - -On the master node create an environment file for the cluster: - -.. code-block:: shell - - #!/bin/bash - set -xe - function net_default_iface { - sudo ip -4 route list 0/0 | awk '{ print $5; exit }' - } - cat > /opt/openstack-helm-infra/tools/gate/devel/multinode-vars.yaml <<EOF - kubernetes_network_default_device: $(net_default_iface) - EOF - -Additional configuration variables can be found `here -<https://github.com/openstack/openstack-helm-infra/blob/master/roles/deploy-kubeadm-aio-common/defaults/main.yml>`_. -In particular, ``kubernetes_cluster_pod_subnet`` can be used to override the -pod subnet set up by Calico (the default container SDN), if you have a -preexisting network that conflicts with the default pod subnet of 192.168.0.0/16. - -.. note:: - This installation, by default will use Google DNS servers, 8.8.8.8 or 8.8.4.4 - and updates resolv.conf. These DNS nameserver entries can be changed by - updating file ``/opt/openstack-helm-infra/tools/images/kubeadm-aio/assets/opt/playbooks/vars.yaml`` - under section ``external_dns_nameservers``. This change must be done on each - node in your cluster. - - -Run the playbooks ------------------ - -On the master node run the playbooks: - -.. code-block:: shell - - #!/bin/bash - set -xe - cd /opt/openstack-helm-infra - make dev-deploy setup-host multinode - make dev-deploy k8s multinode diff --git a/doc/source/install/multinode.rst b/doc/source/install/multinode.rst deleted file mode 100644 index bf39bfd246..0000000000 --- a/doc/source/install/multinode.rst +++ /dev/null @@ -1,331 +0,0 @@ -========= -Multinode -========= - -Overview -======== - -In order to drive towards a production-ready OpenStack solution, our -goal is to provide containerized, yet stable `persistent -volumes <https://kubernetes.io/docs/concepts/storage/persistent-volumes/>`_ -that Kubernetes can use to schedule applications that require state, -such as MariaDB (Galera). Although we assume that the project should -provide a "batteries included" approach towards persistent storage, we -want to allow operators to define their own solution as well. Examples -of this work will be documented in another section, however evidence of -this is found throughout the project. If you find any issues or gaps, -please create a `story <https://storyboard.openstack.org/#!/project/886>`_ -to track what can be done to improve our documentation. - -.. note:: - Please see the supported application versions outlined in the - `source variable file <https://github.com/openstack/openstack-helm-infra/blob/master/roles/build-images/defaults/main.yml>`_. - -Other versions and considerations (such as other CNI SDN providers), -config map data, and value overrides will be included in other -documentation as we explore these options further. - -The installation procedures below, will take an administrator from a new -``kubeadm`` installation to OpenStack-Helm deployment. - -.. note:: Many of the default container images that are referenced across - OpenStack-Helm charts are not intended for production use; for example, - while LOCI and Kolla can be used to produce production-grade images, their - public reference images are not prod-grade. In addition, some of the default - images use ``latest`` or ``master`` tags, which are moving targets and can - lead to unpredictable behavior. For production-like deployments, we - recommend building custom images, or at minimum caching a set of known - images, and incorporating them into OpenStack-Helm via values overrides. - -.. warning:: Until the Ubuntu kernel shipped with 16.04 supports CephFS - subvolume mounts by default the `HWE Kernel - <../troubleshooting/ubuntu-hwe-kernel.html>`__ is required to use CephFS. - -Kubernetes Preparation -====================== - -You can use any Kubernetes deployment tool to bring up a working Kubernetes -cluster for use with OpenStack-Helm. For production deployments, -please choose (and tune appropriately) a highly-resilient Kubernetes -distribution, e.g.: - -- `Airship <https://airshipit.org/>`_, a declarative open cloud - infrastructure platform -- `KubeADM <https://kubernetes.io/docs/setup/independent/high-availability/>`_, - the foundation of a number of Kubernetes installation solutions - -For a lab or proof-of-concept environment, the OpenStack-Helm gate scripts -can be used to quickly deploy a multinode Kubernetes cluster using KubeADM -and Ansible. Please refer to the deployment guide -`here <./kubernetes-gate.html>`__. - -Managing and configuring a Kubernetes cluster is beyond the scope -of OpenStack-Helm and this guide. - -Deploy OpenStack-Helm -===================== - -.. note:: - The following commands all assume that they are run from the - ``/opt/openstack-helm`` directory. - - -Setup Clients on the host and assemble the charts -------------------------------------------------- - -The OpenStack clients and Kubernetes RBAC rules, along with assembly of the -charts can be performed by running the following commands: - -.. literalinclude:: ../../../tools/deployment/multinode/010-setup-client.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/multinode/010-setup-client.sh - - -Deploy the ingress controller ------------------------------ - -.. code-block:: shell - - export OSH_DEPLOY_MULTINODE=True - -.. literalinclude:: ../../../tools/deployment/component/common/ingress.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - OSH_DEPLOY_MULTINODE=True ./tools/deployment/component/common/ingress.sh - -Create loopback devices for CEPH --------------------------------- - -Create two loopback devices for ceph as one disk for OSD data and other disk for -block DB and block WAL. -If loop0 and loop1 devices are busy in your case , feel free to change them in parameters -by using --ceph-osd-data and --ceph-osd-dbwal options. - -.. code-block:: shell - - ansible all -i /opt/openstack-helm-infra/tools/gate/devel/multinode-inventory.yaml -m shell -s -a "/opt/openstack-helm/tools/deployment/common/setup-ceph-loopback-device.sh --ceph-osd-data /dev/loop0 --ceph-osd-dbwal /dev/loop1" - -Deploy Ceph ------------ - -The script below configures Ceph to use loopback devices created in previous step as backend for ceph osds. -To configure a custom block device-based backend, please refer -to the ``ceph-osd`` `values.yaml <https://github.com/openstack/openstack-helm/blob/master/ceph-osd/values.yaml>`_. - -Additional information on Kubernetes Ceph-based integration can be found in -the documentation for the -`CephFS <https://github.com/kubernetes-incubator/external-storage/blob/master/ceph/cephfs/README.md>`_ -and `RBD <https://github.com/kubernetes-incubator/external-storage/blob/master/ceph/rbd/README.md>`_ -storage provisioners, as well as for the alternative -`NFS <https://github.com/kubernetes-incubator/external-storage/blob/master/nfs/README.md>`_ provisioner. - -.. warning:: The upstream Ceph image repository does not currently pin tags to - specific Ceph point releases. This can lead to unpredictable results - in long-lived deployments. In production scenarios, we strongly recommend - overriding the Ceph images to use either custom built images or controlled, - cached images. - -.. note:: - The `./tools/deployment/multinode/kube-node-subnet.sh` script requires docker - to run. - -.. literalinclude:: ../../../tools/deployment/multinode/030-ceph.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/multinode/030-ceph.sh - -Activate the openstack namespace to be able to use Ceph -------------------------------------------------------- - -.. literalinclude:: ../../../tools/deployment/multinode/040-ceph-ns-activate.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/multinode/040-ceph-ns-activate.sh - -Deploy MariaDB --------------- - -.. literalinclude:: ../../../tools/deployment/multinode/050-mariadb.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/multinode/050-mariadb.sh - -Deploy RabbitMQ ---------------- - -.. literalinclude:: ../../../tools/deployment/multinode/060-rabbitmq.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/multinode/060-rabbitmq.sh - -Deploy Memcached ----------------- - -.. literalinclude:: ../../../tools/deployment/multinode/070-memcached.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/multinode/070-memcached.sh - -Deploy Keystone ---------------- - -.. literalinclude:: ../../../tools/deployment/multinode/080-keystone.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/multinode/080-keystone.sh - -Deploy Rados Gateway for object store -------------------------------------- - -.. literalinclude:: ../../../tools/deployment/multinode/090-ceph-radosgateway.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/multinode/090-ceph-radosgateway.sh - -Deploy Glance -------------- - -.. literalinclude:: ../../../tools/deployment/multinode/100-glance.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/multinode/100-glance.sh - -Deploy Cinder -------------- - -.. literalinclude:: ../../../tools/deployment/multinode/110-cinder.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/multinode/110-cinder.sh - -Deploy OpenvSwitch ------------------- - -.. literalinclude:: ../../../tools/deployment/multinode/120-openvswitch.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/multinode/120-openvswitch.sh - -Deploy Libvirt --------------- - -.. literalinclude:: ../../../tools/deployment/multinode/130-libvirt.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/multinode/130-libvirt.sh - -Deploy Compute Kit (Nova and Neutron) -------------------------------------- - -.. literalinclude:: ../../../tools/deployment/multinode/140-compute-kit.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/multinode/140-compute-kit.sh - -Deploy Heat ------------ - -.. literalinclude:: ../../../tools/deployment/multinode/150-heat.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/multinode/150-heat.sh - -Deploy Barbican ---------------- - -.. literalinclude:: ../../../tools/deployment/multinode/160-barbican.sh - :language: shell - :lines: 1,17- - -Alternatively, this step can be performed by running the script directly: - -.. code-block:: shell - - ./tools/deployment/multinode/160-barbican.sh - -Configure OpenStack -------------------- - -Configuring OpenStack for a particular production use-case is beyond the scope -of this guide. Please refer to the -OpenStack `Configuration <https://docs.openstack.org/latest/configuration/>`_ -documentation for your selected version of OpenStack to determine -what additional values overrides should be -provided to the OpenStack-Helm charts to ensure appropriate networking, -security, etc. is in place. diff --git a/doc/source/install/plugins/deploy-tap-as-a-service-neutron-plugin.rst b/doc/source/install/plugins/deploy-tap-as-a-service-neutron-plugin.rst deleted file mode 100644 index ece14abfe3..0000000000 --- a/doc/source/install/plugins/deploy-tap-as-a-service-neutron-plugin.rst +++ /dev/null @@ -1,339 +0,0 @@ -.. - This work is licensed under a Creative Commons Attribution 3.0 Unported - License. - - http://creativecommons.org/licenses/by/3.0/legalcode - -.. - -========================================================== -Deploy tap-as-a-service (TaaS) Neutron / Dashboard plugin -========================================================== - -This guide explains how to deploy tap-as-a-service (TaaS) Neutron plugin and -TaaS Dashboard plugin in Neutron and Horizon charts respectively. - -TaaS plugin provides a mechanism to mirror certain traffic (for example tagged -with specific VLANs) from a source VM to any traffic analyzer VM. When packet -will be forwarded, the original value of source and target ip/ports information -will not be altered and the system administrator will be able to run, for ex. -tcpdump, on the target VM to trace these packets. - -For more details, refer to TaaS specification: Tap-as-a-service_. - -.. _Tap-as-a-service: https://github.com/openstack/tap-as-a-service/blob/master/specs/mitaka/tap-as-a-service.rst - - -TaaS Architecture -================== - -As any other Neutron plugin, TaaS neutron plugin functionality consists of -following modules: - -.. figure:: figures/taas-architecture.png - :alt: Neutron TaaS Architecture - -**TaaS Plugin**: This is the front-end of TaaS which runs on controller node -(Neutron server). This serves TaaS APIs and stores/retrieves TaaS configuration -state to/from Neutron TaaS DB. - -**TaaS Agent, TaaS OVS Driver and TaaS SR-IOV Driver**: This forms the back-end -of TaaS which runs as a ML2 agent extension on compute nodes. It handles the RPC -calls made by TaaS Plugin and configures the mechanism driver, i.e. OpenVSwitch -or SR-IOV Nic Switch. - -**TaaS Dashboard Plugin**: Horizon Plugin which adds GUI panels for TaaS -resources in the Horizon Dashboard. - - -Prepare LOCI images -====================== - -Before deploying TaaS and/or TaaS Dashboard, it needs to be added in Neutron -and/or Horizon LOCI images. - -This is a two step process, i.e. - -#. Prepare a requirements LOCI image with Neutron TaaS and TaaS Dashboard code - installed. - -#. Prepare Neutron or Horizon LOCI image using this requirements image as - :code:`docker build --build-arg WHEELS` command argument. - -Requirements LOCI image -------------------------- - -* Create a patchset for ``openstack/requirements`` repo - - Add TaaS and TaaS dashboard dependencies in :code:`upper-constraints.txt` - file in :code:`openstack/requirements` repo, i.e. - https://opendev.org/openstack/requirements - - .. path upper-constraints - .. code-block:: none - - git+https://opendev.org/openstack/tap-as-a-service@master#egg=tap-as-a-service - git+https://opendev.org/openstack/tap-as-a-service-dashboard@master#egg=tap-as-a-service-dashboard - - .. end - - For example if gerrit refspec for this commit is "refs/changes/xx/xxxxxx/x", - so export the :code:`REQUIREMENTS_REF_SPEC` variable as follows: - - .. path REQUIREMENTS_REF_SPEC - .. code-block:: bash - - export REQUIREMENTS_REF_SPEC="refs/changes/xx/xxxxxx/x" - - .. end - -* Build the requirements LOCI image using above commit - - Use it as ``docker build --build-arg PROJECT_REF=${REQUIREMENTS_REF_SPEC}`` - command argument to build the requirements LOCI image. - - -Neutron and Horizon LOCI images ---------------------------------- - -* Create a patchset for ``openstack/neutron`` repo - - Add TaaS dependency in ``requirements.txt`` file in ``openstack/neutron`` - repo, i.e. https://opendev.org/openstack/neutron - - .. path patchset-neutron - .. code-block:: none - - tap-as-a-service - - .. end - - For example if gerrit refspec for this commit is "refs/changes/xx/xxxxxx/x"; - so export the :code:`NEUTRON_REF_SPEC` variable as follows: - - .. path patchset-neutron-export - .. code-block:: bash - - export NEUTRON_REF_SPEC="refs/changes/xx/xxxxxx/x" - - .. end - -* Create a patchset for ``openstack/horizon`` repo - - Add TaaS Dashboard dependency in ``requirements.txt`` file in - ``openstack/horizon`` repo, i.e. https://opendev.org/openstack/horizon - - .. path patchset-horizon - .. code-block:: none - - tap-as-a-service-dashboard - - .. end - - For example if gerrit refspec for this commit is "refs/changes/xx/xxxxxx/x"; - so export the :code:`HORIZON_REF_SPEC` variable as follows: - - .. path patchset-horizon-export - .. code-block:: bash - - export HORIZON_REF_SPEC="refs/changes/xx/xxxxxx/x" - - .. end - -* Putting it all together - - Apart from the variables above with gerrit refspec values, additionally - export following environment variables with values as applicable: - - .. path other-env-export - .. code-block:: bash - - export OPENSTACK_VERSION="stable/ocata" - export PRIVATE_REPO="docker.io/username" - - .. end - - Use above gerrit commits to prepare the LOCI images using following script: - - .. path main-script - .. code-block:: bash - - #!/bin/bash - set -ex - - # export following variables with applicable values before invoking the script - #---------- - : ${OPENSTACK_VERSION:="stable/ocata"} - : ${REQUIREMENTS_REF_SPEC:=""} - : ${NEUTRON_REF_SPEC:=""} - : ${HORIZON_REF_SPEC:=""} - : ${PRIVATE_REPO:="docker.io/username"} # Replace with your own dockerhub repo - #---------- - - IMAGE_TAG="${OPENSTACK_VERSION#*/}" - REGEX_GERRIT_REF_SPEC="^refs" - - [[ ${REQUIREMENTS_REF_SPEC} =~ ${REGEX_GERRIT_REF_SPEC} ]] || - (echo "Please set a proper value for REQUIREMENTS_REF_SPEC env variable" && exit) - - [[ ${NEUTRON_REF_SPEC} =~ ${REGEX_GERRIT_REF_SPEC} ]] || - (echo "Please set a proper value for NEUTRON_REF_SPEC env variable" && exit) - - [[ ${HORIZON_REF_SPEC} =~ ${REGEX_GERRIT_REF_SPEC} ]] || - (echo "Please set a proper value for HORIZON_REF_SPEC env variable" && exit) - - # Login to private-repo : provide login password when asked - sudo docker login - - sudo docker run -d \ - --name docker-in-docker \ - --privileged=true \ - --net=host \ - -v /var/lib/docker \ - -v ${HOME}/.docker/config.json:/root/.docker/config.json:ro\ - docker.io/docker:17.07.0-dind \ - dockerd \ - --pidfile=/var/run/docker.pid \ - --host=unix:///var/run/docker.sock \ - --storage-driver=overlay2 - sudo docker exec docker-in-docker apk update - sudo docker exec docker-in-docker apk add git - - # Prepare Requirements image - sudo docker exec docker-in-docker docker build --force-rm --pull --no-cache \ - https://opendev.org/openstack/loci.git \ - --network host \ - --build-arg FROM=gcr.io/google_containers/ubuntu-slim:0.14 \ - --build-arg PROJECT=requirements \ - --build-arg PROJECT_REF=${REQUIREMENTS_REF_SPEC} \ - --tag ${PRIVATE_REPO}/requirements:${IMAGE_TAG} - sudo docker exec docker-in-docker docker push ${PRIVATE_REPO}/requirements:${IMAGE_TAG} - - # Prepare Neutron image - sudo docker exec docker-in-docker docker build --force-rm --pull --no-cache \ - https://opendev.org/openstack/loci.git \ - --build-arg PROJECT=neutron \ - --build-arg PROJECT_REF=${NEUTRON_REF_SPEC} \ - --build-arg FROM=gcr.io/google_containers/ubuntu-slim:0.14 \ - --build-arg PROFILES="fluent neutron linuxbridge openvswitch" \ - --build-arg PIP_PACKAGES="pycrypto" \ - --build-arg WHEELS=${PRIVATE_REPO}/requirements:${IMAGE_TAG} \ - --tag ${PRIVATE_REPO}/neutron:${IMAGE_TAG} - sudo docker exec docker-in-docker docker push ${PRIVATE_REPO}/neutron:${IMAGE_TAG} - - # Prepare Neutron sriov image - sudo docker exec docker-in-docker docker build --force-rm --pull --no-cache \ - https://opendev.org/openstack/loci.git \ - --build-arg PROJECT=neutron \ - --build-arg PROJECT_REF=${NEUTRON_REF_SPEC} \ - --build-arg FROM=docker.io/ubuntu:18.04 \ - --build-arg PROFILES="fluent neutron linuxbridge openvswitch" \ - --build-arg PIP_PACKAGES="pycrypto" \ - --build-arg DIST_PACKAGES="ethtool lshw" \ - --build-arg WHEELS=${PRIVATE_REPO}/requirements:${IMAGE_TAG} \ - --tag ${PRIVATE_REPO}/neutron:${IMAGE_TAG}-sriov-1804 - sudo docker exec docker-in-docker docker push ${PRIVATE_REPO}/neutron:${IMAGE_TAG}-sriov-1804 - - # Prepare Horizon image - sudo docker exec docker-in-docker docker build --force-rm --pull --no-cache \ - https://opendev.org/openstack/loci.git \ - --build-arg PROJECT=horizon \ - --build-arg PROJECT_REF=${HORIZON_REF_SPEC} \ - --build-arg FROM=gcr.io/google_containers/ubuntu-slim:0.14 \ - --build-arg PROFILES="fluent horizon apache" \ - --build-arg PIP_PACKAGES="pycrypto" \ - --build-arg WHEELS=${PRIVATE_REPO}/requirements:${IMAGE_TAG} \ - --tag ${PRIVATE_REPO}/horizon:${IMAGE_TAG} - sudo docker exec docker-in-docker docker push ${PRIVATE_REPO}/horizon:${IMAGE_TAG} - - .. end - - -Deploy TaaS Plugin -================== - -Override images in Neutron chart ---------------------------------- - -Override the :code:`images` section parameters for Neutron chart with the -custom LOCI image's tag, prepared as explained in above sections. - -.. code-block:: yaml - - images: - tags: - neutron_db_sync: ${PRIVATE_REPO}/neutron:ocata - neutron_server: ${PRIVATE_REPO}/neutron:ocata - neutron_dhcp: ${PRIVATE_REPO}/neutron:ocata - neutron_metadata: ${PRIVATE_REPO}/neutron:ocata - neutron_l3: ${PRIVATE_REPO}/neutron:ocata - neutron_openvswitch_agent: ${PRIVATE_REPO}/neutron:ocata - neutron_linuxbridge_agent: ${PRIVATE_REPO}/neutron:ocata - neutron_sriov_agent: ${PRIVATE_REPO}/neutron:ocata-sriov-1804 - neutron_sriov_agent_init: ${PRIVATE_REPO}/neutron:ocata-sriov-1804 - -Configure TaaS in Neutron chart --------------------------------- - -While deploying neutron-server and L2 agents, TaaS should be enabled in -``conf: neutron`` section to add TaaS as a service plugin; in ``conf: plugins`` -section to add TaaS as a L2 agent extension; in ``conf: taas_plugin`` section -to configure the ``service_provider`` endpoint used by Neutron TaaS plugin: - -.. code-block:: yaml - - conf: - neutron: - DEFAULT: - service_plugins: taas - plugins: - ml2_conf: - agent: - extensions: taas - taas: - taas: - enabled: True - taas_plugin: - service_providers: - service_provider: TAAS:TAAS:neutron_taas.services.taas.service_drivers.taas_rpc.TaasRpcDriver:default - - -Deploy TaaS Dashboard Plugin -============================ - -TaaS dashboard plugin can be deployed simply by using custom LOCI images having -TaaS Dashboard code installed (as explained in above sections), i.e. override -the :code:`images` section parameters for Horizon charts: - -.. code-block:: yaml - - images: - tags: - horizon_db_sync: ${PRIVATE_REPO}/horizon:ocata - horizon: ${PRIVATE_REPO}/horizon:ocata - - -Set log level for TaaS -====================== - -Default log level for Neutron TaaS is :code:`INFO`. For changing it, override -following parameter: - -.. code-block:: yaml - - conf: - logging: - logger_neutron_taas: - level: INFO - - -References -========== -#. Neutron TaaS support in Openstack-Helm commits: - - - https://review.openstack.org/#/c/597200/ - - https://review.openstack.org/#/c/607392/ - -#. Add TaaS panel to Horizon Dashboard: - - - https://review.openstack.org/#/c/621606/ diff --git a/doc/source/install/plugins/figures/taas-architecture.png b/doc/source/install/plugins/figures/taas-architecture.png deleted file mode 100644 index a6ad36315cfc0420041454abaf98e773d54439c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 98682 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 Q7w|_~Tme`sY83px0F;1}u>b%7 diff --git a/doc/source/install/plugins/index.rst b/doc/source/install/plugins/index.rst deleted file mode 100644 index d09fa58b98..0000000000 --- a/doc/source/install/plugins/index.rst +++ /dev/null @@ -1,9 +0,0 @@ -Plugins -======== - -Contents: - -.. toctree:: - :maxdepth: 2 - - deploy-tap-as-a-service-neutron-plugin diff --git a/doc/source/install/prepare_kubernetes.rst b/doc/source/install/prepare_kubernetes.rst new file mode 100644 index 0000000000..2b5a920a7c --- /dev/null +++ b/doc/source/install/prepare_kubernetes.rst @@ -0,0 +1,28 @@ +Prepare Kubernetes +================== + +In this section we assume you have a working Kubernetes cluster and +Kubectl and Helm properly configured to interact with the cluster. + +Before deploying OpenStack components using OpenStack-Helm you have to set +labels on Kubernetes worker nodes which are used as node selectors. + +Also necessary namespaces must be created. + +You can use the `prepare-k8s.sh`_ script as an example of how to prepare +the Kubernetes cluster for OpenStack deployment. The script is assumed to be run +from the openstack-helm repository + +.. code-block:: bash + + cd ~/osh/openstack-helm + ./tools/deployment/common/prepare-k8s.sh + + +.. note:: + Pay attention that in the above script we set labels on all Kubernetes nodes including + Kubernetes control plane nodes which are usually not aimed to run workload pods + (OpenStack in our case). So you have to either untaint control plane nodes or modify the + `prepare-k8s.sh`_ script so it sets labels only on the worker nodes. + +.. _prepare-k8s.sh: https://opendev.org/openstack/openstack-helm/src/branch/master/tools/deployment/common/prepare-k8s.sh diff --git a/doc/source/install/setup_openstack_client.rst b/doc/source/install/setup_openstack_client.rst new file mode 100644 index 0000000000..d39d402220 --- /dev/null +++ b/doc/source/install/setup_openstack_client.rst @@ -0,0 +1,35 @@ +Setup OpenStack client +====================== + +The OpenStack client software is a crucial tool for interacting +with OpenStack services. In certain OpenStack-Helm deployment +scripts, the OpenStack client software is utilized to conduct +essential checks during deployment. Therefore, installing the +OpenStack client on the developer's machine is a vital step. + +The script `setup-client.sh`_ can be used to setup the OpenStack +client. + +.. code-block:: bash + + cd ~/osh/openstack-helm + ./tools/deployment/common/setup-client.sh + +At this point you have to keep in mind that the above script configures +OpenStack client so it uses internal Kubernetes FQDNs like +`keystone.openstack.svc.cluster.local`. In order to be able to resolve these +internal names you have to configure the Kubernetes authoritative DNS server +(CoreDNS) to work as a recursive resolver and then add its IP (`10.96.0.10` by default) +to `/etc/resolv.conf`. This is only going to work when you try to access +to OpenStack services from one of Kubernetes nodes because IPs from the +Kubernetes service network are routed only between Kubernetes nodes. + +If you wish to access OpenStack services from outside the Kubernetes cluster, +you need to expose the OpenStack Ingress controller using an IP address accessible +from outside the Kubernetes cluster, typically achieved through solutions like +`MetalLB`_ or similar tools. In this scenario, you should also ensure that you +have set up proper FQDN resolution to map to the external IP address and +create the necessary Ingress objects for the associated FQDN. + +.. _setup-client.sh: https://opendev.org/openstack/openstack-helm/src/branch/master/tools/deployment/common/setup-client.sh +.. _MetalLB: https://metallb.universe.tf