istio

Форк
0
/
autoserviceexportcontroller.go 
169 строк · 5.7 Кб
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
	"context"
19

20
	v1 "k8s.io/api/core/v1"
21
	"k8s.io/apimachinery/pkg/api/errors"
22
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
24
	"k8s.io/apimachinery/pkg/runtime"
25
	"k8s.io/apimachinery/pkg/types"
26
	mcsapi "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
27

28
	"istio.io/istio/pilot/pkg/model"
29
	serviceRegistryKube "istio.io/istio/pilot/pkg/serviceregistry/kube"
30
	"istio.io/istio/pkg/cluster"
31
	"istio.io/istio/pkg/config/schema/gvk"
32
	"istio.io/istio/pkg/kube"
33
	"istio.io/istio/pkg/kube/controllers"
34
	"istio.io/istio/pkg/kube/kclient"
35
	"istio.io/istio/pkg/kube/kubetypes"
36
	"istio.io/istio/pkg/kube/mcs"
37
)
38

39
type autoServiceExportController struct {
40
	autoServiceExportOptions
41

42
	client   kube.Client
43
	queue    controllers.Queue
44
	services kclient.Client[*v1.Service]
45

46
	// We use this flag to short-circuit the logic and stop the controller
47
	// if the CRD does not exist (or is deleted)
48
	mcsSupported bool
49
}
50

51
// autoServiceExportOptions provide options for creating a autoServiceExportController.
52
type autoServiceExportOptions struct {
53
	Client       kube.Client
54
	ClusterID    cluster.ID
55
	DomainSuffix string
56
	ClusterLocal model.ClusterLocalProvider
57
}
58

59
// newAutoServiceExportController creates a new autoServiceExportController.
60
func newAutoServiceExportController(opts autoServiceExportOptions) *autoServiceExportController {
61
	c := &autoServiceExportController{
62
		autoServiceExportOptions: opts,
63
		client:                   opts.Client,
64
		mcsSupported:             true,
65
	}
66
	c.queue = controllers.NewQueue("auto export",
67
		controllers.WithReconciler(c.Reconcile),
68
		controllers.WithMaxAttempts(5))
69

70
	c.services = kclient.NewFiltered[*v1.Service](opts.Client, kubetypes.Filter{ObjectFilter: opts.Client.ObjectFilter()})
71

72
	// Only handle add. The controller only acts on parts of the service
73
	// that are immutable (e.g. name). When we create ServiceExport, we bind its
74
	// lifecycle to the Service so that when the Service is deleted,
75
	// k8s automatically deletes the ServiceExport.
76
	c.services.AddEventHandler(controllers.EventHandler[controllers.Object]{AddFunc: c.queue.AddObject})
77

78
	return c
79
}
80

81
func (c *autoServiceExportController) Run(stopCh <-chan struct{}) {
82
	kube.WaitForCacheSync("auto service export", stopCh, c.services.HasSynced)
83
	c.queue.Run(stopCh)
84
	c.services.ShutdownHandlers()
85
}
86

87
func (c *autoServiceExportController) logPrefix() string {
88
	return "AutoServiceExport (cluster=" + c.ClusterID.String() + ") "
89
}
90

91
// func (c *autoServiceExportController) createServiceExportIfNotPresent(svc *v1.Service) error {
92
func (c *autoServiceExportController) Reconcile(key types.NamespacedName) error {
93
	if !c.mcsSupported {
94
		// Don't create ServiceExport if MCS is not supported on the cluster.
95
		log.Debugf("%s ignoring added Service, since !mcsSupported", c.logPrefix())
96
		return nil
97
	}
98

99
	svc := c.services.Get(key.Name, key.Namespace)
100
	if svc == nil {
101
		// Service no longer exists, no action needed
102
		return nil
103
	}
104

105
	if c.isClusterLocalService(svc) {
106
		// Don't create ServiceExport if the service is configured to be
107
		// local to the cluster (i.e. non-exported).
108
		log.Debugf("%s ignoring cluster-local service %s/%s", c.logPrefix(), svc.Namespace, svc.Name)
109
		return nil
110
	}
111
	serviceExport := mcsapi.ServiceExport{
112
		TypeMeta: metav1.TypeMeta{
113
			Kind:       "ServiceExport",
114
			APIVersion: mcs.MCSSchemeGroupVersion.String(),
115
		},
116
		ObjectMeta: metav1.ObjectMeta{
117
			Namespace: svc.Namespace,
118
			Name:      svc.Name,
119

120
			// Bind the lifecycle of the ServiceExport to the Service. We do this by making the Service
121
			// the "owner" of the ServiceExport resource.
122
			OwnerReferences: []metav1.OwnerReference{
123
				{
124
					APIVersion: v1.SchemeGroupVersion.String(),
125
					Kind:       gvk.Service.Kind,
126
					Name:       svc.Name,
127
					UID:        svc.UID,
128
				},
129
			},
130
		},
131
	}
132

133
	// Convert to unstructured.
134
	u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&serviceExport)
135
	if err != nil {
136
		log.Warnf("%s failed converting ServiceExport %s/%s to Unstructured: %v", c.logPrefix(),
137
			svc.Namespace, svc.Name, err)
138
		return err
139
	}
140

141
	if _, err = c.client.Dynamic().Resource(mcs.ServiceExportGVR).Namespace(serviceExport.Namespace).Create(
142
		context.TODO(), &unstructured.Unstructured{Object: u}, metav1.CreateOptions{}); err != nil {
143
		switch {
144
		case errors.IsAlreadyExists(err):
145
			// The ServiceExport already exists. Nothing to do.
146
			return nil
147
		case errors.IsNotFound(err):
148
			log.Warnf("%s ServiceExport CRD Not found. Shutting down MCS ServiceExport sync. "+
149
				"Please add the CRD then restart the istiod deployment", c.logPrefix())
150
			c.mcsSupported = false
151

152
			// Do not return the error, so that the queue does not attempt a retry.
153
			return nil
154
		}
155
	}
156

157
	if err != nil {
158
		log.Warnf("%s failed creating ServiceExport %s/%s: %v", c.logPrefix(), svc.Namespace, svc.Name, err)
159
		return err
160
	}
161

162
	log.Debugf("%s created ServiceExport %s/%s", c.logPrefix(), svc.Namespace, svc.Name)
163
	return nil
164
}
165

166
func (c *autoServiceExportController) isClusterLocalService(svc *v1.Service) bool {
167
	hostname := serviceRegistryKube.ServiceHostname(svc.Name, svc.Namespace, c.DomainSuffix)
168
	return c.ClusterLocal.GetClusterLocalHosts().IsClusterLocal(hostname)
169
}
170

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

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

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

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