diff --git a/README.md b/README.md index aaa25259..cbcb0cfd 100644 --- a/README.md +++ b/README.md @@ -716,7 +716,14 @@ spec: control_plane_priority_class: awx-demo-high-priority postgres_priority_class: awx-demo-medium-priority ``` +#### Scaling the Web and Task Pods independently +You can scale replicas up or down for each deployment by using the `web_replicas` or `task_replicas` respectively. You can scale all pods across both deployments by using `replicas` as well. The logic behind these CRD keys acts as such: + +- If you specify the `replicas` field, the key passed will scale both the `web` and `task` replicas to the same number. +- If `web_replicas` or `task_replicas` is ever passed, it will override the existing `replicas` field on the specific deployment with the new key value. + +These new replicas can be constrained in a similar manner to previous single deployments by appending the particular deployment name in front of the constraint used. More about those new constraints can be found below in the [Assigning AWX pods to specific nodes](#assigning-awx-pods-to-specific-nodes) section. #### Assigning AWX pods to specific nodes You can constrain the AWX pods created by the operator to run on a certain subset of nodes. `node_selector` and `postgres_selector` constrains @@ -725,18 +732,28 @@ pods to be scheduled onto nodes with matching taints. The ability to specify topologySpreadConstraints is also allowed through `topology_spread_constraints` If you want to use affinity rules for your AWX pod you can use the `affinity` option. +If you want to constrain the web and task pods individually, you can do so by specificying the deployment type before the specific setting. For +example, specifying `task_tolerations` will allow the AWX task pod to be scheduled onto nodes with matching taints. -| Name | Description | Default | -| --------------------------- | ----------------------------------- | ------- | -| postgres_image | Path of the image to pull | postgres | -| postgres_image_version | Image version to pull | 13 | -| node_selector | AWX pods' nodeSelector | '' | -| topology_spread_constraints | AWX pods' topologySpreadConstraints | '' | -| affinity | AWX pods' affinity rules | '' | -| tolerations | AWX pods' tolerations | '' | -| annotations | AWX pods' annotations | '' | -| postgres_selector | Postgres pods' nodeSelector | '' | -| postgres_tolerations | Postgres pods' tolerations | '' | +| Name | Description | Default | +| -------------------------------- | ---------------------------------------- | ------- | +| postgres_image | Path of the image to pull | postgres | +| postgres_image_version | Image version to pull | 13 | +| node_selector | AWX pods' nodeSelector | '' | +| web_node_selector | AWX web pods' nodeSelector | '' | +| task_node_selector | AWX task pods' nodeSelector | '' | +| topology_spread_constraints | AWX pods' topologySpreadConstraints | '' | +| web_topology_spread_constraints | AWX web pods' topologySpreadConstraints | '' | +| task_topology_spread_constraints | AWX task pods' topologySpreadConstraints | '' | +| affinity | AWX pods' affinity rules | '' | +| web_affinity | AWX web pods' affinity rules | '' | +| task_affinity | AWX task pods' affinity rules | '' | +| tolerations | AWX pods' tolerations | '' | +| web_tolerations | AWX web pods' tolerations | '' | +| task_tolerations | AWX task pods' tolerations | '' | +| annotations | AWX pods' annotations | '' | +| postgres_selector | Postgres pods' nodeSelector | '' | +| postgres_tolerations | Postgres pods' tolerations | '' | Example of customization could be: @@ -760,6 +777,11 @@ spec: operator: "Equal" value: "AWX" effect: "NoSchedule" + task_tolerations: | + - key: "dedicated" + operator: "Equal" + value: "AWX_task" + effect: "NoSchedule" postgres_selector: | disktype: ssd kubernetes.io/arch: amd64 diff --git a/config/crd/bases/awx.ansible.com_awxs.yaml b/config/crd/bases/awx.ansible.com_awxs.yaml index 9e30b9cb..3e0fef0f 100644 --- a/config/crd/bases/awx.ansible.com_awxs.yaml +++ b/config/crd/bases/awx.ansible.com_awxs.yaml @@ -160,9 +160,40 @@ spec: node_selector: description: nodeSelector for the pods type: string + web_node_selector: + description: nodeSelector for the web pods + type: string + task_node_selector: + description: nodeSelector for the task pods + type: string topology_spread_constraints: description: topology rule(s) for the pods type: string + task_topology_spread_constraints: + description: topology rule(s) for the task pods + type: string + web_topology_spread_constraints: + description: topology rule(s) for the web pods + type: string + termination_grace_period_seconds: + description: Optional duration in seconds pods needs to terminate gracefully + type: integer + format: int32 + service_labels: + description: Additional labels to apply to the service + type: string + annotations: + description: annotations for the pods + type: string + tolerations: + description: node tolerations for the pods + type: string + task_tolerations: + description: node tolerations for the task pods + type: string + web_tolerations: + description: node tolerations for the web pods + type: string affinity: description: If specified, the pod's scheduling constraints properties: @@ -529,19 +560,738 @@ spec: type: array type: object type: object - termination_grace_period_seconds: - description: Optional duration in seconds pods needs to terminate gracefully - type: integer - format: int32 - service_labels: - description: Additional labels to apply to the service - type: string - annotations: - description: annotations for the pods - type: string - tolerations: - description: node tolerations for the pods - type: string + web_affinity: + description: If specified, the pod's scheduling constraints + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + task_affinity: + description: If specified, the pod's scheduling constraints + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object image: description: Registry path to the application container to use type: string @@ -704,6 +1454,14 @@ spec: type: integer default: 1 format: int32 + web_replicas: + description: Number of web instance replicas + type: integer + format: int32 + task_replicas: + description: Number of task instance replicas + type: integer + format: int32 garbage_collect_secrets: description: Whether or not to remove secrets upon instance removal default: false diff --git a/config/manifests/bases/awx-operator.clusterserviceversion.yaml b/config/manifests/bases/awx-operator.clusterserviceversion.yaml index 13cf8d1d..656a07be 100644 --- a/config/manifests/bases/awx-operator.clusterserviceversion.yaml +++ b/config/manifests/bases/awx-operator.clusterserviceversion.yaml @@ -360,6 +360,16 @@ spec: x-descriptors: - urn:alm:descriptor:com.tectonic.ui:advanced - urn:alm:descriptor:com.tectonic.ui:number + - displayName: Web Replicas + path: web_replicas + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:number + - displayName: Task Replicas + path: task_replicas + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:number - displayName: Remove used secrets on instance removal? path: garbage_collect_secrets x-descriptors: @@ -608,16 +618,46 @@ spec: x-descriptors: - urn:alm:descriptor:com.tectonic.ui:advanced - urn:alm:descriptor:com.tectonic.ui:hidden + - displayName: Web Node Selector + path: web_node_selector + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:hidden + - displayName: Task Node Selector + path: task_node_selector + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:hidden - displayName: Topology Spread Constraints path: topology_spread_constraints x-descriptors: - urn:alm:descriptor:com.tectonic.ui:advanced - urn:alm:descriptor:com.tectonic.ui:hidden + - displayName: Web Topology Spread Constraints + path: web_topology_spread_constraints + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:hidden + - displayName: Task Topology Spread Constraints + path: task_topology_spread_constraints + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:hidden - displayName: Affinity path: affinity x-descriptors: - urn:alm:descriptor:com.tectonic.ui:advanced - urn:alm:descriptor:com.tectonic.ui:hidden + - displayName: Web Affinity + path: web_affinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:hidden + - displayName: Task Affinity + path: task_affinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:hidden - displayName: Control Plane Priority Class path: control_plane_priority_class x-descriptors: @@ -649,6 +689,16 @@ spec: x-descriptors: - urn:alm:descriptor:com.tectonic.ui:advanced - urn:alm:descriptor:com.tectonic.ui:hidden + - displayName: Web Tolerations + path: web_tolerations + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:hidden + - displayName: Task Tolerations + path: task_tolerations + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - urn:alm:descriptor:com.tectonic.ui:hidden - displayName: CSRF Cookie Secure Setting path: csrf_cookie_secure x-descriptors: diff --git a/roles/common/templates/labels/common.yaml.j2 b/roles/common/templates/labels/common.yaml.j2 index 4e133e87..7287ec9d 100644 --- a/roles/common/templates/labels/common.yaml.j2 +++ b/roles/common/templates/labels/common.yaml.j2 @@ -1,5 +1,4 @@ # https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/ -app.kubernetes.io/name: '{{ ansible_operator_meta.name }}' app.kubernetes.io/part-of: '{{ ansible_operator_meta.name }}' app.kubernetes.io/managed-by: '{{ deployment_type }}-operator' app.kubernetes.io/component: '{{ deployment_type }}' diff --git a/roles/installer/defaults/main.yml b/roles/installer/defaults/main.yml index 85676ee9..e97647c5 100644 --- a/roles/installer/defaults/main.yml +++ b/roles/installer/defaults/main.yml @@ -67,11 +67,24 @@ hostname: '' # Add a nodeSelector for the AWX pods. It must match a node's labels for the pod # to be scheduled on that node. Specify as literal block. E.g.: # node_selector: | -# disktype: ssd # kubernetes.io/arch: amd64 # kubernetes.io/os: linux node_selector: '' +# Add a nodeSelector for the AWX pods. It must match a node's labels for the pod +# to be scheduled on that node. Specify as literal block. E.g.: +# node_selector: | +# kubernetes.io/arch: amd64 +# kubernetes.io/os: linux +web_node_selector: '' + +# Add a nodeSelector for the AWX pods. It must match a node's labels for the pod +# to be scheduled on that node. Specify as literal block. E.g.: +# node_selector: | +# kubernetes.io/arch: amd64 +# kubernetes.io/os: linux +task_node_selector: '' + # Add a topologySpreadConstraints for the AWX pods. # Specify as literal block. E.g.: # topology_spread_constraints: | @@ -83,7 +96,27 @@ node_selector: '' # app.kubernetes.io/name: "" topology_spread_constraints: '' -affinity: {} +# Add a topologySpreadConstraints for the task pods. +# Specify as literal block. E.g.: +# task_topology_spread_constraints: | +# - maxSkew: 100 +# topologyKey: "topology.kubernetes.io/zone" +# whenUnsatisfiable: "ScheduleAnyway" +# labelSelector: +# matchLabels: +# app.kubernetes.io/name: "" +task_topology_spread_constraints: '' + +# Add a topologySpreadConstraints for the web pods. +# Specify as literal block. E.g.: +# web_topology_spread_constraints: | +# - maxSkew: 100 +# topologyKey: "topology.kubernetes.io/zone" +# whenUnsatisfiable: "ScheduleAnyway" +# labelSelector: +# matchLabels: +# app.kubernetes.io/name: "" +web_topology_spread_constraints: '' # Add node tolerations for the AWX pods. Specify as literal block. E.g.: # tolerations: | @@ -93,6 +126,58 @@ affinity: {} # effect: "NoSchedule" tolerations: '' +# Add node tolerations for the task pods. Specify as literal block. E.g.: +# task_tolerations: | +# - key: "dedicated" +# operator: "Equal" +# value: "AWXtask" +# effect: "NoSchedule" +task_tolerations: '' + +# Add node tolerations for the web pods. Specify as literal block. E.g.: +# web_tolerations: | +# - key: "dedicated" +# operator: "Equal" +# value: "AWXweb" +# effect: "NoSchedule" +web_tolerations: '' + +# Add affinities for all pods +# affinity: +# nodeAffinity: +# requiredDuringSchedulingIgnoredDuringExecution: +# nodeSelectorTerms: +# - matchExpressions: +# - key: app.kubernetes.io/component +# operator: In +# values: +# - awx +affinity: {} + +# Add affinities for all task pods +# affinity: +# nodeAffinity: +# requiredDuringSchedulingIgnoredDuringExecution: +# nodeSelectorTerms: +# - matchExpressions: +# - key: app.kubernetes.io/name +# operator: In +# values: +# - awx-task +task_affinity: {} + +# Add affinities for all web pods +# affinity: +# nodeAffinity: +# requiredDuringSchedulingIgnoredDuringExecution: +# nodeSelectorTerms: +# - matchExpressions: +# - key: app.kubernetes.io/name +# operator: In +# values: +# - awx-web +web_affinity: {} + # Add annotations to awx pods. Specify as literal block. E.g.: # annotations: | # my.annotation/1: value @@ -173,13 +258,18 @@ _init_projects_container_image: quay.io/centos/centos:stream9 create_preload_data: true replicas: "1" +web_replicas: '' +task_replicas: '' task_args: - /usr/bin/launch_awx_task.sh task_command: [] web_args: - - /usr/bin/launch_awx.sh + - /usr/bin/launch_awx_web.sh web_command: [] +ryslog_args: + - /usr/bin/launch_awx_rsyslog.sh +rsyslog_command: [] task_resource_requirements: requests: @@ -196,6 +286,12 @@ ee_resource_requirements: cpu: 100m memory: 64Mi +# TODO: validate default resource requirements +rsyslog_resource_requirements: + requests: + cpu: 100m + memory: 128Mi + # Customize CSRF options csrf_cookie_secure: False session_cookie_secure: False diff --git a/roles/installer/tasks/initialize_django.yml b/roles/installer/tasks/initialize_django.yml index bc75a06a..158a7757 100644 --- a/roles/installer/tasks/initialize_django.yml +++ b/roles/installer/tasks/initialize_django.yml @@ -2,7 +2,7 @@ - name: Check if there are any super users defined. k8s_exec: namespace: "{{ ansible_operator_meta.namespace }}" - pod: "{{ tower_pod_name }}" + pod: "{{ awx_task_pod_name }}" container: "{{ ansible_operator_meta.name }}-task" command: >- bash -c "echo 'from django.contrib.auth.models import User; @@ -16,7 +16,7 @@ - name: Create super user via Django if it doesn't exist. k8s_exec: namespace: "{{ ansible_operator_meta.namespace }}" - pod: "{{ tower_pod_name }}" + pod: "{{ awx_task_pod_name }}" container: "{{ ansible_operator_meta.name }}-task" command: awx-manage createsuperuser --username={{ admin_user | quote }} --email={{ admin_email | quote }} --noinput register: result @@ -28,7 +28,7 @@ - name: Update Django super user password k8s_exec: namespace: "{{ ansible_operator_meta.namespace }}" - pod: "{{ tower_pod_name }}" + pod: "{{ awx_task_pod_name }}" container: "{{ ansible_operator_meta.name }}-task" command: awx-manage update_password --username='{{ admin_user }}' --password='{{ admin_password }}' register: result @@ -39,7 +39,7 @@ - name: Check if legacy queue is present k8s_exec: namespace: "{{ ansible_operator_meta.namespace }}" - pod: "{{ tower_pod_name }}" + pod: "{{ awx_task_pod_name }}" container: "{{ ansible_operator_meta.name }}-task" command: >- bash -c "awx-manage list_instances | grep '^\[tower capacity=[0-9]*\]'" @@ -50,7 +50,7 @@ - name: Unregister legacy queue k8s_exec: namespace: "{{ ansible_operator_meta.namespace }}" - pod: "{{ tower_pod_name }}" + pod: "{{ awx_task_pod_name }}" container: "{{ ansible_operator_meta.name }}-task" command: >- bash -c "awx-manage unregister_queue --queuename=tower" @@ -74,7 +74,7 @@ - name: Register default execution environments (without authentication) k8s_exec: namespace: "{{ ansible_operator_meta.namespace }}" - pod: "{{ tower_pod_name }}" + pod: "{{ awx_task_pod_name }}" container: "{{ ansible_operator_meta.name }}-task" command: >- bash -c "awx-manage register_default_execution_environments" @@ -95,7 +95,7 @@ - name: Register default execution environments (with authentication) k8s_exec: namespace: "{{ ansible_operator_meta.namespace }}" - pod: "{{ tower_pod_name }}" + pod: "{{ awx_task_pod_name }}" container: "{{ ansible_operator_meta.name }}-task" command: >- bash -c "awx-manage register_default_execution_environments @@ -111,7 +111,7 @@ - name: Create preload data if necessary. # noqa 305 k8s_exec: namespace: "{{ ansible_operator_meta.namespace }}" - pod: "{{ tower_pod_name }}" + pod: "{{ awx_task_pod_name }}" container: "{{ ansible_operator_meta.name }}-task" command: >- bash -c "awx-manage create_preload_data" diff --git a/roles/installer/tasks/install.yml b/roles/installer/tasks/install.yml index faca317e..ecf945d5 100644 --- a/roles/installer/tasks/install.yml +++ b/roles/installer/tasks/install.yml @@ -1,4 +1,12 @@ --- +- name: Delete old deployment for before installing during upgrade + k8s: + kind: Deployment + api_version: v1 + namespace: "{{ ansible_operator_meta.namespace }}" + name: "{{ ansible_operator_meta.name }}" + state: absent + - name: Patching labels to AWX kind k8s: state: present @@ -75,7 +83,7 @@ - name: Check for pending migrations k8s_exec: namespace: "{{ ansible_operator_meta.namespace }}" - pod: "{{ tower_pod_name }}" + pod: "{{ awx_task_pod_name }}" container: "{{ ansible_operator_meta.name }}-task" command: >- bash -c "awx-manage showmigrations | grep -v '[X]' | grep '[ ]' | wc -l" @@ -85,7 +93,7 @@ - name: Migrate the database if the K8s resources were updated. # noqa 305 k8s_exec: namespace: "{{ ansible_operator_meta.namespace }}" - pod: "{{ tower_pod_name }}" + pod: "{{ awx_task_pod_name }}" container: "{{ ansible_operator_meta.name }}-task" command: >- bash -c "awx-manage migrate --noinput" diff --git a/roles/installer/tasks/main.yml b/roles/installer/tasks/main.yml index bbad1e36..234caa3f 100644 --- a/roles/installer/tasks/main.yml +++ b/roles/installer/tasks/main.yml @@ -1,13 +1,36 @@ --- -- name: Check for presence of Deployment +- name: Check for presence of old awx Deployment k8s_info: api_version: apps/v1 kind: Deployment name: "{{ ansible_operator_meta.name }}" namespace: "{{ ansible_operator_meta.namespace }}" - register: tower_deployment + register: awx_deployment -# Just execute deployment steps when auto_upgrade is true or when no deployment exists -- name: Start installation +- name: Check for presence of awx-task Deployment + k8s_info: + api_version: v1 + kind: Deployment + name: "{{ ansible_operator_meta.name }}-task" + namespace: "{{ ansible_operator_meta.namespace }}" + register: awx_task_deployment + +- name: Check for presence of awx-web Deployment + k8s_info: + api_version: v1 + kind: Deployment + name: "{{ ansible_operator_meta.name }}-web" + namespace: "{{ ansible_operator_meta.namespace }}" + register: awx_web_deployment + +- name: Start installation if auto_upgrade is true include_tasks: install.yml - when: (tower_deployment['resources'] | length > 0 and auto_upgrade | bool ) or (tower_deployment['resources'] | length == 0) + when: + - auto_upgrade | bool + +- name: Start installation if auto_upgrade is false and deployment is missing + include_tasks: install.yml + when: + - not (auto_upgrade | bool) + - not (awx_deployment['resources'] | length > 0) + - not (awx_web_deployment['resources'] | length > 0 and awx_task_deployment['resources'] | length > 0) diff --git a/roles/installer/tasks/resources_configuration.yml b/roles/installer/tasks/resources_configuration.yml index f4286443..d385891f 100644 --- a/roles/installer/tasks/resources_configuration.yml +++ b/roles/installer/tasks/resources_configuration.yml @@ -1,29 +1,28 @@ --- - -- name: Get the current resource pod information. +- name: Get the current resource task pod information. k8s_info: api_version: v1 kind: Pod namespace: '{{ ansible_operator_meta.namespace }}' label_selectors: - - "app.kubernetes.io/name={{ ansible_operator_meta.name }}" + - "app.kubernetes.io/name={{ ansible_operator_meta.name }}-task" - "app.kubernetes.io/managed-by={{ deployment_type }}-operator" - "app.kubernetes.io/component={{ deployment_type }}" field_selectors: - status.phase=Running - register: tower_pod + register: awx_task_pod - name: Set the resource pod as a variable. set_fact: - tower_pod: >- - {{ tower_pod['resources'] + awx_task_pod: >- + {{ awx_task_pod['resources'] | rejectattr('metadata.deletionTimestamp', 'defined') | sort(attribute='metadata.creationTimestamp') | first | default({}) }} - name: Set the resource pod name as a variable. set_fact: - tower_pod_name: "{{ tower_pod['metadata']['name'] | default('') }}" + awx_task_pod_name: "{{ awx_task_pod['metadata']['name'] | default('') }}" - name: Set user provided control plane ee image set_fact: @@ -249,9 +248,12 @@ - name: Apply deployment resources k8s: apply: yes - definition: "{{ lookup('template', 'deployments/deployment.yaml.j2') }}" + definition: "{{ lookup('template', 'deployments/{{ item }}.yaml.j2') }}" wait: yes - wait_timeout: "{{ 120 * replicas or 120 }}" + wait_timeout: "{{ (120 * replicas) or 120 }}" + loop: + - task + - web register: this_deployment_result - block: @@ -260,7 +262,7 @@ kind: Pod namespace: '{{ ansible_operator_meta.namespace }}' label_selectors: - - "app.kubernetes.io/name={{ ansible_operator_meta.name }}" + - "app.kubernetes.io/name={{ ansible_operator_meta.name }}-task" - "app.kubernetes.io/managed-by={{ deployment_type }}-operator" - "app.kubernetes.io/component={{ deployment_type }}" field_selectors: @@ -269,7 +271,7 @@ - name: Update new resource pod as a variable. set_fact: - tower_pod: >- + awx_task_pod: >- {{ _new_pod['resources'] | rejectattr('metadata.deletionTimestamp', 'defined') | sort(attribute='metadata.creationTimestamp') @@ -277,11 +279,11 @@ - name: Update new resource pod name as a variable. set_fact: - tower_pod_name: '{{ tower_pod["metadata"]["name"] | default("")}}' + awx_task_pod_name: '{{ awx_task_pod["metadata"]["name"] | default("")}}' when: - this_deployment_result.changed - name: Verify the resource pod name is populated. assert: - that: tower_pod_name != '' + that: awx_task_pod_name != '' fail_msg: "Could not find the tower pod's name." diff --git a/roles/installer/tasks/scale_down_deployment.yml b/roles/installer/tasks/scale_down_deployment.yml index be731fa0..6f0a63ef 100644 --- a/roles/installer/tasks/scale_down_deployment.yml +++ b/roles/installer/tasks/scale_down_deployment.yml @@ -12,8 +12,11 @@ kubernetes.core.k8s_scale: api_version: apps/v1 kind: Deployment - name: "{{ ansible_operator_meta.name }}" + name: "{{ item }}" namespace: "{{ ansible_operator_meta.namespace }}" replicas: 0 wait: yes + loop: + - "{{ ansible_operator_meta.name }}-task" + - "{{ ansible_operator_meta.name }}-web" when: this_deployment['resources'] | length diff --git a/roles/installer/tasks/update_status.yml b/roles/installer/tasks/update_status.yml index f557f1f4..e6641e77 100644 --- a/roles/installer/tasks/update_status.yml +++ b/roles/installer/tasks/update_status.yml @@ -47,7 +47,7 @@ - name: Retrieve instance version k8s_exec: namespace: "{{ ansible_operator_meta.namespace }}" - pod: "{{ tower_pod_name }}" + pod: "{{ awx_task_pod_name }}" container: "{{ ansible_operator_meta.name }}-task" command: >- bash -c "awx-manage --version" diff --git a/roles/installer/templates/deployments/deployment.yaml.j2 b/roles/installer/templates/deployments/task.yaml.j2 similarity index 83% rename from roles/installer/templates/deployments/deployment.yaml.j2 rename to roles/installer/templates/deployments/task.yaml.j2 index fe02e7f1..db3c59a9 100644 --- a/roles/installer/templates/deployments/deployment.yaml.j2 +++ b/roles/installer/templates/deployments/task.yaml.j2 @@ -1,23 +1,27 @@ -# AWX Deployment. --- apiVersion: apps/v1 kind: Deployment metadata: - name: '{{ ansible_operator_meta.name }}' + name: '{{ ansible_operator_meta.name }}-task' namespace: '{{ ansible_operator_meta.namespace }}' labels: {{ lookup("template", "../common/templates/labels/common.yaml.j2") | indent(width=4) | trim }} {{ lookup("template", "../common/templates/labels/version.yaml.j2") | indent(width=4) | trim }} spec: +{% if task_replicas %} + replicas: {{ task_replicas }} +{% elif replicas %} replicas: {{ replicas }} +{% endif %} selector: matchLabels: - app.kubernetes.io/name: '{{ ansible_operator_meta.name }}' + app.kubernetes.io/name: '{{ ansible_operator_meta.name }}-task' app.kubernetes.io/managed-by: '{{ deployment_type }}-operator' app.kubernetes.io/component: '{{ deployment_type }}' template: metadata: labels: + app.kubernetes.io/name: '{{ ansible_operator_meta.name }}-task' {{ lookup("template", "../common/templates/labels/common.yaml.j2") | indent(width=8) | trim }} {{ lookup("template", "../common/templates/labels/version.yaml.j2") | indent(width=8) | trim }} annotations: @@ -158,108 +162,6 @@ spec: /var/lib/pre-stop/scripts/termination-waiter {% endif %} resources: {{ redis_resource_requirements }} - - image: '{{ _image }}' - name: '{{ ansible_operator_meta.name }}-web' -{% if web_command %} - command: {{ web_command }} -{% endif %} -{% if web_args %} - args: {{ web_args }} -{% endif %} - imagePullPolicy: '{{ image_pull_policy }}' - ports: - - containerPort: 8052 -{% if ingress_type | lower == 'route' and route_tls_termination_mechanism | lower == 'passthrough' %} - - containerPort: 8053 -{% endif %} - volumeMounts: -{% if bundle_ca_crt %} - - name: "ca-trust-extracted" - mountPath: "/etc/pki/ca-trust/extracted" - - name: "{{ ansible_operator_meta.name }}-bundle-cacert" - mountPath: /etc/pki/ca-trust/source/anchors/bundle-ca.crt - subPath: bundle-ca.crt - readOnly: true -{% endif %} - - name: "{{ ansible_operator_meta.name }}-application-credentials" - mountPath: "/etc/tower/conf.d/execution_environments.py" - subPath: execution_environments.py - readOnly: true - - name: "{{ ansible_operator_meta.name }}-application-credentials" - mountPath: "/etc/tower/conf.d/credentials.py" - subPath: credentials.py - readOnly: true - - name: "{{ ansible_operator_meta.name }}-application-credentials" - mountPath: "/etc/tower/conf.d/ldap.py" - subPath: ldap.py - readOnly: true -{% if ingress_type | lower == 'route' and route_tls_termination_mechanism | lower == 'passthrough' %} - - name: "{{ ansible_operator_meta.name }}-nginx-certs" - mountPath: "/etc/nginx/pki" - readOnly: true -{% endif %} -{% if ldap_cacert_ca_crt %} - - name: "{{ ansible_operator_meta.name }}-ldap-cacert" - mountPath: /etc/openldap/certs/ldap-ca.crt - subPath: ldap-ca.crt - readOnly: true -{% endif %} - - name: "{{ secret_key_secret_name }}" - mountPath: /etc/tower/SECRET_KEY - subPath: SECRET_KEY - readOnly: true - - name: {{ ansible_operator_meta.name }}-settings - mountPath: /etc/tower/settings.py - subPath: settings.py - readOnly: true - - name: {{ ansible_operator_meta.name }}-nginx-conf - mountPath: /etc/nginx/nginx.conf - subPath: nginx.conf - readOnly: true - - name: {{ ansible_operator_meta.name }}-redis-socket - mountPath: "/var/run/redis" - - name: supervisor-socket - mountPath: "/var/run/supervisor" - - name: rsyslog-socket - mountPath: "/var/run/awx-rsyslog" - - name: rsyslog-dir - mountPath: "/var/lib/awx/rsyslog" - - name: "{{ ansible_operator_meta.name }}-projects" - mountPath: "/var/lib/awx/projects" - - name: "{{ ansible_operator_meta.name }}-receptor-work-signing" - mountPath: "/etc/receptor/signing/work-public-key.pem" - subPath: "work-public-key.pem" - readOnly: true - - name: "{{ ansible_operator_meta.name }}-receptor-ca" - mountPath: "/etc/receptor/tls/ca/receptor-ca.crt" - subPath: "tls.crt" - readOnly: true - - name: "{{ ansible_operator_meta.name }}-receptor-ca" - mountPath: "/etc/receptor/tls/ca/receptor-ca.key" - subPath: "tls.key" - readOnly: true -{% if development_mode | bool %} - - name: awx-devel - mountPath: "/awx_devel" -{% endif %} -{% if web_extra_volume_mounts -%} - {{ web_extra_volume_mounts | indent(width=12, first=True) }} -{% endif %} - env: - - name: MY_POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: UWSGI_MOUNT_PATH - value: "{{ ingress_path }}" -{% if development_mode | bool %} - - name: AWX_KUBE_DEVEL - value: "1" -{% endif %} -{% if web_extra_env -%} - {{ web_extra_env | indent(width=12, first=True) }} -{% endif %} - resources: {{ web_resource_requirements }} - image: '{{ _image }}' name: '{{ ansible_operator_meta.name }}-task' imagePullPolicy: '{{ image_pull_policy }}' @@ -304,12 +206,8 @@ spec: readOnly: true - name: {{ ansible_operator_meta.name }}-redis-socket mountPath: "/var/run/redis" - - name: supervisor-socket - mountPath: "/var/run/supervisor" - name: rsyslog-socket mountPath: "/var/run/awx-rsyslog" - - name: rsyslog-dir - mountPath: "/var/lib/awx/rsyslog" - name: "{{ ansible_operator_meta.name }}-receptor-config" mountPath: "/etc/receptor/" - name: "{{ ansible_operator_meta.name }}-receptor-work-signing" @@ -340,8 +238,10 @@ spec: - /var/lib/pre-stop/scripts/termination-master {% endif %} env: - - name: SUPERVISOR_WEB_CONFIG_PATH - value: "/etc/supervisord.conf" + - name: AWX_COMPONENT + value: "task" + - name: SUPERVISOR_CONFIG_PATH + value: "/etc/supervisord_task.conf" - name: AWX_SKIP_MIGRATIONS value: "1" - name: MY_POD_UID @@ -430,22 +330,71 @@ spec: {% if ee_extra_env -%} {{ ee_extra_env | indent(width=12, first=True) }} {% endif %} -{% if node_selector %} + - image: '{{ _image }}' + name: '{{ ansible_operator_meta.name }}-rsyslog' +{% if rsyslog_command %} + command: {{ rsyslog_command }} +{% endif %} +{% if ryslog_args %} + args: {{ ryslog_args }} +{% endif %} + imagePullPolicy: '{{ image_pull_policy }}' + volumeMounts: + - name: "{{ ansible_operator_meta.name }}-application-credentials" + mountPath: "/etc/tower/conf.d/credentials.py" + subPath: credentials.py + readOnly: true + - name: "{{ secret_key_secret_name }}" + mountPath: /etc/tower/SECRET_KEY + subPath: SECRET_KEY + readOnly: true + - name: {{ ansible_operator_meta.name }}-settings + mountPath: "/etc/tower/settings.py" + subPath: settings.py + readOnly: true + - name: {{ ansible_operator_meta.name }}-redis-socket + mountPath: "/var/run/redis" + - name: rsyslog-socket + mountPath: "/var/run/awx-rsyslog" +{% if development_mode | bool %} + - name: awx-devel + mountPath: "/awx_devel" +{% endif %} + env: + - name: SUPERVISOR_CONFIG_PATH + value: "/etc/supervisor_rsyslog.conf" +{% if development_mode | bool %} + - name: AWX_KUBE_DEVEL + value: "1" +{% endif %} +{% if task_node_selector %} + nodeSelector: + {{ task_node_selector | indent(width=8) }} +{% elif node_selector %} nodeSelector: {{ node_selector | indent(width=8) }} {% endif %} -{% if topology_spread_constraints %} +{% if task_topology_spread_constraints %} + topologySpreadConstraints: + {{ task_topology_spread_constraints | indent(width=8) }} +{% elif topology_spread_constraints %} topologySpreadConstraints: {{ topology_spread_constraints | indent(width=8) }} {% endif %} -{% if affinity | length %} +{% if task_tolerations %} + tolerations: + {{ task_tolerations | to_nice_yaml | indent(width=8) }} +{% elif tolerations %} + tolerations: + {{ tolerations | to_nice_yaml | indent(width=8) }} +{% endif %} +{% if task_affinity %} + affinity: + {{ task_affinity | to_nice_yaml | indent(width=8) }} +{% elif affinity %} affinity: {{ affinity | to_nice_yaml | indent(width=8) }} {% endif %} -{% if tolerations %} - tolerations: - {{ tolerations | indent(width=8) }} -{% endif %} {% if (projects_persistence|bool and is_k8s|bool) or (security_context_settings|length) %} securityContext: {% if projects_persistence|bool and is_k8s|bool %} @@ -541,14 +490,10 @@ spec: emptyDir: {} - name: {{ ansible_operator_meta.name }}-redis-data emptyDir: {} - - name: supervisor-socket - emptyDir: {} - name: rsyslog-socket emptyDir: {} - name: receptor-socket emptyDir: {} - - name: rsyslog-dir - emptyDir: {} - name: {{ ansible_operator_meta.name }}-receptor-config emptyDir: {} - name: {{ ansible_operator_meta.name }}-default-receptor-config diff --git a/roles/installer/templates/deployments/web.yaml.j2 b/roles/installer/templates/deployments/web.yaml.j2 new file mode 100644 index 00000000..b0ee702a --- /dev/null +++ b/roles/installer/templates/deployments/web.yaml.j2 @@ -0,0 +1,372 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: '{{ ansible_operator_meta.name }}-web' + namespace: '{{ ansible_operator_meta.namespace }}' + labels: + app.kubernetes.io/name: '{{ ansible_operator_meta.name }}-web' + {{ lookup("template", "../common/templates/labels/common.yaml.j2") | indent(width=4) | trim }} + {{ lookup("template", "../common/templates/labels//version.yaml.j2") | indent(width=4) | trim }} +spec: +{% if web_replicas %} + replicas: {{ web_replicas }} +{% elif replicas %} + replicas: {{ replicas }} +{% endif %} + selector: + matchLabels: + app.kubernetes.io/name: '{{ ansible_operator_meta.name }}-web' + app.kubernetes.io/managed-by: '{{ deployment_type }}-operator' + app.kubernetes.io/component: '{{ deployment_type }}' + template: + metadata: + labels: + app.kubernetes.io/name: '{{ ansible_operator_meta.name }}-web' + {{ lookup("template", "../common/templates/labels/common.yaml.j2") | indent(width=8) | trim }} + {{ lookup("template", "../common/templates/labels//version.yaml.j2") | indent(width=8) | trim }} + annotations: +{% for template in [ + "configmaps/config", + "configmaps/pre_stop_scripts", + "secrets/app_credentials", + "storage/persistent", + ] %} + checksum-{{ template | replace('/', '-') }}: "{{ lookup('template', template + '.yaml.j2') | md5 }}" +{% endfor %} +{% for secret in [ + "bundle_cacert", + "route_tls", + "ldap_cacert", + "secret_key", + "receptor_ca", + "receptor_work_signing", + ] %} + checksum-secret-{{ secret }}: "{{ lookup('ansible.builtin.vars', secret, default='')["resources"][0]["data"] | default('') | md5 }}" +{% endfor %} +{% if annotations %} + {{ annotations | indent(width=8) }} +{% endif %} + spec: + serviceAccountName: '{{ ansible_operator_meta.name }}' +{% if image_pull_secret is defined %} + imagePullSecrets: + - name: {{ image_pull_secret }} +{% elif image_pull_secrets | length > 0 %} + imagePullSecrets: +{% for secret in image_pull_secrets %} + - name: {{ secret }} +{% endfor %} +{% endif %} +{% if control_plane_priority_class is defined %} + priorityClassName: '{{ control_plane_priority_class }}' +{% endif %} + initContainers: +{% if bundle_ca_crt or init_container_extra_commands %} + - name: init + image: '{{ _init_container_image }}' + imagePullPolicy: '{{ image_pull_policy }}' + command: + - /bin/sh + - -c + - | +{% if bundle_ca_crt %} + mkdir -p /etc/pki/ca-trust/extracted/{java,pem,openssl,edk2} + update-ca-trust +{% endif %} +{% if init_container_extra_commands %} + {{ init_container_extra_commands | indent(width=14) }} +{% endif %} + volumeMounts: +{% if bundle_ca_crt %} + - name: "ca-trust-extracted" + mountPath: "/etc/pki/ca-trust/extracted" + - name: "{{ ansible_operator_meta.name }}-bundle-cacert" + mountPath: /etc/pki/ca-trust/source/anchors/bundle-ca.crt + subPath: bundle-ca.crt + readOnly: true +{% endif %} +{% if init_container_extra_volume_mounts -%} + {{ init_container_extra_volume_mounts | indent(width=12, first=True) }} +{% endif %} +{% endif %} + containers: + - image: '{{ _redis_image }}' + imagePullPolicy: '{{ image_pull_policy }}' + name: redis +{% if redis_capabilities is defined and redis_capabilities %} + securityContext: + capabilities: + add: {{ redis_capabilities }} +{% endif %} + args: ["redis-server", "/etc/redis.conf"] + volumeMounts: + - name: {{ ansible_operator_meta.name }}-redis-config + mountPath: "/etc/redis.conf" + subPath: redis.conf + readOnly: true + - name: {{ ansible_operator_meta.name }}-redis-socket + mountPath: "/var/run/redis" + - name: "{{ ansible_operator_meta.name }}-redis-data" + mountPath: "/data" + resources: {{ redis_resource_requirements }} + - image: '{{ _image }}' + name: '{{ ansible_operator_meta.name }}-web' + imagePullPolicy: '{{ image_pull_policy }}' +{% if web_command %} + command: {{ web_command }} +{% endif %} +{% if web_args %} + args: {{ web_args }} +{% endif %} + ports: + - containerPort: 8052 +{% if ingress_type | lower == 'route' and route_tls_termination_mechanism | lower == 'passthrough' %} + - containerPort: 8053 +{% endif %} + volumeMounts: +{% if bundle_ca_crt %} + - name: "ca-trust-extracted" + mountPath: "/etc/pki/ca-trust/extracted" + - name: "{{ ansible_operator_meta.name }}-bundle-cacert" + mountPath: /etc/pki/ca-trust/source/anchors/bundle-ca.crt + subPath: bundle-ca.crt + readOnly: true +{% endif %} + - name: "{{ ansible_operator_meta.name }}-application-credentials" + mountPath: "/etc/tower/conf.d/execution_environments.py" + subPath: execution_environments.py + readOnly: true + - name: "{{ ansible_operator_meta.name }}-application-credentials" + mountPath: "/etc/tower/conf.d/credentials.py" + subPath: credentials.py + readOnly: true + - name: "{{ ansible_operator_meta.name }}-application-credentials" + mountPath: "/etc/tower/conf.d/ldap.py" + subPath: ldap.py + readOnly: true +{% if ingress_type | lower == 'route' and route_tls_termination_mechanism | lower == 'passthrough' %} + - name: "{{ ansible_operator_meta.name }}-nginx-certs" + mountPath: "/etc/nginx/pki" + readOnly: true +{% endif %} +{% if ldap_cacert_ca_crt %} + - name: "{{ ansible_operator_meta.name }}-ldap-cacert" + mountPath: /etc/openldap/certs/ldap-ca.crt + subPath: ldap-ca.crt + readOnly: true +{% endif %} + - name: "{{ secret_key_secret_name }}" + mountPath: /etc/tower/SECRET_KEY + subPath: SECRET_KEY + readOnly: true + - name: {{ ansible_operator_meta.name }}-settings + mountPath: /etc/tower/settings.py + subPath: settings.py + readOnly: true + - name: {{ ansible_operator_meta.name }}-nginx-conf + mountPath: /etc/nginx/nginx.conf + subPath: nginx.conf + readOnly: true + - name: {{ ansible_operator_meta.name }}-redis-socket + mountPath: "/var/run/redis" + - name: rsyslog-socket + mountPath: "/var/run/awx-rsyslog" + - name: "{{ ansible_operator_meta.name }}-receptor-ca" + mountPath: "/etc/receptor/tls/ca/receptor-ca.crt" + subPath: "tls.crt" + readOnly: true + - name: "{{ ansible_operator_meta.name }}-receptor-ca" + mountPath: "/etc/receptor/tls/ca/receptor-ca.key" + subPath: "tls.key" + readOnly: true + - name: "{{ ansible_operator_meta.name }}-receptor-work-signing" + mountPath: "/etc/receptor/signing/work-public-key.pem" + subPath: "work-public-key.pem" + readOnly: true +{% if development_mode | bool %} + - name: awx-devel + mountPath: "/awx_devel" +{% endif %} +{% if web_extra_volume_mounts -%} + {{ web_extra_volume_mounts | indent(width=12, first=True) }} +{% endif %} + env: + - name: AWX_COMPONENT + value: "web" + - name: SUPERVISOR_CONFIG_PATH + value: "/etc/supervisor_web.conf" + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: MY_POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: UWSGI_MOUNT_PATH + value: "{{ ingress_path }}" +{% if development_mode | bool %} + - name: AWX_KUBE_DEVEL + value: "1" +{% endif %} +{% if web_extra_env -%} + {{ web_extra_env | indent(width=12, first=True) }} +{% endif %} + resources: {{ web_resource_requirements }} + - image: '{{ _image }}' + name: '{{ ansible_operator_meta.name }}-rsyslog' +{% if rsyslog_command %} + command: {{ rsyslog_command }} +{% endif %} +{% if ryslog_args %} + args: {{ ryslog_args }} +{% endif %} + imagePullPolicy: '{{ image_pull_policy }}' + volumeMounts: + - name: "{{ ansible_operator_meta.name }}-application-credentials" + mountPath: "/etc/tower/conf.d/credentials.py" + subPath: credentials.py + readOnly: true + - name: "{{ secret_key_secret_name }}" + mountPath: /etc/tower/SECRET_KEY + subPath: SECRET_KEY + readOnly: true + - name: {{ ansible_operator_meta.name }}-settings + mountPath: "/etc/tower/settings.py" + subPath: settings.py + readOnly: true + - name: {{ ansible_operator_meta.name }}-redis-socket + mountPath: "/var/run/redis" + - name: rsyslog-socket + mountPath: "/var/run/awx-rsyslog" +{% if development_mode | bool %} + - name: awx-devel + mountPath: "/awx_devel" +{% endif %} + env: + - name: SUPERVISOR_CONFIG_PATH + value: "/etc/supervisor_rsyslog.conf" +{% if development_mode | bool %} + - name: AWX_KUBE_DEVEL + value: "1" +{% endif %} +{% if web_node_selector %} + nodeSelector: + {{ web_node_selector | indent(width=8) }} +{% elif node_selector %} + nodeSelector: + {{ node_selector | indent(width=8) }} +{% endif %} +{% if web_topology_spread_constraints %} + topologySpreadConstraints: + {{ web_topology_spread_constraints | indent(width=8) }} +{% elif topology_spread_constraints %} + topologySpreadConstraints: + {{ topology_spread_constraints | indent(width=8) }} +{% endif %} +{% if web_tolerations %} + tolerations: + {{ web_tolerations| indent(width=8) }} +{% elif tolerations %} + tolerations: + {{ tolerations| indent(width=8) }} +{% endif %} +{% if web_affinity %} + affinity: + {{ web_affinity | to_nice_yaml | indent(width=8) }} +{% elif affinity %} + affinity: + {{ affinity | to_nice_yaml | indent(width=8) }} +{% endif %} + volumes: + - name: "{{ ansible_operator_meta.name }}-receptor-ca" + secret: + secretName: "{{ ansible_operator_meta.name }}-receptor-ca" + - name: "{{ ansible_operator_meta.name }}-receptor-work-signing" + secret: + secretName: "{{ ansible_operator_meta.name }}-receptor-work-signing" +{% if bundle_ca_crt %} + - name: "ca-trust-extracted" + emptyDir: {} + - name: "{{ ansible_operator_meta.name }}-bundle-cacert" + secret: + secretName: "{{ bundle_cacert_secret }}" + items: + - key: bundle-ca.crt + path: 'bundle-ca.crt' +{% endif %} +{% if ingress_type | lower == 'route' and route_tls_termination_mechanism | lower == 'passthrough' %} + - name: "{{ ansible_operator_meta.name }}-nginx-certs" + secret: + secretName: "{{ route_tls_secret }}" + items: + - key: tls.key + path: 'web.key' + - key: tls.crt + path: 'web.crt' +{% endif %} +{% if ldap_cacert_ca_crt %} + - name: "{{ ansible_operator_meta.name }}-ldap-cacert" + secret: + secretName: "{{ ldap_cacert_secret }}" + items: + - key: ldap-ca.crt + path: 'ldap-ca.crt' +{% endif %} + - name: "{{ ansible_operator_meta.name }}-application-credentials" + secret: + secretName: "{{ ansible_operator_meta.name }}-app-credentials" + items: + - key: credentials.py + path: 'credentials.py' + - key: ldap.py + path: 'ldap.py' + - key: execution_environments.py + path: 'execution_environments.py' + - name: "{{ secret_key_secret_name }}" + secret: + secretName: '{{ secret_key_secret_name }}' + items: + - key: secret_key + path: SECRET_KEY + - name: {{ ansible_operator_meta.name }}-settings + configMap: + name: '{{ ansible_operator_meta.name }}-{{ deployment_type }}-configmap' + items: + - key: settings + path: settings.py + - name: {{ ansible_operator_meta.name }}-nginx-conf + configMap: + name: '{{ ansible_operator_meta.name }}-{{ deployment_type }}-configmap' + items: + - key: nginx_conf + path: nginx.conf + - name: {{ ansible_operator_meta.name }}-redis-config + configMap: + name: {{ ansible_operator_meta.name }}-{{ deployment_type }}-configmap + items: + - key: redis_conf + path: redis.conf + - name: {{ ansible_operator_meta.name }}-redis-socket + emptyDir: {} + - name: {{ ansible_operator_meta.name }}-redis-data + emptyDir: {} + - name: rsyslog-socket + emptyDir: {} + - name: receptor-socket + emptyDir: {} + - name: {{ ansible_operator_meta.name }}-receptor-config + configMap: + name: '{{ ansible_operator_meta.name }}-{{ deployment_type }}-configmap' + items: + - key: receptor_conf + path: receptor.conf +{% if development_mode | bool %} + - name: awx-devel + hostPath: + path: /awx_devel +{% endif %} +{% if extra_volumes -%} + {{ extra_volumes | indent(width=8, first=True) }} +{% endif %} diff --git a/roles/installer/templates/networking/service.yaml.j2 b/roles/installer/templates/networking/service.yaml.j2 index a006d01e..d178a029 100644 --- a/roles/installer/templates/networking/service.yaml.j2 +++ b/roles/installer/templates/networking/service.yaml.j2 @@ -13,7 +13,6 @@ metadata: {% endif %} spec: ports: - {% if service_type | lower == "nodeport" %} - port: 80 protocol: TCP @@ -46,7 +45,7 @@ spec: name: http {% endif %} selector: - app.kubernetes.io/name: '{{ ansible_operator_meta.name }}' + app.kubernetes.io/name: '{{ ansible_operator_meta.name }}-web' app.kubernetes.io/managed-by: '{{ deployment_type }}-operator' app.kubernetes.io/component: '{{ deployment_type }}' {% if service_type | lower == "nodeport" %} diff --git a/roles/restore/tasks/postgres.yml b/roles/restore/tasks/postgres.yml index 417513b4..8c10c1b7 100644 --- a/roles/restore/tasks/postgres.yml +++ b/roles/restore/tasks/postgres.yml @@ -50,7 +50,7 @@ k8s_info: api_version: apps/v1 kind: Deployment - name: "{{ deployment_name }}" + name: "{{ ansible_operator_meta.namespace }}-task" namespace: "{{ ansible_operator_meta.namespace }}" register: this_deployment @@ -58,10 +58,13 @@ k8s_scale: api_version: apps/v1 kind: Deployment - name: "{{ deployment_name }}" + name: "{{ item }}" namespace: "{{ ansible_operator_meta.namespace }}" replicas: 0 wait: yes + loop: + - "{{ ansible_operator_meta.name }}-task" + - "{{ ansible_operator_meta.name }}-web" when: this_deployment['resources'] | length - name: Set full resolvable host name for postgres pod