-
Notifications
You must be signed in to change notification settings - Fork 966
Expand file tree
/
Copy pathmain.yml
More file actions
342 lines (304 loc) · 12.3 KB
/
Copy pathmain.yml
File metadata and controls
342 lines (304 loc) · 12.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
---
- name: Get k3s installed version
ansible.builtin.command: k3s --version
register: k3s_version_output
changed_when: false
ignore_errors: true
- name: Set k3s installed version
when: not ansible_check_mode and k3s_version_output.rc == 0
ansible.builtin.set_fact:
installed_k3s_version: "{{ k3s_version_output.stdout_lines[0].split(' ')[2] }}"
# If airgapped, all K3s artifacts are already on the node.
# We should be downloading and installing the newer version only if we are in one of the following cases :
# - we couldn't get k3s installed version in the first task of this role
# - the installed version of K3s on the nodes is older than the requested version in ansible vars
- name: Download artifact only if needed
when: not ansible_check_mode and airgap_dir is undefined and ( k3s_version_output.rc != 0 or installed_k3s_version is version(k3s_version, '<') )
block:
- name: Download K3s install script
ansible.builtin.get_url:
url: https://get.k3s.io/
timeout: 120
dest: /usr/local/bin/k3s-install.sh
owner: root
group: root
mode: "0755"
- name: Download K3s binary
# For some reason, ansible-lint thinks using enviroment with command is an error
# even though its valid https://ansible.readthedocs.io/projects/lint/rules/inline-env-var/#correct-code
ansible.builtin.command: # noqa inline-env-var
cmd: /usr/local/bin/k3s-install.sh
# Ensures that extra_install_envs are combined with required env vars
environment: >-
{{ extra_install_envs | combine({
"INSTALL_K3S_SKIP_START": "true",
"INSTALL_K3S_VERSION": k3s_version,
}) }}
changed_when: true
- name: Add K3s autocomplete to user bashrc
when: ansible_user is defined
ansible.builtin.lineinfile:
path: "~{{ ansible_user }}/.bashrc"
regexp: '\.\s+<\(k3s completion bash\)'
line: ". <(k3s completion bash) # Added by k3s-ansible"
- name: Compute final server arguments
ansible.builtin.set_fact:
_api_endpoint_in_config: >-
{% if server_config_yaml is defined and api_endpoint is defined and server_config_yaml | regex_search('tls-san:.*' + api_endpoint | regex_escape(), ignorecase=True) %}
true
{% else %}
false
{% endif %}
_api_endpoint_in_args: >-
{% if api_endpoint is defined and extra_server_args | regex_search('--tls-san[=\s]+' + api_endpoint | regex_escape(), ignorecase=True) %}
true
{% else %}
false
{% endif %}
- name: Add TLS SAN to server arguments if needed
ansible.builtin.set_fact:
final_server_args: >-
{{ extra_server_args }}
{% if api_endpoint is defined and api_endpoint != ansible_hostname and _api_endpoint_in_config | bool == false and _api_endpoint_in_args | bool == false %}
--tls-san={{ api_endpoint }}
{% endif %}
- name: Setup optional config file
when: server_config_yaml is defined
block:
- name: Make config directory
ansible.builtin.file:
path: "/etc/rancher/k3s"
mode: "0755"
state: directory
- name: Copy config values
ansible.builtin.copy:
content: "{{ server_config_yaml }}"
dest: "/etc/rancher/k3s/config.yaml"
mode: "0644"
register: _server_config_result
- name: Init first server node
when: inventory_hostname == groups[server_group][0] or ansible_host == groups[server_group][0]
block:
- name: Copy K3s service file [Single]
when: groups[server_group] | length == 1 or use_external_database
ansible.builtin.template:
src: "k3s-single.service.j2"
dest: "{{ systemd_dir }}/k3s.service"
owner: root
group: root
mode: "0644"
register: service_file_single
- name: Copy K3s service file [HA]
when:
- groups[server_group] | length > 1
- not use_external_database
ansible.builtin.template:
src: "k3s-cluster-init.service.j2"
dest: "{{ systemd_dir }}/k3s.service"
owner: root
group: root
mode: "0644"
register: service_file_ha
- name: Add service environment variables
when: extra_service_envs is defined
ansible.builtin.lineinfile:
path: "{{ systemd_dir }}/k3s.service.env"
line: "{{ item }}"
with_items: "{{ extra_service_envs }}"
- name: Delete any existing token from the environment if different from the new one
ansible.builtin.lineinfile:
state: absent
path: "{{ systemd_dir }}/k3s.service.env"
regexp: "^K3S_TOKEN=\\s*(?!{{ token | default('') | regex_escape }}\\s*$)"
# Add the token to the environment if it has been provided.
# Otherwise, let the first server create one on the first run.
- name: Add token as an environment variable
no_log: true # avoid logging the server token
ansible.builtin.lineinfile:
path: "{{ systemd_dir }}/k3s.service.env"
line: "K3S_TOKEN={{ token }}"
when: token is defined
- name: Restart K3s service
when:
- ansible_facts.services['k3s.service'] is defined
- ansible_facts.services['k3s.service'].state == 'running'
- service_file_single.changed or service_file_ha.changed or _server_config_result.changed
ansible.builtin.systemd:
name: k3s
daemon_reload: true
state: restarted
- name: Enable and check K3s service
when: ansible_facts.services['k3s.service'] is not defined or ansible_facts.services['k3s.service'].state != 'running'
ansible.builtin.systemd:
name: k3s
daemon_reload: true
state: started
enabled: true
- name: Pause to allow first server startup
when: (groups[server_group] | length) > 1
ansible.builtin.pause:
seconds: 10
- name: Check whether kubectl is installed on control node
ansible.builtin.command: 'kubectl'
register: kubectl_installed
ignore_errors: true
delegate_to: 127.0.0.1
become: false
changed_when: false
# Copy the k3s config to a second file to detect changes.
# If no changes are found, we can skip copying the kubeconfig to the control node.
- name: Copy k3s.yaml to second file
ansible.builtin.copy:
src: /etc/rancher/k3s/k3s.yaml
dest: /etc/rancher/k3s/k3s-copy.yaml
mode: "0600"
remote_src: true
register: copy_k3s_yaml_file
- name: Apply K3S kubeconfig to control node
when:
- kubectl_installed.rc == 0
- copy_k3s_yaml_file.changed
block:
- name: Copy kubeconfig to control node
ansible.builtin.fetch:
src: /etc/rancher/k3s/k3s.yaml
dest: "{{ kubeconfig }}"
flat: true
- name: Change server address in kubeconfig on control node
ansible.builtin.shell: |
KUBECONFIG={{ kubeconfig }} kubectl config set-cluster default --server=https://{{ api_endpoint }}:{{ api_port }}
delegate_to: 127.0.0.1
become: false
register: csa_result
changed_when:
- csa_result.rc == 0
- name: Setup kubeconfig context on control node - {{ cluster_context }}
when: kubeconfig == "~/.kube/config.new"
ansible.builtin.replace:
path: "{{ kubeconfig }}"
regexp: 'default'
replace: '{{ cluster_context }}'
delegate_to: 127.0.0.1
become: false
- name: Merge with any existing kubeconfig on control node
when: kubeconfig == "~/.kube/config.new"
ansible.builtin.shell: |
TFILE=$(mktemp)
KUBECONFIG={{ kubeconfig }}:~/.kube/config kubectl config set-context {{ cluster_context }} --user={{ cluster_context }} --cluster={{ cluster_context }}
KUBECONFIG={{ kubeconfig }}:~/.kube/config kubectl config view --flatten > ${TFILE}
mv ${TFILE} ~/.kube/config
delegate_to: 127.0.0.1
become: false
register: mv_result
changed_when:
- mv_result.rc == 0
- name: Get the token if randomly generated
when: token is not defined
block:
- name: Wait for token
ansible.builtin.wait_for:
path: /var/lib/rancher/k3s/server/token
- name: Read node-token from master
ansible.builtin.slurp:
src: /var/lib/rancher/k3s/server/token
register: node_token
- name: Store Master node-token
ansible.builtin.set_fact:
token: "{{ node_token.content | b64decode | regex_replace('\n', '') }}"
- name: Start other server if any and verify status
when:
- (groups[server_group] | length) > 1
- inventory_hostname != groups[server_group][0] and ansible_host != groups[server_group][0]
block:
- name: Get the token from the first server
ansible.builtin.set_fact:
token: "{{ hostvars[groups[server_group][0]].token }}"
- name: Add service environment variables
when: extra_service_envs is defined
ansible.builtin.lineinfile:
path: "{{ systemd_dir }}/k3s.service.env"
line: "{{ item }}"
with_items: "{{ extra_service_envs }}"
- name: Delete any existing token from the environment if different from the new one
ansible.builtin.lineinfile:
state: absent
path: "{{ systemd_dir }}/k3s.service.env"
regexp: "^K3S_TOKEN=\\s*(?!{{ token }}\\s*$)"
- name: Add the token for joining the cluster to the environment
no_log: true # avoid logging the server token
ansible.builtin.lineinfile:
path: "{{ systemd_dir }}/k3s.service.env"
line: "{{ item }}"
with_items:
- "K3S_TOKEN={{ token }}"
- name: Copy K3s service file [HA]
when: not use_external_database
ansible.builtin.template:
src: "k3s-ha.service.j2"
dest: "{{ systemd_dir }}/k3s.service"
owner: root
group: root
mode: "0644"
register: service_file_ha
- name: Copy K3s service file [External DB]
when: use_external_database
ansible.builtin.template:
src: "k3s-single.service.j2"
dest: "{{ systemd_dir }}/k3s.service"
owner: root
group: root
mode: "0644"
register: service_file_external_db
- name: Restart K3s service
when:
- ansible_facts.services['k3s.service'] is defined
- ansible_facts.services['k3s.service'].state == 'running'
- service_file_ha.changed or service_file_external_db.changed or _server_config_result.changed
ansible.builtin.systemd:
name: k3s
daemon_reload: true
state: restarted
- name: Enable and check K3s service
when: ansible_facts.services['k3s.service'] is not defined or ansible_facts.services['k3s.service'].state != 'running'
ansible.builtin.systemd:
name: k3s
daemon_reload: true
state: started
enabled: true
- name: Verify that all server nodes joined
when: not ansible_check_mode and (groups[server_group] | length) > 1
ansible.builtin.command:
cmd: >
k3s kubectl get nodes -l "node-role.kubernetes.io/control-plane=true" -o=jsonpath="{.items[*].metadata.name}"
register: nodes
until: nodes.rc == 0 and (nodes.stdout.split() | length) == (groups[server_group] | length)
retries: 20
delay: 10
changed_when: false
- name: Setup kubectl for user
when: user_kubectl
block:
- name: Create directory .kube
ansible.builtin.file:
path: ~{{ ansible_user }}/.kube
state: directory
owner: "{{ ansible_user }}"
mode: "u=rwx,g=rx,o="
- name: Copy config file to user home directory
ansible.builtin.copy:
src: /etc/rancher/k3s/k3s.yaml
dest: ~{{ ansible_user }}/.kube/config
remote_src: true
owner: "{{ ansible_user }}"
mode: "u=rw,g=,o="
- name: Configure default KUBECONFIG for user
ansible.builtin.lineinfile:
path: ~{{ ansible_user }}/.bashrc
regexp: 'export KUBECONFIG=~/.kube/config'
line: 'export KUBECONFIG=~/.kube/config # Added by k3s-ansible'
state: present
- name: Configure kubectl autocomplete
ansible.builtin.lineinfile:
path: ~{{ ansible_user }}/.bashrc
regexp: '\.\s+<\(kubectl completion bash\)'
line: ". <(kubectl completion bash) # Added by k3s-ansible"