-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement mass machine type transition job WIP #2
Draft
prnaraya
wants to merge
13
commits into
main
Choose a base branch
from
dev
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
763ec77
WIP commit, adding the base functions for the job and the informers
prnaraya 7e70d95
Reorganized the functions/files and added a completion count function.
prnaraya 1febd5e
Updated README
prnaraya 7233349
Implemented job using docker image created from golang code
prnaraya 87dbd43
Adding vmiList to track VMs that need to be restarted
prnaraya 49b1e41
Adding restartnow flag and implemented logic to restart all affected …
prnaraya e7d4d01
Addressing Itamar's comments
prnaraya 906d592
Adding env variables for restart now flag and namespace flag
prnaraya d72c2e7
Merge branch 'restart-now-flag' into dev
prnaraya b0b2b56
Removed update function for the VMIs as it is not necessary
prnaraya e97b107
Restructured files to move non-informer functions into their own file.
prnaraya aec2a17
Updating machine type of all VMs who have machine type of "q35"
prnaraya 88419b9
Update the addWarningLabel to apply the label to the VM rather than t…
prnaraya File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
FROM golang:alpine | ||
RUN mkdir /app | ||
ADD . /app/ | ||
WORKDIR /app | ||
RUN go build -o main . | ||
RUN adduser -S -D -H -h /app appuser | ||
USER appuser | ||
CMD ["./main"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
# Mass machine type transition | ||
This project contains the k8s job that will perform a mass machine type transition on an OpenShift cluster. | ||
|
||
## Notes | ||
This is a more cohesive version of the mass machine type transition. This implementation uses Docker to create an image from the golang script that performs the machine type transition, and hangs until all warnings are cleared. The .yaml file is a job that uses this generated image, and will only be completed once this script exits, i.e. there are no warning labels left on any VMs. To run this locally, you will need to build a Docker image with the tag "machine-type-transition", then start the job with kubectl apply. This is not comprehensively tested yet; in the future I will be automating the process of running this job, as well as adding functionality for the user to specify flags to update machine types only on specific namespaces, and to force a restart/shut down of all running VMs when updating their machine types. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,48 @@ | ||
package mass_machine_type_transition | ||
|
||
import "os" | ||
import ( | ||
"fmt" | ||
"os" | ||
"strconv" | ||
) | ||
|
||
func main() { | ||
vmiInformer, err := getVmiInformer() | ||
var err error | ||
// update restartNow if env is set | ||
restartEnv, exists := os.LookupEnv("FORCE_RESTART") | ||
if exists { | ||
restartNow, err = strconv.ParseBool(restartEnv) | ||
if err != nil { | ||
fmt.Println(err) | ||
} | ||
} | ||
|
||
// update namespace if env is set | ||
namespaceEnv, exists := os.LookupEnv("NAMESPACE") | ||
if exists { | ||
namespace = namespaceEnv | ||
} | ||
|
||
virtCli, err := getVirtCli() | ||
if err != nil { | ||
os.Exit(1) | ||
} | ||
|
||
if vmiInformer != nil { | ||
|
||
vmiInformer, err := getVmiInformer(virtCli) | ||
if err != nil { | ||
os.Exit(1) | ||
} | ||
|
||
|
||
go vmiInformer.Run(exitJob) | ||
|
||
|
||
err = updateMachineTypes(virtCli) | ||
if err != nil { | ||
fmt.Println(err) | ||
} | ||
|
||
// wait for list of VMIs that need restart to be empty | ||
<-exitJob | ||
|
||
os.Exit(0) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
apiVersion: batch/v1 | ||
kind: Job | ||
metadata: | ||
name: mass-machine-type-transition | ||
spec: | ||
template: | ||
metadata: | ||
name: mass-machine-type-transition | ||
spec: | ||
containers: | ||
- name: machine-type-transition | ||
image: machine-type-transition:latest | ||
imagePullPolicy: IfNotPresent | ||
env: | ||
- name: NAMESPACE | ||
value: "" | ||
- name: FORCE_RESTART | ||
value: false | ||
restartPolicy: OnFailure |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package mass_machine_type_transition | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
k8sv1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/types" | ||
"k8s.io/client-go/tools/cache" | ||
k6tv1 "kubevirt.io/api/core/v1" | ||
"kubevirt.io/client-go/kubecli" | ||
) | ||
|
||
// using this as a const allows us to easily modify the program to update if a newer version is released | ||
// we generally want to be updating the machine types to the most recent version | ||
const latestMachineTypeVersion = "rhel9.2.0" | ||
|
||
var ( | ||
vmisPendingUpdate = make(map[string]struct{}) | ||
exitJob = make(chan struct{}) | ||
|
||
// by default, update machine type across all namespaces | ||
namespace = k8sv1.NamespaceAll | ||
//labels []string | ||
|
||
// by default, should require manual restarting of VMIs | ||
restartNow = false | ||
) | ||
|
||
func patchVmMachineType(virtCli kubecli.KubevirtClient, vm *k6tv1.VirtualMachine, machineType string) error { | ||
updateMachineType := fmt.Sprintf(`{"spec": {"template": {"spec": {"domain": {"machine": {"type": "%s"}}}}}}`, machineType) | ||
|
||
_, err := virtCli.VirtualMachine(vm.Namespace).Patch(vm.Name, types.StrategicMergePatchType, []byte(updateMachineType), &k8sv1.PatchOptions{}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// add label to running VMs that a restart is required for change to take place | ||
if vm.Status.Created { | ||
// adding the warning label to the VMs regardless if we restart them now or if the user does it manually | ||
// shouldn't matter, since the deletion of the VMI will remove the label and remove the vmi list anyway | ||
err = addWarningLabel(virtCli, vm) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if restartNow { | ||
err = virtCli.VirtualMachine(vm.Namespace).Restart(vm.Name, &k6tv1.RestartOptions{}) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func updateMachineTypes(virtCli kubecli.KubevirtClient) error { | ||
vmList, err := virtCli.VirtualMachine(namespace).List(&k8sv1.ListOptions{}) | ||
if err != nil { | ||
return err | ||
} | ||
for _, vm := range vmList.Items { | ||
machineType := vm.Spec.Template.Spec.Domain.Machine.Type | ||
machineTypeSubstrings := strings.Split(machineType, "-") | ||
|
||
// in the case where q35 is the machine type, the VMI status will contain the | ||
// full machine type string. Since q35 is an alias for the most recent machine type, | ||
// if a VM hasn't been restarted and thus still has an outdated machine type, it should | ||
// be updated to the most recent machine type. I'm not able to access the machine type from | ||
// VMI status using the kv library, so instead I am opting to update the machine types of all | ||
// VMs with q35 instead. It might only be necessary to update the ones that are running as well, | ||
// though I am not sure. | ||
|
||
if len(machineTypeSubstrings) == 1 { | ||
if machineTypeSubstrings[0] == "q35" { | ||
machineType = "pc-q35-" + latestMachineTypeVersion | ||
return patchVmMachineType(virtCli, &vm, machineType) | ||
} | ||
} | ||
|
||
if len(machineTypeSubstrings) == 3 { | ||
version := machineTypeSubstrings[2] | ||
if strings.Contains(version, "rhel") && version < "rhel9.0.0" { | ||
machineTypeSubstrings[2] = latestMachineTypeVersion | ||
machineType = strings.Join(machineTypeSubstrings, "-") | ||
return patchVmMachineType(virtCli, &vm, machineType) | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func addWarningLabel (virtCli kubecli.KubevirtClient, vm *k6tv1.VirtualMachine) error { | ||
addLabel := fmt.Sprint(`{"metadata": {"labels": {"restart-vm-required": "true"}}}}}`) | ||
_, err := virtCli.VirtualMachine(vm.Namespace).Patch(vm.Name, types.StrategicMergePatchType, []byte(addLabel), &k8sv1.PatchOptions{}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// get VM name in the format namespace/name | ||
vmKey, err := cache.MetaNamespaceKeyFunc(vm) | ||
if err != nil { | ||
return err | ||
} | ||
vmisPendingUpdate[vmKey] = struct{}{} | ||
|
||
return nil | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please log / print an error in this case, since it never should happen