Skip to content

Commit

Permalink
feat: add installation of OpenStack Ironic
Browse files Browse the repository at this point in the history
Create an initial configuration to install OpenStack Ironic. The PXE
service right now binds to the host's network device so this
configuration won't work on all systems but it's a first step in getting
this deployed.
  • Loading branch information
cardoe committed Feb 27, 2024
1 parent 86bcff1 commit a12c8b4
Show file tree
Hide file tree
Showing 8 changed files with 354 additions and 0 deletions.
16 changes: 16 additions & 0 deletions apps/components/ironic.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: ironic
spec:
project: understack
source:
repoURL: https://github.com/rackerlabs/understack.git
path: components/13-ironic/
targetRevision: HEAD
destination:
server: "https://kubernetes.default.svc"
namespace: openstack
syncPolicy:
automated:
selfHeal: true
1 change: 1 addition & 0 deletions apps/components/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ resources:
- keystone.yaml
- argo-workflows.yaml
- argo-events.yaml
- ironic.yaml
38 changes: 38 additions & 0 deletions components/01-secrets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,44 @@ for skrt in $(find . -name "secret-keystone*.yaml" -depth 1); do
done
```

## Ironic

Generate the necessary secrets for OpenStack Ironic.

```bash
kubectl --namespace openstack \
create secret generic ironic-rabbitmq-password \
--type Opaque \
--from-literal=username="ironic" \
--from-literal=password="$($(git rev-parse --show-toplevel)/scripts/pwgen.sh)" \
--dry-run -o yaml > secret-ironic-rabbitmq-password.yaml
kubectl --namespace openstack \
create secret generic ironic-db-password \
--type Opaque \
--from-literal=password="$($(git rev-parse --show-toplevel)/scripts/pwgen.sh)" \
--dry-run -o yaml > secret-ironic-db-password.yaml
kubectl --namespace openstack \
create secret generic ironic-keystone-password \
--type Opaque \
--from-literal=username="ironic" \
--from-literal=password="$($(git rev-parse --show-toplevel)/scripts/pwgen.sh)" \
--dry-run -o yaml > secret-ironic-keystone-password.yaml
```

Now let's seal them.

```bash
for skrt in $(find . -name "secret-ironic*.yaml" -depth 1); do
encskrt=$(echo "${skrt}" | sed -e 's/secret-/components\/01-secrets\/encrypted-/')
kubeseal \
--scope cluster-wide \
--allow-empty-data \
-o yaml \
-f "${skrt}" \
-w "${encskrt}"
done
```

## Generate Kustomize for the Install

Now generate the kustomize for this.
Expand Down
81 changes: 81 additions & 0 deletions components/13-ironic/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# OpenStack Ironic

So unfortunately OpenStack Helm doesn't publish helm charts that can be consumed like
regular helm charts. You must instead clone two of their git repos side by side and
build the dependencies manually. They additionally don't split out secrets but instead
template them into giant config files or even executable scripts that then get stored
as secrets, a clear violation of <https://12factor.net>. As a result we cannot store
a declarative config of Keystone and allow users to supply their own secrets.

Due to the above issues, for now we'll skip the ArgoCD ability for this deployment.

## Get OpenStack Helm Ready

You may have done this for another OpenStack component and can share the same
git clones. This assumes you're doing this from the top level of this repo.

```bash
# clone the two repos because they reference the infra one as a relative path
# so you can't use real helm commands
git clone https://github.com/openstack/openstack-helm
git clone https://github.com/openstack/openstack-helm-infra
# update the dependencies cause we can't use real helm references
./scripts/openstack-helm-depend-sync.sh ironic
```

## Deploy Ironic

NOTE: The PXE service currently has the host network devices mapped into
the container. You'll have to edit the [aio-values.yaml](./aio-values.yaml)
file in the `network.pxe.device` field to the correct value for your
server to have this start up successfully.

Since we cannot refer to the secrets by name, we must look them up live from the cluster
so that we can injected them into the templated configs. Upstream should really allow
secrets to be passed by reference. As a result of this we cannot use GitOps to generate
these charts and have them applied to the cluster.

Secrets Reference:

- keystone-admin is the admin password for creating other users, services and endpoints.
It is used by the initialization / bootstrap jobs.
- ironic-db-password is the DB password for the ironic DB user.
- ironic-rabbitmq-password is the RabbitMQ password for the ironic user.
- ironic-keystone-password is the Keystone service account for the Ironic service, this
is created by the ks-user job using the keystone-admin credential.

```bash
helm --namespace openstack template \
ironic \
./openstack-helm/ironic/ \
-f components/13-ironic/aio-values.yaml \
--set endpoints.identity.auth.admin.password="$(kubectl --namespace openstack get secret keystone-admin -o jsonpath='{.data.password}' | base64 -d)" \
--set endpoints.oslo_db.auth.ironic.password="$(kubectl --namespace openstack get secret ironic-db-password -o jsonpath='{.data.password}' | base64 -d)" \
--set endpoints.oslo_messaging.auth.ironic.password="$(kubectl --namespace openstack get secret ironic-rabbitmq-password -o jsonpath='{.data.password}' | base64 -d)" \
--set endpoints.identity.auth.ironic.password="$(kubeclt --namespace openstack get secret ironic-keystone-password -o jsonpath='{.data.password}' | base64 -d)" \
--post-renderer $(git rev-parse --show-toplevel)/scripts/openstack-helm-sealed-secrets.sh \
| kubectl -n openstack apply -f -
```

At this point Ironic will go through some initialization and start up.

## Validating Ironic

You can run an OpenStack client in the cluster to validate it is running correctly.

```bash
# start up a pod with the client
kubectl -n openstack apply -f https://raw.githubusercontent.com/rackerlabs/genestack/main/manifests/utils/utils-openstack-client-admin.yaml
```

Show the driver list

```bash
kubectl exec -it openstack-admin-client -n openstack -- openstack baremetal driver list
```

Show the conductor list

```bash
kubectl exec -it openstack-admin-client -n openstack -- openstack baremetal conductor list
```
100 changes: 100 additions & 0 deletions components/13-ironic/aio-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---

images:
tags:
ironic_manage_cleaning_network: "docker.io/openstackhelm/heat:2023.1-ubuntu_jammy"
ironic_retrive_cleaning_network: "docker.io/openstackhelm/heat:2023.1-ubuntu_jammy"
ironic_retrive_swift_config: "docker.io/openstackhelm/heat:2023.1-ubuntu_jammy"
bootstrap: "docker.io/openstackhelm/heat:2023.1-ubuntu_jammy"
db_init: "docker.io/openstackhelm/heat:2023.1-ubuntu_jammy"
db_drop: "docker.io/openstackhelm/heat:2023.1-ubuntu_jammy"
ironic_db_sync: "docker.io/openstackhelm/ironic:2023.1-ubuntu_jammy"
ironic_api: "docker.io/openstackhelm/ironic:2023.1-ubuntu_jammy"
ironic_conductor: "docker.io/openstackhelm/ironic:2023.1-ubuntu_jammy"
ironic_pxe: "docker.io/openstackhelm/ironic:2023.1-ubuntu_jammy"
ironic_pxe_init: "docker.io/openstackhelm/ironic:2023.1-ubuntu_jammy"
ironic_pxe_http: docker.io/nginx:1.13.3
ks_user: "docker.io/openstackhelm/heat:2023.1-ubuntu_jammy"
ks_service: "docker.io/openstackhelm/heat:2023.1-ubuntu_jammy"
ks_endpoints: "docker.io/openstackhelm/heat:2023.1-ubuntu_jammy"
rabbit_init: docker.io/rabbitmq:3.7-management
dep_check: quay.io/airshipit/kubernetes-entrypoint:v1.0.0
image_repo_sync: docker.io/docker:17.07.0
pull_policy: "IfNotPresent"
local_registry:
active: false
exclude:
- dep_check
- image_repo_sync

bootstrap:
image:
enabled: false
openstack:
enabled: false
network:
enabled: false
openstack:
enabled: false
object_store:
enabled: false
openstack:
enabled: false

conf:
ironic:
conductor:
automated_clean: false
dhcp:
dhcp_provider: none

network:
api:
ingress:
public: true
classes:
namespace: "nginx"
cluster: "nginx-openstack"
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
external_policy_local: false
node_port:
enabled: false
pxe:
device: ens1f0

dependencies:
dynamic:
common:
local_image_registry:
jobs: null
static:
api:
jobs:
- ironic-db-sync
- ironic-ks-user
- ironic-ks-endpoints
services:
- endpoint: internal
service: oslo_db
- endpoint: internal
service: oslo_messaging
conductor:
jobs:
- ironic-db-sync
- ironic-ks-user
- ironic-ks-endpoints
services:
- endpoint: internal
service: oslo_db
- endpoint: internal
service: oslo_messaging

manifests:
job_db_init: false
job_db_drop: false
job_manage_cleaning_network: false
job_rabbit_init: false
secret_db: false
secret_rabbitmq: false
secret_registry: false
52 changes: 52 additions & 0 deletions components/13-ironic/ironic-mariadb-db.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
apiVersion: mariadb.mmontes.io/v1alpha1
kind: Database
metadata:
name: ironic
namespace: openstack
spec:
# If you want the database to be created with a different name than the resource name
# name: data-custom
mariaDbRef:
name: mariadb # name of the MariaDB kind
waitForIt: true
characterSet: utf8
collate: utf8_general_ci
retryInterval: 5s
---
apiVersion: mariadb.mmontes.io/v1alpha1
kind: User
metadata:
name: ironic
namespace: openstack
spec:
# If you want the user to be created with a different name than the resource name
# name: user-custom
mariaDbRef:
name: mariadb # name of the MariaDB kind
waitForIt: true
passwordSecretKeyRef:
name: ironic-db-password
key: password
# This field is immutable and defaults to 10, 0 means unlimited.
maxUserConnections: 0
host: "%"
retryInterval: 5s
---
apiVersion: mariadb.mmontes.io/v1alpha1
kind: Grant
metadata:
name: ironic-grant
namespace: openstack
spec:
mariaDbRef:
name: mariadb # name of the MariaDB kind
waitForIt: true
privileges:
- "ALL"
database: "ironic"
table: "*"
username: ironic
grantOption: true
host: "%"
retryInterval: 5s
59 changes: 59 additions & 0 deletions components/13-ironic/ironic-rabbitmq-queue.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
apiVersion: rabbitmq.com/v1beta1
kind: User
metadata:
name: ironic
namespace: openstack
spec:
tags:
- management # available tags are 'management', 'policymaker', 'monitoring' and 'administrator'

Check warning on line 9 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

9:16 [comments] too few spaces before comment

Check warning on line 9 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

9:16 [comments] too few spaces before comment
- policymaker
rabbitmqClusterReference:
name: rabbitmq # rabbitmqCluster must exist in the same namespace as this resource

Check warning on line 12 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

12:20 [comments] too few spaces before comment

Check warning on line 12 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

12:20 [comments] too few spaces before comment
namespace: openstack
importCredentialsSecret:
name: ironic-rabbitmq-password
---
apiVersion: rabbitmq.com/v1beta1
kind: Vhost
metadata:
name: ironic-vhost
namespace: openstack
spec:
name: "ironic" # vhost name; required and cannot be updated

Check warning on line 23 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

23:18 [comments] too few spaces before comment

Check warning on line 23 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

23:18 [comments] too few spaces before comment
defaultQueueType: quorum # default queue type for this vhost; require RabbitMQ version 3.11.12 or above

Check warning on line 24 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

24:28 [comments] too few spaces before comment

Check warning on line 24 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

24:28 [comments] too few spaces before comment
rabbitmqClusterReference:
name: rabbitmq # rabbitmqCluster must exist in the same namespace as this resource

Check warning on line 26 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

26:20 [comments] too few spaces before comment

Check warning on line 26 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

26:20 [comments] too few spaces before comment
namespace: openstack
---
apiVersion: rabbitmq.com/v1beta1
kind: Queue
metadata:
name: ironic-queue
namespace: openstack
spec:
name: ironic-qq # name of the queue

Check warning on line 35 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

35:19 [comments] too few spaces before comment

Check warning on line 35 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

35:19 [comments] too few spaces before comment
vhost: "ironic" # default to '/' if not provided

Check warning on line 36 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

36:19 [comments] too few spaces before comment

Check warning on line 36 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

36:19 [comments] too few spaces before comment
type: quorum # without providing a queue type, rabbitmq creates a classic queue

Check warning on line 37 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

37:16 [comments] too few spaces before comment

Check warning on line 37 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

37:16 [comments] too few spaces before comment
autoDelete: false
durable: true # seting 'durable' to false means this queue won't survive a server restart

Check warning on line 39 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

39:17 [comments] too few spaces before comment

Check warning on line 39 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

39:17 [comments] too few spaces before comment
rabbitmqClusterReference:
name: rabbitmq # rabbitmqCluster must exist in the same namespace as this resource

Check warning on line 41 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

41:20 [comments] too few spaces before comment

Check warning on line 41 in components/13-ironic/ironic-rabbitmq-queue.yaml

View workflow job for this annotation

GitHub Actions / lint-yaml

41:20 [comments] too few spaces before comment
namespace: openstack
---
apiVersion: rabbitmq.com/v1beta1
kind: Permission
metadata:
name: ironic-permission
namespace: openstack
spec:
vhost: "ironic" # name of a vhost
userReference:
name: "ironic" # name of a user.rabbitmq.com in the same namespace; must specify either spec.userReference or spec.user
permissions:
write: ".*"
configure: ".*"
read: ".*"
rabbitmqClusterReference:
name: rabbitmq # rabbitmqCluster must exist in the same namespace as this resource
namespace: openstack
7 changes: 7 additions & 0 deletions components/13-ironic/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- ironic-mariadb-db.yaml
- ironic-rabbitmq-queue.yaml

0 comments on commit a12c8b4

Please sign in to comment.