From 73066f308dd655f7b749d0672bfe87b9909f19fe Mon Sep 17 00:00:00 2001 From: Matthew Mosesohn Date: Wed, 28 Sep 2016 14:05:08 +0300 Subject: [PATCH] use nginx proxy on non-master nodes to proxy apiserver traffic Also adds all masters by hostname and localhost/127.0.0.1 to apiserver SSL certificate. Includes documentation update on how localhost loadbalancer works. --- docs/figures/loadbalancer_localhost.png | Bin 0 -> 58266 bytes docs/ha-mode.md | 56 +++++++----------- inventory/group_vars/all.yml | 5 +- roles/kubernetes/node/defaults/main.yml | 3 + roles/kubernetes/node/tasks/main.yml | 3 + roles/kubernetes/node/tasks/nginx-proxy.yml | 9 +++ .../manifests/nginx-proxy.manifest.j2 | 20 +++++++ roles/kubernetes/node/templates/nginx.conf.j2 | 26 ++++++++ roles/kubernetes/preinstall/defaults/main.yml | 2 + .../kubernetes/preinstall/tasks/set_facts.yml | 8 +-- roles/kubernetes/secrets/files/make-ssl.sh | 7 ++- roles/kubernetes/secrets/tasks/gen_certs.yml | 27 +++++++++ .../secrets/templates/openssl.conf.j2 | 10 ++-- 13 files changed, 129 insertions(+), 47 deletions(-) create mode 100644 docs/figures/loadbalancer_localhost.png create mode 100644 roles/kubernetes/node/tasks/nginx-proxy.yml create mode 100644 roles/kubernetes/node/templates/manifests/nginx-proxy.manifest.j2 create mode 100644 roles/kubernetes/node/templates/nginx.conf.j2 diff --git a/docs/figures/loadbalancer_localhost.png b/docs/figures/loadbalancer_localhost.png new file mode 100644 index 0000000000000000000000000000000000000000..0732d5489a919007e65f58f15ac0e181b612e7ee GIT binary patch literal 58266 zcmeFZWmr{R)HVu;l1hn63cBeM36W0On^d|(x*Mb$1f{#XJEc(&5D<{=?(UF0a~sd| zeDArwpXblH-d`fR)|zX~F-P3@JyyVLDbc&=gy;we2zOynVHpI3Tj2-@Na?6|z;7~L z7BLVI?uo`JZTcq$oKqfSvk9ty5WO|towX)==V9d|btJEnhueC*42lY#D)H5dJu^UwFGZekg zVg>$JNJr`K-EqeFz62&`Gh!VG7kw(>7Q0UWswfhrrhXxyRJyZq;v5j0vwbG7U7)vh zSi*XMarFe^cP)d;;oc$AFm&U8z{7o@SJW}z_v|tTnXrUUDtUOa=90Ph@UkcR?6RnX zZ^d5v=i>t6j)P6ef%gF)b;7V!?N^?$)a%GhpWycokRN_v=(H#w8LXyiBpS9-3i#$L zr|cuuAZ%rgcYGO^Cw)kDOm;B;sL9TV#+4SZu7|VMJbkAVFWa<9`4XxL|aY0 zSfrLn!$H?hZsl2T5B`jYfy2>4i0q{Beey|vmFSFtF=iK!{1eK8XTgUho<{1qc8tR0 z&&bT%s{>BUgapk3)B*=Gi>*du(3BWH=bN5Um=1q@wQtlxyy|c#(tJ4n(9>Wq%dM;Q z8>QKnwea`00C}km_7nRBan|%8XlDq|$~?VsHud#X?sE-M{FVr7e`1|SMc&r5S*Fu| z)7KvZwGA(d_mnem?<+z5JXz5@$uq~U0isN4uNsP5EKEUa1mt0-28`T^ygYot z`&Za;S@=HT;&Eaf!H*jAOiZ|Q1jiZ2v`n53n3;`i-KFQ)b{59U7HV)CDC%cu_BFAwYn z4lfQi#pS-N_1UfXv;V& z_Y3W27&Pib40Df^t#4RU|J^Fi0~x~%J$;H7<-|z^gkj;VagjOJc4xebe$E;pv*x9% zK?d6|X7t$Wn#+3_2jp~V_QC}hbIHl%bIQKTkblX+-z>dXgP>Pi5+wdQ5Ha=pS<3*1 zXO)hg#8!0ndRmdJcF$g$HxcUMEqC5gL9HJsg0Pp-n>jL10&OrH85OHH^3mc}XwOfQ zH>aOtrS@6-*4xrtlC)>T+MUVZ=Qc%`3G9x*q^0r|lamvNlb^CV3F z+KFTT^_5n6eKUui)rCiL49GQcDZFzTZ>Vd=3%QLnE=h#^^ zxhGeb(U12nFP>8zbAA_J?){*>#6fu`efWI2?DCO7_3G&R%q0<4DqX$lg2Ptq5E-&cyW-5$ca6Kj9(U4{u6OO(hJQ zVx(V;LOI@xRv1Klc(!Gg!@x5a@5l)=rz7dN;Xf-uvtr(&eZqHMMDR@O!LtvKuy4JcYfe6I;yoeg zjmz6vPaYh!8MU+OvCOX9D5^Jh+F1XzQAF{8L8bB=6x#yYLdf5nm?&A-{qcncg5+9^CXGG zly*0Lg@iJ7>v3NS->gcd;Tr`*PNs6rN(A2&CGh zkwHv8?HV}}AiKDYS=7wm;W}T-*j`O>w`V)vnV!7f4{;w07iUy{)$;*kTm?T|(`Dbc zsOfy;WHE$Kg_&8CeT$a%vw@nz8=L%rA!D3y7x!|O2C?JYvzuE-_|d>+kHHfNaIoJC zqz++SWW{J0Q>D0At9N!hc5euJ#GIZ?#qz4kE@m!_wSGN2A(2B-5XyM%fk?UR(z>9j z${-lND}Bi;b>1c8`ex&l(#V+_3wXB&6QWNh6U~7DnQ-bD)|1*O!WOn8I~nFl-NgJ+L^s?t}?z z!PKaF)x9S(gge(`kp3VMWdH7)>{$BGpg!j+_oVrc4ccUXsb&<9?U~Z~ORe z8V(=jPhl`M{NS|P7$U>cOlVOfq@~^pIAmae z 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:8080 - server master2 :8080 - balance leastconn -``` - -And the corresponding example global vars config: -``` -loadbalancer_apiserver_localhost: true -``` - -This var overrides an external LB configuration, if any. Note that for this -example, the `kubernetes-apiserver-http` endpoint has backends receiving -unencrypted traffic, which may be a security issue when interconnecting -different nodes, or may be not, if those belong to the isolated management -network without external access. +Specifying an external LB overrides any internal localhost LB configuration. +Note that for this example, the `kubernetes-apiserver-http` endpoint +has backends receiving unencrypted traffic, which may be a security issue +when interconnecting different nodes, or maybe not, if those belong to the +isolated management network without external access. In order to achieve HA for HAProxy instances, those must be running on the each node in the `k8s-cluster` group as well, but require no VIP, thus @@ -109,8 +97,8 @@ Access endpoints are evaluated automagically, as the following: | Endpoint type | kube-master | non-master | |------------------------------|---------------|---------------------| -| Local LB (overrides ext) | http://lc:p | http://lc:p | -| External LB, no internal | https://lb:lp | https://lb:lp | +| Local LB | http://lc:p | http://lc:sp | +| External LB, no internal | http://lc:p | https://lb:lp | | No ext/int LB (default) | http://lc:p | https://m[0].aip:sp | Where: diff --git a/inventory/group_vars/all.yml b/inventory/group_vars/all.yml index add9fdd2a..ec715b960 100644 --- a/inventory/group_vars/all.yml +++ b/inventory/group_vars/all.yml @@ -64,8 +64,9 @@ ndots: 5 # This may be the case if clients support and loadbalance multiple etcd servers natively. etcd_multiaccess: false -# Assume there are no internal loadbalancers for apiservers exist -loadbalancer_apiserver_localhost: false +# Assume there are no internal loadbalancers for apiservers exist and listen on +# kube_apiserver_port (default 443) +loadbalancer_apiserver_localhost: true # Choose network plugin (calico, weave or flannel) kube_network_plugin: flannel diff --git a/roles/kubernetes/node/defaults/main.yml b/roles/kubernetes/node/defaults/main.yml index 94da756be..79b1faef0 100644 --- a/roles/kubernetes/node/defaults/main.yml +++ b/roles/kubernetes/node/defaults/main.yml @@ -11,3 +11,6 @@ kube_proxy_mode: iptables # kube_api_runtime_config: # - extensions/v1beta1/daemonsets=true # - extensions/v1beta1/deployments=true + +nginx_image_repo: nginx +nginx_image_tag: 1.11.4-alpine diff --git a/roles/kubernetes/node/tasks/main.yml b/roles/kubernetes/node/tasks/main.yml index 9c14e7a4c..a8cb6ce5a 100644 --- a/roles/kubernetes/node/tasks/main.yml +++ b/roles/kubernetes/node/tasks/main.yml @@ -1,6 +1,9 @@ --- - include: install.yml +- include: nginx-proxy.yml + when: is_kube_master == false and loadbalancer_apiserver_localhost|default(false) + - name: Write Calico cni config template: src: "cni-calico.conf.j2" diff --git a/roles/kubernetes/node/tasks/nginx-proxy.yml b/roles/kubernetes/node/tasks/nginx-proxy.yml new file mode 100644 index 000000000..056c55a93 --- /dev/null +++ b/roles/kubernetes/node/tasks/nginx-proxy.yml @@ -0,0 +1,9 @@ +--- +- name: nginx-proxy | Write static pod + template: src=manifests/nginx-proxy.manifest.j2 dest=/etc/kubernetes/manifests/nginx-proxy.yml + +- name: nginx-proxy | Make nginx directory + file: path=/etc/nginx state=directory mode=0700 owner=root + +- name: nginx-proxy | Write nginx-proxy configuration + template: src=nginx.conf.j2 dest="/etc/nginx/nginx.conf" owner=root mode=0755 backup=yes diff --git a/roles/kubernetes/node/templates/manifests/nginx-proxy.manifest.j2 b/roles/kubernetes/node/templates/manifests/nginx-proxy.manifest.j2 new file mode 100644 index 000000000..50e054268 --- /dev/null +++ b/roles/kubernetes/node/templates/manifests/nginx-proxy.manifest.j2 @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx-proxy + namespace: kube-system +spec: + hostNetwork: true + containers: + - name: nginx-proxy + image: {{ nginx_image_repo }}:{{ nginx_image_tag }} + securityContext: + privileged: true + volumeMounts: + - mountPath: /etc/nginx + name: etc-nginx + readOnly: true + volumes: + - name: etc-nginx + hostPath: + path: /etc/nginx diff --git a/roles/kubernetes/node/templates/nginx.conf.j2 b/roles/kubernetes/node/templates/nginx.conf.j2 new file mode 100644 index 000000000..edcee08a9 --- /dev/null +++ b/roles/kubernetes/node/templates/nginx.conf.j2 @@ -0,0 +1,26 @@ +error_log stderr notice; + +worker_processes auto; +events { + multi_accept on; + use epoll; + worker_connections 1024; +} + +stream { + upstream kube_apiserver { + least_conn; + {% for host in groups['kube-master'] -%} + server {{ hostvars[host]['access_ip'] | default(hostvars[host]['ip'] | default(hostvars[host]['ansible_default_ipv4']['address'])) }}:{{ kube_apiserver_port }}; + {% endfor %} + } + + server { + listen {{ kube_apiserver_port }}; + proxy_pass kube_apiserver; + proxy_timeout 3s; + proxy_connect_timeout 1s; + + } + +} diff --git a/roles/kubernetes/preinstall/defaults/main.yml b/roles/kubernetes/preinstall/defaults/main.yml index 343ba5707..5d1b2cd2e 100644 --- a/roles/kubernetes/preinstall/defaults/main.yml +++ b/roles/kubernetes/preinstall/defaults/main.yml @@ -21,6 +21,8 @@ kube_log_dir: "/var/log/kubernetes" # pods on startup kube_manifest_dir: "{{ kube_config_dir }}/manifests" +# change to 0.0.0.0 to enable insecure access from anywhere (not recommended) +kube_apiserver_insecure_bind_address: 127.0.0.1 common_required_pkgs: - python-httplib2 diff --git a/roles/kubernetes/preinstall/tasks/set_facts.yml b/roles/kubernetes/preinstall/tasks/set_facts.yml index e3f4757a7..19f08df78 100644 --- a/roles/kubernetes/preinstall/tasks/set_facts.yml +++ b/roles/kubernetes/preinstall/tasks/set_facts.yml @@ -5,12 +5,12 @@ - set_fact: is_kube_master="{{ inventory_hostname in groups['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'])) }}" - set_fact: - kube_apiserver_insecure_bind_address: |- - {% if loadbalancer_apiserver_localhost %}{{ kube_apiserver_address }}{% else %}127.0.0.1{% endif %} + loadbalancer_apiserver_localhost: false + when: loadbalancer_apiserver is defined - set_fact: kube_apiserver_endpoint: |- - {% if loadbalancer_apiserver_localhost -%} - http://127.0.0.1:{{ kube_apiserver_insecure_port }} + {% if not is_kube_master and loadbalancer_apiserver_localhost -%} + https://localhost:{{ kube_apiserver_port }} {%- elif is_kube_master and loadbalancer_apiserver is not defined -%} http://127.0.0.1:{{ kube_apiserver_insecure_port }} {%- else -%} diff --git a/roles/kubernetes/secrets/files/make-ssl.sh b/roles/kubernetes/secrets/files/make-ssl.sh index a2f698541..f90fb7e8b 100755 --- a/roles/kubernetes/secrets/files/make-ssl.sh +++ b/roles/kubernetes/secrets/files/make-ssl.sh @@ -26,8 +26,8 @@ Usage : $(basename $0) -f [-d ] -h | --help : Show this message -f | --config : Openssl configuration file -d | --ssldir : Directory where the certificates will be installed - - ex : + + ex : $(basename $0) -f openssl.conf -d /srv/ssl EOF } @@ -37,7 +37,7 @@ while (($#)); do case "$1" in -h | --help) usage; exit 0;; -f | --config) CONFIG=${2}; shift 2;; - -d | --ssldir) SSLDIR="${2}"; shift 2;; + -d | --ssldir) SSLDIR="${2}"; shift 2;; *) usage echo "ERROR : Unknown option" @@ -68,6 +68,7 @@ openssl req -x509 -new -nodes -key ca-key.pem -days 10000 -out ca.pem -subj "/CN openssl genrsa -out apiserver-key.pem 2048 > /dev/null 2>&1 openssl req -new -key apiserver-key.pem -out apiserver.csr -subj "/CN=kube-apiserver" -config ${CONFIG} > /dev/null 2>&1 openssl x509 -req -in apiserver.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out apiserver.pem -days 365 -extensions v3_req -extfile ${CONFIG} > /dev/null 2>&1 +cat ca.pem >> apiserver.pem # Nodes and Admin for i in node admin; do diff --git a/roles/kubernetes/secrets/tasks/gen_certs.yml b/roles/kubernetes/secrets/tasks/gen_certs.yml index 7178bce0c..6057c0676 100644 --- a/roles/kubernetes/secrets/tasks/gen_certs.yml +++ b/roles/kubernetes/secrets/tasks/gen_certs.yml @@ -65,3 +65,30 @@ shell: chmod 0600 {{ kube_cert_dir}}/*key.pem when: inventory_hostname in groups['kube-master'] changed_when: false + +- name: Gen_certs | target ca-certificates directory + set_fact: + ca_cert_dir: |- + {% if ansible_os_family == "Debian" -%} + /usr/local/share/ca-certificates + {%- elif ansible_os_family == "RedHat" -%} + /etc/pki/ca-trust/source/anchors + {%- elif ansible_os_family == "CoreOS" -%} + /etc/ssl/certs + {%- endif %} + +- name: Gen_certs | add CA to trusted CA dir + copy: + src: "{{ kube_cert_dir }}/ca.pem" + dest: "{{ ca_cert_dir }}/kube-ca.crt" + remote_src: true + register: kube_ca_cert + +- name: Gen_certs | update ca-certificates (Debian/Ubuntu/CoreOS) + command: update-ca-certificates + when: kube_ca_cert.changed and ansible_os_family in ["Debian", "CoreOS"] + +- name: Gen_certs | update ca-certificatesa (RedHat) + command: update-ca-trust extract + when: kube_ca_cert.changed and ansible_os_family == "RedHat" + diff --git a/roles/kubernetes/secrets/templates/openssl.conf.j2 b/roles/kubernetes/secrets/templates/openssl.conf.j2 index 5eab64979..ac94b6800 100644 --- a/roles/kubernetes/secrets/templates/openssl.conf.j2 +++ b/roles/kubernetes/secrets/templates/openssl.conf.j2 @@ -11,16 +11,18 @@ DNS.1 = kubernetes DNS.2 = kubernetes.default DNS.3 = kubernetes.default.svc DNS.4 = kubernetes.default.svc.{{ dns_domain }} +DNS.5 = localhost {% for host in groups['kube-master'] %} -DNS.{{ 4 + loop.index }} = {{ host }} +DNS.{{ 5 + loop.index }} = {{ host }} {% endfor %} {% if loadbalancer_apiserver is defined and apiserver_loadbalancer_domain_name is defined %} -{% set idx = groups['kube-master'] | length | int + 4 %} -DNS.5 = {{ apiserver_loadbalancer_domain_name }} +{% set idx = groups['kube-master'] | length | int + 5 %} +DNS.{{ idx | string }} = {{ apiserver_loadbalancer_domain_name }} {% endif %} {% for host in groups['kube-master'] %} IP.{{ 2 * loop.index - 1 }} = {{ hostvars[host]['access_ip'] | default(hostvars[host]['ansible_default_ipv4']['address']) }} IP.{{ 2 * loop.index }} = {{ hostvars[host]['ip'] | default(hostvars[host]['ansible_default_ipv4']['address']) }} {% endfor %} {% set idx = groups['kube-master'] | length | int * 2 + 1 %} -IP.{{ idx | string }} = {{ kube_apiserver_ip }} +IP.{{ idx }} = {{ kube_apiserver_ip }} +IP.{{ idx + 1 }} = 127.0.0.1