Skip to content

Commit

Permalink
[yugabyte#8950][Platform] Use matching helm chart version to operate …
Browse files Browse the repository at this point in the history
…on db k8s pods

Summary:
Modify platform release metadata to associate a helm chart with each release
version. Perform kubernetes universe operations (create, edit, upgrade, etc.),
using the helm chart associated with the universe version. If there is no
associated helm chart (and the universe version < 2.7), use special "legacy"
helm chart to manage the universe.

Test Plan:
Launch previous version platform. Create k8s provider and universe. Stop the
platform.

Add two new releases to releases dir and add their helm charts to
helm.packagePath.

Start new version of platform and verify that the helm charts in the
helm.packagePpath are now copied into the releases directory (alongside the
release binary archives) and the platform stores the helm chart paths in the
release metadata.

Observe the releases page shows the helm chart paths for each release.

Perform following operations and ensure the correct version of the helm chart
is used for each step:
1. Increase # of pods (verify legacy 2.7 helm chart is used)
2. Upgrade universe (to newer version that has associated chart)
3. Modify gflags
4. Upgrade universe version (to other newer version)
5. Decrease # of pods
6. Modify gflags
7. Delete universe

Run unit tests.

Run K8s integration tests.

Reviewers: arnav, sanketh

Reviewed By: sanketh

Subscribers: jason, yugaware, jenkins-bot

Differential Revision: https://phabricator.dev.yugabyte.com/D12255
  • Loading branch information
jvigil-yugabyte committed Jul 23, 2021
1 parent d99463e commit 3fd0736
Show file tree
Hide file tree
Showing 24 changed files with 509 additions and 137 deletions.
2 changes: 1 addition & 1 deletion managed/devops/replicated.yml
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ components:
releases.path = "/opt/yugabyte/releases"
docker.release = "/opt/yugabyte/release"
thirdparty.packagePath = /opt/third-party
helm.package = "/opt/yugabyte/helm/yugabyte-latest.tgz"
helm.packagePath = "/opt/yugabyte/helm"
health.check_interval_ms = 300000
health.status_interval_ms = 43200000
health.default_email = "YB_ALERTS_EMAIL_REPLACE"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,14 @@ public void updateRemainingPods(
PlacementInfoUtil.computeMasterAddresses(
newPI, newPlacement.masters, taskParams().nodePrefix, provider, masterRpcPort);

String ybSoftwareVersion = taskParams().getPrimaryCluster().userIntent.ybSoftwareVersion;

upgradePodsTask(
newPlacement,
masterAddresses,
currPlacement,
serverType,
null,
ybSoftwareVersion,
DEFAULT_WAIT_TIME_MS,
masterChanged,
tserverChanged);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ public void createPodsTask(
ServerType serverType,
PlacementInfo activeZones) {

String ybSoftwareVersion = taskParams().getPrimaryCluster().userIntent.ybSoftwareVersion;

boolean edit = currPlacement != null;
boolean isMultiAz = masterAddresses != null;

Expand Down Expand Up @@ -151,7 +153,7 @@ public void createPodsTask(
tempPI,
azCode,
masterAddresses,
null,
ybSoftwareVersion,
serverType,
config,
masterPartition,
Expand Down Expand Up @@ -189,6 +191,7 @@ public void createPodsTask(
tempPI,
azCode,
masterAddresses,
ybSoftwareVersion,
config));

// Add zone to active configs.
Expand Down Expand Up @@ -324,6 +327,8 @@ public void deletePodsTask(
KubernetesPlacement newPlacement,
boolean userIntentChange) {

String ybSoftwareVersion = taskParams().getPrimaryCluster().userIntent.ybSoftwareVersion;

boolean edit = newPlacement != null;
boolean isMultiAz = masterAddresses != null;

Expand Down Expand Up @@ -370,7 +375,12 @@ public void deletePodsTask(
newPlacement.masters.getOrDefault(azUUID, 0);
helmDeletes.addTask(
createKubernetesExecutorTask(
CommandType.HELM_UPGRADE, tempPI, azCode, masterAddresses, config));
CommandType.HELM_UPGRADE,
tempPI,
azCode,
masterAddresses,
ybSoftwareVersion,
config));
podsWait.addTask(
createKubernetesCheckPodNumTask(
KubernetesCheckNumPod.CommandType.WAIT_FOR_PODS,
Expand Down Expand Up @@ -472,22 +482,23 @@ public Set<NodeDetails> getPodsToRemove(
// Create Kubernetes Executor task for creating the namespaces and pull secrets.
public KubernetesCommandExecutor createKubernetesExecutorTask(
KubernetesCommandExecutor.CommandType commandType, String az, Map<String, String> config) {
return createKubernetesExecutorTask(commandType, null, az, null, config);
return createKubernetesExecutorTask(commandType, null, az, null, null, config);
}

// Create the Kubernetes Executor task for the helm deployments. (USED)
public KubernetesCommandExecutor createKubernetesExecutorTask(
KubernetesCommandExecutor.CommandType commandType,
CommandType commandType,
PlacementInfo pi,
String az,
String masterAddresses,
String ybSoftwareVersion,
Map<String, String> config) {
return createKubernetesExecutorTaskForServerType(
commandType,
pi,
az,
masterAddresses,
null,
ybSoftwareVersion,
ServerType.EITHER,
config,
0 /* master partition */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,15 @@ private SubTaskGroupType getTaskSubGroupType() {
}

private void createUpgradeTask(UserIntent userIntent, Universe universe, PlacementInfo pi) {
String version = null;
String ybSoftwareVersion = null;
boolean masterChanged = false;
boolean tserverChanged = false;
if (taskParams().taskType == UpgradeTaskType.Software) {
version = taskParams().ybSoftwareVersion;
ybSoftwareVersion = taskParams().ybSoftwareVersion;
masterChanged = true;
tserverChanged = true;
} else {
ybSoftwareVersion = userIntent.ybSoftwareVersion;
if (!taskParams().masterGFlags.equals(userIntent.masterGFlags)) {
masterChanged = true;
}
Expand Down Expand Up @@ -164,7 +165,7 @@ private void createUpgradeTask(UserIntent userIntent, Universe universe, Placeme
masterAddresses,
null,
ServerType.MASTER,
version,
ybSoftwareVersion,
taskParams().sleepAfterMasterRestartMillis,
masterChanged,
tserverChanged);
Expand All @@ -179,7 +180,7 @@ private void createUpgradeTask(UserIntent userIntent, Universe universe, Placeme
masterAddresses,
null,
ServerType.TSERVER,
version,
ybSoftwareVersion,
taskParams().sleepAfterTServerRestartMillis,
false /* master change is false since it has already been upgraded.*/,
tserverChanged);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ public void run() {
overridesFile = this.generateHelmOverride();
response =
kubernetesManager.helmInstall(
taskParams().ybSoftwareVersion,
config,
taskParams().providerUUID,
taskParams().nodePrefix,
Expand All @@ -185,7 +186,11 @@ public void run() {
overridesFile = this.generateHelmOverride();
response =
kubernetesManager.helmUpgrade(
config, taskParams().nodePrefix, taskParams().namespace, overridesFile);
taskParams().ybSoftwareVersion,
config,
taskParams().nodePrefix,
taskParams().namespace,
overridesFile);
flag = true;
break;
case UPDATE_NUM_NODES:
Expand Down
70 changes: 55 additions & 15 deletions managed/src/main/java/com/yugabyte/yw/common/KubernetesManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.ImmutableList;
import com.google.inject.Inject;
import com.yugabyte.yw.models.Provider;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand All @@ -16,17 +16,22 @@

@Singleton
public class KubernetesManager {
public static final Logger LOG = LoggerFactory.getLogger(KubernetesManager.class);

private static final long DEFAULT_TIMEOUT_SECS = 300;
@Inject ReleaseManager releaseManager;

@Inject ShellProcessHandler shellProcessHandler;

@Inject play.Configuration appConfig;

private static String SERVICE_INFO_JSONPATH =
public static final Logger LOG = LoggerFactory.getLogger(KubernetesManager.class);

private static final long DEFAULT_TIMEOUT_SECS = 300;

private static final String SERVICE_INFO_JSONPATH =
"{.spec.clusterIP}|" + "{.status.*.ingress[0].ip}|{.status.*.ingress[0].hostname}";

private static final String LEGACY_HELM_CHART_FILENAME = "yugabyte-2.7-helm-legacy.tar.gz";

public ShellResponse createNamespace(Map<String, String> config, String universePrefix) {
List<String> commandList = ImmutableList.of("kubectl", "create", "namespace", universePrefix);
return execCommand(config, commandList);
Expand Down Expand Up @@ -54,17 +59,15 @@ public String getTimeout() {
}

public ShellResponse helmInstall(
String ybSoftwareVersion,
Map<String, String> config,
UUID providerUUID,
String universePrefix,
String namespace,
String overridesFile) {
String helmPackagePath = appConfig.getString("yb.helm.package");
if (helmPackagePath == null || helmPackagePath.isEmpty()) {
throw new RuntimeException("Helm Package path not provided.");
}
Provider provider = Provider.get(providerUUID);
Map<String, String> configProvider = provider.getConfig();

String helmPackagePath = this.getHelmPackagePath(ybSoftwareVersion);

List<String> commandList =
ImmutableList.of(
"helm",
Expand Down Expand Up @@ -180,11 +183,14 @@ public ShellResponse runGetSecret(
}

public ShellResponse helmUpgrade(
Map<String, String> config, String universePrefix, String namespace, String overridesFile) {
String helmPackagePath = appConfig.getString("yb.helm.package");
if (helmPackagePath == null || helmPackagePath.isEmpty()) {
throw new RuntimeException("Helm Package path not provided.");
}
String ybSoftwareVersion,
Map<String, String> config,
String universePrefix,
String namespace,
String overridesFile) {

String helmPackagePath = this.getHelmPackagePath(ybSoftwareVersion);

List<String> commandList =
ImmutableList.of(
"helm",
Expand Down Expand Up @@ -257,4 +263,38 @@ private ShellResponse execCommand(Map<String, String> config, List<String> comma
String description = String.join(" ", command);
return shellProcessHandler.run(command, config, description);
}

public String getHelmPackagePath(String ybSoftwareVersion) {
String helmPackagePath = null;

// Get helm package filename from release metadata.
ReleaseManager.ReleaseMetadata releaseMetadata =
releaseManager.getReleaseByVersion(ybSoftwareVersion);
if (releaseMetadata != null) {
helmPackagePath = releaseMetadata.chartPath;
}

if (helmPackagePath == null || helmPackagePath.isEmpty()) {
// TODO: The "legacy" helm chart is included in the yugaware container build to ensure that
// universes deployed using previous versions of the platform (that did not use versioned
// helm charts) will still be usable after upgrading to newer versions of the platform (that
// use versioned helm charts). We can (and should) remove this special case once all customers
// that use the k8s provider have upgraded their platforms and universes to versions > 2.7.
if (Util.compareYbVersions(ybSoftwareVersion, "2.8.0.0") < 0) {
helmPackagePath =
new File(appConfig.getString("yb.helm.packagePath"), LEGACY_HELM_CHART_FILENAME)
.toString();
} else {
throw new RuntimeException("Helm Package path not found for release: " + ybSoftwareVersion);
}
}

// Ensure helm package file actually exists.
File helmPackage = new File(helmPackagePath);
if (!helmPackage.exists()) {
throw new RuntimeException("Helm Package file not found: " + helmPackagePath);
}

return helmPackagePath;
}
}
Loading

0 comments on commit 3fd0736

Please sign in to comment.