[mariadb] Add mariadb controller support

This patch adds mairadb controller that is responsible to mark one
ready pod as mariadb_role: primary to forward all traffic to it.
This will allow to drop nginx ingress controller which adds extra
hops between client and server and uses heavy customized nginx templates.

Change-Id: I3b29bc2029bfd39754516e73a09e4e14c52ccc99
This commit is contained in:
Vasyl Saienko 2024-09-14 12:51:31 +00:00
parent d27ea24745
commit 954e338d17
10 changed files with 314 additions and 2 deletions

View File

@ -15,7 +15,7 @@ apiVersion: v1
appVersion: v10.6.7 appVersion: v10.6.7
description: OpenStack-Helm MariaDB description: OpenStack-Helm MariaDB
name: mariadb name: mariadb
version: 0.2.44 version: 0.2.45
home: https://mariadb.com/kb/en/ home: https://mariadb.com/kb/en/
icon: http://badges.mariadb.org/mariadb-badge-180x60.png icon: http://badges.mariadb.org/mariadb-badge-180x60.png
sources: sources:

View File

@ -0,0 +1,112 @@
#!/usr/bin/env python3
"""
Mariadb controller
The script is responsible for set mariadb_role: primary to first
active pod in mariadb deployment.
Env variables:
MARIADB_CONTROLLER_DEBUG: Flag to enable debug when set to 1.
MARIADB_CONTROLLER_CHECK_PODS_DELAY: The delay between check pod attempts.
MARIADB_CONTROLLER_PYKUBE_REQUEST_TIMEOUT: The timeout for kubernetes http session
MARIADB_CONTROLLER_PODS_NAMESPACE: The namespace to look for mariadb pods.
MARIADB_MASTER_SERVICE_NAME: The name of master service for mariadb.
Changelog:
0.1.0: Initial varsion
"""
import logging
import os
import sys
import time
import pykube
MARIADB_CONTROLLER_DEBUG = os.getenv("MARIADB_CONTROLLER_DEBUG")
MARIADB_CONTROLLER_CHECK_PODS_DELAY = int(
os.getenv("MARIADB_CONTROLLER_CHECK_PODS_DELAY", 10)
)
MARIADB_CONTROLLER_PYKUBE_REQUEST_TIMEOUT = int(
os.getenv("MARIADB_CONTROLLER_PYKUBE_REQUEST_TIMEOUT", 60)
)
MARIADB_CONTROLLER_PODS_NAMESPACE = os.getenv(
"MARIADB_CONTROLLER_PODS_NAMESPACE", "openstack"
)
MARIADB_MASTER_SERVICE_NAME = os.getenv(
"MARIADB_MASTER_SERVICE_NAME", "mariadb"
)
log_level = "DEBUG" if MARIADB_CONTROLLER_DEBUG else "INFO"
logging.basicConfig(
stream=sys.stdout,
format="%(asctime)s %(levelname)s %(name)s %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
LOG = logging.getLogger("mariadb-controller")
LOG.setLevel(log_level)
def login():
config = pykube.KubeConfig.from_env()
client = pykube.HTTPClient(
config=config, timeout=MARIADB_CONTROLLER_PYKUBE_REQUEST_TIMEOUT
)
LOG.info(f"Created k8s api client from context {config.current_context}")
return client
api = login()
def resource_list(klass, selector, namespace=None):
return klass.objects(api).filter(namespace=namespace, selector=selector)
def get_mariadb_pods():
sorted_pods = sorted(
resource_list(
pykube.Pod,
{"application": "mariadb", "component": "server"},
MARIADB_CONTROLLER_PODS_NAMESPACE,
).iterator(),
key=lambda i: i.name,
)
return sorted_pods
def get_mariadb_master_service(namespace):
return pykube.Service.objects(api).filter(namespace=namespace).get(name=MARIADB_MASTER_SERVICE_NAME)
def link_master_service(pod):
svc = get_mariadb_master_service(MARIADB_CONTROLLER_PODS_NAMESPACE)
svc.reload()
if svc.obj['spec']['selector'].get('statefulset.kubernetes.io/pod-name') == pod.name:
LOG.debug(f"Nothing to do, master service points to {pod.name}")
else:
svc.obj['spec']['selector']['statefulset.kubernetes.io/pod-name'] = pod.name
svc.update()
LOG.info(f"Link master service with {pod.name}")
def is_ready(pod):
if pod.ready and "deletionTimestamp" not in pod.metadata:
return True
def main():
while True:
for pod in get_mariadb_pods():
pod.reload()
if is_ready(pod):
link_master_service(pod)
break
LOG.debug(f"Sleeping for {MARIADB_CONTROLLER_CHECK_PODS_DELAY}")
time.sleep(MARIADB_CONTROLLER_CHECK_PODS_DELAY)
main()

View File

@ -53,4 +53,8 @@ data:
ks-user.sh: | ks-user.sh: |
{{ include "helm-toolkit.scripts.keystone_user" . | indent 4 }} {{ include "helm-toolkit.scripts.keystone_user" . | indent 4 }}
{{- end }} {{- end }}
{{- if .Values.manifests.deployment_controller }}
mariadb_controller.py: |
{{ tuple "bin/_mariadb_controller.py.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
{{- end }}
{{- end }} {{- end }}

View File

@ -0,0 +1,119 @@
{{/*
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.
*/}}
{{- if .Values.manifests.deployment_controller }}
{{- if .Values.manifests.deployment_ingress }}
{{- fail ".Values.manifests.deployment_ingress and .Values.manifests.deployment_controlle are mutually exclusive" }}
{{- end }}
{{- $envAll := . }}
{{- $serviceAccountName := "mariadb-controller" }}
{{ tuple $envAll "controller" $serviceAccountName | include "helm-toolkit.snippets.kubernetes_pod_rbac_serviceaccount" }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ $envAll.Release.Name }}-{{ $serviceAccountName }}-pod
namespace: {{ $envAll.Release.Namespace }}
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- apiGroups:
- ""
resources:
- services
verbs:
- update
- patch
- get
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ $envAll.Release.Name }}-{{ $serviceAccountName }}-pod
namespace: {{ $envAll.Release.Namespace }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ $envAll.Release.Name }}-{{ $serviceAccountName }}-pod
subjects:
- kind: ServiceAccount
name: {{ $serviceAccountName }}
namespace: {{ $envAll.Release.Namespace }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mariadb-controller
annotations:
{{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" }}
labels:
{{ tuple $envAll "mariadb" "controller" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
spec:
replicas: {{ .Values.pod.replicas.controller }}
selector:
matchLabels:
{{ tuple $envAll "mariadb" "controller" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 6 }}
{{ tuple $envAll | include "helm-toolkit.snippets.kubernetes_upgrades_deployment" | indent 2 }}
template:
metadata:
labels:
{{ tuple $envAll "mariadb" "controller" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
annotations:
{{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" | indent 8 }}
configmap-bin-hash: {{ tuple "configmap-bin.yaml" . | include "helm-toolkit.utils.hash" }}
spec:
serviceAccountName: {{ $serviceAccountName }}
{{ dict "envAll" $envAll "application" "controller" | include "helm-toolkit.snippets.kubernetes_pod_security_context" | indent 6 }}
affinity:
{{ tuple $envAll "mariadb" "controller" | include "helm-toolkit.snippets.kubernetes_pod_anti_affinity" | indent 8 }}
nodeSelector:
{{ .Values.labels.controller.node_selector_key }}: {{ .Values.labels.controller.node_selector_value }}
initContainers:
{{ tuple $envAll "controller" list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
containers:
- name: controller
{{ tuple $envAll "mariadb_controller" | include "helm-toolkit.snippets.image" | indent 10 }}
{{ dict "envAll" $envAll "application" "controller" "container" "controller" | include "helm-toolkit.snippets.kubernetes_container_security_context" | indent 10 }}
{{ tuple $envAll $envAll.Values.pod.resources.controller | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
command:
- /tmp/mariadb_controller.py
env:
{{ include "helm-toolkit.utils.to_k8s_env_vars" .Values.pod.env.mariadb_controller | indent 12 }}
- name: MARIADB_CONTROLLER_PODS_NAMESPACE
value: {{ $envAll.Release.Namespace }}
- name: MARIADB_MASTER_SERVICE_NAME
value: {{ tuple "oslo_db" "internal" . | include "helm-toolkit.endpoints.hostname_short_endpoint_lookup" }}
volumeMounts:
- name: pod-tmp
mountPath: /tmp
- mountPath: /tmp/mariadb_controller.py
name: mariadb-bin
readOnly: true
subPath: mariadb_controller.py
volumes:
- name: pod-tmp
emptyDir: {}
- name: mariadb-bin
configMap:
name: mariadb-bin
defaultMode: 365
{{- end }}

View File

@ -25,8 +25,13 @@ spec:
port: {{ tuple "oslo_db" "direct" "mysql" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }} port: {{ tuple "oslo_db" "direct" "mysql" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
- name: wsrep - name: wsrep
port: {{ tuple "oslo_db" "direct" "wsrep" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }} port: {{ tuple "oslo_db" "direct" "wsrep" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
- name: ist
port: {{ tuple "oslo_db" "direct" "ist" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
- name: sst
port: {{ tuple "oslo_db" "direct" "sst" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
clusterIP: None clusterIP: None
publishNotReadyAddresses: true publishNotReadyAddresses: true
selector: selector:
{{ tuple $envAll "mariadb" "server" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }} {{ tuple $envAll "mariadb" "server" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
{{ .Values.network.mariadb_discovery | include "helm-toolkit.snippets.service_params" | indent 2 }}
{{- end }} {{- end }}

View File

@ -0,0 +1,33 @@
{{/*
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.
*/}}
{{- if .Values.manifests.service_master }}
{{- if .Values.manifests.service_ingress }}
{{- fail ".Values.manifests.service_ingress and .Values.manifests.service_master are mutually exclusive" }}
{{- end }}
{{- $envAll := . }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ tuple "oslo_db" "internal" . | include "helm-toolkit.endpoints.hostname_short_endpoint_lookup" }}
spec:
ports:
- name: mysql
port: {{ tuple "oslo_db" "direct" "mysql" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
selector:
{{ tuple $envAll "mariadb" "server" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
{{ .Values.network.mariadb_master | include "helm-toolkit.snippets.service_params" | indent 2 }}
{{- end }}

View File

@ -25,4 +25,5 @@ spec:
port: {{ tuple "oslo_db" "direct" "mysql" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }} port: {{ tuple "oslo_db" "direct" "mysql" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
selector: selector:
{{ tuple $envAll "mariadb" "server" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }} {{ tuple $envAll "mariadb" "server" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
{{ .Values.network.mariadb | include "helm-toolkit.snippets.service_params" | indent 2 }}
{{- end }} {{- end }}

View File

@ -226,6 +226,12 @@ spec:
- name: wsrep - name: wsrep
protocol: TCP protocol: TCP
containerPort: {{ tuple "oslo_db" "direct" "wsrep" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }} containerPort: {{ tuple "oslo_db" "direct" "wsrep" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
- name: ist
protocol: TCP
containerPort: {{ tuple "oslo_db" "direct" "ist" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
- name: sst
protocol: TCP
containerPort: {{ tuple "oslo_db" "direct" "sst" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
command: command:
- /tmp/start.py - /tmp/start.py
lifecycle: lifecycle:

View File

@ -31,6 +31,7 @@ images:
mariadb_backup: quay.io/airshipit/porthole-mysqlclient-utility:latest-ubuntu_focal mariadb_backup: quay.io/airshipit/porthole-mysqlclient-utility:latest-ubuntu_focal
ks_user: docker.io/openstackhelm/heat:wallaby-ubuntu_focal ks_user: docker.io/openstackhelm/heat:wallaby-ubuntu_focal
scripted_test: docker.io/openstackhelm/mariadb:ubuntu_focal-20210415 scripted_test: docker.io/openstackhelm/mariadb:ubuntu_focal-20210415
mariadb_controller: docker.io/openstackhelm/mariadb:latest-ubuntu_focal
pull_policy: "IfNotPresent" pull_policy: "IfNotPresent"
local_registry: local_registry:
active: false active: false
@ -57,8 +58,16 @@ labels:
test: test:
node_selector_key: openstack-control-plane node_selector_key: openstack-control-plane
node_selector_value: enabled node_selector_value: enabled
controller:
node_selector_key: openstack-control-plane
node_selector_value: enabled
pod: pod:
env:
mariadb_controller:
MARIADB_CONTROLLER_DEBUG: 0
MARIADB_CONTROLLER_CHECK_PODS_DELAY: 10
MARIADB_CONTROLLER_PYKUBE_REQUEST_TIMEOUT: 60
probes: probes:
server: server:
mariadb: mariadb:
@ -136,6 +145,13 @@ pod:
test: test:
runAsUser: 999 runAsUser: 999
readOnlyRootFilesystem: true readOnlyRootFilesystem: true
controller:
pod:
runAsUser: 65534
container:
controller:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
affinity: affinity:
anti: anti:
type: type:
@ -159,6 +175,7 @@ pod:
ingress: 2 ingress: 2
error_page: 1 error_page: 1
prometheus_mysql_exporter: 1 prometheus_mysql_exporter: 1
controller: 1
lifecycle: lifecycle:
upgrades: upgrades:
deployments: deployments:
@ -282,7 +299,8 @@ dependencies:
services: services:
- endpoint: internal - endpoint: internal
service: oslo_db service: oslo_db
controller:
services: null
volume: volume:
# this value is used for single pod deployments of mariadb to prevent losing all data # this value is used for single pod deployments of mariadb to prevent losing all data
# if the pod is restarted # if the pod is restarted
@ -615,6 +633,10 @@ endpoints:
default: 3306 default: 3306
wsrep: wsrep:
default: 4567 default: 4567
ist:
default: 4568
sst:
default: 4444
kube_dns: kube_dns:
namespace: kube-system namespace: kube-system
name: kubernetes-dns name: kubernetes-dns
@ -670,6 +692,13 @@ endpoints:
default: 80 default: 80
internal: 5000 internal: 5000
network:
mariadb: {}
mariadb_discovery: {}
mariadb_ingress: {}
mariadb_ingress_error_pages: {}
mariadb_master: {}
network_policy: network_policy:
mariadb: mariadb:
ingress: ingress:
@ -721,4 +750,6 @@ manifests:
service_error: false service_error: false
service: true service: true
statefulset: true statefulset: true
deployment_controller: false
service_master: false
... ...

View File

@ -60,4 +60,5 @@ mariadb:
- 0.2.42 Use quay.io/airshipit/kubernetes-entrypoint:latest-ubuntu_focal by default - 0.2.42 Use quay.io/airshipit/kubernetes-entrypoint:latest-ubuntu_focal by default
- 0.2.43 Add 2024.1 Ubuntu Jammy overrides - 0.2.43 Add 2024.1 Ubuntu Jammy overrides
- 0.2.44 Uplift ingress controller image to 1.11.2 - 0.2.44 Uplift ingress controller image to 1.11.2
- 0.2.45 Add mariadb controller support
... ...