Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Expose host port services in Cilium #6

Open
protochron opened this issue May 11, 2023 · 2 comments
Open

[FEATURE] Expose host port services in Cilium #6

protochron opened this issue May 11, 2023 · 2 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@protochron
Copy link
Contributor

Is your feature request related to a problem? Please describe.
Right now Netreap doesn't have a great way to support host services. The easy way to enable that is to simply add the portmap CNI plugin to the configuration chain, ex.

{
  "name": "cilium",
  "cniVersion": "1.0.0",
  "plugins": [
     {
       "type": "cilium-cni",
       "enable-debug": false
     },
     {
      "type": "portmap",
      "capabilities": {"portMappings": true}
     }
  ]
}

Describe the solution you'd like
Cilium has an API for managing services. Normally these are derived from Kubernetes services, but it looks like we should be able to create services with that API to map host ports in Nomad jobs that request them.

Describe alternatives you've considered

Additional context

@protochron protochron added enhancement New feature or request help wanted Extra attention is needed labels May 11, 2023
@deverton
Copy link
Contributor

@deverton
Copy link
Contributor

deverton commented May 29, 2023

As a workaround for now I've got this hacky way of using a pre and post start task to add and remove service definitions. It requires that the Nomad client's are configured to have the Cilium socket directory declared as a host volume. You can define a task that needs host port mapping like the example below.

You will also need to manually manage the service IDs to ensure that they are unique as the Cilium API doesn't seem to provide a way to generate those.

With this configuration you no longer need the portmap plugin in the CNI config.

The way this works is that when Nomad creates group network via the Cilium CNI plugin, that call includes a unique ID for the allocation. We can then use that unique ID to pull the Cilium endpoint ID out and the assigned IPv4 address. From there the Cilium service command can be used to create the actual port mapping.

job "fabio" {
  type      = "system"

  group "fabio" {

    network {
      mode = "cni/cilium"
      port "lb" {
        static = 8080
      }
      port "ui" {
        static = 8081
      }
    }

    volume "cilium" {
      type      = "host"
      read_only = false
      source    = "cilium"
    }

    task "create-service" {
      driver = "exec"

      config {
        command = "/bin/sh"
        args = [
          "$${NOMAD_TASK_DIR}/create-service.sh"
        ]
      }

      lifecycle {
        hook    = "poststart"
        sidecar = false
      }

      template {
        destination = "local/create-service.sh"
        data        = <<-EOH
          #!/bin/sh

          ENDPOINT_ID=$(cilium endpoint list -o jsonpath='{$[?(@.status.external-identifiers.container-id=="{{ env "NOMAD_ALLOC_ID" }}")].id}')
          BACKEND_IP=$(cilium endpoint get "$ENDPOINT_ID" -o jsonpath='{$[0].status.networking.addressing[0].ipv4}')

          cilium service update \
            --k8s-host-port \
            --id 1 \
            --backends "$BACKEND_IP:{{ env "NOMAD_ALLOC_PORT_lb" }}" \
            --frontend "{{ env "NOMAD_HOST_ADDR_lb" }}"

          cilium service update \
            --k8s-host-port \
            --id 2 \
            --backends "$BACKEND_IP:{{ env "NOMAD_ALLOC_PORT_ui" }}" \
            --frontend "{{ env "NOMAD_HOST_ADDR_ui" }}"
        EOH
        perms = "0755"
      }

      volume_mount {
        volume           = "cilium"
        destination      = "/var/run/cilium"
        propagation_mode = "private"
      }
    }

    task "delete-service" {
      driver = "exec"

      config {
        command = "/bin/sh"
        args = [
          "$${NOMAD_TASK_DIR}/delete-service.sh"
        ]
      }

      lifecycle {
        hook    = "poststop"
        sidecar = false
      }

      template {
        destination = "local/delete-service.sh"
        data        = <<-EOH
          #!/bin/sh

          set -x 

          cilium service delete 2
          cilium service delete 1
        EOH
        perms = "0755"
      }

      volume_mount {
        volume           = "cilium"
        destination      = "/var/run/cilium"
        propagation_mode = "private"
      }
    }

# .... rest of the task definition
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants