Developing a Custom Namer Plugin for Linkerd
In this article, we will explore how to create a simple custom namer plugin for Linkerd. This example will focus on a minimal implementation that uses hardcoded addresses for demonstration purposes.
Initializer Class
The initializer is responsible for registering your custom namer configuration with Linkerd. Below is a basic implementation:
package com.consg
import io.buoyant.namer.NamerInitializer
class MyInitializer extends NamerInitializer {
val configClass = classOf[MyConfig]
override def configId = "com.consg.MyConfig"
}
object MyInitializer extends MyInitializer
Configuration Class
The configuration class defines the parameters for your custom namer. Here’s how you can set it up:
package com.consg
import com.fasterxml.jackson.annotation.JsonIgnore
import com.twitter.finagle.{Path, Stack}
import io.buoyant.config.types.Directory
import io.buoyant.namer.NamerConfig
case class MyConfig(rootDir: Directory) extends NamerConfig {
@JsonIgnore
override def defaultPrefix: Path = Path.read("/my.namer")
@JsonIgnore
def newNamer(params: Stack.Params) = {
println("params: " + params)
new MyNamer(rootDir.path, prefix)
}
}
Namer Implementation
The namer itself is where the logic for resolving names to addresses is implemented. Below is a simple example:
package com.consg
import java.nio.file.{Path => NioPath}
import com.twitter.finagle._
import com.twitter.util._
import io.buoyant.namer.EnumeratingNamer
class MyNamer(rootDir: NioPath, prefix: Path) extends EnumeratingNamer {
def lookup(path: Path): Activity[NameTree[Name]] = {
println("lookup path: " + path)
val address1 = Address("127.0.0.1", 7777)
val addr = Addr.Bound(Set(address1), Addr.Metadata.empty)
val varr = Var.apply(addr)
Activity.value(NameTree.Leaf(Name.Bound(varr, path, path)))
}
override def getAllNames: Activity[Set[Path]] = {
println("getAllNames!")
Activity.value(Set.apply(Path.read("animal")))
}
}
Build Configuration
To build your plugin, you will need to set up your build.sbt file as follows:
name := "plug"
version := "1"
scalaVersion := "2.12.1"
libraryDependencies += "io.buoyant" % "linkerd-core_2.12" % "1.3.2" % "provided"
Make sure to expose your initializer in the META-INF/services/io.buoyant.namer.NamerInitializer file.
Plugin Deployment
After building your plugin JAR, place it in the plugins directory of your Linkerd installation (e.g., linkerd-1.3.1/plugins).
Linkerd Configuration
To use your custom namer, configure Linkerd with the following YAML:
namers:
- kind: com.consg.MyConfig
rootDir: disco
routers:
- protocol: http
dtab: /svc => /#/my.namer;
servers:
- port: 8080
Troubleshooting
If you encounter errors such as InvalidTypeIdException, it may indicate that your plugin is not being loaded correctly. Ensure that your JAR is in the correct directory and that the service is properly registered.
For further assistance, you can refer to the GitHub repository containing the example code.