Imagine a company named ACME Technologies that has been using Argo CD for continuous delivery to their Kubernetes clusters. They use resource hooks to schedule certain jobs which can be deleted automatically based on pre-configured hook deletion policies. However, a developer failed to use the recommended guidelines to set the parameter '/metadata/name` with 'BeforeHookCreation' as its value. This led to jobs not being cleaned up and a misconfiguration in production.
Situations like these can easily be avoided by putting a policy in place to check the parameter value automatically before deployment. Different tools allow you to create policies and take preventive action. Tools like OPA, Rego, and, Trivy allow us to enforce security policies and ensure compliance. However, for scenarios like the above where enforcing generic policies is required, Monokle shines as it allows us to create custom policies and validations.
By leveraging Monokle's custom policy validation framework, we can efficiently enforce such policies, and ensure that they are applied consistently helping to mitigate risks and ensuring that your organization complies with its obligations for security and best practices. In this blog post, we will explore custom policy validators, write a policy rule, and demonstrate how to enable it for a manifest using Monokle.
A policy validator is a tool to verify that manifests conform to specific rules and guidelines, such as compliance regulations or security best practices. Monokle has its implementation of a policy validator, called the custom policy validator that allows organizations or developers to define their own policy validation rules that are tailored to their unique needs.
The Monokle validation framework offers several benefits, including
By using the Monokle validation framework, organizations can improve their policy management processes, reduce the risk of errors, and increase overall efficiency.
Monokle provides a library that makes getting started with policy validation much more convenient. Using this library, we will create the template files which are essential for plugin development. To get started, we will make some basic changes and then write a custom policy. Using Monokle Cloud, we will enable it to validate our manifest for compliance. You can also make use of Monokle CLI to enable the custom policy.
To understand how custom policy works in Monokle, we will create a policy that checks the memory consumption of deployment resource containers on the development server. Complying with this policy will limit the developers from exceeding the optimum resource utilization for the dev environment.
The solution to this use case can be split into two parts as policies:
Let us go ahead and set up the prerequisites to get started with configuring and enabling the above two policies.
With the pre-requisite setup, we can get started with configuring the first policy using the Metadata plugin. Once done, we will then set up the plugin for creating a custom policy using the library provided by Monokle.
With Metadata Plugin, we can create a policy on the go to check for the metadata. It allows us to add metadata as a key value for labels and annotations. In this use case, we need to check if the env label is set for resource and has a value `dev`.
Access the repository in Monokle Cloud. In the Toolbar, click on the validation icon, scroll to the bottom, and use the toggle button to enable the Metadata plugin.
Click on Configure and select the metadata type as Label. Enter the key and the expected possible values. Click on `OK`.
Great! The policy to check if resources are for the dev environment only is ready to use. Let us go ahead and get started with creating a custom policy for checking memory consumption, importing it as a plugin, and enabling developer mode to allow integration in Monokle Cloud.
The developer mode allows interaction with the policy plugin in Monokle Cloud. Once enabled, you can configure the plugin after development. To get started, select your Kubernetes resources repository for which you want to enable validation in Monokle Cloud.
Select the validation icon from the Toolbar, scroll to the bottom in the Validate your resources pane, and click on the toggle button to enable developer mode.
Great! Now that developer mode is enabled, when you run the development server on your local machine, Monokle will automatically sync the changes you make in the plugin in real time.
Clone the GitHub repository of the library.
```
$ git clone https://github.com/kubeshop/monokle-core.git
```
Change the directory to `create-monokle-plugin` directory and initiate the creation of the plugin package using the following commands:
```
$ cd monokle-core/packages/create-monokle-plugin/
$ npm create monokle-plugin@latest
```
This will initiate the plugin setup in interactive mode as shown below:
```
$ npm create monokle-plugin@latest
✔ Plugin name: … resource-limit
✔ Select a plugin type: › validation
✔ Select a variant: › validation-ts
✔ Select a template: › basic
Scaffolding plugin in /kubeshop/test_setup/resource-limit...
Done. Now run:
cd resource-limit
npm install
npm run dev
```
Let’s dig into what happens in each of these steps.
You can continue pressing enter for each step further as Monokle takes care of filling in all default values.
Once the plugin setup is complete, a directory will be created with the `plugin name` provided that contains the package for the plugin.
Change the directory to the newly created directory for the plugin and initiate installation.
```
$ cd resource-limit/
~/resource-limit$ npm install
> resource-limit@1.0.0 postinstall
> npm run codegen
> resource-limit@1.0.0 codegen
> monokle-plugin-toolkit codegen
added 166 packages, and audited 167 packages in 5s
14 packages are looking for funding
run `npm fund` for details
```
Refer to our tutorial to understand the autogenerated files that are essential for plugin development.
The package.json maintains the package details. Update `author` in `package.json` for the unique identification of who is maintaining the package.
```
{
"name": "resource-limit",
"author": "Sonali Srivastava",
"description": "Validates with custom rules.",
"license": "MIT",
"version": "1.0.0",
"main": "dist/plugin.js",
"type": "module",
"scripts": {
"postinstall": "npm run codegen",
"codegen": "monokle-plugin-toolkit codegen",
"dev": "monokle-plugin-toolkit dev",
"build": "monokle-plugin-toolkit build",
"debug": "monokle-plugin-toolkit build --debug"
},
"dependencies": {
"@monokle/plugin-toolkit": "^0.1.0"
}
}
```
In the above codebase for `package.json`, we have updated the `author` value from unknown to maintainer name.
Next, update `/src/plugin.ts` which maintains the plugin metadata. This information will be visible in Monokle Cloud when the plugin is imported which will help in identifying it.
```
import { definePlugin } from "@monokle/plugin-toolkit";
import { noEmptyAnnotations } from "./rules/1-example.js";
export default definePlugin({
id: "YCP",
name: "ycp",
displayName: "Resource Limit Check Plugin",
description: "Optimize your resource utilization!",
rules: {
noEmptyAnnotations
},
});
```
In the above codebase for `/src/plugin.ts`, update the `displayName` and `description` for the plugin specific to your requirements. Once the file is saved and the development server starts, you should be able to see the custom basic changes in the plugin in Monokle Cloud. Now, let’s head over to the terminal and start the development server.
Execute the following command to make the plugin available in Monokle Cloud. This command will start the development server, ensuring that any saved changes to the plugin package are immediately reflected in the Monokle Cloud in developer mode.
```
~/resource-limit$ npm run dev
> resource-limit@1.0.0 dev
> monokle-plugin-toolkit dev
Monokle dev server (beta)
You can now develop and preview your rules in real-time within Monokle Cloud.
tip: make sure you have developer mode enabled.
```
The custom display information and the default rule are available in Monokle Cloud and can be enabled using the toggle button. Click on Configure to view the default rule.
Plugin available in Monokle Cloud
Now that the plugin is ready, we can add our custom policy to it. In this section, we will write a custom policy. As per the policy, each Kubernetes deployment resource for the `dev` environment can only consume 1G of memory.
Create a new Typescript file named `2-ensureMemLimit.ts` in the /src/rules directory. Import function `defineRule` which will be used for defining the policy rule. Set a name for the policy and get started with writing the policy. The `defineRule` function takes a unique ID, a description, help text, and the validation rule.
In this rule, for each deployment resource, check for the memory limit of containers. The value allowed for memory consumption is 1G. In case the value does not match, report a violation of policy along with the line where the violation is happening. All the configuration files in this setup are available on GitHub.
```
import { defineRule } from "@monokle/plugin-toolkit";
import { isDeployment } from "../schemas/__generated__/deployment.apps.v1.js";
export const ensureMemLimit = defineRule({
id: 2,
description: "Please ensure mem limit is set to 1G for dev env deployments",
help: "Value allowed is 1G",
validate({ resources }, { report }) {
resources.filter(isDeployment).forEach((deployment) => {
const containers = deployment.spec?.template?.spec?.containers;
if (containers) {
for (const container of containers) {
if( container.resources?.limits?.memory !== '1G' ){
report(deployment, { path: "spec.template.spec.containers" });
}
}
}
});
},
});
```
Save the file. The policy created above that contains the rule needs to be imported into the plugin.
`/src/plugin.ts` maintains the plugin metadata including the display information and rules. Add the policy by importing it to the rule path as shown below and adding the rule in `rules`:
```
import { definePlugin } from "@monokle/plugin-toolkit";
import { noEmptyAnnotations } from "./rules/1-example.js";
import { ensureMemLimit } from "./rules/2-ensureMemLimit.js";
export default definePlugin({
id: "YCP",
name: "ycp",
displayName: "Resource Limit Check Plugin",
description: "Optimize your resource utilization!",
rules: {
noEmptyAnnotations,
ensureMemLimit
},
});
```
Save both files that have the policy and the plugin metadata. Run the development server in the terminal. That should allow us to directly view and manage the plugin in Monokle Cloud.
Open Monokle Cloud in the browser and click on the validation icon in the toolbar to access the validation setup. The new plugin is added, and the policy is enabled to apply to the manifest. For verification purposes, change the memory limit value and see if a warning is returned.
Congratulations!! Your memory consumption validator is ready to use. The policy is set to notify as a warning when the policy is violated. Monokle Cloud highlights the issue with a warning sign along with a simple description and a helpful dialogue text box to assist all project members in setting the memory limit to 1G as established by the custom policy you created and plugged into Monokle for the dev environment.
Thus, Monokle saves a lot of time and effort in manually checking every time the env for which the resource limit is intended. Also, it will reduce the risk of accidentally deploying resources with misconfigurations to specific environments. In case you want to develop a plugin and share it across your organization, you can do so by maintaining a repository like the Monokle community plugin.
For scenarios like complex data analysis or parameterized data, the organization needs custom policy validation to mitigate risk and comply with its obligation. Monokle's policy as a code approach streamlines the development process and increases developer productivity.
Moreover, Monokle fosters collaboration and community contribution by providing a platform for developers to create and share custom plugins. All you have to do is fork this repository, add your plugin in `/validation`, and raise a PR.
With Monokle, we have seen how much easier it is to frame your organization's custom policy into a validator and enable that in Monokle to apply on Kubernetes manifests. Future versions of Kubernetes will add similar rules for ingress policies. With Monokle’s custom policy validators, you can tailor your policy enforcement to your specific needs, ensuring that you're always in compliance and reducing the risk of costly mistakes. So, whether you're an IT professional, a compliance officer, or just someone interested in keeping your organization on track, custom policy validators are an absolute must-have.
You can also reach out to Monokle Product Leader Ole if you have feedback about how we can make Monokle work better for you or drop a mail to ole@kubeshop.io for information/assistance. You can also join in conversation with other users via Discord as part of our growing community.
Join the Monokle Community in one of these channels:
Subscribe to our monthly newsletter to stay up to date with all-things Monokle.