diff --git a/.gitignore b/.gitignore index 4df491aa1..4791280e9 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ __pycache__/ # Distribution / packaging .Python +artifacts/ env/ build/ credentials/ diff --git a/cluster.yml b/cluster.yml index 7b842d917..d9240ac97 100644 --- a/cluster.yml +++ b/cluster.yml @@ -82,6 +82,7 @@ - { role: kubespray-defaults} - { role: kubernetes-apps/network_plugin, tags: network } - { role: kubernetes-apps/policy_controller, tags: policy-controller } + - { role: kubernetes/client, tags: client } - hosts: calico-rr any_errors_fatal: "{{ any_errors_fatal | default(true) }}" diff --git a/docs/getting-started.md b/docs/getting-started.md index 65b590a2f..f0c7c0014 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -101,3 +101,17 @@ access the Kubernetes Dashboard at the following URL: To see the password, refer to the section above, titled *Connecting to Kubernetes*. The host can be any kube-master or kube-node or loadbalancer (when enabled). + +Accessing Kubernetes API +------------------------ + +The main client of Kubernetes is `kubectl`. It is installed on each kube-master +host and can optionally be configured on your ansible host by setting +`kubeconfig_localhost: true` in the configuration. If enabled, kubectl and +admin.conf will appear in the artifacts/ directory after deployment. You can +see a list of nodes by running the following commands: + + cd artifacts/ + ./kubectl --kubeconfig admin.conf get nodes + +If desired, copy kubectl to your bin dir and admin.conf to ~/.kube/config. diff --git a/inventory/group_vars/k8s-cluster.yml b/inventory/group_vars/k8s-cluster.yml index bdcca73d4..c185fe46c 100644 --- a/inventory/group_vars/k8s-cluster.yml +++ b/inventory/group_vars/k8s-cluster.yml @@ -152,6 +152,11 @@ efk_enabled: false # Helm deployment helm_enabled: false +# Make a copy of kubeconfig on the host that runs Ansible in GITDIR/artifacts +# kubeconfig_localhost: false +# Download kubectl onto the host that runs Ansible in GITDIR/artifacts +# kubectl_localhost: false + # dnsmasq # dnsmasq_upstream_dns_servers: # - /resolvethiszone.with/10.0.4.250 diff --git a/roles/kubernetes/client/defaults/main.yml b/roles/kubernetes/client/defaults/main.yml new file mode 100644 index 000000000..5864e991f --- /dev/null +++ b/roles/kubernetes/client/defaults/main.yml @@ -0,0 +1,7 @@ +--- +kubeconfig_localhost: false +kubectl_localhost: false +artifacts_dir: "./artifacts" + +kube_config_dir: "/etc/kubernetes" +kube_apiserver_port: "6443" diff --git a/roles/kubernetes/client/tasks/main.yml b/roles/kubernetes/client/tasks/main.yml new file mode 100644 index 000000000..06df5af68 --- /dev/null +++ b/roles/kubernetes/client/tasks/main.yml @@ -0,0 +1,66 @@ +--- +- name: Set first kube master + set_fact: + first_kube_master: "{{ hostvars[groups['kube-master'][0]]['access_ip'] | default(hostvars[groups['kube-master'][0]]['ip'] | default(hostvars[groups['kube-master'][0]]['ansible_default_ipv4']['address'])) }}" + +- name: Set external kube-apiserver endpoint + set_fact: + external_apiserver_endpoint: >- + {%- if loadbalancer_apiserver is defined and loadbalancer_apiserver.port is defined -%} + https://{{ apiserver_loadbalancer_domain_name|default('lb-apiserver.kubernetes.local') }}:{{ loadbalancer_apiserver.port|default(kube_apiserver_port) }} + {%- else -%} + https://{{ first_kube_master }}:{{ kube_apiserver_port }} + {%- endif -%} + tags: facts + +- name: Gather certs for admin kubeconfig + slurp: + src: "{{ item }}" + delegate_to: "{{ groups['kube-master'][0] }}" + delegate_facts: no + register: admin_certs + with_items: + - "{{ kube_cert_dir }}/ca.pem" + - "{{ kube_cert_dir }}/admin-{{ inventory_hostname }}.pem" + - "{{ kube_cert_dir }}/admin-{{ inventory_hostname }}-key.pem" + when: not kubeadm_enabled|d(false)|bool + +- name: Write admin kubeconfig + template: + src: admin.conf.j2 + dest: "{{ kube_config_dir }}/admin.conf" + when: not kubeadm_enabled|d(false)|bool + +- name: Create kube config dir + file: + path: "/root/.kube" + mode: "0700" + state: directory + +- name: Copy admin kubeconfig to root user home + copy: + src: "{{ kube_config_dir }}/admin.conf" + dest: "/root/.kube/config" + remote_src: yes + mode: "0700" + backup: yes + +- name: Copy admin kubeconfig to ansible host + fetch: + src: "{{ kube_config_dir }}/admin.conf" + dest: "{{ artifacts_dir }}/admin.conf" + flat: yes + validate_checksum: no + become: no + run_once: yes + when: kubeconfig_localhost|default(false) + +- name: Copy kubectl binary to ansible host + fetch: + src: "{{ bin_dir }}/kubectl" + dest: "{{ artifacts_dir }}/kubectl" + flat: yes + validate_checksum: no + become: no + run_once: yes + when: kubectl_localhost|default(false) diff --git a/roles/kubernetes/client/templates/admin.conf.j2 b/roles/kubernetes/client/templates/admin.conf.j2 new file mode 100644 index 000000000..b1640c1c5 --- /dev/null +++ b/roles/kubernetes/client/templates/admin.conf.j2 @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Config +current-context: admin-{{ cluster_name }} +preferences: {} +clusters: +- cluster: + certificate-authority-data: {{ admin_certs.results[0]['content'] }} + server: {{ external_apiserver_endpoint }} + name: {{ cluster_name }} +contexts: +- context: + cluster: {{ cluster_name }} + user: admin-{{ cluster_name }} + name: admin-{{ cluster_name }} +users: +- name: admin-{{ cluster_name }} + user: + client-certificate-data: {{ admin_certs.results[1]['content'] }} + client-key-data: {{ admin_certs.results[2]['content'] }} diff --git a/roles/kubespray-defaults/defaults/main.yaml b/roles/kubespray-defaults/defaults/main.yaml index 5bd2fdc14..3c07147da 100644 --- a/roles/kubespray-defaults/defaults/main.yaml +++ b/roles/kubespray-defaults/defaults/main.yaml @@ -118,6 +118,11 @@ vault_deployment_type: docker kubeadm_enabled: false kubeadm_token: "abcdef.0123456789abcdef" +# Make a copy of kubeconfig on the host that runs Ansible in GITDIR/artifacts +kubeconfig_localhost: false +# Download kubectl onto the host that runs Ansible in GITDIR/artifacts +kubectl_localhost: false + # K8s image pull policy (imagePullPolicy) k8s_image_pull_policy: IfNotPresent efk_enabled: false diff --git a/tests/cloud_playbooks/create-gce.yml b/tests/cloud_playbooks/create-gce.yml index 2b4822723..11cd9a646 100644 --- a/tests/cloud_playbooks/create-gce.yml +++ b/tests/cloud_playbooks/create-gce.yml @@ -63,4 +63,4 @@ gather_facts: false tasks: - name: Wait for SSH to come up. - local_action: wait_for host={{inventory_hostname}} port=22 delay=60 timeout=240 state=started + local_action: wait_for host={{ansible_host}} port=22 delay=60 timeout=240 state=started diff --git a/upgrade-cluster.yml b/upgrade-cluster.yml index 3dcb69f29..b83681525 100644 --- a/upgrade-cluster.yml +++ b/upgrade-cluster.yml @@ -89,6 +89,7 @@ - { role: kubespray-defaults} - { role: kubernetes-apps/network_plugin, tags: network } - { role: kubernetes-apps/policy_controller, tags: policy-controller } + - { role: kubernetes/client, tags: client } - hosts: calico-rr any_errors_fatal: "{{ any_errors_fatal | default(true) }}"