diff --git a/devstack/lib/heat b/devstack/lib/heat index 8f572aec..0858d389 100644 --- a/devstack/lib/heat +++ b/devstack/lib/heat @@ -237,13 +237,13 @@ function install_heat { # start_heat() - Start running processes, including screen - function start_heat { # rollout heat - kubernetes_rollout_restart deploy/heat-api - kubernetes_rollout_restart deploy/heat-api-cfn - kubernetes_rollout_restart deploy/heat-engine + kubernetes_rollout_restart daemonset/heat-api + kubernetes_rollout_restart daemonset/heat-api-cfn + kubernetes_rollout_restart daemonset/heat-engine - kubernetes_rollout_status deploy/heat-api - kubernetes_rollout_status deploy/heat-api-cfn - kubernetes_rollout_status deploy/heat-engine + kubernetes_rollout_status daemonset/heat-api + kubernetes_rollout_status daemonset/heat-api-cfn + kubernetes_rollout_status daemonset/heat-engine proxy_pass_to_kubernetes /heat-api heat-api heat-wsgi-api proxy_pass_to_kubernetes /heat-api-cfn heat-api-cfn heat-wsgi-api-cfn diff --git a/images/heat/Dockerfile b/images/heat/Dockerfile index 6cee0447..ff68b56a 100644 --- a/images/heat/Dockerfile +++ b/images/heat/Dockerfile @@ -27,10 +27,12 @@ RUN /output/install-from-bindep FROM heat-api-base AS heat-api EXPOSE 8004 ENV UWSGI_HTTP_SOCKET=:8004 UWSGI_WSGI_FILE=/usr/local/bin/heat-wsgi-api +CMD ["/usr/local/bin/uwsgi","--ini","/etc/uwsgi/uwsgi.ini"] FROM heat-api-base AS heat-api-cfn EXPOSE 8000 ENV UWSGI_HTTP_SOCKET=:8000 UWSGI_WSGI_FILE=/usr/local/bin/heat-wsgi-api-cfn +CMD ["/usr/local/bin/uwsgi","--ini","/etc/uwsgi/uwsgi.ini"] FROM docker.io/opendevorg/python-base AS heat-engine COPY --from=builder /output/ /output diff --git a/openstack_operator/heat.py b/openstack_operator/heat.py index 9996325b..5e45bdfa 100644 --- a/openstack_operator/heat.py +++ b/openstack_operator/heat.py @@ -32,24 +32,46 @@ def create_or_resume(name, spec, **_): config_hash = utils.generate_hash(spec) for component in ("api", "api-cfn"): - utils.create_or_update('heat/deployment.yml.j2', + utils.create_or_update('heat/daemonset.yml.j2', name=name, spec=spec, component=component, config_hash=config_hash) + utils.create_or_update('heat/service.yml.j2', name=name, component=component) - utils.create_or_update('heat/horizontalpodautoscaler.yml.j2', - name=name, component=component) - utils.create_or_update('heat/deployment.yml.j2', + # NOTE(Alex): We should remove this once all deployments are no longer + # using Deployment. + utils.ensure_absent('heat/deployment.yml.j2', + name=name, spec=spec, + component=component, + config_hash=config_hash) + + # NOTE(Alex): We should remove this once all deployments are no longer + # using HPA. + utils.ensure_absent('heat/horizontalpodautoscaler.yml.j2', + name=name, component=component) + + utils.create_or_update('heat/daemonset.yml.j2', name=name, spec=spec, component='engine', config_hash=config_hash) - utils.create_or_update('heat/horizontalpodautoscaler.yml.j2', - name=name, component='engine') + if "ingress" in spec: utils.create_or_update('heat/ingress.yml.j2', name=name, spec=spec) + # NOTE(Alex): We should remove this once all deployments are no longer + # using Deployment. + utils.ensure_absent('heat/deployment.yml.j2', + name=name, spec=spec, + component='engine', + config_hash=config_hash) + + # NOTE(Alex): We should remove this once all deployments are no longer + # using HPA. + utils.ensure_absent('heat/horizontalpodautoscaler.yml.j2', + name=name, component='engine') + def update(name, spec, **_): """Update a heat diff --git a/openstack_operator/templates/heat/daemonset.yml.j2 b/openstack_operator/templates/heat/daemonset.yml.j2 new file mode 100644 index 00000000..57b29cf6 --- /dev/null +++ b/openstack_operator/templates/heat/daemonset.yml.j2 @@ -0,0 +1,117 @@ +--- +# 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. + +{% if component is defined %} +{% set component = component %} +{% else %} +{% set component = "api" %} +{% endif %} + +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: heat-{{ component }} + namespace: openstack + labels: + {{ labels("heat", name, component) | indent(4) }} +spec: + updateStrategy: + rollingUpdate: + maxUnavailable: 1 + type: RollingUpdate + selector: + matchLabels: + {{ labels("heat", name, component) | indent(6) }} + template: + metadata: + labels: + {{ labels("heat", name, component) | indent(8) }} + annotations: + checksum/config: "{{ config_hash }}" + spec: + {% if 'engine' in component %} + terminationGracePeriodSeconds: 300 + initContainers: + - name: db-sync + image: vexxhost/heat-{{ component }}:latest + imagePullPolicy: Always + command: + - heat-manage + - db_sync + volumeMounts: + - mountPath: /etc/heat + name: config + {% endif %} + containers: + - name: heat-{{ component }} + image: vexxhost/heat-{{ component }}:latest + imagePullPolicy: Always + {% if env is defined %} + env: + {% for v in env %} + - name: "{{ v.name }}" + value: "{{ v.value }}" + {% endfor %} + {% endif %} + {% if 'api' in component %} + ports: + - name: heat-{{ component }} + protocol: TCP + containerPort: {% if component == 'api' %}8004{% else %}8000{% endif%} + livenessProbe: + tcpSocket: + port: heat-{{ component }} + readinessProbe: + tcpSocket: + port: heat-{{ component }} + lifecycle: + preStop: + exec: + command: ["/bin/sleep", "5"] + {% endif %} + resources: + requests: + cpu: 200m + ephemeral-storage: 50M + memory: 64M + securityContext: + runAsUser: 65534 + runAsGroup: 65534 + volumeMounts: + - mountPath: /etc/heat + name: config + - name: uwsgi-config + mountPath: /etc/uwsgi + volumes: + - name: config + hostPath: + path: {{ spec['configDir'] }} + type: Directory + - name: uwsgi-config + configMap: + defaultMode: 420 + name: uwsgi-default +{% if 'nodeSelector' in spec %} + nodeSelector: + {{ spec.nodeSelector | to_yaml | indent(8) }} +{% endif %} +{% if 'tolerations' in spec %} + tolerations: + {{ spec.tolerations | to_yaml | indent(8) }} +{% endif %} +{% if 'hostAliases' in spec %} + hostAliases: + {{ spec.hostAliases | to_yaml | indent(8) }} +{% endif %} diff --git a/openstack_operator/templates/operator/uwsgidefaultconfig.yml.j2 b/openstack_operator/templates/operator/uwsgidefaultconfig.yml.j2 index 5fc18eeb..4e5a3c4b 100644 --- a/openstack_operator/templates/operator/uwsgidefaultconfig.yml.j2 +++ b/openstack_operator/templates/operator/uwsgidefaultconfig.yml.j2 @@ -4,19 +4,19 @@ metadata: name: uwsgi-default namespace: openstack data: - uwsgi.yaml: | - uwsgi: - enable-threads: True - processes: '%k' - exit-on-reload: True - die-on-term: True - lazy-apps: True - add-header: 'Connection: close' - buffer-size: 65535 - thunder-lock: True - http-auto-chunked: True - http-raw-body: True - socket-timeout: 10 - need-app: True - route-user-agent: '^kube-probe.* donotlog:' - log-x-forwarded-for: True + uwsgi.ini: |- + [uwsgi] + enable-threads = true + workers = %(%k * 1) + exit-on-reload = true + die-on-term = true + lazy-apps = true + add-header = 'Connection: close' + buffer-size = 65535 + thunder-lock = true + http-auto-chunked = true + http-raw-body = true + socket-timeout = 10 + need-app = true + route-user-agent = '^kube-probe.* donotlog:' + log-x-forwarded-for = true