tripleo-heat-templates/common/deploy-steps.j2
Dan Prince 949d367dde Add DockerPuppetProcessCount defaults to 3
docker-puppet.py is very aggressive about running concurrently.
It uses python multiprocessing to run multiple config generating
containers at once. This seems to work well in general, but
in some cases... perhaps when the registry is slow or under
heavy load can cause timeouts to occur. Lately I'm seeing
several 'container did not start before the specified timeout'
errors that always seem to occur when config files are generated
(docker-puppet.py is initially executed.

A couple of things:

 -when config files are generated this is the first time
  most of the containers are pulled to each host machine
  during deployment

 -docker-puppet.py runs many of these processes at once. Some
  of them run faster, other not.

 -docker daemon's pull limit defaults to 3. This would throttle
  the above a bit perhaps contributing the the likelyhood of a timeout.

One solution that seems to work for me is to set the PROCESS_COUNT
in docker-puppet.py to 3. As this matches docker daemon's default
it is probably safer at the cost of being slightly slower in some
cases.

Change-Id: I17feb3abd9d36fe7c95865a064502ce9902a074e
Closes-bug: #1713188
2017-08-25 23:01:24 -04:00

364 lines
14 KiB
Django/Jinja

# certain initialization steps (run in a container) will occur
# on the role marked as primary controller or the first role listed
{%- set primary_role = [roles[0]] -%}
{%- for role in roles -%}
{%- if 'primary' in role.tags and 'controller' in role.tags -%}
{%- set _ = primary_role.pop() -%}
{%- set _ = primary_role.append(role) -%}
{%- endif -%}
{%- endfor -%}
{%- set primary_role_name = primary_role[0].name -%}
# primary role is: {{primary_role_name}}
{% set deploy_steps_max = 6 -%}
{% set update_steps_max = 6 -%}
{% set upgrade_steps_max = 6 -%}
heat_template_version: pike
description: >
Post-deploy configuration steps via puppet for all roles,
as defined in ../roles_data.yaml
parameters:
servers:
type: json
description: Mapping of Role name e.g Controller to a list of servers
stack_name:
type: string
description: Name of the topmost stack
role_data:
type: json
description: Mapping of Role name e.g Controller to the per-role data
DeployIdentifier:
default: ''
type: string
description: >
Setting this to a unique value will re-run any deployment tasks which
perform configuration on a Heat stack-update.
EndpointMap:
default: {}
description: Mapping of service endpoint -> protocol. Typically set
via parameter_defaults in the resource registry.
type: json
DockerPuppetDebug:
type: string
default: ''
description: Set to True to enable debug logging with docker-puppet.py
DockerPuppetProcessCount:
type: number
default: 3
description: Number of concurrent processes to use when running docker-puppet to generate config files.
ctlplane_service_ips:
type: json
conditions:
{% for step in range(1, deploy_steps_max) %}
WorkflowTasks_Step{{step}}_Enabled:
or:
{%- for role in roles %}
- not:
equals:
- get_param: [role_data, {{role.name}}, service_workflow_tasks, step{{step}}]
- ''
- False
{%- endfor %}
{% endfor %}
resources:
RoleConfig:
type: OS::Heat::SoftwareConfig
properties:
group: ansible
options:
modulepath: /usr/share/ansible-modules
inputs:
- name: step
- name: role_name
- name: update_identifier
- name: bootstrap_server_id
- name: docker_puppet_debug
- name: docker_puppet_process_count
config:
str_replace:
template: |
- hosts: localhost
connection: local
tasks:
_TASKS
params:
_TASKS: {get_file: deploy-steps-tasks.yaml}
{%- for step in range(1, deploy_steps_max) %}
# BEGIN service_workflow_tasks handling
WorkflowTasks_Step{{step}}:
type: OS::Mistral::Workflow
condition: WorkflowTasks_Step{{step}}_Enabled
depends_on:
{%- if step == 1 %}
{%- for dep in roles %}
- {{dep.name}}PreConfig
- {{dep.name}}ArtifactsDeploy
{%- endfor %}
{%- else %}
{%- for dep in roles %}
- {{dep.name}}Deployment_Step{{step -1}}
{%- endfor %}
{%- endif %}
properties:
name: {list_join: [".", ["tripleo", {get_param: stack_name}, "workflowtasks", "step{{step}}"]]}
type: direct
tasks:
yaql:
expression: $.data.where($ != '').select($.get('step{{step}}')).where($ != null).flatten()
data:
{%- for role in roles %}
- get_param: [role_data, {{role.name}}, service_workflow_tasks]
{%- endfor %}
WorkflowTasks_Step{{step}}_Execution:
type: OS::Mistral::ExternalResource
condition: WorkflowTasks_Step{{step}}_Enabled
depends_on: WorkflowTasks_Step{{step}}
properties:
actions:
CREATE:
workflow: { get_resource: WorkflowTasks_Step{{step}} }
params:
env:
service_ips: { get_param: ctlplane_service_ips }
role_merged_configs:
{%- for r in roles %}
{{r.name}}: {get_param: [role_data, {{r.name}}, merged_config_settings]}
{%- endfor %}
evaluate_env: false
UPDATE:
workflow: { get_resource: WorkflowTasks_Step{{step}} }
params:
env:
service_ips: { get_param: ctlplane_service_ips }
role_merged_configs:
{%- for r in roles %}
{{r.name}}: {get_param: [role_data, {{r.name}}, merged_config_settings]}
{%- endfor %}
evaluate_env: false
always_update: true
# END service_workflow_tasks handling
{% endfor %}
{% for role in roles %}
# Post deployment steps for all roles
# A single config is re-applied with an incrementing step number
# {{role.name}} Role steps
{{role.name}}ArtifactsConfig:
type: ../puppet/deploy-artifacts.yaml
{{role.name}}ArtifactsDeploy:
type: OS::Heat::StructuredDeploymentGroup
properties:
servers: {get_param: [servers, {{role.name}}]}
config: {get_resource: {{role.name}}ArtifactsConfig}
{{role.name}}HostPrepConfig:
type: OS::Heat::SoftwareConfig
properties:
group: ansible
options:
modulepath: /usr/share/ansible-modules
config:
str_replace:
template: _PLAYBOOK
params:
_PLAYBOOK:
- hosts: localhost
connection: local
vars:
puppet_config: {get_param: [role_data, {{role.name}}, puppet_config]}
docker_puppet_script: {get_file: ../docker/docker-puppet.py}
docker_puppet_tasks: {get_param: [role_data, {{role.name}}, docker_puppet_tasks]}
docker_startup_configs: {get_param: [role_data, {{role.name}}, docker_config]}
kolla_config: {get_param: [role_data, {{role.name}}, kolla_config]}
bootstrap_server_id: {get_param: [servers, {{primary_role_name}}, '0']}
puppet_step_config: {get_param: [role_data, {{role.name}}, step_config]}
tasks:
# Join host_prep_tasks with the other per-host configuration
yaql:
expression: $.data.host_prep_tasks + $.data.template_tasks
data:
host_prep_tasks: {get_param: [role_data, {{role.name}}, host_prep_tasks]}
template_tasks:
{%- raw %}
# Write the manifest for baremetal puppet configuration
- name: Create /var/lib/tripleo-config directory
file: path=/var/lib/tripleo-config state=directory
- name: Write the puppet step_config manifest
copy: content="{{puppet_step_config}}" dest=/var/lib/tripleo-config/puppet_step_config.pp force=yes
# this creates a JSON config file for our docker-puppet.py script
- name: Create /var/lib/docker-puppet
file: path=/var/lib/docker-puppet state=directory
- name: Write docker-puppet-tasks json files
copy: content="{{puppet_config | to_json}}" dest=/var/lib/docker-puppet/docker-puppet.json force=yes
# FIXME: can we move docker-puppet somewhere so it's installed via a package?
- name: Write docker-puppet.py
copy: content="{{docker_puppet_script}}" dest=/var/lib/docker-puppet/docker-puppet.py force=yes
# Here we are dumping all the docker container startup configuration data
# so that we can have access to how they are started outside of heat
# and docker-cmd. This lets us create command line tools to test containers.
# FIXME do we need the docker-container-startup-configs.json or is the new per-step
# data consumed by paunch enough?
- name: Write docker-container-startup-configs
copy: content="{{docker_startup_configs | to_json}}" dest=/var/lib/docker-container-startup-configs.json force=yes
- name: Write per-step docker-container-startup-configs
copy: content="{{item.value|to_json}}" dest="/var/lib/tripleo-config/docker-container-startup-config-{{item.key}}.json" force=yes
with_dict: "{{docker_startup_configs}}"
- name: Create /var/lib/kolla/config_files directory
file: path=/var/lib/kolla/config_files state=directory
- name: Write kolla config json files
copy: content="{{item.value|to_json}}" dest="{{item.key}}" force=yes
with_dict: "{{kolla_config}}"
########################################################
# Bootstrap tasks, only performed on bootstrap_server_id
########################################################
- name: Clean /var/lib/docker-puppet/docker-puppet-tasks*.json files
file:
path: "{{item}}"
state: absent
with_fileglob:
- /var/lib/docker-puppet/docker-puppet-tasks*.json
when: deploy_server_id == bootstrap_server_id
- name: Write docker-puppet-tasks json files
copy: content="{{item.value|to_json}}" dest=/var/lib/docker-puppet/docker-puppet-tasks{{item.key.replace("step_", "")}}.json force=yes
with_dict: "{{docker_puppet_tasks}}"
when: deploy_server_id == bootstrap_server_id
{%- endraw %}
{{role.name}}HostPrepDeployment:
type: OS::Heat::SoftwareDeploymentGroup
properties:
servers: {get_param: [servers, {{role.name}}]}
config: {get_resource: {{role.name}}HostPrepConfig}
# BEGIN CONFIG STEPS
{{role.name}}PreConfig:
type: OS::TripleO::Tasks::{{role.name}}PreConfig
depends_on: {{role.name}}HostPrepDeployment
properties:
servers: {get_param: [servers, {{role.name}}]}
input_values:
update_identifier: {get_param: DeployIdentifier}
{% for step in range(1, deploy_steps_max) %}
{{role.name}}Deployment_Step{{step}}:
type: OS::TripleO::DeploymentSteps
depends_on:
- WorkflowTasks_Step{{step}}_Execution
# TODO(gfidente): the following if/else condition
# replicates what is already defined for the
# WorkflowTasks_StepX resource and can be remove
# if https://bugs.launchpad.net/heat/+bug/1700569
# is fixed.
{%- if step == 1 %}
{%- for dep in roles %}
- {{dep.name}}PreConfig
- {{dep.name}}ArtifactsDeploy
{%- endfor %}
{%- else %}
{%- for dep in roles %}
- {{dep.name}}Deployment_Step{{step -1}}
{%- endfor %}
{%- endif %}
properties:
name: {{role.name}}Deployment_Step{{step}}
servers: {get_param: [servers, {{role.name}}]}
config: {get_resource: RoleConfig}
input_values:
step: {{step}}
role_name: {{role.name}}
update_identifier: {get_param: DeployIdentifier}
bootstrap_server_id: {get_param: [servers, {{primary_role_name}}, '0']}
docker_puppet_debug: {get_param: DockerPuppetDebug}
docker_puppet_process_count: {get_param: DockerPuppetProcessCount}
{% endfor %}
# END CONFIG STEPS
# Note, this should be the last step to execute configuration changes.
# Ensure that all {{role.name}}ExtraConfigPost steps are executed
# after all the previous deployment steps.
{{role.name}}ExtraConfigPost:
depends_on:
{%- for dep in roles %}
- {{dep.name}}Deployment_Step5
{%- endfor %}
type: OS::TripleO::NodeExtraConfigPost
properties:
servers: {get_param: [servers, {{role.name}}]}
# The {{role.name}}PostConfig steps are in charge of
# quiescing all services, i.e. in the Controller case,
# we should run a full service reload.
{{role.name}}PostConfig:
type: OS::TripleO::Tasks::{{role.name}}PostConfig
depends_on:
{%- for dep in roles %}
- {{dep.name}}ExtraConfigPost
{%- endfor %}
properties:
servers: {get_param: servers}
input_values:
update_identifier: {get_param: DeployIdentifier}
{% endfor %}
outputs:
RoleConfig:
description: Mapping of config data for all roles
value:
deploy_steps_tasks: {get_file: deploy-steps-tasks.yaml}
deploy_steps_playbook: |
- hosts: overcloud
tasks:
{%- for role in roles %}
- include: {{role.name}}/host_prep_tasks.yaml
when: role_name == '{{role.name}}'
{%- endfor %}
- include: deploy_steps_tasks.yaml
with_sequence: start=0 end={{deploy_steps_max-1}}
loop_control:
loop_var: step
update_steps_tasks: |
{%- for role in roles %}
- include: {{role.name}}/update_tasks.yaml
when: role_name == '{{role.name}}'
{%- endfor %}
update_steps_playbook: |
- hosts: overcloud
serial: 1
tasks:
- include: update_steps_tasks.yaml
with_sequence: start=0 end={{update_steps_max-1}}
loop_control:
loop_var: step
- include: deploy_steps_tasks.yaml
with_sequence: start=0 end={{deploy_steps_max-1}}
loop_control:
loop_var: step
upgrade_steps_tasks: |
{%- for role in roles %}
- include: {{role.name}}/upgrade_tasks.yaml
when: role_name == '{{role.name}}'
{%- endfor %}
upgrade_steps_playbook: |
- hosts: overcloud
tasks:
- include: upgrade_steps_tasks.yaml
with_sequence: start=0 end={{upgrade_steps_max-1}}
loop_control:
loop_var: step
- include: deploy_steps_tasks.yaml
with_sequence: start=0 end={{deploy_steps_max-1}}
loop_control:
loop_var: step