-
Notifications
You must be signed in to change notification settings - Fork 18
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
Update Kubernetes Tentacle to use ConfigMap for configuration storage #674
Conversation
[sc-60480] |
This pull request has been linked to Shortcut Story #60480: When Tentacle is running in Kubernetes, store configuration in ConfigMap. |
4240cfa
to
d8b14a5
Compare
@@ -115,9 +115,6 @@ function configureTentacle() { | |||
tentacle configure --instance "$instanceName" --port $internalListeningPort --noListen "False" | |||
fi | |||
|
|||
echo "Updating trust ..." | |||
tentacle configure --instance "$instanceName" --reset-trust |
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.
This clears out the TrustedOctopusServers
which is set when registering. If we skip registering when we've already registered, we effectively clear out the trusted servers and then never replace them meaning a restart of the container fails.
I've remove this because we set the trusted server once and then never clear it. Is this going to cause us issues?
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.
Rather than removing it, could we skip some of this configuration if we know it's configured? Or do we need to set some information before we start the tentacle app?
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.
If we just skip it when "isRegistered" is true, the only time it would be executed is when "isRegistered" is false, which is when there would be no trusted servers configured anyway. So I thought it didn't really make sense to have it when running in kubernetes...
@@ -596,9 +596,6 @@ public async Task ShowConfigurationCommandLooksSensibleToHumans(TentacleConfigur | |||
{{ | |||
""Thumbprint"": ""{clientAndTentacle.Server.Thumbprint}"", | |||
""CommunicationStyle"": 2, | |||
""KubernetesTentacleCommunicationMode"": {{ | |||
""Value"": ""Polling"" | |||
}}, |
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.
This property only shows up on serialisation if the CommunicationStyle is KubernetesTentacle
now.
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.
I did this because the example below is using CommunicationStyle
of Passive
but the KubernetesTentacleCommunicationMode
says Polling
which is confusing.
@@ -86,26 +87,14 @@ async Task StartAsync() | |||
|
|||
internal async Task CollectConfigurationSettings(DictionaryKeyValueStore outputStore) |
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.
This method was a PITA - The HomeConfiguration
and TentacleConfiguration
classes would take a Configuration store (IKeyValueStore
) but also an instance selector which is what you're meant to use to get the IKeyValueStore
. But it was used to collect the properties to output them in JSON format. It's just very unclear where values are sourced from and where values are set. I think I've made it clearer by using the WriteTo
method so we know that the IKeyValueStore
from the selector is used to source the data and it's written to the outputStore.
c5d8cbf
to
feb31b8
Compare
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.
Broadly I like the approach, there is just a few things that need cleaning up/addressing
@@ -115,9 +115,6 @@ function configureTentacle() { | |||
tentacle configure --instance "$instanceName" --port $internalListeningPort --noListen "False" | |||
fi | |||
|
|||
echo "Updating trust ..." | |||
tentacle configure --instance "$instanceName" --reset-trust |
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.
Rather than removing it, could we skip some of this configuration if we know it's configured? Or do we need to set some information before we start the tentacle app?
source/Octopus.Tentacle/Configuration/Instances/ConfigMapKeyValueStore.cs
Outdated
Show resolved
Hide resolved
source/Octopus.Tentacle/Configuration/Instances/ApplicationInstanceSelector.cs
Outdated
Show resolved
Hide resolved
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.
Looks good! Couple of minor things that aren't blocking. The only other piece missing is the setting encryption when ProectionLevel.MachineKey
using a value in a secret
if (appInstance is { instanceName: not null, configurationpath: null } && | ||
KubernetesConfig.Namespace is {} @namespace) | ||
{ | ||
var message = !string.IsNullOrEmpty(instanceName) | ||
? $"The configuration file for instance {instanceName} could not be located at the specified location {configurationPath}. " + | ||
"The file might have been manually removed without properly removing the instance and as such it is still listed as present." + | ||
"The instance must be created again before you can interact with it." | ||
: $"The configuration file at {configurationPath} could not be located at the specified location."; | ||
|
||
throw new ControlledFailureException(message); | ||
log.Verbose($"Loading configuration from ConfigMap for namespace {@namespace}"); | ||
var configMapWritableStore = configMapStoreFactory.Value; | ||
return (ContributeAdditionalConfiguration(configMapWritableStore), configMapWritableStore); | ||
} |
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.
This check seems weird (checking the namespace). Should we be using the PlatformDetection
here?
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.
Ah yep, good call!
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.
Fixed 👍
Task<V1ConfigMap> Patch(string name, IDictionary<string, string> data, CancellationToken cancellationToken); | ||
} | ||
|
||
public class KubernetesV1ConfigMapService : KubernetesService, IKubernetesV1ConfigMapService |
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.
You can drop the V1
here. I doubt we'll need to worry about V2
K8s apis/types for a while
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.
Removed 👍
…n configuring kubernetes tentacle
…tection implementation
… already registered
# Conflicts: # source/Octopus.Tentacle.Tests/Configuration/ApplicationInstanceSelectorFixture.cs # source/Octopus.Tentacle/Configuration/Instances/ConfigMapKeyValueStore.cs # source/Octopus.Tentacle/Kubernetes/KubernetesModule.cs
815a4de
to
44f4e32
Compare
} | ||
|
||
AggregatedKeyValueStore ContributeAdditionalConfiguration(XmlFileKeyValueStore writableConfig) | ||
bool ConfigurationFileExists([NotNullWhen(true)] string? configurationPath) |
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.
nit: Did these methods need to be pulled out? It may be best to leave what we can alone to avoid any chance of introducing inadvertent changes.
ultra nit: Also since this just throws we could have pulled out the entire if
into a single method.
Background
Part of #project-k8s-agent
To make sure that the Kubernetes Tentacle is able to handle restarts (including when the nfs pod is restarted) we need to update Tentacle to be able to store its configuration into a ConfigMap.
Results
I've add a new
IKeyValueStore
andIWritableKeyValueStore
implementation which stores data in a Kubernetes ConfigMap. It requires a namespace to make sure that each Kubernetes Tentacle in the cluster has a unique ConfigMap.I've also added an
IsRegistered
value to the store so that we can skip registration for Kubernetes Tentacles. We also needed to update the configuration process to remove the "remove trust" step which breaks the configuration process if we're already registered. I thought about updating that command to not clear if we're already registered but that seems to defeat the purpose of the command.How to review this PR
Quality ✔️
Pre-requisites