[Operator] Allow to configure to chown NFS volumes
Change-Id: I573ce6a9d5eed385d4bd68a28d2b5848e47b8074
diff --git a/operator/README.md b/operator/README.md
index a4e2e02..6ea2313 100644
--- a/operator/README.md
+++ b/operator/README.md
@@ -147,10 +147,15 @@
## NFS is not well supported by Kubernetes. These options provide a workaround
## to ensure correct file ownership and id mapping
nfsWorkaround:
- ## If enabled, file ownership will be manually set, if a volume is mounted
- ## for the first time. (default: false)
+ ## If enabled, below options might be used. (default: false)
enabled: false
+ ## If enabled, the ownership of the mounted NFS volumes will be set on pod
+ ## startup. Note that this is not done recursively. It is expected that all
+ ## data already present in the volume was created by the user used in accessing
+ ## containers. (default: false)
+ chownOnStartup: false
+
## The idmapd.config file can be used to e.g. configure the ID domain. This
## might be necessary for some NFS servers to ensure correct mapping of
## user and group IDs. (optional)
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/GerritCluster.java b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/GerritCluster.java
index ddc15ac..98f6232 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/GerritCluster.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/GerritCluster.java
@@ -20,6 +20,10 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.gerrit.k8s.operator.gerrit.Gerrit;
+import io.fabric8.kubernetes.api.model.Container;
+import io.fabric8.kubernetes.api.model.ContainerBuilder;
+import io.fabric8.kubernetes.api.model.EnvVar;
+import io.fabric8.kubernetes.api.model.EnvVarBuilder;
import io.fabric8.kubernetes.api.model.Namespaced;
import io.fabric8.kubernetes.api.model.Volume;
import io.fabric8.kubernetes.api.model.VolumeBuilder;
@@ -29,7 +33,9 @@
import io.fabric8.kubernetes.model.annotation.Group;
import io.fabric8.kubernetes.model.annotation.ShortNames;
import io.fabric8.kubernetes.model.annotation.Version;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
@@ -43,6 +49,8 @@
private static final String GIT_REPOSITORIES_VOLUME_NAME = "git-repositories";
private static final String LOGS_VOLUME_NAME = "logs";
private static final String NFS_IDMAPD_CONFIG_VOLUME_NAME = "nfs-config";
+ private static final int GERRIT_FS_UID = 1000;
+ private static final int GERRIT_FS_GID = 100;
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
@@ -129,4 +137,39 @@
public static boolean isGerritInstancePartOfCluster(Gerrit gerrit, GerritCluster cluster) {
return gerrit.getSpec().getCluster().equals(cluster.getMetadata().getName());
}
+
+ @JsonIgnore
+ public Container createNfsInitContainer() {
+ List<VolumeMount> volumeMounts = new ArrayList<>();
+ volumeMounts.add(getLogsVolumeMount());
+ volumeMounts.add(getGitRepositoriesVolumeMount());
+
+ if (getSpec().getStorageClasses().getNfsWorkaround().getIdmapdConfig() != null) {
+ volumeMounts.add(getNfsImapdConfigVolumeMount());
+ }
+
+ return new ContainerBuilder()
+ .withName("nfs-init")
+ .withImagePullPolicy(getSpec().getImagePullPolicy())
+ .withImage(getSpec().getBusyBox().getBusyBoxImage())
+ .withCommand(List.of("sh", "-c"))
+ .withArgs(
+ String.format(
+ "chown -R %d:%d /var/mnt/logs /var/mnt/git", GERRIT_FS_UID, GERRIT_FS_GID))
+ .withEnv(getPodNameEnvVar())
+ .withVolumeMounts(volumeMounts)
+ .build();
+ }
+
+ @JsonIgnore
+ public static EnvVar getPodNameEnvVar() {
+ return new EnvVarBuilder()
+ .withName("POD_NAME")
+ .withNewValueFrom()
+ .withNewFieldRef()
+ .withFieldPath("metadata.name")
+ .endFieldRef()
+ .endValueFrom()
+ .build();
+ }
}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/NfsWorkaroundConfig.java b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/NfsWorkaroundConfig.java
index 5408333..590a1b0 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/NfsWorkaroundConfig.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/NfsWorkaroundConfig.java
@@ -17,6 +17,7 @@
public class NfsWorkaroundConfig {
private boolean enabled = false;
+ private boolean chownOnStartup = false;
private String idmapdConfig;
public boolean isEnabled() {
@@ -27,6 +28,14 @@
this.enabled = enabled;
}
+ public boolean isChownOnStartup() {
+ return chownOnStartup;
+ }
+
+ public void setChownOnStartup(boolean chownOnStartup) {
+ this.chownOnStartup = chownOnStartup;
+ }
+
public String getIdmapdConfig() {
return idmapdConfig;
}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/StatefulSetDependentResource.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/StatefulSetDependentResource.java
index 7726274..ece807b 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/StatefulSetDependentResource.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/StatefulSetDependentResource.java
@@ -15,7 +15,9 @@
package com.google.gerrit.k8s.operator.gerrit;
import com.google.gerrit.k8s.operator.cluster.GerritCluster;
+import com.google.gerrit.k8s.operator.cluster.NfsWorkaroundConfig;
import com.google.gerrit.k8s.operator.cluster.PluginCachePVC;
+import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.ContainerPort;
import io.fabric8.kubernetes.api.model.Volume;
import io.fabric8.kubernetes.api.model.VolumeBuilder;
@@ -59,6 +61,14 @@
StatefulSetBuilder stsBuilder = new StatefulSetBuilder();
+ List<Container> initContainers = new ArrayList<>();
+
+ NfsWorkaroundConfig nfsWorkaround =
+ gerritCluster.getSpec().getStorageClasses().getNfsWorkaround();
+ if (nfsWorkaround.isEnabled() && nfsWorkaround.isChownOnStartup()) {
+ initContainers.add(gerritCluster.createNfsInitContainer());
+ }
+
stsBuilder
.withApiVersion("apps/v1")
.withNewMetadata()
@@ -98,6 +108,7 @@
.withResources(gerrit.getSpec().getResources())
.addAllToVolumeMounts(getVolumeMounts(gerrit, gerritCluster, true))
.endInitContainer()
+ .addAllToInitContainers(initContainers)
.addNewContainer()
.withName("gerrit")
.withImagePullPolicy(gerritCluster.getSpec().getImagePullPolicy())
@@ -110,6 +121,7 @@
.endExec()
.endPreStop()
.endLifecycle()
+ .withEnv(GerritCluster.getPodNameEnvVar())
.withPorts(getContainerPorts(gerrit))
.withResources(gerrit.getSpec().getResources())
.withStartupProbe(gerrit.getSpec().getStartupProbe())
@@ -186,6 +198,12 @@
.build());
}
+ NfsWorkaroundConfig nfsWorkaround =
+ gerritCluster.getSpec().getStorageClasses().getNfsWorkaround();
+ if (nfsWorkaround.isEnabled() && nfsWorkaround.getIdmapdConfig() != null) {
+ volumes.add(gerritCluster.getNfsImapdConfigVolume());
+ }
+
return volumes;
}
@@ -225,6 +243,13 @@
.build());
}
}
+
+ NfsWorkaroundConfig nfsWorkaround =
+ gerritCluster.getSpec().getStorageClasses().getNfsWorkaround();
+ if (nfsWorkaround.isEnabled() && nfsWorkaround.getIdmapdConfig() != null) {
+ volumeMounts.add(gerritCluster.getNfsImapdConfigVolumeMount());
+ }
+
return volumeMounts;
}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gitgc/GitGarbageCollectionCronJob.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gitgc/GitGarbageCollectionCronJob.java
index 4c2e5e4..83e1874 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gitgc/GitGarbageCollectionCronJob.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/gitgc/GitGarbageCollectionCronJob.java
@@ -18,8 +18,6 @@
import com.google.gerrit.k8s.operator.cluster.GerritCluster;
import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.ContainerBuilder;
-import io.fabric8.kubernetes.api.model.EnvVar;
-import io.fabric8.kubernetes.api.model.EnvVarBuilder;
import io.fabric8.kubernetes.api.model.Volume;
import io.fabric8.kubernetes.api.model.VolumeMount;
import io.fabric8.kubernetes.api.model.batch.v1.CronJob;
@@ -65,7 +63,9 @@
List.of(gerritCluster.getGitRepositoriesVolume(), gerritCluster.getLogsVolume());
if (gerritCluster.getSpec().getStorageClasses().getNfsWorkaround().isEnabled()) {
- initContainers.add(createNfsImapdInitContainer(gerritCluster));
+ if (gerritCluster.getSpec().getStorageClasses().getNfsWorkaround().isChownOnStartup()) {
+ initContainers.add(gerritCluster.createNfsInitContainer());
+ }
if (gerritCluster.getSpec().getStorageClasses().getNfsWorkaround().getIdmapdConfig()
!= null) {
volumes.add(gerritCluster.getNfsImapdConfigVolume());
@@ -123,37 +123,6 @@
.build();
}
- private Container createNfsImapdInitContainer(GerritCluster gerritCluster) {
- List<VolumeMount> volumeMounts = List.of(gerritCluster.getLogsVolumeMount());
-
- if (gerritCluster.getSpec().getStorageClasses().getNfsWorkaround().isEnabled()
- && gerritCluster.getSpec().getStorageClasses().getNfsWorkaround().getIdmapdConfig()
- != null) {
- volumeMounts.add(gerritCluster.getNfsImapdConfigVolumeMount());
- }
-
- return new ContainerBuilder()
- .withName("nfs-init")
- .withImagePullPolicy(gerritCluster.getSpec().getImagePullPolicy())
- .withImage(gerritCluster.getSpec().getBusyBox().getBusyBoxImage())
- .withCommand(List.of("sh", "-c"))
- .withArgs("chown -R 1000:100 /var/mnt/logs")
- .withEnv(getPodNameEnvVar())
- .withVolumeMounts(volumeMounts)
- .build();
- }
-
- private static EnvVar getPodNameEnvVar() {
- return new EnvVarBuilder()
- .withName("POD_NAME")
- .withNewValueFrom()
- .withNewFieldRef()
- .withFieldPath("metadata.name")
- .endFieldRef()
- .endValueFrom()
- .build();
- }
-
private Container buildGitGcContainer(GitGarbageCollection gitGc, GerritCluster gerritCluster) {
List<VolumeMount> volumeMounts =
List.of(
@@ -172,7 +141,7 @@
.withImagePullPolicy(gerritCluster.getSpec().getImagePullPolicy())
.withImage(gerritCluster.getSpec().getGerritImages().getFullImageName("git-gc"))
.withResources(gitGc.getSpec().getResources())
- .withEnv(getPodNameEnvVar())
+ .withEnv(GerritCluster.getPodNameEnvVar())
.withVolumeMounts(volumeMounts);
ArrayList<String> args = new ArrayList<>();