Skip to content

Commit dd42351

Browse files
authored
Merge pull request #116 from leaseweb/chore/update_docs
docs: Reorganize documentation into docs/ folder
2 parents 29e02a3 + cfaee15 commit dd42351

File tree

5 files changed

+254
-140
lines changed

5 files changed

+254
-140
lines changed

README.md

Lines changed: 19 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -4,158 +4,37 @@
44
[![](https://img.shields.io/badge/license-Apache%202.0-blue.svg?color=%23282661&logo=apache&style=flat-square "Apache 2.0 license")](/LICENSE-2.0)
55
[![](https://img.shields.io/badge/language-Go-%235adaff.svg?logo=go&style=flat-square "Go language")](https://golang.org)
66

7-
A Cloud Controller Manager to facilitate Kubernetes deployments on Cloudstack.
7+
A Kubernetes Cloud Controller Manager (CCM) for Apache CloudStack. It provides node metadata, lifecycle management, and load balancer integration for Kubernetes clusters running on CloudStack.
88

9-
Based on the old in-tree CloudStack provider in Kubernetes that was removed.
9+
## Quick Start
1010

11-
Refer:
12-
* https://github.com/kubernetes/kubernetes/tree/release-1.15/pkg/cloudprovider/providers/cloudstack
13-
* https://github.com/kubernetes/enhancements/issues/672
14-
* https://github.com/kubernetes/enhancements/issues/88
15-
16-
## Deployment
17-
18-
The CloudStack Kubernetes Provider is automatically deployed when a Kubernetes Cluster is created on CloudStack 4.16+
19-
20-
In order to communicate with CloudStack, a separate service user **kubeadmin** is created in the same account as the cluster owner.
21-
The provider uses this user's API keys to get the details of the cluster as well as update the networking rules. It is imperative that this user
22-
is not altered or have its keys regenerated.
23-
24-
The provider can also be manually deployed as follows :
25-
26-
### Kubernetes
27-
28-
Prebuilt containers are posted [here](https://github.com/leaseweb/cloudstack-kubernetes-provider/pkgs/container/cloudstack-kubernetes-provider).
29-
30-
To configure API access to your CloudStack management server, you need to create a secret containing a `cloud-config`
31-
that is suitable for your environment.
32-
33-
`cloud-config` should look like this:
34-
```ini
35-
[Global]
36-
api-url = <CloudStack API URL>
37-
api-key = <CloudStack API Key>
38-
secret-key = <CloudStack API Secret>
39-
project-id = <CloudStack Project UUID (optional)>
40-
zone = <CloudStack Zone Name (optional)>
41-
ssl-no-verify = <Disable SSL certificate validation: true or false (optional)>
42-
```
43-
44-
The access token needs to be able to fetch VM information and deploy load balancers in the project or domain where the nodes reside.
45-
46-
To create the secret, use the following command:
47-
```bash
48-
kubectl -n kube-system create secret generic cloudstack-secret --from-file=cloud-config
49-
```
50-
51-
You can then use the provided example [deployment.yaml](/deployment.yaml) to deploy the controller:
5211
```bash
53-
kubectl apply -f deployment.yaml
54-
```
55-
56-
### Protocols
57-
58-
This CCM supports TCP, UDP and [TCP-Proxy](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) LoadBalancer deployments.
59-
60-
For UDP and Proxy Protocol support, CloudStack 4.6 or later is required.
61-
62-
Since kube-proxy does not support the Proxy Protocol or UDP, you should connect this directly to pods, for example by deploying a DaemonSet and setting `hostPort: <TCP port>` on the desired container port.
63-
Important: The service running in the pod must support the chosen protocol. Do not try to enable TCP-Proxy when the service only supports regular TCP.
64-
65-
[traefik-ingress-controller.yml](/traefik-ingress-controller.yml) contains a basic deployment for the Træfik ingress controller that illustrates how to use it with the proxy protocol.
66-
67-
For the nginx ingress controller, please refer to the official documentation at [kubernetes.github.io/ingress-nginx/deploy](https://kubernetes.github.io/ingress-nginx/deploy/). After applying the deployment, patch it for proxy protocol support with the provided fragment:
68-
69-
```bash
70-
kubectl apply -f nginx-ingress-controller-patch.yml
71-
```
72-
73-
### Node Labels
74-
75-
:warning: **The node name must match the host name, so the controller can fetch and assign metadata from CloudStack.**
76-
77-
It is recommended to launch `kubelet` with the following parameter:
78-
12+
helm install cloud-controller-manager charts/cloud-controller-manager/ \
13+
--namespace kube-system \
14+
--set cloudConfig.global.api-url="https://cloudstack.example.com/client/api" \
15+
--set cloudConfig.global.api-key="YOUR_API_KEY" \
16+
--set cloudConfig.global.secret-key="YOUR_SECRET_KEY"
7917
```
80-
--register-with-taints=node.cloudprovider.kubernetes.io/uninitialized=true:NoSchedule
81-
```
82-
83-
This will treat the node as 'uninitialized' and cause the CCM to apply metadata labels from CloudStack automatically.
84-
85-
Supported labels for Kubernetes versions up to 1.16 are:
86-
* kubernetes.io/hostname (= the instance name)
87-
* beta.kubernetes.io/instance-type (= the compute offering)
88-
* failure-domain.beta.kubernetes.io/zone (= the zone)
89-
* failure-domain.beta.kubernetes.io/region (also = the zone)
90-
91-
Supported labels for Kubernetes versions 1.17 and later are:
92-
* kubernetes.io/hostname (= the instance name)
93-
* node.kubernetes.io/instance-type (= the compute offering)
94-
* topology.kubernetes.io/zone (= the zone)
95-
* topology.kubernetes.io/region (also = the zone)
96-
97-
It is also possible to trigger this process manually by issuing the following command:
98-
99-
```
100-
kubectl taint nodes <my-node-without-labels> node.cloudprovider.kubernetes.io/uninitialized=true:NoSchedule
101-
```
102-
103-
## Migration Guide
104-
105-
There are several notable differences to the old Kubernetes CloudStack cloud provider that need to be taken into
106-
account when migrating from the old cloud provider to the standalone controller.
107-
108-
### Load Balancer
109-
110-
Load balancer rule names now include the protocol in addition to the LB name and service port.
111-
This was added to distinguish tcp, udp and tcp-proxy services operating on the same port.
112-
Without this change, it would not be possible to map a service that runs on both TCP and UDP port 8000, for example.
113-
114-
:warning: **If you have existing rules, remove them before the migration, and add them back afterwards.**
115-
116-
If you don't do this, you will end up with duplicate rules for the same service, which won't work.
11718

118-
### Metadata
19+
## Documentation
11920

120-
Since the controller is now intended to be run inside a pod and not on the node, it will not be able to fetch metadata from the Virtual Router's DHCP server.
121-
122-
Instead, it first obtains the name of the node from Kubernetes, then fetches information from the CloudStack API.
21+
| Guide | Description |
22+
|-------|-------------|
23+
| [Getting Started](docs/getting-started.md) | Installation via Helm or Kubernetes manifests, node setup |
24+
| [Configuration](docs/configuration.md) | Cloud config reference, Helm chart values |
25+
| [Load Balancer](docs/load-balancer.md) | Protocols, annotations, IP management |
26+
| [Development](docs/development.md) | Building, testing, local development |
12327

12428
## Development
12529

126-
### Building
127-
128-
At least Go 1.21 is required to build cloudstack-ccm.
129-
130-
To build the controller with correct versioning, some build flags need to be passed.
131-
A Makefile is provided that sets these build flags to automatically derived values.
132-
133-
```bash
134-
go get github.com/apache/cloudstack-kubernetes-provider
135-
cd ${GOPATH}/src/github.com/apache/cloudstack-kubernetes-provider
136-
make
137-
```
138-
139-
To build the cloudstack-cloud-controller-manager container, please use the provided Dockerfile.
140-
The Makefile will also with that and properly tag the resulting container.
141-
14230
```bash
143-
make docker
31+
make # Build
32+
make docker # Build container image
33+
make lint # Lint
34+
make test # Test
14435
```
14536

146-
### Testing
147-
148-
You need a local instance of the CloudStack Management Server or a 'real' one to connect to.
149-
The CCM supports the same cloud-config configuration file format used by [the cs tool](https://github.com/exoscale/cs),
150-
so you can simply point it to that.
151-
152-
```bash
153-
./cloudstack-ccm --cloud-provider cloudstack --cloud-config ~/.cloud-config --master k8s-apiserver
154-
```
155-
156-
Replace k8s-apiserver with the host name of your Kubernetes development clusters's API server.
157-
158-
If you don't have a 'real' CloudStack installation, you can also launch a local [simulator instance](https://hub.docker.com/r/cloudstack/simulator) instead. This is very useful for dry-run testing.
37+
See [docs/development.md](docs/development.md) for details.
15938

16039
## Copyright
16140

docs/configuration.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Configuration
2+
3+
## Cloud Config
4+
5+
The CCM reads its CloudStack credentials from a `cloud-config` file in INI format. When using Kubernetes manifests, this file is mounted from a secret. When using the Helm chart, it is generated from the `cloudConfig` values.
6+
7+
```ini
8+
[Global]
9+
api-url = <CloudStack API URL>
10+
api-key = <CloudStack API Key>
11+
secret-key = <CloudStack API Secret>
12+
project-id = <CloudStack Project UUID (optional)>
13+
zone = <CloudStack Zone Name (optional)>
14+
ssl-no-verify = <Disable SSL certificate validation: true or false (optional)>
15+
```
16+
17+
| Field | Required | Description |
18+
|-------|----------|-------------|
19+
| `api-url` | Yes | Full URL to the CloudStack API endpoint |
20+
| `api-key` | Yes | API key for authentication |
21+
| `secret-key` | Yes | Secret key for authentication |
22+
| `project-id` | No | UUID of the CloudStack project. Required when nodes are in a project |
23+
| `zone` | No | CloudStack zone name to scope operations to |
24+
| `ssl-no-verify` | No | Set to `true` to skip TLS certificate verification |
25+
26+
The API credentials need permission to fetch VM information and manage load balancers in the project or domain where the nodes reside.
27+
28+
## Helm Chart Values
29+
30+
The chart is located at [`charts/cloud-controller-manager/`](../charts/cloud-controller-manager/). Below are the key values. See [`values.yaml`](../charts/cloud-controller-manager/values.yaml) for the full reference.
31+
32+
| Value | Default | Description |
33+
|-------|---------|-------------|
34+
| `replicaCount` | `1` | Number of CCM replicas. Leader election is automatically enabled when > 1 |
35+
| `image.repository` | `ghcr.io/leaseweb/cloudstack-kubernetes-provider` | Container image repository |
36+
| `image.tag` | Chart `appVersion` | Container image tag |
37+
| `nodeSelector` | `node-role.kubernetes.io/control-plane: ""` | Node selector for scheduling |
38+
| `tolerations` | Uninitialized, CriticalAddonsOnly, control-plane, not-ready | Pod tolerations |
39+
| `enabledControllers` | `[cloud-node, cloud-node-lifecycle, route, service]` | List of controllers to enable |
40+
| `cluster.name` | `kubernetes` | Cluster name passed to the CCM |
41+
| `logVerbosityLevel` | `2` | klog verbosity level |
42+
| `hostNetwork` | `true` | Run pods with host networking |
43+
| `dnsPolicy` | `ClusterFirstWithHostNet` | DNS policy (should match `hostNetwork`) |
44+
| `secret.enabled` | `true` | Mount cloud-config from a Kubernetes secret |
45+
| `secret.create` | `true` | Create the secret from `cloudConfig` values. Set to `false` to use a pre-existing secret |
46+
| `secret.name` | `cloud-config` | Name of the secret |
47+
| `cloudConfig.global.api-url` | `""` | CloudStack API URL |
48+
| `cloudConfig.global.api-key` | `""` | CloudStack API key |
49+
| `cloudConfig.global.secret-key` | `""` | CloudStack secret key |
50+
| `serviceMonitor` | `{}` | Prometheus ServiceMonitor configuration |
51+
| `priorityClassName` | `system-node-critical` | Pod priority class |

docs/development.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Development
2+
3+
## Requirements
4+
5+
- Go 1.24+
6+
- Docker (for building container images)
7+
8+
## Building
9+
10+
A Makefile is provided that sets build flags with automatically derived version information.
11+
12+
```bash
13+
make # Build the cloudstack-ccm binary
14+
make docker # Build and tag the container image
15+
make lint # Run linting (fmt, vet, golangci-lint)
16+
make test # Run tests, vet, and format checks
17+
```
18+
19+
## Local Testing
20+
21+
You can run the CCM locally against a Kubernetes cluster and CloudStack API:
22+
23+
```bash
24+
./cloudstack-ccm --cloud-provider cloudstack --cloud-config /path/to/cloud-config --master <k8s-apiserver>
25+
```
26+
27+
Replace `<k8s-apiserver>` with the hostname or address of your Kubernetes API server.
28+
29+
If you don't have a CloudStack installation available, you can use the CloudStack [simulator image](https://hub.docker.com/r/cloudstack/simulator) for dry-run testing.

docs/getting-started.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Getting Started
2+
3+
## Prerequisites
4+
5+
- A Kubernetes cluster running on Apache CloudStack
6+
- CloudStack API credentials (API key and secret key) with permissions to manage VMs and load balancers
7+
- `kubectl` configured to access your cluster
8+
- `helm` (optional, for Helm-based installation)
9+
10+
## Installation
11+
12+
### Helm Chart (recommended)
13+
14+
Install from the bundled chart in [`charts/cloud-controller-manager/`](../charts/cloud-controller-manager/):
15+
16+
```bash
17+
helm install cloud-controller-manager charts/cloud-controller-manager/ \
18+
--namespace kube-system \
19+
--set cloudConfig.global.api-url="https://cloudstack.example.com/client/api" \
20+
--set cloudConfig.global.api-key="YOUR_API_KEY" \
21+
--set cloudConfig.global.secret-key="YOUR_SECRET_KEY"
22+
```
23+
24+
See [`charts/cloud-controller-manager/values.yaml`](../charts/cloud-controller-manager/values.yaml) for the full list of configurable values, or refer to the [Configuration](configuration.md) guide.
25+
26+
### Kubernetes Manifests
27+
28+
1. Create a `cloud-config` file:
29+
30+
```ini
31+
[Global]
32+
api-url = https://cloudstack.example.com/client/api
33+
api-key = YOUR_API_KEY
34+
secret-key = YOUR_SECRET_KEY
35+
```
36+
37+
See [Configuration](configuration.md) for all available fields.
38+
39+
2. Create the secret:
40+
41+
```bash
42+
kubectl -n kube-system create secret generic cloudstack-secret --from-file=cloud-config
43+
```
44+
45+
3. Apply RBAC and deployment manifests:
46+
47+
```bash
48+
kubectl apply -f deploy/k8s/rbac.yaml
49+
kubectl apply -f deploy/k8s/deployment.yaml
50+
```
51+
52+
Prebuilt container images are available at [ghcr.io/leaseweb/cloudstack-kubernetes-provider](https://github.com/leaseweb/cloudstack-kubernetes-provider/pkgs/container/cloudstack-kubernetes-provider).
53+
54+
## Node Setup
55+
56+
**The node name must match the CloudStack VM hostname** so the controller can fetch and assign metadata.
57+
58+
It is recommended to launch `kubelet` with the following flag:
59+
60+
```
61+
--register-with-taints=node.cloudprovider.kubernetes.io/uninitialized=true:NoSchedule
62+
```
63+
64+
This marks the node as uninitialized, causing the CCM to automatically apply metadata labels from CloudStack:
65+
66+
| Label | Value |
67+
|-------|-------|
68+
| `kubernetes.io/hostname` | Instance name |
69+
| `node.kubernetes.io/instance-type` | Compute offering |
70+
| `topology.kubernetes.io/zone` | CloudStack zone |
71+
| `topology.kubernetes.io/region` | CloudStack zone |
72+
73+
To trigger this process manually on an existing node:
74+
75+
```bash
76+
kubectl taint nodes <node-name> node.cloudprovider.kubernetes.io/uninitialized=true:NoSchedule
77+
```

0 commit comments

Comments
 (0)