 Okay, let's get started. Welcome everyone to today's CNCF webinar, Delivering Cloud Native Apps to Kubernetes Using Worf. I'm Jerry Fallon and I will be moderating today's webinar. We would like to welcome our presenter today, Dmitry Stolyarovov, CTO, Flan. So a few moments, a few housekeeping items before we get started. During the webinar, you are not able to talk as an attendee. There is a Q&A box at the bottom of your screen. Please feel free to drop your questions in there and we'll get to as many as we can at the end. This is an official webinar of the CNCF and as such is subject to the CNCF Code of Conduct. So please do not add anything to the chat or questions that are in violation of the Code of Conduct. Please be respectful of your fellow participants and presenters. Please also note that the recording and slides will be posted later today to the CNCF webinar page at cncf.io slash webinars. And with that I will hand it over to Dmitry for today's presentation. Thank you very much, Jerry, for the invitation to this webinar and I am starting. So hello everyone. My name is Dmitry Stolyarov and as you already know, I am CTO and co-founder of Flan. Basically, the only thing I've done in my life is working in this company. So it was quite a nice journey and it says 10 years with Linux. Actually, it's like 15 or 17 years with Linux. So what I've been doing during my professional life almost all the time. It was Linux containers and everything around Linux and containers. Okay, and today I am talking about our open source project and the name, the right name would be not W, but W, because it's a Dutch name that came. Actually in Russian we also use the same name and it's the name for the shipyard. So it's a Dutch word for a shipyard that came in Russian in 17th century, I suppose. So before talking about any details, I want to just quickly go, quickly walk through about what Verve does and basically what you can do with it and basic principles of how it is working. Okay, so basic idea is that we have three main things that are interacting with each other. It's Git repository, Kubernetes cluster and Docker registry. In Git repository, when we talk about Verve, in Git repository we usually have, it's Git repository for our application. It might be one single application or it might be repository having several applications like back-end and front-end written in different languages. So for each application we of course have source code and Docker file and for some application we might have only Docker file if we, for example, want to deploy Redis as part of our installation and also we have a health chart with the manifests for Kubernetes. And what Verve does, it's kind of very simple and very clear thing. It just builds images, all images that you define in repository and it deploys manifests to Kubernetes. But what is important is that if we have one commit in the Git repo having this state and if at some moment we already build images for this commit, Verve will not rebuild them and Verve will give you idempotency, idempotence, determinism and kind of consistency of building process. So you can rerun Verve as many time. Oh, one important thing that I've missed. Verve is just a CLI tool and it's not an operator as you usually see when we talk about GitOps. It's just a CLI tool that can be run, for example, from CI system or from your laptop or from anywhere. So what it does is synchronizes the state of the registry to the state defined in the Git and the state of Kubernetes to the state defined in the Git. Okay, so when you commit, when we run Verve, what it does, it calculates digests for each Docker file, checks them in Docker registry whether they exist there or not, and then checks the state of Kubernetes whether it matches the manifest defined in Git repository. And if something doesn't match, it just changes the state defined in the Git. It converges, it converges the state of the Docker registry to the state defined in the Git and it converges the state of Kubernetes to the state defined in the Git. So if, for example, some user will change anything in Kubernetes directly and you can then rerun Verve on the same commit, it might be branch or Git tag or just check out any random check out commit. And if you rerun Verve on the same commit, what you will have is just the state restored back from what user changed. So it makes kind of small fans that protects Kubernetes from direct changes from users and this fans kind of motivates user to make his changes directly, not to make changes directly to Kubernetes to make changes to the single source of truth in the Git. So that's kind of a basic idea. Then if we change something, for example, in this example, we changed source code of front-end and if after that we rerun Verve, it will detect that only one source code has changed, only one of application existing in repo changed. So it will rebuild only one image and roll out only one of the deployment. And basically, same happens with HelmChart. If we change only HelmChart, for example, only manifest for a inverse resource, Verve will only change inverse resource in Kubernetes, but that's merit of Helm, that's merit of Kubernetes API. So that's kind of, we just send them, we just send to the Kubernetes manifest and it does what it does. One important thing is that Verve provides very good feedback. So basically when you run it, it says you, okay, let me be clear here. When you run Helm install or when you run kubectl apply, both of them says you successfully, successfully completed, successfully applied, successfully finished. But you know that when Helm says you that chart is installed or when kubectl says you that file is applied, it doesn't mean that your changes were really applied. It doesn't mean that they were rolled out. It only means that Kubernetes received the request for rollout. And then if, for example, new version of your application is not responding well, the deployment will not roll out new version. So from these tools, from Helm and from kubectl, you usually don't have direct feedback whether you successfully deployed, whether your changes were successfully rolled out. You have only part of feedback. So what Verve does, and we worked on this part a lot, is providing feedback on what's going on, how rollout is going on. And I will show you during the demo time this part extensively. So, okay, another thing that Verve does is basically when there is a difference between, like, big difference between two commits, of course it can build what should be built and apply what should be applied. So you can think of Verve as of just a thing that can change docker registry to the desired state and change Kubernetes to the desired state in one simple run. And you can make many, many, many commits, change between them, and you just check out commit, run one CLI command, and you change Kubernetes to the desired state. Okay, so that's kind of a very quick overview of what Verve does. And now I want to show you, I want to quickly show you, like, to walk you through all the steps you need to do to deploy some simple, some small, simple application with Verve. And I will start with a very basic thing with installation. And to do this, I have already a completely clean virtual machine, a completely clean VM. The only thing I did is I've run up to update, I've installed docker, and I've pulled few images just to not to waste time viewing the presentation. So it's completely new, completely clean VM with just docker installed. And if we open Verve.io installation, we can find that I will use alpha version of 1.2, and that's because for 1.2, unfortunately, the website says different, but for 1.2, there is only one version that exists, there is only one channel for now, it's alpha, and I want to use version 1.2 because we switch to home 3, and I think it's kind of important change, and I don't want to show during this webinar version that will be kind of deprecated in few months. So it seems for me much more reasonable to show, yes, it's alpha version, but it will be stable at least in early access channel. By the way, I will talk a little bit more about delivery, about how we deliver new versions. But it will be in early access or stable in a month, so I suppose you can kind of try it now during development and when you will be ready for deploying something to production, it might be already in stable. So first of all, you need to install dependencies, and the only dependence, okay, Verve has two dependencies, so I don't know why, but it looks like Git is pre-installed in Ubuntu, and I've already installed Docker, and documentation for Verve suggests you to add kind of yourself to user group Docker to be able to run Docker without any permission problems, because by default you cannot do this, so the only thing I'm doing is just adding myself to the group, and yeah, I can run Docker, and that's probably the only dependency we need. Then we need to create bin directory in our home. Of course, you can choose to any other location, but that's kind of the easiest, and then you can use just one liner to get not Verve, but multiverve. Multiverve is a tool that does two things. It basically checks whether a new version is released, and if it's released, it downloads it, and then it garbage-collects old versions, so it's kind of a simple delivery tool, and it's very convenient to use, and we recommend instead of downloading an exact version, like for example, for now it's 1.2.0-9, instead of downloading one version and sticking to one version, we strongly recommend using multiverve, and with multiverve we can use... It's easier to show. Now I've added this line to my bash RC, so if I re-enter, restart my session, you can see that it just downloaded the latest version, and now I have the latest version of Verve, and you can easily switch between different channels, and it's very convenient if you use it from CI system, but you don't have to install an exact version on a runner, on a CI runner, you have to just choose 1.1 or 1.2, like a minor version, and then all the bug fixes, you will get all bug fixes automatically, and we guarantee... We really work a lot on backward compatibility, and we guarantee full compatibility inside minor versions, so it can be updated automatically. We recommend updating it automatically. So that's it. We have now Verve installed. It's written in Go, so it's just a single binary, static binary, and it's very, very easy to install. Okay, next step. We want to deploy something to Kubernetes, and to do that, we need something, we need application to deploy to Kubernetes. And I already have something prepared, and I will just clone it to this VM, and we'll show you what it is. Okay. And here we have kind of the simplest possible application in Node.js. It's only one file, and it's super short and super simple, and what it does, it just serves Hello World when you get root, when you access root. So, and we also have package.json having information about our dependencies, and the only dependency we have is Express. Express is a small framework for building applications in Node.js. Okay, next step, the next step we need is actually Dockerfile, we don't have Dockerfile, and I will use just prepared commits from, I have prepared commits, so I will use them and show you what changes, what's happening. So, I've added two things to repository. One is Dockerfile, and another is Verve YAML, and Verve YAML lives in the root of the repository, and Dockerfile lives in the directory with the backend. And what we have in the Dockerfile, it's a very, very basic thing. Sorry. I know what's happening. I've used Reset in Git, and yeah, sorry, a bit, a bit. Okay, so we have very basic Dockerfile, and it uses just Node.js image, and it adds our application to some location, and it runs NPMCI. Okay, and what we have in Verve YAML, it's also a very simple thing. We have one section describing the name of the project, and one important thing that the name of the project should be unique, and it shouldn't change, because based on this name, a lot of things are automatically generated, like namespace, or the name of the helm chart, or the name of the helm release, and so on. So you better choose unique and stable name. And then you can add as many, as many of these sections as you need. For example, you have backend and front-end, you can call one image backend, another image front-end, and use just two different Dockerfiles. Or you can use one Dockerfile, and if you have multi-stage Dockerfile, and you have named stages in this Dockerfile, you can tell Verve use this Dockerfile and build this stage, and it will do it. Okay, and now the only thing we need to do is to execute Verve. I will start with building, and we need to execute Verve build, but we need to provide the address of the Docker registry that we will use for storing images. And as I've already told, it's this registry, so if we execute Verve build, it converges the state of the registry to images defined in the git. Okay, so I don't remember address for the registry, but I have special file with memos. So very simple and kind of straightforward command Verve build, and we tell the address of the registry. What is important is that you can have distributed runners, and you can execute from different runners Verve build, and it will synchronize itself, and it will make everything correctly. Okay, during build Verve pushes all the stages to registry, and if you run concurrently multiple instances, just of, I don't know, Docker build, Docker push, they will be competing with each other on a... There might be a race condition, okay? Distributed race condition. So that's completely solved in Verve because we just use synchronization algorithms, and we have different implementations of lock server. We can use Kubernetes API to synchronize multiple instances of Verve, or we can... Verve has its own kind of embedded lock server, and we just run publicly available version, because the only things that are sent to this server is digest, so it's nothing... There are no security problems with that, so, okay, I'm executing Verve build. And explaining what's going on. First thing that happened is that Verve acquired a lock from our publicly available synchronization server, so you can run multiple instances. I've already told you about that. Second, it created so-called Staple container. It's just an internal container with special tools we use during build process, and Staple is also Dutch word, and it's kind of sleep way. So when you build a ship, you need to launch it to the sea, so you use sleep way, and we... Of course, like everything around Kubernetes, we usually use words from Siemenship vocabulary. Okay, and then, because it's Dockerfile, it's just standard Docker output, but it's just pretty printed, and it shows that it successfully built our Dockerfile, and I don't know what's happening, but I suppose it's just Docker push. Like always, when you do online demo, something happening. Okay, that's really scary, but we can use verbose mode. Yeah, it's my registry that is not very fast. Why? It's not very fast. Sorry. Oh, everything went well. So it built and pushed. The reason for that is that not JS image I'm using, I don't know why I'm using such large image, but it's like 900 megabytes, and it's just our DIY open stack that we use only for development. Well, it has its little problems. Okay, so what we have now is image that is built and pushed in registry, and it was tagged, and for tech we use such a long string, but that's basically a digest of the source code and the things you have used in the Docker file, and it's a digest that is stable across multiple runners. I will show you this just in a moment. And we can rerun this command as many times as we want, and after it successfully built image once, it will not change anything because nothing has changed in source code. Okay, from this moment, I will switch to another VM having this same repository with my commits, and I will use the same commit, but on another virtual machine to show you that I can run the same command from multiple VMs, and it will give the same result. So as you can see, the tag is same. 472A, 472A, and it ends with 9274, 9274. Yeah, that's the same, and we can run as many times as we want this command, and now it's running garbage collect because on the other VM I've already have been using there for some time, and it utilizes a lot of, it generates a lot of cache, but it garbage collects it, so it's kind of built to run from CI, so when you run something from CI, you need time to time to run garbage collect to just collect, but we can do it as many times as we want, and it will be doing it always correctly. Okay, next step, we want to deploy this app to Kubernetes, and on the second VM, I already have kubectl, and I already have access to some Kubernetes cluster, and we'll switch to next commit and show you what we have in Helm. Okay, so what was added to the repository? Maybe this? Oh, no, that's not... Yeah, Helm. So basically, the only thing that was added to the repository with the new commit was a directory with a Helm template, so it's called .helm, and you can change this name to another by default, verfuse.helm, and it's simplified chart, so we have value.syaml with only one value, it's like .isdeback with a true value, and in Tinklates we have directory with back-end, and here we have deployment, service, and ingress. Let's just very quickly walk through them. So, name nothing interesting, it's just basic deployment, selector nothing interesting, nothing interesting, what's interesting is an image. So, we use just special template that returns the name of the Docker registry we used and tag that verf-calculate, and generate it. Yeah, that's basically the most important part. In ingress we have just basic definition for ingress, we use nginx ingress, so it's for nginx, and in services just basic declaration of service that points to our deployment. Okay, what can we do with this? We can use command that is named converge, and most of the time you need to pass two or three arguments to converge. One is the same as for build, the address of the Docker registry, another is name of your environment, it might be staging, testing, production, and so on, and the third one that I'm not using is kubeconfig. If your kubeconfig is not in standard location, you need to pass where it resides. Okay, so verf-converge, and I press enter, and what's happening is, first of all, it builds images, but because I've already executed verf-build, it has nothing to build, so it goes to the next step and it converges kubeconfig to the desired state, but basically, verf has a helm compiled in with a small additions, and the largest, what we've changed in helm is the way how we show feedback. As you can see here, it says release with the name verf-demo staging, and verf-demo is the name of our project from verf-demo file, and staging is because I passed minus, minus, and staging to the command. Okay, I'm increasing the speed and starting talking less because it's only 20 minutes left. So, as you can see, it says waiting for release resource to become ready. Let me just quickly change something in helm. I will show you what we will change. So, what we are changing is we are introducing the first version deployed on the domain example.com, and of course, we don't own example.com, I don't know who owns, and probably it's just recommended by RFC domain to use in examples. So, of course, it will not work. But now we use values, we use helm values to read the hostname from. So, Coupctl name space verf-demo staging, get ingress, and it says example.com. And if I use a command like that, passing with a minus, minus, set app.hostname with the value with some really long hostname, what will happen is now our ingress is configured for the right domain so we can try to access it, and yeah, it shows hello world. So, our application is running. Okay, next step. Next step. And next step would be very easy. We don't want to pass this param each time. So, we use values YAML, and we have value for staging and for production. So, and different, we use different hostnames for staging for production. So, now I don't need to pass this param, and I also can create another environment just by using, just by using, by passing another argument. And so, what will happen is we will have another name space. So, now we have two, one for staging, one for production. Okay, what next? What next? Okay, I know what next. I want to change my application, and to do it, what I can do is just modify app.js and say, instead of hello world say, for example, hey, hey, world. That's, and I make a commit with that. And if I now run verveconverge, the same command, the same command that we already used, first to staging, so, of course, what we will have is new image is built, and it takes some time, as you can see, because it's, it's rebuilding Dockerfile from the beginning. And then it will be pushed to registry, and then changes will be applied to Kubernetes. So, now, yeah, it's done. So, and you can show, you can see that verve shows, says that one pod is terminating, another one is already running. And we can use, we can check that, yeah, we have, we have new text from our backend. Okay, one more important thing from verve. Instead of using Dockerfile, you can use our, our own builder that is called Stapel, but what is, what is very, very good is that it has very, very powerful integration with Git. I will show you just one example. So, what we, in previous example, we had only, only three lines here with the image. It's better, it's better to show, it's better to show changes from the Git. So, image name, same, Dockerfile and context removed, and added from, it's the same as a Dockerfirm. Git is smart integration with Git. I will show you what, what, what, what I mean by smart. And it basically adds slash backend to slash app. And I will not go into the details, but what is important is when package.json changes, it will reexecute npmci. But if package.json hasn't changed, npmci will not be reexecuted. Okay. I run vervconverge. It will take some time to build it once again, because it's not, it's not built. We switch, we switch builder from Dockerfile to Stapel. So, it's, it needs some time to rebuild it again. We better wait just a few seconds. And it says image is built. But then what's, what's really beautiful is that when we change our app.js once again, it, it's hello world again, because I use git reset. So, but we will change it to, it to hello comma world. And now when we run vervconverge, you can, you can see that image is built in, oh, sorry, that's too fast, because I haven't committed it. Sam, comma. So the only thing that was done is vervcalculated div from previous commit to current, and then use previously built image and only apply patch. So that's kind of powerful integration with git that, that I call. If you, if you want to read more details, I will show you where can you, where you can get them. Okay. I just want to show one, one important thing. If I add readiness probe, yeah, that's it. And I've made a mistake and my container is listening on the port, on port with number 3000, and I'm checking 3000, 3001. So of course it will not work, but what's important is that if we run vervconverge, it will go through image building part fastly and then it will not exit. It will show you the progress and it will tell waiting for replicas. It's a bit strange. It waits while it will be one ready replica and now it's two replicas. Old one is ready. It's still ready. And new one is not ready because the, the Lineness probe is wrong. I can go to next commit and what this commit does is it adds another container to our deployment. Noisy sidecar. And it's just, it just logs some log each, each second. And if we, if you, if we try to converge this comment, what we will have is, you will just, you will, you will see in just a moment. So you can see that verv outputs log messages from containers during waiting, waiting phase. And you can, you can control how much of this logs you receive by different annotations. For example, you can use skip logs to completely disable log printing on, or you can skip logs from several containers in a pod, or you can show logs for only from some containers. You can basically filter by regular expressions and so on. And also you can define how verv will, will track failure mode. For example, by default, we allow some amount of failures per replica. And verv will wait while, you know, while your application will be deployed. Okay. And the last commit I have, which I will show you today is just, just this one. And what it does is just fixes the port for, for readiness prop. And now if you, if we use verv converge, it will, it will finish successfully. This time it should finish successfully. Yeah. And it's successfully, it's successfully finished. Okay. It's only eight minutes left. So I probably will go to presentation and make some final, final notes quickly. And then if we will have time, we will go through questions if there are any. So what's next? This demo project that I've used will be published just in a few minutes after, after this presentation on the, on the shown, on the link shown. So it's GitHub, verv and the repository name demo and today's date. We have a very good quick start with more comprehensive project. So you can try it. We also have a lot of information about how you can use verv from CI and you can start with using with CI CD systems. So if you open verv.io documentation, you can find using with CI CD systems. And that's kind of basic generic information. But if you want to go deeper, you can open advanced CI CD and then CI CD workflow basic and you can find different approaches that you can use with GitLab or GitHub or any other CI system with verv to make it really effective and efficient and different approaches how you can deliver things. Okay. We have also very comprehensive guides, but for now only in Russian, but they are under translation. Sorry, it's really hard for us for all my colleagues to fluently write in English for now. We are learning English, but need some time. So some of things are written in Russian but as far as we know, you can use Google Translate and to try, but probably in a month it will be in English. Okay. I'm going very quick. Where to ask questions? We have a discourse server and basically this right button will lead you to the community.flam.com. We just launched it and we will be very happy to answer any questions there. Oh, it should be, do we need help? Yes. And if you can approve the documentation, if you will be trying verv and you will find some mistakes, please send a PR, it would be beautiful. One important thing about GitOps, the website says GitOps done another way. I have not yet published a video about what we think about GitOps and our approach to GitOps and the link is in, you can see it on the slide. And please subscribe. It's our actually first video in English so we will be very happy if you subscribe to our channel. Thank you very much for your attention. Thank you very much for your time. If you would like, if you will like verv, please don't forget to start. And Jerry, I'm finished. I'm sorry, it's four minutes till the end. Not a problem, not a problem Dimitri. Thank you for that wonderful presentation. We have a few minutes for questions now. So if anyone has any questions, please just drop them into the Q&A box and we'll get to as many as we can. Do we have any? At the moment, no. But so if anyone, if you guys have any questions at all, please feel free to drop them in. While we are waiting for questions, I can just quickly walk through what we have in the documentation. So it's like overview shows basically what I've already shown you in presentation. Introduction is just... Oh, sorry, introductions, what I've shown you in the presentation. Overview is just how the commutation is structured. Quick start is a quick start. It quickly walks you through basic steps you need to do to try them. And using the CI-CD systems, we have two integrations with the GitLab and GitHub. And you can use this guide to adapt Verve to your own CI system. It might be anything like CircleCI Jenkins, whatever. What else? There are some limitations on using registry because, oh, I've skipped this part. Verve has comprehensive cleaning things to clean. Jerry, I see some message in there. So we have a list of supported registry because Verve has part that can clean registry based on the state of the Kubernetes and the state of the Git. So if we know that this image is not used in Kubernetes and according to Git history, it's very far. We clean it in the doc registry. And because we are deleting images from registry, this part is not implemented in the same way between all the registry. We have some limitations, but we've done a lot of work to support as many as we can. So basically, all major doc registry limitations are supported. Jerry, do we have any questions? No, we do not. Okay. I would think that I've done a good presentation and answered all questions. I think that was one of my friends. Well, that being said, that will wrap up today's presentation. Dmitry, I want to thank you again for your time and for the wonderful presentation and for everyone who joined us today. We'll see you with the next CNCF webinar. Everyone, take care, stay safe, and we will see you next time. Thank you. Bye. Thank you.