Skip to content

Commit 6744726

Browse files
authored
kubeadm support (#1631)
* kubeadm support * move k8s master to a subtask * disable k8s secrets when using kubeadm * fix etcd cert serial var * move simple auth users to master role * make a kubeadm-specific env file for kubelet * add non-ha CI job * change ci boolean vars to json format * fixup * Update create-gce.yml * Update create-gce.yml * Update create-gce.yml
1 parent 69fac8e commit 6744726

File tree

35 files changed

+469
-120
lines changed

35 files changed

+469
-120
lines changed

.gitlab-ci.yml

+62-16
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ before_script:
5353
IDEMPOT_CHECK: "false"
5454
RESET_CHECK: "false"
5555
UPGRADE_TEST: "false"
56+
KUBEADM_ENABLED: "false"
5657
RESOLVCONF_MODE: docker_dns
5758
LOG_LEVEL: "-vv"
5859
ETCD_DEPLOYMENT: "docker"
@@ -117,16 +118,19 @@ before_script:
117118
-e bootstrap_os=${BOOTSTRAP_OS}
118119
-e cert_management=${CERT_MGMT:-script}
119120
-e cloud_provider=gce
120-
-e deploy_netchecker=true
121-
-e download_localhost=${DOWNLOAD_LOCALHOST}
122-
-e download_run_once=${DOWNLOAD_RUN_ONCE}
121+
-e "{deploy_netchecker: true}"
122+
-e "{download_localhost: ${DOWNLOAD_LOCALHOST}}"
123+
-e "{download_run_once: ${DOWNLOAD_RUN_ONCE}}"
123124
-e etcd_deployment_type=${ETCD_DEPLOYMENT}
124125
-e kube_network_plugin=${KUBE_NETWORK_PLUGIN}
125126
-e kubedns_min_replicas=1
126127
-e kubelet_deployment_type=${KUBELET_DEPLOYMENT}
127128
-e local_release_dir=${PWD}/downloads
128129
-e resolvconf_mode=${RESOLVCONF_MODE}
129130
-e vault_deployment_type=${VAULT_DEPLOYMENT}
131+
-e weave_cpu_requests=${WEAVE_CPU_LIMIT}
132+
-e weave_cpu_limit=${WEAVE_CPU_LIMIT}
133+
-e "{kubeadm_enabled: ${KUBEADM_ENABLED}}"
130134
-e "${AUTHORIZATION_MODES}"
131135
--limit "all:!fake_hosts"
132136
cluster.yml
@@ -144,17 +148,19 @@ before_script:
144148
-e ansible_ssh_user=${SSH_USER}
145149
-e bootstrap_os=${BOOTSTRAP_OS}
146150
-e cloud_provider=gce
147-
-e deploy_netchecker=true
148-
-e download_localhost=${DOWNLOAD_LOCALHOST}
149-
-e download_run_once=${DOWNLOAD_RUN_ONCE}
151+
-e "{deploy_netchecker: true}"
152+
-e "{download_localhost: ${DOWNLOAD_LOCALHOST}}"
153+
-e "{download_run_once: ${DOWNLOAD_RUN_ONCE}}"
150154
-e etcd_deployment_type=${ETCD_DEPLOYMENT}
151155
-e kube_network_plugin=${KUBE_NETWORK_PLUGIN}
152156
-e kubedns_min_replicas=1
153157
-e kubelet_deployment_type=${KUBELET_DEPLOYMENT}
154158
-e local_release_dir=${PWD}/downloads
155159
-e resolvconf_mode=${RESOLVCONF_MODE}
160+
-e vault_deployment_type=${VAULT_DEPLOYMENT}
156161
-e weave_cpu_requests=${WEAVE_CPU_LIMIT}
157162
-e weave_cpu_limit=${WEAVE_CPU_LIMIT}
163+
-e "{kubeadm_enabled: ${KUBEADM_ENABLED}}"
158164
-e "${AUTHORIZATION_MODES}"
159165
--limit "all:!fake_hosts"
160166
$PLAYBOOK;
@@ -178,14 +184,18 @@ before_script:
178184
--private-key=${HOME}/.ssh/id_rsa
179185
-e bootstrap_os=${BOOTSTRAP_OS}
180186
-e ansible_python_interpreter=${PYPATH}
181-
-e download_localhost=${DOWNLOAD_LOCALHOST}
182-
-e download_run_once=${DOWNLOAD_RUN_ONCE}
183-
-e deploy_netchecker=true
184-
-e resolvconf_mode=${RESOLVCONF_MODE}
185-
-e local_release_dir=${PWD}/downloads
187+
-e "{deploy_netchecker: true}"
188+
-e "{download_localhost: ${DOWNLOAD_LOCALHOST}}"
189+
-e "{download_run_once: ${DOWNLOAD_RUN_ONCE}}"
186190
-e etcd_deployment_type=${ETCD_DEPLOYMENT}
187191
-e kubedns_min_replicas=1
188192
-e kubelet_deployment_type=${KUBELET_DEPLOYMENT}
193+
-e local_release_dir=${PWD}/downloads
194+
-e resolvconf_mode=${RESOLVCONF_MODE}
195+
-e vault_deployment_type=${VAULT_DEPLOYMENT}
196+
-e "{kubeadm_enabled: ${KUBEADM_ENABLED}}"
197+
-e weave_cpu_requests=${WEAVE_CPU_LIMIT}
198+
-e weave_cpu_limit=${WEAVE_CPU_LIMIT}
189199
-e "${AUTHORIZATION_MODES}"
190200
--limit "all:!fake_hosts"
191201
cluster.yml;
@@ -221,14 +231,18 @@ before_script:
221231
--private-key=${HOME}/.ssh/id_rsa
222232
-e bootstrap_os=${BOOTSTRAP_OS}
223233
-e ansible_python_interpreter=${PYPATH}
224-
-e download_localhost=${DOWNLOAD_LOCALHOST}
225-
-e download_run_once=${DOWNLOAD_RUN_ONCE}
226-
-e deploy_netchecker=true
227-
-e resolvconf_mode=${RESOLVCONF_MODE}
228-
-e local_release_dir=${PWD}/downloads
234+
-e "{deploy_netchecker: true}"
235+
-e "{download_localhost: ${DOWNLOAD_LOCALHOST}}"
236+
-e "{download_run_once: ${DOWNLOAD_RUN_ONCE}}"
229237
-e etcd_deployment_type=${ETCD_DEPLOYMENT}
230238
-e kubedns_min_replicas=1
231239
-e kubelet_deployment_type=${KUBELET_DEPLOYMENT}
240+
-e local_release_dir=${PWD}/downloads
241+
-e resolvconf_mode=${RESOLVCONF_MODE}
242+
-e vault_deployment_type=${VAULT_DEPLOYMENT}
243+
-e "{kubeadm_enabled: ${KUBEADM_ENABLED}}"
244+
-e weave_cpu_requests=${WEAVE_CPU_LIMIT}
245+
-e weave_cpu_limit=${WEAVE_CPU_LIMIT}
232246
-e "${AUTHORIZATION_MODES}"
233247
--limit "all:!fake_hosts"
234248
cluster.yml;
@@ -280,6 +294,17 @@ before_script:
280294
UPGRADE_TEST: "graceful"
281295
STARTUP_SCRIPT: ""
282296

297+
.ubuntu_canal_kubeadm_variables: &ubuntu_canal_kubeadm_variables
298+
# stage: deploy-gce-part1
299+
KUBE_NETWORK_PLUGIN: canal
300+
AUTHORIZATION_MODES: "{ 'authorization_modes': [ 'RBAC' ] }"
301+
CLOUD_IMAGE: ubuntu-1604-xenial
302+
CLOUD_MACHINE_TYPE: "n1-standard-2"
303+
CLOUD_REGION: europe-west1-b
304+
CLUSTER_MODE: default
305+
KUBEADM_ENABLED: "true"
306+
STARTUP_SCRIPT: ""
307+
283308
.rhel7_weave_variables: &rhel7_weave_variables
284309
# stage: deploy-gce-part1
285310
KUBE_NETWORK_PLUGIN: weave
@@ -470,6 +495,27 @@ ubuntu-canal-ha-rbac-triggers:
470495
when: on_success
471496
only: ['triggers']
472497

498+
ubuntu-canal-kubeadm-rbac:
499+
stage: deploy-gce-part1
500+
<<: *job
501+
<<: *gce
502+
variables:
503+
<<: *gce_variables
504+
<<: *ubuntu_canal_kubeadm_variables
505+
when: manual
506+
except: ['triggers']
507+
only: ['master', /^pr-.*$/]
508+
509+
ubuntu-canal-kubeadm-triggers:
510+
stage: deploy-gce-part1
511+
<<: *job
512+
<<: *gce
513+
variables:
514+
<<: *gce_variables
515+
<<: *ubuntu_canal_kubeadm_variables
516+
when: on_success
517+
only: ['triggers']
518+
473519
rhel7-weave:
474520
stage: deploy-gce-part1
475521
<<: *job

cluster.yml

+11
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@
6969
roles:
7070
- { role: kubespray-defaults}
7171
- { role: kubernetes/master, tags: master }
72+
73+
- hosts: k8s-cluster
74+
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
75+
roles:
76+
- { role: kubespray-defaults}
77+
- { role: kubernetes/kubeadm, tags: kubeadm, when: "kubeadm_enabled" }
78+
79+
- hosts: kube-master
80+
any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
81+
roles:
82+
- { role: kubespray-defaults}
7283
- { role: kubernetes-apps/network_plugin, tags: network }
7384
- { role: kubernetes-apps/policy_controller, tags: policy-controller }
7485

inventory/group_vars/all.yml

+6
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ bin_dir: /usr/local/bin
8282
#openstack_lbaas_monitor_timeout: "30s"
8383
#openstack_lbaas_monitor_max_retries: "3"
8484

85+
## Uncomment to enable experimental kubeadm deployment mode
86+
#kubeadm_enabled: false
87+
#kubeadm_token_first: "{{ lookup('password', 'credentials/kubeadm_token_first length=6 chars=ascii_letters,digits') }}"
88+
#kubeadm_token_second: "{{ lookup('password', 'credentials/kubeadm_token_second length=16 chars=ascii_letters,digits') }}"
89+
#kubeadm_token: "{{ kubeadm_token_first }}.{{ kubeadm_token_second }}"
90+
#
8591
## Set these proxy values in order to update docker daemon to use proxies
8692
#http_proxy: ""
8793
#https_proxy: ""

library/kube.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -135,24 +135,27 @@ def _execute_nofail(self, cmd):
135135
return None
136136
return out.splitlines()
137137

138-
def create(self, check=True):
138+
def create(self, check=True, force=True):
139139
if check and self.exists():
140140
return []
141141

142142
cmd = ['apply']
143143

144+
if force:
145+
cmd.append('--force')
146+
144147
if not self.filename:
145148
self.module.fail_json(msg='filename required to create')
146149

147150
cmd.append('--filename=' + self.filename)
148151

149152
return self._execute(cmd)
150153

151-
def replace(self):
154+
def replace(self, force=True):
152155

153156
cmd = ['apply']
154157

155-
if self.force:
158+
if force:
156159
cmd.append('--force')
157160

158161
if not self.filename:

roles/download/defaults/main.yml

+13-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ download_always_pull: False
1919

2020
# Versions
2121
kube_version: v1.7.3
22+
kubeadm_version: "{{ kube_version }}"
2223
etcd_version: v3.2.4
2324
# TODO(mattymo): Move calico versions to roles/network_plugins/calico/defaults
2425
# after migration to container download
@@ -31,11 +32,13 @@ flannel_version: "v0.8.0"
3132
flannel_cni_version: "v0.2.0"
3233
pod_infra_version: 3.0
3334

34-
# Download URL's
35+
# Download URLs
3536
etcd_download_url: "https://storage.googleapis.com/kargo/{{etcd_version}}_etcd"
37+
kubeadm_download_url: "https://storage.googleapis.com/kubernetes-release/release/{{ kubeadm_version }}/bin/linux/amd64/kubeadm"
3638

3739
# Checksums
3840
etcd_checksum: "274c46a7f8d26f7ae99d6880610f54933cbcf7f3beafa19236c52eb5df8c7a0b"
41+
kubeadm_checksum: "378e6052f8b178f8e6a38e8637681c72d389443b66b78b51b8ddc9a162c655c3"
3942

4043
# Containers
4144
# Possible values: host, docker
@@ -132,6 +135,15 @@ downloads:
132135
container: "{{ etcd_deployment_type in [ 'docker', 'rkt' ] }}"
133136
repo: "{{ etcd_image_repo }}"
134137
tag: "{{ etcd_image_tag }}"
138+
kubeadm:
139+
version: "{{ kubeadm_version }}"
140+
dest: "kubeadm"
141+
sha256: "{{ kubeadm_checksum }}"
142+
source_url: "{{ kubeadm_download_url }}"
143+
url: "{{ kubeadm_download_url }}"
144+
unarchive: false
145+
owner: "root"
146+
mode: "0755"
135147
hyperkube:
136148
container: true
137149
repo: "{{ hyperkube_image_repo }}"

roles/etcd/tasks/main.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
- name: "Gen_certs | Get etcd certificate serials"
1313
shell: "openssl x509 -in {{ etcd_cert_dir }}/node-{{ inventory_hostname }}.pem -noout -serial | cut -d= -f2"
14-
register: "node-{{ inventory_hostname }}_serial"
14+
register: "etcd_client_cert_serial"
1515
when: inventory_hostname in groups['k8s-cluster']|union(groups['etcd'])|union(groups['calico-rr']|default([]))|unique|sort
1616

1717
- include: "install_{{ etcd_deployment_type }}.yml"

roles/kubernetes-apps/ansible/tasks/main.yml

+12
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,18 @@
88
delay: 6
99
when: inventory_hostname == groups['kube-master'][0]
1010

11+
- name: kubeadm | Delete kubeadm kubedns
12+
kube:
13+
name: "kubedns"
14+
namespace: "{{ system_namespace }}"
15+
kubectl: "{{bin_dir}}/kubectl"
16+
resource: "deploy"
17+
state: absent
18+
when:
19+
- kubeadm_enabled|default(false)
20+
- kubeadm_init.changed|default(false)
21+
- inventory_hostname == groups['kube-master'][0]
22+
1123
- name: Kubernetes Apps | Lay Down KubeDNS Template
1224
template:
1325
src: "{{item.file}}"
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
- name: Set kubeadm_discovery_address
3+
set_fact:
4+
kubeadm_discovery_address: >-
5+
{%- if "127.0.0.1" or "localhost" in kube_apiserver_endpoint -%}
6+
{{ first_kube_master }}:{{ kube_apiserver_port }}
7+
{%- else -%}
8+
{{ kube_apiserver_endpoint }}
9+
{%- endif %}
10+
when: not is_kube_master
11+
tags: facts
12+
13+
- name: Create kubeadm client config
14+
template:
15+
src: kubeadm-client.conf.j2
16+
dest: "{{ kube_config_dir }}/kubeadm-client.conf"
17+
backup: yes
18+
when: not is_kube_master
19+
register: kubeadm_client_conf
20+
21+
- name: Join to cluster if needed
22+
command: kubeadm join --config {{ kube_config_dir}}/kubeadm-client.conf --skip-preflight-checks
23+
register: kubeadm_join
24+
when: not is_kube_master and kubeadm_client_conf.changed
25+
26+
- name: Update server field in kubelet kubeconfig
27+
replace:
28+
path: "{{ kube_config_dir }}/kubelet.conf"
29+
regexp: '(\s+){{ first_kube_master }}:{{ kube_apiserver_port }}(\s+.*)?$'
30+
replace: '\1{{ kube_apiserver_endpoint }}\2'
31+
backup: yes
32+
when: not is_kube_master and kubeadm_discovery_address != kube_apiserver_endpoint
33+
34+
# FIXME(mattymo): Reconcile kubelet kubeconfig filename for both deploy modes
35+
- name: Symlink kubelet kubeconfig for calico/canal
36+
file:
37+
src: "{{ kube_config_dir }}//kubelet.conf"
38+
dest: "{{ kube_config_dir }}/node-kubeconfig.yaml"
39+
state: link
40+
force: yes
41+
when: kube_network_plugin in ['calico','canal']
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
apiVersion: kubeadm.k8s.io/v1alpha1
2+
kind: NodeConfiguration
3+
caCertPath: {{ kube_config_dir }}/ssl/ca.crt
4+
token: {{ kubeadm_token }}
5+
discoveryTokenAPIServers:
6+
- {{ kubeadm_discovery_address | replace("https://", "")}}

roles/kubernetes/master/defaults/main.yml

+4
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,7 @@ apiserver_custom_flags: []
6666
controller_mgr_custom_flags: []
6767

6868
scheduler_custom_flags: []
69+
70+
# kubeadm settings
71+
# Value of 0 means it never expires
72+
kubeadm_token_ttl: 0

roles/kubernetes/master/handlers/main.yml

+4
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,7 @@
4444
until: result.status == 200
4545
retries: 20
4646
delay: 6
47+
48+
- name: Master | set secret_changed
49+
set_fact:
50+
secret_changed: true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
- name: kubeadm | aggregate all SANs
3+
set_fact:
4+
apiserver_sans: >-
5+
kubernetes
6+
kubernetes.default
7+
kubernetes.default.svc
8+
kubernetes.default.svc.{{ dns_domain }}
9+
{{ kube_apiserver_ip }}
10+
localhost
11+
127.0.0.1
12+
{{ ' '.join(groups['kube-master']) }}
13+
{%- if loadbalancer_apiserver is defined and apiserver_loadbalancer_domain_name is defined %}
14+
{{ apiserver_loadbalancer_domain_name }}
15+
{%- endif %}
16+
{%- for host in groups['kube-master'] -%}
17+
{%- if hostvars[host]['access_ip'] is defined %}{{ hostvars[host]['access_ip'] }}{% endif -%}
18+
{{ hostvars[host]['ip'] | default(hostvars[host]['ansible_default_ipv4']['address']) }}
19+
{%- endfor %}
20+
tags: facts
21+
22+
- name: kubeadm | Copy etcd cert dir under k8s cert dir
23+
command: "cp -TR {{ etcd_cert_dir }} {{ kube_config_dir }}/ssl/etcd"
24+
changed_when: false
25+
26+
- name: kubeadm | Create kubeadm config
27+
template:
28+
src: kubeadm-config.yaml.j2
29+
dest: "{{ kube_config_dir }}/kubeadm-config.yaml"
30+
register: kubeadm_config
31+
32+
- name: kubeadm | Initialize cluster
33+
command: timeout -k 240s 240s kubeadm init --config={{ kube_config_dir }}/kubeadm-config.yaml --skip-preflight-checks
34+
register: kubeadm_init
35+
when: kubeadm_config.changed

0 commit comments

Comments
 (0)