Skip to content

Commit

Permalink
Merge pull request #3759 from telepresenceio/thallgren/namespaces-and…
Browse files Browse the repository at this point in the history
…-rbac

Dynamic namespace support
  • Loading branch information
thallgren authored Jan 2, 2025
2 parents 7a9d21f + 08ea777 commit 13f0c83
Show file tree
Hide file tree
Showing 70 changed files with 2,589 additions and 1,072 deletions.
36 changes: 25 additions & 11 deletions CHANGELOG.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# The YAML in this file should contain:
#
# changelog: An (optional) URL to the CHANGELOG for the product.
# items: An array of releases with the following attributes:
# - version: The (optional) version number of the release, if applicable.
# - date: >-
Expand All @@ -22,25 +21,40 @@
# `FOO/releaseNotes.yml`, then the image paths are
# relative to `FOO/release-notes/`.
# - docs: The path to the documentation page where additional information can be found.
# - href: A path from the root to a resource on the getambassador website, takes precedence over a docs link.
#
# For older changes, see CHANGELOG.OLD.md
docTitle: Telepresence Release Notes
docDescription: >-
Release notes for Telepresence by Ambassador Labs, a CNCF project
that enables developers to iterate rapidly on Kubernetes
microservices by arming them with infinite-scale development
environments, access to instantaneous feedback loops, and highly
customizable development environments.
items:
- version: 2.22.0
date: (TBD)
notes:
- type: feature
title: Unify how Traffic Manager selects namespaces
body: |-
The definition of what namespaces that a Traffic Manager would manage use was scattered into several Helm
chart values, such as `manager.Rbac.namespaces`, `client.Rbac.namespaces`, and
`agentInjector.webhook.namespaceSelector`. The definition is now unified to the mutual exclusive top-level
Helm chart values `namespaces` and `namespaceSelector`.
The `namespaces` value is just for convenience and a short form of expressing:
```yaml
namespaceSelector:
matchExpressions:
- key: kubernetes.io/metadata.name
operator: in
values: <namespaces>`.
```
docs: install/manager#static-versus-dynamic-namespace-selection
- type: change
title: Drop deprecated current-cluster-id command.
body: >-
The clusterID was deprecated some time ago, and replaced by the ID of the namespace where the traffic-manager
is installed.
- type: bugfix
title: Conflict detection between namespaced and cluster-wide install.
body: >-
The namespace conflict detection mechanism would only discover conflicts between two _namespaced_ Traffic
Managers trying to manage the same namespace. This is now fixed so that all types conflicts are discovered.
docs: install/manager#namespace-collision-detection
- type: bugfix
title: Don't dispatch DNS discovery queries to the cluster.
body: >-
Expand Down Expand Up @@ -80,7 +94,7 @@ items:
docs: reference/vpn
- type: feature
title: Intercepts targeting a specific container
body: >-
body: |-
In certain scenarios, the container owning the intercepted port differs
from the container the intercept targets. This port owner's sole purpose
is to route traffic from the service to the intended container, often
Expand Down Expand Up @@ -156,7 +170,7 @@ items:
The Helm chart value `workloads` now supports the kinds `deployments.enabled`, `statefulSets.enabled`, `replicaSets.enabled`.
and `rollouts.enabled`. All except `rollouts` are enabled by default. The traffic-manager will ignore workloads, and
Telepresence will not be able to intercept them, if the `enabled` of the corresponding kind is set to `false`.
docs: reference/intecepts/sidecar#disable-workloads
docs: reference/intercepts/sidecar#disable-workloads
- type: feature
title: Improved command auto-completion
body: >-
Expand Down
177 changes: 90 additions & 87 deletions charts/telepresence/README.md

Large diffs are not rendered by default.

151 changes: 130 additions & 21 deletions charts/telepresence/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,128 @@ Traffic Manager Namespace
{{- end }}
{{- end -}}

{{- /*
traffic-manager.namespace-list extracts the list of namespace names from the namespaces variable.
For backward compatibility, it will also consider names from the deprecated managerRbac.namespaces.
It's an error if namespaces and managerRbac.namespaces both have values.
*/}}
{{- define "private.namespace-list" }}
{{- $names := .Values.namespaces }}
{{- if .Values.managerRbac.namespaces }}
{{- if $names }}
{{- fail "namespaces and managerRbac.namespaces are mutually exclusive" }}
{{- end }}
{{- $names = .Values.managerRbac.namespaces }}
{{- end }}
{{- range $names }}
{{- if not (regexMatch `^[a-z0-9]([a-z0-9-]*[a-z0-9])?$` .) }}
{{- fail (printf "namespace %q is not a valid RFC 1123 namespace name" .) }}
{{- end }}
{{- else }}
{{ $names = list }}
{{- end }}
{{- toJson (uniq ($names)) }}
{{- end }}
{{- define "private.namespaceSelector" }}
{{- $labels := list }}
{{- $matches := list }}
{{- with .Values.namespaceSelector }}
{{- with .matchLabels }}
{{- $labels = . }}
{{- end }}
{{- with .matchExpressions }}
{{- $matches = . }}
{{- end }}
{{- end }}
{{- with fromJsonArray (include "private.namespace-list" $) }}
{{- if (or $labels $matches) }}{{ fail "namespaces and namespaceSelector are mutually exclusive" }}{{ end }}
{{- $matches = append $matches (dict "key" "kubernetes.io/metadata.name" "operator" "In" "values" .) }}
{{- end }}
{{- $selector := dict }}
{{- with $labels }}
{{- $selector = set $selector "matchLabels" . }}
{{- end }}
{{- with $matches }}
{{- $selector = set $selector "matchExpressions" . }}
{{- end }}
{{- toJson $selector }}
{{- end }}
{{- /*
traffic-manager.namespaceSelector extracts the selector to use when selecting namespaces.
This selector will either include the namespaceSelector variable or include namespaces returned by the
private.namespace-list definition. It will fail if both of them have values.
The selector will default to the deprecated agentInjector.webhook.namespaceSelector when neither the namespaceSelector
nor the private.namespace-list definition has any value.
A selector can be dynamic or static. This in turn controls if telepresence is "cluster-wide" or "namespaced". A dynamic
selector requires cluster-wide access for the traffic-manager, and only a static selector can serve as base when
installing Role/RoleBinding pairs.
A selector is considered static if it meets the following conditions:
- The selector must have exactly one element in the `matchLabels` or the `matchExpression`
list (if the element is in the `matchLabels` list, it is normalized into "key in [value]").
- The element must meet the following criteria:
The `key` of the match expression must be "kubernetes.io/metadata.name".
The `operator` of the match expression must be "In" (case sensitive).
The `values` list of the match expression must contain at least one value.
*/}}
{{- define "traffic-manager.namespaceSelector" }}
{{- $selector := mustFromJson (include "private.namespaceSelector" $) }}
{{- $legacy := false }}
{{- if not $selector }}
{{- with .Values.agentInjector.webhook.namespaceSelector }}
{{- $legacy = true }}
{{- $selector = . }}
{{- end }}
{{- end }}
{{- if not (or $legacy (fromJsonArray (include "traffic-manager.namespaces" $))) }}
{{- /*Ensure that his dynamic selector rejects "kube-system" and "kube-node-lease" */}}
{{- $mes := $selector.matchExpressions }}
{{- if not $mes }}
{{- $mes = list }}
{{- end }}
{{- $selector = set $selector "matchExpressions" (append $mes
(dict "key" "kubernetes.io/metadata.name" "operator" "NotIn" "values" (list "kube-system" "kube-node-lease")))
}}
{{- end }}
{{- toJson $selector }}
{{- end }}
{{- /*
traffic-manager.namespaced will yield the string "true" if the traffic-manager.namespaceSelector that is static.
*/}}
{{- define "traffic-manager.namespaced" }}
{{- if fromJsonArray (include "traffic-manager.namespaces" $) }}
{{- true }}
{{- end }}
{{- end }}
{{- /*
traffic-manager.namespaces will return a list of namespaces, provided that the traffic-manager.namespaceSelector is static.
*/}}
{{- define "traffic-manager.namespaces" }}
{{- $namespaces := list }}
{{- with mustFromJson (include "private.namespaceSelector" $) }}
{{- if and .matchExpressions (eq (len .matchExpressions) 1) (not .matchLabels) }}
{{- with index .matchExpressions 0}}
{{- if (and (eq .operator "In") (eq .key "kubernetes.io/metadata.name")) }}
{{- $namespaces = .values }}
{{- end }}
{{- end }}
{{- end }}
{{- if and .matchLabels (eq (len .matchLabels) 1) (not .matchExpressions) }}
{{- with get .matchLabels "kubernetes.io/metadata.name" }}
{{- $namespaces = list . }}
{{- end }}
{{- end }}
{{- end }}
{{- toJson $namespaces }}
{{- end }}
{{- /*
Create chart name and version as used by the chart label.
*/}}
Expand All @@ -35,8 +157,8 @@ Create chart name and version as used by the chart label.
Common labels
*/}}
{{- define "telepresence.labels" -}}
{{ include "telepresence.selectorLabels" . }}
helm.sh/chart: {{ include "telepresence.chart" . }}
{{ include "telepresence.selectorLabels" $ }}
helm.sh/chart: {{ include "telepresence.chart" $ }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
Expand All @@ -61,37 +183,24 @@ telepresence: manager
Client RBAC name suffix
*/}}
{{- define "telepresence.clientRbacName" -}}
{{ printf "%s-%s" (default (include "telepresence.name" .) .Values.rbac.nameOverride) (include "traffic-manager.namespace" .) }}
{{ printf "%s-%s" (default (include "telepresence.name" $) .Values.rbac.nameOverride) (include "traffic-manager.namespace" $) }}
{{- end -}}

{{- /*
RBAC rules required to create an intercept in a namespace; excludes any rules that are always cluster wide.
*/}}
{{- define "telepresence.clientRbacInterceptRules" -}}
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
{{- /* Mandatory. Controls namespace access command completion experience */}}
- apiGroups: [""]
resources: ["pods"]
verbs: ["list", "get"]
verbs: ["get","list"] {{- /* "list" is only necessary if the client should be able to gather the pod logs */}}
- apiGroups: [""]
resources: ["services"]
verbs: ["list", "watch", "get"]
resources: ["pods/log"]
verbs: ["get"]
{{- /* All traffic will be routed via the traffic-manager unless a portforward can be created directly to a pod */}}
- apiGroups: [""]
resources: ["pods/portforward"]
verbs: ["create"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets", "statefulsets"]
verbs: ["get", "watch", "list"]
{{- if and .Values.workloads .Values.workloads.argoRollouts .Values.workloads.argoRollouts.enabled }}
- apiGroups: ["argoproj.io"]
resources: ["rollouts"]
verbs: ["get", "watch", "list"]
{{- end }}
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["telepresence-agents"]
verbs: ["get", "watch", "list"]
{{- if and .Values.clientRbac .Values.clientRbac.ruleExtras }}
{{ template "clientRbac-ruleExtras" . }}
{{- end }}
Expand Down
2 changes: 1 addition & 1 deletion charts/telepresence/templates/agent-configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: telepresence-agents
namespace: {{ include "traffic-manager.namespace" . }}
namespace: {{ include "traffic-manager.namespace" $ }}
{{- end }}
{{- end }}
Loading

0 comments on commit 13f0c83

Please sign in to comment.