diff --git a/Makefile b/Makefile index 630a6ce4..848c0aea 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ ORG = polarismesh REPO = polaris-controller SIDECAR_INIT_REPO = polaris-sidecar-init ENVOY_SIDECAR_INIT_REPO = polaris-envoy-bootstrap-generator -IMAGE_TAG = v1.7.2 +IMAGE_TAG = v1.7.3 PLATFORMS = linux/amd64,linux/arm64 .PHONY: all diff --git a/build.sh b/build.sh index 66ab122e..e09ce1ba 100644 --- a/build.sh +++ b/build.sh @@ -26,7 +26,11 @@ else fi workdir=$(dirname $(realpath $0)) -sed -i "s/##VERSION##/$version/g" "$workdir"/deploy/variables.txt +if [ "$(uname)" == "Darwin" ]; then + sed -i "" "s/##VERSION##/$version/g" "$workdir"/deploy/variables.txt +else + sed -i "s/##VERSION##/$version/g" "$workdir"/deploy/variables.txt +fi cat "$workdir"/deploy/variables.txt function replaceVar() { diff --git a/cmd/polaris-controller/app/config.go b/cmd/polaris-controller/app/config.go index 2dfbd8da..9b618107 100644 --- a/cmd/polaris-controller/app/config.go +++ b/cmd/polaris-controller/app/config.go @@ -21,10 +21,11 @@ import ( "gopkg.in/yaml.v2" "github.com/polarismesh/polaris-controller/cmd/polaris-controller/app/options" + "github.com/polarismesh/polaris-controller/common" "github.com/polarismesh/polaris-controller/common/log" ) -// ServiceSync controller 用到的配置 +// ProxyMetadata mesh envoy用到的配置 type ProxyMetadata struct { ServerAddress string `yaml:"serverAddress"` ClusterName string `yaml:"clusterName"` @@ -32,7 +33,7 @@ type ProxyMetadata struct { CAAddress string `yaml:"caAddress"` } -// DefaultConfig controller 用到的配置 +// DefaultConfig mesh envoy sidecar 用到的配置 type DefaultConfig struct { ProxyMetadata ProxyMetadata `yaml:"proxyMetadata"` } @@ -56,16 +57,66 @@ type Server struct { } type controllerConfig struct { - Logger map[string]*log.Options `yaml:"logger"` - ClusterName string `yaml:"clusterName"` - Server Server `yaml:"server"` - ServiceSync *options.ServiceSync `yaml:"serviceSync"` - ConfigSync *options.ConfigSync `yaml:"configSync"` - SidecarInject SidecarInject `yaml:"sidecarInject"` + // 北极星服务端地址 + ServerAddress string `yaml:"serverAddress"` + // 北极星服务端token(北极星开启鉴权时需要配置) + PolarisAccessToken string `yaml:"accessToken"` + // Operator 北极星主账户ID, 用于数据同步 + Operator string `yaml:"operator"` + // 容器集群名称或ID + ClusterName string `yaml:"clusterName"` + // k8s服务同步配置 + ServiceSync *options.ServiceSync `yaml:"serviceSync"` + // 配置同步配置 + ConfigSync *options.ConfigSync `yaml:"configSync"` + // sidecar注入相关配置 + SidecarInject SidecarInject `yaml:"sidecarInject"` + // mesh envoy 相关配置 + DefaultConfig DefaultConfig `yaml:"defaultConfig"` + // 组件日志配置 + Logger map[string]*log.Options `yaml:"logger"` + // 健康检查和对账配置 + Server Server `yaml:"server"` +} + +func (c *controllerConfig) getPolarisServerAddress() string { + // 新配置格式 + if c.ServerAddress != "" { + return c.ServerAddress + } + // 老的配置格式 + if c.ServiceSync.ServerAddress != "" { + return c.ServiceSync.ServerAddress + } + return common.PolarisServerAddress +} + +func (c *controllerConfig) getPolarisAccessToken() string { + // 新配置格式 + if c.PolarisAccessToken != "" { + return c.PolarisAccessToken + } + // 老的配置格式 + if c.ServiceSync.PolarisAccessToken != "" { + return c.ServiceSync.PolarisAccessToken + } + return "" +} + +func (c *controllerConfig) getPolarisOperator() string { + // 新配置格式 + if c.Operator != "" { + return c.Operator + } + // 老的配置格式 + if c.ServiceSync.Operator != "" { + return c.ServiceSync.Operator + } + return "" } func readConfFromFile() (*controllerConfig, error) { - buf, err := os.ReadFile(MeshFile) + buf, err := os.ReadFile(BootstrapConfigFile) if err != nil { log.Errorf("read file error, %v", err) return nil, err diff --git a/cmd/polaris-controller/app/options/polaris.go b/cmd/polaris-controller/app/options/polaris.go index 67a60726..1bb8247a 100644 --- a/cmd/polaris-controller/app/options/polaris.go +++ b/cmd/polaris-controller/app/options/polaris.go @@ -29,7 +29,8 @@ type PolarisControllerOptions struct { // ServiceSync 服务同步相关配置 type ServiceSync struct { - Mode string `yaml:"mode"` + Mode string `yaml:"mode"` + // deprecated, use SyncMode instead ServerAddress string `yaml:"serverAddress"` // 以下配置仅 polaris-server 开启 console auth // 调用 polaris-server OpenAPI 的凭据 @@ -40,15 +41,9 @@ type ServiceSync struct { Enable bool `yaml:"enable"` } -// ConfigSync 服务同步相关配置 +// ConfigSync 配置同步相关配置 type ConfigSync struct { - Mode string `yaml:"mode"` - ServerAddress string `yaml:"serverAddress"` - // 以下配置仅 polaris-server 开启 console auth - // 调用 polaris-server OpenAPI 的凭据 - PolarisAccessToken string `yaml:"accessToken"` - // Operator 用于数据同步的帐户ID - Operator string `yaml:"operator"` + Mode string `yaml:"mode"` // AllowDelete 允许向 Polaris 发起删除操作 AllowDelete bool `yaml:"allowDelete"` // SyncDirection 配置同步方向, kubernetesToPolaris/polarisToKubernetes/both diff --git a/cmd/polaris-controller/app/polaris-controller-manager.go b/cmd/polaris-controller/app/polaris-controller-manager.go index dafeb3aa..5f4778f4 100644 --- a/cmd/polaris-controller/app/polaris-controller-manager.go +++ b/cmd/polaris-controller/app/polaris-controller-manager.go @@ -48,6 +48,7 @@ import ( "github.com/polarismesh/polaris-controller/common" "github.com/polarismesh/polaris-controller/common/log" polarisController "github.com/polarismesh/polaris-controller/pkg/controller" + "github.com/polarismesh/polaris-controller/pkg/inject/pkg/config" "github.com/polarismesh/polaris-controller/pkg/inject/pkg/kube/inject" _ "github.com/polarismesh/polaris-controller/pkg/inject/pkg/kube/inject/apply/javaagent" _ "github.com/polarismesh/polaris-controller/pkg/inject/pkg/kube/inject/apply/mesh" @@ -68,7 +69,7 @@ const ( DnsConfigFile = "/etc/polaris-inject/inject/dns-config" JavaAgentConfigFile = "/etc/polaris-inject/inject/java-agent-config" ValuesFile = "/etc/polaris-inject/inject/values" - MeshFile = "/etc/polaris-inject/config/mesh" + BootstrapConfigFile = "/etc/polaris-inject/config/mesh" CertFile = "/etc/polaris-inject/certs/cert.pem" KeyFile = "/etc/polaris-inject/certs/key.pem" ) @@ -186,8 +187,7 @@ func initControllerConfig(s *options.KubeControllerManagerOptions) { if flags.polarisServerAddress != "" { polarisServerAddress = flags.polarisServerAddress } else { - // 启动参数没有指定,取 mesh config 中的地址 - polarisServerAddress = config.ServiceSync.ServerAddress + polarisServerAddress = config.getPolarisServerAddress() } // 去除前后的空格字符 polarisServerAddress = strings.TrimSpace(polarisServerAddress) @@ -196,9 +196,8 @@ func initControllerConfig(s *options.KubeControllerManagerOptions) { polarisapi.PolarisConfigGrpc = polarisServerAddress + ":8093" log.Infof("[Manager] polaris http address %s, discover grpc address %s, config grpc address %s", polarisapi.PolarisHttpURL, polarisapi.PolarisGrpc, polarisapi.PolarisConfigGrpc) - // 设置北极星开启鉴权之后,需要使用的访问token - polarisapi.PolarisAccessToken = config.ServiceSync.PolarisAccessToken - polarisapi.PolarisOperator = config.ServiceSync.Operator + polarisapi.PolarisAccessToken = config.getPolarisAccessToken() + polarisapi.PolarisOperator = config.getPolarisOperator() // 2. 配置 polaris 同步模式 if s.PolarisController.SyncMode == "" { @@ -247,15 +246,18 @@ func closeGrpcLog() { } func initPolarisSidecarInjector(c *options.CompletedConfig) error { - parameters := inject.WebhookParameters{ - DefaultSidecarMode: util.ParseSidecarMode(c.ComponentConfig.PolarisController.SidecarMode), + templateFilePath := config.TemplateFileConfig{ MeshConfigFile: MeshConfigFile, DnsConfigFile: DnsConfigFile, JavaAgentConfigFile: JavaAgentConfigFile, ValuesFile: ValuesFile, - MeshFile: MeshFile, + BootstrapConfigFile: BootstrapConfigFile, CertFile: CertFile, KeyFile: KeyFile, + } + parameters := inject.WebhookParameters{ + DefaultSidecarMode: util.ParseSidecarMode(c.ComponentConfig.PolarisController.SidecarMode), + TemplateFileConfig: templateFilePath, Port: flags.injectPort, HealthCheckInterval: 3 * time.Second, HealthCheckFile: "/tmp/health", diff --git a/deploy/kubernetes_v1.21/helm/templates/_helpers.tpl b/deploy/kubernetes_v1.21/helm/templates/_helpers.tpl index d984542c..9a212e1a 100644 --- a/deploy/kubernetes_v1.21/helm/templates/_helpers.tpl +++ b/deploy/kubernetes_v1.21/helm/templates/_helpers.tpl @@ -55,6 +55,13 @@ Get specific image for sidecar init container {{- printf "%s:%s" .Values.sidecar.envoy.image.repo .Values.sidecar.envoy.image.tag -}} {{- end -}} +{{/* +Get specific image for javaagent init container +*/}} +{{- define "polaris-controller.sidecar.javaagent.image" -}} +{{- printf "%s:%s" .Values.sidecar.javaagent.image.repo .Values.sidecar.javaagent.image.tag -}} +{{- end -}} + {{/* Get specific image for sidecar init container */}} diff --git a/deploy/kubernetes_v1.21/helm/templates/admission-webhooks/mutating-webhook.yaml b/deploy/kubernetes_v1.21/helm/templates/admission-webhooks/mutating-webhook.yaml index c1ec676e..a51951eb 100644 --- a/deploy/kubernetes_v1.21/helm/templates/admission-webhooks/mutating-webhook.yaml +++ b/deploy/kubernetes_v1.21/helm/templates/admission-webhooks/mutating-webhook.yaml @@ -20,4 +20,40 @@ webhooks: failurePolicy: Fail namespaceSelector: matchLabels: - polaris-injection: enabled \ No newline at end of file + polaris-injection: enabled + - name: ns.injector.polarismesh.cn + clientConfig: + service: + name: polaris-sidecar-injector + namespace: polaris-system + path: "/inject" + caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZpVENDQTNHZ0F3SUJBZ0lVSUJGZmZMeE84K2RNSTNrd3hOcXpibGg4Zm9Vd0RRWUpLb1pJaHZjTkFRRUwKQlFBd05qRTBNRElHQTFVRUF3d3JjRzlzWVhKcGN5MXphV1JsWTJGeUxXbHVhbVZqZEc5eUxuQnZiR0Z5YVhNdApjM2x6ZEdWdExuTjJZekFnRncweU1qQTNNRFF3TXpFNU1UaGFHQTh5TVRJeE1EWXhNREF6TVRreE9Gb3dOakUwCk1ESUdBMVVFQXd3cmNHOXNZWEpwY3kxemFXUmxZMkZ5TFdsdWFtVmpkRzl5TG5CdmJHRnlhWE10YzNsemRHVnQKTG5OMll6Q0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUxMWmE4NzZkQnRmQlJ1cgpaSzZpK0UzRUs4UWJFWitlaG1lNWNhaXhsakRwTlJIdHFyb2I2NGExYldTUWQxU0IvMmVxbVdiY1ZXY24vVFRQCk45WFVHN2JsNExSaWRWQktYODE3ekdDWEYra3BqbTNOekFseEdEK3lteXhJeWhYS1U5K3A3VGk5SXpORXNPNE8KSlhaQm5iOVdzWGU2eGJJN0dlUUY5WXVCdit0ekNMNVJ0ZmRiUmtMVGQ2eWF3NlZYTFdEcDFrUUU4Q1pEc0g5ZApTZmxBeUhCUitaLzVqbzBtMnQzU3hiNTVPak9YcDhVNmV3bVRmdzZ0VXE1Z3dmZXBjWGNOUWlVTXJveFl0dXkxCkxnWGVBN3MvMFdCeDcrVlFPWXlGSGlaQUI0V1dkSEk1S0JIeFlpSFA3Y2N5aWEvM0gwQ2lYVSthYnd0NHk5TDQKdmVSMHQ5ZmMvbXZXUU01aFBjT1hwdzVJZU5sUG8wZE9vZ0NNdE1qaTkwTEFFS2RMQVNhemxDT0hzdVFqNkczaQp4Nk4rdzQrYy9VTGFxR1REUGc2K0c0UDl5UUVZNXVDNDRZWWpJSGxjQlhyR0YwVFFKTEZMM3F4dnU1VitpYXF1CnMvaWZyRzllY3RyY3lLczVWM0dESGlDdE93Y29MajI1TG1oYzF4MEdvT1RmWis3VFA1NjRyM1k3cVVhcUJ3WFgKMWREak4wREFtU1k1VW1tTGhhZ205bU9xcVo4T29XY0M2clFEVUJwbW1hTTUxVEVkeVEwbHNCc0g1T0Jvalp1UgpkeUZuTXkxWHdSRjVNenRrTW9nRnZKYWhnN1hVUTJBN1NBaUhxaUlCY1AyZTZKNDdUMVNqa0s4NUpwMU1WRW5PCjZhSFZxR29wQm9tUi9BNzBTUlRLeGp2UW52UC9BZ01CQUFHamdZd3dnWWt3SFFZRFZSME9CQllFRkNMTkZlMHUKd3Z3RGRiT0VRQWwxNFMwRTRBQzhNQjhHQTFVZEl3UVlNQmFBRkNMTkZlMHV3dndEZGJPRVFBbDE0UzBFNEFDOApNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdOZ1lEVlIwUkJDOHdMWUlyY0c5c1lYSnBjeTF6YVdSbFkyRnlMV2x1CmFtVmpkRzl5TG5CdmJHRnlhWE10YzNsemRHVnRMbk4yWXpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQWdFQWx5aXQKVjdYaHRqZTFXK3RBMUtiUUtBUi8rendiUW1RUHpRTHpRdEdqUERvbmk5VVYyK3A1OEF5YmtvVVo3cEhXb2hFcgoxUGI2WGpKVVYxNjhGb3FZMUR4OS9SRCtDeC9mOWZ1MkswTTEvc2pYTk9oVERuMHZwZ2VvMFZJOVdCcUMrK1EyCllORmZNM2ZhaDQyaXVaSTBZNldnRldJM3dGbUQ3MTBWTC8xOVhMQ0dpditUbmc0ZnRwcHhOZW9rWlI1dU1janAKM0hNeExnUkExbnFYQ2ZhT3VrRVZLbnhvQ1hoQmRySXErV1VsOUZjZ09iVGxaU0RMNEpkZTl2R1B3cFBFRS9pVgo5cHhsMkhxWWdUZEdXZjJXeWluSmhZazFXempmZzFRTEY0TnJIQ2o3alJNbDBFbXZHM0hTNDM0ME9PUURKTlptClBDVHVrODV6L2dwaml5b3RxUlorcmNXSThBbVZDdURWbkg0VHVqb2swU1RXdUlWUDM5c21DUE5kUElwUVIxblIKSnZ1L2szV0IrTmlZbU94QzJ5SjRvMWRtYnZvS2ZadGIxVVBObVRJcmxXNThlMDdmUGV4QmNwR3JSRk5yVS9kaQpJbEpMNytXVVBKQWluTC8zL0FLQm5md1ZaemtrOVlUdld0b2xZeElhRExTd3JsdEdvZjBQUkptYnI0UDdxbm56ClFDUXVlZDFsUjRaUHJnYUlnZEdHSjdac1lESlVZbS8xd2g3N3FmR3FlYlRFZmorV09JYzV2S09vcEZTY0ZXd3oKNGVZVmVMYjBZdkc0dmc3ZHhCNFArbElzaFNpdmRVUE5XMW5ZY05pcFIrNnI2Q3h0ZnIwWjZWSkFjZjdTR1FHNwpYZkNuQXdMdlJtMEs2Q1Z6WUhPTFVRR2ZVSjBEbGFEeUR3c0JOc009Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + rules: + - operations: ["CREATE"] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + admissionReviewVersions: ["v1"] + sideEffects: "None" + failurePolicy: Fail + namespaceSelector: + matchLabels: + polarismesh.cn/inject: enabled + - name: allowlist.polarismesh.cn + clientConfig: + service: + name: polaris-sidecar-injector + namespace: polaris-system + path: "/inject" + caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZpVENDQTNHZ0F3SUJBZ0lVSUJGZmZMeE84K2RNSTNrd3hOcXpibGg4Zm9Vd0RRWUpLb1pJaHZjTkFRRUwKQlFBd05qRTBNRElHQTFVRUF3d3JjRzlzWVhKcGN5MXphV1JsWTJGeUxXbHVhbVZqZEc5eUxuQnZiR0Z5YVhNdApjM2x6ZEdWdExuTjJZekFnRncweU1qQTNNRFF3TXpFNU1UaGFHQTh5TVRJeE1EWXhNREF6TVRreE9Gb3dOakUwCk1ESUdBMVVFQXd3cmNHOXNZWEpwY3kxemFXUmxZMkZ5TFdsdWFtVmpkRzl5TG5CdmJHRnlhWE10YzNsemRHVnQKTG5OMll6Q0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUxMWmE4NzZkQnRmQlJ1cgpaSzZpK0UzRUs4UWJFWitlaG1lNWNhaXhsakRwTlJIdHFyb2I2NGExYldTUWQxU0IvMmVxbVdiY1ZXY24vVFRQCk45WFVHN2JsNExSaWRWQktYODE3ekdDWEYra3BqbTNOekFseEdEK3lteXhJeWhYS1U5K3A3VGk5SXpORXNPNE8KSlhaQm5iOVdzWGU2eGJJN0dlUUY5WXVCdit0ekNMNVJ0ZmRiUmtMVGQ2eWF3NlZYTFdEcDFrUUU4Q1pEc0g5ZApTZmxBeUhCUitaLzVqbzBtMnQzU3hiNTVPak9YcDhVNmV3bVRmdzZ0VXE1Z3dmZXBjWGNOUWlVTXJveFl0dXkxCkxnWGVBN3MvMFdCeDcrVlFPWXlGSGlaQUI0V1dkSEk1S0JIeFlpSFA3Y2N5aWEvM0gwQ2lYVSthYnd0NHk5TDQKdmVSMHQ5ZmMvbXZXUU01aFBjT1hwdzVJZU5sUG8wZE9vZ0NNdE1qaTkwTEFFS2RMQVNhemxDT0hzdVFqNkczaQp4Nk4rdzQrYy9VTGFxR1REUGc2K0c0UDl5UUVZNXVDNDRZWWpJSGxjQlhyR0YwVFFKTEZMM3F4dnU1VitpYXF1CnMvaWZyRzllY3RyY3lLczVWM0dESGlDdE93Y29MajI1TG1oYzF4MEdvT1RmWis3VFA1NjRyM1k3cVVhcUJ3WFgKMWREak4wREFtU1k1VW1tTGhhZ205bU9xcVo4T29XY0M2clFEVUJwbW1hTTUxVEVkeVEwbHNCc0g1T0Jvalp1UgpkeUZuTXkxWHdSRjVNenRrTW9nRnZKYWhnN1hVUTJBN1NBaUhxaUlCY1AyZTZKNDdUMVNqa0s4NUpwMU1WRW5PCjZhSFZxR29wQm9tUi9BNzBTUlRLeGp2UW52UC9BZ01CQUFHamdZd3dnWWt3SFFZRFZSME9CQllFRkNMTkZlMHUKd3Z3RGRiT0VRQWwxNFMwRTRBQzhNQjhHQTFVZEl3UVlNQmFBRkNMTkZlMHV3dndEZGJPRVFBbDE0UzBFNEFDOApNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdOZ1lEVlIwUkJDOHdMWUlyY0c5c1lYSnBjeTF6YVdSbFkyRnlMV2x1CmFtVmpkRzl5TG5CdmJHRnlhWE10YzNsemRHVnRMbk4yWXpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQWdFQWx5aXQKVjdYaHRqZTFXK3RBMUtiUUtBUi8rendiUW1RUHpRTHpRdEdqUERvbmk5VVYyK3A1OEF5YmtvVVo3cEhXb2hFcgoxUGI2WGpKVVYxNjhGb3FZMUR4OS9SRCtDeC9mOWZ1MkswTTEvc2pYTk9oVERuMHZwZ2VvMFZJOVdCcUMrK1EyCllORmZNM2ZhaDQyaXVaSTBZNldnRldJM3dGbUQ3MTBWTC8xOVhMQ0dpditUbmc0ZnRwcHhOZW9rWlI1dU1janAKM0hNeExnUkExbnFYQ2ZhT3VrRVZLbnhvQ1hoQmRySXErV1VsOUZjZ09iVGxaU0RMNEpkZTl2R1B3cFBFRS9pVgo5cHhsMkhxWWdUZEdXZjJXeWluSmhZazFXempmZzFRTEY0TnJIQ2o3alJNbDBFbXZHM0hTNDM0ME9PUURKTlptClBDVHVrODV6L2dwaml5b3RxUlorcmNXSThBbVZDdURWbkg0VHVqb2swU1RXdUlWUDM5c21DUE5kUElwUVIxblIKSnZ1L2szV0IrTmlZbU94QzJ5SjRvMWRtYnZvS2ZadGIxVVBObVRJcmxXNThlMDdmUGV4QmNwR3JSRk5yVS9kaQpJbEpMNytXVVBKQWluTC8zL0FLQm5md1ZaemtrOVlUdld0b2xZeElhRExTd3JsdEdvZjBQUkptYnI0UDdxbm56ClFDUXVlZDFsUjRaUHJnYUlnZEdHSjdac1lESlVZbS8xd2g3N3FmR3FlYlRFZmorV09JYzV2S09vcEZTY0ZXd3oKNGVZVmVMYjBZdkc0dmc3ZHhCNFArbElzaFNpdmRVUE5XMW5ZY05pcFIrNnI2Q3h0ZnIwWjZWSkFjZjdTR1FHNwpYZkNuQXdMdlJtMEs2Q1Z6WUhPTFVRR2ZVSjBEbGFEeUR3c0JOc009Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + rules: + - operations: ["CREATE"] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + admissionReviewVersions: ["v1"] + sideEffects: "None" + failurePolicy: Fail + objectSelector: + matchLabels: + polarismesh.cn/inject: enabled \ No newline at end of file diff --git a/deploy/kubernetes_v1.21/helm/templates/controller-configmap-javaagent.yaml b/deploy/kubernetes_v1.21/helm/templates/controller-configmap-javaagent.yaml index 6bf29631..d26dd33f 100644 --- a/deploy/kubernetes_v1.21/helm/templates/controller-configmap-javaagent.yaml +++ b/deploy/kubernetes_v1.21/helm/templates/controller-configmap-javaagent.yaml @@ -16,7 +16,7 @@ data: # 启用 Java Agent 的 Spring Cloud Tencent 注册发现能力 spring.cloud.discovery.enabled=true # 配置服务注册发现的命名空间信息 - spring.cloud.polaris.discovery.namespace=default + spring.cloud.polaris.discovery.namespace={{ .MicroserviceNamespace }} # 启用从北极星 spring.cloud.polaris.discovery.enabled=true spring.cloud.polaris.discovery.register=true @@ -66,7 +66,7 @@ data: # 启用 Java Agent 的 Spring Cloud Tencent 注册发现能力 spring.cloud.discovery.enabled=true # 配置服务注册发现的命名空间信息 - spring.cloud.polaris.discovery.namespace=default + spring.cloud.polaris.discovery.namespace={{ .MicroserviceNamespace }} # 启用从北极星 spring.cloud.polaris.discovery.enabled=true spring.cloud.polaris.discovery.register=true @@ -116,7 +116,7 @@ data: # 启用 Java Agent 的 Spring Cloud Tencent 注册发现能力 spring.cloud.discovery.enabled=true # 配置服务注册发现的命名空间信息 - spring.cloud.polaris.discovery.namespace=default + spring.cloud.polaris.discovery.namespace={{ .MicroserviceNamespace }} # 启用从北极星 spring.cloud.polaris.discovery.enabled=true spring.cloud.polaris.discovery.register=true diff --git a/deploy/kubernetes_v1.21/helm/templates/controller-configmap-mesh.yaml b/deploy/kubernetes_v1.21/helm/templates/controller-configmap-mesh.yaml index e285c48b..db6c2fe4 100644 --- a/deploy/kubernetes_v1.21/helm/templates/controller-configmap-mesh.yaml +++ b/deploy/kubernetes_v1.21/helm/templates/controller-configmap-mesh.yaml @@ -61,22 +61,22 @@ data: - stdout errorOutputPaths: - stderr + # 北极星服务端地址 + serverAddress: {{ .Values.polaris.server.address }} + # 北极星服务端token(北极星开启鉴权时需要配置) + accessToken: {{ .Values.polaris.server.token }} + # 北极星主账户ID + operator: {{ .Values.polaris.server.operator }} # k8s cluster name clusterName: "{{ .Values.cluster.name }}" - # polaris-sidecar 注入的默认启动模式, 可以配置 mesh 或者 dns + # polaris-sidecar 注入的默认启动模式, 可以配置 java-agent, mesh 或者 dns sidecarInject: - mode: "{{ .Values.sidecar.mesh }}" + mode: "{{ .Values.sidecar.mode }}" # service sync serviceSync: mode: {{ .Values.polaris.sync.service.mode }} - serverAddress: {{ .Values.polaris.server.address }} - # 北极星开启鉴权时需要配置 - accessToken: {{ .Values.polaris.server.token }} configSync: enable: {{ .Values.polaris.sync.config.enable }} - serverAddress: {{ .Values.polaris.server.address }} - # 北极星开启鉴权时需要配置 - accessToken: {{ .Values.polaris.server.token }} allowDelete: {{ .Values.polaris.sync.config.allowDelete }} # 配置同步方向: kubernetesToPolaris|polarisToKubernetes|both syncDirection: {{ .Values.polaris.sync.config.direction }} diff --git a/deploy/kubernetes_v1.21/helm/templates/controller-configmap-sidecar.yaml b/deploy/kubernetes_v1.21/helm/templates/controller-configmap-sidecar.yaml index f49281d5..1314e7dc 100644 --- a/deploy/kubernetes_v1.21/helm/templates/controller-configmap-sidecar.yaml +++ b/deploy/kubernetes_v1.21/helm/templates/controller-configmap-sidecar.yaml @@ -15,7 +15,7 @@ data: [] neverInjectSelector: - [] + [{"matchLabels":{"polarismesh.cn/inject":"disabled"}}] template: | containers: @@ -93,12 +93,12 @@ data: [] neverInjectSelector: - [] + [{"matchLabels":{"polarismesh.cn/inject":"disabled"}}] template: | initContainers: - name: polaris-javaagent-init - image: polarismesh/polaris-javaagent-init:#JAVA_AGENT_INIT# + image: {{ include "polaris-controller.sidecar.javaagent.image" . }} imagePullPolicy: Always env: - name: JAVA_AGENT_DIR @@ -138,7 +138,7 @@ data: [] neverInjectSelector: - [] + [{"matchLabels":{"polarismesh.cn/inject":"disabled"}}] template: | containers: diff --git a/deploy/kubernetes_v1.21/helm/values.yaml b/deploy/kubernetes_v1.21/helm/values.yaml index b37094de..4b1ecda7 100644 --- a/deploy/kubernetes_v1.21/helm/values.yaml +++ b/deploy/kubernetes_v1.21/helm/values.yaml @@ -31,12 +31,18 @@ sidecar: image: repo: polarismesh/polaris-envoy-bootstrap-generator tag: #CONTROLLER_VERSION# + javaagent: + image: + repo: polarismesh/polaris-javaagent-init + tag: #JAVA_AGENT_INIT# + pullPolicy: Always ## polaris server config polaris: server: address: #POLARIS_HOST# token: #POLARIS_TOKEN# + operator: #POLARIS_OPERATOR# sync: service: mode: all diff --git a/deploy/kubernetes_v1.21/kubernetes/configmap.yaml b/deploy/kubernetes_v1.21/kubernetes/configmap.yaml index bf45c353..519e6243 100644 --- a/deploy/kubernetes_v1.21/kubernetes/configmap.yaml +++ b/deploy/kubernetes_v1.21/kubernetes/configmap.yaml @@ -61,25 +61,23 @@ data: - stdout errorOutputPaths: - stderr + # 北极星服务端地址 + serverAddress: #POLARIS_HOST# + # 北极星服务端token(北极星开启鉴权时需要配置) + accessToken: "#POLARIS_TOKEN#" + # 北极星主账户ID + operator: #POLARIS_OPERATOR# # k8s cluster name clusterName: "#CLUSTER_NAME#" - # polaris-sidecar 注入的默认启动模式, 可以配置 mesh 或者 dns + # polaris-sidecar 注入的默认启动模式, 可以配置 java-agent, mesh 或者 dns sidecarInject: - mode: "mesh" + mode: "" # service sync serviceSync: - enable: true - mode: "all" - serverAddress: #POLARIS_HOST# - # 北极星开启鉴权时需要配置 - accessToken: #POLARIS_TOKEN# + mode: #SYNC_MODE# configSync: - enable: true - serverAddress: #POLARIS_HOST# - # 北极星开启鉴权时需要配置 - accessToken: #POLARIS_TOKEN# + enable: false allowDelete: false - # 配置同步方向: kubernetesToPolaris|polarisToKubernetes|both syncDirection: both defaultGroup: "#CLUSTER_NAME#" defaultConfig: diff --git a/deploy/kubernetes_v1.21/kubernetes/injector.yaml b/deploy/kubernetes_v1.21/kubernetes/injector.yaml index a4ec5277..c384bdd9 100644 --- a/deploy/kubernetes_v1.21/kubernetes/injector.yaml +++ b/deploy/kubernetes_v1.21/kubernetes/injector.yaml @@ -30,7 +30,7 @@ data: [] neverInjectSelector: - [] + [{"matchLabels":{"polarismesh.cn/inject":"disabled"}}] template: | containers: @@ -113,7 +113,7 @@ data: [] neverInjectSelector: - [] + [{"matchLabels":{"polarismesh.cn/inject":"disabled"}}] template: | initContainers: @@ -156,7 +156,7 @@ data: [] neverInjectSelector: - [] + [{"matchLabels":{"polarismesh.cn/inject":"disabled"}}] template: |+ containers: @@ -353,5 +353,43 @@ webhooks: namespaceSelector: matchLabels: polaris-injection: enabled + # 命名空间范围自动注入,新命名格式 + - name: ns.injector.polarismesh.cn + clientConfig: + service: + name: polaris-sidecar-injector + namespace: polaris-system + path: "/inject" + caBundle: "" + rules: + - operations: ["CREATE"] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + admissionReviewVersions: ["v1"] + sideEffects: "None" + failurePolicy: Fail + namespaceSelector: + matchLabels: + polarismesh.cn/inject: enabled + # 白名单功能, 支持按pod范围按需加载 + - name: allowlist.polarismesh.cn + clientConfig: + service: + name: polaris-sidecar-injector + namespace: polaris-system + path: "/inject" + caBundle: "" + rules: + - operations: ["CREATE"] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + admissionReviewVersions: ["v1"] + sideEffects: "None" + failurePolicy: Fail + objectSelector: + matchLabels: + polarismesh.cn/inject: enabled --- diff --git a/deploy/kubernetes_v1.21/kubernetes/javaagent-configmap.yaml b/deploy/kubernetes_v1.21/kubernetes/javaagent-configmap.yaml index 8fd0e297..2f1090d2 100644 --- a/deploy/kubernetes_v1.21/kubernetes/javaagent-configmap.yaml +++ b/deploy/kubernetes_v1.21/kubernetes/javaagent-configmap.yaml @@ -16,7 +16,7 @@ data: # 启用 Java Agent 的 Spring Cloud Tencent 注册发现能力 spring.cloud.discovery.enabled=true # 配置服务注册发现的命名空间信息 - spring.cloud.polaris.discovery.namespace=default + spring.cloud.polaris.discovery.namespace={{ .MicroserviceNamespace }} # 启用从北极星 spring.cloud.polaris.discovery.enabled=true spring.cloud.polaris.discovery.register=true @@ -76,7 +76,7 @@ data: # 启用 Java Agent 的 Spring Cloud Tencent 注册发现能力 spring.cloud.discovery.enabled=true # 配置服务注册发现的命名空间信息 - spring.cloud.polaris.discovery.namespace=default + spring.cloud.polaris.discovery.namespace={{ .MicroserviceNamespace }} # 启用从北极星 spring.cloud.polaris.discovery.enabled=true spring.cloud.polaris.discovery.register=true @@ -139,7 +139,7 @@ data: # 启用 Java Agent 的 Spring Cloud Tencent 注册发现能力 spring.cloud.discovery.enabled=true # 配置服务注册发现的命名空间信息 - spring.cloud.polaris.discovery.namespace=default + spring.cloud.polaris.discovery.namespace={{ .MicroserviceNamespace }} # 启用从北极星 spring.cloud.polaris.discovery.enabled=true spring.cloud.polaris.discovery.register=true @@ -189,7 +189,7 @@ data: # 启用 Java Agent 的 Spring Cloud Tencent 注册发现能力 spring.cloud.discovery.enabled=true # 配置服务注册发现的命名空间信息 - spring.cloud.polaris.discovery.namespace=default + spring.cloud.polaris.discovery.namespace={{ .MicroserviceNamespace }} # 启用从北极星 spring.cloud.polaris.discovery.enabled=true spring.cloud.polaris.discovery.register=true @@ -239,7 +239,7 @@ data: # 启用 Java Agent 的 Spring Cloud Tencent 注册发现能力 spring.cloud.discovery.enabled=true # 配置服务注册发现的命名空间信息 - spring.cloud.polaris.discovery.namespace=default + spring.cloud.polaris.discovery.namespace={{ .MicroserviceNamespace }} # 启用从北极星 spring.cloud.polaris.discovery.enabled=true spring.cloud.polaris.discovery.register=true diff --git a/deploy/kubernetes_v1.22/helm/templates/_helpers.tpl b/deploy/kubernetes_v1.22/helm/templates/_helpers.tpl index 64df51ff..47f74d64 100644 --- a/deploy/kubernetes_v1.22/helm/templates/_helpers.tpl +++ b/deploy/kubernetes_v1.22/helm/templates/_helpers.tpl @@ -48,6 +48,12 @@ Get specific image for sidecar init container {{- printf "%s:%s" .Values.sidecar.envoy.image.repo .Values.sidecar.envoy.image.tag -}} {{- end -}} +{{/* +Get specific image for javaagent init container +*/}} +{{- define "polaris-controller.sidecar.javaagent.image" -}} +{{- printf "%s:%s" .Values.sidecar.javaagent.image.repo .Values.sidecar.javaagent.image.tag -}} +{{- end -}} {{/* Get specific image for sidecar init container diff --git a/deploy/kubernetes_v1.22/helm/templates/admission-webhooks/mutating-webhook.yaml b/deploy/kubernetes_v1.22/helm/templates/admission-webhooks/mutating-webhook.yaml index aa494b7c..050235f4 100644 --- a/deploy/kubernetes_v1.22/helm/templates/admission-webhooks/mutating-webhook.yaml +++ b/deploy/kubernetes_v1.22/helm/templates/admission-webhooks/mutating-webhook.yaml @@ -22,4 +22,40 @@ webhooks: failurePolicy: Fail namespaceSelector: matchLabels: - polaris-injection: enabled \ No newline at end of file + polaris-injection: enabled + - name: ns.injector.polarismesh.cn + clientConfig: + service: + name: polaris-sidecar-injector + namespace: polaris-system + path: "/inject" + caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZpVENDQTNHZ0F3SUJBZ0lVSUJGZmZMeE84K2RNSTNrd3hOcXpibGg4Zm9Vd0RRWUpLb1pJaHZjTkFRRUwKQlFBd05qRTBNRElHQTFVRUF3d3JjRzlzWVhKcGN5MXphV1JsWTJGeUxXbHVhbVZqZEc5eUxuQnZiR0Z5YVhNdApjM2x6ZEdWdExuTjJZekFnRncweU1qQTNNRFF3TXpFNU1UaGFHQTh5TVRJeE1EWXhNREF6TVRreE9Gb3dOakUwCk1ESUdBMVVFQXd3cmNHOXNZWEpwY3kxemFXUmxZMkZ5TFdsdWFtVmpkRzl5TG5CdmJHRnlhWE10YzNsemRHVnQKTG5OMll6Q0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUxMWmE4NzZkQnRmQlJ1cgpaSzZpK0UzRUs4UWJFWitlaG1lNWNhaXhsakRwTlJIdHFyb2I2NGExYldTUWQxU0IvMmVxbVdiY1ZXY24vVFRQCk45WFVHN2JsNExSaWRWQktYODE3ekdDWEYra3BqbTNOekFseEdEK3lteXhJeWhYS1U5K3A3VGk5SXpORXNPNE8KSlhaQm5iOVdzWGU2eGJJN0dlUUY5WXVCdit0ekNMNVJ0ZmRiUmtMVGQ2eWF3NlZYTFdEcDFrUUU4Q1pEc0g5ZApTZmxBeUhCUitaLzVqbzBtMnQzU3hiNTVPak9YcDhVNmV3bVRmdzZ0VXE1Z3dmZXBjWGNOUWlVTXJveFl0dXkxCkxnWGVBN3MvMFdCeDcrVlFPWXlGSGlaQUI0V1dkSEk1S0JIeFlpSFA3Y2N5aWEvM0gwQ2lYVSthYnd0NHk5TDQKdmVSMHQ5ZmMvbXZXUU01aFBjT1hwdzVJZU5sUG8wZE9vZ0NNdE1qaTkwTEFFS2RMQVNhemxDT0hzdVFqNkczaQp4Nk4rdzQrYy9VTGFxR1REUGc2K0c0UDl5UUVZNXVDNDRZWWpJSGxjQlhyR0YwVFFKTEZMM3F4dnU1VitpYXF1CnMvaWZyRzllY3RyY3lLczVWM0dESGlDdE93Y29MajI1TG1oYzF4MEdvT1RmWis3VFA1NjRyM1k3cVVhcUJ3WFgKMWREak4wREFtU1k1VW1tTGhhZ205bU9xcVo4T29XY0M2clFEVUJwbW1hTTUxVEVkeVEwbHNCc0g1T0Jvalp1UgpkeUZuTXkxWHdSRjVNenRrTW9nRnZKYWhnN1hVUTJBN1NBaUhxaUlCY1AyZTZKNDdUMVNqa0s4NUpwMU1WRW5PCjZhSFZxR29wQm9tUi9BNzBTUlRLeGp2UW52UC9BZ01CQUFHamdZd3dnWWt3SFFZRFZSME9CQllFRkNMTkZlMHUKd3Z3RGRiT0VRQWwxNFMwRTRBQzhNQjhHQTFVZEl3UVlNQmFBRkNMTkZlMHV3dndEZGJPRVFBbDE0UzBFNEFDOApNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdOZ1lEVlIwUkJDOHdMWUlyY0c5c1lYSnBjeTF6YVdSbFkyRnlMV2x1CmFtVmpkRzl5TG5CdmJHRnlhWE10YzNsemRHVnRMbk4yWXpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQWdFQWx5aXQKVjdYaHRqZTFXK3RBMUtiUUtBUi8rendiUW1RUHpRTHpRdEdqUERvbmk5VVYyK3A1OEF5YmtvVVo3cEhXb2hFcgoxUGI2WGpKVVYxNjhGb3FZMUR4OS9SRCtDeC9mOWZ1MkswTTEvc2pYTk9oVERuMHZwZ2VvMFZJOVdCcUMrK1EyCllORmZNM2ZhaDQyaXVaSTBZNldnRldJM3dGbUQ3MTBWTC8xOVhMQ0dpditUbmc0ZnRwcHhOZW9rWlI1dU1janAKM0hNeExnUkExbnFYQ2ZhT3VrRVZLbnhvQ1hoQmRySXErV1VsOUZjZ09iVGxaU0RMNEpkZTl2R1B3cFBFRS9pVgo5cHhsMkhxWWdUZEdXZjJXeWluSmhZazFXempmZzFRTEY0TnJIQ2o3alJNbDBFbXZHM0hTNDM0ME9PUURKTlptClBDVHVrODV6L2dwaml5b3RxUlorcmNXSThBbVZDdURWbkg0VHVqb2swU1RXdUlWUDM5c21DUE5kUElwUVIxblIKSnZ1L2szV0IrTmlZbU94QzJ5SjRvMWRtYnZvS2ZadGIxVVBObVRJcmxXNThlMDdmUGV4QmNwR3JSRk5yVS9kaQpJbEpMNytXVVBKQWluTC8zL0FLQm5md1ZaemtrOVlUdld0b2xZeElhRExTd3JsdEdvZjBQUkptYnI0UDdxbm56ClFDUXVlZDFsUjRaUHJnYUlnZEdHSjdac1lESlVZbS8xd2g3N3FmR3FlYlRFZmorV09JYzV2S09vcEZTY0ZXd3oKNGVZVmVMYjBZdkc0dmc3ZHhCNFArbElzaFNpdmRVUE5XMW5ZY05pcFIrNnI2Q3h0ZnIwWjZWSkFjZjdTR1FHNwpYZkNuQXdMdlJtMEs2Q1Z6WUhPTFVRR2ZVSjBEbGFEeUR3c0JOc009Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + rules: + - operations: ["CREATE"] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + admissionReviewVersions: ["v1"] + sideEffects: "None" + failurePolicy: Fail + namespaceSelector: + matchLabels: + polarismesh.cn/inject: enabled + - name: allowlist.polarismesh.cn + clientConfig: + service: + name: polaris-sidecar-injector + namespace: polaris-system + path: "/inject" + caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZpVENDQTNHZ0F3SUJBZ0lVSUJGZmZMeE84K2RNSTNrd3hOcXpibGg4Zm9Vd0RRWUpLb1pJaHZjTkFRRUwKQlFBd05qRTBNRElHQTFVRUF3d3JjRzlzWVhKcGN5MXphV1JsWTJGeUxXbHVhbVZqZEc5eUxuQnZiR0Z5YVhNdApjM2x6ZEdWdExuTjJZekFnRncweU1qQTNNRFF3TXpFNU1UaGFHQTh5TVRJeE1EWXhNREF6TVRreE9Gb3dOakUwCk1ESUdBMVVFQXd3cmNHOXNZWEpwY3kxemFXUmxZMkZ5TFdsdWFtVmpkRzl5TG5CdmJHRnlhWE10YzNsemRHVnQKTG5OMll6Q0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUxMWmE4NzZkQnRmQlJ1cgpaSzZpK0UzRUs4UWJFWitlaG1lNWNhaXhsakRwTlJIdHFyb2I2NGExYldTUWQxU0IvMmVxbVdiY1ZXY24vVFRQCk45WFVHN2JsNExSaWRWQktYODE3ekdDWEYra3BqbTNOekFseEdEK3lteXhJeWhYS1U5K3A3VGk5SXpORXNPNE8KSlhaQm5iOVdzWGU2eGJJN0dlUUY5WXVCdit0ekNMNVJ0ZmRiUmtMVGQ2eWF3NlZYTFdEcDFrUUU4Q1pEc0g5ZApTZmxBeUhCUitaLzVqbzBtMnQzU3hiNTVPak9YcDhVNmV3bVRmdzZ0VXE1Z3dmZXBjWGNOUWlVTXJveFl0dXkxCkxnWGVBN3MvMFdCeDcrVlFPWXlGSGlaQUI0V1dkSEk1S0JIeFlpSFA3Y2N5aWEvM0gwQ2lYVSthYnd0NHk5TDQKdmVSMHQ5ZmMvbXZXUU01aFBjT1hwdzVJZU5sUG8wZE9vZ0NNdE1qaTkwTEFFS2RMQVNhemxDT0hzdVFqNkczaQp4Nk4rdzQrYy9VTGFxR1REUGc2K0c0UDl5UUVZNXVDNDRZWWpJSGxjQlhyR0YwVFFKTEZMM3F4dnU1VitpYXF1CnMvaWZyRzllY3RyY3lLczVWM0dESGlDdE93Y29MajI1TG1oYzF4MEdvT1RmWis3VFA1NjRyM1k3cVVhcUJ3WFgKMWREak4wREFtU1k1VW1tTGhhZ205bU9xcVo4T29XY0M2clFEVUJwbW1hTTUxVEVkeVEwbHNCc0g1T0Jvalp1UgpkeUZuTXkxWHdSRjVNenRrTW9nRnZKYWhnN1hVUTJBN1NBaUhxaUlCY1AyZTZKNDdUMVNqa0s4NUpwMU1WRW5PCjZhSFZxR29wQm9tUi9BNzBTUlRLeGp2UW52UC9BZ01CQUFHamdZd3dnWWt3SFFZRFZSME9CQllFRkNMTkZlMHUKd3Z3RGRiT0VRQWwxNFMwRTRBQzhNQjhHQTFVZEl3UVlNQmFBRkNMTkZlMHV3dndEZGJPRVFBbDE0UzBFNEFDOApNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdOZ1lEVlIwUkJDOHdMWUlyY0c5c1lYSnBjeTF6YVdSbFkyRnlMV2x1CmFtVmpkRzl5TG5CdmJHRnlhWE10YzNsemRHVnRMbk4yWXpBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQWdFQWx5aXQKVjdYaHRqZTFXK3RBMUtiUUtBUi8rendiUW1RUHpRTHpRdEdqUERvbmk5VVYyK3A1OEF5YmtvVVo3cEhXb2hFcgoxUGI2WGpKVVYxNjhGb3FZMUR4OS9SRCtDeC9mOWZ1MkswTTEvc2pYTk9oVERuMHZwZ2VvMFZJOVdCcUMrK1EyCllORmZNM2ZhaDQyaXVaSTBZNldnRldJM3dGbUQ3MTBWTC8xOVhMQ0dpditUbmc0ZnRwcHhOZW9rWlI1dU1janAKM0hNeExnUkExbnFYQ2ZhT3VrRVZLbnhvQ1hoQmRySXErV1VsOUZjZ09iVGxaU0RMNEpkZTl2R1B3cFBFRS9pVgo5cHhsMkhxWWdUZEdXZjJXeWluSmhZazFXempmZzFRTEY0TnJIQ2o3alJNbDBFbXZHM0hTNDM0ME9PUURKTlptClBDVHVrODV6L2dwaml5b3RxUlorcmNXSThBbVZDdURWbkg0VHVqb2swU1RXdUlWUDM5c21DUE5kUElwUVIxblIKSnZ1L2szV0IrTmlZbU94QzJ5SjRvMWRtYnZvS2ZadGIxVVBObVRJcmxXNThlMDdmUGV4QmNwR3JSRk5yVS9kaQpJbEpMNytXVVBKQWluTC8zL0FLQm5md1ZaemtrOVlUdld0b2xZeElhRExTd3JsdEdvZjBQUkptYnI0UDdxbm56ClFDUXVlZDFsUjRaUHJnYUlnZEdHSjdac1lESlVZbS8xd2g3N3FmR3FlYlRFZmorV09JYzV2S09vcEZTY0ZXd3oKNGVZVmVMYjBZdkc0dmc3ZHhCNFArbElzaFNpdmRVUE5XMW5ZY05pcFIrNnI2Q3h0ZnIwWjZWSkFjZjdTR1FHNwpYZkNuQXdMdlJtMEs2Q1Z6WUhPTFVRR2ZVSjBEbGFEeUR3c0JOc009Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + rules: + - operations: ["CREATE"] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + admissionReviewVersions: ["v1"] + sideEffects: "None" + failurePolicy: Fail + objectSelector: + matchLabels: + polarismesh.cn/inject: enabled \ No newline at end of file diff --git a/deploy/kubernetes_v1.22/helm/templates/controller-configmap-javaagent.yaml b/deploy/kubernetes_v1.22/helm/templates/controller-configmap-javaagent.yaml index c317063c..5b127929 100644 --- a/deploy/kubernetes_v1.22/helm/templates/controller-configmap-javaagent.yaml +++ b/deploy/kubernetes_v1.22/helm/templates/controller-configmap-javaagent.yaml @@ -16,7 +16,7 @@ data: # 启用 Java Agent 的 Spring Cloud Tencent 注册发现能力 spring.cloud.discovery.enabled=true # 配置服务注册发现的命名空间信息 - spring.cloud.polaris.discovery.namespace=default + spring.cloud.polaris.discovery.namespace={{ .MicroserviceNamespace }} # 启用从北极星 spring.cloud.polaris.discovery.enabled=true spring.cloud.polaris.discovery.register=true @@ -76,7 +76,7 @@ data: # 启用 Java Agent 的 Spring Cloud Tencent 注册发现能力 spring.cloud.discovery.enabled=true # 配置服务注册发现的命名空间信息 - spring.cloud.polaris.discovery.namespace=default + spring.cloud.polaris.discovery.namespace={{ .MicroserviceNamespace }} # 启用从北极星 spring.cloud.polaris.discovery.enabled=true spring.cloud.polaris.discovery.register=true @@ -126,7 +126,7 @@ data: # 启用 Java Agent 的 Spring Cloud Tencent 注册发现能力 spring.cloud.discovery.enabled=true # 配置服务注册发现的命名空间信息 - spring.cloud.polaris.discovery.namespace=default + spring.cloud.polaris.discovery.namespace={{ .MicroserviceNamespace }} # 启用从北极星 spring.cloud.polaris.discovery.enabled=true spring.cloud.polaris.discovery.register=true @@ -176,7 +176,7 @@ data: # 启用 Java Agent 的 Spring Cloud Tencent 注册发现能力 spring.cloud.discovery.enabled=true # 配置服务注册发现的命名空间信息 - spring.cloud.polaris.discovery.namespace=default + spring.cloud.polaris.discovery.namespace={{ .MicroserviceNamespace }} # 启用从北极星 spring.cloud.polaris.discovery.enabled=true spring.cloud.polaris.discovery.register=true diff --git a/deploy/kubernetes_v1.22/helm/templates/controller-configmap-mesh.yaml b/deploy/kubernetes_v1.22/helm/templates/controller-configmap-mesh.yaml index e285c48b..db6c2fe4 100644 --- a/deploy/kubernetes_v1.22/helm/templates/controller-configmap-mesh.yaml +++ b/deploy/kubernetes_v1.22/helm/templates/controller-configmap-mesh.yaml @@ -61,22 +61,22 @@ data: - stdout errorOutputPaths: - stderr + # 北极星服务端地址 + serverAddress: {{ .Values.polaris.server.address }} + # 北极星服务端token(北极星开启鉴权时需要配置) + accessToken: {{ .Values.polaris.server.token }} + # 北极星主账户ID + operator: {{ .Values.polaris.server.operator }} # k8s cluster name clusterName: "{{ .Values.cluster.name }}" - # polaris-sidecar 注入的默认启动模式, 可以配置 mesh 或者 dns + # polaris-sidecar 注入的默认启动模式, 可以配置 java-agent, mesh 或者 dns sidecarInject: - mode: "{{ .Values.sidecar.mesh }}" + mode: "{{ .Values.sidecar.mode }}" # service sync serviceSync: mode: {{ .Values.polaris.sync.service.mode }} - serverAddress: {{ .Values.polaris.server.address }} - # 北极星开启鉴权时需要配置 - accessToken: {{ .Values.polaris.server.token }} configSync: enable: {{ .Values.polaris.sync.config.enable }} - serverAddress: {{ .Values.polaris.server.address }} - # 北极星开启鉴权时需要配置 - accessToken: {{ .Values.polaris.server.token }} allowDelete: {{ .Values.polaris.sync.config.allowDelete }} # 配置同步方向: kubernetesToPolaris|polarisToKubernetes|both syncDirection: {{ .Values.polaris.sync.config.direction }} diff --git a/deploy/kubernetes_v1.22/helm/templates/controller-configmap-sidecar.yaml b/deploy/kubernetes_v1.22/helm/templates/controller-configmap-sidecar.yaml index f49281d5..1314e7dc 100644 --- a/deploy/kubernetes_v1.22/helm/templates/controller-configmap-sidecar.yaml +++ b/deploy/kubernetes_v1.22/helm/templates/controller-configmap-sidecar.yaml @@ -15,7 +15,7 @@ data: [] neverInjectSelector: - [] + [{"matchLabels":{"polarismesh.cn/inject":"disabled"}}] template: | containers: @@ -93,12 +93,12 @@ data: [] neverInjectSelector: - [] + [{"matchLabels":{"polarismesh.cn/inject":"disabled"}}] template: | initContainers: - name: polaris-javaagent-init - image: polarismesh/polaris-javaagent-init:#JAVA_AGENT_INIT# + image: {{ include "polaris-controller.sidecar.javaagent.image" . }} imagePullPolicy: Always env: - name: JAVA_AGENT_DIR @@ -138,7 +138,7 @@ data: [] neverInjectSelector: - [] + [{"matchLabels":{"polarismesh.cn/inject":"disabled"}}] template: | containers: diff --git a/deploy/kubernetes_v1.22/helm/values.yaml b/deploy/kubernetes_v1.22/helm/values.yaml index b37094de..4b1ecda7 100644 --- a/deploy/kubernetes_v1.22/helm/values.yaml +++ b/deploy/kubernetes_v1.22/helm/values.yaml @@ -31,12 +31,18 @@ sidecar: image: repo: polarismesh/polaris-envoy-bootstrap-generator tag: #CONTROLLER_VERSION# + javaagent: + image: + repo: polarismesh/polaris-javaagent-init + tag: #JAVA_AGENT_INIT# + pullPolicy: Always ## polaris server config polaris: server: address: #POLARIS_HOST# token: #POLARIS_TOKEN# + operator: #POLARIS_OPERATOR# sync: service: mode: all diff --git a/deploy/kubernetes_v1.22/kubernetes/configmap.yaml b/deploy/kubernetes_v1.22/kubernetes/configmap.yaml index bf45c353..519e6243 100644 --- a/deploy/kubernetes_v1.22/kubernetes/configmap.yaml +++ b/deploy/kubernetes_v1.22/kubernetes/configmap.yaml @@ -61,25 +61,23 @@ data: - stdout errorOutputPaths: - stderr + # 北极星服务端地址 + serverAddress: #POLARIS_HOST# + # 北极星服务端token(北极星开启鉴权时需要配置) + accessToken: "#POLARIS_TOKEN#" + # 北极星主账户ID + operator: #POLARIS_OPERATOR# # k8s cluster name clusterName: "#CLUSTER_NAME#" - # polaris-sidecar 注入的默认启动模式, 可以配置 mesh 或者 dns + # polaris-sidecar 注入的默认启动模式, 可以配置 java-agent, mesh 或者 dns sidecarInject: - mode: "mesh" + mode: "" # service sync serviceSync: - enable: true - mode: "all" - serverAddress: #POLARIS_HOST# - # 北极星开启鉴权时需要配置 - accessToken: #POLARIS_TOKEN# + mode: #SYNC_MODE# configSync: - enable: true - serverAddress: #POLARIS_HOST# - # 北极星开启鉴权时需要配置 - accessToken: #POLARIS_TOKEN# + enable: false allowDelete: false - # 配置同步方向: kubernetesToPolaris|polarisToKubernetes|both syncDirection: both defaultGroup: "#CLUSTER_NAME#" defaultConfig: diff --git a/deploy/kubernetes_v1.22/kubernetes/injector.yaml b/deploy/kubernetes_v1.22/kubernetes/injector.yaml index 5849f99a..98a25d29 100644 --- a/deploy/kubernetes_v1.22/kubernetes/injector.yaml +++ b/deploy/kubernetes_v1.22/kubernetes/injector.yaml @@ -15,7 +15,7 @@ data: [] neverInjectSelector: - [] + [{"matchLabels":{"polarismesh.cn/inject":"disabled"}}] template: | containers: @@ -98,7 +98,7 @@ data: [] neverInjectSelector: - [] + [{"matchLabels":{"polarismesh.cn/inject":"disabled"}}] template: | initContainers: @@ -142,7 +142,7 @@ data: [] neverInjectSelector: - [] + [{"matchLabels":{"polarismesh.cn/inject":"disabled"}}] template: | containers: diff --git a/deploy/kubernetes_v1.22/kubernetes/javaagent-configmap.yaml b/deploy/kubernetes_v1.22/kubernetes/javaagent-configmap.yaml index 96cbed60..8535131d 100644 --- a/deploy/kubernetes_v1.22/kubernetes/javaagent-configmap.yaml +++ b/deploy/kubernetes_v1.22/kubernetes/javaagent-configmap.yaml @@ -16,7 +16,7 @@ data: # 启用 Java Agent 的 Spring Cloud Tencent 注册发现能力 spring.cloud.discovery.enabled=true # 配置服务注册发现的命名空间信息 - spring.cloud.polaris.discovery.namespace=default + spring.cloud.polaris.discovery.namespace={{ .MicroserviceNamespace }} # 启用从北极星 spring.cloud.polaris.discovery.enabled=true spring.cloud.polaris.discovery.register=true @@ -76,7 +76,7 @@ data: # 启用 Java Agent 的 Spring Cloud Tencent 注册发现能力 spring.cloud.discovery.enabled=true # 配置服务注册发现的命名空间信息 - spring.cloud.polaris.discovery.namespace=default + spring.cloud.polaris.discovery.namespace={{ .MicroserviceNamespace }} # 启用从北极星 spring.cloud.polaris.discovery.enabled=true spring.cloud.polaris.discovery.register=true @@ -139,7 +139,7 @@ data: # 启用 Java Agent 的 Spring Cloud Tencent 注册发现能力 spring.cloud.discovery.enabled=true # 配置服务注册发现的命名空间信息 - spring.cloud.polaris.discovery.namespace=default + spring.cloud.polaris.discovery.namespace={{ .MicroserviceNamespace }} # 启用从北极星 spring.cloud.polaris.discovery.enabled=true spring.cloud.polaris.discovery.register=true @@ -189,7 +189,7 @@ data: # 启用 Java Agent 的 Spring Cloud Tencent 注册发现能力 spring.cloud.discovery.enabled=true # 配置服务注册发现的命名空间信息 - spring.cloud.polaris.discovery.namespace=default + spring.cloud.polaris.discovery.namespace={{ .MicroserviceNamespace }} # 启用从北极星 spring.cloud.polaris.discovery.enabled=true spring.cloud.polaris.discovery.register=true @@ -239,7 +239,7 @@ data: # 启用 Java Agent 的 Spring Cloud Tencent 注册发现能力 spring.cloud.discovery.enabled=true # 配置服务注册发现的命名空间信息 - spring.cloud.polaris.discovery.namespace=default + spring.cloud.polaris.discovery.namespace={{ .MicroserviceNamespace }} # 启用从北极星 spring.cloud.polaris.discovery.enabled=true spring.cloud.polaris.discovery.register=true diff --git a/deploy/kubernetes_v1.22/kubernetes/polaris-controller.yaml b/deploy/kubernetes_v1.22/kubernetes/polaris-controller.yaml index c3361f9d..169d5021 100644 --- a/deploy/kubernetes_v1.22/kubernetes/polaris-controller.yaml +++ b/deploy/kubernetes_v1.22/kubernetes/polaris-controller.yaml @@ -51,6 +51,44 @@ webhooks: namespaceSelector: matchLabels: polaris-injection: enabled + # 命名空间范围自动注入,新命名格式 + - name: ns.injector.polarismesh.cn + clientConfig: + service: + name: polaris-sidecar-injector + namespace: polaris-system + path: "/inject" + caBundle: "" + rules: + - operations: ["CREATE"] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + admissionReviewVersions: ["v1"] + sideEffects: "None" + failurePolicy: Fail + namespaceSelector: + matchLabels: + polarismesh.cn/inject: enabled + # 白名单功能, 支持按pod范围按需加载 + - name: allowlist.polarismesh.cn + clientConfig: + service: + name: polaris-sidecar-injector + namespace: polaris-system + path: "/inject" + caBundle: "" + rules: + - operations: ["CREATE"] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + admissionReviewVersions: ["v1"] + sideEffects: "None" + failurePolicy: Fail + objectSelector: + matchLabels: + polarismesh.cn/inject: enabled --- apiVersion: apps/v1 kind: StatefulSet diff --git a/deploy/variables.txt b/deploy/variables.txt index e50d8a43..2eb8de33 100644 --- a/deploy/variables.txt +++ b/deploy/variables.txt @@ -2,6 +2,7 @@ POLARIS_HOST:polaris.polaris-system CONTROLLER_VERSION:##VERSION## SIDECAR_VERSION:v1.5.1 POLARIS_TOKEN:nu/0WRA4EqSR1FagrjRj0fZwPXuGlMpX+zCuWu4uMqy8xr1vRjisSbA25aAC3mtU8MeeRsKhQiDAynUR09I= +POLARIS_OPERATOR:65e4789a6d5b49669adf1e9e8387549c ENVOY_VERSION:v1.26.2 CLUSTER_NAME:default -JAVA_AGENT_INIT:v0.0.1 \ No newline at end of file +JAVA_AGENT_INIT:latest \ No newline at end of file diff --git a/go.mod b/go.mod index 68cc013f..47c6601c 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( github.com/google/uuid v1.4.0 github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 - github.com/howeyc/fsnotify v0.9.0 github.com/natefinch/lumberjack v2.0.0+incompatible github.com/openshift/api v3.9.1-0.20191008181517-e4fd21196097+incompatible github.com/polarismesh/polaris-go v1.6.0-beta.2 @@ -19,8 +18,8 @@ require ( go.uber.org/atomic v1.11.0 go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.24.0 - golang.org/x/net v0.23.0 // indirect - golang.org/x/sys v0.18.0 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/sys v0.28.0 // indirect google.golang.org/grpc v1.59.0 gopkg.in/yaml.v2 v2.4.0 k8s.io/api v0.27.3 @@ -32,9 +31,15 @@ require ( require ( github.com/polarismesh/specification v1.4.2-alpha.6 + github.com/stretchr/testify v1.8.2 google.golang.org/protobuf v1.33.0 ) +require ( + github.com/evanphx/json-patch v4.12.0+incompatible // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect +) + require ( github.com/NYTimes/gziphandler v1.1.1 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -45,7 +50,7 @@ require ( github.com/dlclark/regexp2 v1.10.0 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/felixge/httpsnoop v1.0.3 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fsnotify/fsnotify v1.6.0 github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect @@ -82,9 +87,9 @@ require ( go.opentelemetry.io/proto/otlp v0.19.0 // indirect go.uber.org/automaxprocs v1.5.3 golang.org/x/oauth2 v0.12.0 // indirect - golang.org/x/sync v0.3.0 // indirect - golang.org/x/term v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/term v0.27.0 // indirect + golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect diff --git a/go.sum b/go.sum index 5ffaf047..87d27f69 100644 --- a/go.sum +++ b/go.sum @@ -381,8 +381,6 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/howeyc/fsnotify v0.9.0 h1:0gtV5JmOKH4A8SsFxG2BczSeXWWPvcMT0euZt5gDAxY= -github.com/howeyc/fsnotify v0.9.0/go.mod h1:41HzSPxBGeFRQKEEwgh49TRw/nKBsYZ2cF1OzPjSJsA= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= @@ -652,8 +650,8 @@ golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -692,8 +690,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -767,13 +765,13 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -784,8 +782,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -846,8 +844,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/pkg/inject/pkg/config/inject_config.go b/pkg/inject/pkg/config/inject_config.go new file mode 100644 index 00000000..c057a0c2 --- /dev/null +++ b/pkg/inject/pkg/config/inject_config.go @@ -0,0 +1,26 @@ +package config + +import ( + "crypto/sha256" + "crypto/tls" + "encoding/hex" + + "github.com/polarismesh/polaris-controller/pkg/inject/pkg/config/mesh" +) + +// InjectConfigInfo is a struct that contains all the configuration +type InjectConfigInfo struct { + MeshInjectConf *TemplateConfig + DnsInjectConf *TemplateConfig + JavaAgentInjectConf *TemplateConfig + MeshEnvoyConf *mesh.MeshEnvoyConfig + ValuesConf string + CertPair *tls.Certificate +} + +// helper function to generate a template version identifier from a +// hash of the un-executed template contents. +func sidecarTemplateVersionHash(in string) string { + hash := sha256.Sum256([]byte(in)) + return hex.EncodeToString(hash[:]) +} diff --git a/pkg/inject/pkg/config/mesh/mesh.go b/pkg/inject/pkg/config/mesh/mesh.go index 835524f1..9cf50589 100644 --- a/pkg/inject/pkg/config/mesh/mesh.go +++ b/pkg/inject/pkg/config/mesh/mesh.go @@ -15,62 +15,98 @@ package mesh import ( + "fmt" "os" "github.com/hashicorp/go-multierror" "gopkg.in/yaml.v2" ) -type MeshConfig struct { - DefaultConfig *DefaultConfig `yaml:"defaultConfig"` +// MeshEnvoyConfig mesh 注入配置, envoy sidecar当前有用到 +type MeshEnvoyConfig struct { + defaultConfig *DefaultConfig `yaml:"DefaultConfig"` } -func (m *MeshConfig) Clone() *MeshConfig { - copyData := &MeshConfig{ - DefaultConfig: &DefaultConfig{ - ProxyMetadata: map[string]string{}, +// DefaultConfig 存储北极星proxy默认配置和用户自定义配置 +type DefaultConfig struct { + proxyMetadata map[string]string `yaml:"proxyMetadata"` +} + +// ReadMeshEnvoyConfig 读取mesh envoy sidecar注入配置 +func ReadMeshEnvoyConfig(filename string) (*MeshEnvoyConfig, error) { + yamlBytes, err := os.ReadFile(filename) + if err != nil { + return nil, multierror.Prefix(err, "cannot read mesh config file") + } + defaultConfig := &MeshEnvoyConfig{ + defaultConfig: &DefaultConfig{ + proxyMetadata: map[string]string{}, }, } + if err = yaml.Unmarshal(yamlBytes, defaultConfig); err != nil { + return nil, err + } + return defaultConfig, nil +} - for k, v := range m.DefaultConfig.ProxyMetadata { - copyData.DefaultConfig.ProxyMetadata[k] = v +// GetDefaultConfig 获取默认配置 +func (ic *MeshEnvoyConfig) GetDefaultConfig() *DefaultConfig { + if ic == nil { + return nil } - return copyData + return ic.defaultConfig } -type DefaultConfig struct { - ProxyMetadata map[string]string `yaml:"proxyMetadata"` +// SetDefaultConfig 设置默认配置 +func (ic *MeshEnvoyConfig) SetDefaultConfig(config *DefaultConfig) { + if ic == nil { + return + } + ic.defaultConfig = config } -// DefaultMeshConfig configuration -func DefaultMeshConfig() MeshConfig { - return MeshConfig{ - DefaultConfig: &DefaultConfig{ - ProxyMetadata: map[string]string{}, - }, +// GetProxyMetadata 获取 proxy 元数据 +func (dc *DefaultConfig) GetProxyMetadata() map[string]string { + if dc == nil { + return nil } + return dc.proxyMetadata } -// ApplyMeshConfig returns a new MeshConfig decoded from the -// input YAML with the provided defaults applied to omitted configuration values. -func ApplyMeshConfig(str string, defaultConfig MeshConfig) (*MeshConfig, error) { - if err := yaml.Unmarshal([]byte(str), &defaultConfig); err != nil { - return nil, err +// SetProxyMetadataWithKV 设置 proxy 元数据 +func (dc *MeshEnvoyConfig) SetProxyMetadataWithKV(k, v string) { + if dc == nil { + return } - return &defaultConfig, nil + dc.defaultConfig.proxyMetadata[k] = v } -// ApplyMeshConfigDefaults returns a new MeshConfig decoded from the -// input YAML with defaults applied to omitted configuration values. -func ApplyMeshConfigDefaults(yaml string) (*MeshConfig, error) { - return ApplyMeshConfig(yaml, DefaultMeshConfig()) +// String 返回 MeshEnvoyConfig 的字符串表示 +func (ic *MeshEnvoyConfig) String() string { + if ic == nil { + return "MeshEnvoyConfig{nil}" + } + + var defaultConfig string + if ic.defaultConfig == nil { + defaultConfig = "nil" + } else { + defaultConfig = ic.defaultConfig.String() + } + + return fmt.Sprintf("MeshEnvoyConfig{DefaultConfig: %s}", defaultConfig) } -// ReadMeshConfig gets mesh configuration from a config file -func ReadMeshConfig(filename string) (*MeshConfig, error) { - yaml, err := os.ReadFile(filename) - if err != nil { - return nil, multierror.Prefix(err, "cannot read mesh config file") +// String 返回 DefaultConfig 的字符串表示 +func (dc *DefaultConfig) String() string { + if dc == nil { + return "DefaultConfig{nil}" } - return ApplyMeshConfigDefaults(string(yaml)) + + metadata := "nil" + if dc.proxyMetadata != nil { + metadata = fmt.Sprintf("%v", dc.proxyMetadata) + } + + return fmt.Sprintf("DefaultConfig{proxyMetadata: %s}", metadata) } diff --git a/pkg/inject/pkg/config/safe_config.go b/pkg/inject/pkg/config/safe_config.go new file mode 100644 index 00000000..aacbaf8a --- /dev/null +++ b/pkg/inject/pkg/config/safe_config.go @@ -0,0 +1,164 @@ +package config + +import ( + "crypto/tls" + "sync" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/polarismesh/polaris-controller/common/log" + "github.com/polarismesh/polaris-controller/pkg/inject/pkg/config/mesh" +) + +type SafeTemplateConfig struct { + mu sync.RWMutex + // envoy mesh 场景下的 sidecar 注入配置 + sidecarMeshTemplate *TemplateConfig + sidecarMeshTemplateVersion string + // dns 场景下的 sidecar 注入配置 + sidecarDnsTemplate *TemplateConfig + sidecarDnsTemplateVersion string + // java agent 场景下的注入配置 + sidecarJavaAgentTemplate *TemplateConfig + sidecarJavaAgentTemplateVersion string + // 北极星proxy配置 + meshEnvoyConfig *mesh.MeshEnvoyConfig + valuesConfig string + cert *tls.Certificate +} + +// TemplateConfig specifies the sidecar injection configuration This includes +// the sidecar template and cluster-side injection policy. It is used +// by kube-inject, sidecar injector, and http endpoint. +type TemplateConfig struct { + Policy InjectionPolicy `json:"policy"` + + // Template is the templated version of `SidecarInjectionSpec` prior to + // expansion over the `SidecarTemplateData`. + Template string `json:"template"` + + // NeverInjectSelector: Refuses the injection on pods whose labels match this selector. + // It's an array of label selectors, that will be OR'ed, meaning we will iterate + // over it and stop at the first match + // Takes precedence over AlwaysInjectSelector. + NeverInjectSelector []metav1.LabelSelector `json:"neverInjectSelector"` + + // AlwaysInjectSelector: Forces the injection on pods whose labels match this selector. + // It's an array of label selectors, that will be OR'ed, meaning we will iterate + // over it and stop at the first match + AlwaysInjectSelector []metav1.LabelSelector `json:"alwaysInjectSelector"` + + // InjectedAnnotations are additional annotations that will be added to the pod spec after injection + // This is primarily to support PSP annotations. + InjectedAnnotations map[string]string `json:"injectedAnnotations"` +} + +// InjectionPolicy determines the policy for injecting the +// sidecar proxy into the watched namespace(s). +type InjectionPolicy string + +const ( + // InjectionPolicyDisabled specifies that the sidecar injector + // will not inject the sidecar into resources by default for the + // namespace(s) being watched. Resources can enable injection + // using the "sidecar.polarismesh.cn/inject" annotation with value of + // true. + InjectionPolicyDisabled InjectionPolicy = "disabled" + + // InjectionPolicyEnabled specifies that the sidecar injector will + // inject the sidecar into resources by default for the + // namespace(s) being watched. Resources can disable injection + // using the "sidecar.polarismesh.cn/inject" annotation with value of + // false. + InjectionPolicyEnabled InjectionPolicy = "enabled" +) + +// NewTemplateConfig 创建模板配置 +func NewTemplateConfig(p TemplateFileConfig) (*SafeTemplateConfig, error) { + injectConf, err := loadConfig(p) + if err != nil { + log.InjectScope().Errorf("Failed to load inject config: %v", err) + return nil, err + } + return &SafeTemplateConfig{ + sidecarMeshTemplate: injectConf.MeshInjectConf, + sidecarMeshTemplateVersion: sidecarTemplateVersionHash(injectConf.MeshInjectConf.Template), + sidecarDnsTemplate: injectConf.DnsInjectConf, + sidecarDnsTemplateVersion: sidecarTemplateVersionHash(injectConf.DnsInjectConf.Template), + sidecarJavaAgentTemplate: injectConf.JavaAgentInjectConf, + sidecarJavaAgentTemplateVersion: sidecarTemplateVersionHash(injectConf.JavaAgentInjectConf.Template), + meshEnvoyConfig: injectConf.MeshEnvoyConf, + valuesConfig: injectConf.ValuesConf, + cert: injectConf.CertPair, + }, nil +} + +// UpdateTemplateConfig 更新模板配置 +func (tc *SafeTemplateConfig) UpdateTemplateConfig(p TemplateFileConfig) error { + injectConf, err := loadConfig(p) + if err != nil { + log.InjectScope().Errorf("Failed to load inject config: %v", err) + return err + } + tc.mu.Lock() + defer tc.mu.Unlock() + tc.sidecarMeshTemplate = injectConf.MeshInjectConf + tc.sidecarMeshTemplateVersion = sidecarTemplateVersionHash(injectConf.MeshInjectConf.Template) + tc.sidecarDnsTemplate = injectConf.DnsInjectConf + tc.sidecarDnsTemplateVersion = sidecarTemplateVersionHash(injectConf.DnsInjectConf.Template) + tc.sidecarJavaAgentTemplate = injectConf.JavaAgentInjectConf + tc.sidecarJavaAgentTemplateVersion = sidecarTemplateVersionHash(injectConf.JavaAgentInjectConf.Template) + tc.meshEnvoyConfig = injectConf.MeshEnvoyConf + tc.valuesConfig = injectConf.ValuesConf + tc.cert = injectConf.CertPair + return nil +} + +// GetSidecarMeshTemplateAndVersion 获取sidecar mesh 注入配置模板 +func (tc *SafeTemplateConfig) GetSidecarMeshTemplateAndVersion() (*TemplateConfig, string) { + tc.mu.RLock() + defer tc.mu.RUnlock() + return tc.sidecarMeshTemplate, tc.sidecarMeshTemplateVersion +} + +// GetSidecarDnsTemplateAndVersion 获取sidecar dns 注入配置模板 +func (tc *SafeTemplateConfig) GetSidecarDnsTemplateAndVersion() (*TemplateConfig, string) { + tc.mu.RLock() + defer tc.mu.RUnlock() + return tc.sidecarDnsTemplate, tc.sidecarDnsTemplateVersion +} + +// GetSidecarJavaAgentTemplateAndVersion 获取sidecar java agent 注入配置模板 +func (tc *SafeTemplateConfig) GetSidecarJavaAgentTemplateAndVersion() (*TemplateConfig, string) { + tc.mu.RLock() + defer tc.mu.RUnlock() + return tc.sidecarJavaAgentTemplate, tc.sidecarJavaAgentTemplateVersion +} + +// GetCert 获取证书 +func (tc *SafeTemplateConfig) GetCert(*tls.ClientHelloInfo) (*tls.Certificate, error) { + tc.mu.RLock() + defer tc.mu.RUnlock() + return tc.cert, nil +} + +// GetMeshEnvoyConfig returns the mesh envoy configuration in a thread-safe way +func (s *SafeTemplateConfig) GetMeshEnvoyConfig() *mesh.MeshEnvoyConfig { + s.mu.RLock() + defer s.mu.RUnlock() + return s.meshEnvoyConfig +} + +// SetMeshEnvoyConfig sets the mesh envoy configuration in a thread-safe way +func (s *SafeTemplateConfig) SetMeshEnvoyConfigWithKV(k, v string) { + s.mu.Lock() + defer s.mu.Unlock() + s.meshEnvoyConfig.SetProxyMetadataWithKV(k, v) +} + +// GetValuesConfig returns the values configuration in a thread-safe way +func (s *SafeTemplateConfig) GetValuesConfig() string { + s.mu.RLock() + defer s.mu.RUnlock() + return s.valuesConfig +} diff --git a/pkg/inject/pkg/config/template_file.go b/pkg/inject/pkg/config/template_file.go new file mode 100644 index 00000000..055fd2e3 --- /dev/null +++ b/pkg/inject/pkg/config/template_file.go @@ -0,0 +1,127 @@ +package config + +import ( + "crypto/sha256" + "crypto/tls" + "os" + "strings" + + gyaml "github.com/ghodss/yaml" + + "github.com/polarismesh/polaris-controller/common/log" + "github.com/polarismesh/polaris-controller/pkg/inject/pkg/config/mesh" +) + +type TemplateFileConfig struct { + // MeshConfigFile 处理 polaris-sidecar 运行模式为 mesh 的配置文件 + MeshConfigFile string + + // DnsConfigFile 处理 polaris-sidecar 运行模式为 dns 的配置文件 + DnsConfigFile string + + // JavaAgentConfigFile 处理运行模式为 javaagent 的配置文件 + JavaAgentConfigFile string + + ValuesFile string + + // BootstrapConfigFile is the path to the mesh configuration file. + BootstrapConfigFile string + + // CertFile is the path to the x509 certificate for https. + CertFile string + + // KeyFile is the path to the x509 private key matching `CertFile`. + KeyFile string +} + +// env will be used for other things besides meshEnvoyConfig - when webhook is running in Istiod it can take advantage +// of the config and endpoint cache. +// nolint +func loadConfig(p TemplateFileConfig) (*InjectConfigInfo, error) { + // 读取 mesh envoy模式的配置模板 + meshData, err := os.ReadFile(p.MeshConfigFile) + if err != nil { + return nil, err + } + var meshConf TemplateConfig + if err := gyaml.Unmarshal(meshData, &meshConf); err != nil { + log.InjectScope().Warnf("Failed to parse inject mesh config file %s", string(meshData)) + return nil, err + } + log.InjectScope().Infof("[MESH] New inject configuration: sha256sum %x", sha256.Sum256(meshData)) + log.InjectScope().Infof("[MESH] Policy: %v", meshConf.Policy) + log.InjectScope().Infof("[MESH] AlwaysInjectSelector: %v", meshConf.AlwaysInjectSelector) + log.InjectScope().Infof("[MESH] NeverInjectSelector: %v", meshConf.NeverInjectSelector) + log.InjectScope().Infof("[MESH] InjectedAnnotations: %v", meshConf.InjectedAnnotations) + log.InjectScope().Infof("[MESH] Template: |\n %v", strings.Replace(meshConf.Template, "\n", "\n ", -1)) + + // 读取 dns 模式的配置模板 + dnsData, err := os.ReadFile(p.DnsConfigFile) + if err != nil { + return nil, err + } + var dnsConf TemplateConfig + if err := gyaml.Unmarshal(dnsData, &dnsConf); err != nil { + log.InjectScope().Warnf("Failed to parse inject dns config file %s", string(dnsData)) + return nil, err + } + log.InjectScope().Infof("[DNS] New inject configuration: sha256sum %x", sha256.Sum256(dnsData)) + log.InjectScope().Infof("[DNS] Policy: %v", dnsConf.Policy) + log.InjectScope().Infof("[DNS] AlwaysInjectSelector: %v", dnsConf.AlwaysInjectSelector) + log.InjectScope().Infof("[DNS] NeverInjectSelector: %v", dnsConf.NeverInjectSelector) + log.InjectScope().Infof("[DNS] InjectedAnnotations: %v", dnsConf.InjectedAnnotations) + log.InjectScope().Infof("[DNS] Template: |\n %v", strings.Replace(dnsConf.Template, "\n", "\n ", -1)) + + // 读取 javaagent 模式的配置模板 + javaAgentData, err := os.ReadFile(p.JavaAgentConfigFile) + if err != nil { + return nil, err + } + var javaAgentConf TemplateConfig + if err := gyaml.Unmarshal(javaAgentData, &javaAgentConf); err != nil { + log.InjectScope().Warnf("Failed to parse inject java-agent config file %s", string(dnsData)) + return nil, err + } + log.InjectScope().Infof("[JavaAgent] New inject configuration: sha256sum %x", sha256.Sum256(javaAgentData)) + log.InjectScope().Infof("[JavaAgent] Policy: %v", javaAgentConf.Policy) + log.InjectScope().Infof("[JavaAgent] AlwaysInjectSelector: %v", javaAgentConf.AlwaysInjectSelector) + log.InjectScope().Infof("[JavaAgent] NeverInjectSelector: %v", javaAgentConf.NeverInjectSelector) + log.InjectScope().Infof("[JavaAgent] InjectedAnnotations: %v", javaAgentConf.InjectedAnnotations) + log.InjectScope().Infof("[JavaAgent] Template: |\n %v", strings.Replace(javaAgentConf.Template, "\n", "\n ", -1)) + + // 读取 values + valuesConfig, err := os.ReadFile(p.ValuesFile) + if err != nil { + return nil, err + } + log.InjectScope().Infof("[ValuesConfig] New inject configuration: sha256sum %x", sha256.Sum256(valuesConfig)) + + // 读取 inject 配置 + meshEnvoyConfig, err := mesh.ReadMeshEnvoyConfig(p.BootstrapConfigFile) + if err != nil { + return nil, err + } + log.InjectScope().Infof("[MeshEnvoyConfig] New inject configuration: sha256sum %x", sha256.Sum256([]byte( + meshEnvoyConfig.String()))) + + // 读取 TLS 证书 + pair, err := tls.LoadX509KeyPair(p.CertFile, p.KeyFile) + if err != nil { + log.InjectScope().Errorf("Failed to load TLS certificate: %v", err) + return nil, err + } + log.InjectScope().Infof("[X509KeyPair] New inject configuration: sha256sum %x", sha256.Sum256(javaAgentData)) + + return &InjectConfigInfo{ + MeshInjectConf: &meshConf, + DnsInjectConf: &dnsConf, + JavaAgentInjectConf: &javaAgentConf, + MeshEnvoyConf: meshEnvoyConfig, + ValuesConf: string(valuesConfig), + CertPair: &pair, + }, nil +} + +func (p TemplateFileConfig) GetWatchList() []string { + return []string{p.MeshConfigFile, p.DnsConfigFile, p.JavaAgentConfigFile, p.CertFile, p.KeyFile} +} diff --git a/pkg/inject/pkg/kube/inject/apply/javaagent/patch.go b/pkg/inject/pkg/kube/inject/apply/javaagent/patch.go index 48235be4..694889da 100644 --- a/pkg/inject/pkg/kube/inject/apply/javaagent/patch.go +++ b/pkg/inject/pkg/kube/inject/apply/javaagent/patch.go @@ -37,10 +37,9 @@ import ( // Java Agent 场景下的特殊 annonations 信息 const ( - customJavaAgentVersion = "polarismesh.cn/javaagentVersion" - customJavaAgentPluginFramework = "polarismesh.cn/javaagentFrameworkName" - customJavaAgentPluginFrameworkVersion = "polarismesh.cn/javaagentFrameworkVersion" - customJavaAgentPluginConfig = "polarismesh.cn/javaagentConfig" + envJavaAgentPluginType = "JAVA_AGENT_PLUGIN_TYPE" + envJavaAgentFrameworkName = "JAVA_AGENT_FRAMEWORK_NAME" + envJavaAgentFrameworkVersion = "JAVA_AGENT_FRAMEWORK_VERSION" ) var oldAgentVersions = map[string]struct{}{ @@ -56,6 +55,8 @@ var oldAgentVersions = map[string]struct{}{ const ( ActiveJavaAgentCmd = "-javaagent:/app/lib/.polaris/java_agent/polaris-java-agent/polaris-agent-core-bootstrap.jar" OldActiveJavaAgentCmd = "-javaagent:/app/lib/.polaris/java_agent/polaris-java-agent-%s/polaris-agent-core-bootstrap.jar" + + javaagentInitContainer = "polaris-javaagent-init" ) func init() { @@ -75,9 +76,9 @@ func (pb *PodPatchBuilder) PatchContainer(req *inject.OperateContainerRequest) ( pod := req.Option.Pod added := req.External for index, add := range added { - if add.Name == "polaris-javaagent-init" { + if add.Name == javaagentInitContainer { log.InjectScope().Infof("begin deal polaris-javaagent-init inject for pod=[%s, %s]", pod.Namespace, pod.Name) - if err := pb.handleJavaAgentInit(req.Option, pod, &add); err != nil { + if err := pb.handleJavaAgentInit(req, &add); err != nil { log.InjectScope().Errorf("handle polaris-javaagent-init inject for pod=[%s, %s] failed: %v", pod.Namespace, pod.Name, err) } } @@ -88,32 +89,34 @@ func (pb *PodPatchBuilder) PatchContainer(req *inject.OperateContainerRequest) ( log.InjectScope().Infof("finish deal polaris-javaagent-init inject for pod=[%s, %s] added: %#v", pod.Namespace, pod.Name, added) return pb.PodPatchBuilder.PatchContainer(req) case inject.PatchType_Update: - return pb.updateContainer(req.Option, req.Option.SidecarMode, req.Option.Pod, req.Option.Pod.Spec.Containers, req.BasePath), nil + return pb.updateContainer(req), nil } return nil, nil } -func (pb *PodPatchBuilder) handleJavaAgentInit(opt *inject.PatchOptions, pod *corev1.Pod, add *corev1.Container) error { +func (pb *PodPatchBuilder) handleJavaAgentInit(req *inject.OperateContainerRequest, add *corev1.Container) error { + pod := req.Option.Pod + opt := req.Option annonations := pod.Annotations log.InjectScope().Infof("handle polaris-javaagent-init inject for pod=[%s, %s] annonations: %#v image: %s", pod.Namespace, pod.Name, pod.Annotations, add.Image) // 判断用户是否自定义了 javaagent 的版本 oldImageInfo := strings.Split(add.Image, ":") if len(oldImageInfo) > 1 { - opt.ExternalInfo[customJavaAgentVersion] = oldImageInfo[1] + opt.ExternalInfo[utils.AnnotationKeyJavaAgentVersion] = oldImageInfo[1] } - if val, ok := annonations[customJavaAgentVersion]; ok && val != "" { + if val, ok := annonations[utils.AnnotationKeyJavaAgentVersion]; ok && val != "" { add.Image = fmt.Sprintf("%s:%s", oldImageInfo[0], val) - opt.ExternalInfo[customJavaAgentVersion] = val + opt.ExternalInfo[utils.AnnotationKeyJavaAgentVersion] = val } - frameworkName, frameworkNameOk := annonations[customJavaAgentPluginFramework] + frameworkName, frameworkNameOk := annonations[utils.AnnotationKeyJavaAgentPluginFramework] if !frameworkNameOk { log.InjectScope().Warnf("handle polaris-javaagent-init inject for pod=[%s, %s] not found frameworkName", pod.Namespace, pod.Name) } - frameworkVersion, frameworkVersionOk := annonations[customJavaAgentPluginFrameworkVersion] + frameworkVersion, frameworkVersionOk := annonations[utils.AnnotationKeyJavaAgentPluginFrameworkVersion] if !frameworkVersionOk { log.InjectScope().Warnf("handle polaris-javaagent-init inject for pod=[%s, %s] not found frameworkVersion", pod.Namespace, pod.Name) @@ -122,25 +125,26 @@ func (pb *PodPatchBuilder) handleJavaAgentInit(opt *inject.PatchOptions, pod *co pluginType := frameworkName + frameworkVersion if frameworkName != "" && frameworkVersion != "" { add.Env = append(add.Env, corev1.EnvVar{ - Name: "JAVA_AGENT_PLUGIN_TYPE", + Name: envJavaAgentPluginType, Value: pluginType, }) add.Env = append(add.Env, corev1.EnvVar{ - Name: "JAVA_AGENT_FRAMEWORK_NAME", + Name: envJavaAgentFrameworkName, Value: frameworkName, }) add.Env = append(add.Env, corev1.EnvVar{ - Name: "JAVA_AGENT_FRAMEWORK_VERSION", + Name: envJavaAgentFrameworkVersion, Value: frameworkVersion, }) } defaultParam := map[string]string{ - "MicroserviceName": opt.Annotations[util.SidecarServiceName], - "PolarisServerIP": strings.Split(polarisapi.PolarisGrpc, ":")[0], - "PolarisDiscoverPort": strings.Split(polarisapi.PolarisGrpc, ":")[1], - "PolarisConfigIP": strings.Split(polarisapi.PolarisConfigGrpc, ":")[0], - "PolarisConfigPort": strings.Split(polarisapi.PolarisConfigGrpc, ":")[1], + "MicroserviceNamespace": getServiceNamespace(opt), + "MicroserviceName": opt.Annotations[util.SidecarServiceName], + "PolarisServerIP": strings.Split(polarisapi.PolarisGrpc, ":")[0], + "PolarisDiscoverPort": strings.Split(polarisapi.PolarisGrpc, ":")[1], + "PolarisConfigIP": strings.Split(polarisapi.PolarisConfigGrpc, ":")[0], + "PolarisConfigPort": strings.Split(polarisapi.PolarisConfigGrpc, ":")[1], } add.Env = append(add.Env, @@ -168,6 +172,7 @@ func (pb *PodPatchBuilder) handleJavaAgentInit(opt *inject.PatchOptions, pod *co defaultProperties := make(map[string]string) // 判断是不是老版本,如果是老版本且客户填写的版本号不为空则走老的逻辑,否则走新的逻辑,只下发北极星的地址和端口信息 newImageInfo := strings.Split(add.Image, ":") + // RC5之前的版本走的逻辑, 向前兼容 if _, valid := oldAgentVersions[newImageInfo[1]]; valid { kubeClient := opt.KubeClient pluginCm, err := kubeClient.CoreV1().ConfigMaps(util.RootNamespace).Get(context.Background(), @@ -195,15 +200,23 @@ func (pb *PodPatchBuilder) handleJavaAgentInit(opt *inject.PatchOptions, pod *co } } } - // 查看用户是否自定义了相关配置信息 + // 查看用户是否自定义了相关配置信息, 优先级最高 // 需要根据用户的自定义参数信息,将 agent 的特定 application.properties 文件注入到 javaagent-init 中 - if properties, ok := annonations[customJavaAgentPluginConfig]; ok { + if properties, ok := annonations[utils.AnnotationKeyJavaAgentPluginConfig]; ok { customProperties := map[string]string{} if err := json.Unmarshal([]byte(properties), &customProperties); err != nil { return err } // 先从 configmap 中获取 java-agent 不同 plugin-type 的默认配置信息 for k, v := range customProperties { + if defaultValue, defaultExist := defaultProperties[k]; defaultExist { + if defaultValue != v { + log.InjectScope().Infof("handle polaris-javaagent-init inject for pod=[%s, %s] "+ + "customProperties[%s]=%s should replace defaultProperties[%s]=%s", + pod.Namespace, pod.Name, k, v, k, defaultValue) + } + } + // 当和默认初始化配置存在冲突时,使用用户自定义配置 defaultProperties[k] = v } } @@ -221,6 +234,33 @@ func (pb *PodPatchBuilder) handleJavaAgentInit(opt *inject.PatchOptions, pod *co return nil } +func getDefaultProperties(opt *inject.PatchOptions) map[string]string { + defaultProperties := make(map[string]string) + if useWorkloadNS, ok := opt.Pod.Annotations[utils.AnnotationKeyWorkloadNamespaceAsServiceNamespace]; ok && + useWorkloadNS == utils.InjectionValueTrue { + log.InjectScope().Infof("handle polaris-javaagent-init inject for pod=[%s, %s] useWorkloadNS=%s", + opt.Pod.Namespace, opt.Pod.Name, useWorkloadNS) + defaultProperties[ServiceNamespaceValueFromKey] = opt.Pod.Namespace + } + if useWorkloadName, ok := opt.Pod.Annotations[utils.AnnotationKeyWorkloadNameAsServiceName]; ok && + useWorkloadName == utils.InjectionValueTrue { + log.InjectScope().Infof("handle polaris-javaagent-init inject for pod=[%s, %s] useWorkloadName=%s", + opt.Pod.Namespace, opt.Pod.Name, opt.WorkloadName) + defaultProperties[ServiceNameValueFromKey] = opt.WorkloadName + } + return defaultProperties +} + +func getServiceNamespace(opt *inject.PatchOptions) string { + if useWorkloadNS, ok := opt.Pod.Annotations[utils.AnnotationKeyWorkloadNamespaceAsServiceNamespace]; ok && + useWorkloadNS == utils.InjectionValueTrue { + log.InjectScope().Infof("handle polaris-javaagent-init inject for pod=[%s, %s] useWorkloadNS=%s", + opt.Pod.Namespace, opt.Pod.Name, useWorkloadNS) + return opt.Pod.Namespace + } + return "default" +} + func nameOfPluginDefault(v string) string { return v + "-default-properties" } @@ -232,44 +272,56 @@ func updateJavaEnvVar(envVar corev1.EnvVar, cmd string, version string) corev1.E } } -func (pb *PodPatchBuilder) updateContainer(opt *inject.PatchOptions, sidecarMode utils.SidecarMode, pod *corev1.Pod, - target []corev1.Container, basePath string) []inject.Rfc6902PatchOperation { +const ( + ServiceNameValueFromKey = "spring.application.name" + ServiceNamespaceValueFromKey = "spring.cloud.polaris.discovery.namespace" +) - patchs := make([]inject.Rfc6902PatchOperation, 0, len(target)) +func (pb *PodPatchBuilder) updateContainer(req *inject.OperateContainerRequest) []inject.Rfc6902PatchOperation { + opt := req.Option + pod := req.Option.Pod + target := req.Option.Pod.Spec.Containers + basePath := req.BasePath + patches := make([]inject.Rfc6902PatchOperation, 0, len(target)) - annonations := pod.Annotations - if val, ok := annonations[customJavaAgentVersion]; ok && val != "" { - opt.ExternalInfo[customJavaAgentVersion] = val + // 判断用户是否自定义了 javaagent 的版本 + if val, ok := pod.Annotations[utils.AnnotationKeyJavaAgentVersion]; ok && val != "" { + opt.ExternalInfo[utils.AnnotationKeyJavaAgentVersion] = val } else { - annonations[customJavaAgentVersion] = "latest" + pod.Annotations[utils.AnnotationKeyJavaAgentVersion] = "latest" } - defaultProperties := make(map[string]string) - var javaToolOptionsValue string - + // 初始化默认配置和用户自定义配置 + defaultProperties := getDefaultProperties(opt) for index, container := range target { envs := container.Env javaEnvIndex := -1 - if _, valid := oldAgentVersions[annonations[customJavaAgentVersion]]; !valid { - if properties, ok := annonations[customJavaAgentPluginConfig]; ok { - customProperties := map[string]string{} - if properties != "" { - if err := json.Unmarshal([]byte(properties), &customProperties); err != nil { - log.InjectScope().Errorf("updateContainer for pod=[%s, %s] json error: %+v", pod.Namespace, - pod.Name, err) - } + if properties, ok := pod.Annotations[utils.AnnotationKeyJavaAgentPluginConfig]; ok { + customProperties := map[string]string{} + if properties != "" { + if err := json.Unmarshal([]byte(properties), &customProperties); err != nil { + log.InjectScope().Errorf("updateContainer for pod=[%s, %s] json error: %+v", pod.Namespace, + pod.Name, err) } - // 先从 configmap 中获取 java-agent 不同 plugin-type 的默认配置信息 - for k, v := range customProperties { - defaultProperties[k] = v + } + // 先从 configmap 中获取 java-agent 不同 plugin-type 的默认配置信息 + for k, v := range customProperties { + if existsValue, exists := defaultProperties[k]; exists { + if existsValue != v { + log.InjectScope().Errorf("updateContainer for pod=[%s, %s] customProperties[%s]=%s, "+ + "replace defaultProperties[%s]=%s", pod.Namespace, pod.Name, k, v, k, existsValue) + } } + // 当和默认初始化配置存在冲突时,使用用户自定义配置 + defaultProperties[k] = v } } + // 将配置转成-D参数, 并追加到JAVA_TOOL_OPTIONS + var javaToolOptionsValue string for key, value := range defaultProperties { javaToolOptionsValue += fmt.Sprintf(" -D%s=%s", key, value) } - if len(envs) != 0 { for i := range envs { if envs[i].Name == "JAVA_TOOL_OPTIONS" { @@ -277,21 +329,27 @@ func (pb *PodPatchBuilder) updateContainer(opt *inject.PatchOptions, sidecarMode break } } + // 环境变量 JAVA_TOOL_OPTIONS 已经存在, 往里面追加参数 if javaEnvIndex != -1 { - if _, valid := oldAgentVersions[annonations[customJavaAgentVersion]]; !valid { + // RC5之后的版本,不再需要javaagentVersion注解,自动识别版本号 + if _, valid := oldAgentVersions[pod.Annotations[utils.AnnotationKeyJavaAgentVersion]]; !valid { envs[javaEnvIndex] = updateJavaEnvVar(envs[javaEnvIndex], ActiveJavaAgentCmd, javaToolOptionsValue) } else { - envs[javaEnvIndex] = updateJavaEnvVar(envs[javaEnvIndex], fmt.Sprintf(OldActiveJavaAgentCmd, opt.ExternalInfo[customJavaAgentVersion]), "") + // RC5之前的版本,需要注入javaagentVersion注解,在-javaagent参数里面指定版本号 + envs[javaEnvIndex] = updateJavaEnvVar(envs[javaEnvIndex], fmt.Sprintf(OldActiveJavaAgentCmd, + opt.ExternalInfo[utils.AnnotationKeyJavaAgentVersion]), "") } } } + // 环境变量 JAVA_TOOL_OPTIONS 不存在, 新建 if javaEnvIndex == -1 { // 注入 java agent 需要用到的参数信息 var newEnvVar corev1.EnvVar - if _, valid := oldAgentVersions[annonations[customJavaAgentVersion]]; !valid { + if _, valid := oldAgentVersions[pod.Annotations[utils.AnnotationKeyJavaAgentVersion]]; !valid { newEnvVar = updateJavaEnvVar(corev1.EnvVar{}, ActiveJavaAgentCmd, javaToolOptionsValue) } else { - newEnvVar = updateJavaEnvVar(corev1.EnvVar{}, fmt.Sprintf(OldActiveJavaAgentCmd, opt.ExternalInfo[customJavaAgentVersion]), "") + newEnvVar = updateJavaEnvVar(corev1.EnvVar{}, fmt.Sprintf(OldActiveJavaAgentCmd, + opt.ExternalInfo[utils.AnnotationKeyJavaAgentVersion]), "") } container.Env = append(container.Env, newEnvVar) } @@ -302,16 +360,15 @@ func (pb *PodPatchBuilder) updateContainer(opt *inject.PatchOptions, sidecarMode Name: "java-agent-dir", MountPath: "/app/lib/.polaris/java_agent", }) - path := basePath path += "/" + strconv.Itoa(index) - patchs = append(patchs, inject.Rfc6902PatchOperation{ + patches = append(patches, inject.Rfc6902PatchOperation{ Op: "replace", Path: path, Value: container, }) } - return patchs + return patches } func (pb *PodPatchBuilder) PatchVolumes(req *inject.OperateVolumesRequest) ([]inject.Rfc6902PatchOperation, error) { diff --git a/pkg/inject/pkg/kube/inject/apply/javaagent/patch_test.go b/pkg/inject/pkg/kube/inject/apply/javaagent/patch_test.go new file mode 100644 index 00000000..cbe06365 --- /dev/null +++ b/pkg/inject/pkg/kube/inject/apply/javaagent/patch_test.go @@ -0,0 +1,335 @@ +package javaagent + +import ( + "testing" + + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/fake" + + "github.com/polarismesh/polaris-controller/pkg/inject/pkg/kube/inject" + "github.com/polarismesh/polaris-controller/pkg/inject/pkg/kube/inject/apply/base" + "github.com/polarismesh/polaris-controller/pkg/util" +) + +func TestUpdateContainer(t *testing.T) { + // 定义测试用例 + tests := []struct { + name string + pod *corev1.Pod + opt *inject.PatchOptions + expectedCmd string + expectMount bool + }{ + { + name: "旧版本使用的javaagent参数需要带版本号", + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-ns", + Annotations: map[string]string{ + util.AnnotationKeyJavaAgentVersion: "1.7.0-RC1", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Name: "main", + Env: []corev1.EnvVar{{ + Name: "JAVA_TOOL_OPTIONS", + Value: "-Xmx512m", + }}, + }}, + }, + }, + opt: &inject.PatchOptions{ + WorkloadName: "test-workload", + ExternalInfo: map[string]string{}, + Pod: &corev1.Pod{}, + }, + expectedCmd: "-Xmx512m -javaagent:/app/lib/.polaris/java_agent/polaris-java-agent-1.7.0-RC1/polaris-agent-core-bootstrap.jar", + expectMount: true, + }, + { + name: "使用k8s工作负载和命名空间作为服务空间和服务名", + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-ns", + Annotations: map[string]string{ + util.AnnotationKeyInjectJavaAgent: util.InjectionValueTrue, + util.AnnotationKeyWorkloadNameAsServiceName: util.InjectionValueTrue, + util.AnnotationKeyWorkloadNamespaceAsServiceNamespace: util.InjectionValueTrue, + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Name: "main", + Env: []corev1.EnvVar{}, + }}, + }, + }, + opt: &inject.PatchOptions{ + ExternalInfo: make(map[string]string), + WorkloadName: "test-workload", + Annotations: map[string]string{}, + Pod: &corev1.Pod{}, + }, + expectedCmd: "-javaagent:/app/lib/.polaris/java_agent/polaris-java-agent/polaris-agent-core-bootstrap.jar -Dspring.cloud.polaris.discovery.namespace=test-ns -Dspring.application.name=test-workload", + expectMount: true, + }, + { + name: "自定义服务名和使用k8s工作负载作为服务名有冲突,使用自定义的服务名", + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-ns", + Annotations: map[string]string{ + util.AnnotationKeyJavaAgentVersion: "v1.10.0", + util.AnnotationKeyWorkloadNameAsServiceName: util.InjectionValueTrue, + util.AnnotationKeyWorkloadNamespaceAsServiceNamespace: util.InjectionValueTrue, + util.AnnotationKeyJavaAgentPluginConfig: `{"spring.application.name":"custom-service","spring.cloud.polaris.discovery.namespace":"custom-ns"}`, + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Name: "main", + Env: []corev1.EnvVar{}, + }}, + }, + }, + opt: &inject.PatchOptions{ + ExternalInfo: make(map[string]string), + WorkloadName: "test-workload", + Annotations: map[string]string{}, + Pod: &corev1.Pod{}, + }, + expectedCmd: "-javaagent:/app/lib/.polaris/java_agent/polaris-java-agent/polaris-agent-core-bootstrap.jar -Dspring.cloud.polaris.discovery.namespace=custom-ns -Dspring.application.name=custom-service", + expectMount: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // 初始化测试环境 + pb := &PodPatchBuilder{ + PodPatchBuilder: &base.PodPatchBuilder{}, + } + + // 构建请求 + req := &inject.OperateContainerRequest{ + Option: tt.opt, + BasePath: "/spec/containers", + } + tt.opt.Pod = tt.pod + + // 执行测试 + patches := pb.updateContainer(req) + + // 验证结果 + assert.NotEmpty(t, patches, "should generate patches") + if len(patches) > 0 { + container := patches[0].Value.(corev1.Container) + + // 验证环境变量 + var javaToolOptions string + for _, env := range container.Env { + if env.Name == "JAVA_TOOL_OPTIONS" { + javaToolOptions = env.Value + break + } + } + assert.Contains(t, javaToolOptions, tt.expectedCmd, "JAVA_TOOL_OPTIONS mismatch") + + // 验证Volume Mount + if tt.expectMount { + assert.Len(t, container.VolumeMounts, 1, "should have volume mount") + assert.Equal(t, "java-agent-dir", container.VolumeMounts[0].Name) + } + + // 验证补丁操作 + assert.Equal(t, "replace", patches[0].Op, "patch operation should be replace") + } + + // 验证版本处理 + if version, ok := tt.pod.Annotations[util.AnnotationKeyJavaAgentVersion]; ok { + if _, isOld := oldAgentVersions[version]; isOld { + assert.Contains(t, tt.opt.ExternalInfo, util.AnnotationKeyJavaAgentVersion, + "should store version in external info for old agents") + } + } + }) + } +} + +func TestHandleJavaAgentInit(t *testing.T) { + // Mock 测试用的 ConfigMap + mockConfigMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "plugin-default.properties", + Namespace: util.RootNamespace, + }, + Data: map[string]string{ + "spring-cloud-default-properties": `spring.application.name={{.MicroserviceName}} +spring.cloud.polaris.discovery.namespace={{.MicroserviceNamespace}}`, + }, + } + + tests := []struct { + name string + podAnnotations map[string]string + initContainer *corev1.Container + expected func(t *testing.T, c *corev1.Container) + }{ + { + name: "default_image_version", + podAnnotations: map[string]string{}, + initContainer: &corev1.Container{ + Image: "polarismesh/polaris-java-agent-init:1.7.0-RC5", + }, + expected: func(t *testing.T, c *corev1.Container) { + assert.Equal(t, "polarismesh/polaris-java-agent-init:1.7.0-RC5", c.Image) + assertContainsEnv(t, c, "POLARIS_SERVER_IP") + assertContainsEnv(t, c, "POLARIS_DISCOVER_PORT") + }, + }, + { + name: "custom_image_version", + podAnnotations: map[string]string{ + util.AnnotationKeyJavaAgentVersion: "v1.8.0", + }, + initContainer: &corev1.Container{ + Image: "polarismesh/polaris-java-agent-init:1.7.0-RC5", + }, + expected: func(t *testing.T, c *corev1.Container) { + assert.Equal(t, "polarismesh/polaris-java-agent-init:v1.8.0", c.Image) + }, + }, + { + name: "old_version_with_configmap", + podAnnotations: map[string]string{ + util.AnnotationKeyJavaAgentVersion: "1.7.0-RC5", + util.AnnotationKeyJavaAgentPluginConfig: `{"logging.level":"DEBUG"}`, + util.AnnotationKeyJavaAgentPluginFramework: "spring-cloud", + }, + initContainer: &corev1.Container{ + Image: "polarismesh/polaris-java-agent-init:1.7.0-RC5", + }, + expected: func(t *testing.T, c *corev1.Container) { + // 验证环境变量 + var pluginConf string + for _, env := range c.Env { + if env.Name == "JAVA_AGENT_PLUGIN_CONF" { + pluginConf = env.Value + } + } + assert.Contains(t, pluginConf, "spring.application.name=test-service") + assert.Contains(t, pluginConf, "logging.level=DEBUG") + assert.Contains(t, pluginConf, "spring.cloud.polaris.discovery.namespace=default") + }, + }, + { + name: "使用k8s命名空间和工作负载名称注册", + podAnnotations: map[string]string{ + util.AnnotationKeyJavaAgentVersion: "1.7.0-RC5", + util.AnnotationKeyJavaAgentPluginConfig: `{"logging.level":"DEBUG"}`, + util.AnnotationKeyJavaAgentPluginFramework: "spring-cloud", + util.AnnotationKeyWorkloadNameAsServiceName: util.InjectionValueTrue, + util.AnnotationKeyWorkloadNamespaceAsServiceNamespace: util.InjectionValueTrue, + }, + initContainer: &corev1.Container{ + Image: "polarismesh/polaris-java-agent-init:1.7.0-RC5", + }, + expected: func(t *testing.T, c *corev1.Container) { + // 验证环境变量 + var pluginConf string + for _, env := range c.Env { + if env.Name == "JAVA_AGENT_PLUGIN_CONF" { + pluginConf = env.Value + } + } + assert.Contains(t, pluginConf, "spring.application.name=test-service") + assert.Contains(t, pluginConf, "logging.level=DEBUG") + assert.Contains(t, pluginConf, "spring.cloud.polaris.discovery.namespace=test-ns") + }, + }, + { + name: "使用k8s命名空间和工作负载名称注册,和自定义配置冲突,使用自定义配置", + podAnnotations: map[string]string{ + util.AnnotationKeyJavaAgentVersion: "1.7.0-RC5", + util.AnnotationKeyJavaAgentPluginConfig: `{"logging.level":"DEBUG","spring.cloud.polaris.discovery.namespace":"custom-ns","spring.application.name":"custom-service"}`, + util.AnnotationKeyJavaAgentPluginFramework: "spring-cloud", + util.AnnotationKeyWorkloadNameAsServiceName: util.InjectionValueTrue, + util.AnnotationKeyWorkloadNamespaceAsServiceNamespace: util.InjectionValueTrue, + }, + initContainer: &corev1.Container{ + Image: "polarismesh/polaris-java-agent-init:1.7.0-RC5", + }, + expected: func(t *testing.T, c *corev1.Container) { + // 验证环境变量 + var pluginConf string + for _, env := range c.Env { + if env.Name == "JAVA_AGENT_PLUGIN_CONF" { + pluginConf = env.Value + } + } + assert.Contains(t, pluginConf, "spring.application.name=custom-service") + assert.Contains(t, pluginConf, "logging.level=DEBUG") + assert.Contains(t, pluginConf, "spring.cloud.polaris.discovery.namespace=custom-ns") + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // 初始化fake client + client := fake.NewSimpleClientset(mockConfigMap) + + // 构建测试请求 + req := &inject.OperateContainerRequest{ + Option: &inject.PatchOptions{ + KubeClient: client, + Pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-ns", + Annotations: tt.podAnnotations, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Name: "main", + Image: "app:latest", + }}, + }, + }, + ExternalInfo: make(map[string]string), + WorkloadName: "test-service", + Annotations: map[string]string{util.SidecarServiceName: "test-service"}, + }, + External: []corev1.Container{*tt.initContainer}, + } + + pb := &PodPatchBuilder{ + PodPatchBuilder: &base.PodPatchBuilder{}, + } + + // 执行测试 + err := pb.handleJavaAgentInit(req, tt.initContainer) + + // 验证结果 + assert.NoError(t, err) + tt.expected(t, tt.initContainer) + + // 验证外部信息存储 + if version, ok := tt.podAnnotations[util.AnnotationKeyJavaAgentVersion]; ok { + assert.Equal(t, version, req.Option.ExternalInfo[util.AnnotationKeyJavaAgentVersion]) + } + }) + } +} + +// 辅助断言函数 +func assertContainsEnv(t *testing.T, container *corev1.Container, name string) { + for _, env := range container.Env { + if env.Name == name { + return + } + } + t.Errorf("Expected env %s not found", name) +} diff --git a/pkg/inject/pkg/kube/inject/apply/mesh/patch.go b/pkg/inject/pkg/kube/inject/apply/mesh/patch.go index 434fd604..ba6db0e9 100644 --- a/pkg/inject/pkg/kube/inject/apply/mesh/patch.go +++ b/pkg/inject/pkg/kube/inject/apply/mesh/patch.go @@ -81,6 +81,7 @@ func (pb *PodPatchBuilder) PatchContainer(req *inject.OperateContainerRequest) ( return pb.PodPatchBuilder.PatchContainer(req) } +// handlePolarisSidecarEnvInject 处理polaris-sidecar容器的环境变量 func (pb *PodPatchBuilder) handlePolarisSidecarEnvInject(opt *inject.PatchOptions, pod *corev1.Pod, add *corev1.Container) (bool, error) { err := pb.ensureRootCertExist(opt.KubeClient, pod) diff --git a/pkg/inject/pkg/kube/inject/base.go b/pkg/inject/pkg/kube/inject/base.go new file mode 100644 index 00000000..4901e5ef --- /dev/null +++ b/pkg/inject/pkg/kube/inject/base.go @@ -0,0 +1,114 @@ +package inject + +import ( + "fmt" + "strings" + "text/template" + + "github.com/ghodss/yaml" + "github.com/hashicorp/go-multierror" + + "github.com/polarismesh/polaris-controller/common/log" +) + +// getPodPatch 处理 admission webhook 请求 +// 返回值: +// +// patchBytes: []byte - 包含需要应用到资源上的 JSON patch 数据。如果不需要修改,则为 nil +// err: error - 处理过程中遇到的错误 +// - nil: 表示处理成功 +// - non-nil: 表示处理过程中出现错误,错误信息包含在 error 中 +func (wh *Webhook) getPodPatch(p *podDataInfo) ([]byte, error) { + // 检查Pod元数据是否合法 + passed, err := p.checkPodData() + if err != nil || !passed { + log.InjectScope().Errorf("[Webhook] skip due to checkPodData result:%v, error: %v", passed, err) + return nil, err + } + + // 检查Pod是否需要注入,过滤掉某些不需要注入的pod + if !wh.requireInject(p) { + skipReason := fmt.Sprintf("policy check failed for namespace=%s, podName=%s, injectConfig=%v", + p.podObject.Namespace, p.podName, p.injectTemplateConfig) + log.InjectScope().Infof("Skipping due to: %s", skipReason) + return nil, nil + } + + // 获取注入后的annotations + sidecarTemplate := p.injectTemplateConfig.Template + values := map[string]interface{}{} + valuesConfig := wh.templateConfig.GetValuesConfig() + if err := yaml.Unmarshal([]byte(wh.templateConfig.GetValuesConfig()), &values); err != nil { + log.InjectScope().Infof("[Webhook] failed to parse values config: %v [%v]\n", err, valuesConfig) + return nil, multierror.Prefix(err, "could not parse configuration values:") + } + metadataCopy := p.podObject.ObjectMeta.DeepCopy() + metadataCopy.Annotations = p.injectedAnnotations + templateData := SidecarTemplateData{ + TypeMeta: p.workloadType, + DeploymentMeta: p.workloadMeta, + ObjectMeta: metadataCopy, + Spec: &p.podObject.Spec, + ProxyConfig: wh.templateConfig.GetMeshEnvoyConfig().GetDefaultConfig(), + Values: values, + } + + funcMap := template.FuncMap{ + "formatDuration": formatDuration, + "isset": isset, + "excludeInboundPort": excludeInboundPort, + "includeInboundPorts": includeInboundPorts, + "kubevirtInterfaces": kubevirtInterfaces, + "applicationPorts": applicationPorts, + "annotation": getAnnotation, + "valueOrDefault": valueOrDefault, + "toJSON": toJSON, + "toJson": toJSON, // Used by, e.g. Istio 1.0.5 template sidecar-injector-configmap.yaml + "fromJSON": fromJSON, + "structToJSON": structToJSON, + "protoToJSON": protoToJSON, + "toYaml": toYaml, + "indent": indent, + "directory": directory, + "contains": flippedContains, + "toLower": strings.ToLower, + "openTlsMode": openTlsMode, + "env": env, + "render": render, + } + + bbuf, err := parseTemplate(sidecarTemplate, funcMap, templateData) + if err != nil { + return nil, err + } + + var injectData SidecarInjectionSpec + if err := yaml.Unmarshal(bbuf.Bytes(), &injectData); err != nil { + // This usually means an invalid injector template; we can't check + // the template itself because it is merely a string. + log.InjectScope().Warnf("Failed to unmarshal template %v \n%s", err, bbuf.String()) + return nil, multierror.Prefix(err, "failed parsing injected YAML (check sidecar injector configuration):") + } + + // set sidecar --concurrency + applyConcurrency(injectData.Containers) + injectStatus := p.addInjectStatusAnnotation(injectData) + // 生成POD修改的patch + opt := &PatchOptions{ + Pod: p.podObject, + KubeClient: wh.k8sClient, + PrevStatus: injectionStatus(p.podObject), + SidecarMode: p.injectMode, + WorkloadName: p.workloadMeta.Name, + Sic: &injectData, + Annotations: p.injectedAnnotations, + ExternalInfo: map[string]string{}, + } + patchBytes, err := createPatch(opt) + if err != nil { + log.InjectScope().Errorf(fmt.Sprintf("AdmissionResponse: err=%v injectStatus:%s injectData=%v\n", err, + injectStatus, injectData)) + return nil, err + } + return patchBytes, err +} diff --git a/pkg/inject/pkg/kube/inject/base_test.go b/pkg/inject/pkg/kube/inject/base_test.go new file mode 100644 index 00000000..c0ba313b --- /dev/null +++ b/pkg/inject/pkg/kube/inject/base_test.go @@ -0,0 +1,204 @@ +package inject + +import ( + "encoding/json" + "log" + "testing" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/polarismesh/polaris-controller/pkg/inject/api/annotation" + "github.com/polarismesh/polaris-controller/pkg/inject/pkg/config" + utils "github.com/polarismesh/polaris-controller/pkg/util" +) + +func TestRequireInject(t *testing.T) { + // 通用测试配置 + defaultTemplate := &config.TemplateConfig{ + NeverInjectSelector: []metav1.LabelSelector{{MatchLabels: map[string]string{ + utils.InjectAdmissionKey: utils.InjectAdmissionValueDisabled}}}, + AlwaysInjectSelector: []metav1.LabelSelector{{MatchLabels: map[string]string{ + utils.InjectAdmissionKey: utils.InjectAdmissionValueEnabled}}}, + InjectedAnnotations: map[string]string{utils.AnnotationKeyWorkloadNamespaceAsServiceNamespace: utils.InjectionValueTrue}, + Policy: config.InjectionPolicyEnabled, + } + str, _ := json.Marshal(defaultTemplate) + log.Printf("defaultTemplate: %s", str) + + // 参考istio官方定义 + // https://istio.io/latest/zh/docs/ops/common-problems/injection/ + testCases := []struct { + name string + podSetup func(*corev1.Pod, *config.TemplateConfig) + injectMode utils.SidecarMode + expected bool + }{ + { + name: "mesh类型,当启用HostNetwork时无需注入", + podSetup: func(p *corev1.Pod, _ *config.TemplateConfig) { + p.Spec.HostNetwork = true + }, + injectMode: utils.SidecarForMesh, + expected: false, + }, + { + name: "dns类型,当启用HostNetwork时无需注入", + podSetup: func(p *corev1.Pod, _ *config.TemplateConfig) { + p.Spec.HostNetwork = true + }, + injectMode: utils.SidecarForDns, + expected: false, + }, + { + name: "javaagent,当启用HostNetwork时不影响注入", + podSetup: func(p *corev1.Pod, _ *config.TemplateConfig) { + p.Spec.HostNetwork = true + }, + injectMode: utils.SidecarForJavaAgent, + expected: true, + }, + { + name: "在kube-system命名空间中跳过注入", + podSetup: func(p *corev1.Pod, _ *config.TemplateConfig) { + p.Namespace = "kube-system" + }, + expected: false, + }, + { + name: "Annotation白名单,当注解明确启用时应该注入", + podSetup: func(p *corev1.Pod, _ *config.TemplateConfig) { + p.Annotations = map[string]string{annotation.SidecarInject.Name: "true"} + }, + expected: true, + }, + { + name: "Annotation黑名单,当注解明确禁用时不注入", + podSetup: func(p *corev1.Pod, _ *config.TemplateConfig) { + p.Annotations = map[string]string{annotation.SidecarInject.Name: "false"} + }, + expected: false, + }, + { + name: "Label黑名单,当匹配NeverInjectSelector时不注入", + podSetup: func(p *corev1.Pod, _ *config.TemplateConfig) { + p.Labels = map[string]string{utils.InjectAdmissionKey: utils.InjectAdmissionValueDisabled} + }, + expected: false, + }, + { + name: "Label白名单功能,当匹配AlwaysInjectSelector时注入", + podSetup: func(p *corev1.Pod, _ *config.TemplateConfig) { + p.Labels = map[string]string{utils.InjectAdmissionKey: utils.InjectAdmissionValueEnabled} + }, + expected: true, + }, + { + name: "Policy白名单,默认策略启用时自动注入", + podSetup: func(p *corev1.Pod, defaultTemplate *config.TemplateConfig) { + defaultTemplate.Policy = config.InjectionPolicyEnabled + }, + expected: true, + }, + { + name: "Policy黑名单,默认策略禁用时不注入", + podSetup: func(p *corev1.Pod, defaultTemplate *config.TemplateConfig) { + defaultTemplate.Policy = config.InjectionPolicyDisabled + }, + expected: false, + }, + { + name: "Annotation白名单,Label黑名单,注入", + podSetup: func(p *corev1.Pod, _ *config.TemplateConfig) { + p.Annotations = map[string]string{annotation.SidecarInject.Name: "true"} + p.Labels = map[string]string{utils.InjectAdmissionKey: utils.InjectAdmissionValueDisabled} + }, + expected: true, + }, + { + name: "Annotation白名单,Policy黑名单,注入", + podSetup: func(p *corev1.Pod, defaultTemplate *config.TemplateConfig) { + p.Annotations = map[string]string{annotation.SidecarInject.Name: "true"} + defaultTemplate.Policy = config.InjectionPolicyDisabled + }, + expected: true, + }, + { + name: "Annotation黑名单,Label白名单,不注入", + podSetup: func(p *corev1.Pod, _ *config.TemplateConfig) { + p.Annotations = map[string]string{annotation.SidecarInject.Name: "false"} + p.Labels = map[string]string{utils.InjectAdmissionKey: utils.InjectAdmissionValueEnabled} + }, + expected: false, + }, + { + name: "Annotation黑名单,Policy白名单,不注入", + podSetup: func(p *corev1.Pod, _ *config.TemplateConfig) { + p.Annotations = map[string]string{annotation.SidecarInject.Name: "false"} + defaultTemplate.Policy = config.InjectionPolicyEnabled + }, + expected: false, + }, + { + name: "Label白名单功能,Policy黑名单,注入", + podSetup: func(p *corev1.Pod, defaultTemplate *config.TemplateConfig) { + p.Labels = map[string]string{utils.InjectAdmissionKey: utils.InjectAdmissionValueEnabled} + defaultTemplate.Policy = config.InjectionPolicyDisabled + }, + expected: true, + }, + { + name: "Label黑名单,Policy白名单,不注入", + podSetup: func(p *corev1.Pod, defaultTemplate *config.TemplateConfig) { + p.Labels = map[string]string{utils.InjectAdmissionKey: utils.InjectAdmissionValueDisabled} + defaultTemplate.Policy = config.InjectionPolicyEnabled + }, + expected: false, + }, + { + name: "Policy为空,默认策略为空时,完全禁止注入", + podSetup: func(p *corev1.Pod, defaultTemplate *config.TemplateConfig) { + defaultTemplate.Policy = "" + }, + expected: false, + }, + { + name: "Policy为空,尽管Annotation白名单,仍会禁止注入", + podSetup: func(p *corev1.Pod, defaultTemplate *config.TemplateConfig) { + p.Annotations = map[string]string{annotation.SidecarInject.Name: "true"} + defaultTemplate.Policy = "" + }, + expected: false, + }, + } + + wh := &Webhook{} + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pod", + Namespace: "default", + Annotations: make(map[string]string), + Labels: make(map[string]string), + }, + Spec: corev1.PodSpec{}, + } + if tc.podSetup != nil { + tc.podSetup(pod, defaultTemplate) + } + + podInfo := &podDataInfo{ + podObject: pod, + injectMode: tc.injectMode, + injectTemplateConfig: defaultTemplate, + podName: pod.Name, + } + + result := wh.requireInject(podInfo) + if result != tc.expected { + t.Errorf("%s: 期望 %v 但得到 %v", tc.name, tc.expected, result) + } + }) + } +} diff --git a/pkg/inject/pkg/kube/inject/common.go b/pkg/inject/pkg/kube/inject/common.go new file mode 100644 index 00000000..92f8638f --- /dev/null +++ b/pkg/inject/pkg/kube/inject/common.go @@ -0,0 +1,139 @@ +package inject + +import ( + "context" + "strings" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/polarismesh/polaris-controller/common/log" + utils "github.com/polarismesh/polaris-controller/pkg/util" +) + +// getInjectMode determines the injection mode for the pod based on annotations and namespace labels. +// The priority order is: +// 1. Pod annotations for Java agent mode +// 2. Pod annotations for Mesh mode +// 3. Pod annotations for custom sidecar mode +// 4. Namespace labels +// 5. Default sidecar mode from webhook configuration +func getInjectMode(wh *Webhook, p *podDataInfo) utils.SidecarMode { + pod := p.podObject + namespace := pod.Namespace + + // Check injection mode by priority + switch { + case isJavaAgentMode(pod.Annotations): + log.InjectScope().Infof("inject pod namespace %q mode is java agent", namespace) + return utils.SidecarForJavaAgent + case isMeshMode(pod.Annotations): + log.InjectScope().Infof("inject pod namespace %q mode is mesh envoy", namespace) + setMeshEnvoyConfig(wh, pod.Annotations) + return utils.SidecarForMesh + case hasSidecarModeAnnotation(pod.Annotations): + return utils.ParseSidecarMode(pod.Annotations[utils.PolarisSidecarMode]) + } + + return getNamespaceInjectMode(wh, namespace) +} + +// isJavaAgentMode checks if the pod should use Java agent injection mode +func isJavaAgentMode(annotations map[string]string) bool { + val, ok := annotations[utils.AnnotationKeyInjectJavaAgent] + return ok && val == utils.InjectionValueTrue +} + +// isMeshMode checks if the pod should use Mesh injection mode +func isMeshMode(annotations map[string]string) bool { + val, ok := annotations[utils.SidecarEnvoyInjectKey] + return ok && val == utils.InjectionValueTrue +} + +// hasSidecarModeAnnotation checks if the pod has custom sidecar mode annotation +func hasSidecarModeAnnotation(annotations map[string]string) bool { + _, ok := annotations[utils.PolarisSidecarMode] + return ok +} + +// setMeshEnvoyConfig sets the Mesh Envoy configuration metadata +func setMeshEnvoyConfig(wh *Webhook, annotations map[string]string) { + wh.templateConfig.SetMeshEnvoyConfigWithKV(utils.SidecarEnvoyInjectProxyKey, + annotations[utils.SidecarEnvoyInjectKey]) +} + +// getNamespaceInjectMode gets injection mode from namespace labels or returns default mode +func getNamespaceInjectMode(wh *Webhook, namespace string) utils.SidecarMode { + ns, err := wh.k8sClient.CoreV1().Namespaces().Get(context.TODO(), namespace, metav1.GetOptions{}) + if err != nil { + log.InjectScope().Errorf("get pod namespace %q failed: %v", namespace, err) + return wh.defaultSidecarMode + } + + if val, ok := ns.Labels[utils.PolarisSidecarModeLabel]; ok { + return utils.ParseSidecarMode(val) + } + return wh.defaultSidecarMode +} + +const ( + workloadDeployment = "Deployment" + workloadReplicaSet = "ReplicaSet" + + podTemplateHashLabel = "pod-template-hash" +) + +// getOwnerMetaAndType 获取Pod创建对象的元数据和类型信息 +func getOwnerMetaAndType(pod *corev1.Pod) (*metav1.ObjectMeta, *metav1.TypeMeta) { + deployMeta := pod.ObjectMeta.DeepCopy() + typeMetadata := &metav1.TypeMeta{ + Kind: "Pod", + APIVersion: "v1", + } + + // 如果不是通过Controller创建的Pod,直接返回Pod的元数据 + if len(pod.GenerateName) == 0 { + return deployMeta, typeMetadata + } + + // 获取Pod的Controller引用 + controllerRef := findControllerRef(pod.GetOwnerReferences()) + if controllerRef.Name == "" { + return deployMeta, typeMetadata + } + + // 更新类型元数据为Controller的信息 + typeMetadata.APIVersion = controllerRef.APIVersion + typeMetadata.Kind = controllerRef.Kind + + // 处理Deployment特殊场景 + if isDeploymentReplicaSet(typeMetadata.Kind, controllerRef.Name, pod.Labels) { + deployMeta.Name = getDeploymentName(controllerRef.Name, pod.Labels[podTemplateHashLabel]) + typeMetadata.Kind = workloadDeployment + } else { + deployMeta.Name = controllerRef.Name + } + + return deployMeta, typeMetadata +} + +// findControllerRef 从OwnerReferences中查找Pod的Controller引用 +func findControllerRef(refs []metav1.OwnerReference) metav1.OwnerReference { + for _, ref := range refs { + if ref.Controller != nil && *ref.Controller { + return ref + } + } + return metav1.OwnerReference{} +} + +// isDeploymentReplicaSet 判断是否为Deployment创建的ReplicaSet +func isDeploymentReplicaSet(kind, name string, labels map[string]string) bool { + return kind == workloadReplicaSet && labels[podTemplateHashLabel] != "" && + strings.HasSuffix(name, labels[podTemplateHashLabel]) +} + +// getDeploymentName 从ReplicaSet名称中提取Deployment名称 +func getDeploymentName(replicaSetName, podTemplateHash string) string { + return strings.TrimSuffix(replicaSetName, "-"+podTemplateHash) +} diff --git a/pkg/inject/pkg/kube/inject/inject.go b/pkg/inject/pkg/kube/inject/inject.go index b22f6c94..abe26bbd 100644 --- a/pkg/inject/pkg/kube/inject/inject.go +++ b/pkg/inject/pkg/kube/inject/inject.go @@ -15,34 +15,18 @@ package inject import ( - "bytes" - "context" - "crypto/sha256" - "encoding/hex" - "encoding/json" "fmt" - "net" - "os" - "path" - "strconv" "strings" - "text/template" - "github.com/ghodss/yaml" - "github.com/gogo/protobuf/jsonpb" - "github.com/gogo/protobuf/proto" - "github.com/gogo/protobuf/types" "github.com/hashicorp/go-multierror" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "github.com/polarismesh/polaris-controller/common/log" "github.com/polarismesh/polaris-controller/pkg/inject/api/annotation" + "github.com/polarismesh/polaris-controller/pkg/inject/pkg/config" "github.com/polarismesh/polaris-controller/pkg/inject/pkg/config/mesh" - "github.com/polarismesh/polaris-controller/pkg/util" utils "github.com/polarismesh/polaris-controller/pkg/util" ) @@ -54,7 +38,7 @@ var ( return nil } - annotationRegistry = map[string]annotationValidationFunc{ + annotationRegistryForMesh = map[string]annotationValidationFunc{ annotation.SidecarInject.Name: alwaysValidFunc, annotation.SidecarStatus.Name: alwaysValidFunc, annotation.SidecarRewriteAppHTTPProbers.Name: alwaysValidFunc, @@ -76,10 +60,28 @@ var ( annotation.SidecarTrafficIncludeInboundPorts.Name: ValidateIncludeInboundPorts, annotation.SidecarTrafficExcludeInboundPorts.Name: ValidateExcludeInboundPorts, annotation.SidecarTrafficExcludeOutboundPorts.Name: ValidateExcludeOutboundPorts, + utils.InjectAdmissionKey: alwaysValidFunc, + } + + annotationRegistryForDns = map[string]annotationValidationFunc{ + annotation.SidecarInject.Name: alwaysValidFunc, + annotation.SidecarStatus.Name: alwaysValidFunc, + utils.InjectAdmissionKey: alwaysValidFunc, + } + + annotationRegistryForJavaAgent = map[string]annotationValidationFunc{ + utils.AnnotationKeyJavaAgentVersion: alwaysValidFunc, + utils.AnnotationKeyJavaAgentPluginFramework: alwaysValidFunc, + utils.AnnotationKeyJavaAgentPluginFrameworkVersion: alwaysValidFunc, + utils.AnnotationKeyJavaAgentPluginConfig: alwaysValidFunc, + annotation.SidecarInject.Name: alwaysValidFunc, + annotation.SidecarStatus.Name: alwaysValidFunc, + utils.InjectAdmissionKey: alwaysValidFunc, } ) -func validateAnnotations(annotations map[string]string) (err error) { +func validateAnnotations(injectMode utils.SidecarMode, annotations map[string]string) (err error) { + annotationRegistry := getAnnotationRegistry(injectMode) for name, value := range annotations { if v, ok := annotationRegistry[name]; ok { if e := v(value); e != nil { @@ -90,26 +92,6 @@ func validateAnnotations(annotations map[string]string) (err error) { return } -// InjectionPolicy determines the policy for injecting the -// sidecar proxy into the watched namespace(s). -type InjectionPolicy string - -const ( - // InjectionPolicyDisabled specifies that the sidecar injector - // will not inject the sidecar into resources by default for the - // namespace(s) being watched. Resources can enable injection - // using the "sidecar.polarismesh.cn/inject" annotation with value of - // true. - InjectionPolicyDisabled InjectionPolicy = "disabled" - - // InjectionPolicyEnabled specifies that the sidecar injector will - // inject the sidecar into resources by default for the - // namespace(s) being watched. Resources can disable injection - // using the "sidecar.polarismesh.cn/inject" annotation with value of - // false. - InjectionPolicyEnabled InjectionPolicy = "enabled" -) - const ( // ProxyContainerName is used by e2e integration tests for fetching logs ProxyContainerName = "polaris-proxy" @@ -140,709 +122,148 @@ type SidecarTemplateData struct { Values map[string]interface{} } -// Config specifies the sidecar injection configuration This includes -// the sidecar template and cluster-side injection policy. It is used -// by kube-inject, sidecar injector, and http endpoint. -type Config struct { - Policy InjectionPolicy `json:"policy"` - - // Template is the templated version of `SidecarInjectionSpec` prior to - // expansion over the `SidecarTemplateData`. - Template string `json:"template"` - - // NeverInjectSelector: Refuses the injection on pods whose labels match this selector. - // It's an array of label selectors, that will be OR'ed, meaning we will iterate - // over it and stop at the first match - // Takes precedence over AlwaysInjectSelector. - NeverInjectSelector []metav1.LabelSelector `json:"neverInjectSelector"` - - // AlwaysInjectSelector: Forces the injection on pods whose labels match this selector. - // It's an array of label selectors, that will be OR'ed, meaning we will iterate - // over it and stop at the first match - AlwaysInjectSelector []metav1.LabelSelector `json:"alwaysInjectSelector"` - - // InjectedAnnotations are additional annotations that will be added to the pod spec after injection - // This is primarily to support PSP annotations. - InjectedAnnotations map[string]string `json:"injectedAnnotations"` -} - -func validateCIDRList(cidrs string) error { - if len(cidrs) > 0 { - for _, cidr := range strings.Split(cidrs, ",") { - if _, _, err := net.ParseCIDR(cidr); err != nil { - return fmt.Errorf("failed parsing cidr '%s': %v", cidr, err) - } - } - } - return nil -} - -func splitPorts(portsString string) []string { - return strings.Split(portsString, ",") -} - -func parsePort(portStr string) (int, error) { - port, err := strconv.ParseUint(strings.TrimSpace(portStr), 10, 16) - if err != nil { - return 0, fmt.Errorf("failed parsing port '%d': %v", port, err) - } - return int(port), nil -} - -func parsePorts(portsString string) ([]int, error) { - portsString = strings.TrimSpace(portsString) - ports := make([]int, 0) - if len(portsString) > 0 { - for _, portStr := range splitPorts(portsString) { - port, err := parsePort(portStr) - if err != nil { - return nil, fmt.Errorf("failed parsing port '%d': %v", port, err) - } - ports = append(ports, port) - } - } - return ports, nil -} - -func validatePortList(parameterName, ports string) error { - if _, err := parsePorts(ports); err != nil { - return fmt.Errorf("%s invalid: %v", parameterName, err) - } - return nil -} - -// ValidateIncludeIPRanges validates the includeIPRanges parameter -func ValidateIncludeIPRanges(ipRanges string) error { - if ipRanges != "*" { - if e := validateCIDRList(ipRanges); e != nil { - return fmt.Errorf("includeIPRanges invalid: %v", e) - } - } - return nil -} - -// ValidateExcludeIPRanges validates the excludeIPRanges parameter -func ValidateExcludeIPRanges(ipRanges string) error { - if e := validateCIDRList(ipRanges); e != nil { - return fmt.Errorf("excludeIPRanges invalid: %v", e) - } - return nil -} - -// ValidateIncludeInboundPorts validates the includeInboundPorts parameter -func ValidateIncludeInboundPorts(ports string) error { - if ports != "*" { - return validatePortList("includeInboundPorts", ports) - } - return nil -} - -// ValidateExcludeInboundPorts validates the excludeInboundPorts parameter -func ValidateExcludeInboundPorts(ports string) error { - return validatePortList("excludeInboundPorts", ports) -} - -// ValidateExcludeOutboundPorts validates the excludeOutboundPorts parameter -func ValidateExcludeOutboundPorts(ports string) error { - return validatePortList("excludeOutboundPorts", ports) -} +// 是否需要注入, 规则参考istio官方定义 +// https://istio.io/latest/zh/docs/ops/common-problems/injection/ +func (wh *Webhook) requireInject(p *podDataInfo) bool { + pod := p.podObject + templateConfig := p.injectTemplateConfig -// validateStatusPort validates the statusPort parameter -func validateStatusPort(port string) error { - if _, e := parsePort(port); e != nil { - return fmt.Errorf("excludeInboundPorts invalid: %v", e) - } - return nil -} - -// nolint -// validateUInt32 validates that the given annotation value is a positive integer. -func validateUInt32(value string) error { - _, err := strconv.ParseUint(value, 10, 32) - return err -} - -// validateBool validates that the given annotation value is a boolean. -func validateBool(value string) error { - _, err := strconv.ParseBool(value) - return err -} - -// getSidecarMode 获取 sidecar 注入模式 -func (wh *Webhook) getSidecarMode(namespace string, pod *corev1.Pod) utils.SidecarMode { - // 这里主要是处理北极星 sidecar, 优先级: pod.annotations > namespace.labels > configmap - if val, ok := pod.Annotations["polarismesh.cn/javaagent"]; ok && val == "true" { - log.InjectScope().Infof("inject pod namespace %q mode is java agent", namespace) - return utils.SidecarForJavaAgent - } - sidecarMode := "" - // 1. pod.annotations - if val, ok := pod.Annotations[utils.PolarisSidecarMode]; ok { - sidecarMode = val - return utils.ParseSidecarMode(sidecarMode) - } - - // 2. namespace.labels - ns, err := wh.k8sClient.CoreV1().Namespaces().Get(context.TODO(), namespace, metav1.GetOptions{}) - if err != nil { - // 如果出现异常,则就采用配置文件中的 Sidecar 的注入模式 - log.InjectScope().Errorf("get pod namespace %q failed: %v", namespace, err) - } else { - if val, ok := ns.Labels[utils.PolarisSidecarModeLabel]; ok { - sidecarMode = val - } - return utils.ParseSidecarMode(sidecarMode) - } - - return wh.defaultSidecarMode -} - -func (wh *Webhook) injectRequired(ignored []string, config *Config, podSpec *corev1.PodSpec, - metadata *metav1.ObjectMeta) bool { - // Skip injection when host networking is enabled. The problem is - // that the iptable changes are assumed to be within the pod when, - // in fact, they are changing the routing at the host level. This - // often results in routing failures within a node which can - // affect the network provider within the cluster causing - // additional pod failures. - if podSpec.HostNetwork { + if pod.Spec.HostNetwork && (p.injectMode == utils.SidecarForMesh || p.injectMode == utils.SidecarForDns) { return false } - // skip special kubernetes system namespaces - for _, namespace := range ignored { - if metadata.Namespace == namespace { - return false - } - } - - annos := metadata.GetAnnotations() - if annos == nil { - annos = map[string]string{} + if isIgnoredNamespace(pod.Namespace) { + return false } - var useDefault bool - var inject bool - switch strings.ToLower(annos[annotation.SidecarInject.Name]) { - // http://yaml.org/type/bool.html - case "y", "yes", "true", "on": - inject = true - case "n", "no", "false", "off": - inject = false - case "": - useDefault = true - } + annotations := pod.GetAnnotations() + annotationStr := buildAnnotationLogString(p.injectMode, annotations) + // annotations为最高优先级 + injectionRequested, useDefaultPolicy := parseInjectionAnnotation(pod.GetAnnotations()) + log.InjectScope().Infof("parseInjectionAnnotation for %s/%s: UseDefault=%v injectionRequested=%v annotations=%s", + pod.Namespace, pod.Name, useDefaultPolicy, injectionRequested, annotationStr) - // If an annotation is not explicitly given, check the LabelSelectors, starting with NeverInject - if useDefault { - for _, neverSelector := range config.NeverInjectSelector { - selector, err := metav1.LabelSelectorAsSelector(&neverSelector) - if err != nil { - log.InjectScope().Warnf("Invalid selector for NeverInjectSelector: %v (%v)", neverSelector, err) - } else if !selector.Empty() && selector.Matches(labels.Set(metadata.Labels)) { - log.InjectScope().Infof("Explicitly disabling injection for pod %s/%s due to pod labels "+ - "matching NeverInjectSelector config map entry.", - metadata.Namespace, potentialPodName(metadata)) - inject = false - useDefault = false - break - } - } + // Labels为次优先级 + if useDefaultPolicy { + injectionRequested, useDefaultPolicy = evaluateSelectors(pod, templateConfig, p.podName) + log.InjectScope().Infof("evaluateSelectors for %s/%s: UseDefault=%v injectionRequested=%v", + pod.Namespace, pod.Name, useDefaultPolicy, injectionRequested) } - // If there's no annotation nor a NeverInjectSelector, check the AlwaysInject one - if useDefault { - for _, alwaysSelector := range config.AlwaysInjectSelector { - selector, err := metav1.LabelSelectorAsSelector(&alwaysSelector) - if err != nil { - log.InjectScope().Warnf("Invalid selector for AlwaysInjectSelector: %v (%v)", alwaysSelector, err) - } else if !selector.Empty() && selector.Matches(labels.Set(metadata.Labels)) { - log.InjectScope().Infof("Explicitly enabling injection for pod %s/%s due to pod labels "+ - " matching AlwaysInjectSelector config map entry.", - metadata.Namespace, potentialPodName(metadata)) - inject = true - useDefault = false - break - } - } - } - - var required bool - switch config.Policy { - default: // InjectionPolicyOff - log.InjectScope().Errorf("Illegal value for autoInject:%s, must be one of [%s,%s]. Auto injection disabled!", - config.Policy, InjectionPolicyDisabled, InjectionPolicyEnabled) - required = false - case InjectionPolicyDisabled: - if useDefault { - required = false - } else { - required = inject - } - case InjectionPolicyEnabled: - if useDefault { - required = true - } else { - required = inject - } - } - - // Build a log message for the annotations. - annotationStr := "" - for name := range annotationRegistry { - value, ok := annos[name] - if !ok { - value = "(unset)" - } - annotationStr += fmt.Sprintf("%s:%s ", name, value) - } - - log.InjectScope().Infof("Sidecar injection for %v/%v: namespacePolicy:%v useDefault:%v inject:%v required:%v %s", - metadata.Namespace, - potentialPodName(metadata), - config.Policy, - useDefault, - inject, - required, - annotationStr) + // Policy为最低优先级 + required := determineInjectionRequirement(templateConfig.Policy, useDefaultPolicy, injectionRequested) + log.InjectScope().Infof("determineInjectionRequirement for %s/%s: Policy=%s UseDefault=%v Requested=%v Required=%v", + pod.Namespace, pod.Name, templateConfig.Policy, useDefaultPolicy, injectionRequested, required) return required } -func formatDuration(in *types.Duration) string { - dur, err := types.DurationFromProto(in) - if err != nil { - return "1s" - } - return dur.String() -} - -func isset(m map[string]string, key string) bool { - _, ok := m[key] - return ok -} - -func openTlsMode(m map[string]string, key string) bool { - if len(m) == 0 { - return false - } - - v, ok := m[key] - if !ok { - return false +func isIgnoredNamespace(namespace string) bool { + for _, ignored := range ignoredNamespaces { + if namespace == ignored { + return true + } } - - return v != util.MTLSModeNone -} - -func directory(filepath string) string { - dir, _ := path.Split(filepath) - return dir -} - -func flippedContains(needle, haystack string) bool { - return strings.Contains(haystack, needle) + return false } -// InjectionData renders sidecarTemplate with valuesConfig. -func InjectionData(sidecarTemplate, valuesConfig, version string, typeMetadata *metav1.TypeMeta, - deploymentMetadata *metav1.ObjectMeta, spec *corev1.PodSpec, - metadata *metav1.ObjectMeta, proxyConfig *mesh.DefaultConfig) ( - *SidecarInjectionSpec, map[string]string, string, error) { - // If DNSPolicy is not ClusterFirst, the Envoy sidecar may not able to connect to polaris. - if spec.DNSPolicy != "" && spec.DNSPolicy != corev1.DNSClusterFirst { - podName := potentialPodName(metadata) - log.InjectScope().Errorf("[Webhook] %q's DNSPolicy is not %q. The Envoy sidecar may not able to "+ - " connect to PolarisMesh Control Plane", - metadata.Namespace+"/"+podName, corev1.DNSClusterFirst) - return nil, nil, "", nil - } - - if err := validateAnnotations(metadata.GetAnnotations()); err != nil { - log.InjectScope().Errorf("[Webhook] injection failed due to invalid annotations: %v", err) - return nil, nil, "", err - } - - values := map[string]interface{}{} - if err := yaml.Unmarshal([]byte(valuesConfig), &values); err != nil { - log.InjectScope().Infof("[Webhook] failed to parse values config: %v [%v]\n", err, valuesConfig) - return nil, nil, "", multierror.Prefix(err, "could not parse configuration values:") - } - - injectAnnonations := map[string]string{} - // 设置需要注入到 envoy 的 metadata - // 强制开启 XDS On-Demand 能力 - envoyMetadata := map[string]string{} - // 这里负责将需要额外塞入的 annonation 数据进行返回 - if len(metadata.Annotations) != 0 { - tlsMode := util.MTLSModeNone - if mode, ok := metadata.Annotations[util.PolarisTLSMode]; ok { - mode = strings.ToLower(mode) - if mode == util.MTLSModeStrict || mode == util.MTLSModePermissive { - tlsMode = mode - } - } - injectAnnonations[util.PolarisTLSMode] = tlsMode - envoyMetadata[util.PolarisTLSMode] = tlsMode - - // 按需加载能力需要显示开启 - if val, ok := metadata.Annotations["sidecar.polarismesh.cn/openOnDemand"]; ok { - envoyMetadata["sidecar.polarismesh.cn/openOnDemand"] = val - proxyConfig.ProxyMetadata["OPEN_DEMAND"] = val - } - } - // 这里需要将 sidecar 所属的服务信息注入到 annonation 中,方便下发到 envoy 的 bootstrap.yaml 中 - // 命名空间可以不太强要求用户设置,大部份场景都是保持和 kubernetes 部署所在的 namespace 保持一致的 - if _, ok := metadata.Annotations[utils.SidecarNamespaceName]; !ok { - injectAnnonations[utils.SidecarNamespaceName] = metadata.Namespace - envoyMetadata[utils.SidecarNamespaceName] = metadata.Namespace - } - if svcName, ok := metadata.Annotations[utils.SidecarServiceName]; !ok { - // 如果官方注解没有查询到,那就默认按照 istio 的约定,从 labels 中读取 app 这个标签的 value 作为服务名 - if val, ok := metadata.Labels["app"]; ok { - injectAnnonations[utils.SidecarServiceName] = val - envoyMetadata[utils.SidecarServiceName] = val - } +// 解析Annotation, 用于注解位置的黑白名单功能 +func parseInjectionAnnotation(annotations map[string]string) (requested bool, useDefault bool) { + var value string + newFlag, newExists := annotations[utils.InjectAdmissionKey] + if newExists { + value = strings.ToLower(newFlag) } else { - envoyMetadata[utils.SidecarServiceName] = svcName - } - - for k, v := range metadata.Labels { - envoyMetadata[k] = v - } - injectAnnonations[utils.SidecarEnvoyMetadata] = fmt.Sprintf("%q", toJSON(envoyMetadata)) - metadataCopy := metadata.DeepCopy() - metadataCopy.Annotations = injectAnnonations - data := SidecarTemplateData{ - TypeMeta: typeMetadata, - DeploymentMeta: deploymentMetadata, - ObjectMeta: metadataCopy, - Spec: spec, - ProxyConfig: proxyConfig, - Values: values, - } - - funcMap := template.FuncMap{ - "formatDuration": formatDuration, - "isset": isset, - "excludeInboundPort": excludeInboundPort, - "includeInboundPorts": includeInboundPorts, - "kubevirtInterfaces": kubevirtInterfaces, - "applicationPorts": applicationPorts, - "annotation": getAnnotation, - "valueOrDefault": valueOrDefault, - "toJSON": toJSON, - "toJson": toJSON, // Used by, e.g. Istio 1.0.5 template sidecar-injector-configmap.yaml - "fromJSON": fromJSON, - "structToJSON": structToJSON, - "protoToJSON": protoToJSON, - "toYaml": toYaml, - "indent": indent, - "directory": directory, - "contains": flippedContains, - "toLower": strings.ToLower, - "openTlsMode": openTlsMode, - } - - // Allows the template to use env variables from istiod. - // Istiod will use a custom template, without 'values.yaml', and the pod will have - // an optional 'vendor' configmap where additional settings can be defined. - funcMap["env"] = func(key string, def string) string { - val := os.Getenv(key) - if val == "" { - return def + if flag, ok := annotations[annotation.SidecarInject.Name]; ok { + value = strings.ToLower(flag) } - return val - } - - // Need to use FuncMap and SidecarTemplateData context - funcMap["render"] = func(template string) string { - bbuf, err := parseTemplate(template, funcMap, data) - if err != nil { - return "" - } - - return bbuf.String() - } - - bbuf, err := parseTemplate(sidecarTemplate, funcMap, data) - if err != nil { - return nil, nil, "", err - } - - var sic SidecarInjectionSpec - if err := yaml.Unmarshal(bbuf.Bytes(), &sic); err != nil { - // This usually means an invalid injector template; we can't check - // the template itself because it is merely a string. - log.InjectScope().Warnf("Failed to unmarshal template %v \n%s", err, bbuf.String()) - return nil, nil, "", multierror.Prefix(err, "failed parsing injected YAML (check sidecar injector configuration):") } - - // set sidecar --concurrency - applyConcurrency(sic.Containers) - - status := &SidecarInjectionStatus{Version: version} - for _, c := range sic.InitContainers { - status.InitContainers = append(status.InitContainers, corev1.Container{ - Name: c.Name, - }) - } - for _, c := range sic.Containers { - status.Containers = append(status.Containers, corev1.Container{ - Name: c.Name, - }) - } - for _, c := range sic.Volumes { - status.Volumes = append(status.Volumes, corev1.Volume{ - Name: c.Name, - }) + switch value { + case "y", "yes", "true", "on", "enable", "enabled": + // annotation白名单, 显示开启 + return true, false + case "n", "no", "false", "off", "disable", "disabled": + // annotation黑名单, 显示关闭 + return false, false + default: // including empty string + return false, true } - for _, c := range sic.ImagePullSecrets { - status.ImagePullSecrets = append(status.ImagePullSecrets, corev1.LocalObjectReference{ - Name: c.Name, - }) - } - statusAnnotationValue, err := json.Marshal(status) - if err != nil { - return nil, nil, "", fmt.Errorf("error encoded injection status: %v", err) - } - return &sic, injectAnnonations, string(statusAnnotationValue), err } -func parseTemplate(tmplStr string, funcMap map[string]interface{}, data SidecarTemplateData) (bytes.Buffer, error) { - var tmpl bytes.Buffer - temp := template.New("inject") - t, err := temp.Funcs(funcMap).Parse(tmplStr) - if err != nil { - log.InjectScope().Errorf("Failed to parse template: %v %v\n", err, tmplStr) - return bytes.Buffer{}, err - } - if err := t.Execute(&tmpl, &data); err != nil { - log.InjectScope().Errorf("Invalid template: %v %v\n", err, tmplStr) - return bytes.Buffer{}, err +// 检查label的黑白名单功能 +func evaluateSelectors(pod *corev1.Pod, config *config.TemplateConfig, podName string) (bool, bool) { + // Check NeverInject selectors first + if inject, ok := checkSelectors(pod, config.NeverInjectSelector, "NeverInjectSelector", podName, false); ok { + return inject, false } - return tmpl, nil -} - -// FromRawToObject is used to convert from raw to the runtime object -func FromRawToObject(raw []byte) (runtime.Object, error) { - var typeMeta metav1.TypeMeta - if err := yaml.Unmarshal(raw, &typeMeta); err != nil { - return nil, err - } - - gvk := schema.FromAPIVersionAndKind(typeMeta.APIVersion, typeMeta.Kind) - obj, err := injectScheme.New(gvk) - if err != nil { - return nil, err - } - if err = yaml.Unmarshal(raw, obj); err != nil { - return nil, err + // Then check AlwaysInject selectors + if inject, ok := checkSelectors(pod, config.AlwaysInjectSelector, "AlwaysInjectSelector", podName, true); ok { + return inject, false } - return obj, nil + return false, true } -func getPortsForContainer(container corev1.Container) []string { - parts := make([]string, 0) - for _, p := range container.Ports { - if p.Protocol == corev1.ProtocolUDP || p.Protocol == corev1.ProtocolSCTP { - continue +func checkSelectors(pod *corev1.Pod, selectors []metav1.LabelSelector, selectorType string, podName string, + allowInject bool) (bool, bool) { + for _, selector := range selectors { + ls, err := metav1.LabelSelectorAsSelector(&selector) + if err != nil { + log.InjectScope().Warnf("Invalid %s: %v (%v)", selectorType, selector, err) + continue // Continue checking other selectors } - parts = append(parts, strconv.Itoa(int(p.ContainerPort))) - } - return parts -} -func getContainerPorts(containers []corev1.Container, shouldIncludePorts func(corev1.Container) bool) string { - parts := make([]string, 0) - for _, c := range containers { - if shouldIncludePorts(c) { - parts = append(parts, getPortsForContainer(c)...) + if !ls.Empty() && ls.Matches(labels.Set(pod.Labels)) { + log.InjectScope().Infof("Pod %s/%s: %s matched labels %v", pod.Namespace, podName, selectorType, pod.Labels) + return allowInject, true } } - - return strings.Join(parts, ",") -} - -// this function is no longer used by the template but kept around for backwards compatibility -func applicationPorts(containers []corev1.Container) string { - return getContainerPorts(containers, func(c corev1.Container) bool { - return c.Name != ProxyContainerName - }) -} - -func includeInboundPorts(containers []corev1.Container) string { - // Include the ports from all containers in the deployment. - return getContainerPorts(containers, func(corev1.Container) bool { return true }) + return false, false } -func kubevirtInterfaces(s string) string { - return s -} - -func structToJSON(v interface{}) string { - if v == nil { - return "{}" - } - - ba, err := json.Marshal(v) - if err != nil { - log.InjectScope().Warnf("Unable to marshal %v", v) - return "{}" - } - - return string(ba) -} - -func protoToJSON(v proto.Message) string { - if v == nil { - return "{}" - } - - m := jsonpb.Marshaler{} - ba, err := m.MarshalToString(v) - if err != nil { - log.InjectScope().Warnf("Unable to marshal %v: %v", v, err) - return "{}" - } - - return ba -} - -func toJSON(m map[string]string) string { - if m == nil { - return "{}" - } - - ba, err := json.Marshal(m) - if err != nil { - log.InjectScope().Warnf("Unable to marshal %v", m) - return "{}" - } - - return string(ba) -} - -func fromJSON(j string) interface{} { - var m interface{} - err := json.Unmarshal([]byte(j), &m) - if err != nil { - log.InjectScope().Warnf("Unable to unmarshal %s", j) - return "{}" - } - - log.InjectScope().Warnf("%v", m) - return m -} - -func indent(spaces int, source string) string { - res := strings.Split(source, "\n") - for i, line := range res { - if i > 0 { - res[i] = fmt.Sprintf(fmt.Sprintf("%% %ds%%s", spaces), "", line) - } - } - return strings.Join(res, "\n") -} - -func toYaml(value interface{}) string { - y, err := yaml.Marshal(value) - if err != nil { - log.InjectScope().Warnf("Unable to marshal %v", value) - return "" - } - - return string(y) -} - -func getAnnotation(meta metav1.ObjectMeta, name string, defaultValue interface{}) string { - value, ok := meta.Annotations[name] - if !ok { - value = fmt.Sprint(defaultValue) - } - return value -} - -func excludeInboundPort(port interface{}, excludedInboundPorts string) string { - portStr := strings.TrimSpace(fmt.Sprint(port)) - if len(portStr) == 0 || portStr == "0" { - // Nothing to do. - return excludedInboundPorts - } - - // Exclude the readiness port if not already excluded. - ports := splitPorts(excludedInboundPorts) - outPorts := make([]string, 0, len(ports)) - for _, port := range ports { - if port == portStr { - // The port is already excluded. - return excludedInboundPorts +func determineInjectionRequirement(policy config.InjectionPolicy, useDefault bool, requested bool) bool { + switch policy { + case config.InjectionPolicyEnabled: + if useDefault { + return true } - port = strings.TrimSpace(port) - if len(port) > 0 { - outPorts = append(outPorts, port) + return requested + case config.InjectionPolicyDisabled: + if useDefault { + return false } + return requested + default: + log.InjectScope().Errorf("Invalid injection policy: %s. Valid values: [%s, %s]", + policy, config.InjectionPolicyDisabled, config.InjectionPolicyEnabled) + return false } - - // The port was not already excluded - exclude it now. - outPorts = append(outPorts, portStr) - return strings.Join(outPorts, ",") -} - -func valueOrDefault(value interface{}, defaultValue interface{}) interface{} { - if value == "" || value == nil { - return defaultValue - } - return value } -// SidecarInjectionStatus contains basic information about the -// injected sidecar. This includes the names of added containers and -// volumes. -type SidecarInjectionStatus struct { - Version string `json:"version"` - InitContainers []corev1.Container `json:"initContainers"` - Containers []corev1.Container `json:"containers"` - Volumes []corev1.Volume `json:"volumes"` - ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets"` -} - -// helper function to generate a template version identifier from a -// hash of the un-executed template contents. -func sidecarTemplateVersionHash(in string) string { - hash := sha256.Sum256([]byte(in)) - return hex.EncodeToString(hash[:]) -} - -func potentialPodName(metadata *metav1.ObjectMeta) string { - if metadata.Name != "" { - return metadata.Name - } - if metadata.GenerateName != "" { - return metadata.GenerateName + "***** (actual name not yet known)" +// buildAnnotationLogString 构建注解日志字符串,格式为"key:value key2:value2" +func buildAnnotationLogString(injectMode utils.SidecarMode, annotations map[string]string) string { + registry := getAnnotationRegistry(injectMode) + var buf strings.Builder + for name := range registry { + value, ok := annotations[name] + if !ok { + value = "(unset)" + } + buf.WriteString(fmt.Sprintf("%s:%s ", name, value)) } - return "" + return strings.TrimSpace(buf.String()) } -// nolint -// rewriteCniPodSpec will check if values from the sidecar injector Helm -// values need to be inserted as Pod annotations so the CNI will apply -// the proper redirection rules. -func rewriteCniPodSpec(annotations map[string]string, spec *SidecarInjectionSpec) { - if spec == nil { - return - } - if len(spec.PodRedirectAnnot) == 0 { - return - } - for k := range annotationRegistry { - if spec.PodRedirectAnnot[k] != "" { - if annotations[k] == spec.PodRedirectAnnot[k] { - continue - } - annotations[k] = spec.PodRedirectAnnot[k] - } +func getAnnotationRegistry(injectMode utils.SidecarMode) map[string]annotationValidationFunc { + var registry map[string]annotationValidationFunc + switch injectMode { + case utils.SidecarForMesh: + registry = annotationRegistryForMesh + case utils.SidecarForDns: + registry = annotationRegistryForDns + case utils.SidecarForJavaAgent: + registry = annotationRegistryForJavaAgent } + return registry } diff --git a/pkg/inject/pkg/kube/inject/pod.go b/pkg/inject/pkg/kube/inject/pod.go new file mode 100644 index 00000000..a3181f82 --- /dev/null +++ b/pkg/inject/pkg/kube/inject/pod.go @@ -0,0 +1,214 @@ +package inject + +import ( + "encoding/json" + "fmt" + "strings" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/polarismesh/polaris-controller/common/log" + "github.com/polarismesh/polaris-controller/pkg/inject/api/annotation" + "github.com/polarismesh/polaris-controller/pkg/inject/pkg/config" + utils "github.com/polarismesh/polaris-controller/pkg/util" +) + +type podDataInfo struct { + podObject *corev1.Pod + podName string + injectMode utils.SidecarMode + injectTemplateConfig *config.TemplateConfig + injectTemplateVersion string + valuesConfig string + workloadMeta *metav1.ObjectMeta + workloadType *metav1.TypeMeta + injectedAnnotations map[string]string +} + +// 解析并填充 pod 的信息 +func assignPodDataInfo(raw []byte, namespace string, wh *Webhook) (*podDataInfo, error) { + var pod corev1.Pod + if err := json.Unmarshal(raw, &pod); err != nil { + handleError(fmt.Sprintf("Could not unmarshal raw object: %v %s", err, + string(raw))) + return nil, err + } + if pod.Namespace == "" { + pod.Namespace = namespace + } + podInfo := &podDataInfo{ + podObject: &pod, + } + podInfo.assignAll(wh) + return podInfo, nil +} + +// 初始化podDataInfo所有字段 +func (p *podDataInfo) assignAll(wh *Webhook) { + p.assignPodName() + p.assignInjectMode(wh) + p.assignInjectTemplateAndVersion(wh) + p.assignWorkloadMeta() + p.assignInjectAnnotations() +} + +func (p *podDataInfo) assignWorkloadMeta() { + p.workloadMeta, p.workloadType = getOwnerMetaAndType(p.podObject) +} + +// 通过Name或GenerateName获取Pod的名称 +func (p *podDataInfo) assignPodName() { + metadata := p.podObject.ObjectMeta + if metadata.Name != "" { + p.podName = metadata.Name + } else if metadata.GenerateName != "" { + p.podName = metadata.GenerateName + "***** (actual name not yet known)" + } +} + +// assignInjectTemplateAndVersion 获取注入配置 +func (p *podDataInfo) assignInjectTemplateAndVersion(wh *Webhook) { + switch p.injectMode { + case utils.SidecarForJavaAgent: + p.injectTemplateConfig, p.injectTemplateVersion = wh.templateConfig.GetSidecarJavaAgentTemplateAndVersion() + case utils.SidecarForDns: + p.injectTemplateConfig, p.injectTemplateVersion = wh.templateConfig.GetSidecarDnsTemplateAndVersion() + default: + // 向前兼容, 默认是mesh模式 + p.injectTemplateConfig, p.injectTemplateVersion = wh.templateConfig.GetSidecarMeshTemplateAndVersion() + } + log.InjectScope().Infof("podName=%s, injectMode=%s, injectTemplateConfig=%v", p.podName, + utils.ParseSidecarModeName(p.injectMode), p.injectTemplateConfig) + p.valuesConfig = wh.templateConfig.GetValuesConfig() + return +} + +// assignInjectMode 获取注入类型 +func (p *podDataInfo) assignInjectMode(wh *Webhook) { + p.injectMode = getInjectMode(wh, p) +} + +// 检查pod的spec和annotations是否符合要求 +func (p *podDataInfo) checkPodData() (bool, error) { + pod := p.podObject + if err := validateAnnotations(p.injectMode, pod.GetAnnotations()); err != nil { + log.InjectScope().Errorf("[Webhook] injection failed due to invalid annotations: %v", err) + return false, err + } + if p.injectMode == utils.SidecarForMesh { + // If DNSPolicy is not ClusterFirst, the Envoy sidecar may not able to connect to polaris. + if pod.Spec.DNSPolicy != "" && pod.Spec.DNSPolicy != corev1.DNSClusterFirst { + log.InjectScope().Errorf("[Webhook] %q's DNSPolicy is not %q. The Envoy sidecar may not able to "+ + " connect to PolarisMesh Control Plane", + pod.Namespace+"/"+p.podName, corev1.DNSClusterFirst) + return false, nil + } + } + return true, nil +} + +// 处理pod的annotations注入 +func (p *podDataInfo) assignInjectAnnotations() { + md := p.podObject.ObjectMeta + injectAnnotations := map[string]string{} + // Add all additional injected annotations + for k, v := range p.injectTemplateConfig.InjectedAnnotations { + injectAnnotations[k] = v + } + if p.injectMode == utils.SidecarForMesh { + // 设置需要注入到 envoy 的 md + // 强制开启 XDS On-Demand 能力 + envoyMetadata := map[string]string{} + // 这里负责将需要额外塞入的 annonation 数据进行返回 + if len(md.Annotations) != 0 { + tlsMode := utils.MTLSModeNone + if mode, ok := md.Annotations[utils.PolarisTLSMode]; ok { + mode = strings.ToLower(mode) + if mode == utils.MTLSModeStrict || mode == utils.MTLSModePermissive { + tlsMode = mode + } + } + injectAnnotations[utils.PolarisTLSMode] = tlsMode + envoyMetadata[utils.PolarisTLSMode] = tlsMode + + // 按需加载能力需要显示开启 + if val, ok := md.Annotations[utils.SidecarEnvoyInjectKey]; ok { + envoyMetadata[utils.SidecarEnvoyInjectKey] = val + } + } + // 这里需要将 sidecar 所属的服务信息注入到 annonation 中,方便下发到 envoy 的 bootstrap.yaml 中 + // 命名空间可以不太强要求用户设置,大部份场景都是保持和 kubernetes 部署所在的 namespace 保持一致的 + if _, ok := md.Annotations[utils.SidecarNamespaceName]; !ok { + injectAnnotations[utils.SidecarNamespaceName] = md.Namespace + envoyMetadata[utils.SidecarNamespaceName] = md.Namespace + } + if svcName, ok := md.Annotations[utils.SidecarServiceName]; !ok { + // 如果官方注解没有查询到,那就默认按照 istio 的约定,从 labels 中读取 app 这个标签的 value 作为服务名 + if val, ok := md.Labels["app"]; ok { + injectAnnotations[utils.SidecarServiceName] = val + envoyMetadata[utils.SidecarServiceName] = val + } else { + injectAnnotations[utils.SidecarServiceName] = p.workloadMeta.Name + envoyMetadata[utils.SidecarServiceName] = p.workloadMeta.Name + } + } else { + envoyMetadata[utils.SidecarServiceName] = svcName + } + + for k, v := range md.Labels { + envoyMetadata[k] = v + } + injectAnnotations[utils.SidecarEnvoyMetadata] = fmt.Sprintf("%q", toJSON(envoyMetadata)) + } else { + // 注入workload的namespace和name + if _, ok := md.Annotations[utils.SidecarNamespaceName]; !ok { + injectAnnotations[utils.SidecarNamespaceName] = md.Namespace + } + if _, ok := md.Annotations[utils.SidecarServiceName]; !ok { + injectAnnotations[utils.SidecarServiceName] = p.workloadMeta.Name + } + } + p.injectedAnnotations = injectAnnotations +} + +// SidecarInjectionStatus contains basic information about the +// injected sidecar. This includes the names of added containers and +// volumes. +type SidecarInjectionStatus struct { + Version string `json:"version"` + InitContainers []corev1.Container `json:"initContainers"` + Containers []corev1.Container `json:"containers"` + Volumes []corev1.Volume `json:"volumes"` + ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets"` +} + +func (p *podDataInfo) addInjectStatusAnnotation(sic SidecarInjectionSpec) string { + status := &SidecarInjectionStatus{Version: p.injectTemplateVersion} + for _, c := range sic.InitContainers { + status.InitContainers = append(status.InitContainers, corev1.Container{ + Name: c.Name, + }) + } + for _, c := range sic.Containers { + status.Containers = append(status.Containers, corev1.Container{ + Name: c.Name, + }) + } + for _, c := range sic.Volumes { + status.Volumes = append(status.Volumes, corev1.Volume{ + Name: c.Name, + }) + } + for _, c := range sic.ImagePullSecrets { + status.ImagePullSecrets = append(status.ImagePullSecrets, corev1.LocalObjectReference{ + Name: c.Name, + }) + } + statusAnnotationValue, _ := json.Marshal(status) + result := string(statusAnnotationValue) + if len(result) != 0 { + p.injectedAnnotations[annotation.SidecarStatus.Name] = result + } + return result +} diff --git a/pkg/inject/pkg/kube/inject/template_funcs.go b/pkg/inject/pkg/kube/inject/template_funcs.go new file mode 100644 index 00000000..105809c8 --- /dev/null +++ b/pkg/inject/pkg/kube/inject/template_funcs.go @@ -0,0 +1,248 @@ +package inject + +import ( + "bytes" + "encoding/json" + "fmt" + "os" + "path" + "strconv" + "strings" + "text/template" + + "github.com/ghodss/yaml" + "github.com/gogo/protobuf/jsonpb" + "github.com/gogo/protobuf/proto" + "github.com/gogo/protobuf/types" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/polarismesh/polaris-controller/common/log" + "github.com/polarismesh/polaris-controller/pkg/util" +) + +func formatDuration(in *types.Duration) string { + dur, err := types.DurationFromProto(in) + if err != nil { + return "1s" + } + return dur.String() +} + +func isset(m map[string]string, key string) bool { + _, ok := m[key] + return ok +} + +func excludeInboundPort(port interface{}, excludedInboundPorts string) string { + portStr := strings.TrimSpace(fmt.Sprint(port)) + if len(portStr) == 0 || portStr == "0" { + // Nothing to do. + return excludedInboundPorts + } + + // Exclude the readiness port if not already excluded. + ports := splitPorts(excludedInboundPorts) + outPorts := make([]string, 0, len(ports)) + for _, port := range ports { + if port == portStr { + // The port is already excluded. + return excludedInboundPorts + } + port = strings.TrimSpace(port) + if len(port) > 0 { + outPorts = append(outPorts, port) + } + } + + // The port was not already excluded - exclude it now. + outPorts = append(outPorts, portStr) + return strings.Join(outPorts, ",") +} + +func openTlsMode(m map[string]string, key string) bool { + if len(m) == 0 { + return false + } + + v, ok := m[key] + if !ok { + return false + } + + return v != util.MTLSModeNone +} + +func directory(filepath string) string { + dir, _ := path.Split(filepath) + return dir +} + +func flippedContains(needle, haystack string) bool { + return strings.Contains(haystack, needle) +} + +func parseTemplate(tmplStr string, funcMap map[string]interface{}, data SidecarTemplateData) (bytes.Buffer, error) { + var tmpl bytes.Buffer + temp := template.New("inject") + t, err := temp.Funcs(funcMap).Parse(tmplStr) + if err != nil { + log.InjectScope().Errorf("Failed to parse template: %v %v\n", err, tmplStr) + return bytes.Buffer{}, err + } + if err := t.Execute(&tmpl, &data); err != nil { + log.InjectScope().Errorf("Invalid template: %v %v\n", err, tmplStr) + return bytes.Buffer{}, err + } + + return tmpl, nil +} + +func toYaml(value interface{}) string { + y, err := yaml.Marshal(value) + if err != nil { + log.InjectScope().Warnf("Unable to marshal %v", value) + return "" + } + + return string(y) +} + +func getPortsForContainer(container corev1.Container) []string { + parts := make([]string, 0) + for _, p := range container.Ports { + if p.Protocol == corev1.ProtocolUDP || p.Protocol == corev1.ProtocolSCTP { + continue + } + parts = append(parts, strconv.Itoa(int(p.ContainerPort))) + } + return parts +} + +func getContainerPorts(containers []corev1.Container, shouldIncludePorts func(corev1.Container) bool) string { + parts := make([]string, 0) + for _, c := range containers { + if shouldIncludePorts(c) { + parts = append(parts, getPortsForContainer(c)...) + } + } + + return strings.Join(parts, ",") +} + +// this function is no longer used by the template but kept around for backwards compatibility +func applicationPorts(containers []corev1.Container) string { + return getContainerPorts(containers, func(c corev1.Container) bool { + return c.Name != ProxyContainerName + }) +} + +func includeInboundPorts(containers []corev1.Container) string { + // Include the ports from all containers in the deployment. + return getContainerPorts(containers, func(corev1.Container) bool { return true }) +} + +func kubevirtInterfaces(s string) string { + return s +} + +func structToJSON(v interface{}) string { + if v == nil { + return "{}" + } + + ba, err := json.Marshal(v) + if err != nil { + log.InjectScope().Warnf("Unable to marshal %v", v) + return "{}" + } + + return string(ba) +} + +func protoToJSON(v proto.Message) string { + if v == nil { + return "{}" + } + + m := jsonpb.Marshaler{} + ba, err := m.MarshalToString(v) + if err != nil { + log.InjectScope().Warnf("Unable to marshal %v: %v", v, err) + return "{}" + } + + return ba +} + +func toJSON(m map[string]string) string { + if m == nil { + return "{}" + } + + ba, err := json.Marshal(m) + if err != nil { + log.InjectScope().Warnf("Unable to marshal %v", m) + return "{}" + } + + return string(ba) +} + +func fromJSON(j string) interface{} { + var m interface{} + err := json.Unmarshal([]byte(j), &m) + if err != nil { + log.InjectScope().Warnf("Unable to unmarshal %s", j) + return "{}" + } + + log.InjectScope().Warnf("%v", m) + return m +} + +func indent(spaces int, source string) string { + res := strings.Split(source, "\n") + for i, line := range res { + if i > 0 { + res[i] = fmt.Sprintf(fmt.Sprintf("%% %ds%%s", spaces), "", line) + } + } + return strings.Join(res, "\n") +} + +func getAnnotation(meta metav1.ObjectMeta, name string, defaultValue interface{}) string { + value, ok := meta.Annotations[name] + if !ok { + value = fmt.Sprint(defaultValue) + } + return value +} + +func valueOrDefault(value interface{}, defaultValue interface{}) interface{} { + if value == "" || value == nil { + return defaultValue + } + return value +} + +// Allows the template to use env variables from istiod. +// Istiod will use a custom template, without 'values.yaml', and the pod will have +// an optional 'vendor' configmap where additional settings can be defined. +func env(key string, def string) string { + val := os.Getenv(key) + if val == "" { + return def + } + return val +} + +// Need to use FuncMap and SidecarTemplateData context +func render(template string, funcMap map[string]interface{}, data SidecarTemplateData) string { + bbuf, err := parseTemplate(template, funcMap, data) + if err != nil { + return "" + } + + return bbuf.String() +} diff --git a/pkg/inject/pkg/kube/inject/validate_funcs.go b/pkg/inject/pkg/kube/inject/validate_funcs.go new file mode 100644 index 00000000..8eeefa3a --- /dev/null +++ b/pkg/inject/pkg/kube/inject/validate_funcs.go @@ -0,0 +1,110 @@ +package inject + +import ( + "fmt" + "net" + "strconv" + "strings" +) + +func validateCIDRList(cidrs string) error { + if len(cidrs) > 0 { + for _, cidr := range strings.Split(cidrs, ",") { + if _, _, err := net.ParseCIDR(cidr); err != nil { + return fmt.Errorf("failed parsing cidr '%s': %v", cidr, err) + } + } + } + return nil +} + +func splitPorts(portsString string) []string { + return strings.Split(portsString, ",") +} + +func parsePort(portStr string) (int, error) { + port, err := strconv.ParseUint(strings.TrimSpace(portStr), 10, 16) + if err != nil { + return 0, fmt.Errorf("failed parsing port '%d': %v", port, err) + } + return int(port), nil +} + +func parsePorts(portsString string) ([]int, error) { + portsString = strings.TrimSpace(portsString) + ports := make([]int, 0) + if len(portsString) > 0 { + for _, portStr := range splitPorts(portsString) { + port, err := parsePort(portStr) + if err != nil { + return nil, fmt.Errorf("failed parsing port '%d': %v", port, err) + } + ports = append(ports, port) + } + } + return ports, nil +} + +func validatePortList(parameterName, ports string) error { + if _, err := parsePorts(ports); err != nil { + return fmt.Errorf("%s invalid: %v", parameterName, err) + } + return nil +} + +// ValidateIncludeIPRanges validates the includeIPRanges parameter +func ValidateIncludeIPRanges(ipRanges string) error { + if ipRanges != "*" { + if e := validateCIDRList(ipRanges); e != nil { + return fmt.Errorf("includeIPRanges invalid: %v", e) + } + } + return nil +} + +// ValidateExcludeIPRanges validates the excludeIPRanges parameter +func ValidateExcludeIPRanges(ipRanges string) error { + if e := validateCIDRList(ipRanges); e != nil { + return fmt.Errorf("excludeIPRanges invalid: %v", e) + } + return nil +} + +// ValidateIncludeInboundPorts validates the includeInboundPorts parameter +func ValidateIncludeInboundPorts(ports string) error { + if ports != "*" { + return validatePortList("includeInboundPorts", ports) + } + return nil +} + +// ValidateExcludeInboundPorts validates the excludeInboundPorts parameter +func ValidateExcludeInboundPorts(ports string) error { + return validatePortList("excludeInboundPorts", ports) +} + +// ValidateExcludeOutboundPorts validates the excludeOutboundPorts parameter +func ValidateExcludeOutboundPorts(ports string) error { + return validatePortList("excludeOutboundPorts", ports) +} + +// validateStatusPort validates the statusPort parameter +func validateStatusPort(port string) error { + if _, e := parsePort(port); e != nil { + return fmt.Errorf("excludeInboundPorts invalid: %v", e) + } + return nil +} + +// nolint +// validateUInt32 validates that the given annotation value is a positive integer. +func validateUInt32(value string) error { + _, err := strconv.ParseUint(value, 10, 32) + return err +} + +// validateBool validates that the given annotation value is a boolean. +func validateBool(value string) error { + _, err := strconv.ParseBool(value) + return err +} diff --git a/pkg/inject/pkg/kube/inject/webhook.go b/pkg/inject/pkg/kube/inject/webhook.go index 4762d164..efd49890 100644 --- a/pkg/inject/pkg/kube/inject/webhook.go +++ b/pkg/inject/pkg/kube/inject/webhook.go @@ -17,7 +17,6 @@ package inject import ( "bytes" "context" - "crypto/sha256" "crypto/tls" "encoding/json" "fmt" @@ -27,12 +26,10 @@ import ( "path/filepath" "sort" "strings" - "sync" "text/template" "time" - gyaml "github.com/ghodss/yaml" - "github.com/howeyc/fsnotify" + "github.com/fsnotify/fsnotify" v1 "k8s.io/api/admission/v1" "k8s.io/api/admission/v1beta1" corev1 "k8s.io/api/core/v1" @@ -47,7 +44,7 @@ import ( "github.com/polarismesh/polaris-controller/common" "github.com/polarismesh/polaris-controller/common/log" "github.com/polarismesh/polaris-controller/pkg/inject/api/annotation" - "github.com/polarismesh/polaris-controller/pkg/inject/pkg/config/mesh" + "github.com/polarismesh/polaris-controller/pkg/inject/pkg/config" utils "github.com/polarismesh/polaris-controller/pkg/util" ) @@ -70,143 +67,25 @@ const ( // Webhook implements a mutating webhook for automatic proxy injection. type Webhook struct { defaultSidecarMode utils.SidecarMode - mu sync.RWMutex - - // envoy mesh 场景下的 sidecar 注入配置 - sidecarMeshConfig *Config - sidecarMeshTemplateVersion string - // dns 场景下的 sidecar 注入配置 - sidecarDnsConfig *Config - sidecarDnsTemplateVersion string - // java agent 场景下的注入配置 - sidecarJavaAgentConfig *Config - sidecarJavaAgentTemplateVersion string - meshConfig *mesh.MeshConfig - valuesConfig string + templateConfig *config.SafeTemplateConfig + templateFileConfig config.TemplateFileConfig healthCheckInterval time.Duration healthCheckFile string - server *http.Server - meshFile string - meshConfigFile string - dnsConfigFile string - javaAgentConfigFile string - valuesFile string - watcher *fsnotify.Watcher - certFile string - keyFile string - cert *tls.Certificate - + server *http.Server + watcher *fsnotify.Watcher k8sClient kubernetes.Interface } -type InjectConfigInfo struct { - MeshInjectConf *Config - DnsInjectConf *Config - JavaAgentInjectConf *Config - MeshConf *mesh.MeshConfig - ValuesConf string -} - -// env will be used for other things besides meshConfig - when webhook is running in Istiod it can take advantage -// of the config and endpoint cache. -// nolint -func loadConfig(injectMeshFile, injectDnsFile, injectJavaFile, meshFile, valuesFile string) (*InjectConfigInfo, error) { - // 处理 polaris-sidecar mesh 模式的注入 - meshData, err := os.ReadFile(injectMeshFile) - if err != nil { - return nil, err - } - var meshConf Config - if err := gyaml.Unmarshal(meshData, &meshConf); err != nil { - log.InjectScope().Warnf("Failed to parse inject mesh config file %s", string(meshData)) - return nil, err - } - - // 处理 polaris-sidecar dns 模式的注入 - dnsData, err := os.ReadFile(injectDnsFile) - if err != nil { - return nil, err - } - var dnsConf Config - if err := gyaml.Unmarshal(dnsData, &dnsConf); err != nil { - log.InjectScope().Warnf("Failed to parse inject dns config file %s", string(dnsData)) - return nil, err - } - - // 处理 java-agent 模式的注入 - javaAgentData, err := os.ReadFile(injectJavaFile) - if err != nil { - return nil, err - } - var javaAgentConf Config - if err := gyaml.Unmarshal(javaAgentData, &javaAgentConf); err != nil { - log.InjectScope().Warnf("Failed to parse inject java-agent config file %s", string(dnsData)) - return nil, err - } - - valuesConfig, err := os.ReadFile(valuesFile) - if err != nil { - return nil, err - } - - meshConfig, err := mesh.ReadMeshConfig(meshFile) - if err != nil { - return nil, err - } - - log.InjectScope().Infof("[MESH] New inject configuration: sha256sum %x", sha256.Sum256(meshData)) - log.InjectScope().Infof("[MESH] Policy: %v", meshConf.Policy) - log.InjectScope().Infof("[MESH] AlwaysInjectSelector: %v", meshConf.AlwaysInjectSelector) - log.InjectScope().Infof("[MESH] NeverInjectSelector: %v", meshConf.NeverInjectSelector) - log.InjectScope().Infof("[MESH] Template: |\n %v", strings.Replace(meshConf.Template, "\n", "\n ", -1)) - - log.InjectScope().Infof("[DNS] New inject configuration: sha256sum %x", sha256.Sum256(dnsData)) - log.InjectScope().Infof("[DNS] Policy: %v", dnsConf.Policy) - log.InjectScope().Infof("[DNS] AlwaysInjectSelector: %v", dnsConf.AlwaysInjectSelector) - log.InjectScope().Infof("[DNS] NeverInjectSelector: %v", dnsConf.NeverInjectSelector) - log.InjectScope().Infof("[DNS] Template: |\n %v", strings.Replace(dnsConf.Template, "\n", "\n ", -1)) - - log.InjectScope().Infof("[JavaAgent] New inject configuration: sha256sum %x", sha256.Sum256(javaAgentData)) - log.InjectScope().Infof("[JavaAgent] AlwaysInjectSelector: %v", javaAgentConf.AlwaysInjectSelector) - log.InjectScope().Infof("[JavaAgent] NeverInjectSelector: %v", javaAgentConf.NeverInjectSelector) - log.InjectScope().Infof("[JavaAgent] Template: |\n %v", strings.Replace(javaAgentConf.Template, "\n", "\n ", -1)) - - return &InjectConfigInfo{ - MeshInjectConf: &meshConf, - DnsInjectConf: &dnsConf, - JavaAgentInjectConf: &javaAgentConf, - MeshConf: meshConfig, - ValuesConf: string(valuesConfig), - }, nil -} - // WebhookParameters configures parameters for the sidecar injection // webhook. type WebhookParameters struct { // DefaultSidecarMode polaris-sidecar 默认的运行模式 DefaultSidecarMode utils.SidecarMode - // MeshConfigFile 处理 polaris-sidecar 运行模式为 mesh 的配置文件 - MeshConfigFile string - - // DnsConfigFile 处理 polaris-sidecar 运行模式为 dns 的配置文件 - DnsConfigFile string - - // JavaAgentConfigFile 处理运行模式为 javaagent 的配置文件 - JavaAgentConfigFile string - - ValuesFile string - - // MeshFile is the path to the mesh configuration file. - MeshFile string - - // CertFile is the path to the x509 certificate for https. - CertFile string - - // KeyFile is the path to the x509 private key matching `CertFile`. - KeyFile string + // TemplateFileConfig 模板配置文件位置 + TemplateFileConfig config.TemplateFileConfig // Port is the webhook port, e.g. typically 443 for https. Port int @@ -229,61 +108,31 @@ type WebhookParameters struct { // NewWebhook creates a new instance of a mutating webhook for automatic sidecar injection. func NewWebhook(p WebhookParameters) (*Webhook, error) { - // TODO: pass a pointer to mesh config from Pilot bootstrap, no need to watch and load 2 times - // This is needed before we implement advanced merging / patching of mesh config - injectConf, err := loadConfig(p.MeshConfigFile, p.DnsConfigFile, - p.JavaAgentConfigFile, p.MeshFile, p.ValuesFile) - - if err != nil { - return nil, err - } - pair, err := tls.LoadX509KeyPair(p.CertFile, p.KeyFile) - if err != nil { - return nil, err - } - watcher, err := fsnotify.NewWatcher() if err != nil { return nil, err } - - // TODO 直接监听 configmap // watch the parent directory of the target files so we can catch // symlink updates of k8s ConfigMaps volumes. - for _, file := range []string{p.MeshConfigFile, p.DnsConfigFile, p.MeshFile, p.CertFile, p.KeyFile} { - if file == p.MeshFile { - continue - } + for _, file := range p.TemplateFileConfig.GetWatchList() { watchDir, _ := filepath.Split(file) - if err := watcher.Watch(watchDir); err != nil { + if err := watcher.Add(watchDir); err != nil { return nil, fmt.Errorf("could not watch %v: %v", file, err) } } - + templateConfig, err := config.NewTemplateConfig(p.TemplateFileConfig) + if err != nil { + log.InjectScope().Errorf("NewTemplateConfig failed: %v", err) + return nil, err + } wh := &Webhook{ - sidecarMeshConfig: injectConf.MeshInjectConf, - sidecarMeshTemplateVersion: sidecarTemplateVersionHash(injectConf.MeshInjectConf.Template), - sidecarDnsConfig: injectConf.DnsInjectConf, - sidecarDnsTemplateVersion: sidecarTemplateVersionHash(injectConf.DnsInjectConf.Template), - sidecarJavaAgentConfig: injectConf.JavaAgentInjectConf, - sidecarJavaAgentTemplateVersion: sidecarTemplateVersionHash(injectConf.JavaAgentInjectConf.Template), - meshConfig: injectConf.MeshConf, - meshConfigFile: p.MeshConfigFile, - dnsConfigFile: p.DnsConfigFile, - javaAgentConfigFile: p.JavaAgentConfigFile, - valuesFile: p.ValuesFile, - valuesConfig: injectConf.ValuesConf, - meshFile: p.MeshFile, - watcher: watcher, - healthCheckInterval: p.HealthCheckInterval, - healthCheckFile: p.HealthCheckFile, - certFile: p.CertFile, - keyFile: p.KeyFile, - cert: &pair, - - // 新增查询 k8s 资源的操作者 - k8sClient: p.Client, - defaultSidecarMode: p.DefaultSidecarMode, + templateConfig: templateConfig, + templateFileConfig: p.TemplateFileConfig, + watcher: watcher, + healthCheckInterval: p.HealthCheckInterval, + healthCheckFile: p.HealthCheckFile, + k8sClient: p.Client, + defaultSidecarMode: p.DefaultSidecarMode, } if p.Mux != nil { @@ -292,7 +141,7 @@ func NewWebhook(p WebhookParameters) (*Webhook, error) { wh.server = &http.Server{ Addr: fmt.Sprintf(":%v", p.Port), // mtls disabled because apiserver webhook cert usage is still TBD. - TLSConfig: &tls.Config{GetCertificate: wh.getCert}, + TLSConfig: &tls.Config{GetCertificate: wh.templateConfig.GetCert}, } mux := http.NewServeMux() mux.HandleFunc("/inject", wh.serveInject) @@ -325,43 +174,16 @@ func (wh *Webhook) Run(stop <-chan struct{}) { select { case <-timerC: timerC = nil - injectConf, err := loadConfig(wh.meshConfigFile, wh.dnsConfigFile, wh.javaAgentConfigFile, wh.meshFile, wh.valuesFile) - if err != nil { - log.InjectScope().Errorf("update error: %v", err) - break + if err := wh.templateConfig.UpdateTemplateConfig(wh.templateFileConfig); err != nil { + log.InjectScope().Errorf("UpdateTemplateConfig failed: %v", err) } - - pair, err := tls.LoadX509KeyPair(wh.certFile, wh.keyFile) - if err != nil { - log.InjectScope().Errorf("reload cert error: %v", err) - break - } - - sidecarMeshConfig := injectConf.MeshInjectConf - sidecarDnsConfig := injectConf.DnsInjectConf - sidecarJavaagentConfig := injectConf.JavaAgentInjectConf - meshConfig := injectConf.MeshConf - valuesConfig := injectConf.ValuesConf - - wh.mu.Lock() - wh.sidecarMeshConfig = sidecarMeshConfig - wh.sidecarMeshTemplateVersion = sidecarTemplateVersionHash(sidecarMeshConfig.Template) - wh.sidecarDnsConfig = sidecarDnsConfig - wh.sidecarDnsTemplateVersion = sidecarTemplateVersionHash(sidecarDnsConfig.Template) - wh.sidecarJavaAgentConfig = sidecarJavaagentConfig - wh.sidecarJavaAgentTemplateVersion = sidecarTemplateVersionHash(sidecarJavaagentConfig.Template) - - wh.valuesConfig = valuesConfig - wh.meshConfig = meshConfig - wh.cert = &pair - wh.mu.Unlock() - case event := <-wh.watcher.Event: + case event := <-wh.watcher.Events: log.InjectScope().Infof("Injector watch update: %+v", event) // use a timer to debounce configuration updates - if (event.IsModify() || event.IsCreate()) && timerC == nil { + if (event.Op&fsnotify.Write != 0 || event.Op&fsnotify.Create != 0) && timerC == nil { timerC = time.After(watchDebounceDelay) } - case err := <-wh.watcher.Error: + case err := <-wh.watcher.Errors: log.InjectScope().Errorf("Watcher error: %v", err) case <-healthC: content := []byte(`ok`) @@ -374,12 +196,6 @@ func (wh *Webhook) Run(stop <-chan struct{}) { } } -func (wh *Webhook) getCert(*tls.ClientHelloInfo) (*tls.Certificate, error) { - wh.mu.Lock() - defer wh.mu.Unlock() - return wh.cert, nil -} - // It would be great to use https://github.com/mattbaird/jsonpatch to // generate RFC6902 JSON patches. Unfortunately, it doesn't produce // correct patches for object removal. Fortunately, our patching needs @@ -582,30 +398,18 @@ func updateAnnotation(target map[string]string, added map[string]string) (patch return patch } -func (wh *Webhook) createPatch(sidecarMode utils.SidecarMode, pod *corev1.Pod, prevStatus *SidecarInjectionStatus, annotations map[string]string, sic *SidecarInjectionSpec, - workloadName string, -) ([]byte, error) { - +func createPatch(opt *PatchOptions) ([]byte, error) { + sidecarMode := opt.SidecarMode + pod := opt.Pod + prevStatus := opt.PrevStatus + sic := opt.Sic + annotations := opt.Annotations var patch []Rfc6902PatchOperation patchBuilder, ok := _PatchBuilders[utils.ParseSidecarModeName(sidecarMode)] if !ok { return nil, errors.NewInternalError(fmt.Errorf("sidecar-mode %+v not found target patch builder", sidecarMode)) } - if sidecarMode != utils.SidecarForMesh { - delete(annotations, utils.SidecarEnvoyMetadata) - } - - opt := &PatchOptions{ - Pod: pod, - KubeClient: wh.k8sClient, - PrevStatus: prevStatus, - SidecarMode: sidecarMode, - WorkloadName: workloadName, - Sic: sic, - Annotations: annotations, - ExternalInfo: map[string]string{}, - } // Remove any containers previously injected by kube-inject using // container and volume name as unique key for removal. @@ -778,117 +582,31 @@ func toV1beta1AdmissionResponse(err error) *v1beta1.AdmissionResponse { func (wh *Webhook) injectV1beta1(ar *v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { req := ar.Request - var pod corev1.Pod - if err := json.Unmarshal(req.Object.Raw, &pod); err != nil { + log.InjectScope().Infof("Object: %v", string(req.Object.Raw)) + log.InjectScope().Infof("OldObject: %v", string(req.OldObject.Raw)) + // 解析原始对象 + podInfo, err := assignPodDataInfo(req.Object.Raw, req.Namespace, wh) + if err != nil { handleError(fmt.Sprintf("Could not unmarshal raw object: %v %s", err, string(req.Object.Raw))) return toV1beta1AdmissionResponse(err) } - - sidecarMode := wh.getSidecarMode(req.Namespace, &pod) - - // Deal with potential empty fields, e.g., when the pod is created by a deployment - podName := potentialPodName(&pod.ObjectMeta) - if pod.ObjectMeta.Namespace == "" { - pod.ObjectMeta.Namespace = req.Namespace - } - - log.InjectScope().Infof("AdmissionReview for Kind=%v Namespace=%v Name=%v (%v) UID=%v Rfc6902PatchOperation=%v UserInfo=%v", - req.Kind, req.Namespace, req.Name, podName, req.UID, req.Operation, req.UserInfo) - log.InjectScope().Infof("Object: %v", string(req.Object.Raw)) - log.InjectScope().Infof("OldObject: %v", string(req.OldObject.Raw)) - - config := wh.sidecarMeshConfig - tempVersion := wh.sidecarMeshTemplateVersion - if sidecarMode == utils.SidecarForDns { - config = wh.sidecarDnsConfig - tempVersion = wh.sidecarDnsTemplateVersion - } - if sidecarMode == utils.SidecarForJavaAgent { - config = wh.sidecarJavaAgentConfig - tempVersion = wh.sidecarJavaAgentTemplateVersion - } - - if !wh.injectRequired(ignoredNamespaces, config, &pod.Spec, &pod.ObjectMeta) { - log.InjectScope().Infof("Skipping %s/%s due to policy check", pod.ObjectMeta.Namespace, podName) - return &v1beta1.AdmissionResponse{ - Allowed: true, - } - } - // try to capture more useful namespace/name info for deployments, etc. - // TODO(dougreid): expand to enable lookup of OWNERs recursively a la kubernetesenv - deployMeta := pod.ObjectMeta.DeepCopy() - deployMeta.Namespace = req.Namespace - - typeMetadata := &metav1.TypeMeta{ - Kind: "Pod", - APIVersion: "v1", - } - - if len(pod.GenerateName) > 0 { - // if the pod name was generated (or is scheduled for generation), we can begin an investigation into the controlling reference for the pod. - var controllerRef metav1.OwnerReference - controllerFound := false - for _, ref := range pod.GetOwnerReferences() { - if *ref.Controller { - controllerRef = ref - controllerFound = true - break - } - } - if controllerFound { - typeMetadata.APIVersion = controllerRef.APIVersion - typeMetadata.Kind = controllerRef.Kind - - // heuristic for deployment detection - if typeMetadata.Kind == "ReplicaSet" && strings.HasSuffix(controllerRef.Name, pod.Labels["pod-template-hash"]) { - name := strings.TrimSuffix(controllerRef.Name, "-"+pod.Labels["pod-template-hash"]) - deployMeta.Name = name - typeMetadata.Kind = "Deployment" - } else { - deployMeta.Name = controllerRef.Name - } - } - } - - if deployMeta.Name == "" { - // if we haven't been able to extract a deployment name, then just give it the pod name - deployMeta.Name = pod.Name - } - proxyCfg := wh.meshConfig.DefaultConfig - spec, annotations, iStatus, err := InjectionData(config.Template, wh.valuesConfig, tempVersion, typeMetadata, - deployMeta, &pod.Spec, &pod.ObjectMeta, proxyCfg) + log.InjectScope().Infof("AdmissionReview for Kind=%v Namespace=%v Name=%v (%v) UID=%v Rfc6902PatchOperation=%v "+ + "UserInfo=%v", req.Kind, req.Namespace, req.Name, podInfo.podName, req.UID, req.Operation, req.UserInfo) + // 获取准入注入patch + patchBytes, err := wh.getPodPatch(podInfo) if err != nil { - handleError(fmt.Sprintf("Injection data: err=%v spec=%v\n", err, iStatus)) + handleError(fmt.Sprintf("Could not get admission patch: %v", err)) return toV1beta1AdmissionResponse(err) } - // 不需要做任何 POD 修改操作 - if spec == nil { - reviewResponse := v1beta1.AdmissionResponse{ + // 跳过注入 + if patchBytes == nil { + log.InjectScope().Infof("[Webhook] skipping %s/%s due to empty patchBytes", req.Namespace, podInfo.podName) + return &v1beta1.AdmissionResponse{ Allowed: true, } - return &reviewResponse - } - - if len(annotations) == 0 { - annotations = map[string]string{} - } - if len(iStatus) != 0 { - annotations[annotation.SidecarStatus.Name] = iStatus - } - // Add all additional injected annotations - for k, v := range config.InjectedAnnotations { - annotations[k] = v - } - - patchBytes, err := wh.createPatch(sidecarMode, &pod, injectionStatus(&pod), annotations, spec, deployMeta.Name) - if err != nil { - handleError(fmt.Sprintf("AdmissionResponse: err=%v spec=%v\n", err, spec)) - return toV1beta1AdmissionResponse(err) } - log.InjectScope().Infof("AdmissionResponse: patch=%v\n", string(patchBytes)) - reviewResponse := v1beta1.AdmissionResponse{ Allowed: true, Patch: patchBytes, @@ -903,120 +621,31 @@ func (wh *Webhook) injectV1beta1(ar *v1beta1.AdmissionReview) *v1beta1.Admission // inject istio 核心准入注入逻辑 func (wh *Webhook) injectV1(ar *v1.AdmissionReview) *v1.AdmissionResponse { req := ar.Request - var pod corev1.Pod - if err := json.Unmarshal(req.Object.Raw, &pod); err != nil { + log.InjectScope().Infof("Object: %v", string(req.Object.Raw)) + log.InjectScope().Infof("OldObject: %v", string(req.OldObject.Raw)) + // 解析原始对象 + podInfo, err := assignPodDataInfo(req.Object.Raw, req.Namespace, wh) + if err != nil { handleError(fmt.Sprintf("Could not unmarshal raw object: %v %s", err, string(req.Object.Raw))) return toV1AdmissionResponse(err) } - - sidecarMode := wh.getSidecarMode(req.Namespace, &pod) - - // Deal with potential empty fields, e.g., when the pod is created by a deployment - podName := potentialPodName(&pod.ObjectMeta) - if pod.ObjectMeta.Namespace == "" { - pod.ObjectMeta.Namespace = req.Namespace - } - - log.InjectScope().Infof("[Webhook] admissionReview for Kind=%v Namespace=%v Name=%v (%v) UID=%v Rfc6902PatchOperation=%v UserInfo=%v", - req.Kind, req.Namespace, req.Name, podName, req.UID, req.Operation, req.UserInfo) - log.InjectScope().Infof("[Webhook] object: %v", string(req.Object.Raw)) - log.InjectScope().Infof("[Webhook] oldObject: %v", string(req.OldObject.Raw)) - - config := wh.sidecarMeshConfig - tempVersion := wh.sidecarMeshTemplateVersion - if sidecarMode == utils.SidecarForDns { - config = wh.sidecarDnsConfig - tempVersion = wh.sidecarDnsTemplateVersion - } - if sidecarMode == utils.SidecarForJavaAgent { - config = wh.sidecarJavaAgentConfig - tempVersion = wh.sidecarJavaAgentTemplateVersion - } - - if !wh.injectRequired(ignoredNamespaces, config, &pod.Spec, &pod.ObjectMeta) { - log.InjectScope().Infof("[Webhook] skipping %s/%s due to policy check", pod.ObjectMeta.Namespace, podName) - return &v1.AdmissionResponse{ - Allowed: true, - } - } - - // try to capture more useful namespace/name info for deployments, etc. - // TODO(dougreid): expand to enable lookup of OWNERs recursively a la kubernetesenv - deployMeta := pod.ObjectMeta.DeepCopy() - deployMeta.Namespace = req.Namespace - - typeMetadata := &metav1.TypeMeta{ - Kind: "Pod", - APIVersion: "v1", - } - - if len(pod.GenerateName) > 0 { - // if the pod name was generated (or is scheduled for generation), we can begin an investigation into the controlling reference for the pod. - var controllerRef metav1.OwnerReference - controllerFound := false - for _, ref := range pod.GetOwnerReferences() { - if *ref.Controller { - controllerRef = ref - controllerFound = true - break - } - } - if controllerFound { - typeMetadata.APIVersion = controllerRef.APIVersion - typeMetadata.Kind = controllerRef.Kind - - // heuristic for deployment detection - if typeMetadata.Kind == "ReplicaSet" && strings.HasSuffix(controllerRef.Name, pod.Labels["pod-template-hash"]) { - name := strings.TrimSuffix(controllerRef.Name, "-"+pod.Labels["pod-template-hash"]) - deployMeta.Name = name - typeMetadata.Kind = "Deployment" - } else { - deployMeta.Name = controllerRef.Name - } - } - } - - if deployMeta.Name == "" { - // if we haven't been able to extract a deployment name, then just give it the pod name - deployMeta.Name = pod.Name - } - - copyProxyCfg := wh.meshConfig.Clone() - spec, annotations, iStatus, err := InjectionData(config.Template, wh.valuesConfig, tempVersion, typeMetadata, deployMeta, - &pod.Spec, &pod.ObjectMeta, copyProxyCfg.DefaultConfig) + log.InjectScope().Infof("AdmissionReview for Kind=%v Namespace=%v Name=%v (%v) UID=%v Rfc6902PatchOperation=%v "+ + "UserInfo=%v", req.Kind, req.Namespace, req.Name, podInfo.podName, req.UID, req.Operation, req.UserInfo) + // 获取准入注入patch + patchBytes, err := wh.getPodPatch(podInfo) if err != nil { - handleError(fmt.Sprintf("Injection data: err=%v spec=%v\n", err, iStatus)) + handleError(fmt.Sprintf("Could not get admission patch: %v", err)) return toV1AdmissionResponse(err) } - // 不需要做任何 POD 修改操作 - if spec == nil { - reviewResponse := v1.AdmissionResponse{ + // 跳过注入 + if patchBytes == nil { + log.InjectScope().Infof("[Webhook] skipping %s/%s due to empty patchBytes", req.Namespace, podInfo.podName) + return &v1.AdmissionResponse{ Allowed: true, } - return &reviewResponse } - - if len(annotations) == 0 { - annotations = map[string]string{} - } - if len(iStatus) != 0 { - annotations[annotation.SidecarStatus.Name] = iStatus - } - - // Add all additional injected annotations - for k, v := range config.InjectedAnnotations { - annotations[k] = v - } - - patchBytes, err := wh.createPatch(sidecarMode, &pod, injectionStatus(&pod), annotations, spec, deployMeta.Name) - if err != nil { - handleError(fmt.Sprintf("AdmissionResponse: err=%v spec=%v\n", err, spec)) - return toV1AdmissionResponse(err) - } - - log.InjectScope().Infof("[Webhook] admissionResponse: patch=%v\n", string(patchBytes)) - + log.InjectScope().Infof("AdmissionResponse: patch=%v\n", string(patchBytes)) reviewResponse := v1.AdmissionResponse{ Allowed: true, Patch: patchBytes, diff --git a/pkg/util/types.go b/pkg/util/types.go index d37915c3..a385d8ff 100644 --- a/pkg/util/types.go +++ b/pkg/util/types.go @@ -48,9 +48,30 @@ const ( // SidecarBindPort xds metadata key when node is run in sidecar mode SidecarBindPort = "sidecar.polarismesh.cn/bindPorts" // SidecarEnvoyMetadata - SidecarEnvoyMetadata = "sidecar.polarismesh.cn/envoyMetadata" + SidecarEnvoyMetadata = "sidecar.polarismesh.cn/envoyMetadata" + SidecarEnvoyInjectKey = "sidecar.polarismesh.cn/openOnDemand" + SidecarEnvoyInjectProxyKey = "OPEN_DEMAND" PolarisSidecarModeLabel = "polaris-sidecar-mode" + + // InjectAdmissionKey 标记是否开启注入 + InjectAdmissionKey = "polarismesh.cn/inject" + // InjectAdmissionValueEnabled 开启注入(白名单功能)的标记值 + InjectAdmissionValueEnabled = "enabled" + // InjectAdmissionValueDisabled 关闭注入(黑名单功能)的标记值 + InjectAdmissionValueDisabled = "disabled" + // InjectionValueTrue 多处使用的标记值 + InjectionValueTrue = "true" + + AnnotationKeyWorkloadNamespaceAsServiceNamespace = "polarismesh.cn/workloadNamespaceAsServiceNamespace" + AnnotationKeyWorkloadNameAsServiceName = "polarismesh.cn/workloadNameAsServiceName" + + // AnnotationKeyInjectJavaAgent 注入模式为 javaagent 的标记 + AnnotationKeyInjectJavaAgent = "polarismesh.cn/javaagent" + AnnotationKeyJavaAgentVersion = "polarismesh.cn/javaagentVersion" + AnnotationKeyJavaAgentPluginFramework = "polarismesh.cn/javaagentFrameworkName" + AnnotationKeyJavaAgentPluginFrameworkVersion = "polarismesh.cn/javaagentFrameworkVersion" + AnnotationKeyJavaAgentPluginConfig = "polarismesh.cn/javaagentConfig" ) const ( diff --git a/version b/version index 75e47606..0d687f1e 100644 --- a/version +++ b/version @@ -1 +1 @@ -v1.7.2 \ No newline at end of file +v1.7.3 \ No newline at end of file