diff --git a/docs/vars.md b/docs/vars.md
index 11e33f5556cec8da54da5a866d57dcb6521ab04f..8c07454d77666cba56bea8b48fb2f18384b580c6 100644
--- a/docs/vars.md
+++ b/docs/vars.md
@@ -37,6 +37,9 @@ Some variables of note include:
   public/floating and private IPs.
 * *ansible_default_ipv4.address* - Not Kubespray-specific, but it is used if ip
   and access_ip are undefined
+* *ip6* - IPv6 address to use for binding services. (host var)
+  If *enable_dual_stack_networks* is set to ``true`` and *ip6* is defined,
+  kubelet's ``--node-ip`` and node's ``InternalIP`` will be the combination of *ip* and *ip6*.
 * *loadbalancer_apiserver* - If defined, all hosts will connect to this
   address instead of localhost for kube_control_planes and kube_control_plane[0] for
   kube_nodes. See more details in the
diff --git a/roles/kubernetes/node/defaults/main.yml b/roles/kubernetes/node/defaults/main.yml
index c7e4a7eb62111efa98f3172c519fe471ccba2066..06a9422e2ecb1f563ae905830087fa648c1ac397 100644
--- a/roles/kubernetes/node/defaults/main.yml
+++ b/roles/kubernetes/node/defaults/main.yml
@@ -3,7 +3,7 @@
 kube_apiserver_insecure_bind_address: 127.0.0.1
 
 # advertised host IP for kubelet. This affects network plugin config. Take caution
-kubelet_address: "{{ ip | default(fallback_ips[inventory_hostname]) }}"
+kubelet_address: "{{ ip | default(fallback_ips[inventory_hostname]) }}{{ ',' + ip6 if enable_dual_stack_networks and ip6 is defined }}"
 
 # bind address for kubelet. Set to 0.0.0.0 to listen on all interfaces
 kubelet_bind_address: "{{ ip | default('0.0.0.0') }}"