Daniel's Tech Blog

Cloud Computing, Cloud Native & Kubernetes

An experiment – Enable Cilium native routing on Azure Kubernetes Service BYOCNI – Part 2

This is the second part of a three-part series about “An experiment – Enable Cilium native routing on Azure Kubernetes Service BYOCNI”.

-> https://www.danielstechblog.io/an-experiment-enable-cilium-native-routing-on-azure-kubernetes-service-byocni-part-1/

We will focus today on how to enable Cilium native routing with WireGuard Transparent Encryption on Azure Kubernetes Service BYOCNI.

Hubble CLI output when calling a webserver from the outside

Enable Cilium native routing with WireGuard Transparent Encryption

In this example, we use 100.64.0.0/10 as the pod CIDR range and have the following Helm chart configuration, condensed on the most important settings.

aksbyocni:
  enabled: true
autoDirectNodeRoutes: false
encryption:
  enabled: true
  type: wireguard
  nodeEncryption: true
ipv4NativeRoutingCIDR: 100.64.0.0/10
routingMode: native

When we apply this configuration to our Cilium installation, we get an error message.

Error: UPGRADE FAILED: execution error at (cilium/templates/cilium-operator/deployment.yaml:49:48): RoutingMode must be set to tunnel when aksbyocni.enabled=true

The Helm chart does not allow native routing when using Azure Kubernetes Service BYOCNI. Looking into the Helm chart, it is the only reason for having “aksbyocni” set to “true. No other Cilium settings are affected by that.

Let us try it again with a new configuration.

aksbyocni:
  enabled: false
autoDirectNodeRoutes: false
encryption:
  enabled: true
  type: wireguard
  nodeEncryption: true
ipv4NativeRoutingCIDR: 100.64.0.0/10
routingMode: native

Now the deployment works, and we should have Cilium running with native routing on Azure Kubernetes Service BYOCNI.

Before I switched the Cilium installation from encapsulation to native routing, I gathered the configuration status via cilium-dbg.

❯ kubectl exec -it cilium-dlrh7 -- cilium-dbg status
...
KubeProxyReplacement:    True   [eth0   10.10.0.12 fe80::20d:3aff:fedf:60c4 (Direct Routing)]
...
CNI Chaining:            none
CNI Config file:         successfully wrote CNI configuration file to /host/etc/cni/net.d/05-cilium.conflist
Cilium:                  Ok   1.18.6 (v1.18.6-95896696)
...
Cilium health daemon:    Ok
IPAM:                    IPv4: 34/254 allocated from 100.64.0.0/24,
...
Routing:                 Network: Tunnel [vxlan]   Host: BPF
Attach Mode:             TCX
Device Mode:             veth
Masquerading:            BPF   [eth0]   100.64.0.0/24  [IPv4: Enabled, IPv6: Disabled]
...
Encryption:              Wireguard       [NodeEncryption: Enabled, cilium_wg0 (Pubkey: OnJFcH+/tGSyXhhiMVJvpUpbQ5ctX7kqPmoNj/cTEGI=, Port: 51871, Peers: 3)]
...

In the output, we see under Routing that the Cilium installation uses VXLAN for encapsulation.

Additionally, I ran a quick network connection test between two pods on different Kubernetes nodes and observed the test with the Hubble CLI.

❯ hubble observe -P --protocol tcp --from-pod kube-system/ping -f
Feb 13 21:20:47.557: kube-system/ping:45284 (ID:30081) -> go-webapp/go-webapp-55f76547b5-xkpm7:8080 (ID:14226) to-endpoint FORWARDED (TCP Flags: SYN)
Feb 13 21:20:47.557: kube-system/ping:45284 (ID:30081) -> go-webapp/go-webapp-55f76547b5-xkpm7:8080 (ID:14226) policy-verdict:all EGRESS ALLOWED (TCP Flags: SYN)
Feb 13 21:20:47.557: kube-system/ping:45284 (ID:30081) -> go-webapp/go-webapp-55f76547b5-xkpm7:8080 (ID:14226) to-overlay FORWARDED (TCP Flags: SYN)
Feb 13 21:20:47.557: kube-system/ping:45284 (ID:30081) -> go-webapp/go-webapp-55f76547b5-xkpm7:8080 (ID:14226) to-overlay FORWARDED (TCP Flags: ACK)
Feb 13 21:20:47.557: kube-system/ping:45284 (ID:30081) -> go-webapp/go-webapp-55f76547b5-xkpm7:8080 (ID:14226) to-overlay FORWARDED (TCP Flags: ACK, PSH)
Feb 13 21:20:47.558: kube-system/ping:45284 (ID:30081) -> go-webapp/go-webapp-55f76547b5-xkpm7:8080 (ID:14226) to-endpoint FORWARDED (TCP Flags: ACK)
Feb 13 21:20:47.558: kube-system/ping:45284 (ID:30081) -> go-webapp/go-webapp-55f76547b5-xkpm7:8080 (ID:14226) to-endpoint FORWARDED (TCP Flags: ACK, PSH)
Feb 13 21:20:47.562: kube-system/ping:45284 (ID:30081) -> go-webapp/go-webapp-55f76547b5-xkpm7:8080 (ID:14226) to-overlay FORWARDED (TCP Flags: ACK, FIN)
Feb 13 21:20:47.562: kube-system/ping:45284 (ID:30081) -> go-webapp/go-webapp-55f76547b5-xkpm7:8080 (ID:14226) to-endpoint FORWARDED (TCP Flags: ACK, FIN)
Feb 13 21:20:47.562: kube-system/ping:45284 (ID:30081) -> go-webapp/go-webapp-55f76547b5-xkpm7:8080 (ID:14226) to-endpoint FORWARDED (TCP Flags: ACK)

You can see in the Hubble CLI output that the packets are sent to the overlay -> to-overlay.

After the switch to the native routing mode, I ran cilium-dbg and executed the test again.

❯ kubectl exec -it cilium-6sggq -- cilium-dbg status
...
KubeProxyReplacement:    True   [eth0   10.10.0.12 fe80::20d:3aff:fedf:60c4 (Direct Routing)]
...
CNI Chaining:            none
CNI Config file:         successfully wrote CNI configuration file to /host/etc/cni/net.d/05-cilium.conflist
Cilium:                  Ok   1.18.6 (v1.18.6-95896696)
...
Cilium health daemon:    Ok
IPAM:                    IPv4: 34/254 allocated from 100.64.0.0/24,
...
Routing:                 Network: Native   Host: BPF
Attach Mode:             TCX
Device Mode:             veth
Masquerading:            BPF   [eth0]   100.64.0.0/10  [IPv4: Enabled, IPv6: Disabled]
...
Encryption:              Wireguard       [NodeEncryption: Enabled, cilium_wg0 (Pubkey: NCgjS0OgiVNOQZyPk+tNQ83zpH7m9kYK16AgkX3VSws=, Port: 51871, Peers: 3)]
...

Now, under Routing, we see that the Cilium installation uses the native routing mode.

❯ hubble observe -P --protocol tcp --from-pod kube-system/ping -f
Feb 13 21:35:13.969: kube-system/ping:38502 (ID:30081) -> go-webapp/go-webapp-55f76547b5-fcpg2:8080 (ID:14226) policy-verdict:all EGRESS ALLOWED (TCP Flags: SYN)
Feb 13 21:35:13.969: kube-system/ping:38502 (ID:30081) -> go-webapp/go-webapp-55f76547b5-fcpg2:8080 (ID:14226) to-network FORWARDED (TCP Flags: SYN)
Feb 13 21:35:13.969: kube-system/ping:38502 (ID:30081) -> go-webapp/go-webapp-55f76547b5-fcpg2:8080 (ID:14226) to-endpoint FORWARDED (TCP Flags: SYN)
Feb 13 21:35:13.970: kube-system/ping:38502 (ID:30081) -> go-webapp/go-webapp-55f76547b5-fcpg2:8080 (ID:14226) to-network FORWARDED (TCP Flags: ACK)
Feb 13 21:35:13.970: kube-system/ping:38502 (ID:30081) -> go-webapp/go-webapp-55f76547b5-fcpg2:8080 (ID:14226) to-endpoint FORWARDED (TCP Flags: ACK)
Feb 13 21:35:13.970: kube-system/ping:38502 (ID:30081) -> go-webapp/go-webapp-55f76547b5-fcpg2:8080 (ID:14226) to-network FORWARDED (TCP Flags: ACK, PSH)
Feb 13 21:35:13.970: kube-system/ping:38502 (ID:30081) -> go-webapp/go-webapp-55f76547b5-fcpg2:8080 (ID:14226) to-endpoint FORWARDED (TCP Flags: ACK, PSH)
Feb 13 21:35:13.974: kube-system/ping:38502 (ID:30081) -> go-webapp/go-webapp-55f76547b5-fcpg2:8080 (ID:14226) to-endpoint FORWARDED (TCP Flags: ACK, FIN)
Feb 13 21:35:13.974: kube-system/ping:38502 (ID:30081) -> go-webapp/go-webapp-55f76547b5-fcpg2:8080 (ID:14226) to-network FORWARDED (TCP Flags: ACK, FIN)
Feb 13 21:35:13.975: kube-system/ping:38502 (ID:30081) -> go-webapp/go-webapp-55f76547b5-fcpg2:8080 (ID:14226) to-endpoint FORWARDED (TCP Flags: ACK)

Also, the observed network traffic via Hubble CLI shows that the packets are sent to the network directly -> to-network.

Summary

Using Cilium native routing with WireGuard Transparent Encryption works on Azure Kubernetes Service BYOCNI when we set certain configuration options for native routing and explicitly set the “aksbyocni” to “false” to bypass the routing mode check in Cilium’s Helm chart.

This solution still uses encapsulation, WireGuard tunnel, but provides secure network communication by encrypting the network traffic.

Outlook

In the third and last part, we have look at Cilium native routing with Azure Route Server and BGP, and then sum up the topic of enabling Cilium native routing on Azure Kubernetes Service BYOCNI.

WordPress Cookie Notice by Real Cookie Banner