Skip to content

Commit 4d14a02

Browse files
committed
add GCP deployment configuration for operator and crdb charts
1 parent 1a6687c commit 4d14a02

8 files changed

Lines changed: 142 additions & 25 deletions

File tree

cockroachdb-parent/charts/cockroachdb/templates/crdb.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ spec:
8585
{{- with .Values.cockroachdb.crdbCluster.startFlags }}
8686
startFlags: {{- toYaml . | nindent 8 }}
8787
{{- end }}
88+
serviceAccountName: {{ include "cockroachdb.serviceAccount.name" . }}
89+
resourceRequirements: {}
8890
{{- with .Values.cockroachdb.crdbCluster.podTemplate }}
8991
podTemplate:
9092
metadata:

cockroachdb-parent/charts/cockroachdb/values.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -473,9 +473,9 @@ cockroachdb:
473473
# # imagePullSecrets captures the secrets for fetching images from private registries.
474474
# imagePullSecrets: []
475475
# # initContainers captures the list of init containers for CockroachDB pods.
476-
# initContainers:
477-
# - name : cockroachdb-init
478-
# image: docker.io/cockroachdb/cockroachdb-init-container:v1.0.0-rc.1
476+
initContainers:
477+
- name : cockroachdb-init
478+
image: us-docker.pkg.dev/cockroach-cloud-images/development/init-container@sha256:4c48b147770b41f74bba995e87f5ff2a396b9d9ecd0447cf43c5f67778ba8b40
479479
# containers captures the list of containers for CockroachDB pods.
480480
containers:
481481
- name: cockroachdb

cockroachdb-parent/charts/operator/templates/operator.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ spec:
496496
priorityClassName: {{ if (.Values.watchNamespaces | trim) }}cockroachdb-operator-{{ .Release.Namespace }}{{ else }}cockroachdb-operator{{ end }}
497497
containers:
498498
- name: cockroach-operator
499-
image: {{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}
499+
image: {{ .Values.image.registry }}/{{ .Values.image.repository }}{{ if .Values.image.digest }}@{{ .Values.image.digest }}{{ else }}:{{ .Values.image.tag }}{{ end }}
500500
args:
501501
# Pin metrics port so it can be properly exposed by the "ports"
502502
# field below even in the event of a change to the default value.

cockroachdb-parent/charts/operator/values.yaml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
# image captures the container image settings for Operator pods.
55
image:
66
# registry is the container registry where the image is stored.
7-
registry: "docker.io/cockroachdb"
7+
registry: "us-docker.pkg.dev/cockroach-cloud-images/development"
88
# repository defines the image repository.
9-
repository: "cockroachdb-operator-v2"
9+
repository: "cockroach-operator"
1010
# pullPolicy specifies the image pull policy.
1111
pullPolicy: IfNotPresent
12-
# tag is the image tag.
12+
# tag is the image tag. Ignored when digest is set.
1313
tag: "v1.0.0-rc.1"
14+
# digest pins the image to a specific digest (e.g. sha256:abc123).
15+
# When set, the image is referenced as registry/repository@digest instead of registry/repository:tag.
16+
digest: "sha256:87223f2098cdb52e2075e9919a3da5352a6922d0b0c3fb7b844ce5b6dde6492a"
1417
# relatedImages configures images the operator injects into CockroachDB pods.
1518
# By default these images share the operator image registry and tag.
1619
relatedImages:
@@ -25,9 +28,9 @@ relatedImages:
2528
# registry overrides image.registry for the cert-reloader image when set.
2629
registry: ""
2730
# repository defines the cert-reloader image repository.
28-
repository: "cockroachdb-cert-reloader"
31+
repository: "inotifywait"
2932
# tag overrides image.tag for the cert-reloader image when set.
30-
tag: ""
33+
tag: "release-2025-04-07-0-242-ge7531af7a2"
3134
# certificate defines the certificate settings for the Operator.
3235
certificate:
3336
# validForDays specifies the number of days the certificate is valid for.

tests/e2e/operator/infra/common.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,8 +302,17 @@ func UpdateKubeconfigGCP(t *testing.T, projectID, region, clusterName, alias str
302302
return fmt.Errorf("failed to get GCP credentials for cluster %s: %w", clusterName, err)
303303
}
304304

305-
// Step 2: Rename context
305+
// Step 2: Skip TLS verification to avoid x509 errors from GKE's internal CA.
306306
longContextName := fmt.Sprintf("gke_%s_%s_%s", projectID, region, clusterName)
307+
skipTLSCmd := exec.Command("kubectl", "config", "set-cluster", longContextName,
308+
"--insecure-skip-tls-verify=true")
309+
output, err = skipTLSCmd.CombinedOutput()
310+
if err != nil {
311+
t.Logf("kubectl set-cluster insecure-skip-tls-verify command failed. Output:\n%s\n", string(output))
312+
return fmt.Errorf("failed to set insecure-skip-tls-verify for cluster %s: %w", clusterName, err)
313+
}
314+
315+
// Step 3: Rename context
307316
renameCmd := exec.Command("kubectl", "config", "rename-context", longContextName, alias)
308317
output, err = renameCmd.CombinedOutput()
309318
if err != nil {

tests/e2e/operator/infra/gcp.go

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package infra
33
import (
44
"context"
55
"encoding/base64"
6+
"encoding/json"
67
"errors"
78
"fmt"
89
"net/http"
@@ -15,6 +16,7 @@ import (
1516

1617
"github.com/gruntwork-io/terratest/modules/k8s"
1718
"github.com/gruntwork-io/terratest/modules/random"
19+
"github.com/gruntwork-io/terratest/modules/retry"
1820
"github.com/stretchr/testify/require"
1921
cloudkms "google.golang.org/api/cloudkms/v1"
2022
"google.golang.org/api/compute/v1"
@@ -52,6 +54,12 @@ const (
5254
gcpKMSCryptoKeyID = "cockroachdb-cmek-key"
5355
)
5456

57+
// getNodeServiceAccount returns the GKE node service account from the environment.
58+
// If empty, gcloud falls back to the project's default Compute Engine service account.
59+
func getNodeServiceAccount() string {
60+
return os.Getenv("GCP_NODE_SERVICE_ACCOUNT")
61+
}
62+
5563
// getProjectID returns the GCP project ID from the environment variable or falls back to default.
5664
func getProjectID() string {
5765
if projectID := os.Getenv("GCP_PROJECT_ID"); projectID != "" {
@@ -236,6 +244,72 @@ func (r *GcpRegion) SetUpInfra(t *testing.T) {
236244
require.NoError(t, err)
237245
err = r.deployAndConfigureCoreDNS(t, kubeConfigPath)
238246
require.NoError(t, err, "failed to deploy and configure CoreDNS")
247+
248+
if r.IsMultiRegion {
249+
for _, clusterName := range r.Clusters {
250+
err = patchKubeDNSForCustomDomains(t, clusterName, kubeConfigPath)
251+
require.NoError(t, err, "failed to patch kube-dns for custom domains on cluster %s", clusterName)
252+
}
253+
}
254+
}
255+
256+
// patchKubeDNSForCustomDomains patches the kube-dns ConfigMap with stubDomains for
257+
// custom cluster domains and restarts node-local-dns to pick up the new config.
258+
func patchKubeDNSForCustomDomains(t *testing.T, clusterName, kubeConfigPath string) error {
259+
kubectlOpts := k8s.NewKubectlOptions(clusterName, kubeConfigPath, "kube-system")
260+
261+
clusterIP, err := k8s.RunKubectlAndGetOutputE(t, kubectlOpts,
262+
"get", "service", "kube-dns-upstream", "-o", "jsonpath={.spec.clusterIP}")
263+
if err != nil {
264+
return fmt.Errorf("failed to get kube-dns-upstream ClusterIP on cluster %s: %w", clusterName, err)
265+
}
266+
clusterIP = strings.TrimSpace(clusterIP)
267+
if clusterIP == "" {
268+
return fmt.Errorf("kube-dns-upstream service has no ClusterIP on cluster %s", clusterName)
269+
}
270+
t.Logf("[gcp] kube-dns-upstream ClusterIP on cluster %s: %s", clusterName, clusterIP)
271+
272+
stubDomains := make(map[string][]string)
273+
for _, domain := range operator.CustomDomains {
274+
stubDomains[domain] = []string{clusterIP}
275+
}
276+
stubDomainsJSON, err := json.Marshal(stubDomains)
277+
if err != nil {
278+
return fmt.Errorf("failed to marshal stubDomains: %w", err)
279+
}
280+
281+
type configMapPatch struct {
282+
Data map[string]string `json:"data"`
283+
}
284+
patchJSON, err := json.Marshal(configMapPatch{Data: map[string]string{
285+
"stubDomains": string(stubDomainsJSON),
286+
}})
287+
if err != nil {
288+
return fmt.Errorf("failed to marshal ConfigMap patch: %w", err)
289+
}
290+
291+
if err := k8s.RunKubectlE(t, kubectlOpts, "patch", "configmap", "kube-dns",
292+
"--type=merge", "-p", string(patchJSON)); err != nil {
293+
return fmt.Errorf("failed to patch kube-dns ConfigMap on cluster %s: %w", clusterName, err)
294+
}
295+
t.Logf("[gcp] Patched kube-dns ConfigMap with stubDomains on cluster %s", clusterName)
296+
297+
if err := k8s.RunKubectlE(t, kubectlOpts, "delete", "pods",
298+
"-l", "k8s-app=node-local-dns", "--grace-period=0", "--force"); err != nil {
299+
t.Logf("[gcp] Warning: force-delete of node-local-dns pods failed (may be harmless): %v", err)
300+
}
301+
302+
_, err = retry.DoWithRetryE(t, "wait for node-local-dns rollout", defaultRetries, defaultRetryInterval,
303+
func() (string, error) {
304+
return k8s.RunKubectlAndGetOutputE(t, kubectlOpts,
305+
"rollout", "status", "daemonset/node-local-dns", "--timeout=10s")
306+
})
307+
if err != nil {
308+
return fmt.Errorf("node-local-dns did not become ready after patching on cluster %s: %w", clusterName, err)
309+
}
310+
311+
t.Logf("[gcp] node-local-dns ready with stub domains for custom cluster domains on cluster %s", clusterName)
312+
return nil
239313
}
240314

241315
func (r *GcpRegion) GetEncryptionProvider() encryption.Provider {
@@ -787,16 +861,20 @@ func createGKERegionalCluster(ctx context.Context, client *container.Service, se
787861
"--tags", strings.Join([]string{defaultNodeTag}, ","), // Join tags if there are multiple
788862
"--enable-master-authorized-networks",
789863
"--master-authorized-networks", strings.Join([]string{"0.0.0.0/0"}, ","),
790-
"--num-nodes", fmt.Sprint(defaultNodesPerZone),
864+
"--num-nodes", fmt.Sprint(defaultNodesPerZone+1), // 2 nodes/zone avoids autoscaling during TestClusterScaleUp
791865
"--min-nodes", fmt.Sprint(defaultNodesPerZone),
792-
"--max-nodes", fmt.Sprint(defaultNodesPerZone + 1), // Needed for scaling cluster
866+
"--max-nodes", fmt.Sprint(defaultNodesPerZone + 2), // headroom above initial count
793867
"--enable-autoscaling", // Enable autoscaling
794868
"--autoprovisioning-network-tags", strings.Join([]string{autoprovisioningNodeTag}, ","),
795869
"--machine-type", gcpDefaultMachineType,
796870
"--disk-size", "30GB", // Limit disk size to 30GB
797871
"--quiet", // Suppress interactive prompts
798872
}
799873

874+
if sa := getNodeServiceAccount(); sa != "" {
875+
args = append(args, "--service-account", sa)
876+
}
877+
800878
cmd := exec.Command("gcloud", args...)
801879

802880
// Stream gcloud's stdout/stderr directly for real-time visibility into the long-running creation process.

tests/e2e/operator/region.go

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,13 @@ const (
3232
LabelSelector = "app=cockroachdb"
3333
OperatorLabelSelector = "app=cockroach-operator"
3434
DefaultClusterDomain = "cluster.local"
35-
testOperatorRegistry = "us-docker.pkg.dev/releases-prod/self-hosted"
36-
testOperatorRepo = "cockroachdb-operator"
35+
// testOperatorRegistry = "us-docker.pkg.dev/releases-prod/self-hosted"
36+
// testOperatorRepo = "cockroachdb-operator"
37+
testOperatorRegistry = "us-docker.pkg.dev/cockroach-cloud-images/development"
38+
testOperatorRepo = "cockroach-operator"
3739
testInitContainerRepo = "init-container"
3840
testInotifywaitRepo = "inotifywait"
41+
testInotifywaitTag = "release-2025-04-07-0-242-ge7531af7a2"
3942
)
4043

4144
var (
@@ -170,9 +173,14 @@ func (r *Region) InstallCharts(t *testing.T, cluster string, index int) {
170173
InstallCockroachDBEnterpriseOperator(t, kubectlOptions, r.RegionCodes[index])
171174
}
172175

176+
clusterDomain := DefaultClusterDomain
177+
if r.IsMultiRegion {
178+
clusterDomain = CustomDomains[index]
179+
}
180+
173181
if r.IsCertManager {
174182
crdbOp = PatchHelmValues(map[string]string{
175-
"cockroachdb.clusterDomain": CustomDomains[index],
183+
"cockroachdb.clusterDomain": clusterDomain,
176184
"cockroachdb.tls.enabled": "true",
177185
"cockroachdb.tls.selfSigner.enabled": "false",
178186
"cockroachdb.tls.certManager.enabled": "true",
@@ -181,7 +189,7 @@ func (r *Region) InstallCharts(t *testing.T, cluster string, index int) {
181189
})
182190
} else {
183191
crdbOp = PatchHelmValues(map[string]string{
184-
"cockroachdb.clusterDomain": CustomDomains[index],
192+
"cockroachdb.clusterDomain": clusterDomain,
185193
"cockroachdb.tls.enabled": "true",
186194
"cockroachdb.tls.selfSigner.caProvided": "true",
187195
"cockroachdb.tls.selfSigner.caSecret": customCASecret,
@@ -391,6 +399,8 @@ func (r *Region) ValidateCRDBContainerResources(t *testing.T, kubectlOptions *k8
391399

392400
// CreateCACertificate creates CA cert and key at the same path.
393401
func (r *Region) CreateCACertificate(t *testing.T) error {
402+
r.CleanUpCACertificate(t)
403+
394404
// Create CA secret in all regions.
395405
cmd := shell.Command{
396406
Command: "cockroach",
@@ -521,10 +531,14 @@ func (r *Region) createOperatorRegions(index int, nodes int, customDomains map[i
521531
"nodes": nodes,
522532
"namespace": r.Namespace[r.Clusters[i]],
523533
}
524-
if len(r.Clusters) > i && r.Clusters[i] != "" {
525-
if domain, ok := customDomains[i]; ok {
526-
region["domain"] = domain
534+
if r.IsMultiRegion {
535+
if len(r.Clusters) > i && r.Clusters[i] != "" {
536+
if domain, ok := customDomains[i]; ok {
537+
region["domain"] = domain
538+
}
527539
}
540+
} else {
541+
region["domain"] = DefaultClusterDomain
528542
}
529543
return region
530544
}
@@ -660,6 +674,7 @@ func InstallCockroachDBEnterpriseOperator(t *testing.T, kubectlOptions *k8s.Kube
660674
"relatedImages.initContainer.repository": testInitContainerRepo,
661675
"relatedImages.inotifywait.registry": testOperatorRegistry,
662676
"relatedImages.inotifywait.repository": testInotifywaitRepo,
677+
"relatedImages.inotifywait.tag": testInotifywaitTag,
663678
"cloudRegion": cloudRegion,
664679
"watchNamespaces": kubectlOptions.Namespace,
665680
},
@@ -921,8 +936,12 @@ func (r *Region) BaseRegionConfig(cluster string, index int) map[string]interfac
921936
"nodes": r.NodeCount,
922937
"namespace": r.Namespace[cluster],
923938
}
924-
if domain, ok := CustomDomains[index]; ok {
925-
region["domain"] = domain
939+
if r.IsMultiRegion {
940+
if domain, ok := CustomDomains[index]; ok {
941+
region["domain"] = domain
942+
}
943+
} else {
944+
region["domain"] = DefaultClusterDomain
926945
}
927946
return region
928947
}
@@ -1037,9 +1056,14 @@ func (r *Region) InstallChartsWithAdvancedConfig(t *testing.T, cluster string, i
10371056
}
10381057
}
10391058

1059+
clusterDomain := DefaultClusterDomain
1060+
if r.IsMultiRegion {
1061+
clusterDomain = CustomDomains[index]
1062+
}
1063+
10401064
// Build helm values
10411065
helmValues := PatchHelmValues(map[string]string{
1042-
"cockroachdb.clusterDomain": CustomDomains[index],
1066+
"cockroachdb.clusterDomain": clusterDomain,
10431067
"cockroachdb.tls.selfSigner.caProvided": "true",
10441068
"cockroachdb.tls.selfSigner.caSecret": customCASecret,
10451069
})

tests/testutil/require.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ func RequireClusterToBeReadyEventuallyTimeout(t *testing.T, crdbCluster Cockroac
5757
func(ctx context.Context) (bool, error) {
5858
ss, err := fetchStatefulSet(crdbCluster.K8sClient, crdbCluster.StatefulSetName, crdbCluster.Namespace)
5959
if err != nil {
60-
t.Logf("error fetching stateful set")
61-
return false, err
60+
t.Logf("transient error fetching stateful set, will retry: %v", err)
61+
return false, nil
6262
}
6363

6464
if ss == nil {
@@ -87,7 +87,8 @@ func RequireCRDBClusterToBeReadyEventuallyTimeout(t *testing.T, opts *k8s.Kubect
8787
LabelSelector: "app=cockroachdb",
8888
})
8989
if err != nil {
90-
return false, err
90+
t.Logf("transient error listing pods, will retry: %v", err)
91+
return false, nil
9192
}
9293

9394
if len(pods) != crdbCluster.DesiredNodes {

0 commit comments

Comments
 (0)