285 lines
10 KiB
YAML
285 lines
10 KiB
YAML
- 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
|
|
ansible.builtin.uri:
|
|
url: https://{{ vapp['hv.fqdn'] }}/api/session
|
|
method: POST
|
|
headers:
|
|
Authorization: Basic {{ ( vapp['hv.username'] ~ ':' ~ vapp['hv.password'] ) | b64encode }}
|
|
register: vcenterapi_token
|
|
|
|
- name: Retrieve vCenter API session details
|
|
ansible.builtin.uri:
|
|
url: https://{{ vapp['hv.fqdn'] }}/api/session
|
|
method: GET
|
|
headers:
|
|
vmware-api-session-id: "{{ vcenterapi_token.json }}"
|
|
register: vcenter_session
|
|
|
|
module_defaults:
|
|
ansible.builtin.uri:
|
|
validate_certs: no
|
|
status_code: [200, 201]
|
|
body_format: json
|
|
|
|
- name: Configure clusterctl
|
|
ansible.builtin.template:
|
|
src: clusterctl.j2
|
|
dest: /opt/metacluster/cluster-api/clusterctl.yaml
|
|
vars:
|
|
_template:
|
|
version:
|
|
base: "{{ components.clusterapi.management.version.base }}"
|
|
cert_manager: "{{ components.clusterapi.management.version.cert_manager }}"
|
|
infrastructure_vsphere: "{{ components.clusterapi.management.version.infrastructure_vsphere }}"
|
|
ipam_incluster: "{{ components.clusterapi.management.version.ipam_incluster }}"
|
|
hv:
|
|
fqdn: "{{ vapp['hv.fqdn'] }}"
|
|
tlsthumbprint: "{{ tls_thumbprint.stdout }}"
|
|
username: "{{ vcenter_session.json.user }}"
|
|
password: "{{ vapp['hv.password'] }}"
|
|
datacenter: "{{ vcenter_info.datacenter }}"
|
|
datastore: "{{ vcenter_info.datastore }}"
|
|
network: "{{ vcenter_info.network }}"
|
|
resourcepool: "{{ vcenter_info.resourcepool }}"
|
|
folder: "{{ vcenter_info.folder }}"
|
|
cluster:
|
|
nodetemplate: "{{ nodetemplate_inventorypath }}"
|
|
publickey: "{{ vapp['guestinfo.rootsshkey'] }}"
|
|
version: "{{ components.clusterapi.workload.version.k8s }}"
|
|
vip: "{{ vapp['workloadcluster.vip'] }}"
|
|
|
|
- name: Generate cluster-template kustomization manifest
|
|
ansible.builtin.template:
|
|
src: kustomization.cluster-template.j2
|
|
dest: /opt/metacluster/cluster-api/infrastructure-vsphere/{{ components.clusterapi.management.version.infrastructure_vsphere }}/kustomization.yaml
|
|
vars:
|
|
_template:
|
|
network:
|
|
fqdn: "{{ vapp['metacluster.fqdn'] }}"
|
|
dnsserver: "{{ vapp['guestinfo.dnsserver'] }}"
|
|
nodesize:
|
|
cpu: "{{ config.clusterapi.size_matrix[ vapp['workloadcluster.nodesize'] ].cpu }}"
|
|
memory: "{{ config.clusterapi.size_matrix[ vapp['workloadcluster.nodesize'] ].memory }}"
|
|
rootca: "{{ stepca_cm_certs.resources[0].data['root_ca.crt'] }}"
|
|
runcmds:
|
|
- update-ca-certificates
|
|
registries: "{{ source_registries }}"
|
|
|
|
- name: Store custom cluster-template
|
|
ansible.builtin.copy:
|
|
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 ) }}"
|
|
|
|
- name: Initialize Cluster API management cluster
|
|
ansible.builtin.shell:
|
|
cmd: >-
|
|
clusterctl init \
|
|
-v5 \
|
|
--infrastructure vsphere:{{ components.clusterapi.management.version.infrastructure_vsphere }} \
|
|
--ipam in-cluster:{{ components.clusterapi.management.version.ipam_incluster }} \
|
|
--config ./clusterctl.yaml \
|
|
--kubeconfig {{ kubeconfig.path }}
|
|
chdir: /opt/metacluster/cluster-api
|
|
|
|
- name: Ensure controller availability
|
|
kubernetes.core.k8s_info:
|
|
kind: Deployment
|
|
name: "{{ item.name }}"
|
|
namespace: "{{ item.namespace }}"
|
|
wait: true
|
|
kubeconfig: "{{ kubeconfig.path }}"
|
|
loop:
|
|
- name: caip-in-cluster-controller-manager
|
|
namespace: caip-in-cluster-system
|
|
- name: capi-controller-manager
|
|
namespace: capi-system
|
|
- name: capv-controller-manager
|
|
namespace: capv-system
|
|
loop_control:
|
|
label: "{{ item.name }}"
|
|
|
|
- name: Parse vApp for workload cluster sizing
|
|
ansible.builtin.set_fact:
|
|
clustersize: >-
|
|
{{ {
|
|
'controlplane': vapp['deployment.type'] | regex_findall('^cp(\d)+') | first,
|
|
'worker': vapp['deployment.type'] | regex_findall('w(\d)+') | first,
|
|
'workerstorage': vapp['deployment.type'] | regex_findall('ws(\d)+$') | first
|
|
} }}
|
|
|
|
- name: Generate workload cluster manifest
|
|
ansible.builtin.shell:
|
|
cmd: >-
|
|
clusterctl generate cluster \
|
|
{{ vapp['workloadcluster.name'] | lower }} \
|
|
--control-plane-machine-count {{ clustersize.controlplane }} \
|
|
--worker-machine-count {{ clustersize.worker }} \
|
|
--from ./custom-cluster-template.yaml \
|
|
--config ./clusterctl.yaml \
|
|
--kubeconfig {{ kubeconfig.path }}
|
|
chdir: /opt/metacluster/cluster-api
|
|
register: clusterctl_newcluster
|
|
|
|
- name: Initialize tempfolder
|
|
ansible.builtin.tempfile:
|
|
state: directory
|
|
register: capi_clustermanifest
|
|
|
|
- name: Save workload cluster manifest
|
|
ansible.builtin.copy:
|
|
dest: "{{ capi_clustermanifest.path }}/new-cluster.yaml"
|
|
content: "{{ clusterctl_newcluster.stdout }}"
|
|
|
|
- name: Split manifest into separate files
|
|
ansible.builtin.shell:
|
|
cmd: >-
|
|
kubectl slice \
|
|
-f {{ capi_clustermanifest.path }}/new-cluster.yaml \
|
|
-o {{ capi_clustermanifest.path }}/manifests
|
|
|
|
- name: Generate nodepool kustomization manifest
|
|
ansible.builtin.template:
|
|
src: kustomization.nodepool.j2
|
|
dest: "{{ capi_clustermanifest.path }}/kustomization.yaml"
|
|
vars:
|
|
_template:
|
|
cluster:
|
|
name: "{{ vapp['workloadcluster.name'] }}"
|
|
nodepool:
|
|
size: "{{ clustersize.workerstorage }}"
|
|
additionaldisk: "{{ vapp['workloadcluster.additionaldisk'] }}"
|
|
|
|
- name: Store nodepool manifest
|
|
ansible.builtin.copy:
|
|
dest: "{{ capi_clustermanifest.path }}/manifests/nodepool-worker-storage.yaml"
|
|
content: "{{ lookup('kubernetes.core.kustomize', dir=capi_clustermanifest.path) }}"
|
|
|
|
- name: Create in-cluster IpPool
|
|
ansible.builtin.template:
|
|
src: ippool.j2
|
|
dest: "{{ capi_clustermanifest.path }}/manifests/inclusterippool-{{ _template.cluster.name }}.yml"
|
|
vars:
|
|
_template:
|
|
cluster:
|
|
name: "{{ vapp['workloadcluster.name'] | lower }}"
|
|
namespace: default
|
|
network:
|
|
startip: "{{ vapp['ippool.startip'] }}"
|
|
endip: "{{ vapp['ippool.endip'] }}"
|
|
prefix: "{{ vapp['guestinfo.prefixlength'] }}"
|
|
gateway: "{{ vapp['guestinfo.gateway'] }}"
|
|
|
|
- name: Initialize/Push git repository
|
|
ansible.builtin.shell:
|
|
cmd: |
|
|
git init
|
|
git config --global user.email "administrator@{{ vapp['metacluster.fqdn'] }}"
|
|
git config --global user.name "administrator"
|
|
git checkout -b main
|
|
git add ./manifests
|
|
git commit -m "Upload manifests"
|
|
git remote add origin https://git.{{ vapp['metacluster.fqdn'] }}/mc/GitOps.ClusterAPI.git
|
|
git push https://administrator:{{ vapp['metacluster.password'] | urlencode }}@git.{{ vapp['metacluster.fqdn'] }}/mc/GitOps.ClusterAPI.git --all
|
|
chdir: "{{ capi_clustermanifest.path }}"
|
|
|
|
- name: Cleanup tempfolder
|
|
ansible.builtin.file:
|
|
path: "{{ capi_clustermanifest.path }}"
|
|
state: absent
|
|
when: capi_clustermanifest.path is defined
|
|
|
|
- name: Configure Cluster API repository
|
|
ansible.builtin.template:
|
|
src: gitrepo.j2
|
|
dest: /var/lib/rancher/k3s/server/manifests/{{ _template.name }}-manifest.yaml
|
|
owner: root
|
|
group: root
|
|
mode: 0600
|
|
vars:
|
|
_template:
|
|
name: gitrepo-mc-gitopsclusterapi
|
|
namespace: argo-cd
|
|
url: https://git.{{ vapp['metacluster.fqdn'] }}/mc/GitOps.ClusterAPI.git
|
|
notify:
|
|
- Apply manifests
|
|
|
|
- name: WORKAROUND - Wait for ingress ACME requests to complete
|
|
ansible.builtin.shell:
|
|
cmd: >-
|
|
openssl s_client -connect registry.{{ vapp['metacluster.fqdn'] }}:443 -servername registry.{{ vapp['metacluster.fqdn'] }} 2>/dev/null </dev/null | \
|
|
openssl x509 -noout -subject | \
|
|
grep 'subject=CN = registry.{{ vapp['metacluster.fqdn'] }}'
|
|
register: certificate_subject
|
|
until: certificate_subject is not failed
|
|
retries: "{{ playbook.retries }}"
|
|
delay: "{{ (storage_benchmark | int) * (playbook.delay.medium | int) }}"
|
|
|
|
- name: Create application
|
|
ansible.builtin.template:
|
|
src: application.j2
|
|
dest: /var/lib/rancher/k3s/server/manifests/{{ _template.application.name }}-manifest.yaml
|
|
owner: root
|
|
group: root
|
|
mode: 0600
|
|
vars:
|
|
_template:
|
|
application:
|
|
name: application-clusterapi-workloadcluster
|
|
namespace: argo-cd
|
|
cluster:
|
|
name: https://kubernetes.default.svc
|
|
namespace: default
|
|
repository:
|
|
url: https://git.{{ vapp['metacluster.fqdn'] }}/mc/GitOps.ClusterAPI.git
|
|
path: manifests
|
|
revision: main
|
|
notify:
|
|
- Apply manifests
|
|
|
|
- name: Trigger handlers
|
|
ansible.builtin.meta: flush_handlers
|
|
|
|
- name: Wait for cluster to be available
|
|
ansible.builtin.shell:
|
|
cmd: >-
|
|
kubectl wait clusters.cluster.x-k8s.io/{{ vapp['workloadcluster.name'] | lower }} \
|
|
--for=condition=Ready \
|
|
--timeout 0s
|
|
register: cluster_readycheck
|
|
until: cluster_readycheck is succeeded
|
|
retries: "{{ playbook.retries }}"
|
|
delay: "{{ (storage_benchmark | int) * (playbook.delay.long | int) }}"
|
|
|
|
- name: Initialize tempfile
|
|
ansible.builtin.tempfile:
|
|
state: file
|
|
register: capi_kubeconfig
|
|
|
|
- name: Retrieve kubeconfig
|
|
ansible.builtin.shell:
|
|
cmd: >-
|
|
clusterctl get kubeconfig \
|
|
{{ vapp['workloadcluster.name'] | lower }} \
|
|
--kubeconfig {{ kubeconfig.path }}
|
|
register: capi_kubectl_config
|
|
|
|
- name: Store kubeconfig in tempfile
|
|
ansible.builtin.copy:
|
|
dest: "{{ capi_kubeconfig.path }}"
|
|
content: "{{ capi_kubectl_config.stdout }}"
|
|
mode: 0600
|
|
no_log: true
|
|
|
|
# TODO: move to git repo
|
|
- name: Apply cni plugin manifest
|
|
kubernetes.core.k8s:
|
|
src: /opt/metacluster/cluster-api/cni-calico/{{ components.clusterapi.workload.version.calico }}/calico.yaml
|
|
state: present
|
|
wait: true
|
|
kubeconfig: "{{ capi_kubeconfig.path }}"
|
|
# TODO: move to git repo
|