3 Commits

Author SHA1 Message Date
4bcb1198f3 Add replica rebuild wait;Upgrade longhorn&harbor
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-25 12:36:21 +01:00
64c2c35383 Fix update strategy 2023-01-25 11:21:08 +01:00
e21b11a37a Fix var reference;Housekeeping;Improve UX 2023-01-25 10:28:28 +01:00
18 changed files with 164 additions and 83 deletions

View File

@@ -83,4 +83,4 @@
# mode: 0600 # mode: 0600
# loop: "{{ lookup('ansible.builtin.dict', components) | map(attribute='value.manifests') | list | select('defined') | flatten }}" # loop: "{{ lookup('ansible.builtin.dict', components) | map(attribute='value.manifests') | list | select('defined') | flatten }}"
# loop_control: # loop_control:
# label: "{{ item.type + '/' + item.name }}" # label: "{{ item.type ~ '/' ~ item.name }}"

View File

@@ -62,7 +62,7 @@
- key: root_ca.crt - key: root_ca.crt
value: "{{ stepca_cm_certs.resources[0].data['root_ca.crt'] | b64encode }}" value: "{{ stepca_cm_certs.resources[0].data['root_ca.crt'] | b64encode }}"
loop_control: loop_control:
label: "{{ item.kind + '/' + item.name + ' (' + item.namespace + ')' }}" label: "{{ item.kind ~ '/' ~ item.name ~ ' (' ~ item.namespace ~ ')' }}"
- name: Configure step-ca passthrough ingress - name: Configure step-ca passthrough ingress
ansible.builtin.template: ansible.builtin.template:

View File

@@ -120,7 +120,7 @@
# default_branch: main # default_branch: main
description: GitOps manifests description: GitOps manifests
loop_control: loop_control:
label: "{{ item.organization + '/' + item.body.name }}" label: "{{ item.organization ~ '/' ~ item.body.name }}"
- name: Rebase/Push source gitops repository - name: Rebase/Push source gitops repository
ansible.builtin.shell: ansible.builtin.shell:

View File

@@ -1,7 +1,7 @@
- name: Configure fallback name resolution - name: Configure fallback name resolution
ansible.builtin.lineinfile: ansible.builtin.lineinfile:
path: /etc/hosts path: /etc/hosts
line: "{{ vapp['guestinfo.ipaddress'] }} {{ item + '.' + vapp['metacluster.fqdn'] }}" line: "{{ vapp['guestinfo.ipaddress'] }} {{ item ~ '.' ~ vapp['metacluster.fqdn'] }}"
state: present state: present
loop: loop:
# TODO: Make this list dynamic # TODO: Make this list dynamic

View File

@@ -1,4 +1,7 @@
- block: - block:
# Below tasks circumvent usernames with `<domain>\<username>` format, which causes CAPV to
# incorrectly interpret the backslash (despite automatic escaping) as an escape sequence.
# `vcenter_session.user` will instead contain the username in `<username>@<domain>` format.
- name: Generate vCenter API token - name: Generate vCenter API token
ansible.builtin.uri: ansible.builtin.uri:
@@ -13,7 +16,7 @@
url: https://{{ vapp['hv.fqdn'] }}/api/session url: https://{{ vapp['hv.fqdn'] }}/api/session
method: GET method: GET
headers: headers:
vmware-api-session-id: "{{ vcenter_api_token.json }}" vmware-api-session-id: "{{ vcenterapi_token.json }}"
register: vcenter_session register: vcenter_session
module_defaults: module_defaults:
@@ -51,7 +54,7 @@
- name: Update image references to use local registry - name: Update image references to use local registry
ansible.builtin.replace: ansible.builtin.replace:
dest: "{{ item.root + '/' + item.path }}" dest: "{{ item.root ~ '/' ~ item.path }}"
regexp: '([ ]+image:[ "]+)(?!({{ _template.pattern }}|"{{ _template.pattern }}))' regexp: '([ ]+image:[ "]+)(?!({{ _template.pattern }}|"{{ _template.pattern }}))'
replace: '\1{{ _template.pattern }}' replace: '\1{{ _template.pattern }}'
vars: vars:
@@ -82,7 +85,7 @@
- name: Store custom cluster-template - name: Store custom cluster-template
ansible.builtin.copy: ansible.builtin.copy:
dest: /opt/metacluster/cluster-api/custom-cluster-template.yaml dest: /opt/metacluster/cluster-api/custom-cluster-template.yaml
content: "{{ lookup('kubernetes.core.kustomize', dir='/opt/metacluster/cluster-api/infrastructure-vsphere/' + components.clusterapi.management.version.infrastructure_vsphere ) }}" content: "{{ lookup('kubernetes.core.kustomize', dir='/opt/metacluster/cluster-api/infrastructure-vsphere/' ~ components.clusterapi.management.version.infrastructure_vsphere ) }}"
- name: Initialize Cluster API management cluster - name: Initialize Cluster API management cluster
ansible.builtin.shell: ansible.builtin.shell:

View File

@@ -68,7 +68,7 @@
--portgroup "{{ vcenter_info.network }}" \ --portgroup "{{ vcenter_info.network }}" \
--startaddress {{ vapp['ippool.startip'] }} \ --startaddress {{ vapp['ippool.startip'] }} \
--endaddress {{ vapp['ippool.endip'] }} \ --endaddress {{ vapp['ippool.endip'] }} \
--netmask {{ (vapp['guestinfo.ipaddress'] + '/' + vapp['guestinfo.prefixlength']) | ansible.utils.ipaddr('netmask') }} \ --netmask {{ (vapp['guestinfo.ipaddress'] ~ '/' ~ vapp['guestinfo.prefixlength']) | ansible.utils.ipaddr('netmask') }} \
{{ vapp['guestinfo.dnsserver'] | split(',') | map('trim') | map('regex_replace', '^', '--dnsserver ') | join(' ') }} \ {{ vapp['guestinfo.dnsserver'] | split(',') | map('trim') | map('regex_replace', '^', '--dnsserver ') | join(' ') }} \
--dnsdomain {{ vapp['metacluster.fqdn'] }} \ --dnsdomain {{ vapp['metacluster.fqdn'] }} \
--gateway {{ vapp['guestinfo.gateway'] }} \ --gateway {{ vapp['guestinfo.gateway'] }} \

View File

@@ -5,7 +5,7 @@
url: https://registry.{{ vapp['metacluster.fqdn'] }}/api/v2.0/projects url: https://registry.{{ vapp['metacluster.fqdn'] }}/api/v2.0/projects
method: POST method: POST
headers: headers:
Authorization: "Basic {{ ('admin:' + vapp['metacluster.password']) | b64encode }}" Authorization: "Basic {{ ('admin:' ~ vapp['metacluster.password']) | b64encode }}"
body: body:
project_name: kubeadm project_name: kubeadm
public: true public: true
@@ -28,7 +28,7 @@
url: https://registry.{{ vapp['metacluster.fqdn'] }}/api/v2.0/projects/kubeadm/repositories/{{ ( item | regex_findall('([^:/]+)') )[-2] }}/artifacts?from=library/{{ item | replace('/', '%2F') | replace(':', '%3A') }} url: https://registry.{{ vapp['metacluster.fqdn'] }}/api/v2.0/projects/kubeadm/repositories/{{ ( item | regex_findall('([^:/]+)') )[-2] }}/artifacts?from=library/{{ item | replace('/', '%2F') | replace(':', '%3A') }}
method: POST method: POST
headers: headers:
Authorization: "Basic {{ ('admin:' + vapp['metacluster.password']) | b64encode }}" Authorization: "Basic {{ ('admin:' ~ vapp['metacluster.password']) | b64encode }}"
body: body:
from: "{{ item }}" from: "{{ item }}"
loop: "{{ kubeadm_images }}" loop: "{{ kubeadm_images }}"

View File

@@ -25,7 +25,7 @@
line: 'PasswordAuthentication yes' line: 'PasswordAuthentication yes'
state: absent state: absent
loop_control: loop_control:
label: "{{ '[' + item.regex + '] ' + item.state }}" label: "{{ '[' ~ item.regex ~ '] ' ~ item.state }}"
- name: Create dedicated SSH keypair - name: Create dedicated SSH keypair
community.crypto.openssh_keypair: community.crypto.openssh_keypair:

View File

@@ -17,7 +17,7 @@ COMPONENTS=('storage' 'registry' 'git' 'gitops')
FQDN='{{ _template.metacluster.fqdn }}' FQDN='{{ _template.metacluster.fqdn }}'
IPADDRESS='{{ _template.metacluster.vip }}' IPADDRESS='{{ _template.metacluster.vip }}'
I=60 I=0
while /bin/true; do while /bin/true; do
if [[ $I -gt 59 ]]; then if [[ $I -gt 59 ]]; then

View File

@@ -0,0 +1,50 @@
- block:
- name: Push images to registry
ansible.builtin.shell:
cmd: >-
skopeo copy \
--insecure-policy \
--dest-tls-verify=false \
--dest-creds admin:{{ vapp['metacluster.password'] }} \
docker-archive:./{{ item | basename }} \
docker://registry.{{ vapp['metacluster.fqdn'] }}/library/$( \
skopeo list-tags \
--insecure-policy \
docker-archive:./{{ item | basename }} | \
jq -r '.Tags[0]')
chdir: /opt/metacluster/container-images/
register: push_result
loop: "{{ query('ansible.builtin.fileglob', '/opt/metacluster/container-images/*.tar') | sort }}"
loop_control:
label: "{{ item | basename }}"
retries: "{{ playbook.retries }}"
delay: "{{ playbook.delays.short }}"
until: push_result is not failed
- name: Get all stored container images (=artifacts)
ansible.builtin.uri:
url: https://registry.{{ vapp['metacluster.fqdn'] }}/api/v2.0/search?q=library
method: GET
register: registry_artifacts
- name: Get source registries of all artifacts
ansible.builtin.set_fact:
source_registries: "{{ (source_registries | default([]) + [(item | split('/'))[1]]) | unique | sort }}"
loop: "{{ registry_artifacts.json.repository | json_query('[*].repository_name') }}"
- name: Configure K3s node for private registry
ansible.builtin.template:
dest: /etc/rancher/k3s/registries.yaml
src: registries.j2
vars:
_template:
data: "{{ source_registries }}"
hv:
fqdn: "{{ vapp['metacluster.fqdn'] }}"
module_defaults:
ansible.builtin.uri:
validate_certs: no
status_code: [200, 201, 401]
body_format: json

View File

@@ -1,7 +1,7 @@
- name: Configure fallback name resolution - name: Configure fallback name resolution
ansible.builtin.lineinfile: ansible.builtin.lineinfile:
path: /etc/hosts path: /etc/hosts
line: "{{ vapp['metacluster.vip'] }} {{ item + '.' + vapp['metacluster.fqdn'] }}" line: "{{ vapp['metacluster.vip'] }} {{ item ~ '.' ~ vapp['metacluster.fqdn'] }}"
state: present state: present
loop: loop:
# TODO: Make this list dynamic # TODO: Make this list dynamic

View File

@@ -1,9 +1,11 @@
- import_tasks: init.yml - import_tasks: init.yml
- import_tasks: registry.yml - import_tasks: containerimages.yml
- import_tasks: k3s.yml - import_tasks: k3s.yml
- import_tasks: assets.yml - import_tasks: assets.yml
# - import_tasks: ingress.yml
- import_tasks: storage.yml - import_tasks: storage.yml
# - import_tasks: charts.yml
- import_tasks: registry.yml
# - import_tasks: certauthority.yml # - import_tasks: certauthority.yml
# - import_tasks: git.yml # - import_tasks: git.yml
# - import_tasks: gitops.yml # - import_tasks: gitops.yml

View File

@@ -1,47 +1,25 @@
- block: - block:
- name: Push images to registry - name: Upgrade harbor chart
ansible.builtin.shell: kubernetes.core.helm:
cmd: >- name: harbor
skopeo copy \ chart_ref: /opt/metacluster/helm-charts/harbor
--insecure-policy \ release_namespace: harbor
--dest-tls-verify=false \ create_namespace: yes
--dest-creds admin:{{ vapp['metacluster.password'] }} \ wait: no
docker-archive:./{{ item | basename }} \ kubeconfig: "{{ kubeconfig.path }}"
docker://registry.{{ vapp['metacluster.fqdn'] }}/library/$( \ values: "{{ components.harbor.chart_values }}"
skopeo list-tags \
--insecure-policy \
docker-archive:./{{ item | basename }} | \
jq -r '.Tags[0]')
chdir: /opt/metacluster/container-images/
register: push_result
loop: "{{ query('ansible.builtin.fileglob', '/opt/metacluster/container-images/*.tar') | sort }}"
loop_control:
label: "{{ item | basename }}"
retries: "{{ playbook.retries }}"
delay: "{{ playbook.delays.short }}"
until: push_result is not failed
- name: Get all stored container images (=artifacts) - name: Ensure harbor API availability
ansible.builtin.uri: ansible.builtin.uri:
url: https://registry.{{ vapp['metacluster.fqdn'] }}/api/v2.0/search?q=library url: https://registry.{{ vapp['metacluster.fqdn'] }}/api/v2.0/health
method: GET method: GET
register: registry_artifacts register: api_readycheck
until:
- name: Get source registries of all artifacts - api_readycheck.json.status is defined
ansible.builtin.set_fact: - api_readycheck.json.status == 'healthy'
source_registries: "{{ (source_registries | default([]) + [(item | split('/'))[1]]) | unique | sort }}" retries: "{{ playbook.retries }}"
loop: "{{ registry_artifacts.json.repository | json_query('[*].repository_name') }}" delay: "{{ playbook.delays.long }}"
- name: Configure K3s node for private registry
ansible.builtin.template:
dest: /etc/rancher/k3s/registries.yaml
src: registries.j2
vars:
_template:
data: "{{ source_registries }}"
hv:
fqdn: "{{ vapp['metacluster.fqdn'] }}"
module_defaults: module_defaults:
ansible.builtin.uri: ansible.builtin.uri:

View File

@@ -1,14 +1,53 @@
- name: Increase replicas for each volume - block:
kubernetes.core.k8s:
api_version: longhorn.io/v1beta2 - name: Increase replicas for each volume
kind: volume kubernetes.core.k8s:
name: "{{ item.metadata.name }}" api_version: longhorn.io/v1beta2
namespace: longhorn-system kind: volume
state: patched name: "{{ item.metadata.name }}"
definition: | namespace: longhorn-system
spec: state: patched
numberOfReplicas: {{ lookup('kubernetes.core.k8s', kind='node', kubeconfig=(kubeconfig.path)) | length | int }} definition: |
kubeconfig: "{{ kubeconfig.path }}" spec:
loop: "{{ lookup('kubernetes.core.k8s', api_version='longhorn.io/v1beta2', kind='volume', namespace='longhorn-system', kubeconfig=(kubeconfig.path)) }}" numberOfReplicas: {{ lookup('kubernetes.core.k8s', kind='node', kubeconfig=(kubeconfig.path)) | length | int }}
loop_control: loop: "{{ lookup('kubernetes.core.k8s', api_version='longhorn.io/v1beta2', kind='volume', namespace='longhorn-system', kubeconfig=(kubeconfig.path)) }}"
label: "{{ item.metadata.name }}" loop_control:
label: "{{ item.metadata.name }}"
- name: Wait for replica rebuilds to complete
ansible.builtin.uri:
url: https://storage.{{ vapp['metacluster.fqdn'] }}/v1/volumes
method: GET
register: volume_details
until:
- (volume_details.json.data | json_query('[*].robustness') | unique | length) == 1
- (volume_details.json.data | json_query('[*].robustness') | first) == "healthy"
retries: "{{ playbook.retries }}"
delay: "{{ playbook.delays.medium }}"
- name: Install longhorn chart
kubernetes.core.helm:
name: longhorn
chart_ref: /opt/metacluster/helm-charts/longhorn
release_namespace: longhorn-system
create_namespace: yes
wait: no
values: "{{ components.longhorn.chart_values }}"
- name: Ensure longhorn API availability
ansible.builtin.uri:
url: https://storage.{{ vapp['metacluster.fqdn'] }}/v1
method: GET
register: api_readycheck
until:
- api_readycheck is not failed
retries: "{{ playbook.retries }}"
delay: "{{ playbook.delays.long }}"
module_defaults:
ansible.builtin.uri:
validate_certs: no
status_code: [200, 201]
body_format: json
group/k8s:
kubeconfig: "{{ kubeconfig.path }}"

View File

@@ -1,4 +1,10 @@
#!/bin/bash #!/bin/bash
# Workaround for ansible output regression
export PYTHONUNBUFFERED=1
# Apply firstboot configuration w/ ansible # Apply firstboot configuration w/ ansible
/usr/local/bin/ansible-playbook -e "PYTHONUNBUFFERED=1" /opt/firstboot/ansible/playbook.yml | tee -a /var/log/firstboot.log > /dev/tty1 2>&1 /usr/local/bin/ansible-playbook /opt/firstboot/ansible/playbook.yml | tee -a /var/log/firstboot.log > /dev/tty1 2>&1
# Cleanup console
clear > /dev/tty1

View File

@@ -42,6 +42,9 @@ platform:
websecure: websecure:
tls: tls:
certResolver: stepca certResolver: stepca
updateStrategy:
type: Recreate
rollingUpdate: null
helm_repositories: helm_repositories:
- name: argo - name: argo

View File

@@ -106,13 +106,13 @@ PropertyCategories:
Configurations: '*' Configurations: '*'
UserConfigurable: true UserConfigurable: true
- Key: guestinfo.ntpserver # - Key: guestinfo.ntpserver
Type: string(1..) # Type: string(1..)
Label: Time server* # Label: Time server*
Description: A comma-separated list of timeservers # Description: A comma-separated list of timeservers
DefaultValue: 0.pool.ntp.org,1.pool.ntp.org,2.pool.ntp.org # DefaultValue: 0.pool.ntp.org,1.pool.ntp.org,2.pool.ntp.org
Configurations: '*' # Configurations: '*'
UserConfigurable: true # UserConfigurable: true
- Name: 3) Workload-cluster - Name: 3) Workload-cluster
ProductProperties: ProductProperties:

View File

@@ -87,13 +87,13 @@ PropertyCategories:
Configurations: '*' Configurations: '*'
UserConfigurable: true UserConfigurable: true
- Key: guestinfo.ntpserver # - Key: guestinfo.ntpserver
Type: string(1..) # Type: string(1..)
Label: Time server* # Label: Time server*
Description: A comma-separated list of timeservers # Description: A comma-separated list of timeservers
DefaultValue: 0.pool.ntp.org,1.pool.ntp.org,2.pool.ntp.org # DefaultValue: 0.pool.ntp.org,1.pool.ntp.org,2.pool.ntp.org
Configurations: '*' # Configurations: '*'
UserConfigurable: true # UserConfigurable: true
- Name: 3) Common - Name: 3) Common
ProductProperties: ProductProperties: