diff --git a/docs/ha-mode.md b/docs/ha-mode.md
index 792c18a19fb6f1a4d1b1855c96c3815046ae66ea..8ec5c93a169d0048bb9dcc0394ac675ef6726321 100644
--- a/docs/ha-mode.md
+++ b/docs/ha-mode.md
@@ -5,10 +5,6 @@ The following components require a highly available endpoints:
 * etcd cluster,
 * kube-apiserver service instances.
 
-The former provides the
-[etcd-proxy](https://coreos.com/etcd/docs/latest/proxy.html) service to access
-the cluster members in HA fashion.
-
 The latter relies on a 3rd side reverse proxies, like Nginx or HAProxy, to
 achieve the same goal.
 
@@ -57,7 +53,7 @@ type. The following diagram shows how traffic to the apiserver is directed.
 
 A user may opt to use an external loadbalancer (LB) instead. An external LB
 provides access for external clients, while the internal LB accepts client
-connections only to the localhost, similarly to the etcd-proxy HA endpoints.
+connections only to the localhost.
 Given a frontend `VIP` address and `IP1, IP2` addresses of backends, here is
 an example configuration for a HAProxy service acting as an external LB:
 ```
diff --git a/inventory/group_vars/all.yml b/inventory/group_vars/all.yml
index cbf2e63a2b6d9422be2da212811973ba5563a36c..f72276ae6e9437aaa52a170959d4326ae3094866 100644
--- a/inventory/group_vars/all.yml
+++ b/inventory/group_vars/all.yml
@@ -62,7 +62,7 @@ ndots: 5
 # Enable multiaccess to configure clients to access all of the etcd members directly
 # as the "http://hostX:port, http://hostY:port, ..." and ignore the proxy loadbalancers.
 # This may be the case if clients support and loadbalance multiple etcd servers  natively.
-etcd_multiaccess: false
+etcd_multiaccess: true
 
 # Assume there are no internal loadbalancers for apiservers exist and listen on
 # kube_apiserver_port (default 443)
diff --git a/roles/etcd/handlers/main.yml b/roles/etcd/handlers/main.yml
index 693754a06364419e0f6750fbb83c6affdd4969fb..8104ff1a86e9f25fdb4796fc8241b96488575c6f 100644
--- a/roles/etcd/handlers/main.yml
+++ b/roles/etcd/handlers/main.yml
@@ -6,21 +6,14 @@
     - reload etcd
     - wait for etcd up
 
-- name: restart etcd-proxy
-  command: /bin/true
-  notify:
-    - etcd | reload systemd
-    - reload etcd-proxy
-    - wait for etcd up
-
 - name: etcd | reload systemd
   command: systemctl daemon-reload
   when: ansible_service_mgr == "systemd"
 
 - name: wait for etcd up
-  uri: url="http://{% if is_etcd_master %}{{ etcd_address }}{% else %}127.0.0.1{% endif %}:2379/health"
+  uri: url="http://{% if is_etcd_master %}{{ etcd_address }}{% else %}127.0.0.1{% endif %}:2379/health" 
   register: result
-  until: result.status == 200
+  until: result.status is defined and result.status == 200
   retries: 10
   delay: 5
 
@@ -29,9 +22,3 @@
     name: etcd
     state: restarted
   when: is_etcd_master
-
-- name: reload etcd-proxy
-  service:
-    name: etcd-proxy
-    state: restarted
-  when: is_etcd_proxy
diff --git a/roles/etcd/tasks/configure.yml b/roles/etcd/tasks/configure.yml
index 514a79d731515bb8db0facbf04847969fbb86558..a2ef38f2c7b3281aa8f1e526d0b0a11d1c4806e0 100644
--- a/roles/etcd/tasks/configure.yml
+++ b/roles/etcd/tasks/configure.yml
@@ -26,19 +26,3 @@
     mode: 0755
   when: ansible_service_mgr in ["sysvinit","upstart"] and ansible_os_family == "Debian" and is_etcd_master
   notify: restart etcd
-
-- name: Configure | Copy etcd-proxy.service systemd file
-  template:
-    src: "etcd-proxy-{{ etcd_deployment_type }}.service.j2"
-    dest: /etc/systemd/system/etcd-proxy.service
-    backup: yes
-  when: ansible_service_mgr == "systemd" and is_etcd_proxy
-  notify: restart etcd-proxy
-- name: Configure | Write etcd-proxy initd script
-  template:
-    src: "deb-etcd-proxy-{{ etcd_deployment_type }}.initd.j2"
-    dest: /etc/init.d/etcd-proxy
-    owner: root
-    mode: 0755
-  when: ansible_service_mgr in ["sysvinit","upstart"] and ansible_os_family == "Debian" and is_etcd_proxy
-  notify: restart etcd-proxy
diff --git a/roles/etcd/tasks/main.yml b/roles/etcd/tasks/main.yml
index 3ecaa00e6ff80fccda66a68e8f6f588cb7d2ad3e..88dfe59d8ffb48872e13ded6a24de0f741a037fe 100644
--- a/roles/etcd/tasks/main.yml
+++ b/roles/etcd/tasks/main.yml
@@ -1,8 +1,13 @@
 ---
+- include: pre_upgrade.yml
 - include: install.yml
+  when: is_etcd_master
 - include: set_cluster_health.yml
+  when: is_etcd_master
 - include: configure.yml
+  when: is_etcd_master
 - include: refresh_config.yml
+  when: is_etcd_master
 
 - name: Ensure etcd is running
   service:
@@ -11,23 +16,11 @@
     enabled: yes
   when: is_etcd_master
 
-- name: Ensure etcd-proxy is running
-  service:
-    name: etcd-proxy
-    state: started
-    enabled: yes
-  when: is_etcd_proxy
-
 - name: Restart etcd if binary changed
   command: /bin/true
   notify: restart etcd
   when: etcd_deployment_type == "host" and etcd_copy.stdout_lines and is_etcd_master
 
-- name: Restart etcd-proxy if binary changed
-  command: /bin/true
-  notify: restart etcd-proxy
-  when: etcd_deployment_type == "host" and etcd_copy.stdout_lines and is_etcd_proxy
-
 # Reload systemd before starting service
 - meta: flush_handlers
 
@@ -35,4 +28,6 @@
 # initial state of the cluster is in `existing`
 # state insted of `new`.
 - include: set_cluster_health.yml
+  when: is_etcd_master
 - include: refresh_config.yml
+  when: is_etcd_master
diff --git a/roles/etcd/tasks/refresh_config.yml b/roles/etcd/tasks/refresh_config.yml
index 178466153d2600fae342e430416eaca0e7cbf291..80a03a7d6feb3f13781f87d904ecd71e49e7bf80 100644
--- a/roles/etcd/tasks/refresh_config.yml
+++ b/roles/etcd/tasks/refresh_config.yml
@@ -5,10 +5,3 @@
     dest: /etc/etcd.env
   notify: restart etcd
   when: is_etcd_master
-
-- name: Refresh config | Create etcd-proxy config file
-  template:
-    src: etcd-proxy.j2
-    dest: /etc/etcd-proxy.env
-  notify: restart etcd-proxy
-  when: is_etcd_proxy
diff --git a/roles/etcd/templates/deb-etcd-proxy-docker.initd.j2 b/roles/etcd/templates/deb-etcd-proxy-docker.initd.j2
deleted file mode 100644
index ad0338a09d72b581bce07510b31a161e1a03e666..0000000000000000000000000000000000000000
--- a/roles/etcd/templates/deb-etcd-proxy-docker.initd.j2
+++ /dev/null
@@ -1,120 +0,0 @@
-#!/bin/sh
-set -a
-
-### BEGIN INIT INFO
-# Provides:   etcd-proxy
-# Required-Start:    $local_fs $network $syslog
-# Required-Stop:
-# Default-Start:     2 3 4 5
-# Default-Stop:      0 1 6
-# Short-Description: etcd-proxy
-# Description:
-#   etcd-proxy is a proxy for etcd: distributed, consistent key-value store for shared configuration and service discovery
-### END INIT INFO
-
-PATH=/sbin:/usr/sbin:/bin/:/usr/bin
-DESC="etcd-proxy"
-NAME=etcd-proxy
-DAEMON={{ docker_bin_dir | default("/usr/bin") }}/docker
-DAEMON_EXEC=`basename $DAEMON`
-DAEMON_ARGS="run --restart=always --env-file=/etc/etcd-proxy.env \
---net=host \
---stop-signal=SIGKILL \
--v /usr/share/ca-certificates/:/etc/ssl/certs:ro \
---name={{ etcd_proxy_member_name | default("etcd-proxy") }} \
-{{ etcd_image_repo }}:{{ etcd_image_tag }} \
-{% if etcd_after_v3 %}
-{{ etcd_container_bin_dir }}etcd
-{% endif %}"
-
-
-SCRIPTNAME=/etc/init.d/$NAME
-DAEMON_USER=root
-STOP_SCHEDULE="${STOP_SCHEDULE:-QUIT/5/TERM/5/KILL/5}"
-PID=/var/run/etcd-proxy.pid
-
-# Exit if the binary is not present
-[ -x "$DAEMON" ] || exit 0
-
-# Define LSB log_* functions.
-# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
-# and status_of_proc is working.
-. /lib/lsb/init-functions
-
-do_status()
-{
-    status_of_proc -p $PID "$DAEMON" "$NAME" && exit 0 || exit $?
-}
-
-# Function that starts the daemon/service
-#
-do_start()
-{
-    {{ docker_bin_dir | default("/usr/bin") }}/docker rm -f {{ etcd_proxy_member_name | default("etcd-proxy") }} &>/dev/null || true
-    sleep 1
-    start-stop-daemon --background --start --quiet --make-pidfile --pidfile $PID --user $DAEMON_USER --exec $DAEMON -- \
-        $DAEMON_ARGS \
-        || return 2
-}
-
-#
-# Function that stops the daemon/service
-#
-do_stop()
-{
-    start-stop-daemon --stop --quiet --retry=$STOP_SCHEDULE --pidfile $PID --name $DAEMON_EXEC
-    RETVAL="$?"
-
-    sleep 1
-    return "$RETVAL"
-}
-
-
-case "$1" in
-  start)
-        log_daemon_msg "Starting $DESC" "$NAME"
-        do_start
-        case "$?" in
-                0|1) log_end_msg 0 || exit 0 ;;
-                2) log_end_msg 1 || exit 1 ;;
-        esac
-        ;;
-  stop)
-        log_daemon_msg "Stopping $DESC" "$NAME"
-        if do_stop; then
-            log_end_msg 0
-        else
-            log_failure_msg "Can't stop etcd-proxy"
-            log_end_msg 1
-        fi
-        ;;
-  status)
-        if do_status; then
-            log_end_msg 0
-        else
-            log_failure_msg "etcd-proxy is not running"
-            log_end_msg 1
-        fi
-        ;;
-
-  restart|force-reload)
-        log_daemon_msg "Restarting $DESC" "$NAME"
-        if do_stop; then
-            if do_start; then
-                log_end_msg 0
-                exit 0
-            else
-                rc="$?"
-            fi
-        else
-           rc="$?"
-        fi
-        log_failure_msg "Can't restart etcd-proxy"
-        log_end_msg ${rc}
-        ;;
-  *)
-        echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
-        exit 3
-        ;;
-esac
-
diff --git a/roles/etcd/templates/deb-etcd-proxy-host.initd.j2 b/roles/etcd/templates/deb-etcd-proxy-host.initd.j2
deleted file mode 100644
index d0858bb2f9513913ce842f7209b30c0383e6f7f0..0000000000000000000000000000000000000000
--- a/roles/etcd/templates/deb-etcd-proxy-host.initd.j2
+++ /dev/null
@@ -1,110 +0,0 @@
-#!/bin/sh
-set -a
-
-### BEGIN INIT INFO
-# Provides:   etcd-proxy
-# Required-Start:    $local_fs $network $syslog
-# Required-Stop:
-# Default-Start:     2 3 4 5
-# Default-Stop:      0 1 6
-# Short-Description: etcd-proxy
-# Description:
-#   etcd-proxy is a proxy for etcd: distributed, consistent key-value store for shared configuration and service discovery
-### END INIT INFO
-
-PATH=/sbin:/usr/sbin:/bin:/usr/bin
-DESC="etcd-proxy"
-NAME=etcd-proxy
-DAEMON={{ bin_dir }}/etcd
-DAEMON_ARGS=""
-SCRIPTNAME=/etc/init.d/$NAME
-DAEMON_USER=etcd
-STOP_SCHEDULE="${STOP_SCHEDULE:-QUIT/5/TERM/5/KILL/5}"
-PID=/var/run/etcd-proxy.pid
-
-# Exit if the binary is not present
-[ -x "$DAEMON" ] || exit 0
-
-# Read configuration variable file if it is present
-[ -f /etc/etcd-proxy.env ] && . /etc/etcd-proxy.env
-
-# Define LSB log_* functions.
-# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
-# and status_of_proc is working.
-. /lib/lsb/init-functions
-
-do_status()
-{
-    status_of_proc -p $PID "$DAEMON" "$NAME" && exit 0 || exit $?
-}
-
-# Function that starts the daemon/service
-#
-do_start()
-{
-    start-stop-daemon --background --start --quiet --make-pidfile --pidfile $PID --user $DAEMON_USER --exec $DAEMON -- \
-        $DAEMON_ARGS \
-        || return 2
-}
-
-#
-# Function that stops the daemon/service
-#
-do_stop()
-{
-    start-stop-daemon --stop --quiet --retry=$STOP_SCHEDULE --pidfile $PID --name $NAME
-    RETVAL="$?"
-
-    sleep 1
-    return "$RETVAL"
-}
-
-
-case "$1" in
-  start)
-        log_daemon_msg "Starting $DESC" "$NAME"
-        do_start
-        case "$?" in
-                0|1) log_end_msg 0 || exit 0 ;;
-                2) log_end_msg 1 || exit 1 ;;
-        esac
-        ;;
-  stop)
-        log_daemon_msg "Stopping $DESC" "$NAME"
-        if do_stop; then
-            log_end_msg 0
-        else
-            log_failure_msg "Can't stop etcd-proxy"
-            log_end_msg 1
-        fi
-        ;;
-  status)
-        if do_status; then
-            log_end_msg 0
-        else
-            log_failure_msg "etcd-proxy is not running"
-            log_end_msg 1
-        fi
-        ;;
-
-  restart|force-reload)
-        log_daemon_msg "Restarting $DESC" "$NAME"
-        if do_stop; then
-            if do_start; then
-                log_end_msg 0
-                exit 0
-            else
-                rc="$?"
-            fi
-        else
-           rc="$?"
-        fi
-        log_failure_msg "Can't restart etcd-proxy"
-        log_end_msg ${rc}
-        ;;
-  *)
-        echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
-        exit 3
-        ;;
-esac
-
diff --git a/roles/etcd/templates/etcd-proxy-docker.service.j2 b/roles/etcd/templates/etcd-proxy-docker.service.j2
deleted file mode 100644
index bf70f0e7fb7d1c12b625047816c472134780b47e..0000000000000000000000000000000000000000
--- a/roles/etcd/templates/etcd-proxy-docker.service.j2
+++ /dev/null
@@ -1,28 +0,0 @@
-[Unit]
-Description=etcd-proxy docker wrapper
-Wants=docker.socket
-After=docker.service
-
-[Service]
-User=root
-PermissionsStartOnly=true
-ExecStart={{ docker_bin_dir | default("/usr/bin") }}/docker run --restart=always \
---env-file=/etc/etcd-proxy.env \
-{# TODO(mattymo): Allow docker IP binding and disable in envfile
-   -p 2380:2380 -p 2379:2379 #}
---net=host \
---stop-signal=SIGKILL \
--v /usr/share/ca-certificates/:/etc/ssl/certs:ro \
---name={{ etcd_proxy_member_name | default("etcd-proxy") }} \
-{{ etcd_image_repo }}:{{ etcd_image_tag }} \
-{% if etcd_after_v3 %}
-{{ etcd_container_bin_dir }}etcd
-{% endif %}
-ExecStartPre=-{{ docker_bin_dir | default("/usr/bin") }}/docker rm -f {{ etcd_proxy_member_name | default("etcd-proxy") }}
-ExecReload={{ docker_bin_dir | default("/usr/bin") }}/docker restart {{ etcd_proxy_member_name | default("etcd-proxy") }}
-ExecStop={{ docker_bin_dir | default("/usr/bin") }}/docker stop {{ etcd_proxy_member_name | default("etcd-proxy") }}
-Restart=always
-RestartSec=15s
-
-[Install]
-WantedBy=multi-user.target
diff --git a/roles/etcd/templates/etcd-proxy-host.service.j2 b/roles/etcd/templates/etcd-proxy-host.service.j2
deleted file mode 100644
index 4ea5f7bc9d583bcddb8dfa7775991df3cb343a8b..0000000000000000000000000000000000000000
--- a/roles/etcd/templates/etcd-proxy-host.service.j2
+++ /dev/null
@@ -1,19 +0,0 @@
-[Unit]
-Description=etcd-proxy
-After=network.target
-
-[Service]
-Type=notify
-User=etcd
-PermissionsStartOnly=true
-EnvironmentFile=/etc/etcd-proxy.env
-ExecStart={{ bin_dir }}/etcd
-ExecStartPre=/bin/mkdir -p /var/lib/etcd-proxy
-ExecStartPre=/bin/chown -R etcd: /var/lib/etcd-proxy
-NotifyAccess=all
-Restart=always
-RestartSec=10s
-LimitNOFILE=40000
-
-[Install]
-WantedBy=multi-user.target
diff --git a/roles/etcd/templates/etcd-proxy.j2 b/roles/etcd/templates/etcd-proxy.j2
deleted file mode 100644
index 0a1492a379eabb6c7c9ce1fad0a5c5d32b938951..0000000000000000000000000000000000000000
--- a/roles/etcd/templates/etcd-proxy.j2
+++ /dev/null
@@ -1,5 +0,0 @@
-ETCD_DATA_DIR=/var/lib/etcd-proxy
-ETCD_PROXY=on
-ETCD_LISTEN_CLIENT_URLS={{ etcd_access_endpoint }}
-ETCD_NAME={{ etcd_proxy_member_name | default("etcd-proxy") }}
-ETCD_INITIAL_CLUSTER={{ etcd_peer_addresses }}
diff --git a/roles/etcd/templates/etcd.j2 b/roles/etcd/templates/etcd.j2
index b82116612ac8e02a76d1c43d2a3e17ed3d482857..c6dc4c28b7cc57caf1f86c1e3ffa62349cee3a3b 100644
--- a/roles/etcd/templates/etcd.j2
+++ b/roles/etcd/templates/etcd.j2
@@ -3,11 +3,7 @@ ETCD_ADVERTISE_CLIENT_URLS={{ etcd_client_url }}
 ETCD_INITIAL_ADVERTISE_PEER_URLS={{ etcd_peer_url }}
 ETCD_INITIAL_CLUSTER_STATE={% if etcd_cluster_is_healthy.rc != 0 | bool %}new{% else %}existing{% endif %}
 
-{% if not is_etcd_proxy %}
 ETCD_LISTEN_CLIENT_URLS=http://{{ etcd_address }}:2379,http://127.0.0.1:2379
-{% else %}
-ETCD_LISTEN_CLIENT_URLS=http://{{ etcd_address }}:2379
-{% endif %}
 ETCD_ELECTION_TIMEOUT=10000
 ETCD_INITIAL_CLUSTER_TOKEN=k8s_etcd
 ETCD_LISTEN_PEER_URLS=http://{{ etcd_address }}:2380
diff --git a/roles/kubernetes-apps/ansible/templates/calico-policy-controller.yml.j2 b/roles/kubernetes-apps/ansible/templates/calico-policy-controller.yml.j2
index 7c0a21cfa4cd66b1bd5abb7e15a4536cdfb4e926..ff69b5ec64d15d2fb685c6513f3e8f660b0da5d5 100644
--- a/roles/kubernetes-apps/ansible/templates/calico-policy-controller.yml.j2
+++ b/roles/kubernetes-apps/ansible/templates/calico-policy-controller.yml.j2
@@ -26,7 +26,7 @@ spec:
           image: calico/kube-policy-controller:latest
           env:
             - name: ETCD_ENDPOINTS
-              value: "{{ etcd_endpoint }}"
+              value: "{{ etcd_access_endpoint }}"
             # Location of the Kubernetes API - this shouldn't need to be
             # changed so long as it is used in conjunction with
             # CONFIGURE_ETC_HOSTS="true".
@@ -38,3 +38,12 @@ spec:
             # This removes the need for KubeDNS to resolve the Service.
             - name: CONFIGURE_ETC_HOSTS
               value: "true"
+    volumeMounts:
+    - mountPath: {{ etcd_cert_dir }}
+      name: etcd-certs
+      readOnly: true
+  volumes:
+  - hostPath:
+      path: {{ etcd_cert_dir }}
+    name: etcd-certs
+
diff --git a/roles/kubernetes/master/tasks/pre-upgrade.yml b/roles/kubernetes/master/tasks/pre-upgrade.yml
index 3b9f26de1d99c1359d77ce439d1ae8d095cfd5bb..239c46be94fb9821418cbfbb640b46dd936c7113 100644
--- a/roles/kubernetes/master/tasks/pre-upgrade.yml
+++ b/roles/kubernetes/master/tasks/pre-upgrade.yml
@@ -14,12 +14,3 @@
     name: kube-apiserver
     state: stopped
   when: (kube_apiserver_service_file.stat.exists|default(False) or kube_apiserver_init_script.stat.exists|default(False))
-
-- name: "Pre-upgrade | remove kube-apiserver service definition"
-  file:
-    path: "{{ item }}"
-    state: absent
-  when: (kube_apiserver_service_file.stat.exists|default(False) or kube_apiserver_init_script.stat.exists|default(False))
-  with_items:
-    - /etc/systemd/system/kube-apiserver.service
-    - /etc/init.d/kube-apiserver
diff --git a/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2 b/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
index 4100e8a3414c00bde7ec61d5a55e53b9762ccb2d..bcf9f22d45e2ddeff246a323af9594f6612f7cb9 100644
--- a/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
+++ b/roles/kubernetes/master/templates/manifests/kube-apiserver.manifest.j2
@@ -62,3 +62,4 @@ spec:
   - hostPath:
       path: /var/log/
     name: logfile
+
diff --git a/roles/kubernetes/node/templates/cni-calico.conf.j2 b/roles/kubernetes/node/templates/cni-calico.conf.j2
index 4615cdabddb31ba5aa830a56460336a90fe7c103..a6558deaa0d90449d223a3a2b09e0028f2ed85f8 100644
--- a/roles/kubernetes/node/templates/cni-calico.conf.j2
+++ b/roles/kubernetes/node/templates/cni-calico.conf.j2
@@ -1,6 +1,7 @@
 {
   "name": "calico-k8s-network",
   "type": "calico",
+  "etcd_endpoints": "{{ etcd_access_endpoint }}",
   "log_level": "info",
   "ipam": {
     "type": "calico-ipam"
diff --git a/roles/kubernetes/preinstall/defaults/main.yml b/roles/kubernetes/preinstall/defaults/main.yml
index 3eae9757d9d464fdc47f1062a8cacd023398d45f..c02a32e29f92f22b692a204197cd8bdcb36bbbea 100644
--- a/roles/kubernetes/preinstall/defaults/main.yml
+++ b/roles/kubernetes/preinstall/defaults/main.yml
@@ -45,3 +45,6 @@ openstack_username: "{{ lookup('env','OS_USERNAME')  }}"
 openstack_password: "{{ lookup('env','OS_PASSWORD')  }}"
 openstack_region: "{{ lookup('env','OS_REGION_NAME')  }}"
 openstack_tenant_id: "{{ lookup('env','OS_TENANT_ID')  }}"
+
+# All clients access each node individually, instead of using a load balancer.
+etcd_multiaccess: true
diff --git a/roles/kubernetes/preinstall/tasks/set_facts.yml b/roles/kubernetes/preinstall/tasks/set_facts.yml
index 2dd947dda89dcb8932d26ace7f551aaa56cebefe..d51bcbed4a710bf75b6cf96493551ab40a93e3b1 100644
--- a/roles/kubernetes/preinstall/tasks/set_facts.yml
+++ b/roles/kubernetes/preinstall/tasks/set_facts.yml
@@ -30,7 +30,7 @@
 - set_fact:
     etcd_access_addresses: |-
       {% for item in groups['etcd'] -%}
-        http://{{ hostvars[item].access_ip | default(hostvars[item].ip | default(hostvars[item].ansible_default_ipv4['address'])) }}:2379{% if not loop.last %},{% endif %}
+        http://{{ item }}:2379{% if not loop.last %},{% endif %}
       {%- endfor %}
 - set_fact: etcd_access_endpoint="{% if etcd_multiaccess %}{{ etcd_access_addresses }}{% else %}{{ etcd_endpoint }}{% endif %}"
 - set_fact:
@@ -43,13 +43,6 @@
       {% for item in groups['etcd'] -%}
         {{ "etcd"+loop.index|string }}=http://{{ hostvars[item].access_ip | default(hostvars[item].ip | default(hostvars[item].ansible_default_ipv4['address'])) }}:2380{% if not loop.last %},{% endif %}
       {%- endfor %}
-- set_fact:
-    etcd_proxy_member_name: |-
-      {% for host in groups['k8s-cluster'] %}
-      {%   if inventory_hostname == host %}{{"etcd-proxy"+loop.index|string }}{% endif %}
-      {% endfor %}
-- set_fact:
-    is_etcd_proxy: "{{ inventory_hostname in groups['k8s-cluster'] }}"
 - set_fact:
     is_etcd_master: "{{ inventory_hostname in groups['etcd'] }}"
 - set_fact:
diff --git a/roles/network_plugin/calico/tasks/main.yml b/roles/network_plugin/calico/tasks/main.yml
index 46f7298833b27df0c5b12b8a70cc8c4c86a7d3da..ce43d52241a2ebfeef58dbfa47b3d99c2cc19e23 100644
--- a/roles/network_plugin/calico/tasks/main.yml
+++ b/roles/network_plugin/calico/tasks/main.yml
@@ -43,17 +43,21 @@
 - name: Calico | wait for etcd
   uri: url=http://localhost:2379/health
   register: result
-  until: result.status == 200
+  until: result.status == 200 or result.status == 401
   retries: 10
   delay: 5
-  when: inventory_hostname in groups['kube-master']
+  delegate_to: "{{groups['etcd'][0]}}"
+  run_once: true
 
 - name: Calico | Check if calico network pool has already been configured
-  uri:
-    url: "{{ etcd_endpoint }}/v2/keys/calico/v1/ipam/v4/pool"
-    return_content: yes
-    status_code: 200,404
+  command: |-
+    curl \
+      --cacert {{ etcd_cert_dir }}/ca.pem \
+      --cert {{ etcd_cert_dir}}/admin.pem \
+      --key {{ etcd_cert_dir }}/admin-key.pem \
+      https://localhost:2379/v2/keys/calico/v1/ipam/v4/pool
   register: calico_conf
+  delegate_to: "{{groups['etcd'][0]}}"
   run_once: true
 
 - name: Calico | Define ipip pool argument
@@ -79,21 +83,25 @@
   environment:
     NO_DEFAULT_POOLS: true
   run_once: true
-  when: calico_conf.status == 404 or "nodes" not in calico_conf.content
+  when: '"Key not found" in calico_conf.stdout or "nodes" not in calico_conf.stdout'
 
 - name: Calico | Get calico configuration from etcd
-  uri:
-    url: "{{ etcd_endpoint }}/v2/keys/calico/v1/ipam/v4/pool"
-    return_content: yes
-  register: calico_pools
+  command: |-
+    curl http://localhost:2379/v2/keys/calico/v1/ipam/v4/pool
+  register: calico_pools_raw
+  delegate_to: "{{groups['etcd'][0]}}"
+  run_once: true
+
+- set_fact:
+    calico_pools: "{{ calico_pools_raw.stdout | from_json }}"
   run_once: true
 
 - name: Calico | Check if calico pool is properly configured
   fail:
     msg: 'Only one network pool must be configured and it must be the subnet {{ kube_pods_subnet }}.
     Please erase calico configuration and run the playbook again ("etcdctl rm --recursive /calico/v1/ipam/v4/pool")'
-  when: ( calico_pools.json['node']['nodes'] | length > 1 ) or
-        ( not calico_pools.json['node']['nodes'][0]['key'] | search(".*{{ kube_pods_subnet | ipaddr('network') }}.*") )
+  when: ( calico_pools['node']['nodes'] | length > 1 ) or
+        ( not calico_pools['node']['nodes'][0]['key'] | search(".*{{ kube_pods_subnet | ipaddr('network') }}.*") )
   run_once: true
 
 - name: Calico | Write /etc/network-environment
@@ -131,4 +139,3 @@
   shell: "{{ bin_dir }}/calicoctl node bgp peer add {{ item.router_id }} as {{ item.as }}"
   with_items: peers
   when: peer_with_router|default(false) and inventory_hostname in groups['kube-node']
-
diff --git a/roles/network_plugin/calico/templates/calico-node.service.j2 b/roles/network_plugin/calico/templates/calico-node.service.j2
index a7f7e4bab302e6ba25218f6c1f705ddfefdb6eb1..2a7775fd45365d127ba659d6a38ce6d8bbcc5132 100644
--- a/roles/network_plugin/calico/templates/calico-node.service.j2
+++ b/roles/network_plugin/calico/templates/calico-node.service.j2
@@ -1,8 +1,8 @@
 [Unit]
 Description=Calico per-node agent
 Documentation=https://github.com/projectcalico/calico-docker
-After=docker.service docker.socket etcd-proxy.service
-Wants=docker.socket etcd-proxy.service
+After=docker.service docker.socket
+Wants=docker.socket
 
 [Service]
 User=root
diff --git a/roles/network_plugin/calico/templates/calicoctl-container.j2 b/roles/network_plugin/calico/templates/calicoctl-container.j2
index 466f1df9395e52d4301f2783a2995b785776a800..c8ac759de6f19abeeae0c022c85c19c36101e68e 100644
--- a/roles/network_plugin/calico/templates/calicoctl-container.j2
+++ b/roles/network_plugin/calico/templates/calicoctl-container.j2
@@ -1,6 +1,7 @@
 #!/bin/bash
 /usr/bin/docker run --privileged --rm \
---net=host --pid=host -e ETCD_AUTHORITY={{ etcd_authority }} \
+--net=host --pid=host \
+-e ETCD_ENDPOINTS={{ etcd_access_endpoint }} \
 -v /usr/bin/docker:/usr/bin/docker \
 -v /var/run/docker.sock:/var/run/docker.sock \
 -v /var/run/calico:/var/run/calico \
diff --git a/roles/network_plugin/calico/templates/network-environment.j2 b/roles/network_plugin/calico/templates/network-environment.j2
index 086803d1b8abc442839380edbab12f9e43300801..0da2db904d66a202fd05fecc3b0adf59f6403e72 100644
--- a/roles/network_plugin/calico/templates/network-environment.j2
+++ b/roles/network_plugin/calico/templates/network-environment.j2
@@ -3,7 +3,7 @@
 DEFAULT_IPV4={{ip | default(ansible_default_ipv4.address) }}
 
 # The Kubernetes master IP
-KUBERNETES_MASTER={{ first_kube_master }}
+KUBERNETES_MASTER={{ kube_apiserver_endpoint }}
 
 # IP and port of etcd instance used by Calico
-ETCD_AUTHORITY={{ etcd_authority }}
+ETCD_ENDPOINTS={{ etcd_access_endpoint }}
diff --git a/roles/network_plugin/flannel/templates/flannel-pod.yml b/roles/network_plugin/flannel/templates/flannel-pod.yml
index 15523bdde83c86725e1ff8806805b41981f9b026..70353f11a8d1ba11ee845b8b6108d392cbda0dd5 100644
--- a/roles/network_plugin/flannel/templates/flannel-pod.yml
+++ b/roles/network_plugin/flannel/templates/flannel-pod.yml
@@ -21,7 +21,7 @@
         args:
           - "--network-config=/etc/flannel-network.json"
           - "--etcd-prefix=/{{ cluster_name }}/network"
-          - "--etcd-server={{ etcd_endpoint }}"
+          - "--etcd-endpoints={{ etcd_access_endpoint }}"
         volumeMounts:
           - name: "networkconfig"
             mountPath: "/etc/flannel-network.json"