diff --git a/Makefile b/Makefile index 7545ebffed..b973ecf02d 100644 --- a/Makefile +++ b/Makefile @@ -181,6 +181,11 @@ webhook-server:pre cp -R ${BCS_CONF_COMPONENT_PATH}/bcs-webhook-server ${PACKAGEPATH}/bcs-runtime/bcs-k8s/bcs-component cd ${BCS_COMPONENT_PATH}/bcs-webhook-server && go mod tidy && go build ${LDFLAG} -o ${WORKSPACE}/${PACKAGEPATH}/bcs-runtime/bcs-k8s/bcs-component/bcs-webhook-server/bcs-webhook-server ./cmd/server.go +istio-policy:pre + mkdir -p ${PACKAGEPATH}/bcs-runtime/bcs-k8s/bcs-component + cp -R ${BCS_CONF_COMPONENT_PATH}/istio-policy-controller ${PACKAGEPATH}/bcs-runtime/bcs-k8s/bcs-component + cd ${BCS_COMPONENT_PATH}/istio-policy-controller && go mod tidy && go build ${LDFLAG} -o ${WORKSPACE}/${PACKAGEPATH}/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/istio-policy-controller main.go + tools:pre tongsuo mkdir -p ${PACKAGEPATH}/bcs-services cd ${BCS_INSTALL_PATH}/cryptool && go mod tidy && $(CGO_BUILD_FLAGS) go build ${LDFLAG} -o ${WORKSPACE}/${PACKAGEPATH}/bcs-services/cryptools main.go diff --git a/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/controllers/service_controller.go b/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/controllers/service_controller.go new file mode 100644 index 0000000000..f17825cb9f --- /dev/null +++ b/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/controllers/service_controller.go @@ -0,0 +1,354 @@ +/* + * Tencent is pleased to support the open source community by making Blueking Container Service available. + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +// package controllers contains the reconcile logic for the istio-policy-controller. +package controllers + +import ( + "context" + "errors" + "fmt" + + "github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/internal/metric" + "github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/internal/option" + "github.com/go-logr/logr" + "istio.io/api/networking/v1alpha3" + networkingv1 "istio.io/client-go/pkg/apis/networking/v1" + "istio.io/client-go/pkg/clientset/versioned" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + k8scorev1 "k8s.io/api/core/v1" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// ServiceReconciler reconciler for k8s svc +type ServiceReconciler struct { + // Client client for reconciler + client.Client + IstioClient *versioned.Clientset + Log logr.Logger + // Option option for controller + Option *option.ControllerOption +} + +// SetupWithManager set node reconciler +func (sr *ServiceReconciler) SetupWithManager(mgr ctrl.Manager) error { + err := ctrl.NewControllerManagedBy(mgr). + For(&k8scorev1.Service{}). + WithEventFilter(getServicePredicate()). + Complete(sr) + if err != nil { + return err + } + + return nil +} + +// Reconcile reconcile for k8s svc +func (sr *ServiceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + // 尝试获取 Service 对象 + var svc corev1.Service + if err := sr.Get(ctx, req.NamespacedName, &svc); err != nil { + // 如果 err 是 NotFound,说明是删除事件 + if client.IgnoreNotFound(err) != nil { + sr.Log.Error(err, "unable to fetch Service") + return ctrl.Result{}, err + } + + sr.Log.Info(fmt.Sprintf("Service deleted, name: %s, namespace: %s", req.Name, req.Namespace)) + err = sr.deletePolicy(ctx, req.Namespace, req.Name) + if err != nil { + return ctrl.Result{}, err + } + + return ctrl.Result{}, nil + } + + sr.Log.Info(fmt.Sprintf("Service created or updated, name: %s, namespace: %s", req.Name, req.Namespace)) + err := sr.createOrUpdatePolicy(ctx, req.Namespace, req.Name) + if err != nil { + return ctrl.Result{}, err + } + + return ctrl.Result{}, nil +} + +// createOrUpdatePolicy 创建或更新策略 +func (sr *ServiceReconciler) createOrUpdatePolicy(ctx context.Context, namespace, name string) error { + dr, err := sr.IstioClient.NetworkingV1().DestinationRules(namespace).Get(ctx, + name, metav1.GetOptions{}) + if err != nil { + if client.IgnoreNotFound(err) != nil { + sr.Log.Error(err, "failed to get DestinationRule") + return err + } + + metric.PolicyGeneratedTotal.Inc() + sr.Log.Info("Creating DestinationRule", "name", name, "namespace", namespace) + err = sr.createDr(ctx, namespace, name) + if err != nil { + sr.Log.Error(err, "failed to create DestinationRule") + return err + } + + metric.PolicySuccessTotal.Inc() + sr.Log.Info("DestinationRule created successfully") + } else if dr != nil && dr.GetName() != "" { + metric.PolicyConflictTotal.Inc() + sr.Log.Info("Updating DestinationRule", "name", name, "namespace", namespace) + err = sr.updateDr(ctx, dr) + if err != nil { + sr.Log.Error(err, "failed to update DestinationRule") + return err + } + + sr.Log.Info("DestinationRule updated successfully") + } + + _, err = sr.IstioClient.NetworkingV1().VirtualServices(namespace).Get(ctx, + name, metav1.GetOptions{}) + if err != nil { + if client.IgnoreNotFound(err) != nil { + sr.Log.Error(err, "failed to get VirtualServices") + return err + } + + // 创建 VirtualServices + sr.Log.Info("Creating VirtualServices", "name", name, "namespace", namespace) + err = sr.createVs(ctx, namespace, name) + if err != nil { + sr.Log.Error(err, "failed to create VirtualServices") + return err + } + + sr.Log.Info("VirtualServices created successfully") + } + + return nil +} + +// createDr 创建 DestinationRule +func (sr *ServiceReconciler) createDr(ctx context.Context, namespace, name string) error { + dr := &networkingv1.DestinationRule{ + TypeMeta: metav1.TypeMeta{ + Kind: "DestinationRule", + APIVersion: "networking.istio.io/v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + Labels: setLabel(namespace, name, nil), + }, + Spec: v1alpha3.DestinationRule{ + Host: sprintfHost(name, namespace), + }, + } + + for _, svc := range sr.Option.Cfg.Services { + if svc.Name == name && svc.Namespace == namespace { + if svc.TrafficPolicy == nil { + return errors.New("no traffic policy found in service config") + } + + dr.Spec.TrafficPolicy = svc.TrafficPolicy + overrideDrPolicy(dr) + _, err := sr.IstioClient.NetworkingV1().DestinationRules(namespace). + Create(ctx, dr, metav1.CreateOptions{}) + + return err + } + } + + if sr.Option.Cfg.Global.TrafficPolicy == nil { + return errors.New("no traffic policy found in global config") + } + + dr.Spec.TrafficPolicy = sr.Option.Cfg.Global.TrafficPolicy + overrideDrPolicy(dr) + _, err := sr.IstioClient.NetworkingV1().DestinationRules(namespace). + Create(ctx, dr, metav1.CreateOptions{}) + + return err +} + +// createVs 创建 VirtualService +func (sr *ServiceReconciler) createVs(ctx context.Context, namespace, name string) error { + vs := &networkingv1.VirtualService{ + TypeMeta: metav1.TypeMeta{ + Kind: "VirtualService", + APIVersion: "networking.istio.io/v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + Labels: setLabel(namespace, name, nil), + }, + Spec: v1alpha3.VirtualService{ + Hosts: []string{sprintfHost(name, namespace)}, + Http: []*v1alpha3.HTTPRoute{ + { + Route: []*v1alpha3.HTTPRouteDestination{ + { + Destination: &v1alpha3.Destination{ + Host: sprintfHost(name, namespace), + }, + }, + }, + }, + }, + }, + } + + for _, svc := range sr.Option.Cfg.Services { + if svc.Name == name && svc.Namespace == namespace { + if svc.Setting.AutoGenerateVS { + _, err := sr.IstioClient.NetworkingV1().VirtualServices(namespace). + Create(ctx, vs, metav1.CreateOptions{}) + if err != nil { + return err + } + } + + return nil + } + } + + if sr.Option.Cfg.Global.Setting.AutoGenerateVS { + _, err := sr.IstioClient.NetworkingV1().VirtualServices(namespace). + Create(ctx, vs, metav1.CreateOptions{}) + if err != nil { + return err + } + } + + return nil +} + +// updateDr 更新 DestinationRule +func (sr *ServiceReconciler) updateDr(ctx context.Context, dr *networkingv1.DestinationRule) error { + label := setLabel(dr.GetNamespace(), dr.GetName(), dr.GetLabels()) + + for _, svc := range sr.Option.Cfg.Services { + if svc.Name == dr.GetName() && svc.Namespace == dr.GetNamespace() { + if v, ok := dr.GetLabels()[LabelKeyManagedBy]; (ok && v == ControllerName) || + svc.Setting.UpdateUnmanagedResources { + if svc.TrafficPolicy == nil { + return errors.New("no traffic policy found in service config") + } + + if svc.Setting.MergeMode == MergeModeMerge { + mergeDrPolicy(dr, svc.TrafficPolicy) + } else { + dr.Spec.TrafficPolicy = svc.TrafficPolicy + overrideDrPolicy(dr) + } + dr.SetLabels(label) + + _, err := sr.IstioClient.NetworkingV1().DestinationRules(dr.GetNamespace()). + Update(ctx, dr, metav1.UpdateOptions{}) + + return err + } + + return nil + } + } + + if v, ok := dr.GetLabels()[LabelKeyManagedBy]; (ok && v == ControllerName) || + sr.Option.Cfg.Global.Setting.UpdateUnmanagedResources { + if sr.Option.Cfg.Global.TrafficPolicy == nil { + return errors.New("no traffic policy found in global config") + } + + if sr.Option.Cfg.Global.Setting.MergeMode == MergeModeMerge { + mergeDrPolicy(dr, sr.Option.Cfg.Global.TrafficPolicy) + } else { + dr.Spec.TrafficPolicy = sr.Option.Cfg.Global.TrafficPolicy + overrideDrPolicy(dr) + } + dr.SetLabels(label) + + _, err := sr.IstioClient.NetworkingV1().DestinationRules(dr.GetNamespace()). + Update(ctx, dr, metav1.UpdateOptions{}) + + return err + } + + return nil +} + +// deletePolicy 删除策略 +func (sr *ServiceReconciler) deletePolicy(ctx context.Context, namespace, name string) error { + dr, err := sr.IstioClient.NetworkingV1().DestinationRules(namespace).Get(ctx, name, metav1.GetOptions{}) + if err != nil { + if client.IgnoreNotFound(err) != nil { + sr.Log.Error(err, "failed to get DestinationRule") + } + } + + vs, err := sr.IstioClient.NetworkingV1().VirtualServices(namespace).Get(ctx, name, metav1.GetOptions{}) + if err != nil { + if client.IgnoreNotFound(err) != nil { + sr.Log.Error(err, "failed to get VirtualService") + } + } + + for _, svc := range sr.Option.Cfg.Services { + if svc.Name == name && svc.Namespace == namespace { + if svc.Setting.DeletePolicyOnServiceDelete { + return sr.deleteDrAndVs(ctx, dr, vs) + } + + return nil + } + } + + if sr.Option.Cfg.Global.Setting.DeletePolicyOnServiceDelete { + return sr.deleteDrAndVs(ctx, dr, vs) + } + + return nil +} + +// deleteDrAndVs 删除 DestinationRule 和 VirtualService +func (sr *ServiceReconciler) deleteDrAndVs(ctx context.Context, dr *networkingv1.DestinationRule, + vs *networkingv1.VirtualService) error { + + var drErr, vsErr error + if dr != nil { + if v, ok := dr.GetLabels()[LabelKeyManagedBy]; ok && v == ControllerName { + drErr = sr.IstioClient.NetworkingV1().DestinationRules(dr.Namespace).Delete(ctx, + dr.Name, metav1.DeleteOptions{}) + if drErr != nil { + sr.Log.Error(drErr, "failed to delete DestinationRule") + } + + sr.Log.Info("DestinationRule deleted successfully") + } + } + + if vs != nil { + if v, ok := vs.GetLabels()[LabelKeyManagedBy]; ok && v == ControllerName { + vsErr = sr.IstioClient.NetworkingV1().VirtualServices(vs.Namespace).Delete(ctx, + vs.Name, metav1.DeleteOptions{}) + if vsErr != nil { + sr.Log.Error(vsErr, "failed to delete VirtualService") + return vsErr + } + + sr.Log.Info("VirtualService deleted successfully") + } + } + + return errors.Join(drErr, vsErr) +} diff --git a/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/controllers/util.go b/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/controllers/util.go new file mode 100644 index 0000000000..e22c42d450 --- /dev/null +++ b/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/controllers/util.go @@ -0,0 +1,283 @@ +/* + * Tencent is pleased to support the open source community by making Blueking Container Service available. + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +// package controllers contains the reconcile logic for the istio-policy-controller. +package controllers + +import ( + "fmt" + "reflect" + + "istio.io/api/networking/v1alpha3" + v1 "istio.io/client-go/pkg/apis/networking/v1" + k8scorev1 "k8s.io/api/core/v1" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/event" + "sigs.k8s.io/controller-runtime/pkg/predicate" +) + +const ( + // ControllerName controller name + ControllerName = "istio-policy-controller" + + // LabelKeyManagedBy label key for istio-policy-controller + LabelKeyManagedBy = "managed-by" + // LabelKeyServiceNamespace label key for service namespace + LabelKeyServiceNamespace = "service-namespace" + // LabelKeyServiceName label key for service name + LabelKeyServiceName = "service-name" + + // MergeModeMerge merge mode merge + MergeModeMerge = "merge" + // MergeModeOverride merge mode override + MergeModeOverride = "override" +) + +// sprintfHost 格式化 host 字符串 +func sprintfHost(name, namespace string) string { + return fmt.Sprintf("%s.%s.svc.cluster.local", name, namespace) +} + +// getServicePredicate 获取 Service 事件的 Predicate +func getServicePredicate() predicate.Predicate { + return predicate.Funcs{ + CreateFunc: func(e event.CreateEvent) bool { + svc, ok := e.Object.(*k8scorev1.Service) + if !ok { + return false + } + ctrl.Log.WithName("event").Info(fmt.Sprintf("Create service, name: %s, namespace: %s", + svc.GetName(), svc.GetNamespace())) + return true + }, + UpdateFunc: func(e event.UpdateEvent) bool { + newSvc, newOk := e.ObjectNew.(*k8scorev1.Service) + oldSvc, oldOk := e.ObjectOld.(*k8scorev1.Service) + if !newOk || !oldOk { + return false + } + if newSvc.DeletionTimestamp != nil { + return true + } + + ctrl.Log.WithName("event").Info(fmt.Sprintf( + "Update new service, new service name: %s, old service name: %s, namespace: %s", + newSvc.GetName(), oldSvc.GetName(), newSvc.GetNamespace())) + return true + }, + DeleteFunc: func(e event.DeleteEvent) bool { + svc, ok := e.Object.(*k8scorev1.Service) + if !ok { + return false + } + + ctrl.Log.WithName("event").Info(fmt.Sprintf("Delete service, name: %s, namespace: %s", + svc.GetName(), svc.GetNamespace())) + return true + }, + } +} + +// overrideDrPolicy override destination policy +func overrideDrPolicy(dr *v1.DestinationRule) { + if isEmptyStruct(dr.Spec.TrafficPolicy.LoadBalancer) { + dr.Spec.TrafficPolicy.LoadBalancer = nil + } + if isEmptyStruct(dr.Spec.TrafficPolicy.ConnectionPool) { + dr.Spec.TrafficPolicy.ConnectionPool = nil + } + if isEmptyStruct(dr.Spec.TrafficPolicy.OutlierDetection) { + dr.Spec.TrafficPolicy.OutlierDetection = nil + } + if isEmptyStruct(dr.Spec.TrafficPolicy.Tls) { + dr.Spec.TrafficPolicy.Tls = nil + } + if len(dr.Spec.TrafficPolicy.PortLevelSettings) == 0 { + dr.Spec.TrafficPolicy.PortLevelSettings = nil + } + if isEmptyStruct(dr.Spec.TrafficPolicy.Tunnel) { + dr.Spec.TrafficPolicy.Tunnel = nil + } + if isEmptyStruct(dr.Spec.TrafficPolicy.ProxyProtocol) { + dr.Spec.TrafficPolicy.ProxyProtocol = nil + } + if isEmptyStruct(dr.Spec.TrafficPolicy.RetryBudget) { + dr.Spec.TrafficPolicy.RetryBudget = nil + } +} + +// mergeDrPolicy merge destination policy +func mergeDrPolicy(dr *v1.DestinationRule, tp *v1alpha3.TrafficPolicy) { + if tp == nil { + return + } + + if dr.Spec.TrafficPolicy == nil { + dr.Spec.TrafficPolicy = &v1alpha3.TrafficPolicy{} + } + + if tp.LoadBalancer != nil { + if isEmptyStruct(tp.LoadBalancer) { + dr.Spec.TrafficPolicy.LoadBalancer = nil + } else { + dr.Spec.TrafficPolicy.LoadBalancer = tp.LoadBalancer + } + } + if tp.ConnectionPool != nil { + if isEmptyStruct(tp.ConnectionPool) { + dr.Spec.TrafficPolicy.ConnectionPool = nil + } else { + dr.Spec.TrafficPolicy.ConnectionPool = tp.ConnectionPool + } + } + if tp.OutlierDetection != nil { + if isEmptyStruct(tp.OutlierDetection) { + dr.Spec.TrafficPolicy.OutlierDetection = nil + } else { + dr.Spec.TrafficPolicy.OutlierDetection = tp.OutlierDetection + } + } + if tp.Tls != nil { + if isEmptyStruct(tp.Tls) { + dr.Spec.TrafficPolicy.Tls = nil + } else { + dr.Spec.TrafficPolicy.Tls = tp.Tls + } + } + if tp.PortLevelSettings != nil { + if len(tp.PortLevelSettings) == 0 { + dr.Spec.TrafficPolicy.PortLevelSettings = nil + } else { + dr.Spec.TrafficPolicy.PortLevelSettings = tp.PortLevelSettings + } + } + if tp.Tunnel != nil { + if isEmptyStruct(tp.Tunnel) { + dr.Spec.TrafficPolicy.Tunnel = nil + } else { + dr.Spec.TrafficPolicy.Tunnel = tp.Tunnel + } + } + if tp.ProxyProtocol != nil { + if isEmptyStruct(tp.ProxyProtocol) { + dr.Spec.TrafficPolicy.ProxyProtocol = nil + } else { + dr.Spec.TrafficPolicy.ProxyProtocol = tp.ProxyProtocol + } + } + if tp.RetryBudget != nil { + if isEmptyStruct(tp.RetryBudget) { + dr.Spec.TrafficPolicy.RetryBudget = nil + } else { + dr.Spec.TrafficPolicy.RetryBudget = tp.RetryBudget + } + } +} + +// setLabel 设置 label +func setLabel(namespace, name string, labels map[string]string) map[string]string { + newLabels := make(map[string]string) + for k, v := range labels { + newLabels[k] = v + } + + newLabels[LabelKeyManagedBy] = ControllerName + newLabels[LabelKeyServiceNamespace] = namespace + newLabels[LabelKeyServiceName] = name + + return newLabels +} + +// isEmptyStruct 判断任意结构体是否逻辑上为零(注意: 不能用于非结构体类型,如 chan、func、interface、array、map等) +func isEmptyStruct(v interface{}) bool { + if v == nil { + return true + } + + rv := reflect.ValueOf(v) + rt := reflect.TypeOf(v) + + // 解引用指针(支持多层) + for rv.Kind() == reflect.Ptr { + if rv.IsNil() { + return true + } + rv = rv.Elem() + rt = rt.Elem() + } + + if rv.Kind() != reflect.Struct { + panic("isEmptyStruct only accepts struct or pointer to struct") + } + + return isLogicallyZero(rv, rt) +} + +// isLogicallyZero 递归判断任意 reflect.Value 是否逻辑上为零 +func isLogicallyZero(val reflect.Value, typ reflect.Type) bool { + switch val.Kind() { + case reflect.Bool: + return !val.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return val.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return val.Uint() == 0 + case reflect.Float32, reflect.Float64: + return val.Float() == 0 + case reflect.Complex64, reflect.Complex128: + return val.Complex() == 0 + case reflect.String: + return val.String() == "" + case reflect.Ptr: + if val.IsNil() { + return true + } + return isLogicallyZero(val.Elem(), typ.Elem()) + case reflect.Slice, reflect.Map: + return val.IsNil() // 若想认为空 slice/map 为零,改为 val.Len() == 0 + case reflect.Array: + elemType := typ.Elem() + for i := 0; i < val.Len(); i++ { + if !isLogicallyZero(val.Index(i), elemType) { + return false + } + } + return true + case reflect.Struct: + // 遍历所有字段,跳过未导出的 + for i := 0; i < val.NumField(); i++ { + fieldVal := val.Field(i) + fieldType := typ.Field(i) + + // 跳过未导出字段:PkgPath 非空表示未导出 + if fieldType.PkgPath != "" { + continue + } + + if !isLogicallyZero(fieldVal, fieldType.Type) { + return false + } + } + return true + case reflect.Interface: + if val.IsNil() { + return true + } + // 获取接口中实际存储的值 + actualVal := val.Elem() + // 递归判断实际值是否为零,使用其自身的 Type + return isLogicallyZero(actualVal, actualVal.Type()) + case reflect.Chan, reflect.Func, reflect.UnsafePointer: + return val.IsNil() + default: + return false // 未知类型视为非零 + } +} diff --git a/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/go.mod b/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/go.mod new file mode 100644 index 0000000000..8372d9eaba --- /dev/null +++ b/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/go.mod @@ -0,0 +1,121 @@ +module github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller + +go 1.23.0 + +replace ( + bitbucket.org/ww/goautoneg => github.com/adjust/goautoneg v0.0.0-20150426214442-d788f35a0315 + github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/kubernetes/common => github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/kubernetes/common v0.0.0-20220117082205-1fdc9e155811 + github.com/Tencent/bk-bcs/bcs-scenarios/kourse => github.com/TencentBlueKing/bk-bcs/bcs-scenarios/kourse v0.0.0-20230620070606-922d3a7a9517 + github.com/coreos/bbolt v1.3.4 => go.etcd.io/bbolt v1.3.4 + github.com/mholt/caddy => github.com/caddyserver/caddy v0.11.1 + go.etcd.io/bbolt v1.3.4 => github.com/coreos/bbolt v1.3.4 + google.golang.org/grpc => google.golang.org/grpc v1.26.0 + k8s.io/api => k8s.io/api v0.26.15 + k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.20.0 + k8s.io/apimachinery => k8s.io/apimachinery v0.26.15 + k8s.io/apiserver => k8s.io/apiserver v0.20.0 + k8s.io/cli-runtime => k8s.io/cli-runtime v0.20.0 + k8s.io/client-go => k8s.io/client-go v0.26.15 + k8s.io/cloud-provider => k8s.io/cloud-provider v0.20.0 + k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.20.0 + k8s.io/code-generator => k8s.io/code-generator v0.20.0 + k8s.io/component-base => k8s.io/component-base v0.20.0 + k8s.io/component-helpers => k8s.io/component-helpers v0.20.0 + k8s.io/controller-manager => k8s.io/controller-manager v0.20.0 + k8s.io/cri-api => k8s.io/cri-api v0.20.0 + k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.20.0 + k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.20.0 + k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.20.0 + k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20220603121420-31174f50af60 + k8s.io/kube-proxy => k8s.io/kube-proxy v0.20.0 + k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.20.0 + k8s.io/kubectl => k8s.io/kubectl v0.20.0 + k8s.io/kubelet => k8s.io/kubelet v0.20.0 + k8s.io/kubernetes => k8s.io/kubernetes v1.20.0 + k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.20.0 + k8s.io/metrics => k8s.io/metrics v0.20.0 + k8s.io/mount-utils => k8s.io/mount-utils v0.20.0 + k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.20.0 +) + +require ( + github.com/Tencent/bk-bcs/bcs-common v0.0.0-20230707084844-155f32c8f606 + github.com/prometheus/client_golang v1.16.0 + k8s.io/api v0.32.1 + k8s.io/apiextensions-apiserver v0.26.10 // indirect + k8s.io/apimachinery v0.32.1 + k8s.io/client-go v0.32.1 +) + +require github.com/pkg/errors v0.9.1 // indirect + +require ( + k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect +) + +require ( + github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/kubernetes v0.0.0-20260123071131-ef141ea25696 + github.com/go-logr/logr v1.4.2 + istio.io/api v1.28.2-0.20251205082437-fde1452f70bc + istio.io/client-go v1.28.3 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/bitly/go-simplejson v0.5.0 // indirect + github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/imdario/mergo v0.3.13 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.10.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/net v0.43.0 // indirect + golang.org/x/oauth2 v0.23.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/term v0.34.0 // indirect + golang.org/x/text v0.28.0 // indirect + golang.org/x/time v0.7.0 // indirect + google.golang.org/protobuf v1.36.7 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect + sigs.k8s.io/controller-runtime v0.14.7 + sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect + sigs.k8s.io/yaml v1.4.0 +) + +require ( + github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/evanphx/json-patch/v5 v5.6.0 // indirect + github.com/go-logr/zapr v1.2.3 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/google/gnostic v0.5.7-v3refs // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + go.uber.org/atomic v1.10.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.24.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250811230008-5f3141c8851a // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + k8s.io/component-base v0.26.10 // indirect + sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect +) diff --git a/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/internal/metric/metric.go b/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/internal/metric/metric.go new file mode 100644 index 0000000000..2bdc47e9c9 --- /dev/null +++ b/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/internal/metric/metric.go @@ -0,0 +1,57 @@ +/* + * Tencent is pleased to support the open source community by making Blueking Container Service available. + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +// package metric is used to collect metrics for controller +package metric + +import ( + "github.com/prometheus/client_golang/prometheus" + "sigs.k8s.io/controller-runtime/pkg/metrics" +) + +const ( + // ControllerName controller name + ControllerName = "istio_policy_controller" +) + +// declare metrics +var ( + // PolicyGeneratedTotal 策略生成数量 + PolicyGeneratedTotal = prometheus.NewCounter( + prometheus.CounterOpts{ + Subsystem: ControllerName, + Name: "policy_generated_total", + Help: "Total number of policies generated.", + }, + ) + // PolicySuccessTotal 策略下发成功数量 + PolicySuccessTotal = prometheus.NewCounter( + prometheus.CounterOpts{ + Subsystem: ControllerName, + Name: "policy_applied_success_total", + Help: "Total number of policies successfully applied.", + }, + ) + // PolicyConflictTotal 策略冲突数量 + PolicyConflictTotal = prometheus.NewCounter( + prometheus.CounterOpts{ + Subsystem: ControllerName, + Name: "policy_conflict_total", + Help: "Total number of policy conflicts detected.", + }, + ) +) + +func init() { + metrics.Registry.MustRegister(PolicyGeneratedTotal) + metrics.Registry.MustRegister(PolicySuccessTotal) + metrics.Registry.MustRegister(PolicyConflictTotal) +} diff --git a/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/internal/option/option.go b/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/internal/option/option.go new file mode 100644 index 0000000000..ef59f29370 --- /dev/null +++ b/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/internal/option/option.go @@ -0,0 +1,88 @@ +/* + * Tencent is pleased to support the open source community by making Blueking Container Service available. + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +// package option app 配置 +package option + +import ( + "fmt" + "os" + + "github.com/Tencent/bk-bcs/bcs-common/common/conf" + "istio.io/api/networking/v1alpha3" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/yaml" +) + +// Configuration 是整个 YAML 配置的根结构 +type Configuration struct { + Global Global + Services []Service +} + +// Global 对应 global 字段 +type Global struct { + TrafficPolicy *v1alpha3.TrafficPolicy + Setting Setting +} + +// Service 单个服务的配置 +type Service struct { + Name string + Namespace string + TrafficPolicy *v1alpha3.TrafficPolicy + Setting Setting +} + +// Setting 全局设置 +type Setting struct { + MergeMode string // e.g., "merge" + DeletePolicyOnServiceDelete bool + AutoGenerateVS bool + UpdateUnmanagedResources bool +} + +// ControllerOption controller option +type ControllerOption struct { + // Address address for server + Address string + + // MetricPort port for metric server + MetricPort int + + conf.LogConfig + + // ConfigPath config file path + ConfigPath string + // Cfg config object + Cfg *Configuration +} + +// InitCfg init config +func (o *ControllerOption) InitCfg() error { + if o.ConfigPath == "" { + return fmt.Errorf("config file name is empty") + } + + content, err := os.ReadFile(o.ConfigPath) + if err != nil { + return err + } + + ctrl.Log.WithName("config").Info(fmt.Sprintf("loaded config from %s", o.ConfigPath)) + + o.Cfg = &Configuration{} + if err := yaml.Unmarshal(content, o.Cfg); err != nil { + return err + } + + return nil +} diff --git a/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/main.go b/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/main.go new file mode 100644 index 0000000000..2b382fc125 --- /dev/null +++ b/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/main.go @@ -0,0 +1,123 @@ +/* + * Tencent is pleased to support the open source community by making Blueking Container Service available. + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ +// package main is the entry point of the program. +package main + +import ( + "flag" + "os" + "strconv" + + "github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/controllers" + "github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/internal/option" + cloudv1 "github.com/Tencent/bk-bcs/bcs-runtime/bcs-k8s/kubernetes/apis/cloud/v1" + networkingv1 "istio.io/client-go/pkg/apis/networking/v1" + "istio.io/client-go/pkg/clientset/versioned" + + "k8s.io/apimachinery/pkg/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/log/zap" +) + +var ( + scheme = runtime.NewScheme() + setupLog = ctrl.Log.WithName("setup") + + verbosity int +) + +func init() { + _ = clientgoscheme.AddToScheme(scheme) + _ = cloudv1.AddToScheme(scheme) +} + +func main() { + opts := &option.ControllerOption{} + + flag.StringVar(&opts.Address, "address", "127.0.0.1", "address for controller") + flag.IntVar(&opts.MetricPort, "metric_port", 8081, "metric port for controller") + + flag.StringVar(&opts.LogDir, "log_dir", "./logs", "If non-empty, write log files in this directory") + flag.Uint64Var(&opts.LogMaxSize, "log_max_size", 500, "Max size (MB) per log file.") + flag.IntVar(&opts.LogMaxNum, "log_max_num", 10, "Max num of log file.") + flag.BoolVar(&opts.ToStdErr, "logtostderr", false, "log to standard error instead of files") + flag.BoolVar(&opts.AlsoToStdErr, "alsologtostderr", false, "log to standard error as well as files") + + flag.IntVar(&verbosity, "v", 0, "log level for V logs") + flag.StringVar(&opts.StdErrThreshold, "stderrthreshold", "2", "logs at or above this threshold go to stderr") + flag.StringVar(&opts.VModule, "vmodule", "", "comma-separated list of pattern=N settings for file-filtered logging") + flag.StringVar(&opts.TraceLocation, "log_backtrace_at", "", "when logging hits line file:N, emit a stack trace") + + flag.StringVar(&opts.ConfigPath, "config", "./etc/config.yaml", "config file path") + + flag.Parse() + + opts.Verbosity = int32(verbosity) + + ctrl.SetLogger(zap.New(zap.UseDevMode(true))) + + setupLog.Info("starting init config") + // 初始化配置 + err := opts.InitCfg() + if err != nil { + setupLog.Error(err, "unable to init config") + os.Exit(1) + } + + cfg, err := ctrl.GetConfig() + if err != nil { + setupLog.Error(err, "unable to get kubeconfig") + os.Exit(1) + } + + // 创建 Istio client + istioClient, err := versioned.NewForConfig(cfg) + if err != nil { + setupLog.Error(err, "unable to create Istio client") + os.Exit(1) + } + + mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ + Scheme: scheme, + MetricsBindAddress: opts.Address + ":" + strconv.Itoa(opts.MetricPort), + LeaderElection: true, + LeaderElectionID: "i8a4x2f5.istio-conroller.bkbcs.tencent.com", + }) + if err != nil { + setupLog.Error(err, "unable to start manager") + os.Exit(1) // nolint + } + + // 注册 Istio networking v1 类型 + if err = networkingv1.AddToScheme(mgr.GetScheme()); err != nil { + setupLog.Error(err, "unable to add Istio networking v1 to scheme") + os.Exit(1) + } + + if err = (&controllers.ServiceReconciler{ + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("service"), + Option: opts, + IstioClient: istioClient, + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create k8s Service controller", "controller", "Service") + os.Exit(1) + } + + setupLog.Info("starting manager") + if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { + setupLog.Error(err, "problem running manager") + os.Exit(1) + } +} diff --git a/install/conf/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/Dockerfile b/install/conf/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/Dockerfile new file mode 100644 index 0000000000..035cc95899 --- /dev/null +++ b/install/conf/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/Dockerfile @@ -0,0 +1,14 @@ +FROM tencentos/tencentos4-minimal + +#for command envsubst +RUN yum install -y gettext + +RUN mkdir -p /data/bcs/logs/bcs /data/bcs/cert +RUN mkdir -p /data/bcs/istio-policy-controller + +ADD istio-policy-controller /data/bcs/istio-policy-controller/ +ADD container-start.sh /data/bcs/istio-policy-controller/ +RUN chmod +x /data/bcs/istio-policy-controller/container-start.sh + +WORKDIR /data/bcs/istio-policy-controller/ +CMD ["/data/bcs/istio-policy-controller/container-start.sh"] diff --git a/install/conf/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/container-start.sh b/install/conf/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/container-start.sh new file mode 100644 index 0000000000..42e6741c1b --- /dev/null +++ b/install/conf/bcs-runtime/bcs-k8s/bcs-component/istio-policy-controller/container-start.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +module="istio-policy-controller" + +cd /data/bcs/${module} +chmod +x ${module} + +#check configuration render +if [[ $BCS_CONFIG_TYPE == "render" ]]; then + cat ${module}.json.template | envsubst | tee ${module}.json +fi + +#ready to start +exec /data/bcs/${module}/${module} $@ \ No newline at end of file diff --git a/install/helm/istio-policy-controller/.helmignore b/install/helm/istio-policy-controller/.helmignore new file mode 100644 index 0000000000..0e8a0eb36f --- /dev/null +++ b/install/helm/istio-policy-controller/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/install/helm/istio-policy-controller/Chart.yaml b/install/helm/istio-policy-controller/Chart.yaml new file mode 100644 index 0000000000..40cab6cbda --- /dev/null +++ b/install/helm/istio-policy-controller/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: istio-policy-controller +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/install/helm/istio-policy-controller/templates/_helpers.tpl b/install/helm/istio-policy-controller/templates/_helpers.tpl new file mode 100644 index 0000000000..554cc4672c --- /dev/null +++ b/install/helm/istio-policy-controller/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "istio-policy-controller.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "istio-policy-controller.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "istio-policy-controller.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "istio-policy-controller.labels" -}} +helm.sh/chart: {{ include "istio-policy-controller.chart" . }} +{{ include "istio-policy-controller.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "istio-policy-controller.selectorLabels" -}} +app.kubernetes.io/name: {{ include "istio-policy-controller.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "istio-policy-controller.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "istio-policy-controller.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/install/helm/istio-policy-controller/templates/configmap.yaml b/install/helm/istio-policy-controller/templates/configmap.yaml new file mode 100644 index 0000000000..9adf89f643 --- /dev/null +++ b/install/helm/istio-policy-controller/templates/configmap.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio-policy-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "istio-policy-controller.labels" . | nindent 4 }} + annotations: + meta.helm.sh/release-name: {{ .Release.Name }} + meta.helm.sh/release-namespace: {{ .Release.Namespace }} +data: + config.yaml: | + {{- .Values.istioPolicyConfig | nindent 4 }} + diff --git a/install/helm/istio-policy-controller/templates/deployment.yaml b/install/helm/istio-policy-controller/templates/deployment.yaml new file mode 100644 index 0000000000..7538a18ea8 --- /dev/null +++ b/install/helm/istio-policy-controller/templates/deployment.yaml @@ -0,0 +1,41 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "istio-policy-controller.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "istio-policy-controller.labels" . | nindent 4 }} + annotations: + meta.helm.sh/release-name: {{ .Release.Name }} + meta.helm.sh/release-namespace: {{ .Release.Namespace }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "istio-policy-controller.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "istio-policy-controller.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: istio-policy-controller-sa + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + volumeMounts: + - name: istio-policy-config + mountPath: /data/bcs/istio-policy-controller/etc + volumes: + - name: istio-policy-config + configMap: + name: istio-policy-config diff --git a/install/helm/istio-policy-controller/templates/full-access-sa.yaml b/install/helm/istio-policy-controller/templates/full-access-sa.yaml new file mode 100644 index 0000000000..a6f89b4bf9 --- /dev/null +++ b/install/helm/istio-policy-controller/templates/full-access-sa.yaml @@ -0,0 +1,61 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-policy-controller-sa + namespace: {{ .Release.Namespace }} + labels: + {{- include "istio-policy-controller.labels" . | nindent 4 }} + annotations: + meta.helm.sh/release-name: {{ .Release.Name }} + meta.helm.sh/release-namespace: {{ .Release.Namespace }} + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: istio-policy-controller-role + labels: + {{- include "istio-policy-controller.labels" . | nindent 4 }} + annotations: + meta.helm.sh/release-name: {{ .Release.Name }} + meta.helm.sh/release-namespace: {{ .Release.Namespace }} +rules: +- apiGroups: ["networking.istio.io"] + resources: ["serviceentries"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +- apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +- apiGroups: ["*"] + resources: ["events"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +- apiGroups: ["networking.istio.io"] + resources: ["destinationrules"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +- apiGroups: ["networking.istio.io"] + resources: ["virtualservices"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +- apiGroups: [""] + resources: ["services"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-policy-controller-rolebinding + namespace: {{ .Release.Namespace }} + labels: + {{- include "istio-policy-controller.labels" . | nindent 4 }} + annotations: + meta.helm.sh/release-name: {{ .Release.Name }} + meta.helm.sh/release-namespace: {{ .Release.Namespace }} +subjects: +- kind: ServiceAccount + name: istio-policy-controller-sa + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: istio-policy-controller-role + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/install/helm/istio-policy-controller/values.yaml b/install/helm/istio-policy-controller/values.yaml new file mode 100644 index 0000000000..2a4442be27 --- /dev/null +++ b/install/helm/istio-policy-controller/values.yaml @@ -0,0 +1,50 @@ +# Default values for istio-policy-controller. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# This will set the replicaset count more information can be found here: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/ +replicaCount: 1 + +# This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/ +image: + repository: + # This sets the pull policy for images. + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "" +# This section is for setting up autoscaling more information can be found here: https://kubernetes.io/docs/concepts/workloads/autoscaling/ +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + + +istioPolicyConfig: | + global: + trafficPolicy: + connectionPool: {} + tunnel: {} + loadBalancer: + simple: RANDOM + localityLbSetting: + enabled: true + failover: + - from: gz + to: nj + setting: + mergeMode: override + deletePolicyOnServiceDelete: true + updateUnmanagedResources: true + autoGenerateVS: true + services: + - name: my-svc + namespace: bcs-system + trafficPolicy: + loadBalancer: + simple: RANDOM + setting: + mergeMode: override + deletePolicyOnServiceDelete: true + updateUnmanagedResources: true \ No newline at end of file