Skip to content

Commit 71162c0

Browse files
authored
Implement RemoteNodeSet controllers (#181)
1 parent 8877289 commit 71162c0

File tree

36 files changed

+2147
-166
lines changed

36 files changed

+2147
-166
lines changed

.github/workflows/run-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,8 @@ jobs:
164164
kind load docker-image k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.0
165165
166166
# TODO would be cool to parse YDB image from manifests to avoid duplicating information
167-
docker pull cr.yandex/crptqonuodf51kdj7a7d/ydb:22.4.44
168-
kind load docker-image cr.yandex/crptqonuodf51kdj7a7d/ydb:22.4.44
167+
docker pull cr.yandex/crptqonuodf51kdj7a7d/ydb:23.3.17
168+
kind load docker-image cr.yandex/crptqonuodf51kdj7a7d/ydb:23.3.17
169169
- name: run-tests
170170
run: |
171171
go test -v -timeout 1800s -p 1 ./... -args -ginkgo.v

Makefile

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,21 @@ kind-init:
7070
kind create cluster --config e2e/kind-cluster-config.yaml --name kind-ydb-operator; \
7171
docker pull k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.0; \
7272
kind load docker-image k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.0 --name kind-ydb-operator; \
73-
docker pull cr.yandex/crptqonuodf51kdj7a7d/ydb:22.4.44; \
74-
kind load docker-image cr.yandex/crptqonuodf51kdj7a7d/ydb:22.4.44 --name kind-ydb-operator
73+
docker pull cr.yandex/crptqonuodf51kdj7a7d/ydb:23.3.17; \
74+
kind load docker-image cr.yandex/crptqonuodf51kdj7a7d/ydb:23.3.17 --name kind-ydb-operator
7575

7676
kind-load:
7777
docker tag cr.yandex/yc/ydb-operator:latest kind/ydb-operator:current
7878
kind load docker-image kind/ydb-operator:current --name kind-ydb-operator
7979

80+
unit-test: manifests generate fmt vet envtest ## Run unit tests
81+
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test -v -timeout 1800s -p 1 ./internal/controllers/... -ginkgo.vv -coverprofile cover.out
82+
83+
e2e-test: docker-build kind-init kind-load ## Run e2e tests
84+
go test -v -timeout 1800s -p 1 ./e2e/... -args -ginkgo.vv
85+
8086
.PHONY: test
81-
test: manifests generate fmt vet docker-build kind-init kind-load envtest ## Run tests.
82-
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test -timeout 1800s -p 1 ./... -ginkgo.v -coverprofile cover.out
87+
test: unit-test test ## Run all tests
8388

8489
.PHONY: clean
8590
clean:

api/v1alpha1/databasenodeset_types.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,17 @@ type DatabaseNodeSetList struct {
6565
func init() {
6666
SchemeBuilder.Register(&DatabaseNodeSet{}, &DatabaseNodeSetList{})
6767
}
68+
69+
func RecastDatabaseNodeSet(databaseNodeSet *DatabaseNodeSet) *Database {
70+
return &Database{
71+
ObjectMeta: metav1.ObjectMeta{
72+
Name: databaseNodeSet.Spec.DatabaseRef.Name,
73+
Namespace: databaseNodeSet.Spec.DatabaseRef.Namespace,
74+
Labels: databaseNodeSet.Labels,
75+
},
76+
Spec: DatabaseSpec{
77+
DatabaseClusterSpec: databaseNodeSet.Spec.DatabaseClusterSpec,
78+
DatabaseNodeSpec: databaseNodeSet.Spec.DatabaseNodeSpec,
79+
},
80+
}
81+
}

api/v1alpha1/storagenodeset_types.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,17 @@ type StorageNodeSetList struct {
6565
func init() {
6666
SchemeBuilder.Register(&StorageNodeSet{}, &StorageNodeSetList{})
6767
}
68+
69+
func RecastStorageNodeSet(storageNodeSet *StorageNodeSet) *Storage {
70+
return &Storage{
71+
ObjectMeta: metav1.ObjectMeta{
72+
Name: storageNodeSet.Spec.StorageRef.Name,
73+
Namespace: storageNodeSet.Spec.StorageRef.Namespace,
74+
Labels: storageNodeSet.Labels,
75+
},
76+
Spec: StorageSpec{
77+
StorageClusterSpec: storageNodeSet.Spec.StorageClusterSpec,
78+
StorageNodeSpec: storageNodeSet.Spec.StorageNodeSpec,
79+
},
80+
}
81+
}

cmd/ydb-kubernetes-operator/main.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,19 @@ import (
99
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
1010
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
1111
_ "k8s.io/client-go/plugin/pkg/client/auth"
12+
"k8s.io/client-go/tools/clientcmd"
1213
ctrl "sigs.k8s.io/controller-runtime"
14+
"sigs.k8s.io/controller-runtime/pkg/cache"
15+
"sigs.k8s.io/controller-runtime/pkg/cluster"
1316
"sigs.k8s.io/controller-runtime/pkg/healthz"
1417
"sigs.k8s.io/controller-runtime/pkg/log/zap"
1518

1619
ydbv1alpha1 "github.com/ydb-platform/ydb-kubernetes-operator/api/v1alpha1"
1720
"github.com/ydb-platform/ydb-kubernetes-operator/internal/controllers/database"
1821
"github.com/ydb-platform/ydb-kubernetes-operator/internal/controllers/databasenodeset"
1922
"github.com/ydb-platform/ydb-kubernetes-operator/internal/controllers/monitoring"
23+
"github.com/ydb-platform/ydb-kubernetes-operator/internal/controllers/remotedatabasenodeset"
24+
"github.com/ydb-platform/ydb-kubernetes-operator/internal/controllers/remotestoragenodeset"
2025
"github.com/ydb-platform/ydb-kubernetes-operator/internal/controllers/storage"
2126
"github.com/ydb-platform/ydb-kubernetes-operator/internal/controllers/storagenodeset"
2227
)
@@ -39,13 +44,17 @@ func main() {
3944
var disableWebhooks bool
4045
var enableServiceMonitors bool
4146
var probeAddr string
47+
var mgmtClusterKubeconfig string
48+
var mgmtClusterName string
4249
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
4350
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
4451
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
4552
"Enable leader election for controller manager. "+
4653
"Enabling this will ensure there is only one active controller manager.")
4754
flag.BoolVar(&disableWebhooks, "disable-webhooks", false, "Disable webhooks registration on start.")
4855
flag.BoolVar(&enableServiceMonitors, "with-service-monitors", false, "Enables service monitoring")
56+
flag.StringVar(&mgmtClusterKubeconfig, "mgmt-cluster-kubeconfig", "/mgmt-cluster/kubeconfig", "Path to kubeconfig for mgmt remote k8s cluster. Only required if using Remote objects")
57+
flag.StringVar(&mgmtClusterName, "mgmt-cluster-name", "", "The name of mgmt remote cluster to sync k8s resources. Only required if using Remote objects")
4958
opts := zap.Options{
5059
Development: true,
5160
}
@@ -143,6 +152,36 @@ func main() {
143152
os.Exit(1)
144153
}
145154
}
155+
156+
if mgmtClusterName != "" && mgmtClusterKubeconfig != "" {
157+
remoteCluster, err := createRemoteCluster(mgmtClusterName, mgmtClusterKubeconfig)
158+
if err != nil {
159+
setupLog.Error(err, "unable to create mgmt cluster client")
160+
os.Exit(1)
161+
}
162+
163+
if err = mgr.Add(remoteCluster); err != nil {
164+
setupLog.Error(err, "unable to add mgmt cluster client to controller manager")
165+
os.Exit(1)
166+
}
167+
168+
if err = (&remotestoragenodeset.Reconciler{
169+
Client: mgr.GetClient(),
170+
Scheme: mgr.GetScheme(),
171+
}).SetupWithManager(mgr, &remoteCluster); err != nil {
172+
setupLog.Error(err, "unable to create controller", "controller", "RemoteStorageNodeSet")
173+
os.Exit(1)
174+
}
175+
176+
if err = (&remotedatabasenodeset.Reconciler{
177+
Client: mgr.GetClient(),
178+
Scheme: mgr.GetScheme(),
179+
}).SetupWithManager(mgr, &remoteCluster); err != nil {
180+
setupLog.Error(err, "unable to create controller", "controller", "RemoteDatabaseNodeSet")
181+
os.Exit(1)
182+
}
183+
}
184+
146185
//+kubebuilder:scaffold:builder
147186

148187
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
@@ -160,3 +199,33 @@ func main() {
160199
os.Exit(1)
161200
}
162201
}
202+
203+
func createRemoteCluster(mgmtClusterName, mgmtClusterKubeconfig string) (cluster.Cluster, error) {
204+
remoteConfig, err := clientcmd.BuildConfigFromFlags("", mgmtClusterKubeconfig)
205+
if err != nil {
206+
setupLog.Error(err, "unable to read mgmt cluster kubeconfig")
207+
return nil, err
208+
}
209+
210+
storageSelector, err := remotestoragenodeset.BuildRemoteSelector(mgmtClusterName)
211+
if err != nil {
212+
setupLog.Error(err, "unable to create label selector", "selector", "RemoteStorageNodeSet")
213+
return nil, err
214+
}
215+
216+
databaseSelector, err := remotedatabasenodeset.BuildRemoteSelector(mgmtClusterName)
217+
if err != nil {
218+
setupLog.Error(err, "unable to create label selector", "selector", "RemoteDatabaseNodeSet")
219+
return nil, err
220+
}
221+
222+
return cluster.New(remoteConfig, func(o *cluster.Options) {
223+
o.Scheme = scheme
224+
o.NewCache = cache.BuilderWithOptions(cache.Options{
225+
SelectorsByObject: cache.SelectorsByObject{
226+
&ydbv1alpha1.RemoteStorageNodeSet{}: {Label: storageSelector},
227+
&ydbv1alpha1.RemoteDatabaseNodeSet{}: {Label: databaseSelector},
228+
},
229+
})
230+
})
231+
}

deploy/ydb-operator/templates/deployment.yaml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ spec:
3030
{{- if .Values.metrics.enabled }}
3131
- --with-service-monitors=true
3232
{{- end }}
33+
{{- if .Values.mgmtCluster.enabled }}
34+
- --mgmt-cluster-name={{- .Values.mgmtCluster.name }}
35+
- --mgmt-cluster-kubeconfig=/mgmt-cluster/kubeconfig
36+
{{- end }}
3337
command:
3438
- /manager
3539
image: {{ default "cr.yandex/yc/ydb-kubernetes-operator" .Values.image.repository }}:
@@ -60,17 +64,24 @@ spec:
6064
{{- toYaml .Values.resources | nindent 12 }}
6165
securityContext:
6266
allowPrivilegeEscalation: false
67+
{{- if or .Values.webhook.enabled .Values.mgmtCluster.enabled }}
6368
{{- if .Values.webhook.enabled }}
6469
volumeMounts:
6570
- mountPath: /tmp/k8s-webhook-server/serving-certs
6671
name: webhook-tls
6772
{{- end }}
73+
{{- if .Values.mgmtCluster.enabled }}
74+
- mountPath: /mgmt-cluster
75+
name: mgmt-cluster-kubeconfig
76+
{{- end }}
77+
{{- end }}
6878
securityContext:
6979
runAsNonRoot: true
7080
serviceAccountName: {{ include "ydb.fullname" . }}
7181
terminationGracePeriodSeconds: 10
72-
{{- if .Values.webhook.enabled }}
82+
{{- if or .Values.webhook.enabled .Values.mgmtCluster.enabled }}
7383
volumes:
84+
{{- if .Values.webhook.enabled }}
7485
- name: webhook-tls
7586
secret:
7687
secretName: {{ include "ydb.fullname" . }}-webhook
@@ -83,6 +94,12 @@ spec:
8394
- key: key
8495
path: tls.key
8596
{{- end }}
97+
{{- end }}
98+
{{- if .Values.mgmtCluster.enabled }}
99+
- name: mgmt-cluster-kubeconfig
100+
secret:
101+
secretName: {{ .Values.mgmtCluster.kubeconfig }}
102+
{{- end }}
86103
{{- end }}
87104
{{- if .Values.imagePullSecrets }}
88105
{{- with .Values.imagePullSecrets }}

deploy/ydb-operator/values.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ metrics:
4747
##
4848
enabled: false
4949

50+
mgmtCluster:
51+
## Watch resources from mgmtCluster
52+
##
53+
enabled: false
54+
name: ""
55+
## Define existing kubeconfig Secret name in current namespace
56+
kubeconfig: "remote-kubeconfig"
57+
5058
webhook:
5159
enabled: true
5260

docs/tests.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,14 @@ kind create cluster \
8888
kubectl config use-context kind-local-kind
8989

9090
# Within tests, the following two images are used:
91-
# cr.yandex/crptqonuodf51kdj7a7d/ydb:22.4.44
91+
# cr.yandex/crptqonuodf51kdj7a7d/ydb:23.3.17
9292
# kind/ydb-operator:current
9393

9494
# You have to download the ydb image and build the operator image yourself. Then, explicitly
9595
# upload them into the kind cluster. Refer to `./github/e2e.yaml` github workflow which essentially
9696
# does the same thing.
9797
kind --name local-kind load docker-image kind/ydb-operator:current
98-
kind --name local-kind load docker-image ydb:22.4.44
98+
kind --name local-kind load docker-image ydb:23.3.17
9999

100100
# Run all tests with disabled concurrency, because there is only one cluster to run tests against
101101
go test -p 1 -v ./...

e2e/tests/test-objects/objects.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
)
1212

1313
const (
14-
YdbImage = "cr.yandex/crptqonuodf51kdj7a7d/ydb:22.4.44"
14+
YdbImage = "cr.yandex/crptqonuodf51kdj7a7d/ydb:23.3.17"
1515
YdbNamespace = "ydb"
1616
StorageName = "storage"
1717
DatabaseName = "database"

internal/annotations/annotations.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ package annotations
22

33
import "strings"
44

5+
const (
6+
PrimaryResourceStorageAnnotation = "ydb.tech/primary-resource-storage"
7+
PrimaryResourceDatabaseAnnotation = "ydb.tech/primary-resource-database"
8+
RemoteResourceVersionAnnotation = "ydb.tech/remote-resource-version"
9+
RemoteFinalizerKey = "ydb.tech/remote-finalizer"
10+
LastAppliedAnnotation = "ydb.tech/last-applied"
11+
)
12+
513
func GetYdbTechAnnotations(annotations map[string]string) map[string]string {
614
result := make(map[string]string)
715
for key, value := range annotations {

0 commit comments

Comments
 (0)