 Hello, everybody. Welcome. Hope you enjoyed the keynotes today. My name is John Bellamerick from Google and here my co-speaker, Yong Tang from Avanti. Thanks for joining us today. Talk about Kordianus a little bit. So the first bit of this, we'll talk just kind of give an update on the Kordianus project in a little bit of an overview and then Yong will drill in a little bit on what it takes to develop the Kordianus plugin, which is actually really really easy. And then we'll have time for some Q&A probably. So most of you use Kubernetes, I assume, which means you're probably using Kordianus, whether you know it or not. Most Kubernetes clusters out there use Kordianus as their in-cluster DNS for service resolution. But in fact, Kordianus is an independent project with uses outside of Kubernetes and it kind of grew up alongside Kubernetes for the most part and was built to provide an alternative to the traditional DNS server. So if you look at something like Bind, it's a very venerable code base, quite difficult to extend, quite difficult to kind of manage in a cloud native way. And so Kordianus was built to start to provide a DNS server that one was written in a sort of a modern language that was memory safe, so it's written in Go, but also because a lot of bind vulnerabilities came out of just being in C. And to be able to be evolved quickly and to be able to add functionality quickly, to be able to kind of adapt to the rapidly changing cloud native environment that we saw happening a few years back as in the growth of containerized services. So Kordianus started with a focus on service discovery, but kind of the most important part in my mind to it is this, what we call a plugin-based architecture. And it's different than most DNS servers. It's a sort of request handling process. So the individual DNS requests come in and we feed them through a series of sort of pipeline of plugins, and those plugins can make decisions, and we can compose the plugins and the configuration of those plugins to really do some interesting things with the DNS requests. We do have quite a few contributors, nearly 400 now, and a lot of growth in the project. Part of CNCF process is this idea of a public contributor's file, so there's many, many more public adopters file rather. So we've got 35 people, 35 companies who've said they're using Kordianus in some way or another, but really it's in the thousands or more because, like I said, anybody using EKS or AKS or I'm from Google, but actually GKE not the core GKE. We don't use Kordianus, but we do for our on-prem and bare metal offerings we use Kordianus. So really the vast majority of people using Kubernetes out there are using Kordianus in some way or another. We did, in the last year or two, shift from a benevolent dictator for life governance model to a steering committee. So now we have, I think, five people on the steering committee, both of us are on the steering committee, but it's a pretty low drama project, so not much happens in the steering committee, but if anybody's interested in jumping in and participating in Kordianus, we'd love to have you. Very friendly, welcoming place, and we'd love to see you there. Since the last QCUT EU, this is some of the new functionality that's been added. So a new plugin for dealing with the configuration of listener timeouts, which we're just using the defaults before, and a bunch of new features on individual plugins. We had a release, our most recent release was in August, but we should be having, I think, a new release, in particular with the new, using built with a newer version of Go coming out pretty soon. Like I said, Kordianus is really originally targeted around service discovery, and what we'll show you in a moment is just an example use case of how you can use Kordianus outside of Kubernetes as a DNS server that can be backed by multiple different data sources rather than a typical DNS server, which is backed, say by bind, or maybe just serves data for your Kubernetes cluster. You can actually take Kordianus out separately and configure it to do additional things. So what the example core file, so I guess I didn't give that much background. So Kordianus is, you know, as a process is configured by something we call a core file, not a core dump. It's a different thing. And it's just a very simple file that allows you to specify for any given zone, what are the plugins that are active for that zone and what are the plugins that are then, what data sources are used for that, for those to serve up the data for that zone. And what are the interesting things I think in Kordianus is that a single zone can actually be divided among different data sources. So you can sort of create a hierarchy of your records that are served for your different zones where you'd say, I'm going to allow the, I'm going to allow you to override, say directly in the core file a few A records for this zone. But if you don't find it in that list for like a host file type of list, you can consult your Kubernetes cluster. If you don't find it there, you can consult a file or something like that. So there's a sort of, allows you to construct a single DNS zone from a composition of different data sources. And in this example that we have here, what we've done is allowed you to compose a zone from that's backed by your three different clouds. So, or I guess we have two here, AWS and Google cloud DNS. So essentially this allows a single zone to be served up in part by AWS, backed by the AWS API and in part backed up by the Google cloud API of services that are out there and in part backed up by a local, local data source. Who am I plugging? And honestly, that's all there is to it. It's not much to say. This is what, this is an example core file. We can digest this a little bit. It starts with dot, dot colon 53. So the dot just means root zone, right? Any, any query coming in for any zone will be processed by this block of, of plugins. The first one processed is route 53. So what's happening here, the, the, if we go back to this, this diagram, quarter DNS is a process is sitting there. You're configured with the route 53 plugins. So what you do is you actually take your AWS credentials and you connect to the AWS API and you load the data from there and you use that to synthesize the records for the zone. Similarly for cloud DNS, this connects back to Google cloud, brings in the, the, or synthesizes the record based on the API data available in Google cloud. And the fall through statement on here basically says that we can, if we don't find an answer in this, in that data source, fall through to the next data source. So that's why it goes from route 53 to cloud DNS, which then eventually falls through to this just sort of plugin that returns an answer for everything. So that's really all you need to configure this. It's a really very simple, simple process. The functionality, and I don't know if we have a slide here young on the, no, the, the, the functionality available. There's many plugins available and we tend to divide it into three different categories. So there's plugins that allow you to configure court DNS, like the bind plugin, which allows you to tell you which interface to bind to. There's plugins that provide different data sources. So like I said, the different cloud vendors, a file or a Kubernetes cluster or even multiple Kubernetes clusters can be, can be used to back data for, for zones or database. And each of these plugins, you know, if you have your own data source, you may decide that you want to be able to serve up data from that data source, say an internal, uh, CMDB or something that manages your services. And what young is going to cover in a moment is how easy it is to actually extend court DNS to, to do that kind of, um, uh, add a, add a data source. The third kind of, um, plug in that we have is what we would call sort of data manipulation plugin. So here you can, um, you can use policies to block particular queries. You can add metadata to a request and then you can alter the request based upon the content, the contents of that metadata. So we have another talk tomorrow where what we'll look at is, uh, in a Kubernetes cluster, you could actually configure the Kubernetes plugin to append client data information. So if a pod makes a query to your court DNS server, uh, within your court DNS plugin pipeline, you'll be able to see the, the namespace of that client pod. And then you can make a policy decision on that and say, Hey, this, this client, uh, pod from this particular namespace is trying to access a service in a different namespace. I'm going to disallow that. So that's the kind of functionality you can do with these plugins and with the kind of infrastructure, uh, that's really would be extremely challenging to do in any other, uh, DNS server with that, um, do you want to jump in on the demo piece? Okay. So first of all, you know, like, uh, John just mentioned that, uh, if we are going to combine different sources of DNS information from different sources, like from cloud windows from let's say your local DNS, uh, zones or from your local DNS servers, you can combine them into one under that's the data consolidation process. And why you need that is because sometimes you may want to have a, let's go back. You may want to have a so-called a single source of truth. Let's say you'll have DNS server all the place because your IT infrastructure has DNS server, your cloud vendor has DNS server. You have some coordinate clusters on AWS. Uh, you have some, let's say, uh, uh, database services, uh, let's say on Azure or maybe on Google cloud. And then you have your VPNs with some, like a corporate, uh, internal IT stuff. All those things you can consolidate it into one. And in this case, putting us, it's supposed to be just, uh, what should I say, a front end of all the source of information. You can have one place to control the information. Uh, you make sure there's no collision. If the collision for DNS will sort out, like, uh, you can, you can go through the order of different, uh, information. So you can decide which information will be exposed first. If the information is not available, you move to the next plugin and maybe you'll search for the next source. Let's say, uh, Google cloud or AWS to find out. That's, that's one process of consolidation. But now here I'm going to share another example of saying you'll have the same, uh, DNS record and, uh, you wanted to adjust your response based on the, the, the request. So what does that mean? Is it's a source IP based service discovery. Uh, let's just hyper-sector say you'll maintain, uh, let's say, uh, uh, DNS server and, uh, this DNS server is located in your, uh, company VPN. But of course your company may not just have a VPN, right? Your company may have some external information. Your company may, may also have some, like, a test workload. And sometimes, uh, when you're doing test, uh, when you're doing testing of your companies, let's say your company have, uh, active development, you may want to manipulate in DNS to configure, configure additional stuff so that let's say, uh, a QA tester can potentially get a different DNS record based on which network it is in, right? So that's, that's very common practice. But then you're going to ask the question, how do I return a different, different response if for, I only know the source IP of the request, uh, right? So there's an easy way to do that. Of course, you're going to say, is there any existing plugins available in QoDNS so that I can utilize the, you know, core file to manipulating different plugins and get the information? Uh, there's no such thing, uh, unfortunately, because, uh, there, there was some pretty, no pretty extensive discussion in the past about you should we set up certain, let's say, source IP based survey discovery plugins. And the conclusion was that, uh, the source IP based survey discovery is fairly easy. However, to sort out different, uh, different use cases by different users, it's a hard process because we had to make sure if we're going to, uh, write a plugin, we have to make sure it can fit into all different scenarios. Unfortunately, all the scenarios look like to be totally different. Some people may have one request. Some people have another request. Sometimes they say they want the source IP to be based on side block. Sometimes they say they want the source IP to be, to be, you know, like a single standalone source IP or sometimes they say, okay, so they have some additional filtering rules to decide how they are going to do the source IP based survey discovery. So eventually we say, okay, so maybe we can, we will ask about the source IP based survey discovery plugin for many years. Eventually we just say, okay, so maybe we can just write a simple plugin as a demo plugin to let people see how this can be done. And unfortunately, this is super easy. I'll just show with the total of, let's say 80 lines of Golan code and you can get job done. And this is actually going to be a lot of fine experience, right? I mean, you can actually learn a little Golan. You can build a plugin with Quoting S and you can get through all the necessary customizations as you need and feed your scenario, right? So let's just give an example of how exactly this demo plugin is going to work. So as this slide shows, the demo plugin is the source IP based survey discovery. Let's say you assist admin or let's IT admin and you just decided to say, okay, so I have a server. This server is going to be serving multiple purposes. This server has a DNS server. If, if a request is within certain, you know, like a side block or within the internal VPN or a segment of VPN, you want to return to one IP address, which potentially could be your testing server. And then you'll say, if the requester is not from this specific side block, you're going to say, okay, so let's just assume anyone else requesting a DNS, DNS record will return by default one IP. And if request is within a specific side block, it's going to return another IP. So this diagram, as you can see, actually separates the network into two parts. The first part is internal network. That's 172.0.0.0.0 slash eight. That's internal network. And then anything else will be outside. So let's just make it everything simple because we can certainly pick up any IPs to return. But just for fun, I pick up like two IPs. One IP is 1.1.1.1. Another IP is 8.8.8.8. It's very unlikely you're going to use those two IPs, but 1.1.1.1 is Cloudflare's DNS server. And as we all know, 8.8.8.8 is actually Google's DNS resolver. So let's just set up this scenario and see how we can get the job done with minimal lines of Golan code. So as we can see, if it's internal, we are going to return 1.1.1.1 IP. And if it's external, it's going to be 8.8.8.8. And the request, we just make it straightforward. The request will always be example.org. You set up example.org server, you return different IPs. That's fairly simple. So you're going to write a plugin for Quoding S. And the plugin, surprisingly, it's very simple. So how simple it is, it don't require three functions to fill in. And two out of three functions are just available. Start function, you need to get the skeletons in place. And there's one function that you need. As you can see, the first function is a need function, which will perform a one-time initialization because you need to register your plugin with Quoding S. So Quoding S knows they will pass the information to a plugin, allow your plugin to process the request. Setup is plumbing in place so that it can pass the configuration from the file and capture it at the struct. Sorry. Okay. The setup plugin, by itself, is also straightforward. If you wanted to make your plugin a little complicated because you have different configurations, then you need to add more content. But in case, all you need to do is just register a plugin, then that's fairly straightforward. And finally, the need of the plugin is a serve DNS function. This function is doing the processing of a DNS request and return the response. And once the processing has been done in this plugin, you just return and allow the next plugin to process. The next plugin can be a standalone plugin or another plugin you wrote. But let's just focus on one plugin for this demo plugin. That's going to be the source IP-based server discovery. Okay. So as you can see, the need and setup function are fairly straightforward. For need function, you register a plugin because the plugin is a DNS plugin. So you're going to register the server type as DNS. By the way, you'll probably notice there's a caddy in place. The reason caddy appears in QuotingS is because QuotingS started by itself as a plugin of caddy. Some of you may know that caddy is a web server written goal. So at the beginning, when QuotingS was developed, there was some design scenarios you had to figure out. So you need to get the plumbing in place. But as we are developers, sometimes we just think, what's the best way to write some system? You probably want to reuse some more code as much as possible in open source field, right? Because you don't want to waste time writing something from scratch. So that's how QuotingS gets started. QuotingS started as a plugin of caddy by itself. Of course, you're going to say caddy is what should I say ATP server, right? But it's all similar, right? It's either ATP or DNS. It's pretty much the same thing. You can utilize the plumbing to get the job done. So that's some of the creations to make your code reusable, to reuse other people's code. That's a unique function. Now the second one is the setup. The setup is essentially just a pass configuration. Now for the service-based source IP-based discovery. The configuration, we don't want to have any configuration because we just want to hard code everything. But in the future, you want to make it a little fun. You can certainly write more stuff. But for now, let's just assume there's nothing. Everything is hard coded. Okay. So that's the setup. Setup is to just get the configuration. And finally, that's the service DNS, which is truly the need of the plugin you need to write in Go. So first of all, the service DNS will pass three parameters. The first one is going to be context. That's a pretty standard. The second one is a response writer. And the third one is just a request. So the first thing is you have to construct the request state to figure out what exactly is the information that has been passed to this plugin. As you can see, you can get a kill name, which in our case, in our example setup case, that's going to be example.org. Then you're going to say, I want to reply. What kind of IP address I'm going to reply? I'm going to reply either 8.8.8 or I'm going to reply 1.1.1.1. And because I want to, I want my plugin to be source IP based, I do check the IP of the request. And the IP of request, I'll just make a very simple go-down function for prefix search. If IP starts with 172. something, okay, that means it's internal IP. I'm going to reply 1.1.1.1. Otherwise, I'm going to reply 8.8.8.8. That's fairly straightforward, right? And then you have a, there's some like a logging facility to say you'll just print the kill name, the IP and reply so that you can keep track of what they have done. And finally, you just need to construct the answer. Now you're going to say, what else do you need? Well, that's pretty much all you need. You just return the answer. And if you cannot process, you just let the next plugin to continue. So that's all you need. Then you'll say, okay, so if I build this plugin, so what else do I need to launch this plugin? In order to start, you also need to initiate the plugin in the profile, the profile, the configuration, because our demo plugin, a hard code, everything. You saw the code, we use specific IP addresses in the go-down code. So there's nothing to config. As I said, that's a setup function. There's nothing. So we just invoke by specify that demo is a plugin we wanted to invoke. And that's it. Now next thing is going to say how to build that. In order to build this plugin, you have to do several things. First of all, you can just download a code in a source code. And your go-down plugin should be placed under the plugin directory. In addition to that, there's a plugin.configure which is needed in order to allow your go-down compiler to pick up this code and build. And that's it. There are some easy ways to compile this plugin. I managed to draft a pretty lengthy dummy doc build code that you can just get the job done. There are some flags to pass. That's mostly just to get around some security-related like restrictions. So you can just build it. If you run this one line command, it's several lines, but it's just one doc command. You can build your plugin as well as coding as code. And you will see a binary that's coding as local directory. And then you can just run this local directory. You can just run this coding as a binary. And that's it. Just one more thing is, you see like in the core file, you use 10.53. Of course, you can pick up for 53, but in case you pick up 53 in certain Linux system, you may realize that you need a root address. If you're just doing some testing, you can start with 10.53, which will avoid the collision. And that's it. Okay, so you're going to see where the source code. The source code is in the small repo. The repo is part of the coding as well. And if you just go to this repo, you're going to realize the whole repo consists of virtually 80 lines. And with 80 lines of Golan code, you'll pretty much write the service discovery based on the source IP. And why we showcase this plugin is because many people ask, okay, I want to achieve this thing. How to get the job done? Is there any core file we can use? And sometimes the answer has been, okay, it's a little, you know, if you just want to grab the existing plugin and tweak around some configurations to get job done, you know what? It's going to take some time to be a little creative to manipulating or even hack into the core file. And you're going to spend a lot of effort. And then if you say you wanted to learn Golan, you wanted to write some simple plugin, you can just maybe spend like several hours, write like 100 lines of code and get your job done, right? I think it's a fine process. Okay, so that's a demo plugin we showcased. As I said, you can go through this repo. You're going to realize it's super simple, extremely simple. That's something very important because we don't want to solve a problem in a complex way. We want to solve a complex problem in a simple way, not the other way around. Okay, so that's a demo plugin we showcased. And finally, we wanted to go through several bullet points about coding as a community. If anyone is interested in contributing to coding as, you have several ways to contribute. You can start coding as a GitHub to increase the visibility of coding as. You can also add your institution's name to adopt the start MD. This will actually allow you to have a chance to create a pull request. No, you can just create a pull request and should be easy. You can also become a maintainer. In order to become a maintainer, you probably need to contribute a significant pull request. What is the definition of significant pull request? If you write a plugin, that's a significant pull request. You also need to be sponsored by one existing maintainer, which is a very low threshold. And then you'll become a maintainer, which sounds like a small badge to you. And you can just let people know that you're also part of open source community and you're part of this CNC project and you're a maintainer. Right? So it's interesting you can do. Like I said, the lecture I mentioned, we have 28 maintainers. So the threshold to be a maintainer is extremely low. So just contribute something, address some Golan code, spend maybe several hours and have a little fun. Okay, that's pretty much it from our side. Any questions? All right, it looks like we have about five minutes for questions. So gentlemen here, there's a microphone there you can go stand at. That way you'll show up on the recording properly and whatever. Yeah, thank you for the talk. Very insightful. Also very interesting that GKE does not use cordiness. Thank you for this insight. I was wondering whether you considered using WebAssembly runtime as an extension to your current plugin system, because on the one hand side this would allow an author to create a plugin in basically any language, plus you would avoid the recompilation step of cordiness. You said wasm, is that what you said? WebAssembly wasm. Yeah, wasm. Okay. I haven't explored that. I mean, it's definitely a possibility. At one point, one of our maintainers was looking at adding Lua support, but I think that that's a reasonable thing to do. I have not looked at it and you're welcome to join in on GitHub and our Slack channel. We have a Slack channel on the CNCF Slack, but on the Kubernetes Slack and we'd love to see something like that. Right now you're right. It requires a recompile of, we don't have a dynamic plugin system. It's a built-in compiled in plugin system. All right, I have created a ticket. Any other quick, looks like there's somebody here. Hey, thank you for the presentation. Small question about the testing. What do you suggest for the testing of the plugins? Are there any tools or techniques? Well, unit tests for sure. Just go unit test, standard go unit test. We have some end-to-end tests that are part of our CI infrastructure. I don't recall what we're using there specifically, but years ago I put together a container image with some testing tools in it for DNS, but I don't have anything specific that I can recall off the top of my head. We do some performance tests. If we go look at the tooling we have in our CI, that's probably where I would start and pick up the tools that we have there. What if the plugin is not going to land in the main base, code base of core DNS? What if it is a homemade plugin and we would like just to run the tests in our CI, apart from the unit test of course? Yeah, I mean, whatever you're using your CI now, it's just a process. It's pretty straightforward. So as far as testing query tools, it all depends. If you're doing what you want to do, sort of end-to-end testing from a functional standpoint, then things like just your simple command line tools like dig or whatever are fine. But if you want to do load testing, sorry, it's been a couple of years since I looked at the testing tool, since I was working on the testing tools in this, so I can't recall. There's a few that we used to really, so one of the interesting things, and I don't have one minute left, like when you do start to do some of the load testing on DNS, you start to tend to be limited by things like the packets per second that your cloud provider will even allow on that particular level of node because the packets per seconds tend to be pretty high on the DNS server. So with a bunch of, do you recall any of the names of the tools? I would have to look it up. Frankly, I'm going to say, if you're going to test DNS, I mean, dig is certainly the best tool available, frankly. On the other hand, if you're going to say you want to write something in Golan, as you walk through the plugin, you'll probably realize the DNS by itself is fairly straightforward. You have the query, you're going to return a response. I mean, you can find many ways to test, frankly. Looks like we have one more question. Maybe we can sneak it in quick. We're being yelled at now. Yeah. So my question is based on how core DNS might be used or be helpful for like blockchain networks where you need to find peers and stuff like that. But it's a bit different because in this case, it's like some peers might behave in some way that you might not want to keep it up, but not about behavior, just like about finding the peers and maybe putting them down if it's not working anymore or something like that. And this is the first question in the following what is like, if those peers are not supposed to be kept in there, like in a file if they're not working anymore, or if we can find them anymore, like is deploying core DNS on a stateless service a way to go or that will be like a no go? I think I'm going to need a little more context and we're out of time. Why don't you come over here. We can talk about it offline. Sure. Okay. Thank you. Thanks everybody.