Externally exposing a LXD-based Kubernetes service



  • This article originally appeared on Rye Terrell’s blog

    So you’ve conjured up a Kubernetes cluster on top of LXD on your dev box. Cool. You’ve created a deployment, you’ve got a service directing traffic to it, and you can query it from your box. Sweet. Time to demo this to your boss!

    “Hey boss,” starts your email, “check it out — I’ve got our product running in a k8s cluster! Just click here to see it for yourself: https://…”

    Oops, what IP do you send your boss? You can’t use the internal LXD container IP. You can’t use the IP of your dev box, no traffic is going to reach the relevant container. Damn. What to do?

    There’s actually a few ways to solve this. Here, I’ll cover an iptables one-liner that will forward traffic on a particular port to the proper container.

    Let’s make sure we’re on the same page. First, I’ll create a “hello-world” deployment:

    <pre id="e631" class="graf graf--pre graf-after--p">$ kubectl run hello-world --replicas=2 --labels="run=load-balancer-example" --image=gcr.io/google-samples/node-hello:1.0 --port=8080</pre>

    Then I’ll create an associated service (with type NodePort, since I want to expose it externally):

    <pre id="6b8a" class="graf graf--pre graf-after--p">$ kubectl expose deployment hello-world --type=NodePort --name=example-service</pre>

    Now we should be in roughly the same place. Let’s grab the NodePort for our service:

    <pre id="81f7" class="graf graf--pre graf-after--p">$ kubectl describe services example-service</pre>

    <pre id="ff33" class="graf graf--pre graf-after--pre">Name: example-service Namespace: default Labels: run=load-balancer-example Annotations: <none> Selector: run=load-balancer-example Type: NodePort IP: 10.152.183.175 Port: <unset> 8080/TCP TargetPort: 8080/TCP NodePort: <unset> 30386/TCP Endpoints: <none> Session Affinity: None External Traffic Policy: Cluster Events: <none></pre>

    And find one of the nodes it’s running on:

    <pre id="eff3" class="graf graf--pre graf-after--p">$ kubectl get pods --selector="run=load-balancer-example" --output=wide</pre>

    <pre id="6a5a" class="graf graf--pre graf-after--pre">NAME READY STATUS RESTARTS AGE IP NODE hello-world-58f9949f8-2cqw7 1/1 Running 0 1h 10.1.7.2 juju-2282c0-7 hello-world-58f9949f8-k5zvl 1/1 Running 0 1h 10.1.102.6 juju-2282c0-3</pre>

    Next we’ll need to find the IP address associated with that node:

    <pre id="9c45" class="graf graf--pre graf-after--p">$ lxc info juju-2282c0-3 | grep eth0</pre>

    <pre id="6fa5" class="graf graf--pre graf-after--pre">eth0: inet 10.218.5.81 vethV8TI50</pre>

    Finally, using the node IP and the NodePort information we just collected, we’ll set up an iptables rule (note that the port 8080 is the port I’ll expose on my host):

    <pre id="5739" class="graf graf--pre graf-after--p">iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 8080 -j DNAT --to-destination 10.218.5.81:30386</pre>

    Feel free to use iptables-save and iptables-persistent to allow your new rule to survive a reboot.

    Now we can test it out from another host (note that 35.169.124.27 is the IP of my host):

    <pre id="232d" class="graf graf--pre graf-after--p">$ curl 35.169.124.27:8080 Hello Kubernetes!</pre>

    Great! Alright, go finish that email.

    Want to know more?

    On February 7th, technical lead Stephane Graber will be presenting a webinar for Ubuntu Product Month that will dive into how LXD works, what it does, how it can be used in the enterprise, and even provide an opportunity for Q&A.

    Register For Webinar

    https://insights.ubuntu.com/2018/02/01/externally-exposing-a-lxd-based-kubernetes-service/



© Lightnetics 2024