{"id":13839297,"url":"https://github.com/zalando-incubator/cluster-lifecycle-manager","last_synced_at":"2025-05-16T09:06:30.377Z","repository":{"id":38375750,"uuid":"131291943","full_name":"zalando-incubator/cluster-lifecycle-manager","owner":"zalando-incubator","description":"Cluster Lifecycle Manager (CLM) to provision and update multiple Kubernetes clusters","archived":false,"fork":false,"pushed_at":"2025-05-13T05:07:02.000Z","size":9909,"stargazers_count":238,"open_issues_count":19,"forks_count":27,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-05-13T06:20:04.864Z","etag":null,"topics":["aws","cloud","cloudformation","cluster","go","kubernetes","lifecycle","manager"],"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/zalando-incubator.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-04-27T12:11:30.000Z","updated_at":"2025-05-13T05:07:04.000Z","dependencies_parsed_at":"2024-01-16T12:49:11.308Z","dependency_job_id":"67c0e24c-8653-4337-8389-428d81b0be49","html_url":"https://github.com/zalando-incubator/cluster-lifecycle-manager","commit_stats":{"total_commits":621,"total_committers":27,"mean_commits":23.0,"dds":0.789049919484702,"last_synced_commit":"0a7121e5fdf6edfa515555d3fae2582cd7886df0"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zalando-incubator%2Fcluster-lifecycle-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zalando-incubator%2Fcluster-lifecycle-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zalando-incubator%2Fcluster-lifecycle-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zalando-incubator%2Fcluster-lifecycle-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zalando-incubator","download_url":"https://codeload.github.com/zalando-incubator/cluster-lifecycle-manager/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254501558,"owners_count":22081528,"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":["aws","cloud","cloudformation","cluster","go","kubernetes","lifecycle","manager"],"created_at":"2024-08-04T17:00:18.164Z","updated_at":"2025-05-16T09:06:25.367Z","avatar_url":"https://github.com/zalando-incubator.png","language":"Go","funding_links":[],"categories":["Cluster Provisioning \u0026 Lifecycle","Cluster"],"sub_categories":[],"readme":"# Cluster Lifecycle Manager (CLM)\n\n[![Build Status](https://travis-ci.org/zalando-incubator/cluster-lifecycle-manager.svg?branch=master)](https://travis-ci.org/zalando-incubator/cluster-lifecycle-manager)\n[![Coverage Status](https://coveralls.io/repos/github/zalando-incubator/cluster-lifecycle-manager/badge.svg?branch=master)](https://coveralls.io/github/zalando-incubator/cluster-lifecycle-manager?branch=master)\n[![Go Report Card](https://goreportcard.com/badge/github.com/zalando-incubator/cluster-lifecycle-manager)](https://goreportcard.com/report/github.com/zalando-incubator/cluster-lifecycle-manager)\n\nThe Cluster Lifecycle Manager (CLM) is a component responsible for operating\n(create, update, delete) Kubernetes clusters. It interacts with a Cluster\nRegistry and a configuration source from which it reads information about the\nclusters and keep them up to date with the latest configuration.\n\n![clm](docs/images/cluster-lifecycle-manager.svg)\n\nThe CLM is designed to run either as a CLI tool for launching clusters directly\nfrom your development machine, or as a controller running as a single instance\noperating many clusters.\n\nIt is designed in a reentrant way meaning it can be killed at any point in time\nand it will just continue any cluster updates from where it left off. All state\nis stored in the Cluster Registry and the git configuration repository.\n\nFor a better understanding on how we use the CLM within Zalando, see the 2018 KubeCon EU talk:\n* [Continuously Deliver your Kubernetes Infrastructure - Mikkel Larsen, Zalando SE](https://www.youtube.com/watch?v=1xHmCrd8Qn8).\n\n## Current state\n\nThe CLM has been developed internally at Zalando since January 2017. It's\ncurrently used to operate 200+ clusters on AWS where the oldest clusters has\nbeen continuously updated all the way from Kubernetes v1.4 to Kubernetes v1.24\nby the CLM.\n\nIt is currently tightly coupled with our [production cluster\nconfiguration](https://github.com/zalando-incubator/kubernetes-on-aws), but by\nmaking it Open Source and developing it in the open going forward we aim to\nmake the CLM useful as a generic solution for operating Kubernetes clusters at\nscale.\n\n### Features\n\n* Automatically trigger cluster updates based on changes to a Cluster Registry\n  defined either as an HTTP REST API or a YAML file.\n* Automatically trigger cluster updates based on configuration changes, where\n  configuration is stored in a remote git repository or a local directory.\n* Perform [Non-disruptive Rolling Updates](#non-disruptive-rolling-updates) of\n  nodes in a cluster especially with respect to stateful applications.\n* Declarative [deletion](#deletions) of decommissioned cluster resources.\n\n## How to build it\n\nThis project uses [Go modules](https://github.com/golang/go/wiki/Modules) as\nintroduced in Go 1.11 therefore you need Go \u003e=1.11 installed in order to build.\nIf using Go 1.11 you also need to [activate Module\nsupport](https://github.com/golang/go/wiki/Modules#installing-and-activating-module-support).\n\nAssuming Go has been setup with module support it can be built simply by running:\n\n```sh\nexport GO111MODULE=on # needed if the project is checked out in your $GOPATH.\n$ make\n```\n\n## How to run it\n\nTo run CLM you need to provide at least the following information:\n\n* URI to a registry `--registry` either a file path or a URL to a cluster\n  registry.\n* A `$TOKEN` used for authenticating with the target Kubernetes cluster once it\n  has been provisioned (the `$TOKEN` is an assumption of the Zalando setup, we\n  should support a generic `kubeconfig` in the future).\n* URL to repository containing the configuration `--git-repository-url` or, in\n  alternative, a directory `--directory`\n\n### Run CLM locally\n\nTo run CLM locally you can use the following command. This assumes valid AWS\ncredentials on your machine e.g. in `~/.aws/credentials`.\n\n```sh\n$ ./build/clm provision \\\n  --registry=clusters.yaml \\\n  --token=$TOKEN \\\n  --directory=/path/to/configuration-folder \\\n  --debug\n```\n\nThe `provision` command does a cluster *create* or *update* depending on\nwhether the cluster already exists. The other command is `decommission` which\nterminates the cluster.\n\nThe `clusters.yaml` is of the following format:\n\n```yaml\nclusters:\n- id: cluster-id\n  alias: alias-for-cluster-id # human readable alias\n  local_id: local-cluster-id  # used for separating clusters in the same AWS account\n  api_server_url: https://kube-api.example.org\n  config_items:\n    custom_config_item: value # custom key/value config items\n  criticality_level: 1\n  environment: test\n  infrastructure_account: \"aws:12345678910\" # AWS account ID\n  region: eu-central-1\n  provider: zalando-aws\n  node_pools:\n  - name: master-default\n    profile: master-default\n    min_size: 2\n    max_size: 2\n    instance_type: m5.large\n    discount_strategy: none\n  - name: worker-default\n    profile: worker-default\n    min_size: 3\n    max_size: 20\n    instance_type: m5.large\n    discount_strategy: none\n```\n\n## Deletions\n\nBy default the Cluster Lifecycle Manager will just apply any manifest defined\nin the manifests folder. In order to support deletion of deprecated resources\nthe CLM will read a `deletions.yaml` file of the following format:\n\n```yaml\npre_apply: # everything defined under here will be deleted before applying the manifests\n- name: mate\n  namespace: kube-system\n  kind: deployment\n- name: with-options\n  namespace: kube-system\n  kind: deployment\n  propagation_policy: Orphan\n  grace_period_seconds: 10\n- name: orphan-replicasets\n  namespace: kube-system\n  kind: ReplicaSet\n  labels:\n    foo: bar\n  has_owner: false\n- namespace: kube-system\n  kind: deployment\n  selector: version != v1\npost_apply: # everything defined under here will be deleted after applying the manifests\n- namespace: kube-system\n  kind: deployment\n  labels:\n    application: external-dns\n    version: \"v1.0\"\n```\n\nWhatever is defined in this file will be deleted pre/post applying the other\nmanifest files, if the resource exists. If the resource has already been\ndeleted previously it's treated as a no-op.\n\nA resource can be identified either by `name`,\n[`selector`](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors) or\n`labels` and only one of them should be defined.\n\n`namespace` can be left out, in which case it will default to `kube-system`.\n\n`kind` must be one of the kinds defined in `kubectl get`.\n\nAn optional boolean `has_owner` may be specified to narrow down resources identified by the `labels`:\n- `has_owner: true` selects resources with non-empty `metadata.ownerReferences`\n- `has_owner: false` selects resources with empty `metadata.ownerReferences`\n\nIt is possible to specify deletion options via optional:\n- `propagation_policy` - one of \"Orphan\", \"Background\" or \"Foreground\" - corresponds to `kubectl delete --cascade` flag\n- `grace_period_seconds` - corresponds to `kubectl delete --grace-period` flag\n\n## Configuration defaults\n\nCLM will look for a `config-defaults.yaml` file in the cluster configuration\ndirectory. If the file exists, it will be evaluated as a Go template with all\nthe usual CLM variables and functions available, and the resulting output will\nbe parsed as a simple key-value map. CLM will use the contents of the file to\npopulate the cluster's configuration items, taking care not to overwrite the\nexisting ones.\n\nFor example, you can use the defaults file to have different settings for\nproduction and test clusters, while keeping the manifests readable:\n\n* **config-defaults.yaml**:\n    ```yaml\n    {{ if eq .Environment \"production\"}}\n    autoscaling_buffer_pods: \"3\"\n    {{else}}\n    autoscaling_buffer_pods: \"0\"\n    {{end}}\n    ```\n\n* **manifests/example/example.yaml**:\n    ```yaml\n    …\n    spec:\n      replicas: {{.ConfigItems.autoscaling_buffer_pods}}\n    …\n    ```\n\n### A Note on Using Multiple Config Sources\nThe CLM supports specifying multiple `config-sources` on the command line, see [here](https://github.com/zalando-incubator/cluster-lifecycle-manager/blob/2bb1b5ffd184dbdffefc4c7529671025edf460c4/config/config.go#L92).\nIt's important to understand that the order in which these are provided is important. If the same `config-item`\nexists in multiple sources, the value in the source specified _later_ will override the one defined in the\nearlier source. For instance, consider a CLM deployment that contains the following arguments:\n```yaml\n...\n          - --config-source=source1:git:example.domain-1\n          - --config-source=source2:example.domain-2\n          - --config-source=source3:git:example.domain-3\n...\n```\nThen for any `config-item`, the value from `source3` will be the final value and in case of it existing in the sources specified earlier, the value will be overridden by the value in `source3`.\nThis is the intended behavior of the CLI flags i.e. when multiple values are specified for a flag, they are appended, in order, to a slice. Later, in the CLM code, when these are [merged](https://github.com/zalando-incubator/cluster-lifecycle-manager/blob/2bb1b5ffd184dbdffefc4c7529671025edf460c4/cmd/clm/main.go#L44), the order of the\nsource names in the slice is respected.\n\n## Non-disruptive rolling updates\n\nOne of the main features of the CLM is the update strategy implemented which is\ndesigned to do rolling node updates which are non-disruptive for workloads\nrunning in the target cluster. Special care is taken to support stateful\napplications.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzalando-incubator%2Fcluster-lifecycle-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzalando-incubator%2Fcluster-lifecycle-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzalando-incubator%2Fcluster-lifecycle-manager/lists"}