Skip to content

Initial state transfer - #2

Merged
jmontleon merged 8 commits into
migtools:mainfrom
jmontleon:initial-state-transfer
Jun 25, 2021
Merged

Initial state transfer#2
jmontleon merged 8 commits into
migtools:mainfrom
jmontleon:initial-state-transfer

Conversation

@jmontleon

Copy link
Copy Markdown
Contributor

Not ready for merge. Publishing a PR for visibility and to allow feedback.

https://github.com/jmontleon/crane-test makes use of this library as a simple test.

It provides interfaces for a transfer method such as rsync (potentiall rclone and others), a transport like stunnel, and endpoint such as route and loadbalancer

I've run tests with:

rsync/stunnel/route
rsync/stunnel/loadbalancer

Comment thread state_transfer/route_endpoint.go
@jmontleon

Copy link
Copy Markdown
Contributor Author

Added a null/socat transport to demonstrate swapping out. Could be useful in cases where the transfer utility provides encryption too. I did this with a load balancer. I believe using a rsync/socat/route combo wouldn't work due to route limitations like we hit when working with pvc migrate, but I'll confirm later... There might be need for a compatibility matrix...

I'd like to add rclone to the mix as well, but I need to sit down and learn some about rclone.

@jmontleon
jmontleon force-pushed the initial-state-transfer branch from 6eacd67 to a503346 Compare May 7, 2021 02:21
Comment thread state_transfer/quiesce.go
)

// Quiesce applications on source cluster
func QuiesceApplications(cfg *rest.Config, ns string) error {

@alaypatel07 alaypatel07 May 7, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wired up this example to use the scale subresource instead of patching the objects on each GVR separately , if it helps you in anyway to make this modular https://gist.github.com/alaypatel07/4c1494f70b3cebad1f9534c1c0fde639#file-scale-go-L151.

I would have strongly urged to do this way but I think it will not work with jobs and deploymentconfig is doubtful so it is kind of up to you.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update 1: I verified, deploymentconfigs works with generic approach in the gist

@jmontleon jmontleon May 7, 2021

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alaypatel07 thank you for investigating. I was talking to Shawn late yesterday and I think it would be nice if we had an interface for quiesce as well. We could have simple, scaler, and / or others. It may be beneficial to have multiple options like with the other interfaces; here I could even see potential for perhaps running multiple quiesce options on one cluster if we become able to handle different classes of applications better or worse.

For now I was looking to mimic what MTC does so I can do a quiesced data migration so the thought here is less well formed.

@jmontleon
jmontleon force-pushed the initial-state-transfer branch 2 times, most recently from 0b85235 to 18cafdb Compare May 7, 2021 13:51
@jmontleon

jmontleon commented May 7, 2021

Copy link
Copy Markdown
Contributor Author

Added rclone transfer and a README.md with a compatibility matrix. Without stunnel neither work over routes.

@jmontleon
jmontleon force-pushed the initial-state-transfer branch 4 times, most recently from 1b37e06 to 21de238 Compare May 10, 2021 17:17
@jmontleon
jmontleon requested a review from jortel May 10, 2021 18:28

@shawn-hurley shawn-hurley left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, the implementation looks right, I think we should take a second on the interfaces though WDYT?

Comment thread state_transfer/endpoint.go Outdated
var labels = map[string]string{"app": "crane2"}

type Transfer interface {
SetSource(*rest.Config)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if instead of this, should we create an initializer that creates a Transfer object, but the sources are set in stone? same with PVC/Endpoint/Transport...

I wonder if a builder pattern with an options struct might be an interesting UX here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That might make sense. I'll admit to not being 100% certain on what the best/simplest way to build up an entire transfer would be.


func createLoadBalancerService(c client.Client, r *LoadBalancerEndpoint, t Transfer) error {
serviceSelector := labels
serviceSelector["pvc"] = t.PVC().Name

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since the label selector will only work when pods have this label. If the name of PVC is larger than 63 chars, this would be an invalid label. We would have to make sure we get the labels truncated or hashed.

}

//FIXME. Seems to take a moment, probably something better to do than wait 5 seconds
time.Sleep(5 * time.Second)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably split this into two methods, CreateEndpoint simply tries to create the service. The other method, ValidateEndpoint checks if the valid status is present? Once the valid status is populated, we can call the r.SetHostname and r.SetPort

return err
}

//FIXME. Seems to take a moment, probably something better to do than wait 5 seconds

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rcloneConfigMap := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: r.PVC().Namespace,
Name: rcloneConfigPrefix + r.PVC().Name,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you probably want to be using something more narrow-scoped for not running into shared config with same named PVC accross two namespaces.

DVM uses md5hash(rcloneConfigPrefix + r.PVC().Name + r.PVC().Namespace), we got bugs in DVM where PVC name was the same across two namespaces and the config was shared and failed DVM

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't fully understand, but sure, if this produces something unique, it works for me. That's all I was after.


err := createRcloneServerConfig(c, r)
if err != nil {
return err

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might want to check if this error is IsAlreadyExists(err)

If the config exists the right things to do is to update/patch with the desired configuration


func (r *RcloneTransfer) createTransferServer(c client.Client) error {
deploymentLabels := labels
deploymentLabels["pvc"] = r.PVC().Name

@alaypatel07 alaypatel07 Jun 22, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as the previous comment about PVC names greater than 63 chars

Comment thread state_transfer/route_endpoint.go
return err
}

r.SetHostname(route.Spec.Host)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alaypatel07 alaypatel07 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we could have subpackages for each major component. The pattern I have seen is something like this:

state_transfer/endpoint/*
state_transfer/transport/*
state_transfer/transfer/*

and then each package has an interface.go which would declare the interface, other files can be implementation or helpers for implementation.

@alaypatel07
alaypatel07 marked this pull request as ready for review June 24, 2021 15:55
@alaypatel07

Copy link
Copy Markdown

@jmontleon I am sorry I clicked the "Ready for review" button by mistake.

@alaypatel07
alaypatel07 marked this pull request as draft June 24, 2021 15:56
@jmontleon
jmontleon force-pushed the initial-state-transfer branch 2 times, most recently from 8973fbb to 0c72d75 Compare June 25, 2021 16:32
@jmontleon
jmontleon marked this pull request as ready for review June 25, 2021 16:34
@jmontleon
jmontleon force-pushed the initial-state-transfer branch from 0c72d75 to 1240609 Compare June 25, 2021 16:36
@jmontleon
jmontleon force-pushed the initial-state-transfer branch from 1240609 to 5529834 Compare June 25, 2021 16:36
@jmontleon

Copy link
Copy Markdown
Contributor Author

@alaypatel07 @shawn-hurley i would vote merge from here so we can start working in earnest. I feel like the client scheme setup and stuff is creating a couple unnecessary functions but maybe one of you can lend some wizardry after it's merged.

@alaypatel07

Copy link
Copy Markdown

Sounds good to me on the merge.

@jmontleon

Copy link
Copy Markdown
Contributor Author

Sounds good to me on the merge.

I haven't fixed a lot of the stuff you mentioned here. I'll parse them out into Issues so we don't forget. They make sense. Just not sure it should hold up getting code in so we can start improving.

@jmontleon

Copy link
Copy Markdown
Contributor Author

I think that's all of them.

@shawn-hurley shawn-hurley left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree on merging and starting to work in parallel

@jmontleon
jmontleon merged commit a5ead85 into migtools:main Jun 25, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants