istio

Форк
0
/
namespacecontroller.go 
157 строк · 5.4 Кб
1
// Copyright Istio Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
package controller
16

17
import (
18
	v1 "k8s.io/api/core/v1"
19
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
20
	"k8s.io/apimachinery/pkg/labels"
21
	"k8s.io/apimachinery/pkg/types"
22

23
	"istio.io/istio/pilot/pkg/features"
24
	"istio.io/istio/pilot/pkg/keycertbundle"
25
	"istio.io/istio/pkg/config/constants"
26
	"istio.io/istio/pkg/kube"
27
	"istio.io/istio/pkg/kube/controllers"
28
	"istio.io/istio/pkg/kube/inject"
29
	"istio.io/istio/pkg/kube/kclient"
30
	"istio.io/istio/pkg/util/sets"
31
	"istio.io/istio/security/pkg/k8s"
32
)
33

34
const (
35
	// CACertNamespaceConfigMap is the name of the ConfigMap in each namespace storing the root cert of non-Kube CA.
36
	CACertNamespaceConfigMap = "istio-ca-root-cert"
37

38
	// maxRetries is the number of times a namespace will be retried before it is dropped out of the queue.
39
	// With the current rate-limiter in use (5ms*2^(maxRetries-1)) the following numbers represent the
40
	// sequence of delays between successive queuing of a namespace.
41
	//
42
	// 5ms, 10ms, 20ms, 40ms, 80ms
43
	maxRetries = 5
44
)
45

46
var configMapLabel = map[string]string{"istio.io/config": "true"}
47

48
// NamespaceController manages reconciles a configmap in each namespace with a desired set of data.
49
type NamespaceController struct {
50
	caBundleWatcher *keycertbundle.Watcher
51

52
	queue controllers.Queue
53

54
	namespaces kclient.Client[*v1.Namespace]
55
	configmaps kclient.Client[*v1.ConfigMap]
56

57
	ignoredNamespaces sets.Set[string]
58
}
59

60
// NewNamespaceController returns a pointer to a newly constructed NamespaceController instance.
61
func NewNamespaceController(kubeClient kube.Client, caBundleWatcher *keycertbundle.Watcher) *NamespaceController {
62
	c := &NamespaceController{
63
		caBundleWatcher: caBundleWatcher,
64
	}
65
	c.queue = controllers.NewQueue("namespace controller",
66
		controllers.WithReconciler(c.reconcileCACert),
67
		controllers.WithMaxAttempts(maxRetries))
68

69
	c.configmaps = kclient.NewFiltered[*v1.ConfigMap](kubeClient, kclient.Filter{
70
		FieldSelector: "metadata.name=" + CACertNamespaceConfigMap,
71
		ObjectFilter:  kube.FilterIfEnhancedFilteringEnabled(kubeClient),
72
	})
73
	c.namespaces = kclient.NewFiltered[*v1.Namespace](kubeClient, kclient.Filter{
74
		ObjectFilter: kube.FilterIfEnhancedFilteringEnabled(kubeClient),
75
	})
76
	// kube-system is not skipped to enable deploying ztunnel in that namespace
77
	c.ignoredNamespaces = inject.IgnoredNamespaces.Copy().Delete(constants.KubeSystemNamespace)
78

79
	c.configmaps.AddEventHandler(controllers.FilteredObjectSpecHandler(c.queue.AddObject, func(o controllers.Object) bool {
80
		// skip special kubernetes system namespaces
81
		return !c.ignoredNamespaces.Contains(o.GetNamespace())
82
	}))
83

84
	c.namespaces.AddEventHandler(controllers.FilteredObjectSpecHandler(c.queue.AddObject, func(o controllers.Object) bool {
85
		if features.InformerWatchNamespace != "" && features.InformerWatchNamespace != o.GetName() {
86
			// We are only watching one namespace, and its not this one
87
			return false
88
		}
89
		if c.ignoredNamespaces.Contains(o.GetName()) {
90
			// skip special kubernetes system namespaces
91
			return false
92
		}
93
		return true
94
	}))
95
	return c
96
}
97

98
// Run starts the NamespaceController until a value is sent to stopCh.
99
func (nc *NamespaceController) Run(stopCh <-chan struct{}) {
100
	if !kube.WaitForCacheSync("namespace controller", stopCh, nc.namespaces.HasSynced, nc.configmaps.HasSynced) {
101
		return
102
	}
103

104
	go nc.startCaBundleWatcher(stopCh)
105
	nc.queue.Run(stopCh)
106
	controllers.ShutdownAll(nc.configmaps, nc.namespaces)
107
}
108

109
// startCaBundleWatcher listens for updates to the CA bundle and update cm in each namespace
110
func (nc *NamespaceController) startCaBundleWatcher(stop <-chan struct{}) {
111
	id, watchCh := nc.caBundleWatcher.AddWatcher()
112
	defer nc.caBundleWatcher.RemoveWatcher(id)
113
	for {
114
		select {
115
		case <-watchCh:
116
			for _, ns := range nc.namespaces.List("", labels.Everything()) {
117
				nc.namespaceChange(ns)
118
			}
119
		case <-stop:
120
			return
121
		}
122
	}
123
}
124

125
// reconcileCACert will reconcile the ca root cert configmap for the specified namespace
126
// If the configmap is not found, it will be created.
127
// If the namespace is filtered out by discovery selector, the configmap will be deleted.
128
func (nc *NamespaceController) reconcileCACert(o types.NamespacedName) error {
129
	ns := o.Namespace
130
	if ns == "" {
131
		// For Namespace object, it will not have o.Namespace field set
132
		ns = o.Name
133
	}
134

135
	meta := metav1.ObjectMeta{
136
		Name:      CACertNamespaceConfigMap,
137
		Namespace: ns,
138
		Labels:    configMapLabel,
139
	}
140
	return k8s.InsertDataToConfigMap(nc.configmaps, meta, nc.caBundleWatcher.GetCABundle())
141
}
142

143
// On namespace change, update the config map.
144
// If terminating, this will be skipped
145
func (nc *NamespaceController) namespaceChange(ns *v1.Namespace) {
146
	if ns.Status.Phase != v1.NamespaceTerminating {
147
		nc.syncNamespace(ns.Name)
148
	}
149
}
150

151
func (nc *NamespaceController) syncNamespace(ns string) {
152
	// skip special kubernetes system namespaces
153
	if nc.ignoredNamespaces.Contains(ns) {
154
		return
155
	}
156
	nc.queue.Add(types.NamespacedName{Name: ns})
157
}
158

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.