├── Boxfile ├── LICENSE ├── Makefile ├── README.md ├── proxy-service.sh └── start.sh /Boxfile: -------------------------------------------------------------------------------- 1 | from "ubuntu:xenial" 2 | 3 | def install_packages pkgs 4 | cmds = [ 5 | %(apt-get update -q), 6 | %(apt-get upgrade -qy), 7 | %(apt-get install -qy #{pkgs}), 8 | ] 9 | 10 | cmds.each { |cmd| run cmd } 11 | end 12 | 13 | def install_dependencies 14 | versions = { 15 | kubernetes: "v1.7.5", 16 | weave: "v2.0.4", 17 | tini: "v0.14.0", 18 | } 19 | 20 | prepare = [ 21 | 'curl --silent "https://packages.cloud.google.com/apt/doc/apt-key.gpg" | apt-key add -', 22 | 'echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" > /etc/apt/sources.list.d/kubernetes.list', 23 | ] 24 | 25 | dependencies = %(curl apt-transport-https) 26 | 27 | # TODO pin versions here 28 | # TODO docker-engine 29 | # TODO installing kubeadm fails due to systemd 30 | official_packages = %(docker.io kubectl kubelet kubernetes-cni) 31 | 32 | kube_release_artefacts = "https://dl.k8s.io/#{versions[:kubernetes]}/bin/linux/amd64" 33 | weave_release_artefacts = "https://github.com/weaveworks/weave/releases/download" 34 | weave_launcher = "https://cloud.weave.works/k8s/v1.6/net.yaml?v=#{versions[:weave]}" 35 | 36 | download_files = [ 37 | "/usr/bin/weave" => { 38 | url: "#{weave_release_artefacts}/#{versions[:weave]}/weave", 39 | mode: '0755', 40 | }, 41 | "/etc/weave.yaml" => { 42 | url: weave_launcher, 43 | mode: '0644', 44 | }, 45 | "/usr/bin/kubeadm" => { 46 | url: "#{kube_release_artefacts}/kubeadm", 47 | mode: '0755', 48 | }, 49 | "/usr/bin/tini" => { 50 | url: "https://github.com/krallin/tini/releases/download/#{versions[:tini]}/tini", 51 | mode: '0755', 52 | }, 53 | ] 54 | 55 | install_packages dependencies 56 | 57 | prepare.each { |cmd| run cmd } 58 | 59 | install_packages official_packages 60 | 61 | download_files.each do |file| 62 | file.each do |dest,info| 63 | run %(curl --output "#{dest}" --fail --silent --location "#{info[:url]}") 64 | run %(chmod "#{info[:mode]}" "#{dest}") 65 | end 66 | end 67 | 68 | end 69 | 70 | def kubelet_cmd 71 | %w( 72 | kubelet 73 | --kubeconfig=/etc/kubernetes/kubelet.conf --require-kubeconfig=true 74 | --pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true 75 | --network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin 76 | --cluster-dns=10.96.0.10 --cluster-domain=cluster.local 77 | --cgroups-per-qos=false --enforce-node-allocatable="" 78 | --node-ip="192.168.65.2" 79 | ) 80 | end 81 | 82 | def create_kubelet_wrapper 83 | kubelet_wrapper = "#!/bin/sh\nuntil #{kubelet_cmd.join(' ')} ; do sleep 1 ; done" 84 | run "echo \"#{kubelet_wrapper}\" > /usr/bin/kubelet.sh && chmod 0755 /usr/bin/kubelet.sh" 85 | end 86 | 87 | install_dependencies 88 | 89 | create_kubelet_wrapper 90 | 91 | # TODO use environment variable to set (https://github.com/erikh/box/issues/144) 92 | # org.label-schema.vcs-url 93 | # org.label-schema.vcs-ref 94 | 95 | env KUBECONFIG: "/etc/kubernetes/admin.conf" 96 | 97 | image_name = "errordeveloper/kxd" 98 | 99 | set_exec entrypoint: %w(/bin/bash -c), cmd: [] 100 | 101 | tag "#{image_name}:shell" 102 | 103 | set_exec entrypoint: %w(tini -s --), cmd: %w(kubelet.sh) 104 | 105 | tag "#{image_name}:kubelet" 106 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | Copyright 2017 Weaveworks Ltd. 180 | 181 | Licensed under the Apache License, Version 2.0 (the "License"); 182 | you may not use this file except in compliance with the License. 183 | You may obtain a copy of the License at 184 | 185 | http://www.apache.org/licenses/LICENSE-2.0 186 | 187 | Unless required by applicable law or agreed to in writing, software 188 | distributed under the License is distributed on an "AS IS" BASIS, 189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 190 | See the License for the specific language governing permissions and 191 | limitations under the License. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | build: Boxfile 2 | docker run --rm -ti \ 3 | -v $(PWD):$(PWD) \ 4 | -v /var/run/docker.sock:/var/run/docker.sock \ 5 | -w $(PWD) \ 6 | boxbuilder/box:master Boxfile 7 | 8 | push: build 9 | docker push errordeveloper/kxd:kubelet 10 | docker push errordeveloper/kxd:shell 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kubernetes on Docker for Mac 2 | 3 | > Please note, this project is work in progress. 4 | 5 | > Also note, there exists a known issue (see [docker/for-mac#1305](https://github.com/docker/for-mac/issues/1305) & [docker/for-mac#1176](https://github.com/docker/for-mac/issues/1176)), where a crash may occur when some suffiecently large payload is deployed onto Kubernetes. A known work-around is to ensure Docker for Mac has only one vCPU. 6 | 7 | ```bash 8 | git clone https://github.com/errordeveloper/kxd 9 | cd kxd 10 | ./start.sh 11 | ``` 12 | 13 | Kubernetes API is now available on `localhost:8080` and doesn't require `kubeconfig`. 14 | 15 | ```console 16 | > kubectl -s localhost:8080 cluster-info 17 | Kubernetes master is running at localhost:8080 18 | KubeDNS is running at localhost:8080/api/v1/proxy/namespaces/kube-system/services/kube-dns 19 | 20 | To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. 21 | 22 | > kubectl -s localhost:8080 get nodes 23 | NAME STATUS AGE 24 | moby Ready,master 2m 25 | ``` 26 | 27 | Next, let's make cluster DNS accessible from the Mac: 28 | ``` 29 | ./proxy-service.sh --namespace kube-system kube-dns 30 | ``` 31 | 32 | Kubernetes DNS server is now directly accessible via it's service IP: 33 | ``` 34 | > dig kubernetes.default.svc.cluster.local @10.96.0.10 35 | 36 | ; <<>> DiG 9.8.3-P1 <<>> kubernetes.default.svc.cluster.local @10.96.0.10 37 | ;; global options: +cmd 38 | ;; Got answer: 39 | ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25798 40 | ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 41 | 42 | ;; QUESTION SECTION: 43 | ;kubernetes.default.svc.cluster.local. IN A 44 | 45 | ;; ANSWER SECTION: 46 | kubernetes.default.svc.cluster.local. 22 IN A 10.96.0.1 47 | 48 | ;; Query time: 0 msec 49 | ;; SERVER: 10.96.0.10#53(10.96.0.10) 50 | ;; WHEN: Fri Feb 17 09:31:53 2017 51 | ;; MSG SIZE rcvd: 70 52 | ``` 53 | 54 | To make any service IP available on the Mac, run `./proxy-service.sh [--namespace ] `. 55 | 56 | ## Credits 57 | 58 | Thanks to [@justincormack](https://github.com/justincormack) for help in understanding how to make service IPs work with Docker for Mac. 59 | -------------------------------------------------------------------------------- /proxy-service.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o pipefail 5 | set -o nounset 6 | 7 | readonly image_name="errordeveloper/kxd" 8 | 9 | readonly svc="$(kubectl get service "$@" -o json)" 10 | 11 | test "$(echo "${svc}" | jq -r '.kind')" = "Service" || exit 1 12 | 13 | readonly darwin_ifconfig_cmd=" \ 14 | sudo ifconfig lo0 alias \ 15 | "$(echo "${svc}" | jq -r '.spec | "\(.clusterIP) netmask 255.240.0.0"')"\ 16 | " 17 | 18 | readonly docker_slirp_proxy_cmd=" \ 19 | /rootfs/usr/bin/slirp-proxy -i -no-local-ip \ 20 | "$(echo "${svc}" | jq -r '.spec | "-proto \(.ports[0].protocol | ascii_downcase) -host-ip \(.clusterIP) -host-port \(.ports[0].port) -container-ip \(.clusterIP) -container-port \(.ports[0].port)"')" \ 21 | " 22 | readonly docker_container_name="$(echo "${svc}" \ 23 | | jq -r '"kxd-svc-\(.metadata.namespace)-\(.metadata.name)-\(.spec.clusterIP)-\(.spec.ports[0].port)-\(.spec.ports[0].protocol | ascii_downcase)"')\ 24 | " 25 | 26 | readonly sys_volumes=( 27 | "/:/rootfs:ro" 28 | "/port:/port:rw" 29 | "/lib/ld-musl-x86_64.so.1:/lib/ld-musl-x86_64.so.1:ro" 30 | "/lib/libc.musl-x86_64.so.1:/lib/libc.musl-x86_64.so.1:ro" 31 | ) 32 | 33 | args=( 34 | --detach 35 | --net=host 36 | --name=${docker_container_name} 37 | ) 38 | 39 | labels=( 40 | "kxd.k8s.io/infra=true" 41 | "kxd.k8s.io/svc-proxy-for=\"$*\"" 42 | ) 43 | 44 | for v in "${sys_volumes[@]}" ; do args+=("--volume=${v}") ; done 45 | for l in "${labels[@]}" ; do args+=("--label=${l}") ; done 46 | 47 | printf "Will run the following command that requires root privileges, please enter your password below\n%s\n" "${darwin_ifconfig_cmd}" 48 | ${darwin_ifconfig_cmd} 49 | 50 | docker run "${args[@]}" "${image_name}:shell" "${docker_slirp_proxy_cmd}" 51 | -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -x 2 | 3 | ## Using new Python client would be nice, there is a lot of dancing around already 4 | ## and we will have more and more of it... Otherwise we can do it in Go. 5 | 6 | set -o errexit 7 | set -o pipefail 8 | set -o nounset 9 | 10 | readonly image_name="errordeveloper/kxd" 11 | readonly shell_image_name="${image_name}:${shell_image_tag:-shell}" 12 | readonly kubelet_image_name="${image_name}:${kubelet_image_tag:-kubelet}" 13 | 14 | ## TODO rootfs should be mounted read-only, this is because of CNI hack... 15 | readonly sys_volumes=( 16 | /sys:/sys:rw 17 | /sys/fs/cgroup:/sys/fs/cgroup:rw 18 | /dev:/dev:rw 19 | /port:/port:rw 20 | /var/run:/var/run:rw 21 | /var/lib:/var/lib:rw 22 | ) 23 | 24 | readonly kxd_volumes=( 25 | /opt/cni:/opt/cni:ro 26 | /etc/cni:/etc/cni:ro 27 | /etc/kubernetes:/etc/kubernetes:rw 28 | /var/lib/kubelet:/var/lib/kubelet:rw,rshared 29 | /var/log/containers:/var/log/containers:rw 30 | ) 31 | 32 | readonly infra_label="kxd.k8s.io/infra=true" 33 | 34 | readonly kill_list=( 35 | $(docker ps --all --filter "label=${infra_label}" --quiet) 36 | $(docker ps --all --filter "label=io.kubernetes.pod.name" --quiet) 37 | ) 38 | 39 | test "${#kill_list}" -gt 0 && docker rm --volumes --force "${kill_list[@]}" 40 | 41 | args=( 42 | --privileged --net=host --pid=host 43 | ) 44 | 45 | for v in "${sys_volumes[@]}" ; do args+=("--volume=${v}") ; done 46 | rootfs_vol="--volume=/:/rootfs:rw" 47 | 48 | ## TODO this will fail on the first run for numerous reasons 49 | # - directories missing in /, so Docker for Mac will refuse mounts 50 | # - does kubeadm reset fail miserably? 51 | docker run "${args[@]}" "${rootfs_vol}" --rm "${shell_image_name}" "mkdir -p /rootfs/etc/kubernetes" 52 | docker run "${args[@]}" "${rootfs_vol}" --rm "${shell_image_name}" "mkdir -p /rootfs/var/lib/kubelet" 53 | docker run "${args[@]}" "${rootfs_vol}" --rm "${shell_image_name}" "mkdir -p /rootfs/var/log/containers" 54 | docker run "${args[@]}" "${rootfs_vol}" --rm "${shell_image_name}" "mkdir -p /rootfs/etc/cni" 55 | docker run "${args[@]}" "${rootfs_vol}" --rm "${shell_image_name}" "mkdir -p /rootfs/opt/cni" 56 | docker run "${args[@]}" "${rootfs_vol}" --rm "${shell_image_name}" "cp -r /opt/cni/bin /rootfs/opt/cni" 57 | docker run "${args[@]}" "${rootfs_vol}" --rm "${shell_image_name}" "nsenter --mount=/proc/1/ns/mnt -- mount --bind /var/lib/kubelet /var/lib/kubelet" 58 | docker run "${args[@]}" "${rootfs_vol}" --rm "${shell_image_name}" "nsenter --mount=/proc/1/ns/mnt -- mount --make-rshared /var/lib/kubelet" 59 | 60 | for v in "${kxd_volumes[@]}" ; do args+=("--volume=${v}") ; done 61 | rootfs_vol="--volume=/:/rootfs:ro" 62 | 63 | docker run "${args[@]}" "${rootfs_vol}" --rm "${shell_image_name}" "rm -r -f /var/lib/etcd && mkdir -p /var/lib/etcd" 64 | docker run "${args[@]}" "${rootfs_vol}" --rm "${shell_image_name}" "kubeadm reset" 65 | 66 | if [ "$#" -gt 0 ] ; then 67 | echo "$*" | grep -q '\--only-reset' && exit 68 | echo "$*" | grep -q '\--reset-only' && exit 69 | fi 70 | 71 | readonly labels="--label=${infra_label}" 72 | 73 | docker run "${args[@]}" "${rootfs_vol}" --name=kxd-kubelet --detach "${labels}" "${kubelet_image_name}" 74 | 75 | ## TODO it is possible Docker for Mac VM gets a different address on eth0 76 | readonly primary_address="192.168.65.2" 77 | readonly localhost="127.0.0.1" 78 | 79 | docker_exec() { 80 | docker exec --tty --interactive kxd-kubelet "$@" 81 | } 82 | 83 | docker_exec kubeadm init --skip-preflight-checks --apiserver-advertise-address="${primary_address}" --apiserver-cert-extra-sans="${localhost}" --kubernetes-version="v1.7.5" 84 | docker_exec kubectl create --namespace="kube-system" --filename="https://frontend.dev.weave.works/k8s/v1.6/net.yaml" 85 | docker_exec kubectl taint node moby node-role.kubernetes.io/master:NoSchedule- 86 | 87 | readonly proxy_port="6443" 88 | readonly kubernetes_service_ip="10.96.0.1" 89 | readonly kubernetes_service_port="443" 90 | readonly slirp_proxy_kubernetes_service=" \ 91 | /rootfs/usr/bin/slirp-proxy \ 92 | -i -no-local-ip -proto tcp \ 93 | -host-ip ${localhost} -host-port ${proxy_port} \ 94 | -container-ip ${kubernetes_service_ip} -container-port ${kubernetes_service_port} \ 95 | " 96 | readonly kubernetes_insecure_port="8080" 97 | readonly slirp_proxy_kubernetes_localhost=" \ 98 | /rootfs/usr/bin/slirp-proxy \ 99 | -i -no-local-ip -proto tcp \ 100 | -host-ip ${localhost} -host-port ${kubernetes_insecure_port} \ 101 | -container-ip ${localhost} -container-port ${kubernetes_insecure_port} \ 102 | " 103 | 104 | docker run "${args[@]}" "${rootfs_vol}" --name=kxd-api-proxy --detach "${labels}" \ 105 | --volume="/lib/ld-musl-x86_64.so.1:/lib/ld-musl-x86_64.so.1:ro" \ 106 | --volume="/lib/libc.musl-x86_64.so.1:/lib/libc.musl-x86_64.so.1:ro" \ 107 | "${shell_image_name}" "${slirp_proxy_kubernetes_service}" 108 | 109 | docker run "${args[@]}" "${rootfs_vol}" --name=kxd-api-proxy-insecure1 --detach "${labels}" \ 110 | "${shell_image_name}" "kubectl proxy --port=8080" 111 | 112 | docker run "${args[@]}" "${rootfs_vol}" --name=kxd-api-proxy-insecure2 --detach "${labels}" \ 113 | --volume="/lib/ld-musl-x86_64.so.1:/lib/ld-musl-x86_64.so.1:ro" \ 114 | --volume="/lib/libc.musl-x86_64.so.1:/lib/libc.musl-x86_64.so.1:ro" \ 115 | "${shell_image_name}" "${slirp_proxy_kubernetes_localhost}" 116 | 117 | docker cp kxd-kubelet:/etc/kubernetes/admin.conf kubeconfig 118 | export KUBECONFIG=kubeconfig 119 | kubectl config set-cluster kubernetes --server="https://${localhost}:${proxy_port}" 120 | kubectl get nodes 121 | --------------------------------------------------------------------------------