Compare commits

..

1 Commits

Author SHA1 Message Date
Christian Adams
d53c93c864 Document the need for quotes on pg secret port value 2023-03-15 13:35:49 -04:00
23 changed files with 263 additions and 1642 deletions

View File

@@ -39,5 +39,5 @@ jobs:
-e operator_image=quay.io/${{ github.repository }} \
-e chart_owner=${{ github.repository_owner }} \
-e tag=${{ github.event.release.tag_name }} \
-e gh_token=${{ secrets.GITHUB_TOKEN }} \
-e gh_token=${{ secrets.GITHUB_TOKEN }}
-e gh_user=${{ github.actor }}

View File

@@ -403,14 +403,12 @@ The following variables are customizable only when `service_type=LoadBalancer`
| --------------------- | ---------------------------------------- | ------- |
| loadbalancer_protocol | Protocol to use for Loadbalancer ingress | http |
| loadbalancer_port | Port used for Loadbalancer ingress | 80 |
| loadbalancer_ip | Assign Loadbalancer IP | '' |
```yaml
---
spec:
...
service_type: LoadBalancer
loadbalancer_ip: '192.168.10.25'
loadbalancer_protocol: https
loadbalancer_port: 443
service_annotations: |
@@ -716,14 +714,7 @@ 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
@@ -732,28 +723,18 @@ 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 | '' |
| 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 | '' |
| 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 | '' |
Example of customization could be:
@@ -777,11 +758,6 @@ 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
@@ -894,7 +870,7 @@ A sample of extra settings can be found as below. All possible options can be fo
value: 'LDAPSearch("OU=Groups,DC=abc,DC=com",ldap.SCOPE_SUBTREE,"(objectClass=group)",)'
- setting: AUTH_LDAP_GROUP_TYPE
value: 'GroupOfNamesType'
value: 'GroupOfNamesType(name_attr="cn")'
- setting: AUTH_LDAP_USER_ATTR_MAP
value: '{"first_name": "givenName","last_name": "sn","email": "mail"}'

View File

@@ -14,78 +14,49 @@
Release must exist before running this playbook
when: release is not success
- name: Set helm filename and commit message
set_fact:
asset_already_attached: False
helm_file_name: "awx-operator-{{ tag }}.tgz"
commit_message: "Updated index.yaml for release {{ release.json.tag_name }}"
- name: Build and package helm chart
command: |
make helm-package
environment:
VERSION: "{{ tag }}"
IMAGE_TAG_BASE: "{{ operator_image }}"
args:
chdir: "{{ playbook_dir }}/../"
- name: See if file is already attached
set_fact:
asset_already_attached: True
loop: "{{ release.json.get('assets', []) }}"
loop_control:
label: "{{ item.name }}"
when: item.name == helm_file_name
# Move to chart releaser after https://github.com/helm/chart-releaser/issues/122 exists
- name: Upload helm chart
uri:
url: "https://uploads.github.com/repos/{{ chart_owner }}/{{ chart_repo }}/releases/{{ release.json.id }}/assets?name=awx-operator-{{ tag }}.tgz"
src: "{{ playbook_dir }}/../.cr-release-packages/awx-operator-{{ tag }}.tgz"
headers:
Authorization: "token {{ gh_token }}"
Content-Type: "application/octet-stream"
status_code:
- 200
- 201
register: asset_upload
changed_when: asset_upload.json.state == "uploaded"
- when: not asset_already_attached
block:
- name: Build and package helm chart
command: |
make helm-package
environment:
VERSION: "{{ tag }}"
IMAGE_TAG_BASE: "{{ operator_image }}"
args:
chdir: "{{ playbook_dir }}/../"
# Move to chart releaser after https://github.com/helm/chart-releaser/issues/122 exists
- name: Upload helm chart
uri:
url: "https://uploads.github.com/repos/{{ chart_owner }}/{{ chart_repo }}/releases/{{ release.json.id }}/assets?name={{ helm_file_name }}"
src: "{{ playbook_dir }}/../.cr-release-packages/awx-operator-{{ tag }}.tgz"
headers:
Authorization: "token {{ gh_token }}"
Content-Type: "application/octet-stream"
status_code:
- 200
- 201
register: asset_upload
changed_when: asset_upload.json.state == "uploaded"
- name: Ensure gh-pages exists
file:
state: directory
path: "{{ playbook_dir }}/../gh-pages"
- name: Check if we have published the release
command:
cmd: "git log --grep='{{ commit_message }}'"
- name: Configure git config
shell: |
git config user.name {{ gh_user }}
git config user.email {{ gh_user }}@users.noreply.github.com
args:
chdir: "{{ playbook_dir }}/../gh-pages"
register: commits_for_release
- when: commits_for_release.stdout == ''
block:
- name: Configure git config
shell: |
git config user.name {{ gh_user }}
git config user.email {{ gh_user }}@users.noreply.github.com
args:
chdir: "{{ playbook_dir }}/../gh-pages"
- name: Publish helm index
command: |
make helm-index
environment:
CHART_OWNER: "{{ chart_owner }}"
CR_TOKEN: "{{ gh_token }}"
args:
chdir: "{{ playbook_dir }}/../"
- name: Publish helm index
command: |
make helm-index
environment:
CHART_OWNER: "{{ chart_owner }}"
CR_TOKEN: "{{ gh_token }}"
args:
chdir: "{{ playbook_dir }}/../"
- name: Stage and Push commit to gh-pages branch
shell: |
git add index.yaml
git commit -m "{{ commit_message }}"
git push
args:
chdir: "{{ playbook_dir }}/../gh-pages"
- name: Stage and Push commit to gh-pages branch
shell: |
git add index.yaml
git commit -m "Updated index.yaml latest release"
git push
args:
chdir: "{{ playbook_dir }}/../gh-pages"

View File

@@ -39,14 +39,12 @@ spec:
spec:
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- deployment_name
properties:
backup_source:
description: Backup source
type: string
enum:
- Backup CR
- CR
- PVC
deployment_name:
description: Name of the restored deployment. This should be different from the original deployment name

View File

@@ -132,10 +132,6 @@ spec:
description: Port to use for the loadbalancer
type: integer
default: 80
loadbalancer_ip:
description: Assign LoadBalancer IP address
type: string
default: ''
route_host:
description: The DNS to use to points to the instance
type: string
@@ -160,40 +156,9 @@ 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:
@@ -560,738 +525,19 @@ spec:
type: array
type: object
type: object
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
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
image:
description: Registry path to the application container to use
type: string
@@ -1454,14 +700,6 @@ 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

View File

@@ -270,12 +270,6 @@ spec:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:number
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:service_type:LoadBalancer
- displayName: LoadBalancer IP
path: loadbalancer_ip
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- urn:alm:descriptor:com.tectonic.ui:string
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:service_type:LoadBalancer
- displayName: Route API Version
path: route_api_version
x-descriptors:
@@ -360,16 +354,6 @@ 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:
@@ -618,46 +602,16 @@ 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:
@@ -689,16 +643,6 @@ 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:

View File

@@ -1,67 +1,4 @@
# Debugging the AWX Operator
## General Debugging
When the operator is deploying AWX, it is running the `installer` role inside the operator container. If the AWX CR's status is `Failed`, it is often useful to look at the awx-operator container logs, which shows the output of the installer role. To see these logs, run:
```
kubectl logs deployments/awx-operator-controller-manager -c awx-manager -f
```
### Inspect k8s Resources
Past that, it is often useful to inspect various resources the AWX Operator manages like:
* awx
* awxbackup
* awxrestore
* pod
* deployment
* pvc
* service
* ingress
* route
* secrets
* serviceaccount
And if installing via OperatorHub and OLM:
* subscription
* csv
* installPlan
* catalogSource
To inspect these resources you can use these commands
```
# Inspecting k8s resources
kubectl describe -n <namespace> <resource> <resource-name>
kubectl get -n <namespace> <resource> <resource-name> -o yaml
kubectl logs -n <namespace> <resource> <resource-name>
# Inspecting Pods
kubectl exec -it -n <namespace> <pod> <pod-name>
```
### Configure No Log
It is possible to show task output for debugging by setting no_log to false on the AWX CR spec.
This will show output in the awx-operator logs for any failed tasks where no_log was set to true.
For example:
```
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: awx-demo
spec:
service_type: nodeport
no_log: false # <------------
```
## Iterating on the installer without deploying the operator
# Iterating on the installer without deploying the operator
Go through the [normal basic install](https://github.com/ansible/awx-operator/blob/devel/README.md#basic-install) steps.

View File

@@ -24,7 +24,7 @@
namespace: '{{ namespace }}'
kind: Pod
label_selectors:
- app.kubernetes.io/name = example-awx-web
- app.kubernetes.io/name = example-awx
register: awx_pod
when: not awx_version
@@ -85,7 +85,7 @@
msg: '{{ failed_task }}'
- block:
- name: Look up details for this AWX instance
- name: Look up details for this deployment
k8s_info:
namespace: "{{ namespace }}"
api_version: "awx.ansible.com/v1beta1"
@@ -98,7 +98,7 @@
namespace: '{{ namespace }}'
kind: Pod
label_selectors:
- app.kubernetes.io/name = example-awx-web
- app.kubernetes.io/name = example-awx
register: awx_pod
- name: Extract additional_labels from AWX spec

View File

@@ -1,4 +1,5 @@
# 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 }}'

View File

@@ -67,24 +67,11 @@ 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: |
@@ -96,27 +83,7 @@ task_node_selector: ''
# app.kubernetes.io/name: "<resourcename>"
topology_spread_constraints: ''
# 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: "<resourcename>"
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: "<resourcename>"
web_topology_spread_constraints: ''
affinity: {}
# Add node tolerations for the AWX pods. Specify as literal block. E.g.:
# tolerations: |
@@ -126,58 +93,6 @@ web_topology_spread_constraints: ''
# 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
@@ -258,18 +173,13 @@ _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_web.sh
- /usr/bin/launch_awx.sh
web_command: []
ryslog_args:
- /usr/bin/launch_awx_rsyslog.sh
rsyslog_command: []
task_resource_requirements:
requests:
@@ -286,12 +196,6 @@ 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

View File

@@ -2,7 +2,7 @@
- name: Check if there are any super users defined.
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_task_pod_name }}"
pod: "{{ tower_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: "{{ awx_task_pod_name }}"
pod: "{{ tower_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: "{{ awx_task_pod_name }}"
pod: "{{ tower_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: "{{ awx_task_pod_name }}"
pod: "{{ tower_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: "{{ awx_task_pod_name }}"
pod: "{{ tower_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: "{{ awx_task_pod_name }}"
pod: "{{ tower_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: "{{ awx_task_pod_name }}"
pod: "{{ tower_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: "{{ awx_task_pod_name }}"
pod: "{{ tower_pod_name }}"
container: "{{ ansible_operator_meta.name }}-task"
command: >-
bash -c "awx-manage create_preload_data"

View File

@@ -1,12 +1,4 @@
---
- 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
@@ -83,7 +75,7 @@
- name: Check for pending migrations
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_task_pod_name }}"
pod: "{{ tower_pod_name }}"
container: "{{ ansible_operator_meta.name }}-task"
command: >-
bash -c "awx-manage showmigrations | grep -v '[X]' | grep '[ ]' | wc -l"
@@ -93,7 +85,7 @@
- name: Migrate the database if the K8s resources were updated. # noqa 305
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_task_pod_name }}"
pod: "{{ tower_pod_name }}"
container: "{{ ansible_operator_meta.name }}-task"
command: >-
bash -c "awx-manage migrate --noinput"

View File

@@ -1,36 +1,13 @@
---
- name: Check for presence of old awx Deployment
- name: Check for presence of Deployment
k8s_info:
api_version: apps/v1
api_version: v1
kind: Deployment
name: "{{ ansible_operator_meta.name }}"
namespace: "{{ ansible_operator_meta.namespace }}"
register: awx_deployment
register: tower_deployment
- 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
# Just execute deployment steps when auto_upgrade is true or when no deployment exists
- name: Start installation
include_tasks: install.yml
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)
when: (tower_deployment['resources'] | length > 0 and auto_upgrade | bool ) or (tower_deployment['resources'] | length == 0)

View File

@@ -1,28 +1,29 @@
---
- name: Get the current resource task pod information.
- name: Get the current resource pod information.
k8s_info:
api_version: v1
kind: Pod
namespace: '{{ ansible_operator_meta.namespace }}'
label_selectors:
- "app.kubernetes.io/name={{ ansible_operator_meta.name }}-task"
- "app.kubernetes.io/name={{ ansible_operator_meta.name }}"
- "app.kubernetes.io/managed-by={{ deployment_type }}-operator"
- "app.kubernetes.io/component={{ deployment_type }}"
field_selectors:
- status.phase=Running
register: awx_task_pod
register: tower_pod
- name: Set the resource pod as a variable.
set_fact:
awx_task_pod: >-
{{ awx_task_pod['resources']
tower_pod: >-
{{ tower_pod['resources']
| rejectattr('metadata.deletionTimestamp', 'defined')
| sort(attribute='metadata.creationTimestamp')
| first | default({}) }}
- name: Set the resource pod name as a variable.
set_fact:
awx_task_pod_name: "{{ awx_task_pod['metadata']['name'] | default('') }}"
tower_pod_name: "{{ tower_pod['metadata']['name'] | default('') }}"
- name: Set user provided control plane ee image
set_fact:
@@ -248,12 +249,9 @@
- name: Apply deployment resources
k8s:
apply: yes
definition: "{{ lookup('template', 'deployments/{{ item }}.yaml.j2') }}"
definition: "{{ lookup('template', 'deployments/deployment.yaml.j2') }}"
wait: yes
wait_timeout: "{{ (120 * replicas) or 120 }}"
loop:
- task
- web
wait_timeout: "{{ 120 * replicas or 120 }}"
register: this_deployment_result
- block:
@@ -262,7 +260,7 @@
kind: Pod
namespace: '{{ ansible_operator_meta.namespace }}'
label_selectors:
- "app.kubernetes.io/name={{ ansible_operator_meta.name }}-task"
- "app.kubernetes.io/name={{ ansible_operator_meta.name }}"
- "app.kubernetes.io/managed-by={{ deployment_type }}-operator"
- "app.kubernetes.io/component={{ deployment_type }}"
field_selectors:
@@ -271,7 +269,7 @@
- name: Update new resource pod as a variable.
set_fact:
awx_task_pod: >-
tower_pod: >-
{{ _new_pod['resources']
| rejectattr('metadata.deletionTimestamp', 'defined')
| sort(attribute='metadata.creationTimestamp')
@@ -279,11 +277,11 @@
- name: Update new resource pod name as a variable.
set_fact:
awx_task_pod_name: '{{ awx_task_pod["metadata"]["name"] | default("")}}'
tower_pod_name: '{{ tower_pod["metadata"]["name"] | default("")}}'
when:
- this_deployment_result.changed
- name: Verify the resource pod name is populated.
assert:
that: awx_task_pod_name != ''
that: tower_pod_name != ''
fail_msg: "Could not find the tower pod's name."

View File

@@ -2,7 +2,7 @@
- name: Check for presence of Deployment
k8s_info:
api_version: apps/v1
api_version: v1
kind: Deployment
name: "{{ ansible_operator_meta.name }}"
namespace: "{{ ansible_operator_meta.namespace }}"
@@ -10,13 +10,10 @@
- name: Scale down Deployment for migration
kubernetes.core.k8s_scale:
api_version: apps/v1
api_version: v1
kind: Deployment
name: "{{ item }}"
name: "{{ ansible_operator_meta.name }}"
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

View File

@@ -47,7 +47,7 @@
- name: Retrieve instance version
k8s_exec:
namespace: "{{ ansible_operator_meta.namespace }}"
pod: "{{ awx_task_pod_name }}"
pod: "{{ tower_pod_name }}"
container: "{{ ansible_operator_meta.name }}-task"
command: >-
bash -c "awx-manage --version"

View File

@@ -100,7 +100,6 @@ data:
include /etc/nginx/mime.types;
default_type application/octet-stream;
server_tokens off;
client_max_body_size 5M;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
@@ -269,7 +268,6 @@ data:
key: /etc/receptor/tls/receptor.key
name: tlsclient
rootcas: /etc/receptor/tls/ca/receptor-ca.crt
mintls13: false
- work-signing:
privatekey: /etc/receptor/signing/work-private-key.pem
tokenexpiration: 1m

View File

@@ -1,27 +1,23 @@
# AWX Deployment.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: '{{ ansible_operator_meta.name }}-task'
name: '{{ ansible_operator_meta.name }}'
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 }}-task'
app.kubernetes.io/name: '{{ ansible_operator_meta.name }}'
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:
@@ -162,6 +158,108 @@ 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 }}'
@@ -206,8 +304,12 @@ 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"
@@ -238,10 +340,8 @@ spec:
- /var/lib/pre-stop/scripts/termination-master
{% endif %}
env:
- name: AWX_COMPONENT
value: "task"
- name: SUPERVISOR_CONFIG_PATH
value: "/etc/supervisord_task.conf"
- name: SUPERVISOR_WEB_CONFIG_PATH
value: "/etc/supervisord.conf"
- name: AWX_SKIP_MIGRATIONS
value: "1"
- name: MY_POD_UID
@@ -330,71 +430,22 @@ spec:
{% if ee_extra_env -%}
{{ ee_extra_env | indent(width=12, first=True) }}
{% endif %}
- 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 %}
{% if node_selector %}
nodeSelector:
{{ node_selector | indent(width=8) }}
{% endif %}
{% if task_topology_spread_constraints %}
topologySpreadConstraints:
{{ task_topology_spread_constraints | indent(width=8) }}
{% elif topology_spread_constraints %}
{% if topology_spread_constraints %}
topologySpreadConstraints:
{{ topology_spread_constraints | indent(width=8) }}
{% endif %}
{% 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 %}
{% if affinity | length %}
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 %}
@@ -490,10 +541,14 @@ 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

View File

@@ -1,372 +0,0 @@
---
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 %}

View File

@@ -13,6 +13,7 @@ metadata:
{% endif %}
spec:
ports:
{% if service_type | lower == "nodeport" %}
- port: 80
protocol: TCP
@@ -45,16 +46,13 @@ spec:
name: http
{% endif %}
selector:
app.kubernetes.io/name: '{{ ansible_operator_meta.name }}-web'
app.kubernetes.io/name: '{{ ansible_operator_meta.name }}'
app.kubernetes.io/managed-by: '{{ deployment_type }}-operator'
app.kubernetes.io/component: '{{ deployment_type }}'
{% if service_type | lower == "nodeport" %}
type: NodePort
{% elif service_type | lower == "loadbalancer" %}
type: LoadBalancer
{% if variable is defined and variable|length %}
loadbalancerip: '{{ loadbalancer_ip }}'
{% endif %}
{% else %}
type: ClusterIP
{% endif %}

View File

@@ -2,19 +2,24 @@
- name: Import awx_object variables
block:
- name: Get AWX object definition from pvc
k8s_exec:
namespace: "{{ backup_pvc_namespace }}"
pod: "{{ ansible_operator_meta.name }}-db-management"
command: >-
bash -c "cat '{{ backup_dir }}/awx_object'"
register: awx_object
- name: Create temp file for spec dict
tempfile:
state: file
register: tmp_spec
- name: Get AWX object definition from pvc
k8s_cp:
namespace: "{{ backup_pvc_namespace }}"
pod: "{{ ansible_operator_meta.name }}-db-management"
remote_path: "{{ backup_dir }}/awx_object"
local_path: "{{ tmp_spec.path }}"
state: from_pod
- name: Write spec vars to temp file
copy:
content: "{{ awx_object.stdout }}"
dest: "{{ tmp_spec.path }}"
mode: '0644'
- name: Include spec vars to save them as a dict
include_vars: "{{ tmp_spec.path }}"

View File

@@ -48,23 +48,20 @@
- name: Check for presence of AWX Deployment
k8s_info:
api_version: apps/v1
api_version: v1
kind: Deployment
name: "{{ ansible_operator_meta.namespace }}-task"
name: "{{ deployment_name }}"
namespace: "{{ ansible_operator_meta.namespace }}"
register: this_deployment
- name: Scale down Deployment for migration
k8s_scale:
api_version: apps/v1
api_version: v1
kind: Deployment
name: "{{ item }}"
name: "{{ deployment_name }}"
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

View File

@@ -1,18 +1,25 @@
---
- name: Get secret definition from pvc
k8s_exec:
namespace: "{{ backup_pvc_namespace }}"
pod: "{{ ansible_operator_meta.name }}-db-management"
command: >-
bash -c "cat '{{ backup_dir }}/secrets.yml'"
register: _secrets
no_log: "{{ no_log }}"
- name: Create Temporary secrets file
tempfile:
state: file
suffix: .json
register: tmp_secrets
- name: Get secret definition from pvc
k8s_cp:
namespace: "{{ backup_pvc_namespace }}"
pod: "{{ ansible_operator_meta.name }}-db-management"
remote_path: "{{ backup_dir }}/secrets.yml"
local_path: "{{ tmp_secrets.path }}"
state: from_pod
- name: Write vars to file locally
copy:
dest: "{{ tmp_secrets.path }}"
content: "{{ _secrets.stdout }}"
mode: 0640
no_log: "{{ no_log }}"
- name: Include secret vars from backup