Added OpenStack services

Change-Id: I9aadad2919a6a7400d6f11a884317e33e787b416
This commit is contained in:
Mohammed Naser 2022-03-12 16:30:00 -05:00
parent 0003fd0da6
commit b7b97d6c04
94 changed files with 5725 additions and 5 deletions

View File

@ -1 +1,2 @@
molecule==3.5.2 # https://github.com/ansible-community/molecule/issues/3435
openstacksdk

112
playbooks/openstack.yml Normal file
View File

@ -0,0 +1,112 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- hosts: controllers[0]
gather_facts: false
become: true
roles:
- role: cilium
tags:
- cilium
- role: ceph_csi_rbd
tags:
- ceph-csi-rbd
- role: kube_prometheus_stack
tags:
- kube-prometheus-stack
- role: node_feature_discovery
tags:
- node-feature-discovery
- role: prometheus_pushgateway
tags:
- prometheus-pushgateway
- role: openstack_namespace
tags:
- openstack-namespace
- role: ingress_nginx
tags:
- ingress-nginx
- role: cert_manager
tags:
- cert-manager
- role: percona_xtradb_cluster
tags:
- percona-xtradb-cluster
- role: openstack_helm_infra_memcached
tags:
- openstack-helm-infra-memcached
- role: openstack_helm_infra_rabbitmq
tags:
- openstack-helm-infra-rabbitmq
- role: openstack_helm_keystone
tags:
- openstack-helm-keystone
- role: openstack_helm_infra_ceph_provisioners
tags:
- openstack-helm-infra-ceph-provisioners
- role: openstack_helm_glance
tags:
- openstack-helm-glance
- role: openstack_helm_cinder
tags:
- openstack-helm-cinder
- role: openstack_helm_placement
tags:
- openstack-helm-placement
- role: openstack_helm_infra_openvswitch
tags:
- openstack-helm-infra-openvswitch
- role: openstack_helm_infra_libvirt
tags:
- openstack-helm-infra-libvirt
- role: openstack_helm_neutron
tags:
- openstack-helm-neutron
- role: openstack_helm_nova
tags:
- openstack-helm-nova
- role: openstack_helm_heat
tags:
- openstack-helm-heat
- role: openstack_helm_horizon
tags:
- openstack-helm-horizon
- hosts: controllers
gather_facts: false
roles:
- role: openstack_cli
tags:
- openstack-cli

View File

@ -14,3 +14,4 @@
- import_playbook: vexxhost.atmosphere.ceph
- import_playbook: vexxhost.atmosphere.kubernetes
- import_playbook: vexxhost.atmosphere.openstack

View File

@ -0,0 +1,114 @@
import os
import datetime
def generate_ceph_cmd(sub_cmd, args, user_key=None, cluster='ceph', user='client.admin', container_image=None, interactive=False):
'''
Generate 'ceph' command line to execute
'''
if not user_key:
user_key = '/etc/ceph/{}.{}.keyring'.format(cluster, user)
cmd = pre_generate_ceph_cmd(
container_image=container_image, interactive=interactive)
base_cmd = [
'-n',
user,
'-k',
user_key,
'--cluster',
cluster
]
base_cmd.extend(sub_cmd)
cmd.extend(base_cmd + args)
return cmd
def container_exec(binary, container_image, interactive=False):
'''
Build the docker CLI to run a command inside a container
'''
container_binary = os.getenv('CEPH_CONTAINER_BINARY')
command_exec = [container_binary, 'run']
if interactive:
command_exec.extend(['--interactive'])
command_exec.extend(['--rm',
'--net=host',
'-v', '/etc/ceph:/etc/ceph:z',
'-v', '/var/lib/ceph/:/var/lib/ceph/:z',
'-v', '/var/log/ceph/:/var/log/ceph/:z',
'--entrypoint=' + binary, container_image])
return command_exec
def is_containerized():
'''
Check if we are running on a containerized cluster
'''
if 'CEPH_CONTAINER_IMAGE' in os.environ:
container_image = os.getenv('CEPH_CONTAINER_IMAGE')
else:
container_image = None
return container_image
def pre_generate_ceph_cmd(container_image=None, interactive=False):
'''
Generate ceph prefix comaand
'''
if container_image:
cmd = container_exec('ceph', container_image, interactive=interactive)
else:
cmd = ['ceph']
return cmd
def exec_command(module, cmd, stdin=None):
'''
Execute command(s)
'''
binary_data = False
if stdin:
binary_data = True
rc, out, err = module.run_command(cmd, data=stdin, binary_data=binary_data)
return rc, cmd, out, err
def exit_module(module, out, rc, cmd, err, startd, changed=False, diff=dict(before="", after="")):
endd = datetime.datetime.now()
delta = endd - startd
result = dict(
cmd=cmd,
start=str(startd),
end=str(endd),
delta=str(delta),
rc=rc,
stdout=out.rstrip("\r\n"),
stderr=err.rstrip("\r\n"),
changed=changed,
diff=diff
)
module.exit_json(**result)
def fatal(message, module):
'''
Report a fatal error and exit
'''
if module:
module.fail_json(msg=message, rc=1)
else:
raise(Exception(message))

692
plugins/modules/ceph_key.py Normal file
View File

@ -0,0 +1,692 @@
#!/usr/bin/python3
# Copyright 2018, Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.vexxhost.atmosphere.plugins.module_utils.ca_common import generate_ceph_cmd, \
is_containerized, \
container_exec, \
fatal
import datetime
import json
import os
import struct
import time
import base64
import socket
ANSIBLE_METADATA = {
'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'
}
DOCUMENTATION = '''
---
module: ceph_key
author: Sebastien Han <seb@redhat.com>
short_description: Manage Cephx key(s)
version_added: "2.6"
description:
- Manage CephX creation, deletion and updates.
It can also list and get information about keyring(s).
options:
cluster:
description:
- The ceph cluster name.
required: false
default: ceph
name:
description:
- name of the CephX key
required: true
user:
description:
- entity used to perform operation.
It corresponds to the -n option (--name)
required: false
user_key:
description:
- the path to the keyring corresponding to the
user being used.
It corresponds to the -k option (--keyring)
state:
description:
- If 'present' is used, the module creates a keyring
with the associated capabilities.
If 'present' is used and a secret is provided the module
will always add the key. Which means it will update
the keyring if the secret changes, the same goes for
the capabilities.
If 'absent' is used, the module will simply delete the keyring.
If 'list' is used, the module will list all the keys and will
return a json output.
If 'info' is used, the module will return in a json format the
description of a given keyring.
If 'generate_secret' is used, the module will simply output a cephx keyring.
required: false
choices: ['present', 'update', 'absent', 'list', 'info', 'fetch_initial_keys', 'generate_secret']
default: present
caps:
description:
- CephX key capabilities
default: None
required: false
secret:
description:
- keyring's secret value
required: false
default: None
import_key:
description:
- Wether or not to import the created keyring into Ceph.
This can be useful for someone that only wants to generate keyrings
but not add them into Ceph.
required: false
default: True
dest:
description:
- Destination to write the keyring, can a file or a directory
required: false
default: /etc/ceph/
fetch_initial_keys:
description:
- Fetch client.admin and bootstrap key.
This is only needed for Nautilus and above.
Writes down to the filesystem the initial keys generated by the monitor. # noqa: E501
This command can ONLY run from a monitor node.
required: false
default: false
output_format:
description:
- The key output format when retrieving the information of an
entity.
required: false
default: json
'''
EXAMPLES = '''
keys_to_create:
- { name: client.key, key: "AQAin8tUUK84ExAA/QgBtI7gEMWdmnvKBzlXdQ==", caps: { mon: "allow rwx", mds: "allow *" } , mode: "0600" } # noqa: E501
- { name: client.cle, caps: { mon: "allow r", osd: "allow *" } , mode: "0600" } # noqa: E501
caps:
mon: "allow rwx"
mds: "allow *"
- name: create ceph admin key
ceph_key:
name: client.admin
state: present
secret: AQAin8tU2DsKFBAAFIAzVTzkL3+gtAjjpQiomw==
caps:
mon: allow *
osd: allow *
mgr: allow *
mds: allow
mode: 0400
import_key: False
- name: create monitor initial keyring
ceph_key:
name: mon.
state: present
secret: AQAin8tUMICVFBAALRHNrV0Z4MXupRw4v9JQ6Q==
caps:
mon: allow *
dest: "/var/lib/ceph/tmp/"
import_key: False
- name: create cephx key
ceph_key:
name: "{{ keys_to_create }}"
user: client.bootstrap-rgw
user_key: /var/lib/ceph/bootstrap-rgw/ceph.keyring
state: present
caps: "{{ caps }}"
- name: create cephx key but don't import it in Ceph
ceph_key:
name: "{{ keys_to_create }}"
state: present
caps: "{{ caps }}"
import_key: False
- name: delete cephx key
ceph_key:
name: "my_key"
state: absent
- name: info cephx key
ceph_key:
name: "my_key""
state: info
- name: info cephx admin key (plain)
ceph_key:
name: client.admin
output_format: plain
state: info
register: client_admin_key
- name: list cephx keys
ceph_key:
state: list
- name: fetch cephx keys
ceph_key:
state: fetch_initial_keys
'''
RETURN = '''# '''
CEPH_INITIAL_KEYS = ['client.admin', 'client.bootstrap-mds', 'client.bootstrap-mgr', # noqa: E501
'client.bootstrap-osd', 'client.bootstrap-rbd', 'client.bootstrap-rbd-mirror', 'client.bootstrap-rgw'] # noqa: E501
def str_to_bool(val):
try:
val = val.lower()
except AttributeError:
val = str(val).lower()
if val == 'true':
return True
elif val == 'false':
return False
else:
raise ValueError("Invalid input value: %s" % val)
def generate_secret():
'''
Generate a CephX secret
'''
key = os.urandom(16)
header = struct.pack('<hiih', 1, int(time.time()), 0, len(key))
secret = base64.b64encode(header + key)
return secret
def generate_caps(_type, caps):
'''
Generate CephX capabilities list
'''
caps_cli = []
for k, v in caps.items():
# makes sure someone didn't pass an empty var,
# we don't want to add an empty cap
if len(k) == 0:
continue
if _type == "ceph-authtool":
caps_cli.extend(["--cap"])
caps_cli.extend([k, v])
return caps_cli
def generate_ceph_authtool_cmd(cluster, name, secret, caps, dest, container_image=None): # noqa: E501
'''
Generate 'ceph-authtool' command line to execute
'''
if container_image:
binary = 'ceph-authtool'
cmd = container_exec(
binary, container_image)
else:
binary = ['ceph-authtool']
cmd = binary
base_cmd = [
'--create-keyring',
dest,
'--name',
name,
'--add-key',
secret,
]
cmd.extend(base_cmd)
cmd.extend(generate_caps("ceph-authtool", caps))
return cmd
def create_key(module, result, cluster, user, user_key, name, secret, caps, import_key, dest, container_image=None): # noqa: E501
'''
Create a CephX key
'''
cmd_list = []
if not secret:
secret = generate_secret()
if user == 'client.admin':
args = ['import', '-i', dest]
else:
args = ['get-or-create', name]
args.extend(generate_caps(None, caps))
args.extend(['-o', dest])
cmd_list.append(generate_ceph_authtool_cmd(
cluster, name, secret, caps, dest, container_image))
if import_key or user != 'client.admin':
cmd_list.append(generate_ceph_cmd(sub_cmd=['auth'],
args=args,
cluster=cluster,
user=user,
user_key=user_key,
container_image=container_image))
return cmd_list
def delete_key(cluster, user, user_key, name, container_image=None):
'''
Delete a CephX key
'''
cmd_list = []
args = [
'del',
name,
]
cmd_list.append(generate_ceph_cmd(sub_cmd=['auth'],
args=args,
cluster=cluster,
user=user,
user_key=user_key,
container_image=container_image))
return cmd_list
def get_key(cluster, user, user_key, name, dest, container_image=None):
'''
Get a CephX key (write on the filesystem)
'''
cmd_list = []
args = [
'get',
name,
'-o',
dest,
]
cmd_list.append(generate_ceph_cmd(sub_cmd=['auth'],
args=args,
cluster=cluster,
user=user,
user_key=user_key,
container_image=container_image))
return cmd_list
def info_key(cluster, name, user, user_key, output_format, container_image=None): # noqa: E501
'''
Get information about a CephX key
'''
cmd_list = []
args = [
'get',
name,
'-f',
output_format,
]
cmd_list.append(generate_ceph_cmd(sub_cmd=['auth'],
args=args,
cluster=cluster,
user=user,
user_key=user_key,
container_image=container_image))
return cmd_list
def list_keys(cluster, user, user_key, container_image=None):
'''
List all CephX keys
'''
cmd_list = []
args = [
'ls',
'-f',
'json',
]
cmd_list.append(generate_ceph_cmd(sub_cmd=['auth'],
args=args,
cluster=cluster,
user=user,
user_key=user_key,
container_image=container_image))
return cmd_list
def exec_commands(module, cmd_list):
'''
Execute command(s)
'''
for cmd in cmd_list:
rc, out, err = module.run_command(cmd)
if rc != 0:
return rc, cmd, out, err
return rc, cmd, out, err
def lookup_ceph_initial_entities(module, out):
'''
Lookup Ceph initial keys entries in the auth map
'''
# convert out to json, ansible returns a string...
try:
out_dict = json.loads(out)
except ValueError as e:
fatal("Could not decode 'ceph auth list' json output: {}".format(e), module) # noqa: E501
entities = []
if "auth_dump" in out_dict:
for key in out_dict["auth_dump"]:
for k, v in key.items():
if k == "entity":
if v in CEPH_INITIAL_KEYS:
entities.append(v)
else:
fatal("'auth_dump' key not present in json output:", module) # noqa: E501
if len(entities) != len(CEPH_INITIAL_KEYS) and not str_to_bool(os.environ.get('CEPH_ROLLING_UPDATE', False)): # noqa: E501
# must be missing in auth_dump, as if it were in CEPH_INITIAL_KEYS
# it'd be in entities from the above test. Report what's missing.
missing = []
for e in CEPH_INITIAL_KEYS:
if e not in entities:
missing.append(e)
fatal("initial keyring does not contain keys: " + ' '.join(missing), module) # noqa: E501
return entities
def build_key_path(cluster, entity):
'''
Build key path depending on the key type
'''
if "admin" in entity:
path = "/etc/ceph"
keyring_filename = cluster + "." + entity + ".keyring"
key_path = os.path.join(path, keyring_filename)
elif "bootstrap" in entity:
path = "/var/lib/ceph"
# bootstrap keys show up as 'client.boostrap-osd'
# however the directory is called '/var/lib/ceph/bootstrap-osd'
# so we need to substring 'client.'
entity_split = entity.split('.')[1]
keyring_filename = cluster + ".keyring"
key_path = os.path.join(path, entity_split, keyring_filename)
else:
return None
return key_path
def run_module():
module_args = dict(
cluster=dict(type='str', required=False, default='ceph'),
name=dict(type='str', required=False),
state=dict(type='str', required=False, default='present', choices=['present', 'update', 'absent', # noqa: E501
'list', 'info', 'fetch_initial_keys', 'generate_secret']), # noqa: E501
caps=dict(type='dict', required=False, default=None),
secret=dict(type='str', required=False, default=None, no_log=True),
import_key=dict(type='bool', required=False, default=True),
dest=dict(type='str', required=False, default='/etc/ceph/'),
user=dict(type='str', required=False, default='client.admin'),
user_key=dict(type='str', required=False, default=None),
output_format=dict(type='str', required=False, default='json', choices=['json', 'plain', 'xml', 'yaml']) # noqa: E501
)
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True,
add_file_common_args=True,
)
file_args = module.load_file_common_arguments(module.params)
# Gather module parameters in variables
state = module.params['state']
name = module.params.get('name')
cluster = module.params.get('cluster')
caps = module.params.get('caps')
secret = module.params.get('secret')
import_key = module.params.get('import_key')
dest = module.params.get('dest')
user = module.params.get('user')
user_key = module.params.get('user_key')
output_format = module.params.get('output_format')
changed = False
result = dict(
changed=changed,
stdout='',
stderr='',
rc=0,
start='',
end='',
delta='',
)
if module.check_mode and state != "info":
module.exit_json(**result)
startd = datetime.datetime.now()
# will return either the image name or None
container_image = is_containerized()
# Test if the key exists, if it does we skip its creation
# We only want to run this check when a key needs to be added
# There is no guarantee that any cluster is running and we don't need one
_secret = secret
_caps = caps
key_exist = 1
if not user_key:
user_key_filename = '{}.{}.keyring'.format(cluster, user)
user_key_dir = '/etc/ceph'
user_key_path = os.path.join(user_key_dir, user_key_filename)
else:
user_key_path = user_key
if (state in ["present", "update"]):
# if dest is not a directory, the user wants to change the file's name
# (e,g: /etc/ceph/ceph.mgr.ceph-mon2.keyring)
if not os.path.isdir(dest):
file_path = dest
else:
if 'bootstrap' in dest:
# Build a different path for bootstrap keys as there are stored
# as /var/lib/ceph/bootstrap-rbd/ceph.keyring
keyring_filename = cluster + '.keyring'
else:
keyring_filename = cluster + "." + name + ".keyring"
file_path = os.path.join(dest, keyring_filename)
file_args['path'] = file_path
if import_key:
_info_key = []
rc, cmd, out, err = exec_commands(
module, info_key(cluster, name, user, user_key_path, output_format, container_image)) # noqa: E501
key_exist = rc
if not caps and key_exist != 0:
fatal("Capabilities must be provided when state is 'present'", module) # noqa: E501
if key_exist != 0 and secret is None and caps is None:
fatal("Keyring doesn't exist, you must provide 'secret' and 'caps'", module) # noqa: E501
if key_exist == 0:
_info_key = json.loads(out)
if not secret:
secret = _info_key[0]['key']
_secret = _info_key[0]['key']
if not caps:
caps = _info_key[0]['caps']
_caps = _info_key[0]['caps']
if secret == _secret and caps == _caps:
if not os.path.isfile(file_path):
rc, cmd, out, err = exec_commands(module, get_key(cluster, user, user_key_path, name, file_path, container_image)) # noqa: E501
result["rc"] = rc
if rc != 0:
result["stdout"] = "Couldn't fetch the key {0} at {1}.".format(name, file_path) # noqa: E501
module.exit_json(**result)
result["stdout"] = "fetched the key {0} at {1}.".format(name, file_path) # noqa: E501
result["stdout"] = "{0} already exists and doesn't need to be updated.".format(name) # noqa: E501
result["rc"] = 0
module.set_fs_attributes_if_different(file_args, False)
module.exit_json(**result)
else:
if os.path.isfile(file_path) and not secret or not caps:
result["stdout"] = "{0} already exists in {1} you must provide secret *and* caps when import_key is {2}".format(name, dest, import_key) # noqa: E501
result["rc"] = 0
module.exit_json(**result)
if (key_exist == 0 and (secret != _secret or caps != _caps)) or key_exist != 0: # noqa: E501
rc, cmd, out, err = exec_commands(module, create_key(
module, result, cluster, user, user_key_path, name, secret, caps, import_key, file_path, container_image)) # noqa: E501
if rc != 0:
result["stdout"] = "Couldn't create or update {0}".format(name)
result["stderr"] = err
module.exit_json(**result)
module.set_fs_attributes_if_different(file_args, False)
changed = True
elif state == "absent":
if key_exist == 0:
rc, cmd, out, err = exec_commands(
module, delete_key(cluster, user, user_key_path, name, container_image)) # noqa: E501
if rc == 0:
changed = True
else:
rc = 0
elif state == "info":
rc, cmd, out, err = exec_commands(
module, info_key(cluster, name, user, user_key_path, output_format, container_image)) # noqa: E501
elif state == "list":
rc, cmd, out, err = exec_commands(
module, list_keys(cluster, user, user_key_path, container_image))
elif state == "fetch_initial_keys":
hostname = socket.gethostname().split('.', 1)[0]
user = "mon."
keyring_filename = cluster + "-" + hostname + "/keyring"
user_key_path = os.path.join("/var/lib/ceph/mon/", keyring_filename)
rc, cmd, out, err = exec_commands(
module, list_keys(cluster, user, user_key_path, container_image))
if rc != 0:
result["stdout"] = "failed to retrieve ceph keys"
result["sdterr"] = err
result['rc'] = 0
module.exit_json(**result)
entities = lookup_ceph_initial_entities(module, out)
output_format = "plain"
for entity in entities:
key_path = build_key_path(cluster, entity)
if key_path is None:
fatal("Failed to build key path, no entity yet?", module)
elif os.path.isfile(key_path):
# if the key is already on the filesystem
# there is no need to fetch it again
continue
extra_args = [
'-o',
key_path,
]
info_cmd = info_key(cluster, entity, user,
user_key_path, output_format, container_image)
# we use info_cmd[0] because info_cmd is an array made of an array
info_cmd[0].extend(extra_args)
rc, cmd, out, err = exec_commands(
module, info_cmd) # noqa: E501
file_args = module.load_file_common_arguments(module.params)
file_args['path'] = key_path
module.set_fs_attributes_if_different(file_args, False)
elif state == "generate_secret":
out = generate_secret().decode()
cmd = ''
rc = 0
err = ''
changed = True
endd = datetime.datetime.now()
delta = endd - startd
result = dict(
cmd=cmd,
start=str(startd),
end=str(endd),
delta=str(delta),
rc=rc,
stdout=out.rstrip("\r\n"),
stderr=err.rstrip("\r\n"),
changed=changed,
)
if rc != 0:
module.fail_json(msg='non-zero return code', **result)
module.exit_json(**result)
def main():
run_module()
if __name__ == '__main__':
main()

View File

@ -0,0 +1,684 @@
#!/usr/bin/python3
# Copyright 2020, Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.vexxhost.atmosphere.plugins.module_utils.ca_common import generate_ceph_cmd, \
pre_generate_ceph_cmd, \
is_containerized, \
exec_command, \
exit_module
import datetime
import json
import os
ANSIBLE_METADATA = {
'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'
}
DOCUMENTATION = '''
---
module: ceph_pool
author: Guillaume Abrioux <gabrioux@redhat.com>
short_description: Manage Ceph Pools
version_added: "2.8"
description:
- Manage Ceph pool(s) creation, deletion and updates.
options:
cluster:
description:
- The ceph cluster name.
required: false
default: ceph
name:
description:
- name of the Ceph pool
required: true
state:
description:
If 'present' is used, the module creates a pool if it doesn't exist
or update it if it already exists.
If 'absent' is used, the module will simply delete the pool.
If 'list' is used, the module will return all details about the
existing pools. (json formatted).
required: false
choices: ['present', 'absent', 'list']
default: present
size:
description:
- set the replica size of the pool.
required: false
default: 3
min_size:
description:
- set the min_size parameter of the pool.
required: false
default: default to `osd_pool_default_min_size` (ceph)
pg_num:
description:
- set the pg_num of the pool.
required: false
default: default to `osd_pool_default_pg_num` (ceph)
pgp_num:
description:
- set the pgp_num of the pool.
required: false
default: default to `osd_pool_default_pgp_num` (ceph)
pg_autoscale_mode:
description:
- set the pg autoscaler on the pool.
required: false
default: 'on'
target_size_ratio:
description:
- set the target_size_ratio on the pool
required: false
default: None
pool_type:
description:
- set the pool type, either 'replicated' or 'erasure'
required: false
default: 'replicated'
erasure_profile:
description:
- When pool_type = 'erasure', set the erasure profile of the pool
required: false
default: 'default'
rule_name:
description:
- Set the crush rule name assigned to the pool
required: false
default: 'replicated_rule' when pool_type is 'erasure' else None
expected_num_objects:
description:
- Set the expected_num_objects parameter of the pool.
required: false
default: '0'
application:
description:
- Set the pool application on the pool.
required: false
default: None
'''
EXAMPLES = '''
pools:
- { name: foo, size: 3, application: rbd, pool_type: 'replicated',
pg_autoscale_mode: 'on' }
- hosts: all
become: true
tasks:
- name: create a pool
ceph_pool:
name: "{{ item.name }}"
state: present
size: "{{ item.size }}"
application: "{{ item.application }}"
pool_type: "{{ item.pool_type }}"
pg_autoscale_mode: "{{ item.pg_autoscale_mode }}"
with_items: "{{ pools }}"
'''
RETURN = '''# '''
def check_pool_exist(cluster,
name,
user,
user_key,
output_format='json',
container_image=None):
'''
Check if a given pool exists
'''
args = ['stats', name, '-f', output_format]
cmd = generate_ceph_cmd(sub_cmd=['osd', 'pool'],
args=args,
cluster=cluster,
user=user,
user_key=user_key,
container_image=container_image)
return cmd
def generate_get_config_cmd(param,
cluster,
user,
user_key,
container_image=None):
_cmd = pre_generate_ceph_cmd(container_image=container_image)
args = [
'-n',
user,
'-k',
user_key,
'--cluster',
cluster,
'config',
'get',
'mon.*',
param
]
cmd = _cmd + args
return cmd
def get_application_pool(cluster,
name,
user,
user_key,
output_format='json',
container_image=None):
'''
Get application type enabled on a given pool
'''
args = ['application', 'get', name, '-f', output_format]
cmd = generate_ceph_cmd(sub_cmd=['osd', 'pool'],
args=args,
cluster=cluster,
user=user,
user_key=user_key,
container_image=container_image)
return cmd
def enable_application_pool(cluster,
name,
application,
user,
user_key,
container_image=None):
'''
Enable application on a given pool
'''
args = ['application', 'enable', name, application]
cmd = generate_ceph_cmd(sub_cmd=['osd', 'pool'],
args=args,
cluster=cluster,
user=user,
user_key=user_key,
container_image=container_image)
return cmd
def disable_application_pool(cluster,
name,
application,
user,
user_key,
container_image=None):
'''
Disable application on a given pool
'''
args = ['application', 'disable', name,
application, '--yes-i-really-mean-it']
cmd = generate_ceph_cmd(sub_cmd=['osd', 'pool'],
args=args,
cluster=cluster,
user=user,
user_key=user_key,
container_image=container_image)
return cmd
def get_pool_details(module,
cluster,
name,
user,
user_key,
output_format='json',
container_image=None):
'''
Get details about a given pool
'''
args = ['ls', 'detail', '-f', output_format]
cmd = generate_ceph_cmd(sub_cmd=['osd', 'pool'],
args=args,
cluster=cluster,
user=user,
user_key=user_key,
container_image=container_image)
rc, cmd, out, err = exec_command(module, cmd)
if rc == 0:
out = [p for p in json.loads(out.strip()) if p['pool_name'] == name][0]
_rc, _cmd, application_pool, _err = exec_command(module,
get_application_pool(cluster, # noqa: E501
name, # noqa: E501
user, # noqa: E501
user_key, # noqa: E501
container_image=container_image)) # noqa: E501
# This is a trick because "target_size_ratio" isn't present at the same
# level in the dict
# ie:
# {
# 'pg_num': 8,
# 'pgp_num': 8,
# 'pg_autoscale_mode': 'on',
# 'options': {
# 'target_size_ratio': 0.1
# }
# }
# If 'target_size_ratio' is present in 'options', we set it, this way we
# end up with a dict containing all needed keys at the same level.
if 'target_size_ratio' in out['options'].keys():
out['target_size_ratio'] = out['options']['target_size_ratio']
else:
out['target_size_ratio'] = None
application = list(json.loads(application_pool.strip()).keys())
if len(application) == 0:
out['application'] = ''
else:
out['application'] = application[0]
return rc, cmd, out, err
def compare_pool_config(user_pool_config, running_pool_details):
'''
Compare user input config pool details with current running pool details
'''
delta = {}
filter_keys = ['pg_num', 'pg_placement_num', 'size',
'pg_autoscale_mode', 'target_size_ratio']
for key in filter_keys:
if (str(running_pool_details[key]) != user_pool_config[key]['value'] and # noqa: E501
user_pool_config[key]['value']):
delta[key] = user_pool_config[key]
if (running_pool_details['application'] !=
user_pool_config['application']['value'] and
user_pool_config['application']['value']):
delta['application'] = {}
delta['application']['new_application'] = user_pool_config['application']['value'] # noqa: E501
# to be improved (for update_pools()...)
delta['application']['value'] = delta['application']['new_application']
delta['application']['old_application'] = running_pool_details['application'] # noqa: E501
return delta
def list_pools(cluster,
user,
user_key,
details,
output_format='json',
container_image=None):
'''
List existing pools
'''
args = ['ls']
if details:
args.append('detail')
args.extend(['-f', output_format])
cmd = generate_ceph_cmd(sub_cmd=['osd', 'pool'],
args=args,
cluster=cluster,
user=user,
user_key=user_key,
container_image=container_image)
return cmd
def create_pool(cluster,
name,
user,
user_key,
user_pool_config,
container_image=None):
'''
Create a new pool
'''
args = ['create', user_pool_config['pool_name']['value'],
user_pool_config['type']['value']]
if user_pool_config['pg_autoscale_mode']['value'] != 'on':
args.extend(['--pg_num',
user_pool_config['pg_num']['value'],
'--pgp_num',
user_pool_config['pgp_num']['value'] or
user_pool_config['pg_num']['value']])
elif user_pool_config['target_size_ratio']['value']:
args.extend(['--target_size_ratio',
user_pool_config['target_size_ratio']['value']])
if user_pool_config['type']['value'] == 'replicated':
args.extend([user_pool_config['crush_rule']['value'],
'--expected_num_objects',
user_pool_config['expected_num_objects']['value'],
'--autoscale-mode',
user_pool_config['pg_autoscale_mode']['value']])
if (user_pool_config['size']['value'] and
user_pool_config['type']['value'] == "replicated"):
args.extend(['--size', user_pool_config['size']['value']])
elif user_pool_config['type']['value'] == 'erasure':
args.extend([user_pool_config['erasure_profile']['value']])
if user_pool_config['crush_rule']['value']:
args.extend([user_pool_config['crush_rule']['value']])
args.extend(['--expected_num_objects',
user_pool_config['expected_num_objects']['value'],
'--autoscale-mode',
user_pool_config['pg_autoscale_mode']['value']])
cmd = generate_ceph_cmd(sub_cmd=['osd', 'pool'],
args=args,
cluster=cluster,
user=user,
user_key=user_key,
container_image=container_image)
return cmd
def remove_pool(cluster, name, user, user_key, container_image=None):
'''
Remove a pool
'''
args = ['rm', name, name, '--yes-i-really-really-mean-it']
cmd = generate_ceph_cmd(sub_cmd=['osd', 'pool'],
args=args,
cluster=cluster,
user=user,
user_key=user_key,
container_image=container_image)
return cmd
def update_pool(module, cluster, name,
user, user_key, delta, container_image=None):
'''
Update an existing pool
'''
report = ""
for key in delta.keys():
if key != 'application':
args = ['set',
name,
delta[key]['cli_set_opt'],
delta[key]['value']]
cmd = generate_ceph_cmd(sub_cmd=['osd', 'pool'],
args=args,
cluster=cluster,
user=user,
user_key=user_key,
container_image=container_image)
rc, cmd, out, err = exec_command(module, cmd)
if rc != 0:
return rc, cmd, out, err
else:
rc, cmd, out, err = exec_command(module, disable_application_pool(cluster, name, delta['application']['old_application'], user, user_key, container_image=container_image)) # noqa: E501
if rc != 0:
return rc, cmd, out, err
rc, cmd, out, err = exec_command(module, enable_application_pool(cluster, name, delta['application']['new_application'], user, user_key, container_image=container_image)) # noqa: E501
if rc != 0:
return rc, cmd, out, err
report = report + "\n" + "{} has been updated: {} is now {}".format(name, key, delta[key]['value']) # noqa: E501
out = report
return rc, cmd, out, err
def run_module():
module_args = dict(
cluster=dict(type='str', required=False, default='ceph'),
name=dict(type='str', required=True),
state=dict(type='str', required=False, default='present',
choices=['present', 'absent', 'list']),
details=dict(type='bool', required=False, default=False),
size=dict(type='str', required=False),
min_size=dict(type='str', required=False),
pg_num=dict(type='str', required=False),
pgp_num=dict(type='str', required=False),
pg_autoscale_mode=dict(type='str', required=False, default='on'),
target_size_ratio=dict(type='str', required=False, default=None),
pool_type=dict(type='str', required=False, default='replicated',
choices=['replicated', 'erasure', '1', '3']),
erasure_profile=dict(type='str', required=False, default='default'),
rule_name=dict(type='str', required=False, default=None),
expected_num_objects=dict(type='str', required=False, default="0"),
application=dict(type='str', required=False, default=None),
)
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True
)
# Gather module parameters in variables
cluster = module.params.get('cluster')
name = module.params.get('name')
state = module.params.get('state')
details = module.params.get('details')
size = module.params.get('size')
min_size = module.params.get('min_size')
pg_num = module.params.get('pg_num')
pgp_num = module.params.get('pgp_num')
pg_autoscale_mode = module.params.get('pg_autoscale_mode')
target_size_ratio = module.params.get('target_size_ratio')
application = module.params.get('application')
if (module.params.get('pg_autoscale_mode').lower() in
['true', 'on', 'yes']):
pg_autoscale_mode = 'on'
elif (module.params.get('pg_autoscale_mode').lower() in
['false', 'off', 'no']):
pg_autoscale_mode = 'off'
else:
pg_autoscale_mode = 'warn'
if module.params.get('pool_type') == '1':
pool_type = 'replicated'
elif module.params.get('pool_type') == '3':
pool_type = 'erasure'
else:
pool_type = module.params.get('pool_type')
if not module.params.get('rule_name'):
rule_name = 'replicated_rule' if pool_type == 'replicated' else None
else:
rule_name = module.params.get('rule_name')
erasure_profile = module.params.get('erasure_profile')
expected_num_objects = module.params.get('expected_num_objects')
user_pool_config = {
'pool_name': {'value': name},
'pg_num': {'value': pg_num, 'cli_set_opt': 'pg_num'},
'pgp_num': {'value': pgp_num, 'cli_set_opt': 'pgp_num'},
'pg_autoscale_mode': {'value': pg_autoscale_mode,
'cli_set_opt': 'pg_autoscale_mode'},
'target_size_ratio': {'value': target_size_ratio,
'cli_set_opt': 'target_size_ratio'},
'application': {'value': application},
'type': {'value': pool_type},
'erasure_profile': {'value': erasure_profile},
'crush_rule': {'value': rule_name, 'cli_set_opt': 'crush_rule'},
'expected_num_objects': {'value': expected_num_objects},
'size': {'value': size, 'cli_set_opt': 'size'},
'min_size': {'value': min_size}
}
if module.check_mode:
module.exit_json(
changed=False,
stdout='',
stderr='',
rc=0,
start='',
end='',
delta='',
)
startd = datetime.datetime.now()
changed = False
# will return either the image name or None
container_image = is_containerized()
user = "client.admin"
keyring_filename = cluster + '.' + user + '.keyring'
user_key = os.path.join("/etc/ceph/", keyring_filename)
if state == "present":
rc, cmd, out, err = exec_command(module,
check_pool_exist(cluster,
name,
user,
user_key,
container_image=container_image)) # noqa: E501
if rc == 0:
running_pool_details = get_pool_details(module,
cluster,
name,
user,
user_key,
container_image=container_image) # noqa: E501
user_pool_config['pg_placement_num'] = {'value': str(running_pool_details[2]['pg_placement_num']), 'cli_set_opt': 'pgp_num'} # noqa: E501
delta = compare_pool_config(user_pool_config,
running_pool_details[2])
if len(delta) > 0:
keys = list(delta.keys())
details = running_pool_details[2]
if details['erasure_code_profile'] and 'size' in keys:
del delta['size']
if details['pg_autoscale_mode'] == 'on':
delta.pop('pg_num', None)
delta.pop('pgp_num', None)
if len(delta) == 0:
out = "Skipping pool {}.\nUpdating either 'size' on an erasure-coded pool or 'pg_num'/'pgp_num' on a pg autoscaled pool is incompatible".format(name) # noqa: E501
else:
rc, cmd, out, err = update_pool(module,
cluster,
name,
user,
user_key,
delta,
container_image=container_image) # noqa: E501
if rc == 0:
changed = True
else:
out = "Pool {} already exists and there is nothing to update.".format(name) # noqa: E501
else:
rc, cmd, out, err = exec_command(module,
create_pool(cluster,
name,
user,
user_key,
user_pool_config=user_pool_config, # noqa: E501
container_image=container_image)) # noqa: E501
if user_pool_config['application']['value']:
rc, _, _, _ = exec_command(module,
enable_application_pool(cluster,
name,
user_pool_config['application']['value'], # noqa: E501
user,
user_key,
container_image=container_image)) # noqa: E501
if user_pool_config['min_size']['value']:
# not implemented yet
pass
changed = True
elif state == "list":
rc, cmd, out, err = exec_command(module,
list_pools(cluster,
name, user,
user_key,
details,
container_image=container_image)) # noqa: E501
if rc != 0:
out = "Couldn't list pool(s) present on the cluster"
elif state == "absent":
rc, cmd, out, err = exec_command(module,
check_pool_exist(cluster,
name, user,
user_key,
container_image=container_image)) # noqa: E501
if rc == 0:
rc, cmd, out, err = exec_command(module,
remove_pool(cluster,
name,
user,
user_key,
container_image=container_image)) # noqa: E501
changed = True
else:
rc = 0
out = "Skipped, since pool {} doesn't exist".format(name)
exit_module(module=module, out=out, rc=rc, cmd=cmd, err=err, startd=startd,
changed=changed)
def main():
run_module()
if __name__ == '__main__':
main()

View File

@ -0,0 +1,20 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
ceph_csi_rbd_ceph_fsid: "{{ ceph_mon_fsid }}"
ceph_csi_rbd_mons_group: ceph_mons
ceph_csi_rbd_id: kube
ceph_csi_rbd_user: "client.{{ ceph_csi_rbd_id }}"
ceph_csi_rbd_pool: kube

View File

@ -0,0 +1,20 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: ceph
helm_repository_repo_url: https://ceph.github.io/csi-charts
- cilium

View File

@ -0,0 +1,72 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: collect facts for all monitors
run_once: true
delegate_to: "{{ item }}"
delegate_facts: true
ansible.builtin.setup:
gather_subset: network
loop: "{{ groups[ceph_csi_rbd_mons_group] }}"
- vexxhost.atmosphere.ceph_pool:
name: "{{ ceph_csi_rbd_pool }}"
application: rbd
pg_autoscale_mode: on
- vexxhost.atmosphere.ceph_key:
name: "{{ ceph_csi_rbd_user }}"
caps:
mon: profile rbd
mgr: profile rbd pool={{ ceph_csi_rbd_pool }}
osd: profile rbd pool={{ ceph_csi_rbd_pool }}
- vexxhost.atmosphere.ceph_key:
name: "{{ ceph_csi_rbd_user }}"
state: info
output_format: json
register: _ceph_key
- ansible.builtin.set_fact:
_ceph_rbd_csi_ceph_keyring: "{{ _ceph_key.stdout | from_json | first }}"
- kubernetes.core.helm:
name: ceph-csi-rbd
chart_ref: ceph/ceph-csi-rbd
chart_version: 3.5.1
release_namespace: kube-system
kubeconfig: /etc/kubernetes/admin.conf
values:
csiConfig:
- clusterID: "{{ ceph_mon_fsid }}"
monitors: "{{ groups[ceph_csi_rbd_mons_group] | map('extract', hostvars, ['ansible_default_ipv4', 'address']) }}"
nodeplugin:
httpMetrics:
containerPort: 8081
provisioner:
nodeSelector:
openstack-control-plane: enabled
storageClass:
create: true
name: general
annotations:
storageclass.kubernetes.io/is-default-class: "true"
clusterID: "{{ ceph_csi_rbd_ceph_fsid }}"
pool: "{{ ceph_csi_rbd_pool }}"
mountOptions:
- discard
secret:
create: true
userID: "{{ ceph_csi_rbd_id }}"
userKey: "{{ _ceph_rbd_csi_ceph_keyring.key }}"

View File

@ -0,0 +1,26 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
cert_manager_acme_server: https://acme-v02.api.letsencrypt.org/directory
cert_manager_issuer:
acme:
email: mnaser@vexxhost.com
server: "{{ cert_manager_acme_server }}"
privateKeySecretRef:
name: issuer-account-key
solvers:
- http01:
ingress:
class: openstack

View File

@ -0,0 +1,22 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: jetstack
helm_repository_repo_url: https://charts.jetstack.io
- cilium
- ingress_nginx
- openstack_namespace

View File

@ -0,0 +1,43 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Deploy Helm chart
kubernetes.core.helm:
name: cert-manager
chart_ref: jetstack/cert-manager
chart_version: v1.7.1
release_namespace: cert-manager
create_namespace: true
kubeconfig: /etc/kubernetes/admin.conf
values:
installCRDs: true
volumes:
- name: etc-ssl-certs
hostPath:
path: /etc/ssl/certs
volumeMounts:
- name: etc-ssl-certs
mountPath: /etc/ssl/certs
readOnly: true
- name: Create issuer
kubernetes.core.k8s:
state: present
definition:
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: openstack
namespace: openstack
spec: "{{ cert_manager_issuer }}"

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: cilium
helm_repository_repo_url: https://helm.cilium.io/

View File

@ -0,0 +1,21 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Deploy Helm chart
kubernetes.core.helm:
name: cilium
chart_ref: cilium/cilium
chart_version: 1.10.7
release_namespace: kube-system
kubeconfig: /etc/kubernetes/admin.conf

View File

@ -0,0 +1,27 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Retrieve values for current Helm release
kubernetes.core.helm_info:
name: "{{ helm_diff_release_name }}"
release_namespace: "{{ helm_diff_release_namespace }}"
register: _helm_diff_info
- name: Generate diff between old and new values
ansible.utils.fact_diff:
before: "{{ _helm_diff_info.status['values'] }}"
after: "{{ helm_diff_values }}"
- name: Pause until you can verify values are correct
ansible.builtin.pause:

View File

@ -0,0 +1,16 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- helm

View File

@ -0,0 +1,18 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Configure Helm repository ({{ helm_repository_name }})
kubernetes.core.helm_repository:
name: "{{ helm_repository_name }}"
repo_url: "{{ helm_repository_repo_url }}"

View File

@ -0,0 +1,20 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: ingress-nginx
helm_repository_repo_url: https://kubernetes.github.io/ingress-nginx
- openstack_namespace

View File

@ -0,0 +1,39 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Deploy Helm chart
kubernetes.core.helm:
name: ingress-nginx
chart_ref: ingress-nginx/ingress-nginx
chart_version: 4.0.17
release_namespace: openstack
kubeconfig: /etc/kubernetes/admin.conf
values:
controller:
config:
proxy-buffer-size: 16k
dnsPolicy: ClusterFirstWithHostNet
hostNetwork: true
ingressClassResource:
name: openstack
ingressClass: openstack
extraArgs:
default-ssl-certificate: ingress-nginx/wildcard
kind: DaemonSet
nodeSelector:
openstack-control-plane: enabled
service:
type: ClusterIP
admissionWebhooks:
port: 7443

View File

@ -0,0 +1,21 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: prometheus-community
helm_repository_repo_url: https://prometheus-community.github.io/helm-charts
- cilium
- ceph_csi_rbd

View File

@ -0,0 +1,270 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- ansible.builtin.slurp:
src: /etc/kubernetes/pki/etcd/ca.crt
register: _etcd_ca_crt
- ansible.builtin.slurp:
src: /etc/kubernetes/pki/etcd/healthcheck-client.crt
register: _etcd_healthcheck_client_crt
- ansible.builtin.slurp:
src: /etc/kubernetes/pki/etcd/healthcheck-client.key
register: _etcd_healthcheck_client_key
- kubernetes.core.helm:
name: kube-prometheus-stack
chart_ref: prometheus-community/kube-prometheus-stack
chart_version: 30.2.0
release_namespace: monitoring
create_namespace: true
kubeconfig: /etc/kubernetes/admin.conf
values:
alertmanager:
serviceMonitor:
relabelings:
- sourceLabels: ["__meta_kubernetes_pod_name"]
targetLabel: "instance"
- action: "labeldrop"
regex: "^(container|endpoint|namespace|pod|service)$"
grafana:
serviceMonitor:
relabelings:
- sourceLabels: ["__meta_kubernetes_pod_name"]
targetLabel: "instance"
- action: "labeldrop"
regex: "^(container|endpoint|namespace|pod|service)$"
kubeApiServer:
serviceMonitor:
relabelings:
- sourceLabels: ["__meta_kubernetes_pod_node_name"]
targetLabel: "instance"
- action: "labeldrop"
regex: "^(container|endpoint|namespace|pod|service)$"
kubelet:
serviceMonitor:
cAdvisorRelabelings:
- sourceLabels: [__metrics_path__]
targetLabel: metrics_path
- sourceLabels: ["node"]
targetLabel: "instance"
- action: "labeldrop"
regex: "^(container|endpoint|namespace|node|service)$"
probesRelabelings:
- sourceLabels: [__metrics_path__]
targetLabel: metrics_path
- sourceLabels: ["node"]
targetLabel: "instance"
- action: "labeldrop"
regex: "^(container|endpoint|namespace|node|service)$"
relabelings:
- sourceLabels: [__metrics_path__]
targetLabel: metrics_path
- sourceLabels: ["node"]
targetLabel: "instance"
- action: "labeldrop"
regex: "^(container|endpoint|namespace|node|service)$"
kubeControllerManager:
serviceMonitor:
relabelings:
- sourceLabels: ["__meta_kubernetes_pod_node_name"]
targetLabel: "instance"
- action: "labeldrop"
regex: "^(container|endpoint|namespace|pod|service)$"
coreDns:
serviceMonitor:
relabelings:
- sourceLabels: ["__meta_kubernetes_pod_name"]
targetLabel: "instance"
- regex: "^(container|endpoint|namespace|pod|service)$"
action: "labeldrop"
kubeEtcd:
serviceMonitor:
scheme: https
serverName: localhost
insecureSkipVerify: false
caFile: /etc/prometheus/secrets/kube-prometheus-stack-etcd-client-cert/ca.crt
certFile: /etc/prometheus/secrets/kube-prometheus-stack-etcd-client-cert/healthcheck-client.crt
keyFile: /etc/prometheus/secrets/kube-prometheus-stack-etcd-client-cert/healthcheck-client.key
relabelings:
- sourceLabels: ["__meta_kubernetes_pod_node_name"]
targetLabel: "instance"
- action: "labeldrop"
regex: "^(container|endpoint|namespace|pod|service)$"
kubeScheduler:
service:
port: 10259
targetPort: 10259
serviceMonitor:
https: true
insecureSkipVerify: true
relabelings:
- sourceLabels: ["__meta_kubernetes_pod_node_name"]
targetLabel: "instance"
- action: "labeldrop"
regex: "^(container|endpoint|namespace|pod|service)$"
kubeProxy:
serviceMonitor:
relabelings:
- sourceLabels: ["__meta_kubernetes_pod_node_name"]
targetLabel: "instance"
- action: "labeldrop"
regex: "^(container|endpoint|namespace|pod|service)$"
kube-state-metrics:
prometheus:
monitor:
relabelings:
- sourceLabels: ["__meta_kubernetes_pod_name"]
targetLabel: "instance"
- action: "labeldrop"
regex: "^(container|endpoint|namespace|pod|service)$"
nodeSelector:
openstack-control-plane: enabled
prometheus:
serviceMonitor:
relabelings:
- sourceLabels: ["__meta_kubernetes_pod_name"]
targetLabel: "instance"
- action: "labeldrop"
regex: "^(container|endpoint|namespace|pod|service)$"
prometheusSpec:
nodeSelector:
openstack-control-plane: enabled
secrets:
- kube-prometheus-stack-etcd-client-cert
prometheusOperator:
serviceMonitor:
relabelings:
- sourceLabels: ["__meta_kubernetes_pod_name"]
targetLabel: "instance"
- action: "labeldrop"
regex: "^(container|endpoint|namespace|pod|service)$"
nodeSelector:
openstack-control-plane: enabled
prometheus-node-exporter:
extraArgs:
- --collector.diskstats.ignored-devices=^(ram|loop|nbd|fd|(h|s|v|xv)d[a-z]|nvme\\d+n\\d+p)\\d+$
- --collector.filesystem.fs-types-exclude=^(autofs|binfmt_misc|bpf|cgroup2?|configfs|debugfs|devpts|devtmpfs|fusectl|fuse.squashfuse_ll|hugetlbfs|iso9660|mqueue|nsfs|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|selinuxfs|squashfs|sysfs|tracefs)$
- --collector.filesystem.mount-points-exclude=^/(dev|proc|run/credentials/.+|sys|var/lib/docker/.+|var/lib/kubelet/pods/.+|var/lib/kubelet/plugins/kubernetes.io/csi/.+|run/containerd/.+)($|/)
- --collector.netclass.ignored-devices=^(lxc|cilium_|qbr|qvb|qvo|ovs-system).*$
- --collector.netdev.device-exclude=^(lxc|cilium_|qbr|qvb|qvo|ovs-system).*$
prometheus:
monitor:
relabelings:
- sourceLabels: ["__meta_kubernetes_pod_node_name"]
targetLabel: "instance"
- action: "labeldrop"
regex: "^(container|endpoint|namespace|pod|service)$"
additionalPrometheusRulesMap:
coredns:
groups:
- name: coredns
rules:
- alert: CoreDNSDown
expr: absent(up{job="coredns"} == 1)
for: 15m
labels:
severity: critical
- alert: CoreDNSLatencyHigh
expr: histogram_quantile(0.99, sum(rate(coredns_dns_request_duration_seconds_bucket{job="coredns"}[5m])) by(server, zone, le)) > 4
for: 10m
labels:
severity: critical
- alert: CoreDNSErrorsHigh
expr: sum(rate(coredns_dns_responses_total{job="coredns",rcode="SERVFAIL"}[5m])) / sum(rate(coredns_dns_responses_total{job="coredns"}[5m])) > 0.01
for: 10m
labels:
severity: warning
- alert: CoreDNSErrorsHigh
expr: sum(rate(coredns_dns_responses_total{job="coredns",rcode="SERVFAIL"}[5m])) / sum(rate(coredns_dns_responses_total{job="coredns"}[5m])) > 0.03
for: 10m
labels:
severity: critical
- name: coredns_forward
rules:
- alert: CoreDNSForwardLatencyHigh
expr: histogram_quantile(0.99, sum(rate(coredns_forward_request_duration_seconds_bucket{job="coredns"}[5m])) by(to, le)) > 4
for: 10m
labels:
severity: critical
- alert: CoreDNSForwardErrorsHigh
expr: sum(rate(coredns_forward_responses_total{job="coredns",rcode="SERVFAIL"}[5m])) / sum(rate(coredns_forward_responses_total{job="coredns"}[5m])) > 0.01
for: 10m
labels:
severity: warning
- alert: CoreDNSForwardErrorsHigh
expr: sum(rate(coredns_forward_responses_total{job="coredns",rcode="SERVFAIL"}[5m])) / sum(rate(coredns_forward_responses_total{job="coredns"}[5m])) > 0.03
for: 10m
labels:
severity: critical
- alert: CoreDNSForwardHealthcheckFailureCount
expr: sum(rate(coredns_forward_healthcheck_failures_total{job="coredns"}[5m])) by (to) > 0
for: 2m
labels:
severity: warning
- alert: CoreDNSForwardHealthcheckBrokenCount
expr: sum(rate(coredns_forward_healthcheck_broken_total{job="coredns"}[5m])) > 0
for: 2m
labels:
severity: critical
node-exporter-local:
groups:
- name: node
rules:
- alert: NodeHighLoadAverage
expr: node_load5 / count(node_cpu_seconds_total{mode="system"}) without (cpu, mode) > 1.5
for: 30m
labels:
severity: warning
- alert: NodeHighMemoryUsage
expr: (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 < 2.5
for: 2m
labels:
severity: critical
- alert: NodeHighCpuUsage
expr: sum by(instance)(irate(node_cpu_seconds_total{mode='idle'}[5m])) < 1
for: 2m
labels:
severity: warning
- alert: NodeLowEntropy
expr: node_entropy_available_bits < 1000
for: 5m
labels:
severity: warning
- name: softnet
rules:
- alert: NodeSoftNetTimesSqueezed
expr: sum(rate(node_softnet_times_squeezed_total[1m])) by (instance) > 10
for: 10m
labels:
severity: warning
- alert: NodeSoftNetDrops
expr: sum(rate(node_softnet_dropped_total[1m])) by (instance) != 0
for: 1m
labels:
severity: critical
- kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Secret
metadata:
name: kube-prometheus-stack-etcd-client-cert
namespace: monitoring
data:
ca.crt: "{{ _etcd_ca_crt.content }}"
healthcheck-client.crt: "{{ _etcd_healthcheck_client_crt.content }}"
healthcheck-client.key: "{{ _etcd_healthcheck_client_key.content }}"

View File

@ -47,5 +47,5 @@ backend apiserver
option ssl-hello-chk
balance roundrobin
{% for host in groups[kubernetes_control_plane_group] %}
server {{ host }} {{ hostvars[host]['ansible_host'] }}:16443 check
server {{ host }} {{ hostvars[host]['ansible_default_ipv4']['address'] }}:16443 check
{% endfor %}

View File

@ -7,7 +7,7 @@ nodeRegistration:
kubeletExtraArgs:
cgroups-per-qos: "false"
enforce-node-allocatable: ""
node-ip: "{{ ansible_host }}"
node-ip: "{{ ansible_default_ipv4.address }}"
---
apiVersion: kubeadm.k8s.io/v1beta3
kind: JoinConfiguration
@ -15,7 +15,7 @@ nodeRegistration:
kubeletExtraArgs:
cgroups-per-qos: "false"
enforce-node-allocatable: ""
node-ip: "{{ ansible_host }}"
node-ip: "{{ ansible_default_ipv4.address }}"
{% if (_kubernetes_bootstrap_node is not defined) or (_kubernetes_bootstrap_node is defined and inventory_hostname != _kubernetes_bootstrap_node) %}
discovery:
bootstrapToken:

View File

@ -0,0 +1,21 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: node-feature-discovery
helm_repository_repo_url: https://kubernetes-sigs.github.io/node-feature-discovery/charts
- cilium
- kube_prometheus_stack

View File

@ -0,0 +1,39 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- kubernetes.core.helm:
name: node-feature-discovery
chart_ref: node-feature-discovery/node-feature-discovery
chart_version: 0.10.0
release_namespace: monitoring
kubeconfig: /etc/kubernetes/admin.conf
values:
image:
repository: "{{ atmosphere_image_repository | default('us-docker.pkg.dev/vexxhost-infra/openstack') }}/node-feature-discovery"
tag: 0.10.0
master:
nodeSelector:
openstack-control-plane: enabled
worker:
config:
sources:
custom:
- name: ipmi
labels:
ipmi: "true"
matchFeatures:
- feature: kernel.loadedmodule
matchExpresions:
ipmi_msghandler:
op: Exists

View File

@ -0,0 +1,16 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
openstack_cli_packages:
- python3-openstackclient

View File

@ -0,0 +1,33 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Install OpenStack client
become: true
ansible.builtin.apt:
name: "{{ openstack_cli_packages }}"
- name: Generate OpenStack-Helm endpoints
ansible.builtin.include_role:
name: openstack_helm_endpoints
vars:
openstack_helm_endpoints_list: ["identity"]
- name: Generate openrc file
become: true
ansible.builtin.template:
src: openrc.j2
dest: /root/openrc
owner: root
group: root
mode: 0600

View File

@ -0,0 +1,12 @@
# {{ ansible_managed }}
export OS_IDENTITY_API_VERSION=3
export OS_AUTH_URL="{{ openstack_helm_endpoints['identity']['scheme']['public'] }}://{{ openstack_helm_endpoints['identity']['host_fqdn_override']['public']['host'] }}/v3"
export OS_AUTH_TYPE=password
export OS_REGION_NAME="{{ openstack_helm_endpoints['identity']['auth']['admin']['region_name'] }}"
export OS_USER_DOMAIN_NAME=Default
export OS_USERNAME="{{ openstack_helm_endpoints['identity']['auth']['admin']['username'] }}"
export OS_PASSWORD="{{ openstack_helm_endpoints['identity']['auth']['admin']['password'] }}"
export OS_PROJECT_DOMAIN_NAME=Default
export OS_PROJECT_NAME=admin

View File

@ -0,0 +1,23 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
openstack_helm_cinder_chart_repo_name: openstack-helm
openstack_helm_cinder_chart_repo_url: https://tarballs.opendev.org/openstack/openstack-helm/
openstack_helm_cinder_chart_name: cinder
openstack_helm_cinder_image_repository: "{{ atmosphere_image_repository | default('us-docker.pkg.dev/vexxhost-infra/openstack') }}"
openstack_helm_cinder_image_tag: 18.1.1.dev29-1
openstack_helm_cinder_heat_image_tag: wallaby
openstack_helm_cinder_values: {}

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: "{{ openstack_helm_cinder_chart_repo_name }}"
helm_repository_repo_url: "{{ openstack_helm_cinder_chart_repo_url }}"

View File

@ -0,0 +1,41 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Generate OpenStack-Helm endpoints
ansible.builtin.include_role:
name: openstack_helm_endpoints
vars:
openstack_helm_endpoints_repo_name: "{{ openstack_helm_cinder_chart_repo_name }}"
openstack_helm_endpoints_repo_url: "{{ openstack_helm_cinder_chart_repo_url }}"
openstack_helm_endpoints_chart: "{{ openstack_helm_cinder_chart_name }}"
- name: Deploy Helm chart
kubernetes.core.helm:
name: "{{ openstack_helm_cinder_chart_name }}"
chart_ref: "{{ openstack_helm_cinder_chart_repo_name }}/{{ openstack_helm_cinder_chart_name }}"
chart_version: 0.2.15
release_namespace: openstack
kubeconfig: /etc/kubernetes/admin.conf
values: "{{ _openstack_helm_cinder_values | combine(openstack_helm_cinder_values, recursive=True) }}"
- name: Create Ingress
ansible.builtin.include_role:
name: openstack_helm_ingress
vars:
openstack_helm_ingress_endpoint: volumev3
openstack_helm_ingress_service_name: cinder-api
openstack_helm_ingress_service_port: 8776
openstack_helm_ingress_annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/proxy-request-buffering: "off"

View File

@ -0,0 +1,61 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
_openstack_helm_cinder_values:
endpoints: "{{ openstack_helm_endpoints }}"
images:
tags:
bootstrap: "{{ openstack_helm_cinder_image_repository }}/heat:{{ openstack_helm_cinder_heat_image_tag }}"
cinder_api: "{{ openstack_helm_cinder_image_repository }}/cinder:{{ openstack_helm_cinder_image_tag }}"
cinder_backup_storage_init: "{{ openstack_helm_cinder_image_repository }}/cinder:{{ openstack_helm_cinder_image_tag }}"
cinder_backup: "{{ openstack_helm_cinder_image_repository }}/cinder:{{ openstack_helm_cinder_image_tag }}"
cinder_db_sync: "{{ openstack_helm_cinder_image_repository }}/cinder:{{ openstack_helm_cinder_image_tag }}"
cinder_scheduler: "{{ openstack_helm_cinder_image_repository }}/cinder:{{ openstack_helm_cinder_image_tag }}"
cinder_storage_init: "{{ openstack_helm_cinder_image_repository }}/cinder:{{ openstack_helm_cinder_image_tag }}"
cinder_volume_usage_audit: "{{ openstack_helm_cinder_image_repository }}/cinder:{{ openstack_helm_cinder_image_tag }}"
cinder_volume: "{{ openstack_helm_cinder_image_repository }}/cinder:{{ openstack_helm_cinder_image_tag }}"
db_drop: "{{ openstack_helm_cinder_image_repository }}/heat:{{ openstack_helm_cinder_heat_image_tag }}"
db_init: "{{ openstack_helm_cinder_image_repository }}/heat:{{ openstack_helm_cinder_heat_image_tag }}"
dep_check: "{{ openstack_helm_cinder_image_repository }}/kubernetes-entrypoint:latest"
ks_endpoints: "{{ openstack_helm_cinder_image_repository }}/heat:{{ openstack_helm_cinder_heat_image_tag }}"
ks_service: "{{ openstack_helm_cinder_image_repository }}/heat:{{ openstack_helm_cinder_heat_image_tag }}"
ks_user: "{{ openstack_helm_cinder_image_repository }}/heat:{{ openstack_helm_cinder_heat_image_tag }}"
rabbit_init: "{{ openstack_helm_cinder_image_repository }}/rabbitmq:3.8.23-management"
pod:
replicas:
api: 3
scheduler: 3
conf:
paste:
composite:openstack_volume_api_v3:
use: call:cinder.api.middleware.auth:pipeline_factory
noauth: cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler noauth apiv3
keystone: cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext apiv3
keystone_nolimit: cors http_proxy_to_wsgi request_id faultwrap sizelimit osprofiler authtoken keystonecontext apiv3
cinder:
DEFAULT:
allowed_direct_url_schemes: cinder
backup_driver: cinder.backup.drivers.ceph.CephBackupDriver
log_config_append: null
os_region_name: "{{ openstack_helm_endpoints['identity']['auth']['cinder']['region_name'] }}"
volume_usage_audit_period: hour
volume_name_template: volume-%s
barbican:
barbican_endpoint_type: internal
cors:
allowed_origins: "*"
manifests:
ingress_api: false
job_clean: false
service_ingress_api: false

View File

@ -0,0 +1,102 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# Base configuration
openstack_helm_endpoints_region_name: "{{ undef(hint='You must specify an OpenStack region name') }}"
openstack_helm_endpoints_config: {}
# RabbitMQ
openstack_helm_endpoints_rabbitmq_erlang_cookie: "{{ undef(hint='You must specify an RabbitMQ Erlang cookie') }}"
openstack_helm_endpoints_rabbitmq_admin_password: "{{ undef(hint='You must specify a RabbitMQ admin password') }}"
# Memcached
openstack_helm_endpoints_memcached_secret_key: "{{ undef(hint='You must specify a Memcached secret key') }}"
# Keystone
openstack_helm_endpoints_keystone_api_host: "{{ undef(hint='You must specify a Keystone API hostname') }}"
openstack_helm_endpoints_keystone_region_name: "{{ openstack_helm_endpoints_region_name }}"
openstack_helm_endpoints_keystone_admin_password: "{{ undef(hint='You must specify a Keystone administrator password') }}"
openstack_helm_endpoints_keystone_mariadb_password: "{{ undef(hint='You must specify a Keystone MariaDB password') }}"
openstack_helm_endpoints_keystone_rabbitmq_password: "{{ undef(hint='You must specify a Keystone RabbitMQ password') }}"
# Glance
openstack_helm_endpoints_glance_api_host: "{{ undef(hint='You must specify a Glance API hostname') }}"
openstack_helm_endpoints_glance_region_name: "{{ openstack_helm_endpoints_region_name }}"
openstack_helm_endpoints_glance_keystone_password: "{{ undef(hint='You must specify a Glance Keystone password') }}"
openstack_helm_endpoints_glance_mariadb_password: "{{ undef(hint='You must specify a Glance MariaDB password') }}"
openstack_helm_endpoints_glance_rabbitmq_password: "{{ undef(hint='You must specify a Glance RabbitMQ password') }}"
# Cinder
openstack_helm_endpoints_cinder_api_host: "{{ undef(hint='You must specify a Cinder API hostname') }}"
openstack_helm_endpoints_cinder_region_name: "{{ openstack_helm_endpoints_region_name }}"
openstack_helm_endpoints_cinder_keystone_password: "{{ undef(hint='You must specify a Cinder Keystone password') }}"
openstack_helm_endpoints_cinder_mariadb_password: "{{ undef(hint='You must specify a Cinder MariaDB password') }}"
openstack_helm_endpoints_cinder_rabbitmq_password: "{{ undef(hint='You must specify a Cinder RabbitMQ password') }}"
# Placement
openstack_helm_endpoints_placement_api_host: "{{ undef(hint='You must specify a Placement API hostname') }}"
openstack_helm_endpoints_placement_region_name: "{{ openstack_helm_endpoints_region_name }}"
openstack_helm_endpoints_placement_keystone_password: "{{ undef(hint='You must specify a Placement Keystone password') }}"
openstack_helm_endpoints_placement_mariadb_password: "{{ undef(hint='You must specify a Placement MariaDB password') }}"
# Neutron
openstack_helm_endpoints_neutron_api_host: "{{ undef(hint='You must specify a Neutron API hostname') }}"
openstack_helm_endpoints_neutron_region_name: "{{ openstack_helm_endpoints_region_name }}"
openstack_helm_endpoints_neutron_keystone_password: "{{ undef(hint='You must specify a Neutron Keystone password') }}"
openstack_helm_endpoints_neutron_mariadb_password: "{{ undef(hint='You must specify a Neutron MariaDB password') }}"
openstack_helm_endpoints_neutron_rabbitmq_password: "{{ undef(hint='You must specify a Neutron RabbitMQ password') }}"
openstack_helm_endpoints_neutron_metadata_secret: "{{ undef(hint='You must specify a Neutron metadata secret') }}"
# Nova
openstack_helm_endpoints_nova_api_host: "{{ undef(hint='You must specify a Nova API hostname') }}"
openstack_helm_endpoints_nova_novnc_host: "{{ undef(hint='You must specify a Nova NoVNC hostname') }}"
openstack_helm_endpoints_nova_region_name: "{{ openstack_helm_endpoints_region_name }}"
openstack_helm_endpoints_nova_keystone_password: "{{ undef(hint='You must specify a Nova Keystone password') }}"
openstack_helm_endpoints_nova_mariadb_password: "{{ undef(hint='You must specify a Nova MariaDB password') }}"
openstack_helm_endpoints_nova_rabbitmq_password: "{{ undef(hint='You must specify a Nova RabbitMQ password') }}"
# Ironic
openstack_helm_endpoints_ironic_api_host: "{{ undef(hint='You must specify an Ironic API hostname') }}"
openstack_helm_endpoints_ironic_region_name: "{{ openstack_helm_endpoints_region_name }}"
openstack_helm_endpoints_ironic_keystone_password: "{{ undef(hint='You must specify an Ironic Keystone password') }}"
openstack_helm_endpoints_ironic_mariadb_password: "{{ undef(hint='You must specify an Ironic MariaDB password') }}"
openstack_helm_endpoints_ironic_rabbitmq_password: "{{ undef(hint='You must specify an Ironic RabbitMQ password') }}"
# Designate
openstack_helm_endpoints_designate_api_host: "{{ undef(hint='You must specify a Designate API hostname') }}"
openstack_helm_endpoints_designate_region_name: "{{ openstack_helm_endpoints_region_name }}"
openstack_helm_endpoints_designate_keystone_password: "{{ undef(hint='You must specify a Designate Keystone password') }}"
openstack_helm_endpoints_designate_mariadb_password: "{{ undef(hint='You must specify a Designate MariaDB password') }}"
openstack_helm_endpoints_designate_rabbitmq_password: "{{ undef(hint='You must specify a Designate RabbitMQ password') }}"
# Octavia
openstack_helm_endpoints_octavia_api_host: "{{ undef(hint='You must specify an Octavia API hostname') }}"
openstack_helm_endpoints_octavia_region_name: "{{ openstack_helm_endpoints_region_name }}"
openstack_helm_endpoints_octavia_keystone_password: "{{ undef(hint='You must specify an Octavia Keystone password') }}"
openstack_helm_endpoints_octavia_mariadb_password: "{{ undef(hint='You must specify an Octavia MariaDB password') }}"
openstack_helm_endpoints_octavia_rabbitmq_password: "{{ undef(hint='You must specify an Octavia RabbitMQ password') }}"
# Heat
openstack_helm_endpoints_heat_api_host: "{{ undef(hint='You must specify a Heat API hostname') }}"
openstack_helm_endpoints_heat_region_name: "{{ openstack_helm_endpoints_region_name }}"
openstack_helm_endpoints_heat_keystone_password: "{{ undef(hint='You must specify a Heat Keystone password') }}"
openstack_helm_endpoints_heat_trustee_keystone_password: "{{ undef(hint='You must specify a Heat trustee Keystone password') }}"
openstack_helm_endpoints_heat_stack_user_keystone_password: "{{ undef(hint='You must specify a Heat stack user Keystone password') }}"
openstack_helm_endpoints_heat_mariadb_password: "{{ undef(hint='You must specify a Heat MariaDB password') }}"
openstack_helm_endpoints_heat_rabbitmq_password: "{{ undef(hint='You must specify a Heat RabbitMQ password') }}"
openstack_helm_endpoints_heat_cfn_api_host: "{{ undef(hint='You must specify a Heat CloudFormation API hostname') }}"
# Horizon
openstack_helm_endpoints_horizon_api_host: "{{ undef(hint='You must specify a Horizon API hostname') }}"
openstack_helm_endpoints_horizon_mariadb_password: "{{ undef(hint='You must specify a Horizon MariaDB password') }}"

View File

@ -0,0 +1,65 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Get Helm values if chart is provided
block:
- name: Get the default values for the Helm chart
ansible.builtin.shell: helm show values {{ openstack_helm_endpoints_repo_name }}/{{ openstack_helm_endpoints_chart }}
changed_when: false
register: _helm_show_values
- name: Retrieve list of all the needed endpoints
ansible.builtin.set_fact:
openstack_helm_endpoints_list: "{{ _helm_show_values.stdout | from_yaml | community.general.json_query('keys(endpoints)') | difference(_openstack_helm_endpoints_ignore) }}"
when:
- openstack_helm_endpoints_list is not defined or openstack_helm_endpoints_list == None
# NOTE(mnaser): Since we deploy the database using the operator and we let it
# generate the root password, we look it up if the fact has not
# been cached from a previous run.
- name: Append endpoints for "oslo_db"
block:
- name: Grab Percona XtraDB cluster secret
kubernetes.core.k8s_info:
api_version: v1
kind: Secret
name: percona-xtradb
namespace: openstack
register: _openstack_helm_endpoints_oslo_db_secret
- name: Cache fact with Percona XtraDB password
ansible.builtin.set_fact:
openstack_helm_endpoints_maridb_admin_password: "{{ _openstack_helm_endpoints_oslo_db_secret.resources[0]['data']['root'] | b64decode }}"
when:
- '"oslo_db" in openstack_helm_endpoints_list'
- openstack_helm_endpoints_maridb_admin_password is not defined
- name: Reset value for OpenStack_Helm endpoints
ansible.builtin.set_fact:
openstack_helm_endpoints: "{{ openstack_helm_endpoints_config }}"
- name: Generate OpenStack-Helm endpoints
ansible.builtin.set_fact:
openstack_helm_endpoints: |
{{ openstack_helm_endpoints | combine(lookup('vars', '_openstack_helm_endpoints_' + service), recursive=True) }}
loop: "{{ openstack_helm_endpoints_list }}"
loop_control:
loop_var: service
# NOTE(mnaser): Since we use `openstack_helm_endpoints_list` to ensure that we
# have a common entry for endpoints and stay DRY, we need to
# reset the fact so it works for follow-up requests.
- name: Clean-up facts
ansible.builtin.set_fact:
openstack_helm_endpoints_list:

View File

@ -0,0 +1,378 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
_openstack_helm_endpoints_ignore:
- ceph_object_store
- cloudwatch
- cluster_domain_suffix
- compute_spice_proxy
- fluentd
- ingress
- kube_dns
- ldap
- local_image_registry
- monitoring
- object_store
- prometheus_rabbitmq_exporter
_openstack_helm_endpoints_oslo_db:
oslo_db:
auth:
admin:
password: "{{ openstack_helm_endpoints_maridb_admin_password }}"
hosts:
default: percona-xtradb-haproxy
_openstack_helm_endpoints_oslo_messaging:
oslo_messaging:
auth:
erlang_cookie: "{{ openstack_helm_endpoints_rabbitmq_erlang_cookie }}"
user:
password: "{{ openstack_helm_endpoints_rabbitmq_admin_password }}"
# NOTE(mnaser): The following is not actually used by the chart, however,
# since we are actually doing dynamic lookups to generate
# endpoints, we add it here.
admin:
password: "{{ openstack_helm_endpoints_rabbitmq_admin_password }}"
statefulset:
replicas: 3
_openstack_helm_endpoints_oslo_cache:
oslo_cache:
auth:
memcache_secret_key: "{{ openstack_helm_endpoints_memcached_secret_key }}"
_openstack_helm_endpoints_identity:
identity:
auth:
admin:
region_name: "{{ openstack_helm_endpoints_keystone_region_name }}"
username: "admin-{{ openstack_helm_endpoints_keystone_region_name }}"
password: "{{ openstack_helm_endpoints_keystone_admin_password }}"
hosts:
default: keystone-api
scheme:
public: https
host_fqdn_override:
public:
host: "{{ openstack_helm_endpoints_keystone_api_host }}"
port:
api:
default: 5000
public: 443
oslo_db:
auth:
keystone:
password: "{{ openstack_helm_endpoints_keystone_mariadb_password }}"
oslo_messaging:
auth:
keystone:
password: "{{ openstack_helm_endpoints_keystone_rabbitmq_password }}"
_openstack_helm_endpoints_image:
identity:
auth:
glance:
region_name: "{{ openstack_helm_endpoints_glance_region_name }}"
username: "glance-{{ openstack_helm_endpoints_glance_region_name }}"
password: "{{ openstack_helm_endpoints_glance_keystone_password }}"
image:
scheme:
public: https
host_fqdn_override:
public:
host: "{{ openstack_helm_endpoints_glance_api_host }}"
port:
api:
public: 443
oslo_db:
auth:
glance:
password: "{{ openstack_helm_endpoints_glance_mariadb_password }}"
oslo_messaging:
auth:
glance:
password: "{{ openstack_helm_endpoints_glance_rabbitmq_password }}"
_openstack_helm_endpoints_volumev3:
identity:
auth:
cinder:
region_name: "{{ openstack_helm_endpoints_cinder_region_name }}"
username: "cinder-{{ openstack_helm_endpoints_cinder_region_name }}"
password: "{{ openstack_helm_endpoints_cinder_keystone_password }}"
volumev3:
scheme:
public: https
host_fqdn_override:
public:
host: "{{ openstack_helm_endpoints_cinder_api_host }}"
port:
api:
public: 443
oslo_db:
auth:
cinder:
password: "{{ openstack_helm_endpoints_cinder_mariadb_password }}"
oslo_messaging:
auth:
cinder:
password: "{{ openstack_helm_endpoints_cinder_rabbitmq_password }}"
_openstack_helm_endpoints_placement:
identity:
auth:
placement:
region_name: "{{ openstack_helm_endpoints_placement_region_name }}"
username: "placement-{{ openstack_helm_endpoints_placement_region_name }}"
password: "{{ openstack_helm_endpoints_placement_keystone_password }}"
oslo_db:
auth:
placement:
password: "{{ openstack_helm_endpoints_placement_mariadb_password }}"
placement:
scheme:
public: https
host_fqdn_override:
public:
host: "{{ openstack_helm_endpoints_placement_api_host }}"
port:
api:
public: 443
_openstack_helm_endpoints_network:
identity:
auth:
neutron:
region_name: "{{ openstack_helm_endpoints_neutron_region_name }}"
username: "neutron-{{ openstack_helm_endpoints_neutron_region_name }}"
password: "{{ openstack_helm_endpoints_neutron_keystone_password }}"
network:
scheme:
public: https
host_fqdn_override:
public:
host: "{{ openstack_helm_endpoints_neutron_api_host }}"
port:
api:
public: 443
oslo_db:
auth:
neutron:
password: "{{ openstack_helm_endpoints_neutron_mariadb_password }}"
oslo_messaging:
auth:
neutron:
password: "{{ openstack_helm_endpoints_neutron_rabbitmq_password }}"
_openstack_helm_endpoints_compute:
identity:
auth:
nova:
region_name: "{{ openstack_helm_endpoints_nova_region_name }}"
username: "nova-{{ openstack_helm_endpoints_nova_region_name }}"
password: "{{ openstack_helm_endpoints_nova_keystone_password }}"
compute:
scheme:
public: https
host_fqdn_override:
public:
host: "{{ openstack_helm_endpoints_nova_api_host }}"
port:
api:
public: 443
oslo_db:
auth:
nova:
password: "{{ openstack_helm_endpoints_nova_mariadb_password }}"
oslo_messaging:
auth:
nova:
password: "{{ openstack_helm_endpoints_nova_rabbitmq_password }}"
_openstack_helm_endpoints_oslo_db_api:
oslo_db_api:
auth:
admin:
password: "{{ openstack_helm_endpoints_maridb_admin_password }}"
nova:
password: "{{ openstack_helm_endpoints_nova_mariadb_password }}"
hosts:
default: percona-xtradb-haproxy
_openstack_helm_endpoints_oslo_db_cell0:
oslo_db_cell0:
auth:
admin:
password: "{{ openstack_helm_endpoints_maridb_admin_password }}"
nova:
password: "{{ openstack_helm_endpoints_nova_mariadb_password }}"
hosts:
default: percona-xtradb-haproxy
_openstack_helm_endpoints_compute_metadata:
compute_metadata:
secret: "{{ openstack_helm_endpoints_neutron_metadata_secret }}"
hosts:
public: nova-metadata
port:
metadata:
public: 8775
_openstack_helm_endpoints_compute_novnc_proxy:
compute_novnc_proxy:
scheme:
public: https
host_fqdn_override:
public:
host: "{{ openstack_helm_endpoints_nova_novnc_host }}"
port:
novnc_proxy:
public: 443
_openstack_helm_endpoints_baremetal:
identity:
auth:
ironic:
region_name: "{{ openstack_helm_endpoints_ironic_region_name }}"
username: "ironic-{{ openstack_helm_endpoints_ironic_region_name }}"
password: "{{ openstack_helm_endpoints_ironic_keystone_password }}"
baremetal:
scheme:
public: https
host_fqdn_override:
public:
host: "{{ openstack_helm_endpoints_ironic_api_host }}"
port:
api:
public: 443
oslo_db:
auth:
ironic:
password: "{{ openstack_helm_endpoints_ironic_mariadb_password }}"
oslo_messaging:
auth:
ironic:
password: "{{ openstack_helm_endpoints_ironic_rabbitmq_password }}"
_openstack_helm_endpoints_dns:
identity:
auth:
designate:
region_name: "{{ openstack_helm_endpoints_designate_region_name }}"
username: "desigante-{{ openstack_helm_endpoints_designate_region_name }}"
password: "{{ openstack_helm_endpoints_designate_keystone_password }}"
dns:
scheme:
public: https
host_fqdn_override:
public:
host: "{{ openstack_helm_endpoints_designate_api_host }}"
port:
api:
public: 443
oslo_db:
auth:
designate:
password: "{{ openstack_helm_endpoints_designate_mariadb_password }}"
oslo_messaging:
auth:
designate:
password: "{{ openstack_helm_endpoints_designate_rabbitmq_password }}"
_openstack_helm_endpoints_load_balancer:
identity:
auth:
octavia:
region_name: "{{ openstack_helm_endpoints_octavia_region_name }}"
username: "octavia-{{ openstack_helm_endpoints_octavia_region_name }}"
password: "{{ openstack_helm_endpoints_octavia_keystone_password }}"
load_balancer:
scheme:
public: https
host_fqdn_override:
public:
host: "{{ openstack_helm_endpoints_octavia_api_host }}"
port:
api:
public: 443
oslo_db:
auth:
octavia:
password: "{{ openstack_helm_endpoints_octavia_mariadb_password }}"
oslo_messaging:
auth:
octavia:
password: "{{ openstack_helm_endpoints_octavia_rabbitmq_password }}"
_openstack_helm_endpoints_cloudformation:
cloudformation:
scheme:
public: https
host_fqdn_override:
public:
host: "{{ openstack_helm_endpoints_heat_cfn_api_host }}"
port:
api:
public: 443
_openstack_helm_endpoints_orchestration:
identity:
auth:
heat:
region_name: "{{ openstack_helm_endpoints_heat_region_name }}"
username: "heat-{{ openstack_helm_endpoints_heat_region_name }}"
password: "{{ openstack_helm_endpoints_heat_keystone_password }}"
heat_trustee:
region_name: "{{ openstack_helm_endpoints_heat_region_name }}"
username: "heat-trustee-{{ openstack_helm_endpoints_heat_region_name }}"
password: "{{ openstack_helm_endpoints_heat_trustee_keystone_password }}"
heat_stack_user:
region_name: "{{ openstack_helm_endpoints_heat_region_name }}"
username: "heat-stack-user-{{ openstack_helm_endpoints_heat_region_name }}"
password: "{{ openstack_helm_endpoints_heat_stack_user_keystone_password }}"
path:
public: /v3
orchestration:
scheme:
public: https
host_fqdn_override:
public:
host: "{{ openstack_helm_endpoints_heat_api_host }}"
port:
api:
public: 443
oslo_db:
auth:
heat:
password: "{{ openstack_helm_endpoints_heat_mariadb_password }}"
oslo_messaging:
auth:
heat:
password: "{{ openstack_helm_endpoints_heat_rabbitmq_password }}"
_openstack_helm_endpoints_dashboard:
dashboard:
scheme:
public: https
host_fqdn_override:
public:
host: "{{ openstack_helm_endpoints_horizon_api_host }}"
port:
api:
public: 443
oslo_db:
auth:
horizon:
password: "{{ openstack_helm_endpoints_horizon_mariadb_password }}"

View File

@ -0,0 +1,23 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
openstack_helm_glance_chart_repo_name: openstack-helm
openstack_helm_glance_chart_repo_url: https://tarballs.opendev.org/openstack/openstack-helm/
openstack_helm_glance_chart_name: glance
openstack_helm_glance_image_repository: "{{ atmosphere_image_repository | default('us-docker.pkg.dev/vexxhost-infra/openstack') }}"
openstack_helm_glance_image_tag: 22.1.1.dev2-1
openstack_helm_glance_heat_image_tag: wallaby
openstack_helm_glance_values: {}

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: "{{ openstack_helm_glance_chart_repo_name }}"
helm_repository_repo_url: "{{ openstack_helm_glance_chart_repo_url }}"

View File

@ -0,0 +1,41 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Generate OpenStack-Helm endpoints
ansible.builtin.include_role:
name: openstack_helm_endpoints
vars:
openstack_helm_endpoints_repo_name: "{{ openstack_helm_glance_chart_repo_name }}"
openstack_helm_endpoints_repo_url: "{{ openstack_helm_glance_chart_repo_url }}"
openstack_helm_endpoints_chart: "{{ openstack_helm_glance_chart_name }}"
- name: Deploy Helm chart
kubernetes.core.helm:
name: "{{ openstack_helm_glance_chart_name }}"
chart_ref: "{{ openstack_helm_glance_chart_repo_name }}/{{ openstack_helm_glance_chart_name }}"
chart_version: 0.2.10
release_namespace: openstack
kubeconfig: /etc/kubernetes/admin.conf
values: "{{ _openstack_helm_glance_values | combine(openstack_helm_glance_values, recursive=True) }}"
- name: Create Ingress
ansible.builtin.include_role:
name: openstack_helm_ingress
vars:
openstack_helm_ingress_endpoint: image
openstack_helm_ingress_service_name: glance-api
openstack_helm_ingress_service_port: 9292
openstack_helm_ingress_annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.ingress.kubernetes.io/proxy-request-buffering: "off"

View File

@ -0,0 +1,51 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
_openstack_helm_glance_values:
endpoints: "{{ openstack_helm_endpoints }}"
storage: rbd
images:
tags:
bootstrap: "{{ openstack_helm_glance_image_repository }}/heat:{{ openstack_helm_glance_heat_image_tag }}"
db_drop: "{{ openstack_helm_glance_image_repository }}/heat:{{ openstack_helm_glance_heat_image_tag }}"
db_init: "{{ openstack_helm_glance_image_repository }}/heat:{{ openstack_helm_glance_heat_image_tag }}"
dep_check: "{{ openstack_helm_glance_image_repository }}/kubernetes-entrypoint:latest"
glance_api: "{{ openstack_helm_glance_image_repository }}/glance:{{ openstack_helm_glance_image_tag }}"
glance_db_sync: "{{ openstack_helm_glance_image_repository }}/glance:{{ openstack_helm_glance_image_tag }}"
glance_metadefs_load: "{{ openstack_helm_glance_image_repository }}/glance:{{ openstack_helm_glance_image_tag }}"
glance_registry: "{{ openstack_helm_glance_image_repository }}/glance:{{ openstack_helm_glance_image_tag }}"
glance_storage_init: "{{ openstack_helm_glance_image_repository }}/glance:{{ openstack_helm_glance_image_tag }}"
ks_endpoints: "{{ openstack_helm_glance_image_repository }}/heat:{{ openstack_helm_glance_heat_image_tag }}"
ks_service: "{{ openstack_helm_glance_image_repository }}/heat:{{ openstack_helm_glance_heat_image_tag }}"
ks_user: "{{ openstack_helm_glance_image_repository }}/heat:{{ openstack_helm_glance_heat_image_tag }}"
rabbit_init: "{{ openstack_helm_glance_image_repository }}/rabbitmq:3.8.23-management"
bootstrap:
enabled: false
pod:
replicas:
api: 3
conf:
glance:
DEFAULT:
log_config_append: null
show_image_direct_url: true
show_multiple_locations: true
enable_import_methods: "[]"
cors:
allowed_origins: "*"
image_formats:
disk_formats: "qcow2,raw"
manifests:
ingress_api: false
service_ingress_api: false

View File

@ -0,0 +1,27 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
openstack_helm_heat_chart_repo_name: openstack-helm
openstack_helm_heat_chart_repo_url: https://tarballs.opendev.org/openstack/openstack-helm/
openstack_helm_heat_chart_name: heat
openstack_helm_heat_image_repository: "{{ atmosphere_image_repository | default('us-docker.pkg.dev/vexxhost-infra/openstack') }}"
openstack_helm_heat_image_tag: 16.0.1.dev16
openstack_helm_heat_auth_encryption_key: "{{ undef(hint='You must specifiy an encryption key for Heat.') }}"
openstack_helm_heat_diff: false
openstack_helm_heat_migrate_from_mariadb: false
openstack_helm_heat_values: {}

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: "{{ openstack_helm_heat_chart_repo_name }}"
helm_repository_repo_url: "{{ openstack_helm_heat_chart_repo_url }}"

View File

@ -0,0 +1,74 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Generate OpenStack-Helm endpoints
ansible.builtin.include_role:
name: openstack_helm_endpoints
vars:
openstack_helm_endpoints_repo_name: "{{ openstack_helm_heat_chart_repo_name }}"
openstack_helm_endpoints_repo_url: "{{ openstack_helm_heat_chart_repo_url }}"
openstack_helm_endpoints_chart: "{{ openstack_helm_heat_chart_name }}"
- name: Generate Helm values comparison
ansible.builtin.include_role:
name: helm_diff
vars:
helm_diff_release_name: "{{ openstack_helm_heat_chart_name }}"
helm_diff_release_namespace: openstack
helm_diff_values: "{{ _openstack_helm_heat_values }}"
when:
- openstack_helm_heat_diff | bool
- name: Migrate database from MariaDB to Percona XtraDB Cluster
ansible.builtin.include_role:
name: openstack_helm_migrate_to_percona_xtradb_cluster
vars:
openstack_helm_migrate_to_percona_xtradb_cluster_release_name: "{{ openstack_helm_heat_chart_name }}"
openstack_helm_migrate_to_percona_xtradb_cluster_release_namespace: openstack
openstack_helm_migrate_to_percona_xtradb_cluster_databases:
- heat
openstack_helm_migrate_to_percona_xtradb_cluster_services:
- kind: Deployment
name: heat-api
- kind: Deployment
name: heat-cfn
- kind: Deployment
name: heat-engine
when:
- openstack_helm_heat_migrate_from_mariadb | bool
- name: Deploy Helm chart
kubernetes.core.helm:
name: "{{ openstack_helm_heat_chart_name }}"
chart_ref: "{{ openstack_helm_heat_chart_repo_name }}/{{ openstack_helm_heat_chart_name }}"
chart_version: 0.2.8
release_namespace: openstack
kubeconfig: /etc/kubernetes/admin.conf
values: "{{ _openstack_helm_heat_values }}"
- name: Create Ingress
ansible.builtin.include_role:
name: openstack_helm_ingress
vars:
openstack_helm_ingress_endpoint: orchestration
openstack_helm_ingress_service_name: heat-api
openstack_helm_ingress_service_port: 8004
- name: Create Ingress
ansible.builtin.include_role:
name: openstack_helm_ingress
vars:
openstack_helm_ingress_endpoint: cloudformation
openstack_helm_ingress_service_name: heat-cfn
openstack_helm_ingress_service_port: 8000

View File

@ -0,0 +1,54 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
_openstack_helm_heat_values: "{{ __openstack_helm_heat_values | combine(openstack_helm_heat_values, recursive=True) }}"
__openstack_helm_heat_values:
endpoints: "{{ openstack_helm_endpoints }}"
images:
tags:
bootstrap: "{{ openstack_helm_heat_image_repository }}/heat:{{ openstack_helm_heat_image_tag }}"
db_drop: "{{ openstack_helm_heat_image_repository }}/heat:{{ openstack_helm_heat_image_tag }}"
db_init: "{{ openstack_helm_heat_image_repository }}/heat:{{ openstack_helm_heat_image_tag }}"
dep_check: "{{ openstack_helm_heat_image_repository }}/kubernetes-entrypoint:latest"
heat_api: "{{ openstack_helm_heat_image_repository }}/heat:{{ openstack_helm_heat_image_tag }}"
heat_cfn: "{{ openstack_helm_heat_image_repository }}/heat:{{ openstack_helm_heat_image_tag }}"
heat_cloudwatch: "{{ openstack_helm_heat_image_repository }}/heat:{{ openstack_helm_heat_image_tag }}"
heat_db_sync: "{{ openstack_helm_heat_image_repository }}/heat:{{ openstack_helm_heat_image_tag }}"
heat_engine_cleaner: "{{ openstack_helm_heat_image_repository }}/heat:{{ openstack_helm_heat_image_tag }}"
heat_engine: "{{ openstack_helm_heat_image_repository }}/heat:{{ openstack_helm_heat_image_tag }}"
heat_purge_deleted: "{{ openstack_helm_heat_image_repository }}/heat:{{ openstack_helm_heat_image_tag }}"
ks_endpoints: "{{ openstack_helm_heat_image_repository }}/heat:{{ openstack_helm_heat_image_tag }}"
ks_service: "{{ openstack_helm_heat_image_repository }}/heat:{{ openstack_helm_heat_image_tag }}"
ks_user: "{{ openstack_helm_heat_image_repository }}/heat:{{ openstack_helm_heat_image_tag }}"
rabbit_init: "{{ openstack_helm_heat_image_repository }}/rabbitmq:3.8.23-management"
pod:
replicas:
api: 3
cfn: 3
cloudwatch: 3
engine: 3
conf:
heat:
DEFAULT:
auth_encryption_key: "{{ openstack_helm_heat_auth_encryption_key }}"
log_config_append: null
region_name_for_services: "{{ openstack_helm_endpoints['identity']['auth']['heat']['region_name'] }}"
server_keystone_endpoint_type: public
clients_keystone:
endpoint_type: publicURL
manifests:
ingress_api: false
ingress_cfn: false
service_ingress_api: false
service_ingress_cfn: false

View File

@ -0,0 +1,23 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
openstack_helm_horizon_chart_repo_name: openstack-helm
openstack_helm_horizon_chart_repo_url: https://tarballs.opendev.org/openstack/openstack-helm/
openstack_helm_horizon_chart_name: horizon
openstack_helm_horizon_image_repository: "{{ atmosphere_image_repository | default('us-docker.pkg.dev/vexxhost-infra/openstack') }}"
openstack_helm_horizon_image_tag: 19.2.1.dev13
openstack_helm_horizon_heat_image_tag: wallaby
openstack_helm_horizon_values: {}

View File

@ -0,0 +1,56 @@
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
# Service group names (global across all projects):
MONITORING_SERVICES_GROUPS = [
{'name': _('OpenStack Services'), 'groupBy': 'service'},
{'name': _('Servers'), 'groupBy': 'hostname'}
]
# Services being monitored
MONITORING_SERVICES = getattr(
settings,
'MONITORING_SERVICES_GROUPS',
MONITORING_SERVICES_GROUPS
)
MONITORING_SERVICE_VERSION = getattr(
settings, 'MONITORING_SERVICE_VERSION', '2_0'
)
MONITORING_SERVICE_TYPE = getattr(
settings, 'MONITORING_SERVICE_TYPE', 'monitoring'
)
MONITORING_ENDPOINT_TYPE = getattr(
# NOTE(trebskit) # will default to OPENSTACK_ENDPOINT_TYPE
settings, 'MONITORING_ENDPOINT_TYPE', None
)
# Grafana button titles/file names (global across all projects):
# GRAFANA_LINKS = [{"raw": True, "path": "monasca-dashboard", "title": "Sub page1"}]
GRAFANA_LINKS = []
DASHBOARDS = getattr(settings, 'GRAFANA_LINKS', GRAFANA_LINKS)
GRAFANA_URL = {"regionOne": "/grafana"}
SHOW_GRAFANA_HOME = getattr(settings, 'SHOW_GRAFANA_HOME', True)
ENABLE_LOG_MANAGEMENT_BUTTON = getattr(
settings, 'ENABLE_LOG_MANAGEMENT_BUTTON', False)
ENABLE_EVENT_MANAGEMENT_BUTTON = getattr(
settings, 'ENABLE_EVENT_MANAGEMENT_BUTTON', False)
KIBANA_POLICY_RULE = getattr(settings, 'KIBANA_POLICY_RULE',
'monitoring:kibana_access')
KIBANA_POLICY_SCOPE = getattr(settings, 'KIBANA_POLICY_SCOPE',
'monitoring')
KIBANA_HOST = getattr(settings, 'KIBANA_HOST',
'http://192.168.10.6:5601/')
OPENSTACK_SSL_NO_VERIFY = getattr(
settings, 'OPENSTACK_SSL_NO_VERIFY', False)
OPENSTACK_SSL_CACERT = getattr(
settings, 'OPENSTACK_SSL_CACERT', None)
POLICY_FILES = getattr(settings, 'POLICY_FILES', {})
POLICY_FILES.update({'monitoring': 'monitoring_policy.json', }) # noqa
setattr(settings, 'POLICY_FILES', POLICY_FILES)

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: "{{ openstack_helm_horizon_chart_repo_name }}"
helm_repository_repo_url: "{{ openstack_helm_horizon_chart_repo_url }}"

View File

@ -0,0 +1,46 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Generate OpenStack-Helm endpoints
ansible.builtin.include_role:
name: openstack_helm_endpoints
vars:
openstack_helm_endpoints_repo_name: "{{ openstack_helm_horizon_chart_repo_name }}"
openstack_helm_endpoints_repo_url: "{{ openstack_helm_horizon_chart_repo_url }}"
openstack_helm_endpoints_chart: "{{ openstack_helm_horizon_chart_name }}"
- name: Deploy Helm chart
kubernetes.core.helm:
name: "{{ openstack_helm_horizon_chart_name }}"
chart_ref: "{{ openstack_helm_horizon_chart_repo_name }}/{{ openstack_helm_horizon_chart_name }}"
chart_version: 0.2.16
release_namespace: openstack
kubeconfig: /etc/kubernetes/admin.conf
values: "{{ _openstack_helm_horizon_values | combine(openstack_helm_horizon_values, recursive=True) }}"
- name: Create Ingress
ansible.builtin.include_role:
name: openstack_helm_ingress
vars:
openstack_helm_ingress_endpoint: dashboard
openstack_helm_ingress_service_name: horizon-int
openstack_helm_ingress_service_port: 80
openstack_helm_ingress_paths:
- path: /
pathType: Prefix
backend:
service:
name: grafana
port:
number: 80

View File

@ -0,0 +1,60 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
_openstack_helm_horizon_values:
endpoints: "{{ openstack_helm_endpoints }}"
images:
tags:
bootstrap: "{{ openstack_helm_horizon_image_repository }}/heat:{{ openstack_helm_horizon_heat_image_tag }}"
db_drop: "{{ openstack_helm_horizon_image_repository }}/heat:{{ openstack_helm_horizon_heat_image_tag }}"
db_init: "{{ openstack_helm_horizon_image_repository }}/heat:{{ openstack_helm_horizon_heat_image_tag }}"
dep_check: "{{ openstack_helm_horizon_image_repository }}/kubernetes-entrypoint:latest"
ks_endpoints: "{{ openstack_helm_horizon_image_repository }}/heat:{{ openstack_helm_horizon_heat_image_tag }}"
ks_service: "{{ openstack_helm_horizon_image_repository }}/heat:{{ openstack_helm_horizon_heat_image_tag }}"
ks_user: "{{ openstack_helm_horizon_image_repository }}/heat:{{ openstack_helm_horizon_heat_image_tag }}"
horizon_db_sync: "{{ openstack_helm_horizon_image_repository }}/horizon:{{ openstack_helm_horizon_image_tag }}"
horizon: "{{ openstack_helm_horizon_image_repository }}/horizon:{{ openstack_helm_horizon_image_tag }}"
rabbit_init: "{{ openstack_helm_horizon_image_repository }}/rabbitmq:3.8.23-management"
pod:
replicas:
server: 3
conf:
horizon:
local_settings:
config:
secure_proxy_ssl_header: "True"
horizon_images_upload_mode: direct
openstack_enable_password_retrieve: "True"
raw:
WEBSSO_KEYSTONE_URL: "https://{{ openstack_helm_endpoints['identity']['scheme']['public'] }}://{{ openstack_helm_endpoints['identity']['host_fqdn_override']['public']['host'] }}/v3"
local_settings_d:
_50_monasca_ui_settings: "{{ lookup('file', '50-monasca-ui-settings.py') }}"
extra_panels:
- designatedashboard
- heat_dashboard
- ironic_ui
- magnum_ui
- monitoring
- neutron_vpnaas_dashboard
- octavia_dashboard
- senlin_dashboard
policy:
monitoring:
default: "@"
monasca_user_role: role:monasca-user
monitoring:monitoring: rule:monasca_user_role
monitoring:kibana_access: rule:monasca_user_role
manifests:
ingress_api: false
service_ingress_api: false

View File

@ -0,0 +1,23 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
openstack_helm_infra_ceph_provisioners_chart_repo_name: openstack-helm-infra
openstack_helm_infra_ceph_provisioners_chart_repo_url: https://tarballs.opendev.org/openstack/openstack-helm-infra/
openstack_helm_infra_ceph_provisioners_chart_name: ceph-provisioners
openstack_helm_infra_ceph_provisioners_ceph_monitors: "{{ _ceph_csi_rbd_helm_info.status['values']['csiConfig'][0]['monitors'] }}"
openstack_helm_infra_ceph_provisioners_ceph_fsid: "{{ _ceph_csi_rbd_helm_info.status['values']['csiConfig'][0]['clusterID'] }}"
openstack_helm_infra_ceph_provisioners_ceph_public_network: "{{ ceph_mon_public_network }}"
openstack_helm_infra_ceph_provisioners_ceph_cluster_network: "{{ openstack_helm_infra_ceph_provisioners_ceph_public_network }}"

View File

@ -0,0 +1,20 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: "{{ openstack_helm_infra_ceph_provisioners_chart_repo_name }}"
helm_repository_repo_url: "{{ openstack_helm_infra_ceph_provisioners_chart_repo_url }}"
- ceph_csi_rbd

View File

@ -0,0 +1,128 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Retrieve Helm values for "ceph-csi-rbd"
kubernetes.core.helm_info:
name: ceph-csi-rbd
release_namespace: kube-system
register: _ceph_csi_rbd_helm_info
- name: Create Ceph service
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Service
metadata:
name: ceph-mon
namespace: openstack
labels:
application: ceph
spec:
clusterIP: None
ports:
- name: mon
port: 6789
targetPort: 6789
- name: mon-msgr2
port: 3300
targetPort: 3300
- name: metrics
port: 9283
targetPort: 9283
- name: Generate Ceph endpoint list
ansible.builtin.set_fact:
_openstack_helm_infra_ceph_provisioners_ceph_monitors: |
{{
_openstack_helm_infra_ceph_provisioners_ceph_monitors | default([]) +
[{'ip': item}]
}}
loop: "{{ openstack_helm_infra_ceph_provisioners_ceph_monitors }}"
- name: Create Ceph endpoints
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Endpoints
metadata:
name: ceph-mon
namespace: openstack
labels:
application: ceph
subsets:
- addresses: "{{ _openstack_helm_infra_ceph_provisioners_ceph_monitors }}"
ports:
- name: mon
port: 6789
protocol: TCP
- name: mon-msgr2
port: 3300
protocol: TCP
- name: metrics
port: 9283
protocol: TCP
- name: Retrieve client.admin keyring
vexxhost.atmosphere.ceph_key:
name: client.admin
state: info
output_format: json
register: _openstack_helm_infra_ceph_provisioners_ceph_key
- name: Parse client.admin keyring
ansible.builtin.set_fact:
_openstack_helm_infra_ceph_provisioners_keyring: "{{ _openstack_helm_infra_ceph_provisioners_ceph_key.stdout | from_json | first }}"
- name: Create "pvc-ceph-client-key" secret
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Secret
type: kubernetes.io/rbd
metadata:
name: pvc-ceph-client-key
namespace: openstack
labels:
application: ceph
stringData:
key: "{{ _openstack_helm_infra_ceph_provisioners_keyring.key }}"
- name: Deploy Helm chart
kubernetes.core.helm:
name: "{{ openstack_helm_infra_ceph_provisioners_chart_name }}"
chart_ref: "{{ openstack_helm_infra_ceph_provisioners_chart_repo_name }}/{{ openstack_helm_infra_ceph_provisioners_chart_name }}"
chart_version: 0.1.17
release_namespace: openstack
kubeconfig: /etc/kubernetes/admin.conf
values:
network:
public: "{{ openstack_helm_infra_ceph_provisioners_ceph_public_network }}"
cluster: "{{ openstack_helm_infra_ceph_provisioners_ceph_cluster_network }}"
conf:
ceph:
global:
fsid: "{{ openstack_helm_infra_ceph_provisioners_ceph_fsid }}"
manifests:
configmap_bin: false
configmap_bin_common: false
deployment_rbd_provisioner: false
deployment_csi_rbd_provisioner: false
deployment_cephfs_provisioner: false
job_cephfs_client_key: false
job_namespace_client_key_cleaner: false
job_namespace_client_key: false
storageclass: false

View File

@ -0,0 +1,22 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
openstack_helm_infra_libvirt_chart_repo_name: openstack-helm-infra
openstack_helm_infra_libvirt_chart_repo_url: https://tarballs.opendev.org/openstack/openstack-helm-infra/
openstack_helm_infra_libvirt_chart_name: libvirt
openstack_helm_infra_libvirt_image_repository: "{{ atmosphere_image_repository | default('us-docker.pkg.dev/vexxhost-infra/openstack') }}"
openstack_helm_infra_libvirt_image_tag: wallaby
openstack_helm_infra_libvirt_values: {}

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: "{{ openstack_helm_infra_libvirt_chart_repo_name }}"
helm_repository_repo_url: "{{ openstack_helm_infra_libvirt_chart_repo_url }}"

View File

@ -0,0 +1,30 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Generate OpenStack-Helm endpoints
ansible.builtin.include_role:
name: openstack_helm_endpoints
vars:
openstack_helm_endpoints_repo_name: "{{ openstack_helm_infra_libvirt_chart_repo_name }}"
openstack_helm_endpoints_repo_url: "{{ openstack_helm_infra_libvirt_chart_repo_url }}"
openstack_helm_endpoints_chart: "{{ openstack_helm_infra_libvirt_chart_name }}"
- name: Deploy Helm chart
kubernetes.core.helm:
name: "{{ openstack_helm_infra_libvirt_chart_name }}"
chart_ref: "{{ openstack_helm_infra_libvirt_chart_repo_name }}/{{ openstack_helm_infra_libvirt_chart_name }}"
chart_version: 0.1.8
release_namespace: openstack
kubeconfig: /etc/kubernetes/admin.conf
values: "{{ _openstack_helm_infra_libvirt_values | combine(openstack_helm_infra_libvirt_values, recursive=True) }}"

View File

@ -0,0 +1,24 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
_openstack_helm_infra_libvirt_values:
endpoints: "{{ openstack_helm_endpoints }}"
images:
tags:
ceph_config_helper: "{{ openstack_helm_infra_libvirt_image_repository }}/libvirt:{{ openstack_helm_infra_libvirt_image_tag }}"
dep_check: "{{ openstack_helm_infra_libvirt_image_repository }}/kubernetes-entrypoint:latest"
libvirt: "{{ openstack_helm_infra_libvirt_image_repository }}/libvirt:{{ openstack_helm_infra_libvirt_image_tag }}"
conf:
libvirt:
listen_addr: 0.0.0.0

View File

@ -0,0 +1,20 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
openstack_helm_infra_memcached_chart_repo_name: openstack-helm-infra
openstack_helm_infra_memcached_chart_repo_url: https://tarballs.opendev.org/openstack/openstack-helm-infra/
openstack_helm_infra_memcached_chart_name: memcached
openstack_helm_infra_memcached_diff: false
openstack_helm_infra_memcached_values: {}

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: "{{ openstack_helm_infra_memcached_chart_repo_name }}"
helm_repository_repo_url: "{{ openstack_helm_infra_memcached_chart_repo_url }}"

View File

@ -0,0 +1,122 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Generate OpenStack-Helm endpoints
ansible.builtin.include_role:
name: openstack_helm_endpoints
vars:
openstack_helm_endpoints_repo_name: "{{ openstack_helm_infra_memcached_chart_repo_name }}"
openstack_helm_endpoints_repo_url: "{{ openstack_helm_infra_memcached_chart_repo_url }}"
openstack_helm_endpoints_chart: "{{ openstack_helm_infra_memcached_chart_name }}"
- name: Generate Helm values comparison
ansible.builtin.include_role:
name: helm_diff
vars:
helm_diff_release_name: "{{ openstack_helm_infra_memcached_chart_name }}"
helm_diff_release_namespace: openstack
helm_diff_values: "{{ _openstack_helm_infra_memcached_values }}"
when:
- openstack_helm_infra_memcached_diff | bool
- name: Deploy Helm chart
kubernetes.core.helm:
name: "{{ openstack_helm_infra_memcached_chart_name }}"
chart_ref: "{{ openstack_helm_infra_memcached_chart_repo_name }}/{{ openstack_helm_infra_memcached_chart_name }}"
chart_version: 0.1.6
release_namespace: openstack
create_namespace: true
kubeconfig: /etc/kubernetes/admin.conf
values: "{{ _openstack_helm_infra_memcached_values }}"
- name: Create Service for metrics
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Service
metadata:
name: memcached-metrics
namespace: openstack
labels:
application: memcached
component: server
spec:
selector:
application: memcached
component: server
ports:
- name: metrics
port: 9150
targetPort: 9150
- name: Create ServiceMonitor
kubernetes.core.k8s:
state: present
definition:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: memcached
namespace: monitoring
labels:
release: kube-prometheus-stack
spec:
jobLabel: application
endpoints:
- port: "metrics"
path: "/metrics"
relabelings:
- sourceLabels: ["__meta_kubernetes_pod_name"]
targetLabel: "instance"
- action: "labeldrop"
regex: "^(container|endpoint|namespace|pod|service)$"
namespaceSelector:
matchNames:
- openstack
selector:
matchLabels:
application: memcached
component: server
- name: Create PrometheusRule
kubernetes.core.k8s:
state: present
definition:
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: memcached
namespace: monitoring
labels:
release: kube-prometheus-stack
spec:
groups:
- name: memcached
rules:
- alert: MemcachedDown
expr: memcached_up == 0
for: 5m
labels:
severity: critical
- alert: MemcachedConnectionLimitApproaching
expr: (memcached_current_connections / memcached_max_connections * 100) > 80
for: 5m
labels:
severity: warning
- alert: MemcachedConnectionLimitApproaching
expr: (memcached_current_connections / memcached_max_connections * 100) > 95
for: 5m
labels:
severity: critical

View File

@ -0,0 +1,24 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
_openstack_helm_infra_memcached_values: "{{ __openstack_helm_infra_memcached_values | combine(openstack_helm_infra_memcached_values, recursive=True) }}"
__openstack_helm_infra_memcached_values:
endpoints: "{{ openstack_helm_endpoints }}"
images:
tags:
memcached: quay.io/vexxhost/memcached:1.6.9
prometheus_memcached_exporter: quay.io/vexxhost/memcached-exporter:v0.9.0-1
monitoring:
prometheus:
enabled: true

View File

@ -0,0 +1,22 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
openstack_helm_infra_openvswitch_chart_repo_name: openstack-helm-infra
openstack_helm_infra_openvswitch_chart_repo_url: https://tarballs.opendev.org/openstack/openstack-helm-infra/
openstack_helm_infra_openvswitch_chart_name: openvswitch
openstack_helm_infra_openvswitch_image_repository: "{{ atmosphere_image_repository | default('us-docker.pkg.dev/vexxhost-infra/openstack') }}"
openstack_helm_infra_openvswitch_image_tag: wallaby
openstack_helm_infra_openvswitch_values: {}

View File

@ -0,0 +1,20 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: "{{ openstack_helm_infra_openvswitch_chart_repo_name }}"
helm_repository_repo_url: "{{ openstack_helm_infra_openvswitch_chart_repo_url }}"
- openstack_namespace

View File

@ -0,0 +1,30 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Generate OpenStack-Helm endpoints
ansible.builtin.include_role:
name: openstack_helm_endpoints
vars:
openstack_helm_endpoints_repo_name: "{{ openstack_helm_infra_openvswitch_chart_repo_name }}"
openstack_helm_endpoints_repo_url: "{{ openstack_helm_infra_openvswitch_chart_repo_url }}"
openstack_helm_endpoints_chart: "{{ openstack_helm_infra_openvswitch_chart_name }}"
- name: Deploy Helm chart
kubernetes.core.helm:
name: "{{ openstack_helm_infra_openvswitch_chart_name }}"
chart_ref: "{{ openstack_helm_infra_openvswitch_chart_repo_name }}/{{ openstack_helm_infra_openvswitch_chart_name }}"
chart_version: 0.1.6
release_namespace: openstack
kubeconfig: /etc/kubernetes/admin.conf
values: "{{ _openstack_helm_infra_openvswitch_values | combine(openstack_helm_infra_openvswitch_values, recursive=True) }}"

View File

@ -0,0 +1,21 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
_openstack_helm_infra_openvswitch_values:
endpoints: "{{ openstack_helm_endpoints }}"
images:
tags:
dep_check: "{{ openstack_helm_infra_openvswitch_image_repository }}/kubernetes-entrypoint:latest"
openvswitch_db_server: "{{ openstack_helm_infra_openvswitch_image_repository }}/openvswitch:{{ openstack_helm_infra_openvswitch_image_tag }}"
openvswitch_vswitchd: "{{ openstack_helm_infra_openvswitch_image_repository }}/openvswitch:{{ openstack_helm_infra_openvswitch_image_tag }}"

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
openstack_helm_infra_rabbitmq_chart_repo_name: openstack-helm-infra
openstack_helm_infra_rabbitmq_chart_repo_url: https://tarballs.opendev.org/openstack/openstack-helm-infra/
openstack_helm_infra_rabbitmq_chart_name: rabbitmq
openstack_helm_infra_rabbitmq_image_repository: "{{ atmosphere_image_repository | default('us-docker.pkg.dev/vexxhost-infra/openstack') }}"

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: "{{ openstack_helm_infra_rabbitmq_chart_repo_name }}"
helm_repository_repo_url: "{{ openstack_helm_infra_rabbitmq_chart_repo_url }}"

View File

@ -0,0 +1,159 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Generate OpenStack-Helm endpoints
ansible.builtin.include_role:
name: openstack_helm_endpoints
vars:
openstack_helm_endpoints_repo_name: "{{ openstack_helm_infra_rabbitmq_chart_repo_name }}"
openstack_helm_endpoints_repo_url: "{{ openstack_helm_infra_rabbitmq_chart_repo_url }}"
openstack_helm_endpoints_chart: "{{ openstack_helm_infra_rabbitmq_chart_name }}"
- name: Deploy Helm chart
kubernetes.core.helm:
name: "{{ openstack_helm_infra_rabbitmq_chart_name }}"
chart_ref: "{{ openstack_helm_infra_rabbitmq_chart_repo_name }}/{{ openstack_helm_infra_rabbitmq_chart_name }}"
chart_version: 0.1.15
release_namespace: openstack
kubeconfig: /etc/kubernetes/admin.conf
values:
endpoints: "{{ openstack_helm_endpoints }}"
images:
tags:
dep_check: "{{ openstack_helm_infra_rabbitmq_image_repository }}/kubernetes-entrypoint:latest"
rabbitmq_init: "{{ openstack_helm_infra_rabbitmq_image_repository }}/cli:latest"
rabbitmq: "{{ openstack_helm_infra_rabbitmq_image_repository }}/rabbitmq:3.8.23"
pod:
replicas:
server: 3
conf:
enabled_plugins:
- rabbitmq_management
- rabbitmq_peer_discovery_k8s
- rabbitmq_prometheus
volume:
size: 10Gi
manifests:
ingress_management: false
- name: Create Service for metrics
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Service
metadata:
name: rabbitmq-metrics
namespace: openstack
labels:
application: rabbitmq
component: server
spec:
selector:
application: rabbitmq
component: server
ports:
- name: metrics
port: 15692
targetPort: 15692
- name: Create ServiceMonitor
kubernetes.core.k8s:
state: present
definition:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: rabbitmq
namespace: monitoring
labels:
release: kube-prometheus-stack
spec:
jobLabel: application
endpoints:
- port: "metrics"
path: "/metrics"
relabelings:
- sourceLabels: ["__meta_kubernetes_pod_name"]
targetLabel: "instance"
- action: "labeldrop"
regex: "^(container|endpoint|namespace|pod|service)$"
namespaceSelector:
matchNames:
- openstack
selector:
matchLabels:
application: rabbitmq
component: server
- name: Create PrometheusRule
kubernetes.core.k8s:
state: present
definition:
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: rabbitmq
namespace: monitoring
labels:
release: kube-prometheus-stack
spec:
groups:
- name: rules
rules:
- alert: RabbitmqDown
expr: absent(rabbitmq_build_info)
for: 1m
labels:
severity: critical
- alert: RabbitmqNodeDown
expr: sum(rabbitmq_build_info) < 3
for: 1m
labels:
severity: critical
- alert: RabbitmqNodeNotDistributed
expr: erlang_vm_dist_node_state < 3
for: 1m
labels:
severity: critical
- alert: RabbitmqMemoryHigh
expr: rabbitmq_process_resident_memory_bytes / rabbitmq_resident_memory_limit_bytes > 0.80
labels:
severity: warning
- alert: RabbitmqMemoryHigh
expr: rabbitmq_process_resident_memory_bytes / rabbitmq_resident_memory_limit_bytes > 0.95
labels:
severity: critical
- alert: RabbitmqFileDescriptorsUsage
expr: rabbitmq_process_open_fds / rabbitmq_process_max_fds > 0.80
labels:
severity: warning
- alert: RabbitmqFileDescriptorsUsage
expr: rabbitmq_process_open_fds / rabbitmq_process_max_fds > 0.95
labels:
severity: critical
- alert: RabbitmqUnackedMessages
expr: sum(rabbitmq_queue_messages_unacked) BY (queue) > 1000
for: 5m
labels:
severity: warning
- alert: RabbitmqUnackedMessages
expr: sum(rabbitmq_queue_messages_unacked) BY (queue) > 1000
for: 1h
labels:
severity: critical
- alert: RabbitmqConnections
expr: rabbitmq_connections > 1000
labels:
severity: warning

View File

@ -0,0 +1,16 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
openstack_helm_ingress_annotations: {}
openstack_helm_ingress_paths: []

View File

@ -0,0 +1,34 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Create Ingress ({{ openstack_helm_ingress_endpoint }})
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Ingress
metadata:
name: "{{ openstack_helm_ingress_endpoint | replace('_', '-') }}"
namespace: openstack
annotations: "{{ _openstack_helm_ingress_annotations | combine(openstack_helm_ingress_annotations, recursive=True) }}"
spec:
ingressClassName: openstack
rules:
- host: "{{ openstack_helm_endpoints[openstack_helm_ingress_endpoint]['host_fqdn_override']['public']['host'] }}"
http:
paths: "{{ _openstack_helm_ingress_paths }}"
tls:
- secretName: "{{ openstack_helm_ingress_service_name }}-certs"
hosts:
- "{{ openstack_helm_endpoints[openstack_helm_ingress_endpoint]['host_fqdn_override']['public']['host'] }}"

View File

@ -0,0 +1,26 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
_openstack_helm_ingress_annotations:
cert-manager.io/issuer: openstack
_openstack_helm_ingress_paths: "{{ openstack_helm_ingress_paths + __openstack_helm_ingress_paths }}"
__openstack_helm_ingress_paths:
- path: /
pathType: Prefix
backend:
service:
name: "{{ openstack_helm_ingress_service_name }}"
port:
number: "{{ openstack_helm_ingress_service_port }}"

View File

@ -0,0 +1,23 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
openstack_helm_keystone_chart_repo_name: openstack-helm
openstack_helm_keystone_chart_repo_url: https://tarballs.opendev.org/openstack/openstack-helm/
openstack_helm_keystone_chart_name: keystone
openstack_helm_keystone_image_repository: "{{ atmosphere_image_repository | default('us-docker.pkg.dev/vexxhost-infra/openstack') }}"
openstack_helm_keystone_image_tag: 19.0.1.dev11
openstack_helm_keystone_heat_image_tag: wallaby
openstack_helm_keystone_values: {}

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: "{{ openstack_helm_keystone_chart_repo_name }}"
helm_repository_repo_url: "{{ openstack_helm_keystone_chart_repo_url }}"

View File

@ -0,0 +1,39 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Generate OpenStack-Helm endpoints
ansible.builtin.include_role:
name: openstack_helm_endpoints
vars:
openstack_helm_endpoints_repo_name: "{{ openstack_helm_keystone_chart_repo_name }}"
openstack_helm_endpoints_repo_url: "{{ openstack_helm_keystone_chart_repo_url }}"
openstack_helm_endpoints_chart: "{{ openstack_helm_keystone_chart_name }}"
- name: Deploy Helm chart
kubernetes.core.helm:
name: "{{ openstack_helm_keystone_chart_name }}"
chart_ref: "{{ openstack_helm_keystone_chart_repo_name }}/{{ openstack_helm_keystone_chart_name }}"
chart_version: 0.2.19
release_namespace: openstack
create_namespace: true
kubeconfig: /etc/kubernetes/admin.conf
values: "{{ _openstack_helm_keystone_values | combine(openstack_helm_keystone_values, recursive=True) }}"
- name: Create Ingress
ansible.builtin.include_role:
name: openstack_helm_ingress
vars:
openstack_helm_ingress_endpoint: identity
openstack_helm_ingress_service_name: keystone-api
openstack_helm_ingress_service_port: 5000

View File

@ -0,0 +1,229 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
_openstack_helm_keystone_values:
endpoints: "{{ openstack_helm_endpoints }}"
images:
tags:
bootstrap: "{{ openstack_helm_keystone_image_repository }}/heat:{{ openstack_helm_keystone_heat_image_tag }}"
db_drop: "{{ openstack_helm_keystone_image_repository }}/heat:{{ openstack_helm_keystone_heat_image_tag }}"
db_init: "{{ openstack_helm_keystone_image_repository }}/heat:{{ openstack_helm_keystone_heat_image_tag }}"
dep_check: "{{ openstack_helm_keystone_image_repository }}/kubernetes-entrypoint:latest"
keystone_api: "{{ openstack_helm_keystone_image_repository }}/keystone:{{ openstack_helm_keystone_image_tag }}"
keystone_credential_cleanup: "{{ openstack_helm_keystone_image_repository }}/heat:{{ openstack_helm_keystone_heat_image_tag }}"
keystone_credential_rotate: "{{ openstack_helm_keystone_image_repository }}/keystone:{{ openstack_helm_keystone_image_tag }}"
keystone_credential_setup: "{{ openstack_helm_keystone_image_repository }}/keystone:{{ openstack_helm_keystone_image_tag }}"
keystone_db_sync: "{{ openstack_helm_keystone_image_repository }}/keystone:{{ openstack_helm_keystone_image_tag }}"
keystone_domain_manage: "{{ openstack_helm_keystone_image_repository }}/keystone:{{ openstack_helm_keystone_image_tag }}"
keystone_fernet_rotate: "{{ openstack_helm_keystone_image_repository }}/keystone:{{ openstack_helm_keystone_image_tag }}"
keystone_fernet_setup: "{{ openstack_helm_keystone_image_repository }}/keystone:{{ openstack_helm_keystone_image_tag }}"
ks_user: "{{ openstack_helm_keystone_image_repository }}/heat:{{ openstack_helm_keystone_heat_image_tag }}"
rabbit_init: "{{ openstack_helm_keystone_image_repository }}/rabbitmq:3.8.23-management"
pod:
# mounts = {
# keystone_api = {
# keystone_api = {
# volumeMounts = [
# {
# name = kubernetes_config_map.keystone_ldap_ca.metadata[0].name
# mountPath = "/etc/keystone/ldap"
# },
# {
# name = kubernetes_config_map.keystone_openid_connect_metadata.metadata[0].name
# mountPath = "/var/lib/apache2/oidc"
# }
# ],
# volumes = [
# {
# name = kubernetes_config_map.keystone_ldap_ca.metadata[0].name
# configMap = {
# name = kubernetes_config_map.keystone_ldap_ca.metadata[0].name
# }
# },
# {
# name = kubernetes_config_map.keystone_openid_connect_metadata.metadata[0].name
# configMap = {
# name = kubernetes_config_map.keystone_openid_connect_metadata.metadata[0].name
# }
# }
# ]
# }
# }
# },
replicas:
api: 3
conf:
keystone:
DEFAULT:
log_config_append: null
auth:
methods: password,token,openid,application_credential
cors:
allowed_origins: "*"
federation:
assertion_prefix: OIDC-
remote_id_attribute: OIDC-iss
# TODO(mnaser): Lookup using openstack_helm_endpoints
trusted_dashboard: "https://{{ openstack_helm_endpoints_horizon_api_host }}/auth/websso/"
identity:
domain_configuration_from_database: true
manifests:
job_credential_cleanup: false
ingress_api: false
service_ingress_api: false
# # LDAP configuration
# yamlencode({
# conf = {
# ks_domains = {
# for domain, details in var.keystone_ldap_domains : domain => {
# identity = {
# driver = "ldap"
# }
# ldap = merge({
# tls_cacertfile = "/etc/keystone/ldap/${domain}.crt"
# }, details.conf)
# }
# }
# }
# }),
# # OpenID Connect
# yamlencode({
# bootstrap = {
# script = <<-EOT
# # Create role for publishing images
# openstack role create --or-show image-publisher
# # Add member role for admin user
# openstack role add \
# --user="$${OS_USERNAME}" \
# --user-domain="$${OS_USER_DOMAIN_NAME}" \
# --project-domain="$${OS_PROJECT_DOMAIN_NAME}" \
# --project="$${OS_PROJECT_NAME}" \
# "member"
# # Create project for tempest-pushgateway
# openstack project create --or-show \
# "${kubernetes_secret.tempest_pushgateway.data.OS_PROJECT_NAME}"
# openstack user create --or-show \
# "${kubernetes_secret.tempest_pushgateway.data.OS_USERNAME}"
# openstack user set \
# --password="${kubernetes_secret.tempest_pushgateway.data.OS_PASSWORD}" \
# "${kubernetes_secret.tempest_pushgateway.data.OS_USERNAME}"
# openstack role add \
# --user="${kubernetes_secret.tempest_pushgateway.data.OS_USERNAME}" \
# --project="${kubernetes_secret.tempest_pushgateway.data.OS_PROJECT_NAME}" \
# "member"
# # Add admin user to default domain
# openstack role add \
# --user="$${OS_USERNAME}" \
# --domain="$${OS_DEFAULT_DOMAIN}" \
# "admin"
# %{for name, config in var.keystone_openid_connect_idps}
# # OpenID connect (${name})
# # Create Identity provider if it doesn't exist
# IDP_ID=$(openstack identity provider show ${name} -c id -f value || :)
# if [ -z "$IDP_ID" ]; then
# openstack identity provider create --remote-id ${config.issuer} ${name}
# else
# openstack identity provider set --remote-id ${config.issuer} ${name}
# fi
# # Generate mapping
# cat <<EOF | tee /tmp/mapping.json
# ${jsonencode(local.keystone_mappings[name])}
# EOF
# # Upload mapping to Keystone
# MAPPING_ID=$(openstack mapping show ${name} -c id -f value || :)
# if [ -z "$MAPPING_ID" ]; then
# openstack mapping create --rules /tmp/mapping.json ${name}
# else
# openstack mapping set --rules /tmp/mapping.json ${name}
# fi
# # Create federation
# FEDERATION_ID=$(openstack federation protocol show --identity-provider ${name} openid -c id -f value || :)
# if [ -z "$FEDERATION_ID" ]; then
# openstack federation protocol create --identity-provider ${name} --mapping ${name} openid
# fi
# %{endfor~}
# EOT
# }
# conf = {
# wsgi_keystone = <<-EOT
# {{- $portInt := tuple "identity" "internal" "api" $ | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
# Listen 0.0.0.0:{{ $portInt }}
# LogFormat "%h %l %u %t \"%r\" %>s %b \"%%{Referer}i\" \"%%{User-Agent}i\"" combined
# LogFormat "%%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%%{Referer}i\" \"%%{User-Agent}i\"" proxy
# SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded
# CustomLog /dev/stdout combined env=!forwarded
# CustomLog /dev/stdout proxy env=forwarded
# <VirtualHost *:{{ $portInt }}>
# WSGIDaemonProcess keystone-public processes=4 threads=1 user=keystone group=keystone display-name=%%{GROUP}
# WSGIProcessGroup keystone-public
# WSGIScriptAlias / /var/www/cgi-bin/keystone/keystone-wsgi-public
# WSGIApplicationGroup %%{GLOBAL}
# WSGIPassAuthorization On
# <IfVersion >= 2.4>
# ErrorLogFormat "%%{cu}t %M"
# </IfVersion>
# ErrorLog /dev/stdout
# SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded
# CustomLog /dev/stdout combined env=!forwarded
# CustomLog /dev/stdout proxy env=forwarded
# # OpenID connect
# OIDCMetadataDir /var/lib/apache2/oidc
# OIDCClaimPrefix "OIDC-"
# OIDCSessionType client-cookie
# OIDCCryptoPassphrase ${random_password.keystone_openid_connect_crypto_passphrase.result}
# OIDCRedirectURLsAllowed ^https://${var.horizon_api_host}/auth/logout/$ ^https://${var.keystone_api_host}
# OIDCOAuthVerifyJwksUri https://vexxhost.us.auth0.com/.well-known/jwks.json
# OIDCRedirectURI https://${var.keystone_api_host}/v3/auth/OS-FEDERATION/identity_providers/redirect
# <Location /v3/auth/OS-FEDERATION/identity_providers/redirect>
# AuthType openid-connect
# Require valid-user
# </Location>
# <Location /v3/auth/OS-FEDERATION/websso/openid>
# AuthType openid-connect
# Require valid-user
# </Location>
# %{for name, config in var.keystone_openid_connect_idps}
# <Location /v3/auth/OS-FEDERATION/identity_providers/${name}/protocols/openid/websso>
# OIDCDiscoverURL https://${var.keystone_api_host}/v3/auth/OS-FEDERATION/identity_providers/redirect?iss=${urlencode(config.issuer)}
# AuthType openid-connect
# Require valid-user
# </Location>
# <Location /v3/OS-FEDERATION/identity_providers/${name}/protocols/openid/auth>
# LoadModule headers_module /usr/lib/apache2/modules/mod_headers.so
# Header set Access-Control-Allow-Headers "Authorization,Content-Type"
# Header set Access-Control-Allow-Origin "*"
# AuthType oauth20
# Require valid-user
# </Location>
# %{endfor}
# </VirtualHost>
# EOT
# }
# }),

View File

@ -0,0 +1,101 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Get the IP address for the legacy MariaDB service
kubernetes.core.k8s_info:
api_version: v1
kind: Service
name: mariadb
namespace: openstack
register: _openstack_helm_migrate_to_percona_xtradb_cluster_legacy_service
when: _openstack_helm_migrate_to_percona_xtradb_cluster_legacy_ip is undefined
- name: Get the IP address for the new Percona XtraDB service
kubernetes.core.k8s_info:
api_version: v1
kind: Service
name: percona-xtradb-haproxy
namespace: openstack
register: _openstack_helm_migrate_to_percona_xtradb_cluster_service
when: _openstack_helm_migrate_to_percona_xtradb_cluster_ip is undefined
- name: Get current values for Helm chart & fail if it already points to Percona XtraDB Cluster
kubernetes.core.helm_info:
name: "{{ openstack_helm_migrate_to_percona_xtradb_cluster_release_name }}"
release_namespace: "{{ openstack_helm_migrate_to_percona_xtradb_cluster_release_namespace }}"
register: _openstack_helm_migrate_to_percona_xtradb_cluster_helm_info
failed_when: _openstack_helm_migrate_to_percona_xtradb_cluster_helm_info.status['values']['endpoints']['oslo_db'].get('hosts', {}).get('default', '') == 'percona-xtradb-haproxy'
- name: Set facts for database endpoints
ansible.builtin.set_fact:
_openstack_helm_migrate_to_percona_xtradb_cluster_legacy_ip: "{{ _openstack_helm_migrate_to_percona_xtradb_cluster_legacy_service.resources[0]['spec']['clusterIP'] }}"
_openstack_helm_migrate_to_percona_xtradb_cluster_legacy_password: "{{ _openstack_helm_migrate_to_percona_xtradb_cluster_helm_info.status['values']['endpoints']['oslo_db']['auth']['admin']['password'] }}"
_openstack_helm_migrate_to_percona_xtradb_cluster_ip: "{{ _openstack_helm_migrate_to_percona_xtradb_cluster_service.resources[0]['spec']['clusterIP'] }}"
_openstack_helm_migrate_to_percona_xtradb_cluster_password: "{{ openstack_helm_endpoints['oslo_db']['auth']['admin']['password'] }}"
- name: Ensure PyMySQL packages are installed
ansible.builtin.pip:
name: PyMySQL
- name: Check if database already exists & fail if it already exists
community.mysql.mysql_db:
login_host: "{{ _openstack_helm_migrate_to_percona_xtradb_cluster_ip }}"
login_user: root
login_password: "{{ _openstack_helm_migrate_to_percona_xtradb_cluster_password }}"
name: "{{ item }}"
state: present
check_mode: true
register: _openstack_helm_migrate_to_percona_xtradb_cluster_db_check
failed_when: _openstack_helm_migrate_to_percona_xtradb_cluster_db_check is not changed
loop: "{{ openstack_helm_migrate_to_percona_xtradb_cluster_databases }}"
- name: Scale down replicas to 0 for database facing services
kubernetes.core.k8s_scale:
api_version: v1
kind: "{{ item.kind }}"
name: "{{ item.name }}"
namespace: "{{ openstack_helm_migrate_to_percona_xtradb_cluster_release_namespace }}"
replicas: 0
loop: "{{ openstack_helm_migrate_to_percona_xtradb_cluster_services }}"
- name: Create temporary file for database dump
ansible.builtin.tempfile:
state: file
prefix: "{{ openstack_helm_migrate_to_percona_xtradb_cluster_release_name }}"
suffix: .sql
register: _openstack_helm_migrate_to_percona_xtradb_cluster_file
- name: Dump all of the databases to the local system
community.mysql.mysql_db:
login_host: "{{ _openstack_helm_migrate_to_percona_xtradb_cluster_legacy_ip }}"
login_user: root
login_password: "{{ _openstack_helm_migrate_to_percona_xtradb_cluster_legacy_password }}"
name: "{{ openstack_helm_migrate_to_percona_xtradb_cluster_databases }}"
state: dump
target: "{{ _openstack_helm_migrate_to_percona_xtradb_cluster_file.path }}"
skip_lock_tables: true
dump_extra_args: --skip-add-locks
async: 7200
poll: 5
- name: Import databases to the new Percona XtraDB Cluster
community.mysql.mysql_db:
login_host: "{{ _openstack_helm_migrate_to_percona_xtradb_cluster_ip }}"
login_user: root
login_password: "{{ _openstack_helm_migrate_to_percona_xtradb_cluster_password }}"
name: "{{ (openstack_helm_migrate_to_percona_xtradb_cluster_databases | length > 1) | ternary('all', openstack_helm_migrate_to_percona_xtradb_cluster_databases) }}"
state: import
target: "{{ _openstack_helm_migrate_to_percona_xtradb_cluster_file.path }}"
async: 7200
poll: 5

View File

@ -0,0 +1,25 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
openstack_helm_neutron_chart_repo_name: openstack-helm
openstack_helm_neutron_chart_repo_url: https://tarballs.opendev.org/openstack/openstack-helm/
openstack_helm_neutron_chart_name: neutron
openstack_helm_neutron_image_repository: "{{ atmosphere_image_repository | default('us-docker.pkg.dev/vexxhost-infra/openstack') }}"
openstack_helm_neutron_image_tag: 18.2.1.dev7-6
openstack_helm_neutron_heat_image_tag: wallaby
openstack_helm_neutron_values: {}
openstack_helm_neutron_networks: []

View File

@ -0,0 +1,26 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: "{{ openstack_helm_neutron_chart_repo_name }}"
helm_repository_repo_url: "{{ openstack_helm_neutron_chart_repo_url }}"
- cilium
- openstack_namespace
- percona_xtradb_cluster
- openstack_helm_infra_memcached
- openstack_helm_infra_rabbitmq
- openstack_helm_infra_openvswitch
- openstack_helm_keystone

View File

@ -0,0 +1,87 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Generate OpenStack-Helm endpoints
ansible.builtin.include_role:
name: openstack_helm_endpoints
vars:
openstack_helm_endpoints_repo_name: "{{ openstack_helm_neutron_chart_repo_name }}"
openstack_helm_endpoints_repo_url: "{{ openstack_helm_neutron_chart_repo_url }}"
openstack_helm_endpoints_chart: "{{ openstack_helm_neutron_chart_name }}"
- name: Deploy Helm chart
kubernetes.core.helm:
name: "{{ openstack_helm_neutron_chart_name }}"
chart_ref: "{{ openstack_helm_neutron_chart_repo_name }}/{{ openstack_helm_neutron_chart_name }}"
chart_version: 0.2.11
release_namespace: openstack
kubeconfig: /etc/kubernetes/admin.conf
values: "{{ _openstack_helm_neutron_values | combine(openstack_helm_neutron_values, recursive=True) }}"
- name: Create Ingress
ansible.builtin.include_role:
name: openstack_helm_ingress
vars:
openstack_helm_ingress_endpoint: network
openstack_helm_ingress_service_name: neutron-server
openstack_helm_ingress_service_port: 9696
- name: Create networks
openstack.cloud.network:
auth:
auth_url: "https://{{ openstack_helm_endpoints['identity']['host_fqdn_override']['public']['host'] }}"
username: "{{ openstack_helm_endpoints['identity']['auth']['admin']['username'] }}"
password: "{{ openstack_helm_endpoints['identity']['auth']['admin']['password'] }}"
project_name: admin
user_domain_name: Default
project_domain_name: Default
region_name: "{{ openstack_helm_endpoints['identity']['auth']['neutron']['region_name'] }}"
# Network settings
name: "{{ item.name }}"
external: "{{ item.external | default(omit) }}"
shared: "{{ item.shared | default(omit) }}"
mtu_size: "{{ item.mtu_size | default(omit) }}"
port_security_enabled: "{{ item.port_security_enabled | default(omit) }}"
provider_network_type: "{{ item.provider_network_type | default(omit) }}"
provider_physical_network: "{{ item.provider_physical_network | default(omit) }}"
provider_segmentation_id: "{{ item.provider_segmentation_id | default(omit) }}"
loop: "{{ openstack_helm_neutron_networks }}"
- name: Create subnets
openstack.cloud.subnet:
auth:
auth_url: "https://{{ openstack_helm_endpoints['identity']['host_fqdn_override']['public']['host'] }}"
username: "{{ openstack_helm_endpoints['identity']['auth']['admin']['username'] }}"
password: "{{ openstack_helm_endpoints['identity']['auth']['admin']['password'] }}"
project_name: admin
user_domain_name: Default
project_domain_name: Default
region_name: "{{ openstack_helm_endpoints['identity']['auth']['neutron']['region_name'] }}"
# Subnet settings
network_name: "{{ item.0.name }}"
name: "{{ item.1.name }}"
ip_version: "{{ item.1.ip_version | default(omit) }}"
cidr: "{{ item.1.cidr | default(omit) }}"
gateway_ip: "{{ item.1.gateway_ip | default(omit) }}"
no_gateway_ip: "{{ item.1.no_gateway_ip | default(omit) }}"
allocation_pool_start: "{{ item.1.allocation_pool_start | default(omit) }}"
allocation_pool_end: "{{ item.1.allocation_pool_end | default(omit) }}"
dns_nameservers: "{{ item.1.dns_nameservers | default(omit) }}"
enable_dhcp: "{{ item.1.enable_dhcp | default(omit) }}"
host_routes: "{{ item.1.host_routes | default(omit) }}"
ipv6_address_mode: "{{ item.1.ipv6_address_mode | default(omit) }}"
ipv6_ra_mode: "{{ item.1.ipv6_ra_mode | default(omit) }}"
with_subelements:
- "{{ openstack_helm_neutron_networks }}"
- subnets

View File

@ -0,0 +1,82 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
_openstack_helm_neutron_values:
endpoints: "{{ openstack_helm_endpoints }}"
images:
tags:
bootstrap: "{{ openstack_helm_neutron_image_repository }}/heat:{{ openstack_helm_neutron_heat_image_tag }}"
db_drop: "{{ openstack_helm_neutron_image_repository }}/heat:{{ openstack_helm_neutron_heat_image_tag }}"
db_init: "{{ openstack_helm_neutron_image_repository }}/heat:{{ openstack_helm_neutron_heat_image_tag }}"
dep_check: "{{ openstack_helm_neutron_image_repository }}/kubernetes-entrypoint:latest"
ks_endpoints: "{{ openstack_helm_neutron_image_repository }}/heat:{{ openstack_helm_neutron_heat_image_tag }}"
ks_service: "{{ openstack_helm_neutron_image_repository }}/heat:{{ openstack_helm_neutron_heat_image_tag }}"
ks_user: "{{ openstack_helm_neutron_image_repository }}/heat:{{ openstack_helm_neutron_heat_image_tag }}"
neutron_bagpipe_bgp: "{{ openstack_helm_neutron_image_repository }}/neutron:{{ openstack_helm_neutron_image_tag }}"
neutron_db_sync: "{{ openstack_helm_neutron_image_repository }}/neutron:{{ openstack_helm_neutron_image_tag }}"
neutron_dhcp: "{{ openstack_helm_neutron_image_repository }}/neutron:{{ openstack_helm_neutron_image_tag }}"
neutron_ironic_agent: "{{ openstack_helm_neutron_image_repository }}/neutron:{{ openstack_helm_neutron_image_tag }}"
neutron_l2gw: "{{ openstack_helm_neutron_image_repository }}/neutron:{{ openstack_helm_neutron_image_tag }}"
neutron_l3: "{{ openstack_helm_neutron_image_repository }}/neutron:{{ openstack_helm_neutron_image_tag }}"
neutron_linuxbridge_agent: "{{ openstack_helm_neutron_image_repository }}/neutron:{{ openstack_helm_neutron_image_tag }}"
neutron_metadata: "{{ openstack_helm_neutron_image_repository }}/neutron:{{ openstack_helm_neutron_image_tag }}"
neutron_netns_cleanup_cron: "{{ openstack_helm_neutron_image_repository }}/neutron:{{ openstack_helm_neutron_image_tag }}"
neutron_openvswitch_agent: "{{ openstack_helm_neutron_image_repository }}/neutron:{{ openstack_helm_neutron_image_tag }}"
neutron_server: "{{ openstack_helm_neutron_image_repository }}/neutron:{{ openstack_helm_neutron_image_tag }}"
neutron_sriov_agent_init: "{{ openstack_helm_neutron_image_repository }}/neutron:{{ openstack_helm_neutron_image_tag }}"
neutron_sriov_agent: "{{ openstack_helm_neutron_image_repository }}/neutron:{{ openstack_helm_neutron_image_tag }}"
rabbit_init: "{{ openstack_helm_neutron_image_repository }}/rabbitmq:3.8.23-management"
pod:
replicas:
server: 3
conf:
paste:
composite:neutronapi_v2_0:
keystone: cors http_proxy_to_wsgi request_id catch_errors authtoken keystonecontext extensions neutronapiapp_v2_0
neutron:
DEFAULT:
api_workers: 8
dhcp_agents_per_network: 3
log_config_append: null
rpc_workers: 8
service_plugins: router,vpnaas
cors:
allowed_origin: "*"
service_providers:
service_provider: VPN:strongswan:neutron_vpnaas.services.vpn.service_drivers.ipsec.IPsecVPNDriver:default
dhcp_agent:
DEFAULT:
dnsmasq_dns_servers: 1.1.1.1
enable_isolated_metadata: true
l3_agent:
AGENT:
extensions: vpnaas
vpnagent:
vpn_device_driver: neutron_vpnaas.services.vpn.device_drivers.strongswan_ipsec.StrongSwanDriver
metadata_agent:
DEFAULT:
nova_metadata_port: 8776
metadata_proxy_shared_secret: "{{ openstack_helm_endpoints['compute_metadata']['secret'] }}"
plugins:
ml2_conf:
ml2:
extension_drivers: port_security,dns
type_drivers: flat,gre,vlan,vxlan
ml2_type_gre:
tunnel_id_ranges: 1:1000
ml2_type_vlan:
network_vlan_ranges: external:1:4094
manifests:
ingress_server: false
service_ingress_server: false

View File

@ -0,0 +1,29 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
openstack_helm_nova_chart_repo_name: openstack-helm
openstack_helm_nova_chart_repo_url: https://tarballs.opendev.org/openstack/openstack-helm/
openstack_helm_nova_chart_name: nova
openstack_helm_nova_image_repository: "{{ atmosphere_image_repository | default('us-docker.pkg.dev/vexxhost-infra/openstack') }}"
openstack_helm_nova_image_tag: 23.1.1.dev11
openstack_helm_nova_ssh_image_tag: wallaby
openstack_helm_nova_heat_image_tag: wallaby
openstack_helm_nova_diff: false
openstack_helm_nova_migrate_from_mariadb: false
openstack_helm_nova_values: {}
openstack_helm_nova_flavors: []

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: "{{ openstack_helm_nova_chart_repo_name }}"
helm_repository_repo_url: "{{ openstack_helm_nova_chart_repo_url }}"

View File

@ -0,0 +1,104 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Generate OpenStack-Helm endpoints
ansible.builtin.include_role:
name: openstack_helm_endpoints
vars:
openstack_helm_endpoints_repo_name: "{{ openstack_helm_nova_chart_repo_name }}"
openstack_helm_endpoints_repo_url: "{{ openstack_helm_nova_chart_repo_url }}"
openstack_helm_endpoints_chart: "{{ openstack_helm_nova_chart_name }}"
- name: Generate Helm values comparison
ansible.builtin.include_role:
name: helm_diff
vars:
helm_diff_release_name: "{{ openstack_helm_nova_chart_name }}"
helm_diff_release_namespace: openstack
helm_diff_values: "{{ _openstack_helm_nova_values }}"
when:
- openstack_helm_nova_diff | bool
- name: Migrate database from MariaDB to Percona XtraDB Cluster
ansible.builtin.include_role:
name: openstack_helm_migrate_to_percona_xtradb_cluster
vars:
openstack_helm_migrate_to_percona_xtradb_cluster_release_name: "{{ openstack_helm_nova_chart_name }}"
openstack_helm_migrate_to_percona_xtradb_cluster_release_namespace: openstack
openstack_helm_migrate_to_percona_xtradb_cluster_databases:
- nova
- nova_api
- nova_cell0
openstack_helm_migrate_to_percona_xtradb_cluster_services:
- kind: Deployment
name: nova-api-metadata
- kind: Deployment
name: nova-api-osapi
- kind: Deployment
name: nova-conductor
- kind: Deployment
name: nova-scheduler
when:
- openstack_helm_nova_migrate_from_mariadb | bool
- name: Deploy Helm chart
kubernetes.core.helm:
name: "{{ openstack_helm_nova_chart_name }}"
chart_ref: "{{ openstack_helm_nova_chart_repo_name }}/{{ openstack_helm_nova_chart_name }}"
chart_version: 0.2.30
release_namespace: openstack
kubeconfig: /etc/kubernetes/admin.conf
values: "{{ _openstack_helm_nova_values }}"
# NOTE(mnaser): This is a a workaround due to the fact that Nova's online
# data migrations take forever.
wait_timeout: 10m
- name: Create Ingress
ansible.builtin.include_role:
name: openstack_helm_ingress
vars:
openstack_helm_ingress_endpoint: compute
openstack_helm_ingress_service_name: nova-api
openstack_helm_ingress_service_port: 8774
- name: Create Ingress
ansible.builtin.include_role:
name: openstack_helm_ingress
vars:
openstack_helm_ingress_endpoint: compute_novnc_proxy
openstack_helm_ingress_service_name: nova-novncproxy
openstack_helm_ingress_service_port: 6080
- name: Create flavors
openstack.cloud.compute_flavor:
auth:
auth_url: "https://{{ openstack_helm_endpoints['identity']['host_fqdn_override']['public']['host'] }}"
username: "{{ openstack_helm_endpoints['identity']['auth']['admin']['username'] }}"
password: "{{ openstack_helm_endpoints['identity']['auth']['admin']['password'] }}"
project_name: admin
user_domain_name: Default
project_domain_name: Default
region_name: "{{ openstack_helm_endpoints['identity']['auth']['neutron']['region_name'] }}"
# Flavor settings
flavorid: "{{ item.flavorid | default(omit) }}"
name: "{{ item.name }}"
vcpus: "{{ item.vcpus }}"
ram: "{{ item.ram }}"
disk: "{{ item.disk | default(omit) }}"
ephemeral: "{{ item.ephemeral | default(omit) }}"
swap: "{{ item.swap | default(omit) }}"
is_public: "{{ item.is_public | default(omit) }}"
rxtx_factor: "{{ item.rxtx_factor | default(omit) }}"
extra_specs: "{{ item.extra_specs | default(omit) }}"
loop: "{{ openstack_helm_nova_flavors }}"

View File

@ -0,0 +1,117 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
_openstack_helm_nova_values: "{{ __openstack_helm_nova_values | combine(openstack_helm_nova_values, recursive=True) }}"
__openstack_helm_nova_values:
endpoints: "{{ openstack_helm_endpoints }}"
labels:
agent:
compute_ironic:
node_selector_key: openstack-control-plane
node_selector_value: enabled
images:
tags:
bootstrap: "{{ openstack_helm_nova_image_repository }}/heat:{{ openstack_helm_nova_heat_image_tag }}"
db_drop: "{{ openstack_helm_nova_image_repository }}/heat:{{ openstack_helm_nova_heat_image_tag }}"
db_init: "{{ openstack_helm_nova_image_repository }}/heat:{{ openstack_helm_nova_heat_image_tag }}"
dep_check: "{{ openstack_helm_nova_image_repository }}/kubernetes-entrypoint:latest"
ks_endpoints: "{{ openstack_helm_nova_image_repository }}/heat:{{ openstack_helm_nova_heat_image_tag }}"
ks_service: "{{ openstack_helm_nova_image_repository }}/heat:{{ openstack_helm_nova_heat_image_tag }}"
ks_user: "{{ openstack_helm_nova_image_repository }}/heat:{{ openstack_helm_nova_heat_image_tag }}"
nova_api: "{{ openstack_helm_nova_image_repository }}/nova:{{ openstack_helm_nova_image_tag }}"
nova_archive_deleted_rows: "{{ openstack_helm_nova_image_repository }}/nova:{{ openstack_helm_nova_image_tag }}"
nova_cell_setup_init: "{{ openstack_helm_nova_image_repository }}/heat:{{ openstack_helm_nova_heat_image_tag }}"
nova_cell_setup: "{{ openstack_helm_nova_image_repository }}/nova:{{ openstack_helm_nova_image_tag }}"
# TODO(mnaser): Fix Ironic images
nova_compute_ironic: "docker.io/kolla/ubuntu-source-nova-compute-ironic:wallaby"
nova_compute_ssh: "{{ openstack_helm_nova_image_repository }}/nova-ssh:{{ openstack_helm_nova_ssh_image_tag }}"
nova_compute: "{{ openstack_helm_nova_image_repository }}/nova:{{ openstack_helm_nova_image_tag }}"
nova_conductor: "{{ openstack_helm_nova_image_repository }}/nova:{{ openstack_helm_nova_image_tag }}"
nova_consoleauth: "{{ openstack_helm_nova_image_repository }}/nova:{{ openstack_helm_nova_image_tag }}"
nova_db_sync: "{{ openstack_helm_nova_image_repository }}/nova:{{ openstack_helm_nova_image_tag }}"
nova_novncproxy_assets: "{{ openstack_helm_nova_image_repository }}/nova:{{ openstack_helm_nova_image_tag }}"
nova_novncproxy: "{{ openstack_helm_nova_image_repository }}/nova:{{ openstack_helm_nova_image_tag }}"
nova_placement: "{{ openstack_helm_nova_image_repository }}/nova:{{ openstack_helm_nova_image_tag }}"
nova_scheduler: "{{ openstack_helm_nova_image_repository }}/nova:{{ openstack_helm_nova_image_tag }}"
nova_service_cleaner: "{{ openstack_helm_nova_image_repository }}/cli:latest"
nova_spiceproxy_assets: "{{ openstack_helm_nova_image_repository }}/nova:{{ openstack_helm_nova_image_tag }}"
nova_spiceproxy: "{{ openstack_helm_nova_image_repository }}/nova:{{ openstack_helm_nova_image_tag }}"
rabbit_init: "{{ openstack_helm_nova_image_repository }}/rabbitmq:3.8.23-management"
bootstrap:
structured:
flavors:
enabled: false
pod:
replicas:
api_metadata: 3
osapi: 3
conductor: 3
scheduler: 3
novncproxy: 3
spiceproxy: 3
conf:
paste:
composite:openstack_compute_api_v21:
keystone: cors http_proxy_to_wsgi compute_req_id faultwrap sizelimit authtoken keystonecontext osapi_compute_app_v21
composite:openstack_compute_api_v21_legacy_v2_compatible:
keystone: cors http_proxy_to_wsgi compute_req_id faultwrap sizelimit authtoken keystonecontext legacy_v2_compatible osapi_compute_app_v21
nova:
DEFAULT:
cpu_allocation_ratio: 4.5
ram_allocation_ratio: 0.9
disk_allocation_ratio: 3.0
resume_guests_state_on_host_boot: true
osapi_compute_workers: 8
metadata_workers: 8
cache:
backend: oslo_cache.memcache_pool
cinder:
catalog_info: volumev3::internalURL
conductor:
workers: 8
cors:
allowed_origin: "*"
allow_headers: "X-Auth-Token,X-OpenStack-Nova-API-Version"
filter_scheduler:
enabled_filters: ComputeFilter, AggregateTypeAffinityFilter, ComputeCapabilitiesFilter, PciPassthroughFilter, ImagePropertiesFilter, ServerGroupAntiAffinityFilter, ServerGroupAffinityFilter
image_properties_default_architecture: x86_64
max_instances_per_host: 200
glance:
enable_rbd_download: true
neutron:
metadata_proxy_shared_secret: "{{ openstack_helm_endpoints['compute_metadata']['secret'] }}"
scheduler:
workers: 8
nova_ironic:
DEFAULT:
log_config_append: null
force_config_drive: true
manifests:
deployment_consoleauth: false
deployment_placement: false
ingress_metadata: false
ingress_novncproxy: false
ingress_osapi: false
ingress_placement: false
job_db_init_placement: false
job_ks_placement_endpoints: false
job_ks_placement_service: false
job_ks_placement_user: false
secret_keystone_placement: false
service_ingress_metadata: false
service_ingress_novncproxy: false
service_ingress_osapi: false
service_ingress_placement: false
service_placement: false
statefulset_compute_ironic: true

View File

@ -0,0 +1,23 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
openstack_helm_placement_chart_repo_name: openstack-helm
openstack_helm_placement_chart_repo_url: https://tarballs.opendev.org/openstack/openstack-helm/
openstack_helm_placement_chart_name: placement
openstack_helm_placement_image_repository: "{{ atmosphere_image_repository | default('us-docker.pkg.dev/vexxhost-infra/openstack') }}"
openstack_helm_placement_image_tag: 5.0.1
openstack_helm_placement_heat_image_tag: wallaby
openstack_helm_placement_values: {}

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: "{{ openstack_helm_placement_chart_repo_name }}"
helm_repository_repo_url: "{{ openstack_helm_placement_chart_repo_url }}"

View File

@ -0,0 +1,38 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Generate OpenStack-Helm endpoints
ansible.builtin.include_role:
name: openstack_helm_endpoints
vars:
openstack_helm_endpoints_repo_name: "{{ openstack_helm_placement_chart_repo_name }}"
openstack_helm_endpoints_repo_url: "{{ openstack_helm_placement_chart_repo_url }}"
openstack_helm_endpoints_chart: "{{ openstack_helm_placement_chart_name }}"
- name: Deploy Helm chart
kubernetes.core.helm:
name: "{{ openstack_helm_placement_chart_name }}"
chart_ref: "{{ openstack_helm_placement_chart_repo_name }}/{{ openstack_helm_placement_chart_name }}"
chart_version: 0.2.5
release_namespace: openstack
kubeconfig: /etc/kubernetes/admin.conf
values: "{{ _openstack_helm_placement_values | combine(openstack_helm_placement_values, recursive=True) }}"
- name: Create Ingress
ansible.builtin.include_role:
name: openstack_helm_ingress
vars:
openstack_helm_ingress_endpoint: placement
openstack_helm_ingress_service_name: placement-api
openstack_helm_ingress_service_port: 8778

View File

@ -0,0 +1,38 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
_openstack_helm_placement_values:
endpoints: "{{ openstack_helm_endpoints }}"
images:
tags:
bootstrap: "{{ openstack_helm_placement_image_repository }}/heat:{{ openstack_helm_placement_heat_image_tag }}"
db_drop: "{{ openstack_helm_placement_image_repository }}/heat:{{ openstack_helm_placement_heat_image_tag }}"
db_init: "{{ openstack_helm_placement_image_repository }}/heat:{{ openstack_helm_placement_heat_image_tag }}"
dep_check: "{{ openstack_helm_placement_image_repository }}/kubernetes-entrypoint:latest"
ks_endpoints: "{{ openstack_helm_placement_image_repository }}/heat:{{ openstack_helm_placement_heat_image_tag }}"
ks_service: "{{ openstack_helm_placement_image_repository }}/heat:{{ openstack_helm_placement_heat_image_tag }}"
ks_user: "{{ openstack_helm_placement_image_repository }}/heat:{{ openstack_helm_placement_heat_image_tag }}"
placement_db_sync: "{{ openstack_helm_placement_image_repository }}/placement:{{ openstack_helm_placement_image_tag }}"
placement: "{{ openstack_helm_placement_image_repository }}/placement:{{ openstack_helm_placement_image_tag }}"
rabbit_init: "{{ openstack_helm_placement_image_repository }}/rabbitmq:3.8.23-management"
pod:
replicas:
api: 3
conf:
placement:
DEFAULT:
log_config_append: null
manifests:
ingress: false
service_ingress: false

View File

@ -0,0 +1,22 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Create namespace
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Namespace
metadata:
name: openstack

View File

@ -0,0 +1,19 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: percona
helm_repository_repo_url: https://percona.github.io/percona-helm-charts/

View File

@ -0,0 +1,180 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Deploy Helm chart
kubernetes.core.helm:
name: pxc-operator
chart_ref: percona/pxc-operator
chart_version: 1.10.0
release_namespace: openstack
create_namespace: true
kubeconfig: /etc/kubernetes/admin.conf
- name: Deploy cluster
kubernetes.core.k8s:
state: present
definition:
apiVersion: pxc.percona.com/v1-10-0
kind: PerconaXtraDBCluster
metadata:
name: percona-xtradb
namespace: openstack
spec:
crVersion: 1.10.0
secretsName: percona-xtradb
pxc:
size: 3
image: percona/percona-xtradb-cluster:5.7.36-31.55
autoRecovery: true
configuration: |
[mysqld]
max_connections=8192
sidecars:
- name: exporter
image: quay.io/prometheus/mysqld-exporter:v0.14.0
ports:
- name: metrics
containerPort: 9104
livenessProbe:
httpGet:
path: /
port: 9104
env:
- name: MONITOR_PASSWORD
valueFrom:
secretKeyRef:
name: percona-xtradb
key: monitor
- name: DATA_SOURCE_NAME
value: "monitor:$(MONITOR_PASSWORD)@(localhost:3306)/"
nodeSelector:
openstack-control-plane: enabled
volumeSpec:
persistentVolumeClaim:
resources:
requests:
storage: 160Gi
haproxy:
enabled: true
size: 3
image: percona/percona-xtradb-cluster-operator:1.10.0-haproxy
nodeSelector:
openstack-control-plane: enabled
wait: true
wait_timeout: 600
wait_condition:
type: "ready"
status: "True"
- name: Create PodMonitor
kubernetes.core.k8s:
state: present
definition:
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: percona-xtradb-pxc
namespace: monitoring
labels:
release: kube-prometheus-stack
spec:
jobLabel: app.kubernetes.io/component
podMetricsEndpoints:
- port: metrics
path: /metrics
relabelings:
- sourceLabels: ["__meta_kubernetes_pod_name"]
targetLabel: "instance"
- action: "labeldrop"
regex: "^(container|endpoint|namespace|pod|service)$"
namespaceSelector:
matchNames:
- openstack
selector:
matchLabels:
app.kubernetes.io/component: pxc
app.kubernetes.io/instance: percona-xtradb
- name: Create PrometheusRule
kubernetes.core.k8s:
state: present
definition:
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: percona-xtradb-pxc
namespace: monitoring
labels:
release: kube-prometheus-stack
spec:
groups:
# TODO: basic rules
- name: general
rules:
- alert: MySQLDown
expr: mysql_up != 1
for: 5m
labels:
severity: critical
- alert: MysqlTooManyConnections
expr: max_over_time(mysql_global_status_threads_connected[1m]) / mysql_global_variables_max_connections * 100 > 80
for: 2m
labels:
severity: warning
- alert: MysqlHighThreadsRunning
expr: max_over_time(mysql_global_status_threads_running[1m]) / mysql_global_variables_max_connections * 100 > 60
for: 2m
labels:
severity: warning
- alert: MysqlSlowQueries
expr: increase(mysql_global_status_slow_queries[1m]) > 0
for: 2m
labels:
severity: warning
- name: galera
rules:
- alert: MySQLGaleraNotReady
expr: mysql_global_status_wsrep_ready != 1
for: 5m
labels:
severity: critical
- alert: MySQLGaleraOutOfSync
expr: mysql_global_status_wsrep_local_state != 4 and mysql_global_variables_wsrep_desync == 0
for: 5m
labels:
severity: critical
- alert: MySQLGaleraDonorFallingBehind
expr: mysql_global_status_wsrep_local_state == 2 and mysql_global_status_wsrep_local_recv_queue > 100
for: 5m
labels:
severity: warning
- alert: MySQLReplicationNotRunning
expr: mysql_slave_status_slave_io_running == 0 or mysql_slave_status_slave_sql_running == 0
for: 2m
labels:
severity: critical
- alert: MySQLReplicationLag
expr: (instance:mysql_slave_lag_seconds > 30) and on(instance) (predict_linear(instance:mysql_slave_lag_seconds[5m], 60 * 2) > 0)
for: 1m
labels:
severity: critical
- alert: MySQLHeartbeatLag
expr: (instance:mysql_heartbeat_lag_seconds > 30) and on(instance) (predict_linear(instance:mysql_heartbeat_lag_seconds[5m], 60 * 2) > 0)
for: 1m
labels:
severity: critical
- alert: MySQLInnoDBLogWaits
expr: rate(mysql_global_status_innodb_log_waits[15m]) > 10
labels:
severity: warning

View File

@ -0,0 +1,21 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
dependencies:
- role: helm_repository
vars:
helm_repository_name: prometheus-community
helm_repository_repo_url: https://prometheus-community.github.io/helm-charts
- cilium
- kube_prometheus_stack

View File

@ -0,0 +1,34 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- name: Deploy Helm chart
kubernetes.core.helm:
name: prometheus-pushgateway
chart_ref: prometheus-community/prometheus-pushgateway
chart_version: 1.16.0
release_namespace: monitoring
kubeconfig: /etc/kubernetes/admin.conf
values:
nodeSelector:
openstack-control-plane: enabled
serviceMonitor:
enabled: true
namespace: monitoring
additionalLabels:
release: kube-prometheus-stack
relabelings:
- sourceLabels: ["__meta_kubernetes_pod_name"]
targetLabel: "instance"
- regex: "^(container|endpoint|namespace|pod|service)$"
action: "labeldrop"

12
tox.ini
View File

@ -17,8 +17,16 @@ requires = tox-ansible
skipsdist = True
[testenv]
usedevelop = True
skipsdist = True
passenv =
OS_*
TERM
STACK_NAME
STACK_NAME
[testenv:molecule]
deps =
ansible
molecule==3.5.2
-rmolecule/default/requirements.txt
commands =
molecule {posargs}

View File

@ -17,6 +17,9 @@
parent: vexxhost-tox-molecule
pre-run:
- zuul.d/playbooks/ansible-collection-atmosphere-tox-molecule/pre-run.yml
cleanup-run:
- zuul.d/playbooks/ansible-collection-atmosphere-tox-molecule/cleanup-run.yml
timeout: 3600
vars:
tox_environment:
STACK_NAME: "atmosphere-{{ zuul.build }}"

View File

@ -0,0 +1,18 @@
# Copyright (c) 2022 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
- hosts: all
tasks:
- name: Destroy the Molecule environment
shell: tox -e molecule -- destroy --all