bhouse-nexthop commented on PR #14649:
URL: https://github.com/apache/cloudstack/pull/14649#issuecomment-6756505549

   ### Test report: pinned autoscaler and CCM in the binaries ISO, on a live 
cluster
   
   **Summary:** I built two ISOs with this PR's 
`create-kubernetes-binaries-iso.sh` and registered both. A cluster created from 
the first runs the autoscaler release that matches its Kubernetes minor 
version, and the CCM at v1.2.0. The autoscaler syncs with no RBAC or cache 
errors. It scaled the cluster up from 1 to 3 workers for Pending pods, and back 
down to 1 once they were gone. Upgrading the cluster to the second ISO 
redeployed the autoscaler with the newer image, keeping the cluster's min, max 
and id.
   
   **Environment**
   - A CloudStack 24.0 (main) build with this PR, alongside some of my other 
open PRs. The management server and all three agents were upgraded in place to 
this build.
   - The PR targets 4.22; it wasn't run on a 4.22 build. The ISO script and 
`KubernetesClusterUpgradeWorker` are the same on both branches apart from this 
PR.
   - Three KVM hosts, Ceph RBD primary storage, one management server.
   - ISOs built on an Ubuntu 24.04 x86_64 host with containerd's `ctr`. The 
arguments were the same as for the lab's existing ISOs: CNI 1.9.1, Calico 
v3.30.7 and Headlamp 0.40.1.
   - A fresh cluster with 1 control node and 1-3 workers, the CKS system VM 
template and an isolated network. Autoscaling ran with min 1 and max 3.
   
   **Results**
   
   | Check | Result |
   |---|---|
   | Build `setup-v1.32.13` and `setup-v1.33.13` with defaults | pass, 139 s 
and 113 s |
   | `versions.txt` in each ISO | pass. It lists the versions, URLs and image 
digests |
   | Autoscaler and CCM pinned in the ISOs | pass: 1.32.13 -> 
`cluster-autoscaler:v1.32.7` and 1.33.13 -> `v1.33.6`; CCM `v1.2.0` in both |
   | Cluster created from the 1.32.13 ISO, CCM | pass. 
`apache/cloudstack-kubernetes-provider:v1.2.0` runs, and a `LoadBalancer` 
Service gets a CloudStack LB rule |
   | Enable autoscaling (1..3) | pass. Pinned image, `--nodes=1:3:<cluster 
id>`, no RBAC or cache-sync errors |
   | Scale-up on Pending pods | pass, 1 -> 3 workers; all pods Running 232 s 
after they were created |
   | Scale-down when idle | pass, 3 -> 1 workers 654 s after the pods were 
deleted (default idle times) |
   | Upgrade 1.32.13 -> 1.33.13 (the second ISO) | pass, 323 s. The autoscaler 
was redeployed with `v1.33.6`, keeping `--nodes=1:3:<cluster id>` |
   | Node `providerID` and the `uninitialized` taint | not applicable to CKS; 
see the CCM section |
   
   **ISOs**
   - Each ISO has `versions.txt` at the root, next to `autoscaler.yaml` and 
`provider.yaml`. The 1.33.13 one:
     ```
     AUTOSCALER_VERSION=1.33.6
     
AUTOSCALER_MANIFEST_URL=https://raw.githubusercontent.com/kubernetes/autoscaler/cluster-autoscaler-1.33.6/cluster-autoscaler/cloudprovider/cloudstack/examples/cluster-autoscaler-standard.yaml
     AUTOSCALER_IMAGE=registry.k8s.io/autoscaling/cluster-autoscaler:v1.33.6
     CCM_VERSION=v1.2.0
     
CCM_MANIFEST_URL=https://raw.githubusercontent.com/apache/cloudstack-kubernetes-provider/v1.2.0/deployment.yaml
     CCM_IMAGE=apache/cloudstack-kubernetes-provider:v1.2.0
     ...
     
IMAGE=registry.k8s.io/autoscaling/cluster-autoscaler:v1.33.6@sha256:7b44e0f0...
     
IMAGE=docker.io/apache/cloudstack-kubernetes-provider:v1.2.0@sha256:09d3042f...
     ```
     It also has the Kubernetes, CNI, crictl, Calico, Headlamp, CSI and kubelet 
unit URLs, and one `IMAGE=` line with a digest for every bundled image.
   - `docker/` has `cluster-autoscaler_v1.32.7.tar` and 
`cluster-autoscaler_v1.33.6.tar` respectively, and 
`cloudstack-kubernetes-provider_v1.2.0.tar` in both.
   - `autoscaler.yaml` names only the pinned image, with `imagePullPolicy: 
IfNotPresent`. It keeps `--nodes=<min>:<max>:<cluster-id>`, and has the six 
objects of the upstream example plus the `cluster-autoscaler-extra` ClusterRole 
and binding: read access to `volumeattachments`, `deviceclasses`, 
`resourceslices` and `resourceclaims`.
   - `provider.yaml` names `apache/cloudstack-kubernetes-provider:v1.2.0`.
   
   **CCM**
   - On the new cluster, the CCM deployment runs 
`apache/cloudstack-kubernetes-provider:v1.2.0`. The existing clusters, built 
from ISOs made with the old script, run v1.1.0.
   - **A `LoadBalancer` Service.** The CCM acquired a public IP and created a 
CloudStack LB rule (`<svc-uid>-tcp-8080`, 8080 -> NodePort, Active). The 
Service got that IP as its `EXTERNAL-IP` within 12 s. Deleting the Service 
removed the rule.
   - **`providerID` stays empty, on every node, as on the clusters running 
v1.1.0.**
     - CKS starts the kubelets without `--cloud-provider=external` 
(`KUBELET_EXTRA_ARGS=--cgroup-driver=systemd`). So no node gets the 
`node.cloudprovider.kubernetes.io/uninitialized` taint, and nothing is left 
behind.
     - The CCM's node controller only initialises nodes that have that taint, 
whatever its version. So the providerID fix in v1.2.0 doesn't come into play on 
a CKS cluster as it is set up today.
     - This PR doesn't change how the kubelet is started, so I don't count it 
against the PR. The PR description says v1.1.0 "does not initialise nodes", 
which suggests v1.2.0 would initialise them on CKS. It doesn't on its own.
   - I didn't see any effect on the autoscaler. It found the cluster's VMs, 
scaled up and down, and only logged `Failed to get nodegroup for <vm id>: 
Unable to find node ...` warnings for the nodes, as it does without a 
providerID.
   
   **Autoscaler**
   - **Enabling** autoscaling with `scaleKubernetesCluster 
autoscalingenabled=true minsize=1 maxsize=3` deployed it from the ISO's 
manifest:
     ```
     registry.k8s.io/autoscaling/cluster-autoscaler:v1.32.7
     
["./cluster-autoscaler","--v=4","--stderrthreshold=info","--cloud-provider=cloudstack","--cloud-config=/config/cloud-config",
      "--skip-nodes-with-local-storage=false","--nodes=1:3:<cluster id>"]
     ```
   - **Log checks over the whole run** (2,628 lines by the end of the 
scale-down):
     - no `Failed to watch` or `Failed to list` lines, no `forbidden` errors, 
and no cache-sync timeouts. The only `forbidden` matches were the 
`lastScaleDownForbidden...` field in the status lines;
     - one `E` line, `Failed to get node infos for groups: Unable to find node 
...`. It came 45 s after a scaled-down node's VM was removed, and the 
autoscaler carried on normally.
   - **Scale-up:**
     - I created a 3-replica Deployment requesting 1200m CPU each. One pod fit 
on the single worker and two were Pending.
     - The autoscaler logged `Final scale-up plan: [{<cluster id> 1->3 (max: 
3)}]` and `Scale-up: setting group <cluster id> size to 3`. That started a 
`KUBERNETES.CLUSTER.SCALE` job in CloudStack.
     - Two workers were added. The cluster went `Running` -> `Scaling` -> 
`Running` with size 3, and all 3 pods were Running on 3 workers 232 s after the 
Deployment was created.
   - **Scale-down:**
     - I deleted the Deployment.
     - About 10 minutes later the autoscaler logged `Scale-down: removing empty 
node` for both new workers. The cluster went `Scaling` (3) -> `Scaling` (2) -> 
`Running` with size 1, 654 s after the deletion.
     - The upstream example doesn't set `--scale-down-unneeded-time` or 
`--scale-down-delay-after-add`, so the defaults applied. I didn't edit the 
manifest.
   
   **Upgrade redeploys the autoscaler**
   - `upgradeKubernetesCluster` from the 1.32.13 ISO to the 1.33.13 ISO took 
323 s, and ended Running with both nodes on v1.33.13.
   - Afterwards the autoscaler deployment had a new pod:
     ```
     before: registry.k8s.io/autoscaling/cluster-autoscaler:v1.32.7  
--nodes=1:3:<cluster id>  (started 00:27:02)
     after:  registry.k8s.io/autoscaling/cluster-autoscaler:v1.33.6  
--nodes=1:3:<cluster id>  (started 00:52:25)
     ```
   - The new pod's log had no `forbidden`, watch or list, or cache-sync errors.
   - The first attempt on the control node failed with `kubectl apply` of the 
network manifest:
     ```
     ... is forbidden: User "kubernetes-admin" cannot get resource 
"customresourcedefinitions" ...
     RBAC: [clusterrole.rbac.authorization.k8s.io "cluster-admin" not found, 
...]
     ```
     This was right after `kubeadm upgrade apply` restarted the API server, 
before its RBAC cache had synced. The upgrade worker's existing retry succeeded 
on the next attempt. It's not related to the autoscaler change.
   
   **Cleanup:** the cluster and both Kubernetes versions were deleted. Neither 
left a VM, network or ISO behind.
   
   **Result:** pass. The ISO records what it holds and bundles the autoscaler 
that matches its Kubernetes version and CCM v1.2.0. The autoscaler they deploy 
scales a CKS cluster up and down, and an upgrade moves it to the new version's 
autoscaler.
   
   **Not covered**
   - Overrides (`AUTOSCALER_VERSION`, `CCM_VERSION`), aarch64, and building 
with etcd. Only default builds were run on the live cluster.
   - Kubernetes 1.35 and later, where the DRA read access in the extra 
ClusterRole matters most. The CKS template here was used with 1.32 and 1.33.
   - Upgrading a cluster onto an ISO built by the old script.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to