{"id":18481328,"url":"https://github.com/ukhomeoffice/kd","last_synced_at":"2025-04-08T16:31:53.313Z","repository":{"id":10620529,"uuid":"66381970","full_name":"UKHomeOffice/kd","owner":"UKHomeOffice","description":"Minimalistic kubernetes resources deployment tool with templating","archived":false,"fork":false,"pushed_at":"2023-02-02T09:17:50.000Z","size":389,"stargazers_count":84,"open_issues_count":18,"forks_count":27,"subscribers_count":30,"default_branch":"master","last_synced_at":"2025-03-23T16:39:18.743Z","etag":null,"topics":["cli","deployment","docker","kubernetes","tool"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/UKHomeOffice.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-08-23T16:00:41.000Z","updated_at":"2025-02-18T09:43:55.000Z","dependencies_parsed_at":"2023-02-17T17:45:36.771Z","dependency_job_id":null,"html_url":"https://github.com/UKHomeOffice/kd","commit_stats":null,"previous_names":[],"tags_count":58,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UKHomeOffice%2Fkd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UKHomeOffice%2Fkd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UKHomeOffice%2Fkd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UKHomeOffice%2Fkd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/UKHomeOffice","download_url":"https://codeload.github.com/UKHomeOffice/kd/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247882113,"owners_count":21011995,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","deployment","docker","kubernetes","tool"],"created_at":"2024-11-06T12:23:16.199Z","updated_at":"2025-04-08T16:31:52.829Z","avatar_url":"https://github.com/UKHomeOffice.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# kd - Kubernetes resources deployment tool\n\n[![Build Status](https://travis-ci.org/UKHomeOffice/kd.svg?branch=master)](https://travis-ci.org/UKHomeOffice/kd) [![Docker Repository on Quay](https://quay.io/repository/ukhomeofficedigital/kd/status \"Docker Repository on Quay\")](https://quay.io/repository/ukhomeofficedigital/kd)\n\nThis is a very minimalistic tool for deploying kubernetes resources.\n\n## Features\n\n- Go template engine support\n- Supports any kubernetes resource type\n- Polls deployment resources for completion\n- Polls statefulset resources (only with updateStrategy type set to [RollingUpdates](https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#rolling-update)).\n\n## Running with Docker\nNote that kd can be run with docker, [check here for the latest image tags](https://quay.io/repository/ukhomeofficedigital/kd?tab=tags)\n\n```bash\ndocker run quay.io/ukhomeofficedigital/kd:latest --help\n```\n## Installation\n\nPlease download the required binary file from the [releases page](https://github.com/UKHomeOffice/kd/releases)\n\nFor Mac Users - Please download release `kd_darwin_amd64` and run the following commands. These will ensure the binary is renamed to 'kd', it's also in your `${PATH}`, and that you have permissions to run it on your system.\n```bash\nmv ~/Downloads/kd_darwin_amd64 /usr/local/bin/kd\nchmod u+x /usr/local/bin/kd\n```\n\n## Getting Started\n\nThe is only requirement and that is a kubectl binary in your `${PATH}`. You\ncan use the docker image or download the binary for your OS from\n[releases](https://github.com/UKHomeOffice/kd/releases) page.\n\nFirst, let's create a simple deployment template. Templating data comes from\nthe environment, so in this example we'll use `NGINX_IMAGE_TAG` environment\nvariable to set nginx image tag.\n\nCreate a `nginx-deployment.yaml` with the following content:\n\n```yaml\n---\napiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: nginx\nspec:\n  replicas: 5\n  template:\n    metadata:\n      labels:\n        name: nginx\n    spec:\n      containers:\n        - name: nginx\n          image: nginx:{{.NGINX_IMAGE_TAG}}\n          ports:\n            - containerPort: 80\n          resources:\n            limits:\n              cpu: \"0.1\"\n          livenessProbe:\n            httpGet:\n              path: /\n              port: 80\n            initialDelaySeconds: 10\n            timeoutSeconds: 1\n```\n\n```bash\n$ export NGINX_IMAGE_TAG=1.11-alpine\n$ kd --context=mykube --namespace=testing --file nginx-deployment.yaml\n[INFO] 2016/09/21 14:06:37 main.go:153: deploying deployment/nginx\n[INFO] 2016/09/21 14:06:38 main.go:157: deployment \"nginx\" submitted\n[INFO] 2016/09/21 14:06:41 main.go:194: deployment \"nginx\" in progress. Unavailable replicas: 5.\n[INFO] 2016/09/21 14:06:56 main.go:194: deployment \"nginx\" in progress. Unavailable replicas: 5.\n[INFO] 2016/09/21 14:07:11 main.go:190: deployment \"nginx\" is complete. Available replicas: 5\n```\n\nYou can fail an ongoing deployment if there's been a new deployment by adding `--fail-superseded` flag.\n\n### Replace\n\nkd will use the `apply` verb to create / update resources which is [appropriate\nin most cases](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#in-place-updates-of-resources).\n\nThe flag `--replace` can be used to override this behaviour and may be useful in\nsome very specific scenarios however the result can be a [disruptive update](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#disruptive-updates)\nif extra kubectl flags are applied (such as `-- --force`). Additionally, the last-applied-configuration is not saved when using this flag.\n\n#### Cronjobs\n\nWhen a cronjob object is created and only updated, any old jobs will continue and some\nfields are immutable, so use of the replace command and force option may be required.\n\n```bash\n# The cronjob resource does not yet exist, and so a create action is performed\n$ kd --replace -f cronjob.yml -- --force\n[INFO] 2018/08/07 22:54:00 main.go:724: resource does not exist, dropping --force flag for create action\n[INFO] 2018/08/07 22:54:00 main.go:466: deploying cronjob/etcd-backup\n[INFO] 2018/08/07 22:54:00 main.go:473: cronjob \"etcd-backup\" created\n\n# The resource now exists, so a kubectl replace is performed with the extra --force arg\n$ kd --replace -f cronjob.yml -- --force\n[INFO] 2018/08/07 22:54:02 main.go:466: deploying cronjob/etcd-backup\n[INFO] 2018/08/07 22:54:03 main.go:473: cronjob \"etcd-backup\" deleted\ncronjob \"etcd-backup\" replaced\n```\n\n#### Large Objects\n\nAs an apply uses 'patch' internally, there is a limit to the size of objects\nthat can be updated this way and you may receive an error such as: `metadata.annotations: Too long: must have at most 262144 characters`\n\nBelow is an example for updating a large ConfigMap:\n```bash\n# 859KB ConfigMap resource\n$ kd --replace -f configmap.yaml\n[INFO] 2018/08/07 23:02:39 main.go:466: deploying configmap/bundle\n[INFO] 2018/08/07 23:02:40 main.go:473: configmap \"bundle\" created\n\n$ kd --replace -f configmap.yaml\n[INFO] 2018/08/07 23:02:41 main.go:466: deploying configmap/bundle\n[INFO] 2018/08/07 23:02:42 main.go:473: configmap \"bundle\" replaced\n```\n\n### Run command\n\nYou can run kubectl with the support of the same flags and environment variables\nthat kd supports to simplify scripted deployments.\n\n```bash\n$ export KUBE_NAMESPACE=testland\n$ kd run get po -l app=myapp -o custom-columns=:.metadata.name --no-headers\n```\n\n## Templating\n\nYou can add the flag --debug-templates to render templates at run time.\nCheck the examples folder for more info.\n\n[Sprig](https://masterminds.github.io/sprig/) is used to add templating functions.\n\nTo preserve backwards compatibility (parameter order) the following functions\n still use the [golang strings libraries](https://golang.org/pkg/strings/):\n\n- contains\n- hasPrefix\n- hasSuffix\n- [split](#split)\n\nkd specific template functions:\n\n- [file](#file)\n- [fileWith](#fileWith)\n- [secret](#secret)\n- [k8lookup](#k8lookup)\n\nExtra template functions (from helm):\n\n- [strvals package](https://github.com/helm/helm/blob/master/pkg/strvals/parser.go)\n\n### split\n\n`split` function is go's `strings.Split()`, it returns a `[]string`. A range function\ncan also be used to iterate over returned list.\n\n```yaml\n# split.yaml\n---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: list\ndata:\n  foo:\n{{ range split .LIST \",\" }}\n    - {{ . }}\n    {{- end -}}\n```\n\n```\n$ export LIST=\"one,two,three\"\n$ ./kd -f split.yaml --dryrun --debug-templates\n[INFO] 2017/10/18 15:08:09 main.go:241: deploying configmap/list\n[INFO] 2017/10/18 15:08:09 main.go:248: apiVersion: v1\n---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: list\ndata:\n  foo:\n    - one\n    - two\n    - three\n```\n\n### file\n\n`file` function will locate and render a configuration file from your repo. A full path will need to be specified, you can run this in drone by using `workspace:` and a base directory (http://docs.drone.io/workspace/#app-drawer). Here's an example:\n\n```yaml\n# file.yaml\n---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: list\ndata:\n  foo:\n{{ file .BAR | indent 4}}\n```\n\n```\n$ cat \u003c\u003cEOF \u003e config.yaml\n- one\n- two\n- three\nEOF\n$ export BAR=${PWD}/config.yaml\n$ ./kd -f file.yaml --dryrun --debug-templates\n[INFO] 2017/10/18 15:08:09 main.go:241: deploying configmap/list\n[INFO] 2017/10/18 15:08:09 main.go:248: apiVersion: v1\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: list\ndata:\n  foo:\n    - one\n    - two\n    - three\n```\n\n### fileWith\n\n`fileWith` function will locate and render a configuration file from your repo with additional values specified as a Sprig dict. A full path will need to be specified, you can run this in drone by using `workspace:` and a base directory (http://docs.drone.io/workspace/#app-drawer). Here's an example:\n\n```yaml\n# file.yaml\n---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: list\ndata:\n  foo:\n{{ fileWith .BAR (dict \"FIRST\" \"one\") | indent 4}}\n```\n\n```\n$ cat \u003c\u003cEOF \u003e config.yaml\n- {{ .FIRST }}\n- two\n- three\nEOF\n$ export BAR=${PWD}/config.yaml\n$ ./kd -f file.yaml --dryrun --debug-templates\n[INFO] 2017/10/18 15:08:09 main.go:241: deploying configmap/list\n[INFO] 2017/10/18 15:08:09 main.go:248: apiVersion: v1\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: list\ndata:\n  foo:\n    - one\n    - two\n    - three\n```\n\n### secret\n\n`secret` function generates a secret given the parameters `type` and `length`.\nSupported types are:\n\n- alphanum\n- mysql\n- yaml\n\n**NOTE** a secret generated will automatically be set to `create-only` and will\nnot be updated for every deploy.\n\n```yaml\n# secret.yaml\n---\napiVersion: v1\nkind: Secret\nmetadata:\n  name: test\ndata:\n  # generate a mysql safe password of 20 chars\n  password: {{ secret \"mysql\" 20 }}\n```\n\n```bash\n$ ./kd -f ./test/secret.yaml --dryrun --debug-templates\n[DEBUG] 2018/07/17 15:10:50 main.go:240: about to open file:./test/secret.yaml\n[DEBUG] 2018/07/17 15:10:50 main.go:260: parsing file:./test/secret.yaml\n[INFO] 2018/07/17 15:10:50 main.go:282: Template:\napiVersion: v1\nkind: Secret\nmetadata:\n  name: test\ntype: Opaque\ndata:\n  username: bob\n  # Create a secret suitable for mysql of 20 chars\n  password: fD1wS2kzTUVVNUdJcDxGWkhedmQ=\n```\n\nIf you are creating a kubernetes secret and need the content to be automatically base64 encoded, you can do the following:\n```yml\n# secret.yml\napiVersion: v1\nkind: Secret\nmetadata:\n  name: test\ndata:\n  # read the contents of the \"MY_HOSTNAME\" environment variable and base64 encode it\n  hostname: {{ .MY_HOSTNAME | b64enc }}\n  # base64 encode the provided string\n  username: {{ \"my-username\" | b64enc }}\n```\n\n### k8lookup\n\n`k8lookup` function allows retrieval of an Kubernetes object value using the parameters:\n- `kind` - a Kubernetes object kind e.g. `pv` or `PersistentVolume`\n- `name` - an object name e.g. `sysdig-mysql-a`\n- `path` - a object path reference e.g. `.spec.capacity.storage`\n\nExample:\n\nWith manually provisioned storage (e.g. iSCSI or NFS) a PV is typically managed\nusing a separate repository. Using lookup, we can discover the appropriate\nstorage size for a given cluster automatically:\n\n```\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  labels:\n    name: sysdig-galera\n  name: data-sysdig-galera-0\nspec:\n  accessModes:\n  - ReadWriteOnce\n  resources:\n    requests:\n      storage: {{ k8lookup \"pv\" \"sysdig-mysql-a\" \".spec.capacity.storage\" }}\n  selector:\n    matchLabels:\n      name: sysdig-mysql\n  storageClassName: manual\n```\n\n## Configuration\n\nConfiguration can be provided via cli flags and arguments as well as\nenvironment variables.\n\n### Config\n\n`--config` use of a .env file see [github.com/joho/godotenv](https://github.com/joho/godotenv/blob/master/README.md)\n\n### Config Data\n\n`--config-data` can be specified to facilitate structured yaml data in templates. It has two forms:\n\n1. `--config-data Scope=file.yaml` - data from file available at `.Scope.rootkey.subkey`\n2. `--config-data  file.yaml` - data from file available at `.rootkey.subkey`\n\nE.g. A deployment using source copied from a simple helm chart source:\n\n```\nkd --config-data Chart=./helm/simple-app/Chart.yaml \\\n   --config-data Values=./helm/simple-app/values.yaml \\\n   --allow-missing \\\n   --pre-render \\\n   --file ./helm/simple-app/templates/\n```\n\n**NOTE** the use of the flag `--pre-render` which allows complex charts to be \nparsed per file instead of per resource. This allows for blocks spanning \nmultiple resources.\n\n**NOTE** Config data is also rendered using [templating](#templating). This\nallows upstream chart templates to be used whilst overriding values that may\ndiffer per environment (e.g. image repositories).\n\n### Kubectl flags\n\nIt supports end of flags `--` parameter, any flags or arguments that are\nspecified after `--` will be passed onto kubectl.\n\n```\n$ kd --help\nNAME:\n   kd - simple kubernetes resources deployment tool\n\nUSAGE:\n   kd [global options] command [command options] [arguments...]\n\nVERSION:\n   v1.10.7\n\nAUTHOR:\n   Vaidas Jablonskis \u003cjablonskis@gmail.com\u003e\n\nCOMMANDS:\n     run      run [kubectl args] - runs kubectl supporting kd flags / environment options\n     help, h  Shows a list of commands or help for one command\n\nGLOBAL OPTIONS:\n   --debug                                debug output [$DEBUG, $PLUGIN_DEBUG]\n   --debug-templates                      debug template output [$DEBUG_TEMPLATES, $PLUGIN_DEBUG_TEMPLATES]\n   --dryrun                               if true, kd will exit prior to deployment [$DRY_RUN]\n   --delete                               instead of applying the resources we are deleting them\n   --insecure-skip-tls-verify             if true, the server's certificate will not be checked for validity [$INSECURE_SKIP_TLS_VERIFY, $PLUGIN_INSECURE_SKIP_TLS_VERIFY]\n   --kube-config-data value               Kubernetes config file data [$KUBE_CONFIG_DATA, $PLUGIN_KUBE_CONFIG_DATA]\n   --kube-server URL, -s URL              kubernetes api server URL [$KUBE_SERVER, $PLUGIN_KUBE_SERVER]\n   --kube-token TOKEN, -t TOKEN           kubernetes auth TOKEN [$KUBE_TOKEN, $PLUGIN_KUBE_TOKEN]\n   --kube-username USERNAME, -u USERNAME  kubernetes auth USERNAME [$KUBE_USERNAME, $PLUGIN_KUBE_USERNAME]\n   --kube-password PASSWORD, -p PASSWORD  kubernetes auth PASSWORD [$KUBE_PASSWORD, $PLUGIN_KUBE_PASSWORD]\n   --config value                         Env file location [$CONFIG_FILE, $PLUGIN_CONFIG_FILE]\n   --config-data value                    Config data e.g. --config-data=Chart=./Chart.yaml [$KD_CONFIG_DATA, $PLUGIN_KD_CONFIG_DATA]\n   --create-only                          only create resources (do not update, skip if exists). [$CREATE_ONLY, $PLUGIN_CREATE_ONLY]\n   --create-only-resource value           only create specified resources e.g. 'kind/name' (do not update, skip if exists). [$CREATE_ONLY_RESOURCES, $PLUGIN_CREATE_ONLY_RESOURCES]\n   --replace                              use replace instead of apply for updating objects [$KUBE_REPLACE, $PLUGIN_KUBE_REPLACE]\n   --context CONTEXT, -c CONTEXT          kube config CONTEXT [$KUBE_CONTEXT, $PLUGIN_CONTEXT]\n   --namespace NAMESPACE, -n NAMESPACE    kubernetes NAMESPACE [$KUBE_NAMESPACE, $PLUGIN_KUBE_NAMESPACE]\n   --fail-superseded                      fail deployment if it has been superseded by another deployment. WARNING: there are some bugs in kubernetes. [$FAIL_SUPERSEDED, $PLUGIN_FAIL_SUPERSEDED]\n   --certificate-authority PATH           the path (or URL) to a file containing the CA for kubernetes API PATH [$KUBE_CERTIFICATE_AUTHORITY, $PLUGIN_KUBE_CERTIFICATE_AUTHORITY]\n   --certificate-authority-data PATH      the certificate authority data for the kubernetes API PATH [$KUBE_CERTIFICATE_AUTHORITY_DATA, $PLUGIN_KUBE_CERTIFICATE_AUTHORITY_DATA]\n   --certificate-authority-file value     the path to save certificate authority data to when data or a URL is specified (default: \"/tmp/kube-ca.pem\") [$KUBE_CERTIFICATE_AUTHORITY_FILE, $PLUGIN_KUBE_CERTIFICATE_AUTHORITY_FILE]\n   --file PATH, -f PATH                   the path to a file or directory containing kubernetes resources PATH [$FILES, $PLUGIN_FILES]\n   --timeout TIMEOUT, -T TIMEOUT          the amount of time to wait for a successful deployment TIMEOUT (default: 3m0s) [$TIMEOUT, $PLUGIN_TIMEOUT]\n   --check-interval INTERVAL              deployment status check interval INTERVAL (default: 1s) [$CHECK_INTERVAL, $PLUGIN_CHECK_INTERVAL]\n   --allow-missing                        if true, missing variables will be replaced with \u003cno value\u003e instead of generating an error [$ALLOW_MISSING]\n   --kubectl-binary value                 the path to the kubectl binary (default: \"kubectl\") [$KUBE_BINARY, $KUBECTL_BINARY]\n   --help, -h                             show help\n   --version, -v                          print the version\n```\n\n## Build\n\nTo build kd just run `make`.\n\nYou can also build `kd` in a docker container:\n\n```bash\ndocker run --rm -v $PWD:/go/src/github.com/UKHomeOffice/kd -w /go/src/github.com/UKHomeOffice/kd -ti golang:1.10 make\n```\n\n## Release process\n\nPush / Merge to master will produce a docker\n[image](https://quay.io/repository/ukhomeofficedigital/kd?tab=tags) with a tag `latest`.\n\nTo create a new release, just create a new tag off master.\n\n\n## Contributing\n\nWe welcome pull requests. Please raise an issue to discuss your changes before\nsubmitting a patch.\n\n\n## Author\n\nVaidas Jablonskis [vaijab](https://github.com/vaijab)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fukhomeoffice%2Fkd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fukhomeoffice%2Fkd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fukhomeoffice%2Fkd/lists"}