Skip to content
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

feat(k8s): dynamic account config #3824

Merged
merged 10 commits into from
Jul 8, 2019

Conversation

ethanfrogers
Copy link
Contributor

@ethanfrogers ethanfrogers commented Jun 27, 2019

implement credential synchronization for kubernetes accounts. defines
CredentialsInitializerSynchronizable on the
KubernetesV*ProviderConfig classes. Each of these classes is
responsible for handling accounts for each provider version.

@ethanfrogers ethanfrogers changed the title feat(k8s): dynamic account config WIP feat(k8s): dynamic account config Jun 27, 2019
@ethanfrogers
Copy link
Contributor Author

ethanfrogers commented Jun 27, 2019

@scottfrederick @ezimanyi submitting a new PR for feedback. It was easier to implement @scottfrederick suggestions on a wholly new branch.

Per his feedback, I've implemented credential synchronization on the 2 provider config classes to prevent the circular dependency between the synchronizer and CatsModule. This seems much cleaner to me.

I'm still not sure what the ScheduledExecutorService is used for in KubernetesV2ProviderConfig as that class does not implement Runnable. Perhaps it's unnecessary? Any insight here would be helpful!

@ethanfrogers
Copy link
Contributor Author

Oh, one more thing I forgot to mention - each time credentials are refreshed we go through the whole check permissions process unless checkPermissionsOnStartup is set to false. As noted in the previous PR, this is a pretty lengthy process which may prove troublesome with a large number of accounts. One one hand, we should do this in the event that permissions on the service account have changed.

@scottfrederick
Copy link
Contributor

This seems much cleaner to me.

Me too! Aside from some cleanup (which I assume is why it's still WIP), this looks like it should work.

It looks like you'll need equals() and hashcode() methods in KubernetesNamedAccountCredentials to get the detection of changed accounts to work.

@ethanfrogers
Copy link
Contributor Author

@scottfrederick I started working on that in the next commit but got distracted by something else. I'll either have it up today or next week.

@ethanfrogers
Copy link
Contributor Author

I ran into a bit of a blocker while implementing the equals and hashCode methods. In order to properly determine if the account has changed you need to compare the underlying credentials (KubernetesV2Credentials) which means that you need the full list of omitKinds and namespaces which, unless defined explicitly, are collected from the Kubernetes API, which is a lengthy process today. In fact, this is one of the exact problems this feature is meant to overcome - the long startup time of Clouddriver. I think we need to address that before this really makes sense. If we don't then it will take the same amount of time it takes Clouddriver to boot.

cc @ezimanyi

@ethanfrogers
Copy link
Contributor Author

With respect to the above comment - while the initialization of credentials is a performance problem it isn't necessarily a blocker to implementing this functionality (dynamic accounts) but more of a tradeoff that can be addressed in a subsequent PR. I'll ensure that this PR is cleaned up and ready to merge before addressing that issue.

@ethanfrogers ethanfrogers force-pushed the kubernetes-cloud-config-2 branch 2 times, most recently from 8256d87 to e639263 Compare June 28, 2019 19:00
@ethanfrogers ethanfrogers changed the title WIP feat(k8s): dynamic account config feat(k8s): dynamic account config Jun 28, 2019
@ethanfrogers
Copy link
Contributor Author

@ezimanyi @scottfrederick I think this is ready for an official review!

Copy link
Contributor

@scottfrederick scottfrederick left a comment

Choose a reason for hiding this comment

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

@ethanfrogers I ran into something when testing this. When kubeconfigFile is a reference to an external file like configserver:kubeconfig (after the PR to support that was merged), KubernetesV2Credentials#equals() will never return true, and therefore KubernetesNamedAccountCredentials#equals() will never return true, and therefore the account sync logic sees the account as "changed" on each refresh.

The root cause of this is that in this scenario each new KubernetesNamedAccountCredentials results in a new temp file being generated with a unique name.

It seems like it would be important for the account sync to know if the kubeconfigFile value were changed on refresh. Maybe ConfigFileService should create a file with a known name in the system tmp dir instead of generating a random file name each time? Kubernetes provider is the only thing using the code path through ConfigFileService that writes the config server file contents to a local file in the container.

AccountCredentialsRepository accountCredentialsRepository,
KubernetesV1CachingAgentDispatcher kubernetesV1CachingAgentDispatcher) {
this.kubernetesV1Provider = new KubernetesV1Provider(kubernetesCloudProvider, Collections.newSetFromMap(new ConcurrentHashMap<Agent, Boolean>()))
class KubernetesV1ProviderConfig implements CredentialsInitializerSynchronizable {
Copy link
Contributor

Choose a reason for hiding this comment

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

A name like KubernetesV1ProviderSynchronizable would be better, since this is no longer an @Configuration class.

@DependsOn("kubernetesNamedAccountCredentials")
KubernetesV2Provider kubernetesV2Provider(
KubernetesCloudProvider kubernetesCloudProvider,
public class KubernetesV2ProviderConfig implements CredentialsInitializerSynchronizable {
Copy link
Contributor

Choose a reason for hiding this comment

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

KubernetesV2ProviderSynchronizable would be better

@scottfrederick
Copy link
Contributor

See #3833 to fix the issue of temp files on refresh.

Copy link
Contributor

@ezimanyi ezimanyi left a comment

Choose a reason for hiding this comment

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

Overall this looks really good! I left a number of inline comments about specific things.

One more general thing is I'd like to see some more tests validating this; at a minimum the tests that were deleted should be recreated in the right place to ensure the logic they were testing is not broken.

this.kubernetesSpinnakerKindMap = kubernetesSpinnakerKindMap
this.catsModule = catsModule

ScheduledExecutorService poller = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory(KubernetesV1ProviderSynchronizable.class.getSimpleName()))
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this being used at all? It looks like we just create it and let it go out of scope.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's something I was confused about. We were doing this in the previous version of this file but I could not figure out what it was actually used for.

@ethanfrogers ethanfrogers force-pushed the kubernetes-cloud-config-2 branch 3 times, most recently from 60c999f to 6a2be6d Compare July 3, 2019 14:24
@ethanfrogers
Copy link
Contributor Author

@ezimanyi I've addressed most of the feedback so far. I only need to address the bit about the metrics flag and add tests. Thanks for the thorough review and the perf recommendations!

@ethanfrogers ethanfrogers force-pushed the kubernetes-cloud-config-2 branch 4 times, most recently from ab26920 to 68bdb72 Compare July 3, 2019 20:02
Copy link
Contributor

@ezimanyi ezimanyi left a comment

Choose a reason for hiding this comment

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

Changes look good! Three tiny comments inline.

The only remaining question from the first review is if we can remove the poller objects...I'm pretty sure they're not needed (unless they are doing something crazy that I don't understand) but also am fine leaving them if they were there before and we don't want to add to this change.

@@ -66,12 +67,17 @@ class KubernetesConfigurationProperties {
}

@ToString(includeNames = true)
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
Copy link
Contributor

Choose a reason for hiding this comment

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

For something like this where you're going to include everything, might be easier to leave out the onlyExplicitlyIncluded (though this may just be leftover from when you were testing this as I think you said this class was behaving strangely).


@Getter private boolean metrics;
@Getter private final boolean debug;
@Include @Getter private boolean metrics;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we could remove the @Getter on the metrics now to make it more clear that consumers shouldn't care. (I think it's used in one test, but that test should probably just check the computed one.)

@@ -0,0 +1,126 @@
/*
* Copyright 2019 Netflix, Inc.
Copy link
Contributor

Choose a reason for hiding this comment

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

s/Netflix/Armory/

@ethanfrogers ethanfrogers force-pushed the kubernetes-cloud-config-2 branch 2 times, most recently from 7125fa1 to 89e12e1 Compare July 8, 2019 15:27
implement credential synchronization for kubernetes accounts. defines
`CredentialsInitializerSynchronizable` on the
`KubernetesV*ProviderConfig` classes. Each of these classes is
responsible for handling accounts for each provider version.
renames provider config classes to synchronizable since there is no
longer an `@Configuration` annotation.
adds a `kubeconfigFileHash` property which enables us to determine if
the file contents of the kubeconfig file changed even if the path hasn't
changed. this kind of change warrants an account refresh becuase the
credentials used by the account may have possibly changed.
previously, we were modifying omitKinds when an account was initialized.
this caused calls to `equals` to fail because they didn't match
configured omitKinds. this change defers to `omitKindsComputed` so that
checking new and existing credentials is accurate according to how the
account it configured. this allows us to only initialize modified or new
accounts rather than every credential.
addressing PR feedback
@ethanfrogers ethanfrogers merged commit 8b941c7 into spinnaker:master Jul 8, 2019
@ethanfrogers ethanfrogers deleted the kubernetes-cloud-config-2 branch July 8, 2019 17:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants