mirror of https://github.com/linkerd/linkerd2.git
Add allow and link commands (#4466)
This change adds a `allow` and `link` commands, effectivelly enabling a cluster to have more than one set of credentials that allow it to be mirrored. Fx #4461 Signed-off-by: Zahari Dichev <zaharidichev@gmail.com> Co-authored-by: Alex Leong <alex@buoyant.io>
This commit is contained in:
parent
d4cdd956f5
commit
7b46682841
|
@ -5,8 +5,7 @@ set -e
|
|||
setValues() {
|
||||
sed -i "s/$1/$2/" charts/linkerd2/values.yaml
|
||||
sed -i "s/$1/$2/" charts/linkerd2-cni/values.yaml
|
||||
sed -i "s/$1/$2/" charts/linkerd2-service-mirror/values.yaml
|
||||
sed -i "s/$1/$2/" charts/linkerd2-multicluster-remote-setup/values.yaml
|
||||
sed -i "s/$1/$2/" charts/linkerd2-multicluster/values.yaml
|
||||
}
|
||||
|
||||
showErr() {
|
||||
|
@ -20,8 +19,7 @@ trap 'showErr' ERR
|
|||
bindir=$( cd "${BASH_SOURCE[0]%/*}" && pwd )
|
||||
rootdir=$( cd "$bindir"/.. && pwd )
|
||||
|
||||
"$bindir"/helm lint "$rootdir"/charts/linkerd2-multicluster-remote-setup
|
||||
"$bindir"/helm lint "$rootdir"/charts/linkerd2-service-mirror
|
||||
"$bindir"/helm lint "$rootdir"/charts/linkerd2-multicluster
|
||||
"$bindir"/helm lint "$rootdir"/charts/partials
|
||||
"$bindir"/helm dep up "$rootdir"/charts/linkerd2-cni
|
||||
"$bindir"/helm lint "$rootdir"/charts/linkerd2-cni
|
||||
|
@ -51,9 +49,7 @@ if [ "$1" = package ]; then
|
|||
|
||||
"$bindir"/helm --version "$version" --app-version "$tag" -d "$rootdir"/target/helm package "$rootdir"/charts/linkerd2
|
||||
"$bindir"/helm --version "$version" --app-version "$tag" -d "$rootdir"/target/helm package "$rootdir"/charts/linkerd2-cni
|
||||
# TODO: When ready to publish, uncomment
|
||||
#"$bindir"/helm --version $version --app-version $tag -d "$rootdir"/target/helm package "$rootdir"/charts/linkerd2-service-mirror
|
||||
#"$bindir"/helm --version $version --app-version $tag -d "$rootdir"/target/helm package "$rootdir"/charts/linkerd2-multicluster-remote-setup
|
||||
"$bindir"/helm --version "$version" --app-version "$tag" -d "$rootdir"/target/helm package "$rootdir"/charts/linkerd2-multicluster
|
||||
mv "$rootdir"/target/helm/index-pre.yaml "$rootdir"/target/helm/index-pre-"$version".yaml
|
||||
"$bindir"/helm repo index --url "https://helm.linkerd.io/$repo/" --merge "$rootdir"/target/helm/index-pre-"$version".yaml "$rootdir"/target/helm
|
||||
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
|
||||
# Linkerd2-multicluster-remote-setup Helm Chart
|
||||
|
||||
Linkerd is a *service mesh*, designed to give platform-wide observability,
|
||||
reliability, and security without requiring configuration or code changes. This
|
||||
chart provides a reference cluster gateway implementation, which coupled with
|
||||
Linkerd and the Service Mirror component can enable multicluster communication
|
||||
and service discovery
|
||||
|
||||
## Configuration
|
||||
|
||||
The following table lists the configurable parameters of the
|
||||
linkerd2-multicluster-remote-setup chart and their default values.
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|--------------------------|-----------------------------------------------------------------------------------------------------------------|------------------------|
|
||||
|`gatewayName` | The name of the gateway that will be installed | `linkerd-gateway` |
|
||||
|`namespace` | The namespace in which the gateway and SA will be created |`linkerd-multicluster` |
|
||||
|`identityTrustDomain` | Trust domain used for identity of the existing linkerd installation |`cluster.local` |
|
||||
|`incomingPort` | The port on which all the gateway will accept incoming traffic |`4180` |
|
||||
|`linkerdNamespace` | The namespace of the existing Linkerd installation |`linkerd` |
|
||||
|`nginxImage` | The Nginx image |`nginx` |
|
||||
|`nginxImageVersion` | The version of the Nginx image |`1.17` |
|
||||
|`probePath` | The path that will be used by remote clusters for determining whether the gateway is alive |`/health` |
|
||||
|`probePeriodSeconds` | The interval (in seconds) between liveness probes |`3` |
|
||||
|`probePort` | The port used for liveliness probing |`4181` |
|
||||
|`serviceAccountName` | The name of the service account that will be created and used by remote clusters, attempting to mirror services |`linkerd-service-mirror`|
|
|
@ -1,16 +0,0 @@
|
|||
gatewayName: linkerd-gateway
|
||||
namespace: linkerd-multicluster
|
||||
identityTrustDomain: cluster.local
|
||||
incomingPort: 4180
|
||||
linkerdNamespace: linkerd
|
||||
probePath: /health
|
||||
probePeriodSeconds: 3
|
||||
probePort: 4181
|
||||
serviceAccountName: linkerd-service-mirror-remote-access
|
||||
linkerdVersion: linkerdVersionValue
|
||||
createdByAnnotation: linkerd.io/created-by
|
||||
nginxImageVersion: 1.17
|
||||
nginxImage: nginx
|
||||
proxyOutboundPort: 4140
|
||||
localProbePath: /health-local
|
||||
localProbePort: 8888
|
|
@ -3,5 +3,5 @@ appVersion: edge-XX.X.X
|
|||
description: A helm chart containing the resources to enable mirroring of services on remote clusters
|
||||
kubeVersion: ">=1.13.0-0"
|
||||
icon: https://linkerd.io/images/logo-only-200h.png
|
||||
name: "linkerd2-multicluster-remote-setup"
|
||||
name: "linkerd2-multicluster"
|
||||
version: 0.1.0
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
# Linkerd2-multicluster Helm Chart
|
||||
|
||||
Linkerd is a *service mesh*, designed to give platform-wide observability,
|
||||
reliability, and security without requiring configuration or code changes. This
|
||||
chart provides the components needed to enable communication between clusters.
|
||||
|
||||
## Configuration
|
||||
|
||||
The following table lists the configurable parameters of the
|
||||
linkerd2-multicluster chart and their default values.
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|---------------------------------|---------------------------------------------------------------------------------------------|----------------------------------------------|
|
||||
|`controllerComponentLabel` | Control plane label. Do not edit |`linkerd.io/control-plane-component` |
|
||||
|`controllerImage` | Docker image for the Service mirror component (uses the Linkerd controller image) |`gcr.io/linkerd-io/controller` |
|
||||
|`controllerImageVersion` | Tag for the Service Mirror container Docker image |`latest version` |
|
||||
|`createdByAnnotation` | Annotation label for the proxy create. Do not edit. |`linkerd.io/created-by` |
|
||||
|`gateway` | If the gateway component should be installed |`true` |
|
||||
|`gatewayLocalProbePath` | The path that will be used by the local liveness checks to ensure the gateway is alive |`/health-local` |
|
||||
|`gatewayLocalProbePort` | The port that will be used by the local liveness checks to ensure the gateway is alive |`8888` |
|
||||
|`gatewayName` | The name of the gateway that will be installed |`linkerd-gateway` |
|
||||
|`gatewayNginxImage` | The Nginx image |`nginx` |
|
||||
|`gatewayNginxImageVersion` | The version of the Nginx image |`1.17` |
|
||||
|`gatewayPort` | The port on which all the gateway will accept incoming traffic |`4180` |
|
||||
|`gatewayProbePath` | The path that will be used by remote clusters for determining whether the gateway is alive |`/health` |
|
||||
|`gatewayProbePort` | The port used for liveliness probing |`4181` |
|
||||
|`gatewayProbeSeconds` | The interval (in seconds) between liveness probes |`3` |
|
||||
|`identityTrustDomain` | Trust domain used for identity of the existing linkerd installation |`cluster.local` |
|
||||
|`linkerdNamespace` | The namespace of the existing Linkerd installation |`linkerd` |
|
||||
|`linkerdVersion` | Control plane version | latest version |
|
||||
|`namespace` | Service Mirror component namespace |`linkerd-multicluster` |
|
||||
|`proxyOutboundPort` | The port on which the proxy accepts outbound traffic |`4140` |
|
||||
|`remoteAccessServiceAccountName` | The name of the service account used to allow remote clusters to mirror local services |`linkerd-service-mirror-remote-access-default`|
|
||||
|`remoteMirrorServiceAccount` | If the remote mirror service account should be installed |`true` |
|
||||
|`serviceMirror` | If the service mirror component should be installed |`true` |
|
||||
|`logLevel` | Log level for the Multicluster components |`info` |
|
||||
|`serviceMirrorRetryLimit` | Number of times update from the remote cluster is allowed to be requeued (retried) |`3` |
|
||||
|`serviceMirrorUID` | User id under which the Service Mirror shall be ran |`2103` |
|
|
@ -1,3 +1,4 @@
|
|||
{{if .Values.gateway -}}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
|
@ -12,21 +13,21 @@ data:
|
|||
}
|
||||
stream {
|
||||
server {
|
||||
listen {{.Values.incomingPort}};
|
||||
listen {{.Values.gatewayPort}};
|
||||
proxy_pass 127.0.0.1:{{.Values.proxyOutboundPort}};
|
||||
}
|
||||
}
|
||||
http {
|
||||
server {
|
||||
listen {{.Values.probePort}};
|
||||
location {{.Values.probePath}} {
|
||||
listen {{.Values.gatewayProbePort}};
|
||||
location {{.Values.gatewayProbePath}} {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
}
|
||||
}
|
||||
server {
|
||||
listen {{.Values.localProbePort}};
|
||||
location {{.Values.localProbePath}} {
|
||||
listen {{.Values.gatewayLocalProbePort}};
|
||||
location {{.Values.gatewayLocalProbePath}} {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
}
|
||||
|
@ -55,7 +56,7 @@ spec:
|
|||
annotations:
|
||||
{{.Values.createdByAnnotation}}: {{default (printf "linkerd/helm %s" .Values.linkerdVersion) .Values.cliVersion}}
|
||||
linkerd.io/inject: enabled
|
||||
config.linkerd.io/proxy-require-identity-inbound-ports: "{{.Values.probePort}},{{.Values.incomingPort}}"
|
||||
config.linkerd.io/proxy-require-identity-inbound-ports: "{{.Values.gatewayProbePort}},{{.Values.gatewayPort}}"
|
||||
labels:
|
||||
app: {{.Values.gatewayName}}
|
||||
spec:
|
||||
|
@ -68,21 +69,21 @@ spec:
|
|||
readinessProbe:
|
||||
failureThreshold: 7
|
||||
httpGet:
|
||||
path: {{.Values.localProbePath}}
|
||||
port: {{.Values.localProbePort}}
|
||||
path: {{.Values.gatewayLocalProbePath}}
|
||||
port: {{.Values.gatewayLocalProbePort}}
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: {{.Values.localProbePath}}
|
||||
port: {{.Values.localProbePort}}
|
||||
path: {{.Values.gatewayLocalProbePath}}
|
||||
port: {{.Values.gatewayLocalProbePort}}
|
||||
initialDelaySeconds: 10
|
||||
image: {{.Values.nginxImage}}:{{.Values.nginxImageVersion}}
|
||||
image: {{.Values.gatewayNginxImage}}:{{.Values.gatewayNginxImageVersion}}
|
||||
ports:
|
||||
- name: incoming-port
|
||||
containerPort: {{.Values.incomingPort}}
|
||||
containerPort: {{.Values.gatewayPort}}
|
||||
- name: probe-port
|
||||
containerPort: {{.Values.probePort}}
|
||||
containerPort: {{.Values.gatewayProbePort}}
|
||||
- name: local-probe
|
||||
containerPort: {{.Values.localProbePort}}
|
||||
containerPort: {{.Values.gatewayLocalProbePort}}
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /etc/nginx
|
||||
|
@ -95,18 +96,18 @@ metadata:
|
|||
namespace: {{.Values.namespace}}
|
||||
annotations:
|
||||
mirror.linkerd.io/gateway-identity: {{.Values.gatewayName}}.{{.Values.namespace}}.serviceaccount.identity.{{.Values.linkerdNamespace}}.{{.Values.identityTrustDomain}}
|
||||
mirror.linkerd.io/probe-port: "{{.Values.probePort}}"
|
||||
mirror.linkerd.io/probe-period: "{{.Values.probePeriodSeconds}}"
|
||||
mirror.linkerd.io/probe-path: {{.Values.probePath}}
|
||||
mirror.linkerd.io/probe-port: "{{.Values.gatewayProbePort}}"
|
||||
mirror.linkerd.io/probe-period: "{{.Values.gatewayProbeSeconds}}"
|
||||
mirror.linkerd.io/probe-path: {{.Values.gatewayProbePath}}
|
||||
mirror.linkerd.io/multicluster-gateway: "true"
|
||||
{{.Values.createdByAnnotation}}: {{default (printf "linkerd/helm %s" .Values.linkerdVersion) .Values.cliVersion}}
|
||||
spec:
|
||||
ports:
|
||||
- name: incoming-port
|
||||
port: {{.Values.incomingPort}}
|
||||
port: {{.Values.gatewayPort}}
|
||||
protocol: TCP
|
||||
- name: probe-port
|
||||
port: {{.Values.probePort}}
|
||||
port: {{.Values.gatewayProbePort}}
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: {{.Values.gatewayName}}
|
||||
|
@ -117,4 +118,4 @@ apiVersion: v1
|
|||
metadata:
|
||||
name: {{.Values.gatewayName}}
|
||||
namespace: {{.Values.namespace}}
|
||||
|
||||
{{end -}}
|
|
@ -1,8 +1,9 @@
|
|||
{{if .Values.remoteMirrorServiceAccount -}}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: {{.Values.serviceAccountName}}
|
||||
name: {{.Values.remoteMirrorServiceAccountName}}
|
||||
namespace: {{.Values.namespace}}
|
||||
annotations:
|
||||
{{.Values.createdByAnnotation}}: {{default (printf "linkerd/helm %s" .Values.linkerdVersion) .Values.cliVersion}}
|
||||
|
@ -18,7 +19,7 @@ rules:
|
|||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{.Values.serviceAccountName}}
|
||||
name: {{.Values.remoteMirrorServiceAccountName}}
|
||||
namespace: {{.Values.namespace}}
|
||||
annotations:
|
||||
{{.Values.createdByAnnotation}}: {{default (printf "linkerd/helm %s" .Values.linkerdVersion) .Values.cliVersion}}
|
||||
|
@ -26,16 +27,17 @@ metadata:
|
|||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: {{.Values.serviceAccountName}}
|
||||
name: {{.Values.remoteMirrorServiceAccountName}}
|
||||
namespace: {{.Values.namespace}}
|
||||
annotations:
|
||||
{{.Values.createdByAnnotation}}: {{default (printf "linkerd/helm %s" .Values.linkerdVersion) .Values.cliVersion}}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: {{.Values.serviceAccountName}}
|
||||
name: {{.Values.remoteMirrorServiceAccountName}}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{.Values.serviceAccountName}}
|
||||
name: {{.Values.remoteMirrorServiceAccountName}}
|
||||
namespace: {{.Values.namespace}}
|
||||
{{end -}}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
{{if .Values.serviceMirror -}}
|
||||
---
|
||||
kind: Namespace
|
||||
apiVersion: v1
|
||||
|
@ -92,7 +93,7 @@ spec:
|
|||
- args:
|
||||
- service-mirror
|
||||
- -log-level={{.Values.logLevel}}
|
||||
- -event-requeue-limit={{.Values.eventRequeueLimit}}
|
||||
- -event-requeue-limit={{.Values.serviceMirrorRetryLimit}}
|
||||
- -namespace={{.Values.namespace}}
|
||||
image: {{.Values.controllerImage}}:{{.Values.controllerImageVersion}}
|
||||
name: service-mirror
|
||||
|
@ -102,3 +103,4 @@ spec:
|
|||
- containerPort: 9999
|
||||
name: admin-http
|
||||
serviceAccountName: linkerd-service-mirror
|
||||
{{end -}}
|
|
@ -0,0 +1,25 @@
|
|||
controllerComponentLabel: linkerd.io/control-plane-component
|
||||
controllerImage: gcr.io/linkerd-io/controller
|
||||
controllerImageVersion: linkerdVersionValue
|
||||
createdByAnnotation: linkerd.io/created-by
|
||||
gateway: true
|
||||
gatewayLocalProbePath: /health-local
|
||||
gatewayLocalProbePort: 8888
|
||||
gatewayName: linkerd-gateway
|
||||
gatewayNginxImage: nginx
|
||||
gatewayNginxImageVersion: 1.17
|
||||
gatewayPort: 4180
|
||||
gatewayProbePath: /health
|
||||
gatewayProbePort: 4181
|
||||
gatewayProbeSeconds: 3
|
||||
identityTrustDomain: cluster.local
|
||||
linkerdNamespace: linkerd
|
||||
linkerdVersion: linkerdVersionValue
|
||||
namespace: linkerd-multicluster
|
||||
proxyOutboundPort: 4140
|
||||
serviceMirror: true
|
||||
logLevel: info
|
||||
serviceMirrorRetryLimit: 3
|
||||
serviceMirrorUID: 2103
|
||||
remoteMirrorServiceAccount: true
|
||||
remoteMirrorServiceAccountName: linkerd-service-mirror-remote-access-default
|
|
@ -1,22 +0,0 @@
|
|||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
OWNERS
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
|
@ -1,8 +0,0 @@
|
|||
apiVersion: v1
|
||||
appVersion: edge-XX.X.X
|
||||
description: A helm chart containing the resources needed by the Linkerd Service Mirror component.
|
||||
kubeVersion: ">=1.13.0-0"
|
||||
icon: https://linkerd.io/images/logo-only-200h.png
|
||||
name: "linkerd2-service-mirror"
|
||||
version: 0.1.0
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
|
||||
# Linkerd2-service-mirror Helm Chart
|
||||
|
||||
Linkerd is a *service mesh*, designed to give platform-wide observability,
|
||||
reliability, and security without requiring configuration or code changes. The
|
||||
Linkerd Service Mirror makes it possible to mirror services located on remote
|
||||
clusters with the purpose of routing traffic to them.
|
||||
|
||||
## Configuration
|
||||
|
||||
The following table lists the configurable parameters of the
|
||||
linkerd2-service-mirror chart and their default values.
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|--------------------------------------|-----------------------------------------------------------------------------------|-------------------------------|
|
||||
|`controllerComponentLabel` | Control plane label. Do not edit | `linkerd.io/control-plane-component`|
|
||||
|`controllerImage` | Docker image for the Service mirror component (uses the Linkerd controller image) |`gcr.io/linkerd-io/controller`|
|
||||
|`controllerImageVersion` | Tag for the Service Mirror container Docker image |latest version|
|
||||
|`namespace` | Service Mirror component namespace |`linkerd-service-mirror`|
|
||||
|`serviceMirrorUID` | User id under which the Service Mirror shall be ran |`2103`|
|
||||
|`logLevel` | Log level for the Service Mirror component |`info`|
|
||||
|`eventRequeueLimit` | Number of times update from the remote cluster is allowed to be requeued (retried)|`3`|
|
|
@ -1,7 +0,0 @@
|
|||
namespace: linkerd-multicluster
|
||||
serviceMirrorUID: 2103
|
||||
logLevel: info
|
||||
eventRequeueLimit: 3
|
||||
controllerImage: gcr.io/linkerd-io/controller
|
||||
controllerImageVersion: linkerdVersionValue
|
||||
controllerComponentLabel: linkerd.io/control-plane-component
|
|
@ -1,153 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/linkerd/linkerd2/pkg/charts"
|
||||
"github.com/linkerd/linkerd2/pkg/charts/servicemirror"
|
||||
"github.com/linkerd/linkerd2/pkg/version"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/helm/pkg/chartutil"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
type installServiceMirrorOptions struct {
|
||||
namespace string
|
||||
controlPlaneVersion string
|
||||
dockerRegistry string
|
||||
logLevel string
|
||||
uid int64
|
||||
requeueLimit int32
|
||||
}
|
||||
|
||||
const helmServiceMirrorDefaultChartName = "linkerd2-service-mirror"
|
||||
|
||||
func newCmdInstallServiceMirror() *cobra.Command {
|
||||
options, err := newInstallServiceMirrorOptionsWithDefaults()
|
||||
if err != nil {
|
||||
fmt.Fprint(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "install-service-mirror [flags]",
|
||||
Short: "Output Kubernetes configs to install Linkerd Service Mirror",
|
||||
Long: "Output Kubernetes configs to install Linkerd Service Mirror",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return renderServiceMirror(os.Stdout, options)
|
||||
},
|
||||
Hidden: true,
|
||||
}
|
||||
|
||||
cmd.PersistentFlags().StringVarP(&options.controlPlaneVersion, "control-plane-version", "", options.controlPlaneVersion, "(Development) Tag to be used for the control plane component images")
|
||||
cmd.PersistentFlags().StringVar(&options.dockerRegistry, "registry", options.dockerRegistry, "Docker registry to pull images from")
|
||||
cmd.PersistentFlags().StringVarP(&options.logLevel, "log-level", "", options.logLevel, "Log level for the Service Mirror Component")
|
||||
cmd.PersistentFlags().Int64Var(&options.uid, "uid", options.uid, "Run the Service Mirror component under this user ID")
|
||||
cmd.PersistentFlags().Int32Var(&options.requeueLimit, "event-requeue-limit", options.requeueLimit, "The number of times a failed update from the remote cluster is allowed to be requeued (retried)")
|
||||
cmd.PersistentFlags().StringVarP(&options.namespace, "namespace", "", options.namespace, "The namespace in which the Service Mirror Component is to be installed")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func newInstallServiceMirrorOptionsWithDefaults() (*installServiceMirrorOptions, error) {
|
||||
defaults, err := servicemirror.NewValues()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &installServiceMirrorOptions{
|
||||
namespace: defaults.Namespace,
|
||||
controlPlaneVersion: version.Version,
|
||||
dockerRegistry: defaultDockerRegistry,
|
||||
logLevel: defaults.LogLevel,
|
||||
uid: defaults.ServiceMirrorUID,
|
||||
requeueLimit: defaults.EventRequeueLimit,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (options *installServiceMirrorOptions) buildValues() (*servicemirror.Values, error) {
|
||||
installValues, err := servicemirror.NewValues()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
installValues.Namespace = options.namespace
|
||||
installValues.LogLevel = options.logLevel
|
||||
installValues.ControllerImageVersion = options.controlPlaneVersion
|
||||
installValues.ControllerImage = fmt.Sprintf("%s/controller", options.dockerRegistry)
|
||||
installValues.ServiceMirrorUID = options.uid
|
||||
installValues.EventRequeueLimit = options.requeueLimit
|
||||
|
||||
return installValues, nil
|
||||
}
|
||||
|
||||
func (options *installServiceMirrorOptions) validate() error {
|
||||
|
||||
_, err := getLinkerdConfigMap()
|
||||
if err != nil {
|
||||
if kerrors.IsNotFound(err) {
|
||||
return errors.New("you need Linkerd to be installed in order to install the service mirroring component")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if !alphaNumDashDot.MatchString(options.controlPlaneVersion) {
|
||||
return fmt.Errorf("%s is not a valid version", options.controlPlaneVersion)
|
||||
}
|
||||
|
||||
if options.namespace == "" {
|
||||
return errors.New("you need to specify a namespace")
|
||||
}
|
||||
|
||||
if options.namespace == controlPlaneNamespace {
|
||||
return errors.New("you need to install the service mirror component in a namespace different than the Linkerd one")
|
||||
}
|
||||
|
||||
if _, err := log.ParseLevel(options.logLevel); err != nil {
|
||||
return fmt.Errorf("--log-level must be one of: panic, fatal, error, warn, info, debug")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func renderServiceMirror(w io.Writer, config *installServiceMirrorOptions) error {
|
||||
if err := config.validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
values, err := config.buildValues()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Render raw values and create chart config
|
||||
rawValues, err := yaml.Marshal(values)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
files := []*chartutil.BufferedFile{
|
||||
{Name: chartutil.ChartfileName},
|
||||
{Name: "templates/service-mirror.yaml"},
|
||||
}
|
||||
|
||||
chart := &charts.Chart{
|
||||
Name: helmServiceMirrorDefaultChartName,
|
||||
Dir: helmServiceMirrorDefaultChartName,
|
||||
Namespace: controlPlaneNamespace,
|
||||
RawValues: rawValues,
|
||||
Files: files,
|
||||
}
|
||||
buf, err := chart.RenderNoPartials()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.Write(buf.Bytes())
|
||||
w.Write([]byte("---\n"))
|
||||
|
||||
return nil
|
||||
|
||||
}
|
|
@ -10,8 +10,6 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/linkerd/linkerd2/cli/table"
|
||||
configPb "github.com/linkerd/linkerd2/controller/gen/config"
|
||||
pb "github.com/linkerd/linkerd2/controller/gen/public"
|
||||
|
@ -21,10 +19,12 @@ import (
|
|||
"github.com/linkerd/linkerd2/pkg/healthcheck"
|
||||
"github.com/linkerd/linkerd2/pkg/k8s"
|
||||
"github.com/linkerd/linkerd2/pkg/version"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
yamlDecoder "k8s.io/apimachinery/pkg/util/yaml"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/client-go/tools/clientcmd/api"
|
||||
|
@ -33,32 +33,40 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
defaultMulticlusterNamespace = "linkerd-multicluster"
|
||||
helmMulticlusterRemoteSetuprDefaultChartName = "linkerd2-multicluster-remote-setup"
|
||||
tokenKey = "token"
|
||||
defaultServiceAccountName = "linkerd-service-mirror-remote-access"
|
||||
defaultClusterName = "remote"
|
||||
defaultMulticlusterNamespace = "linkerd-multicluster"
|
||||
helmMulticlusterDefaultChartName = "linkerd2-multicluster"
|
||||
tokenKey = "token"
|
||||
defaultServiceAccountName = "linkerd-service-mirror-remote-access-default"
|
||||
)
|
||||
|
||||
type (
|
||||
getCredentialsOptions struct {
|
||||
namespace string
|
||||
serviceAccountName string
|
||||
serviceAccountNamespace string
|
||||
clusterName string
|
||||
remoteClusterDomain string
|
||||
}
|
||||
|
||||
setupRemoteClusterOptions struct {
|
||||
allowOptions struct {
|
||||
namespace string
|
||||
serviceAccountName string
|
||||
gatewayName string
|
||||
probePort uint32
|
||||
incomingPort uint32
|
||||
probePeriodSeconds uint32
|
||||
probePath string
|
||||
nginxImageVersion string
|
||||
nginxImage string
|
||||
ignoreCluster bool
|
||||
}
|
||||
|
||||
multiclusterInstallOptions struct {
|
||||
gateway bool
|
||||
gatewayPort uint32
|
||||
gatewayProbeSeconds uint32
|
||||
gatewayProbePort uint32
|
||||
namespace string
|
||||
serviceMirror bool
|
||||
serviceMirrorRetryLimit uint32
|
||||
logLevel string
|
||||
gatewayNginxImage string
|
||||
gatewayNginxVersion string
|
||||
controlPlaneVersion string
|
||||
dockerRegistry string
|
||||
remoteMirrorCredentials bool
|
||||
}
|
||||
|
||||
linkOptions struct {
|
||||
namespace string
|
||||
clusterName string
|
||||
apiServerAddress string
|
||||
serviceAccountName string
|
||||
}
|
||||
|
||||
exportServiceOptions struct {
|
||||
|
@ -73,22 +81,26 @@ type (
|
|||
}
|
||||
)
|
||||
|
||||
func newSetupRemoteClusterOptionsWithDefault() (*setupRemoteClusterOptions, error) {
|
||||
func newMulticlusterInstallOptionsWithDefault() (*multiclusterInstallOptions, error) {
|
||||
defaults, err := mccharts.NewValues()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &setupRemoteClusterOptions{
|
||||
serviceAccountName: defaults.ServiceAccountName,
|
||||
namespace: defaults.Namespace,
|
||||
gatewayName: defaults.GatewayName,
|
||||
probePort: defaults.ProbePort,
|
||||
incomingPort: defaults.IncomingPort,
|
||||
probePeriodSeconds: defaults.ProbePeriodSeconds,
|
||||
probePath: defaults.ProbePath,
|
||||
nginxImageVersion: defaults.NginxImageVersion,
|
||||
nginxImage: defaults.NginxImage,
|
||||
return &multiclusterInstallOptions{
|
||||
gateway: defaults.Gateway,
|
||||
gatewayPort: defaults.GatewayPort,
|
||||
gatewayProbeSeconds: defaults.GatewayProbeSeconds,
|
||||
gatewayProbePort: defaults.GatewayProbePort,
|
||||
namespace: defaults.Namespace,
|
||||
serviceMirror: defaults.ServiceMirror,
|
||||
serviceMirrorRetryLimit: defaults.ServiceMirrorRetryLimit,
|
||||
logLevel: defaults.LogLevel,
|
||||
gatewayNginxImage: defaults.GatewayNginxImage,
|
||||
gatewayNginxVersion: defaults.GatewayNginxImageVersion,
|
||||
controlPlaneVersion: version.Version,
|
||||
dockerRegistry: defaultDockerRegistry,
|
||||
remoteMirrorCredentials: true,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
@ -107,42 +119,161 @@ func getLinkerdConfigMap() (*configPb.All, error) {
|
|||
return global, nil
|
||||
}
|
||||
|
||||
func buildMulticlusterSetupValues(opts *setupRemoteClusterOptions) (*multicluster.Values, error) {
|
||||
func buildMulticlusterInstallValues(opts *multiclusterInstallOptions) (*multicluster.Values, error) {
|
||||
|
||||
global, err := getLinkerdConfigMap()
|
||||
if err != nil {
|
||||
if kerrors.IsNotFound(err) {
|
||||
return nil, errors.New("you need Linkerd to be installed in order to setup a remote cluster")
|
||||
return nil, errors.New("you need Linkerd to be installed in order to install multicluster addons")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !alphaNumDashDot.MatchString(opts.controlPlaneVersion) {
|
||||
return nil, fmt.Errorf("%s is not a valid version", opts.controlPlaneVersion)
|
||||
}
|
||||
|
||||
if opts.namespace == "" {
|
||||
return nil, errors.New("you need to specify a namespace")
|
||||
}
|
||||
|
||||
if opts.namespace == controlPlaneNamespace {
|
||||
return nil, errors.New("you need to setup the multicluster addons in a namespace different than the Linkerd one")
|
||||
}
|
||||
|
||||
if _, err := log.ParseLevel(opts.logLevel); err != nil {
|
||||
return nil, fmt.Errorf("--log-level must be one of: panic, fatal, error, warn, info, debug")
|
||||
}
|
||||
|
||||
defaults, err := mccharts.NewValues()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if opts.probePort == defaults.LocalProbePort {
|
||||
return nil, fmt.Errorf("The probe port needs to be different from %d which is the local probe port", defaults.LocalProbePort)
|
||||
if opts.gatewayProbePort == defaults.GatewayLocalProbePort {
|
||||
return nil, fmt.Errorf("The probe port needs to be different from %d which is the local probe port", opts.gatewayProbePort)
|
||||
}
|
||||
|
||||
defaults.GatewayName = opts.gatewayName
|
||||
defaults.Namespace = opts.namespace
|
||||
defaults.Gateway = opts.gateway
|
||||
defaults.GatewayPort = opts.gatewayPort
|
||||
defaults.GatewayProbeSeconds = opts.gatewayProbeSeconds
|
||||
defaults.GatewayProbePort = opts.gatewayProbePort
|
||||
defaults.ServiceMirror = opts.serviceMirror
|
||||
defaults.ServiceMirrorRetryLimit = opts.serviceMirrorRetryLimit
|
||||
defaults.LogLevel = opts.logLevel
|
||||
defaults.GatewayNginxImage = opts.gatewayNginxImage
|
||||
defaults.GatewayNginxImageVersion = opts.gatewayNginxVersion
|
||||
defaults.IdentityTrustDomain = global.Global.IdentityContext.TrustDomain
|
||||
defaults.IncomingPort = opts.incomingPort
|
||||
defaults.LinkerdNamespace = controlPlaneNamespace
|
||||
defaults.ProbePath = opts.probePath
|
||||
defaults.ProbePeriodSeconds = opts.probePeriodSeconds
|
||||
defaults.ProbePort = opts.probePort
|
||||
defaults.ProxyOutboundPort = global.Proxy.OutboundPort.Port
|
||||
defaults.ServiceAccountName = opts.serviceAccountName
|
||||
defaults.NginxImageVersion = opts.nginxImageVersion
|
||||
defaults.NginxImage = opts.nginxImage
|
||||
defaults.LinkerdVersion = version.Version
|
||||
defaults.ControllerImageVersion = opts.controlPlaneVersion
|
||||
defaults.ControllerImage = fmt.Sprintf("%s/controller", opts.dockerRegistry)
|
||||
defaults.RemoteMirrorServiceAccount = opts.remoteMirrorCredentials
|
||||
|
||||
return defaults, nil
|
||||
}
|
||||
|
||||
func buildMulticlusterAllowValues(opts *allowOptions) (*mccharts.Values, error) {
|
||||
|
||||
kubeAPI, err := k8s.NewAPI(kubeconfigPath, kubeContext, impersonate, impersonateGroup, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if opts.namespace == "" {
|
||||
return nil, errors.New("you need to specify a namespace")
|
||||
}
|
||||
|
||||
if opts.serviceAccountName == "" {
|
||||
return nil, errors.New("you need to specify a service account name")
|
||||
}
|
||||
|
||||
if opts.namespace == controlPlaneNamespace {
|
||||
return nil, errors.New("you need to setup the multicluster addons in a namespace different than the Linkerd one")
|
||||
}
|
||||
|
||||
defaults, err := mccharts.NewValues()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defaults.Namespace = opts.namespace
|
||||
defaults.LinkerdVersion = version.Version
|
||||
defaults.Gateway = false
|
||||
defaults.ServiceMirror = false
|
||||
defaults.RemoteMirrorServiceAccount = true
|
||||
defaults.RemoteMirrorServiceAccountName = opts.serviceAccountName
|
||||
|
||||
if !opts.ignoreCluster {
|
||||
acc, err := kubeAPI.CoreV1().ServiceAccounts(defaults.Namespace).Get(defaults.RemoteMirrorServiceAccountName, metav1.GetOptions{})
|
||||
if err == nil && acc != nil {
|
||||
return nil, fmt.Errorf("Service account with name %s already exists, use --ignore-cluster for force operation", defaults.RemoteMirrorServiceAccountName)
|
||||
}
|
||||
if !kerrors.IsNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return defaults, nil
|
||||
}
|
||||
|
||||
func newAllowCommand() *cobra.Command {
|
||||
opts := allowOptions{
|
||||
namespace: defaultMulticlusterNamespace,
|
||||
ignoreCluster: false,
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Hidden: false,
|
||||
Use: "allow",
|
||||
Short: "Outputs credential resources that allow service-mirror controllers to connect to this cluster",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
values, err := buildMulticlusterAllowValues(&opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Render raw values and create chart config
|
||||
rawValues, err := yaml.Marshal(values)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
files := []*chartutil.BufferedFile{
|
||||
{Name: chartutil.ChartfileName},
|
||||
{Name: "templates/namespace.yaml"},
|
||||
{Name: "templates/remote-access-service-mirror-rbac.yaml"},
|
||||
}
|
||||
|
||||
chart := &charts.Chart{
|
||||
Name: helmMulticlusterDefaultChartName,
|
||||
Dir: helmMulticlusterDefaultChartName,
|
||||
Namespace: controlPlaneNamespace,
|
||||
RawValues: rawValues,
|
||||
Files: files,
|
||||
}
|
||||
buf, err := chart.RenderNoPartials()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stdout.Write(buf.Bytes())
|
||||
stdout.Write([]byte("---\n"))
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVar(&opts.namespace, "namespace", defaultMulticlusterNamespace, "The destination namespace for the service account.")
|
||||
cmd.Flags().BoolVar(&opts.ignoreCluster, "ignore-cluster", false, "Ignore cluster configuration")
|
||||
cmd.Flags().StringVar(&opts.serviceAccountName, "service-account-name", "", "The name of the remote access service account")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func newGatewaysCommand() *cobra.Command {
|
||||
|
||||
opts := gatewaysOptions{}
|
||||
|
@ -175,24 +306,20 @@ func newGatewaysCommand() *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func newSetupRemoteCommand() *cobra.Command {
|
||||
options, err := newSetupRemoteClusterOptionsWithDefault()
|
||||
func newMulticlusterInstallCommand() *cobra.Command {
|
||||
options, err := newMulticlusterInstallOptionsWithDefault()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "setup-remote",
|
||||
Short: "Sets up the remote cluster by creating the gateway and necessary credentials",
|
||||
Args: cobra.NoArgs,
|
||||
Use: "install",
|
||||
Short: "Output Kubernetes configs to install the Linkerd multicluster add-on",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
values, err := buildMulticlusterSetupValues(options)
|
||||
|
||||
if options.namespace == controlPlaneNamespace {
|
||||
return errors.New("you need to specify a namespace different than the one in which Linkerd is installed")
|
||||
}
|
||||
values, err := buildMulticlusterInstallValues(options)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -208,12 +335,13 @@ func newSetupRemoteCommand() *cobra.Command {
|
|||
{Name: chartutil.ChartfileName},
|
||||
{Name: "templates/namespace.yaml"},
|
||||
{Name: "templates/gateway.yaml"},
|
||||
{Name: "templates/service-mirror-rbac.yaml"},
|
||||
{Name: "templates/service-mirror.yaml"},
|
||||
{Name: "templates/remote-access-service-mirror-rbac.yaml"},
|
||||
}
|
||||
|
||||
chart := &charts.Chart{
|
||||
Name: helmMulticlusterRemoteSetuprDefaultChartName,
|
||||
Dir: helmMulticlusterRemoteSetuprDefaultChartName,
|
||||
Name: helmMulticlusterDefaultChartName,
|
||||
Dir: helmMulticlusterDefaultChartName,
|
||||
Namespace: controlPlaneNamespace,
|
||||
RawValues: rawValues,
|
||||
Files: files,
|
||||
|
@ -229,29 +357,48 @@ func newSetupRemoteCommand() *cobra.Command {
|
|||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVar(&options.gatewayName, "gateway-name", options.gatewayName, "the name of the gateway")
|
||||
cmd.Flags().StringVar(&options.namespace, "namespace", options.namespace, "the namespace in which the gateway and service account will be installed")
|
||||
cmd.Flags().Uint32Var(&options.probePort, "probe-port", options.probePort, "the liveness check port of the gateway")
|
||||
cmd.Flags().Uint32Var(&options.incomingPort, "incoming-port", options.incomingPort, "the port on the gateway used for all incomming traffic")
|
||||
cmd.Flags().StringVar(&options.probePath, "probe-path", options.probePath, "the path that will be exercised by the liveness checks")
|
||||
cmd.Flags().Uint32Var(&options.probePeriodSeconds, "probe-period", options.probePeriodSeconds, "the interval at which the gateway will be checked for being alive in seconds")
|
||||
cmd.Flags().StringVar(&options.serviceAccountName, "service-account-name", options.serviceAccountName, "the name of the service account")
|
||||
cmd.Flags().StringVar(&options.nginxImageVersion, "nginx-image-version", options.nginxImageVersion, "the version of nginx to be used")
|
||||
cmd.Flags().StringVar(&options.nginxImage, "nginx-image", options.nginxImage, "the nginx image to be used")
|
||||
cmd.Flags().StringVar(&options.namespace, "namespace", options.namespace, "The namespace in which the multicluster add-on is to be installed. Must not be the control plane namespace. ")
|
||||
cmd.Flags().BoolVar(&options.gateway, "gateway", options.gateway, "If the gateway component should be installed")
|
||||
cmd.Flags().Uint32Var(&options.gatewayPort, "gateway-port", options.gatewayPort, "The port on the gateway used for all incoming traffic")
|
||||
cmd.Flags().Uint32Var(&options.gatewayProbeSeconds, "gateway-probe-seconds", options.gatewayProbeSeconds, "The interval at which the gateway will be checked for being alive in seconds")
|
||||
cmd.Flags().Uint32Var(&options.gatewayProbePort, "gateway-probe-port", options.gatewayProbePort, "The liveness check port of the gateway")
|
||||
cmd.Flags().BoolVar(&options.serviceMirror, "service-mirror", options.serviceMirror, "If the service-mirror component should be installed")
|
||||
cmd.Flags().Uint32Var(&options.serviceMirrorRetryLimit, "service-mirror-retry-limit", options.serviceMirrorRetryLimit, "The number of times a failed update from the remote cluster is allowed to be retried")
|
||||
cmd.Flags().StringVar(&options.logLevel, "log-level", options.logLevel, "Log level for the Multicluster components")
|
||||
cmd.Flags().StringVar(&options.gatewayNginxImage, "gateway-nginx-image", options.gatewayNginxImage, "The nginx image to be used")
|
||||
cmd.Flags().StringVar(&options.gatewayNginxVersion, "gateway-nginx-image-version", options.gatewayNginxVersion, "The version of nginx to be used")
|
||||
cmd.Flags().StringVarP(&options.controlPlaneVersion, "control-plane-version", "", options.controlPlaneVersion, "(Development) Tag to be used for the control plane component images")
|
||||
cmd.Flags().StringVar(&options.dockerRegistry, "registry", options.dockerRegistry, "Docker registry to pull images from")
|
||||
cmd.Flags().BoolVar(&options.remoteMirrorCredentials, "remote-mirror-credentials", options.remoteMirrorCredentials, "Whether to install the default remote access service account")
|
||||
|
||||
// Hide developer focused flags in release builds.
|
||||
release, err := version.IsReleaseChannel(version.Version)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to parse version: %s", version.Version)
|
||||
}
|
||||
if release {
|
||||
cmd.Flags().MarkHidden("control-plane-version")
|
||||
cmd.Flags().MarkHidden("gateway-nginx-image")
|
||||
cmd.Flags().MarkHidden("gateway-nginx-image-version")
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func newGetCredentialsCommand() *cobra.Command {
|
||||
opts := getCredentialsOptions{}
|
||||
func newLinkCommand() *cobra.Command {
|
||||
opts := linkOptions{}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "get-credentials",
|
||||
Short: "Get cluster credentials as a secret",
|
||||
Args: cobra.NoArgs,
|
||||
Use: "link",
|
||||
Short: "Outputs a Kubernetes secret that allows a service mirror component to connect to this cluster",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
_, err := getLinkerdConfigMap()
|
||||
if opts.clusterName == "" {
|
||||
return errors.New("You need to specify cluster name")
|
||||
}
|
||||
|
||||
configMap, err := getLinkerdConfigMap()
|
||||
if err != nil {
|
||||
if kerrors.IsNotFound(err) {
|
||||
return errors.New("you need Linkerd to be installed on a cluster in order to get its credentials")
|
||||
|
@ -276,7 +423,7 @@ func newGetCredentialsCommand() *cobra.Command {
|
|||
return err
|
||||
}
|
||||
|
||||
sa, err := k.CoreV1().ServiceAccounts(opts.serviceAccountNamespace).Get(opts.serviceAccountName, metav1.GetOptions{})
|
||||
sa, err := k.CoreV1().ServiceAccounts(opts.namespace).Get(opts.serviceAccountName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -292,7 +439,7 @@ func newGetCredentialsCommand() *cobra.Command {
|
|||
return fmt.Errorf("could not find service account token secret for %s", sa.Name)
|
||||
}
|
||||
|
||||
secret, err := k.CoreV1().Secrets(opts.serviceAccountNamespace).Get(secretName, metav1.GetOptions{})
|
||||
secret, err := k.CoreV1().Secrets(opts.namespace).Get(secretName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -319,6 +466,10 @@ func newGetCredentialsCommand() *cobra.Command {
|
|||
|
||||
cluster := config.Clusters[context.Cluster]
|
||||
|
||||
if opts.apiServerAddress != "" {
|
||||
cluster.Server = opts.apiServerAddress
|
||||
}
|
||||
|
||||
config.Clusters = map[string]*api.Cluster{
|
||||
context.Cluster: cluster,
|
||||
}
|
||||
|
@ -336,7 +487,7 @@ func newGetCredentialsCommand() *cobra.Command {
|
|||
Namespace: opts.namespace,
|
||||
Annotations: map[string]string{
|
||||
k8s.RemoteClusterNameLabel: opts.clusterName,
|
||||
k8s.RemoteClusterDomainAnnotation: opts.remoteClusterDomain,
|
||||
k8s.RemoteClusterDomainAnnotation: configMap.Global.ClusterDomain,
|
||||
k8s.RemoteClusterLinkerdNamespaceAnnotation: controlPlaneNamespace,
|
||||
},
|
||||
},
|
||||
|
@ -355,11 +506,10 @@ func newGetCredentialsCommand() *cobra.Command {
|
|||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVar(&opts.namespace, "namespace", defaultMulticlusterNamespace, "the namespace in which the secret will be created")
|
||||
cmd.Flags().StringVar(&opts.serviceAccountName, "service-account-name", defaultServiceAccountName, "the name of the service account")
|
||||
cmd.Flags().StringVar(&opts.serviceAccountNamespace, "service-account-namespace", defaultMulticlusterNamespace, "the namespace in which the svc account resides on the remote cluster")
|
||||
cmd.Flags().StringVar(&opts.clusterName, "cluster-name", defaultClusterName, "cluster name")
|
||||
cmd.Flags().StringVar(&opts.remoteClusterDomain, "remote-cluster-domain", defaultClusterDomain, "custom remote cluster domain")
|
||||
cmd.Flags().StringVar(&opts.namespace, "namespace", defaultMulticlusterNamespace, "The namespace for the service account")
|
||||
cmd.Flags().StringVar(&opts.clusterName, "cluster-name", "", "Cluster name")
|
||||
cmd.Flags().StringVar(&opts.apiServerAddress, "api-server-address", "", "The api server address of the target cluster")
|
||||
cmd.Flags().StringVar(&opts.serviceAccountName, "service-account-name", defaultServiceAccountName, "The name of the service account associated with the credentials")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
@ -597,14 +747,13 @@ func newCmdMulticluster() *cobra.Command {
|
|||
Long: `Manages the multicluster setup for Linkerd.
|
||||
|
||||
This command provides subcommands to manage the multicluster support
|
||||
functionality of Linkerd. You can use it to deploy credentials to
|
||||
remote clusters, extract them as well as export remote services to be
|
||||
available across clusters.`,
|
||||
Example: ` # Setup remote cluster.
|
||||
linkerd --context=cluster-a multicluster setup-remote | kubectl --context=cluster-a apply -f -
|
||||
functionality of Linkerd. You can use it to install the service mirror
|
||||
components on a cluster, manage credentials and link clusters together.`,
|
||||
Example: ` # Install multicluster addons.
|
||||
linkerd --context=cluster-a cluster install | kubectl --context=cluster-a apply -f -
|
||||
|
||||
# Extract mirroring cluster credentials from cluster A and install them on cluster B
|
||||
linkerd --context=cluster-a multicluster get-credentials --cluster-name=remote | kubectl apply --context=cluster-b -f -
|
||||
linkerd --context=cluster-a cluster link --cluster-name=remote | kubectl apply --context=cluster-b -f -
|
||||
|
||||
# Export services from cluster to be available to other clusters
|
||||
kubectl get svc -o yaml | linkerd export-service - | kubectl apply -f -
|
||||
|
@ -615,12 +764,12 @@ available across clusters.`,
|
|||
# Exporting all the resources inside a folder and its sub-folders.
|
||||
linkerd export-service <folder> | kubectl apply -f -`,
|
||||
}
|
||||
|
||||
multiclusterCmd.AddCommand(newGetCredentialsCommand())
|
||||
multiclusterCmd.AddCommand(newSetupRemoteCommand())
|
||||
|
||||
multiclusterCmd.AddCommand(newLinkCommand())
|
||||
multiclusterCmd.AddCommand(newMulticlusterInstallCommand())
|
||||
multiclusterCmd.AddCommand(newExportServiceCommand())
|
||||
multiclusterCmd.AddCommand(newGatewaysCommand())
|
||||
|
||||
multiclusterCmd.AddCommand(newAllowCommand())
|
||||
return multiclusterCmd
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,6 @@ func init() {
|
|||
RootCmd.AddCommand(newCmdUninject())
|
||||
RootCmd.AddCommand(newCmdUpgrade())
|
||||
RootCmd.AddCommand(newCmdVersion())
|
||||
RootCmd.AddCommand(newCmdInstallServiceMirror())
|
||||
RootCmd.AddCommand(newCmdMulticluster())
|
||||
RootCmd.AddCommand(newCmdUninstall())
|
||||
}
|
||||
|
|
|
@ -9,27 +9,36 @@ import (
|
|||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
const helmDefaultChartDir = "linkerd2-multicluster-remote-setup"
|
||||
const helmDefaultChartDir = "linkerd2-multicluster"
|
||||
|
||||
// Values contains the top-level elements in the Helm charts
|
||||
type Values struct {
|
||||
CliVersion string `json:"cliVersion"`
|
||||
GatewayName string `json:"gatewayName"`
|
||||
Namespace string `json:"namespace"`
|
||||
IdentityTrustDomain string `json:"identityTrustDomain"`
|
||||
IncomingPort uint32 `json:"incomingPort"`
|
||||
LinkerdNamespace string `json:"linkerdNamespace"`
|
||||
ProbePath string `json:"probePath"`
|
||||
ProbePeriodSeconds uint32 `json:"probePeriodSeconds"`
|
||||
ProbePort uint32 `json:"probePort"`
|
||||
ProxyOutboundPort uint32 `json:"proxyOutboundPort"`
|
||||
ServiceAccountName string `json:"serviceAccountName"`
|
||||
NginxImageVersion string `json:"nginxImageVersion"`
|
||||
NginxImage string `json:"nginxImage"`
|
||||
LinkerdVersion string `json:"linkerdVersion"`
|
||||
CreatedByAnnotation string `json:"createdByAnnotation"`
|
||||
LocalProbePath string `json:"localProbePath"`
|
||||
LocalProbePort uint32 `json:"localProbePort"`
|
||||
CliVersion string `json:"cliVersion"`
|
||||
ControllerComponentLabel string `json:"controllerComponentLabel"`
|
||||
ControllerImage string `json:"controllerImage"`
|
||||
ControllerImageVersion string `json:"controllerImageVersion"`
|
||||
CreatedByAnnotation string `json:"createdByAnnotation"`
|
||||
Gateway bool `json:"gateway"`
|
||||
GatewayLocalProbePath string `json:"gatewayLocalProbePath"`
|
||||
GatewayLocalProbePort uint32 `json:"gatewayLocalProbePort"`
|
||||
GatewayName string `json:"gatewayName"`
|
||||
GatewayNginxImage string `json:"gatewayNginxImage"`
|
||||
GatewayNginxImageVersion string `json:"gatewayNginxImageVersion"`
|
||||
GatewayPort uint32 `json:"gatewayPort"`
|
||||
GatewayProbePath string `json:"gatewayProbePath"`
|
||||
GatewayProbePort uint32 `json:"gatewayProbePort"`
|
||||
GatewayProbeSeconds uint32 `json:"gatewayProbeSeconds"`
|
||||
IdentityTrustDomain string `json:"identityTrustDomain"`
|
||||
LinkerdNamespace string `json:"linkerdNamespace"`
|
||||
LinkerdVersion string `json:"linkerdVersion"`
|
||||
Namespace string `json:"namespace"`
|
||||
ProxyOutboundPort uint32 `json:"proxyOutboundPort"`
|
||||
ServiceMirror bool `json:"serviceMirror"`
|
||||
LogLevel string `json:"logLevel"`
|
||||
ServiceMirrorRetryLimit uint32 `json:"serviceMirrorRetryLimit"`
|
||||
ServiceMirrorUID int64 `json:"serviceMirrorUID"`
|
||||
RemoteMirrorServiceAccount bool `json:"remoteMirrorServiceAccount"`
|
||||
RemoteMirrorServiceAccountName string `json:"remoteMirrorServiceAccountName"`
|
||||
}
|
||||
|
||||
// NewValues returns a new instance of the Values type.
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
package servicemirror
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/linkerd/linkerd2/pkg/charts"
|
||||
"k8s.io/helm/pkg/chartutil"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
const (
|
||||
helmDefaultServiceMirrorChartDir = "linkerd2-service-mirror"
|
||||
)
|
||||
|
||||
// Values contains the top-level elements in the Helm charts
|
||||
type Values struct {
|
||||
Namespace string `json:"namespace"`
|
||||
ControllerImage string `json:"controllerImage"`
|
||||
ControllerImageVersion string `json:"controllerImageVersion"`
|
||||
ControllerComponentLabel string `json:"controllerComponentLabel"`
|
||||
ServiceMirrorUID int64 `json:"serviceMirrorUID"`
|
||||
LogLevel string `json:"logLevel"`
|
||||
EventRequeueLimit int32 `json:"eventRequeueLimit"`
|
||||
}
|
||||
|
||||
// NewValues returns a new instance of the Values type.
|
||||
func NewValues() (*Values, error) {
|
||||
chartDir := fmt.Sprintf("%s/", helmDefaultServiceMirrorChartDir)
|
||||
v, err := readDefaults(chartDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// readDefaults read all the default variables from the values.yaml file.
|
||||
// chartDir is the root directory of the Helm chart where values.yaml is.
|
||||
func readDefaults(chartDir string) (*Values, error) {
|
||||
file := &chartutil.BufferedFile{
|
||||
Name: chartutil.ValuesfileName,
|
||||
}
|
||||
if err := charts.ReadFile(chartDir, file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
values := Values{}
|
||||
if err := yaml.Unmarshal(charts.InsertVersion(file.Data), &values); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &values, nil
|
||||
}
|
Loading…
Reference in New Issue