10 KiB
Kubernetes prerequisites
Ingress controller
Ingress controller when deploying OpenStack on Kubernetes is essential to ensure proper external access for the OpenStack services.
We recommend using the ingress-nginx because it is simple and provides all necessary features. It utilizes Nginx as a reverse proxy backend. Here is how to deploy it.
First, let's create a namespace for the OpenStack workloads. The ingress controller must be deployed in the same namespace because OpenStack-Helm charts create service resources pointing to the ingress controller pods which in turn redirect traffic to particular Openstack API pods.
tee > /tmp/openstack_namespace.yaml <<EOF
apiVersion: v1
kind: Namespace
metadata:
name: openstack
EOF
kubectl apply -f /tmp/openstack_namespace.yaml
Next, deploy the ingress controller in the openstack
namespace:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx \
--version="4.8.3" \
--namespace=openstack \
--set controller.kind=Deployment \
--set controller.admissionWebhooks.enabled="false" \
--set controller.scope.enabled="true" \
--set controller.service.enabled="false" \
--set controller.ingressClassResource.name=nginx \
--set controller.ingressClassResource.controllerValue="k8s.io/ingress-nginx" \
--set controller.ingressClassResource.default="false" \
--set controller.ingressClass=nginx \
--set controller.labels.app=ingress-api
You can deploy any other ingress controller that suits your needs
best. See for example the list of available ingress
controllers. Ensure that the ingress controller pods are deployed
with the app: ingress-api
label which is used by the
OpenStack-Helm as a selector for the Kubernetes service resources.
For example, the OpenStack-Helm keystone
chart by
default creates a service that redirects traffic to the ingress
controller pods selected using the app: ingress-api
label.
Then it also creates an Ingress
resource which the ingress
controller then uses to configure its reverse proxy backend (Nginx)
which eventually routes the traffic to the Keystone API service which
works as an endpoint for Keystone API pods.
Note
For exposing the OpenStack services to the external world, we can a
create service of type LoadBalancer
or
NodePort
with the selector pointing to the ingress
controller pods.
MetalLB
MetalLB is a load-balancer for bare metal Kubernetes clusters levereging L2/L3 protocols. This is a popular way of exposing the web applications running in Kubernetes to the external world.
The following commands can be used to deploy MetalLB:
tee > /tmp/metallb_system_namespace.yaml <<EOF
apiVersion: v1
kind: Namespace
metadata:
name: metallb-system
EOF
kubectl apply -f /tmp/metallb_system_namespace.yaml
helm repo add metallb https://metallb.github.io/metallb
helm install metallb metallb/metallb -n metallb-system
Now it is necessary to configure the MetalLB IP address pool and the IP address advertisement. The MetalLB custom resources are used for this:
tee > /tmp/metallb_ipaddresspool.yaml <<EOF
---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: public
namespace: metallb-system
spec:
addresses:
- "172.24.128.0/24"
EOF
kubectl apply -f /tmp/metallb_ipaddresspool.yaml
tee > /tmp/metallb_l2advertisement.yaml <<EOF
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: public
namespace: metallb-system
spec:
ipAddressPools:
- public
EOF
kubectl apply -f /tmp/metallb_l2advertisement.yaml
Next, let's create a service of type LoadBalancer
which
will the public endpoint for all OpenStack services that we will later
deploy. The MetalLB will assign an IP address to it (we can assinged a
dedicated IP using annotations):
tee > /tmp/openstack_endpoint_service.yaml <<EOF
---
kind: Service
apiVersion: v1
metadata:
name: public-openstack
namespace: openstack
annotations:
metallb.universe.tf/loadBalancerIPs: "172.24.128.100"
spec:
externalTrafficPolicy: Cluster
type: LoadBalancer
selector:
app: ingress-api
ports:
- name: http
port: 80
- name: https
port: 443
EOF
kubectl apply -f /tmp/openstack_endpoint_service.yaml
This service will redirect the traffic to the ingress controller pods
(see the app: ingress-api
selector). OpenStack-Helm charts
create Ingress
resources which are used by the ingress
controller to configure the reverse proxy backend so that the traffic
eventually goes to particular Openstack API pods.
By default, the Ingress
objects will only contain rules
for the openstack.svc.cluster.local
DNS domain. This is the
internal Kubernetes domain and it is not supposed to be used outside the
cluster.
You can use the host_fqdn_override
for the endpoints to
set an alternate hostname using a service like sslip.io. Assuming your services are
exposed at 172.24.128.100
as is referenced in the Service
above, you could use
<service>.172-24-128-100.sslip.io
Here is an example of how to set the host_fqdn_override
for the Keystone chart:
endpoints:
identity:
host_fqdn_override:
public:
host: "keystone.172-24-128-100.sslip.io"
Note
In production environments you probably choose to use a different DNS
domain for public OpenStack endpoints. This is easy to achieve by
setting the necessary chart values. All Openstack-Helm charts values
have the endpoints
section where you can specify the
host_fqdn_override
. In this case a chart will create
additional Ingress
resources to handle the external domain
name and also the Keystone endpoint catalog will be updated.
Ceph
Ceph is a highly scalable and fault-tolerant distributed storage system. It offers object storage, block storage, and file storage capabilities, making it a versatile solution for various storage needs.
Kubernetes CSI (Container Storage Interface) allows storage providers like Ceph to implement their drivers, so that Kubernetes can use the CSI driver to provision and manage volumes which can be used by stateful applications deployed on top of Kubernetes to store their data. In the context of OpenStack running in Kubernetes, the Ceph is used as a storage backend for services like MariaDB, RabbitMQ and other services that require persistent storage. By default OpenStack-Helm stateful sets expect to find a storage class named general.
At the same time, Ceph provides the RBD API, which applications can utilize directly to create and mount block devices distributed across the Ceph cluster. For example the OpenStack Cinder utilizes this Ceph capability to offer persistent block devices to virtual machines managed by the OpenStack Nova.
The recommended way to manage Ceph on top of Kubernetes is by means of the Rook operator. The Rook project provides the Helm chart to deploy the Rook operator which extends the Kubernetes API adding CRDs that enable managing Ceph clusters via Kuberntes custom objects. There is also another Helm chart that facilitates deploying Ceph clusters using Rook custom resources.
For details please refer to the Rook documentation and the charts.
Note
The following script ceph-rook.sh (recommended for testing only) can be used as an example of how to deploy the Rook Ceph operator and a Ceph cluster using the Rook charts. Please note that the script places Ceph OSDs on loopback devices which is not recommended for production. The loopback devices must exist before using this script.
Once the Ceph cluster is deployed, the next step is to enable using
it for services depoyed by OpenStack-Helm charts. The
ceph-adapter-rook
chart provides the necessary
functionality to do this. The chart will prepare Kubernetes secret
resources containing Ceph client keys/configs that are later used to
interface with the Ceph cluster.
Here we assume the Ceph cluster is deployed in the ceph
namespace.
helm upgrade --install ceph-adapter-rook openstack-helm-infra/ceph-adapter-rook \
--namespace=openstack
helm osh wait-for-pods openstack
Node labels
Openstack-Helm charts rely on Kubernetes node labels to determine which nodes are suitable for running specific OpenStack components.
The following sets labels on all the Kubernetes nodes in the cluster including control plane nodes but you can choose to label only a subset of nodes where you want to run OpenStack:
kubectl label --overwrite nodes --all openstack-control-plane=enabled
kubectl label --overwrite nodes --all openstack-compute-node=enabled
kubectl label --overwrite nodes --all openvswitch=enabled
kubectl label --overwrite nodes --all linuxbridge=enabled
Note
The control plane nodes are tainted by default to prevent scheduling of pods on them. You can untaint the control plane nodes using the following command:
kubectl taint nodes -l 'node-role.kubernetes.io/control-plane' node-role.kubernetes.io/control-plane-