diff --git a/Makefile b/Makefile index 81080ca7..988c6876 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ images: docker build images/heat --target heat-api -t vexxhost/heat-api:latest docker build images/heat --target heat-api-cfn -t vexxhost/heat-api-cfn:latest docker build images/heat --target heat-engine -t vexxhost/heat-engine:latest + docker build images/chronyd -t vexxhost/chronyd:latest docker build images/mcrouter -t vexxhost/mcrouter:latest docker build images/mcrouter-exporter -t vexxhost/mcrouter-exporter:latest docker build images/memcached -t vexxhost/memcached:latest diff --git a/chart/templates/clusterrole.yaml b/chart/templates/clusterrole.yaml index 9093a46c..39821942 100644 --- a/chart/templates/clusterrole.yaml +++ b/chart/templates/clusterrole.yaml @@ -9,6 +9,7 @@ rules: - apiGroups: - apps resources: + - daemonsets - deployments - statefulsets verbs: diff --git a/chart/test-values.yaml b/chart/test-values.yaml index 2e3632b4..edca641a 100644 --- a/chart/test-values.yaml +++ b/chart/test-values.yaml @@ -7,4 +7,5 @@ configMap: keystone: configDir: /etc/keystone heat: - configDir: /etc/heat \ No newline at end of file + configDir: /etc/heat + chronyd: {} \ No newline at end of file diff --git a/images/chronyd/Dockerfile b/images/chronyd/Dockerfile new file mode 100644 index 00000000..7ffc67a2 --- /dev/null +++ b/images/chronyd/Dockerfile @@ -0,0 +1,17 @@ +# Copyright (c) 2020 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. + +FROM pnnlmiscscripts/chronyd:latest +CMD ["/usr/sbin/chronyd", "-d"] diff --git a/openstack_operator/chronyd.py b/openstack_operator/chronyd.py new file mode 100644 index 00000000..0acc7d3c --- /dev/null +++ b/openstack_operator/chronyd.py @@ -0,0 +1,35 @@ +# Copyright 2020 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. + +"""chronyd Operator + +This module maintains the operator for Chronyd, it takes care of creating +the appropriate daemonset, and configMap. +""" + + +from openstack_operator import utils + + +def create_or_resume(spec, **_): + """Create and re-sync a chronyd instance + + This function is called when a new resource is created but also when we + start the service up for the first time. + """ + + utils.create_or_update('chronyd/daemonset.yml.j2', + spec=spec) + utils.create_or_update('chronyd/configmap.yml.j2', + spec=spec) diff --git a/openstack_operator/objects.py b/openstack_operator/objects.py index c8db4ae2..26f54122 100644 --- a/openstack_operator/objects.py +++ b/openstack_operator/objects.py @@ -23,6 +23,7 @@ from combinations of apiVersion and kind to the exact model. """ from pykube.objects import ConfigMap +from pykube.objects import DaemonSet from pykube.objects import Deployment from pykube.objects import HorizontalPodAutoscaler from pykube.objects import Ingress @@ -75,6 +76,7 @@ MAPPING = { "Service": Service, }, "apps/v1": { + "DaemonSet": DaemonSet, "Deployment": Deployment, "StatefulSet": StatefulSet, }, diff --git a/openstack_operator/operator.py b/openstack_operator/operator.py index b6ff0618..f1d843aa 100644 --- a/openstack_operator/operator.py +++ b/openstack_operator/operator.py @@ -22,6 +22,7 @@ the appropriate deployments, an instance of Keystone, Heat and Horizon import os import kopf +from openstack_operator import chronyd from openstack_operator import heat from openstack_operator import horizon from openstack_operator import keystone @@ -58,6 +59,8 @@ async def startup_fn(logger, **kwargs): horizon.create_or_resume("horizon", config["horizon"]) if "heat" in config: heat.create_or_resume("heat", config["heat"]) + if "chronyd" in config: + chronyd.create_or_resume(config["chronyd"]) @kopf.on.update('', 'v1', 'configmaps') diff --git a/openstack_operator/templates/chronyd/configmap.yml.j2 b/openstack_operator/templates/chronyd/configmap.yml.j2 new file mode 100644 index 00000000..4db1c10c --- /dev/null +++ b/openstack_operator/templates/chronyd/configmap.yml.j2 @@ -0,0 +1,25 @@ +--- +# Copyright 2020 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. + +apiVersion: v1 +kind: ConfigMap +metadata: + name: chronyd + namespace: openstack +data: + chrony.conf: | + pool pool.ntp.org iburst maxsources 3 + rtcsync + driftfile /var/lib/chrony/drift \ No newline at end of file diff --git a/openstack_operator/templates/chronyd/daemonset.yml.j2 b/openstack_operator/templates/chronyd/daemonset.yml.j2 new file mode 100644 index 00000000..f645daad --- /dev/null +++ b/openstack_operator/templates/chronyd/daemonset.yml.j2 @@ -0,0 +1,76 @@ +--- +# Copyright 2020 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. + +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: chronyd + namespace: openstack + labels: + {{ labels("chronyd", "chronyd") | indent(4) }} +spec: + updateStrategy: + rollingUpdate: + maxUnavailable: 1 + type: RollingUpdate + selector: + matchLabels: + {{ labels("chronyd", "chronyd") | indent(6) }} + template: + metadata: + labels: + {{ labels("chronyd", "chronyd") | indent(8) }} + spec: + containers: + - name: main + image: vexxhost/chronyd:latest + imagePullPolicy: Always + resources: + limits: + cpu: 500m + ephemeral-storage: 100M + memory: 256M + requests: + cpu: 250m + ephemeral-storage: 100M + memory: 128M + securityContext: + capabilities: + add: ["SYS_TIME"] + volumeMounts: + - mountPath: /var/lib/chrony + name: state + - mountPath: /etc/chrony/chrony.conf + subPath: chrony.conf + name: config + volumes: + - name: config + configMap: + name: chronyd + - name: state + emptyDir: {} +{% if 'nodeSelector' in spec %} + nodeSelector: + {{ spec.nodeSelector | to_yaml | indent(8) }} +{% endif %} + tolerations: + - key: CriticalAddonsOnly + operator: Exists + - operator: Exists + - effect: NoSchedule + key: node-role.kubernetes.io/master +{% if 'tolerations' in spec %} + {{ spec.tolerations | to_yaml | indent(8) }} +{% endif %} diff --git a/playbooks/functional/tests/memcached.yaml b/playbooks/functional/tests/memcached.yaml index 354e8493..0460ac86 100644 --- a/playbooks/functional/tests/memcached.yaml +++ b/playbooks/functional/tests/memcached.yaml @@ -25,7 +25,7 @@ command: kubectl get pods -l app.kubernetes.io/name=memcached,app.kubernetes.io/instance=devstack -o=jsonpath='{range .items[*]}{.status.podIP}{"\n"}{end}' register: _memcached_ips until: _memcached_ips is success - retries: 10 + retries: 20 delay: 5 failed_when: | {{ _memcached_ips.stdout_lines | length == 0 }} or diff --git a/zuul.d/chronyd-jobs.yaml b/zuul.d/chronyd-jobs.yaml new file mode 100644 index 00000000..746577df --- /dev/null +++ b/zuul.d/chronyd-jobs.yaml @@ -0,0 +1,35 @@ +- job: + name: openstack-operator:images:build:chronyd + parent: vexxhost-build-docker-image + provides: openstack-operator:image:chronyd + vars: &id001 + docker_images: + - context: images/chronyd + repository: vexxhost/chronyd + dependencies: + - openstack-operator:images:build:openstack-operator + files: &id002 + - ^images/chronyd/.* +- job: + name: openstack-operator:images:upload:chronyd + parent: vexxhost-upload-docker-image + provides: openstack-operator:image:chronyd + vars: *id001 + dependencies: + - openstack-operator:images:upload:openstack-operator + files: *id002 +- job: + name: openstack-operator:images:promote:chronyd + parent: vexxhost-promote-docker-image + vars: *id001 + files: *id002 +- project: + check: + jobs: + - openstack-operator:images:build:chronyd + gate: + jobs: + - openstack-operator:images:upload:chronyd + promote: + jobs: + - openstack-operator:images:promote:chronyd diff --git a/zuul.d/functional-jobs.yaml b/zuul.d/functional-jobs.yaml index 38f31e30..d139dec0 100644 --- a/zuul.d/functional-jobs.yaml +++ b/zuul.d/functional-jobs.yaml @@ -27,6 +27,8 @@ soft: true - name: openstack-operator:images:build:horizon soft: true + - name: openstack-operator:images:build:chronyd + soft: true - name: openstack-operator:images:build:rabbitmq soft: true - name: openstack-operator:images:build:ceilometer @@ -50,6 +52,8 @@ soft: true - name: openstack-operator:images:upload:horizon soft: true + - name: openstack-operator:images:upload:chronyd + soft: true - name: openstack-operator:images:upload:rabbitmq soft: true - name: openstack-operator:images:upload:ceilometer