Skip to content

Commit

Permalink
Add support for federated services to the service mirror controller
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Leong <[email protected]>
  • Loading branch information
adleong committed Nov 5, 2024
1 parent 95bf9a3 commit 000ab19
Show file tree
Hide file tree
Showing 20 changed files with 1,536 additions and 251 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ rules:
- apiGroups: ["multicluster.linkerd.io"]
resources: ["links"]
verbs: ["list", "get", "watch"]
- apiGroups: ["multicluster.linkerd.io"]
resources: ["links/status"]
verbs: ["update"]
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["create", "get", "update", "patch"]
Expand Down
13 changes: 13 additions & 0 deletions multicluster/charts/linkerd-multicluster/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,25 @@ Kubernetes: `>=1.22.0-0`
| imagePullSecrets | list | `[]` | For Private docker registries, authentication is needed. Registry secrets are applied to the respective service accounts |
| linkerdNamespace | string | `"linkerd"` | Namespace of linkerd installation |
| linkerdVersion | string | `"linkerdVersionValue"` | Control plane version |
| localServiceMirror.GID | int | `2103` | Group id under which the Service Mirror shall be ran |
| localServiceMirror.UID | int | `2103` | User id under which the Service Mirror shall be ran |
| localServiceMirror.enablePprof | bool | `false` | enables the use of pprof endpoints on control plane component's admin servers |
| localServiceMirror.federatedServiceSelector | string | `"mirror.linkerd.io/federated=member"` | Label selector for federated service members in the local cluster. |
| localServiceMirror.image.name | string | `"cr.l5d.io/linkerd/controller"` | Docker image for the Service mirror component (uses the Linkerd controller image) |
| localServiceMirror.image.pullPolicy | string | imagePullPolicy | Pull policy for the Service mirror container image |
| localServiceMirror.image.version | string | linkerdVersion | Tag for the Service mirror container image |
| localServiceMirror.logFormat | string | `"plain"` | Log format (`plain` or `json`) |
| localServiceMirror.logLevel | string | `"info"` | Log level for the Multicluster components |
| localServiceMirror.replicas | int | `1` | Number of local service mirror replicas to run |
| localServiceMirror.resources | object | `{}` | Resources for the Service mirror container |
| localServiceMirror.serviceMirrorRetryLimit | int | `3` | Number of times local service mirror updates are allowed to be requeued (retried) |
| namespaceMetadata.image.name | string | `"extension-init"` | Docker image name for the namespace-metadata instance |
| namespaceMetadata.image.pullPolicy | string | imagePullPolicy | Pull policy for the namespace-metadata instance |
| namespaceMetadata.image.registry | string | `"cr.l5d.io/linkerd"` | Docker registry for the namespace-metadata instance |
| namespaceMetadata.image.tag | string | `"v0.1.1"` | Docker image tag for the namespace-metadata instance |
| namespaceMetadata.nodeSelector | object | `{}` | Node selectors for the namespace-metadata instance |
| namespaceMetadata.tolerations | list | `[]` | Tolerations for the namespace-metadata instance |
| podAnnotations | object | `{}` | Additional annotations to add to all pods |
| podLabels | object | `{}` | Additional labels to add to all pods |
| proxyOutboundPort | int | `4140` | The port on which the proxy accepts outbound traffic |
| remoteMirrorServiceAccount | bool | `true` | If the remote mirror service account should be installed |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: linkerd-local-service-mirror-access-local-resources
labels:
linkerd.io/extension: multicluster
component: local-service-mirror
{{- with .Values.commonLabels }}{{ toYaml . | trim | nindent 4 }}{{- end }}
rules:
- apiGroups: [""]
resources: ["endpoints", "services"]
verbs: ["list", "get", "watch", "create", "delete", "update"]
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["list", "get", "watch"]
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["create", "get", "update", "patch"]
- apiGroups: ["multicluster.linkerd.io"]
resources: ["links"]
verbs: ["list", "get", "watch"]
- apiGroups: ["multicluster.linkerd.io"]
resources: ["links/status"]
verbs: ["update"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: linkerd-local-service-mirror-access-local-resources
labels:
linkerd.io/extension: multicluster
component: local-service-mirror
{{- with .Values.commonLabels }}{{ toYaml . | trim | nindent 4 }}{{- end }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: linkerd-local-service-mirror-access-local-resources
subjects:
- kind: ServiceAccount
name: linkerd-local-service-mirror
namespace: {{.Release.Namespace}}
---
kind: ServiceAccount
apiVersion: v1
metadata:
name: linkerd-local-service-mirror
namespace: {{ .Release.Namespace }}
labels:
linkerd.io/extension: multicluster
component: local-service-mirror
{{- with .Values.commonLabels }}{{ toYaml . | trim | nindent 4 }}{{- end }}
{{- include "partials.image-pull-secrets" .Values.imagePullSecrets }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
linkerd.io/extension: multicluster
component: local-service-mirror
{{- with .Values.commonLabels }}{{ toYaml . | trim | nindent 4 }}{{- end }}
name: linkerd-local-service-mirror
namespace: {{ .Release.Namespace }}
spec:
replicas: {{ .Values.localServiceMirror.replicas }}
revisionHistoryLimit: {{.Values.revisionHistoryLimit}}
selector:
matchLabels:
component: local-service-mirror
{{- if .Values.enablePodAntiAffinity }}
strategy:
rollingUpdate:
maxUnavailable: 1
{{- end }}
template:
metadata:
annotations:
linkerd.io/inject: enabled
cluster-autoscaler.kubernetes.io/safe-to-evict: "true"
config.alpha.linkerd.io/proxy-wait-before-exit-seconds: "0"
{{- with .Values.podAnnotations }}{{ toYaml . | trim | nindent 8 }}{{- end }}
labels:
linkerd.io/extension: multicluster
component: local-service-mirror
{{- with .Values.podLabels }}{{ toYaml . | trim | nindent 8 }}{{- end }}
spec:
{{- if .Values.enablePodAntiAffinity}}
{{- with $tree := deepCopy . }}
{{- $_ := set $tree "component" "local-service-mirror" -}}
{{- $_ := set $tree "label" "component" -}}
{{- include "linkerd.affinity" $tree | nindent 6 }}
{{- end }}
{{- end }}
automountServiceAccountToken: false
containers:
- args:
- service-mirror
- -log-level={{.Values.localServiceMirror.logLevel}}
- -log-format={{.Values.localServiceMirror.logFormat}}
- -event-requeue-limit={{.Values.localServiceMirror.serviceMirrorRetryLimit}}
- -namespace={{.Release.Namespace}}
- -enable-pprof={{.Values.localServiceMirror.enablePprof | default false}}
- -local-mirror
- -federated-service-selector={{.Values.localServiceMirror.federatedServiceSelector}}
{{- if or .Values.localServiceMirror.additionalEnv .Values.localServiceMirror.experimentalEnv }}
env:
{{- with .Values.localServiceMirror.additionalEnv }}
{{- toYaml . | nindent 8 -}}
{{- end }}
{{- with .Values.localServiceMirror.experimentalEnv }}
{{- toYaml . | nindent 8 -}}
{{- end }}
{{- end }}
image: {{.Values.localServiceMirror.image.name}}:{{.Values.localServiceMirror.image.version}}
name: service-mirror
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: {{.Values.localServiceMirror.UID}}
runAsGroup: {{.Values.localServiceMirror.GID}}
seccompProfile:
type: RuntimeDefault
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access
readOnly: true
ports:
- containerPort: 9999
name: admin-http
{{- with .Values.localServiceMirror.resources }}
resources: {{ toYaml . | nindent 10 }}
{{- end }}
securityContext:
seccompProfile:
type: RuntimeDefault
serviceAccountName: linkerd-local-service-mirror
volumes:
- {{- include "partials.volumes.manual-mount-service-account-token" . | indent 8 | trimPrefix (repeat 7 " ") }}
{{- with .Values.nodeSelector }}
nodeSelector: {{ toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations: {{ toYaml . | nindent 6 }}
{{- end }}
{{- if .Values.enablePodAntiAffinity }}
---
kind: PodDisruptionBudget
apiVersion: policy/v1
metadata:
name: linkerd-local-service-mirror
namespace: {{ .Release.Namespace }}
labels:
component: local-service-mirror
annotations:
{{ include "partials.annotations.created-by" . }}
spec:
maxUnavailable: 1
selector:
matchLabels:
component: local-service-mirror
{{- end}}
42 changes: 42 additions & 0 deletions multicluster/charts/linkerd-multicluster/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ gateway:

# -- Control plane version
linkerdVersion: linkerdVersionValue
# -- Additional annotations to add to all pods
podAnnotations: {}
# -- Additional labels to add to all pods
podLabels: {}
# -- Labels to apply to all resources
Expand Down Expand Up @@ -112,3 +114,43 @@ createNamespaceMetadataJob: true

# -- Specifies the number of old ReplicaSets to retain to allow rollback.
revisionHistoryLimit: 10

localServiceMirror:
# -- Number of times local service mirror updates are allowed to be requeued
# (retried)
serviceMirrorRetryLimit: 3

# -- Label selector for federated service members in the local cluster.
federatedServiceSelector: "mirror.linkerd.io/federated=member"

# -- Number of local service mirror replicas to run
replicas: 1

image:
# -- Docker image for the Service mirror component (uses the Linkerd controller
# image)
name: cr.l5d.io/linkerd/controller
# -- Pull policy for the Service mirror container image
# @default -- imagePullPolicy
pullPolicy: ""
# -- Tag for the Service mirror container image
# @default -- linkerdVersion
version: linkerdVersionValue

# -- Log level for the Multicluster components
logLevel: info

# -- Log format (`plain` or `json`)
logFormat: plain

# -- enables the use of pprof endpoints on control plane component's admin
# servers
enablePprof: false

# -- User id under which the Service Mirror shall be ran
UID: 2103
# -- Group id under which the Service Mirror shall be ran
GID: 2103

# -- Resources for the Service mirror container
resources: {}
2 changes: 2 additions & 0 deletions multicluster/cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ var TemplatesMulticluster = []string{
"templates/remote-access-service-mirror-rbac.yaml",
"templates/link-crd.yaml",
"templates/service-mirror-policy.yaml",
"templates/local-service-mirror.yaml",
}

func newMulticlusterInstallCommand() *cobra.Command {
Expand Down Expand Up @@ -232,6 +233,7 @@ func buildMulticlusterInstallValues(ctx context.Context, opts *multiclusterInsta
return nil, err
}

defaults.LocalServiceMirror.Image.Version = version.Version
defaults.Gateway.Enabled = opts.gateway.Enabled
defaults.Gateway.Port = opts.gateway.Port
defaults.Gateway.Probe.Seconds = opts.gateway.Probe.Seconds
Expand Down
77 changes: 42 additions & 35 deletions multicluster/cmd/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,25 @@ const (

type (
linkOptions struct {
namespace string
clusterName string
apiServerAddress string
serviceAccountName string
gatewayName string
gatewayNamespace string
serviceMirrorRetryLimit uint32
logLevel string
logFormat string
controlPlaneVersion string
dockerRegistry string
selector string
remoteDiscoverySelector string
gatewayAddresses string
gatewayPort uint32
ha bool
enableGateway bool
output string
namespace string
clusterName string
apiServerAddress string
serviceAccountName string
gatewayName string
gatewayNamespace string
serviceMirrorRetryLimit uint32
logLevel string
logFormat string
controlPlaneVersion string
dockerRegistry string
selector string
remoteDiscoverySelector string
federatedServiceSelector string
gatewayAddresses string
gatewayPort uint32
ha bool
enableGateway bool
output string
}
)

Expand Down Expand Up @@ -237,14 +238,20 @@ A full list of configurable values can be found at https://github.com/linkerd/li
return err
}

federatedServiceSelector, err := metav1.ParseToLabelSelector(opts.federatedServiceSelector)
if err != nil {
return err
}

link := mc.Link{
Name: opts.clusterName,
Namespace: opts.namespace,
TargetClusterName: opts.clusterName,
TargetClusterDomain: configMap.ClusterDomain,
TargetClusterLinkerdNamespace: controlPlaneNamespace,
ClusterCredentialsSecret: fmt.Sprintf("cluster-credentials-%s", opts.clusterName),
RemoteDiscoverySelector: *remoteDiscoverySelector,
RemoteDiscoverySelector: remoteDiscoverySelector,
FederatedServiceSelector: federatedServiceSelector,
}

// If there is a gateway in the exporting cluster, populate Link
Expand Down Expand Up @@ -298,12 +305,10 @@ A full list of configurable values can be found at https://github.com/linkerd/li
}
link.GatewayPort = gatewayPort

selector, err := metav1.ParseToLabelSelector(opts.selector)
link.Selector, err = metav1.ParseToLabelSelector(opts.selector)
if err != nil {
return err
}

link.Selector = *selector
}

obj, err := link.ToUnstructured()
Expand Down Expand Up @@ -384,6 +389,7 @@ A full list of configurable values can be found at https://github.com/linkerd/li
fmt.Sprintf("Docker registry to pull service mirror controller image from ($%s)", flags.EnvOverrideDockerRegistry))
cmd.Flags().StringVarP(&opts.selector, "selector", "l", opts.selector, "Selector (label query) to filter which services in the target cluster to mirror")
cmd.Flags().StringVar(&opts.remoteDiscoverySelector, "remote-discovery-selector", opts.remoteDiscoverySelector, "Selector (label query) to filter which services in the target cluster to mirror in remote discovery mode")
cmd.Flags().StringVar(&opts.federatedServiceSelector, "federated-service-selector", opts.federatedServiceSelector, "Selector (label query) for federated service members in the target cluster")
cmd.Flags().StringVar(&opts.gatewayAddresses, "gateway-addresses", opts.gatewayAddresses, "If specified, overwrites gateway addresses when gateway service is not type LoadBalancer (comma separated list)")
cmd.Flags().Uint32Var(&opts.gatewayPort, "gateway-port", opts.gatewayPort, "If specified, overwrites gateway port when gateway service is not type LoadBalancer")
cmd.Flags().BoolVar(&opts.ha, "ha", opts.ha, "Enable HA configuration for the service-mirror deployment (default false)")
Expand Down Expand Up @@ -482,19 +488,20 @@ func newLinkOptionsWithDefault() (*linkOptions, error) {
}

return &linkOptions{
controlPlaneVersion: version.Version,
namespace: defaultMulticlusterNamespace,
dockerRegistry: pkgcmd.DefaultDockerRegistry,
serviceMirrorRetryLimit: defaults.ServiceMirrorRetryLimit,
logLevel: defaults.LogLevel,
logFormat: defaults.LogFormat,
selector: fmt.Sprintf("%s=%s", k8s.DefaultExportedServiceSelector, "true"),
remoteDiscoverySelector: fmt.Sprintf("%s=%s", k8s.DefaultExportedServiceSelector, "remote-discovery"),
gatewayAddresses: "",
gatewayPort: 0,
ha: false,
enableGateway: true,
output: "yaml",
controlPlaneVersion: version.Version,
namespace: defaultMulticlusterNamespace,
dockerRegistry: pkgcmd.DefaultDockerRegistry,
serviceMirrorRetryLimit: defaults.ServiceMirrorRetryLimit,
logLevel: defaults.LogLevel,
logFormat: defaults.LogFormat,
selector: fmt.Sprintf("%s=%s", k8s.DefaultExportedServiceSelector, "true"),
remoteDiscoverySelector: fmt.Sprintf("%s=%s", k8s.DefaultExportedServiceSelector, "remote-discovery"),
federatedServiceSelector: fmt.Sprintf("%s=%s", k8s.DefaultFederatedServiceSelector, "member"),
gatewayAddresses: "",
gatewayPort: 0,
ha: false,
enableGateway: true,
output: "yaml",
}, nil
}

Expand Down
Loading

0 comments on commit 000ab19

Please sign in to comment.