mirror of
https://github.com/outbackdingo/kamaji.git
synced 2026-01-27 10:19:29 +00:00
feat: konnectivity
This commit is contained in:
committed by
Gonzalo Gabriel Jiménez Fuentes
parent
5b4de76229
commit
3be6cf1c4f
@@ -42,3 +42,32 @@ func (in *TenantControlPlane) GetControlPlaneAddress(ctx context.Context, client
|
||||
|
||||
return "", kamajierrors.MissingValidIPError{}
|
||||
}
|
||||
|
||||
func (in *TenantControlPlane) GetKonnectivityServerAddress(ctx context.Context, client client.Client) (string, error) {
|
||||
var loadBalancerStatus corev1.LoadBalancerStatus
|
||||
|
||||
svc := &corev1.Service{}
|
||||
err := client.Get(ctx, types.NamespacedName{Namespace: in.GetNamespace(), Name: in.Status.Addons.Konnectivity.Service.Name}, svc)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "cannot retrieve Service for Konnectivity")
|
||||
}
|
||||
|
||||
switch {
|
||||
case len(in.Spec.Addons.Konnectivity.ProxyHost) > 0:
|
||||
// Returning the hard-coded value in the specification in case of non LoadBalanced resources
|
||||
return in.Spec.Addons.Konnectivity.ProxyHost, nil
|
||||
case svc.Spec.Type == corev1.ServiceTypeLoadBalancer:
|
||||
loadBalancerStatus = svc.Status.LoadBalancer
|
||||
if len(loadBalancerStatus.Ingress) == 0 {
|
||||
return "", kamajierrors.NonExposedLoadBalancerError{}
|
||||
}
|
||||
|
||||
for _, lb := range loadBalancerStatus.Ingress {
|
||||
if ip := lb.IP; len(ip) > 0 {
|
||||
return ip, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "", kamajierrors.MissingValidIPError{}
|
||||
}
|
||||
|
||||
@@ -98,13 +98,14 @@ type AddonSpec struct{}
|
||||
// KonnectivitySpec defines the spec for Konnectivity.
|
||||
type KonnectivitySpec struct {
|
||||
// Port of Konnectivity proxy server.
|
||||
// +kubebuilder:default=8132
|
||||
ProxyPort int32 `json:"proxyPort"`
|
||||
// Host of Konnectivity proxy server.
|
||||
ProxyHost string `json:"proxyHost,omitempty"`
|
||||
AllowAddressAsExternalIP bool `json:"allowAddressAsExternalIP,omitempty"`
|
||||
// ServiceType allows specifying how to expose the Konnectivity Proxy Server.
|
||||
ServiceType ServiceType `json:"serviceType"`
|
||||
// Version for Konnectivity server and agent.
|
||||
// +kubebuilder:default=v0.0.16
|
||||
// +kubebuilder:default=v0.0.31
|
||||
Version string `json:"version,omitempty"`
|
||||
// ServerImage defines the container image for Konnectivity's server.
|
||||
// +kubebuilder:default=us.gcr.io/k8s-artifacts-prod/kas-network-proxy/proxy-server
|
||||
@@ -155,8 +156,9 @@ type ETCDCertificatesStatus struct {
|
||||
|
||||
// CertificatePrivateKeyPair defines the status.
|
||||
type CertificatePrivateKeyPairStatus struct {
|
||||
SecretName string `json:"secretName,omitempty"`
|
||||
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
|
||||
SecretName string `json:"secretName,omitempty"`
|
||||
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
|
||||
ResourceVersion string `json:"resourceVersion,omitempty"`
|
||||
}
|
||||
|
||||
// CertificatePrivateKeyPair defines the status.
|
||||
@@ -228,6 +230,27 @@ type KubeadmPhasesStatus struct {
|
||||
BootstrapToken KubeadmPhaseStatus `json:"bootstrapToken"`
|
||||
}
|
||||
|
||||
type ExternalKubernetesObjectStatus struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
// Resource version of k8s object
|
||||
RV string `json:"resourceVersion,omitempty"`
|
||||
// Last time when k8s object was updated
|
||||
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
|
||||
}
|
||||
|
||||
// KonnectivityStatus defines the status of Konnectivity as Addon.
|
||||
type KonnectivityStatus struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
EgressSelectorConfiguration string `json:"egressSelectorConfiguration,omitempty"`
|
||||
Certificate CertificatePrivateKeyPairStatus `json:"certificate,omitempty"`
|
||||
Kubeconfig KubeconfigStatus `json:"kubeconfig,omitempty"`
|
||||
ServiceAccount ExternalKubernetesObjectStatus `json:"sa,omitempty"`
|
||||
ClusterRoleBinding ExternalKubernetesObjectStatus `json:"clusterrolebinding,omitempty"`
|
||||
Agent ExternalKubernetesObjectStatus `json:"agent,omitempty"`
|
||||
Service KubernetesServiceStatus `json:"service,omitempty"`
|
||||
}
|
||||
|
||||
// AddonStatus defines the observed state of an Addon.
|
||||
type AddonStatus struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
@@ -247,6 +270,8 @@ func (d *AddonStatus) SetKubeadmConfigResourceVersion(rv string) {
|
||||
type AddonsStatus struct {
|
||||
CoreDNS AddonStatus `json:"coreDNS,omitempty"`
|
||||
KubeProxy AddonStatus `json:"kubeProxy,omitempty"`
|
||||
|
||||
Konnectivity KonnectivityStatus `json:"konnectivity,omitempty"`
|
||||
}
|
||||
|
||||
// TenantControlPlaneStatus defines the observed state of TenantControlPlane.
|
||||
@@ -305,6 +330,8 @@ type KubernetesDeploymentStatus struct {
|
||||
Name string `json:"name"`
|
||||
// The namespace which the Deployment for the given cluster is deployed.
|
||||
Namespace string `json:"namespace"`
|
||||
// Last time when deployment was updated
|
||||
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
|
||||
}
|
||||
|
||||
// KubernetesServiceStatus defines the status for the Tenant Control Plane Service in the management cluster.
|
||||
|
||||
@@ -123,6 +123,7 @@ func (in *AddonsStatus) DeepCopyInto(out *AddonsStatus) {
|
||||
*out = *in
|
||||
in.CoreDNS.DeepCopyInto(&out.CoreDNS)
|
||||
in.KubeProxy.DeepCopyInto(&out.KubeProxy)
|
||||
in.Konnectivity.DeepCopyInto(&out.Konnectivity)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonsStatus.
|
||||
@@ -280,6 +281,22 @@ func (in *ETCDStatus) DeepCopy() *ETCDStatus {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ExternalKubernetesObjectStatus) DeepCopyInto(out *ExternalKubernetesObjectStatus) {
|
||||
*out = *in
|
||||
in.LastUpdate.DeepCopyInto(&out.LastUpdate)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalKubernetesObjectStatus.
|
||||
func (in *ExternalKubernetesObjectStatus) DeepCopy() *ExternalKubernetesObjectStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExternalKubernetesObjectStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *IngressSpec) DeepCopyInto(out *IngressSpec) {
|
||||
*out = *in
|
||||
@@ -435,6 +452,7 @@ func (in *KubeletSpec) DeepCopy() *KubeletSpec {
|
||||
func (in *KubernetesDeploymentStatus) DeepCopyInto(out *KubernetesDeploymentStatus) {
|
||||
*out = *in
|
||||
in.DeploymentStatus.DeepCopyInto(&out.DeploymentStatus)
|
||||
in.LastUpdate.DeepCopyInto(&out.LastUpdate)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesDeploymentStatus.
|
||||
|
||||
@@ -80,7 +80,6 @@ spec:
|
||||
description: Host of Konnectivity proxy server.
|
||||
type: string
|
||||
proxyPort:
|
||||
default: 8132
|
||||
description: Port of Konnectivity proxy server.
|
||||
format: int32
|
||||
type: integer
|
||||
@@ -89,12 +88,21 @@ spec:
|
||||
description: ServerImage defines the container image for Konnectivity's
|
||||
server.
|
||||
type: string
|
||||
serviceType:
|
||||
description: ServiceType allows specifying how to expose the
|
||||
Konnectivity Proxy Server.
|
||||
enum:
|
||||
- ClusterIP
|
||||
- NodePort
|
||||
- LoadBalancer
|
||||
type: string
|
||||
version:
|
||||
default: v0.0.16
|
||||
default: v0.0.31
|
||||
description: Version for Konnectivity server and agent.
|
||||
type: string
|
||||
required:
|
||||
- proxyPort
|
||||
- serviceType
|
||||
type: object
|
||||
kubeProxy:
|
||||
description: AddonSpec defines the spec for every addon.
|
||||
@@ -334,6 +342,248 @@ spec:
|
||||
required:
|
||||
- enabled
|
||||
type: object
|
||||
konnectivity:
|
||||
description: KonnectivityStatus defines the status of Konnectivity
|
||||
as Addon.
|
||||
properties:
|
||||
agent:
|
||||
properties:
|
||||
lastUpdate:
|
||||
description: Last time when k8s object was updated
|
||||
format: date-time
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
resourceVersion:
|
||||
description: Resource version of k8s object
|
||||
type: string
|
||||
type: object
|
||||
certificate:
|
||||
description: CertificatePrivateKeyPair defines the status.
|
||||
properties:
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
resourceVersion:
|
||||
type: string
|
||||
secretName:
|
||||
type: string
|
||||
type: object
|
||||
clusterrolebinding:
|
||||
properties:
|
||||
lastUpdate:
|
||||
description: Last time when k8s object was updated
|
||||
format: date-time
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
resourceVersion:
|
||||
description: Resource version of k8s object
|
||||
type: string
|
||||
type: object
|
||||
egressSelectorConfiguration:
|
||||
type: string
|
||||
enabled:
|
||||
type: boolean
|
||||
kubeconfig:
|
||||
description: TenantControlPlaneKubeconfigsStatus contains
|
||||
information about a the generated kubeconfig.
|
||||
properties:
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
secretName:
|
||||
type: string
|
||||
type: object
|
||||
sa:
|
||||
properties:
|
||||
lastUpdate:
|
||||
description: Last time when k8s object was updated
|
||||
format: date-time
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
resourceVersion:
|
||||
description: Resource version of k8s object
|
||||
type: string
|
||||
type: object
|
||||
service:
|
||||
description: KubernetesServiceStatus defines the status for
|
||||
the Tenant Control Plane Service in the management cluster.
|
||||
properties:
|
||||
conditions:
|
||||
description: Current service state
|
||||
items:
|
||||
description: "Condition contains details for one aspect
|
||||
of the current state of this API Resource. --- This
|
||||
struct is intended for direct use as an array at the
|
||||
field path .status.conditions. For example, type
|
||||
FooStatus struct{ // Represents the observations
|
||||
of a foo's current state. // Known .status.conditions.type
|
||||
are: \"Available\", \"Progressing\", and \"Degraded\"
|
||||
\ // +patchMergeKey=type // +patchStrategy=merge
|
||||
\ // +listType=map // +listMapKey=type Conditions
|
||||
[]metav1.Condition `json:\"conditions,omitempty\"
|
||||
patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`
|
||||
\n // other fields }"
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
description: lastTransitionTime is the last time
|
||||
the condition transitioned from one status to
|
||||
another. This should be when the underlying condition
|
||||
changed. If that is not known, then using the
|
||||
time when the API field changed is acceptable.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: message is a human readable message
|
||||
indicating details about the transition. This
|
||||
may be an empty string.
|
||||
maxLength: 32768
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: observedGeneration represents the .metadata.generation
|
||||
that the condition was set based upon. For instance,
|
||||
if .metadata.generation is currently 12, but the
|
||||
.status.conditions[x].observedGeneration is 9,
|
||||
the condition is out of date with respect to the
|
||||
current state of the instance.
|
||||
format: int64
|
||||
minimum: 0
|
||||
type: integer
|
||||
reason:
|
||||
description: reason contains a programmatic identifier
|
||||
indicating the reason for the condition's last
|
||||
transition. Producers of specific condition types
|
||||
may define expected values and meanings for this
|
||||
field, and whether the values are considered a
|
||||
guaranteed API. The value should be a CamelCase
|
||||
string. This field may not be empty.
|
||||
maxLength: 1024
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||
type: string
|
||||
status:
|
||||
description: status of the condition, one of True,
|
||||
False, Unknown.
|
||||
enum:
|
||||
- "True"
|
||||
- "False"
|
||||
- Unknown
|
||||
type: string
|
||||
type:
|
||||
description: type of condition in CamelCase or in
|
||||
foo.example.com/CamelCase. --- Many .condition.type
|
||||
values are consistent across resources like Available,
|
||||
but because arbitrary conditions can be useful
|
||||
(see .node.status.conditions), the ability to
|
||||
deconflict is important. The regex it matches
|
||||
is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
required:
|
||||
- lastTransitionTime
|
||||
- message
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-map-keys:
|
||||
- type
|
||||
x-kubernetes-list-type: map
|
||||
loadBalancer:
|
||||
description: LoadBalancer contains the current status
|
||||
of the load-balancer, if one is present.
|
||||
properties:
|
||||
ingress:
|
||||
description: Ingress is a list containing ingress
|
||||
points for the load-balancer. Traffic intended for
|
||||
the service should be sent to these ingress points.
|
||||
items:
|
||||
description: 'LoadBalancerIngress represents the
|
||||
status of a load-balancer ingress point: traffic
|
||||
intended for the service should be sent to an
|
||||
ingress point.'
|
||||
properties:
|
||||
hostname:
|
||||
description: Hostname is set for load-balancer
|
||||
ingress points that are DNS based (typically
|
||||
AWS load-balancers)
|
||||
type: string
|
||||
ip:
|
||||
description: IP is set for load-balancer ingress
|
||||
points that are IP based (typically GCE or
|
||||
OpenStack load-balancers)
|
||||
type: string
|
||||
ports:
|
||||
description: Ports is a list of records of service
|
||||
ports If used, every port defined in the service
|
||||
should have an entry in it
|
||||
items:
|
||||
properties:
|
||||
error:
|
||||
description: 'Error is to record the problem
|
||||
with the service port The format of
|
||||
the error shall comply with the following
|
||||
rules: - built-in error values shall
|
||||
be specified in this file and those
|
||||
shall use CamelCase names - cloud
|
||||
provider specific error values must
|
||||
have names that comply with the format
|
||||
foo.example.com/CamelCase. --- The regex
|
||||
it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)'
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
port:
|
||||
description: Port is the port number of
|
||||
the service port of which status is
|
||||
recorded here
|
||||
format: int32
|
||||
type: integer
|
||||
protocol:
|
||||
default: TCP
|
||||
description: 'Protocol is the protocol
|
||||
of the service port of which status
|
||||
is recorded here The supported values
|
||||
are: "TCP", "UDP", "SCTP"'
|
||||
type: string
|
||||
required:
|
||||
- port
|
||||
- protocol
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: The name of the Service for the given cluster.
|
||||
type: string
|
||||
namespace:
|
||||
description: The namespace which the Service for the given
|
||||
cluster is deployed.
|
||||
type: string
|
||||
port:
|
||||
description: The port where the service is running
|
||||
format: int32
|
||||
type: integer
|
||||
required:
|
||||
- name
|
||||
- namespace
|
||||
- port
|
||||
type: object
|
||||
required:
|
||||
- enabled
|
||||
type: object
|
||||
kubeProxy:
|
||||
description: AddonStatus defines the observed state of an Addon.
|
||||
properties:
|
||||
@@ -358,6 +608,8 @@ spec:
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
resourceVersion:
|
||||
type: string
|
||||
secretName:
|
||||
type: string
|
||||
type: object
|
||||
@@ -367,6 +619,8 @@ spec:
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
resourceVersion:
|
||||
type: string
|
||||
secretName:
|
||||
type: string
|
||||
type: object
|
||||
@@ -376,6 +630,8 @@ spec:
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
resourceVersion:
|
||||
type: string
|
||||
secretName:
|
||||
type: string
|
||||
type: object
|
||||
@@ -410,6 +666,8 @@ spec:
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
resourceVersion:
|
||||
type: string
|
||||
secretName:
|
||||
type: string
|
||||
type: object
|
||||
@@ -419,6 +677,8 @@ spec:
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
resourceVersion:
|
||||
type: string
|
||||
secretName:
|
||||
type: string
|
||||
type: object
|
||||
@@ -579,6 +839,10 @@ spec:
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
lastUpdate:
|
||||
description: Last time when deployment was updated
|
||||
format: date-time
|
||||
type: string
|
||||
name:
|
||||
description: The name of the Deployment for the given cluster.
|
||||
type: string
|
||||
|
||||
@@ -61,39 +61,48 @@ spec:
|
||||
description: TenantControlPlaneSpec defines the desired state of TenantControlPlane.
|
||||
properties:
|
||||
addons:
|
||||
default:
|
||||
coreDNS:
|
||||
enabled: true
|
||||
kubeProxy:
|
||||
enabled: true
|
||||
description: Addons contain which addons are enabled
|
||||
properties:
|
||||
coreDNS:
|
||||
default:
|
||||
enabled: true
|
||||
description: AddonSpec defines the spec for every addon.
|
||||
properties:
|
||||
enabled:
|
||||
default: true
|
||||
type: boolean
|
||||
type: object
|
||||
konnectivity:
|
||||
default:
|
||||
enabled: true
|
||||
description: AddonSpec defines the spec for every addon.
|
||||
description: KonnectivitySpec defines the spec for Konnectivity.
|
||||
properties:
|
||||
enabled:
|
||||
default: true
|
||||
agentImage:
|
||||
default: us.gcr.io/k8s-artifacts-prod/kas-network-proxy/proxy-agent
|
||||
description: AgentImage defines the container image for Konnectivity's agent.
|
||||
type: string
|
||||
allowAddressAsExternalIP:
|
||||
type: boolean
|
||||
proxyHost:
|
||||
description: Host of Konnectivity proxy server.
|
||||
type: string
|
||||
proxyPort:
|
||||
description: Port of Konnectivity proxy server.
|
||||
format: int32
|
||||
type: integer
|
||||
serverImage:
|
||||
default: us.gcr.io/k8s-artifacts-prod/kas-network-proxy/proxy-server
|
||||
description: ServerImage defines the container image for Konnectivity's server.
|
||||
type: string
|
||||
serviceType:
|
||||
description: ServiceType allows specifying how to expose the Konnectivity Proxy Server.
|
||||
enum:
|
||||
- ClusterIP
|
||||
- NodePort
|
||||
- LoadBalancer
|
||||
type: string
|
||||
version:
|
||||
default: v0.0.31
|
||||
description: Version for Konnectivity server and agent.
|
||||
type: string
|
||||
required:
|
||||
- proxyPort
|
||||
- serviceType
|
||||
type: object
|
||||
kubeProxy:
|
||||
default:
|
||||
enabled: true
|
||||
description: AddonSpec defines the spec for every addon.
|
||||
properties:
|
||||
enabled:
|
||||
default: true
|
||||
type: boolean
|
||||
type: object
|
||||
type: object
|
||||
controlPlane:
|
||||
@@ -310,10 +319,181 @@ spec:
|
||||
- enabled
|
||||
type: object
|
||||
konnectivity:
|
||||
description: KonnectivityStatus defines the status of Konnectivity as Addon
|
||||
description: KonnectivityStatus defines the status of Konnectivity as Addon.
|
||||
properties:
|
||||
egressSelectorConfigurationStatus:
|
||||
agent:
|
||||
properties:
|
||||
lastUpdate:
|
||||
description: Last time when k8s object was updated
|
||||
format: date-time
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
resourceVersion:
|
||||
description: Resource version of k8s object
|
||||
type: string
|
||||
type: object
|
||||
certificate:
|
||||
description: CertificatePrivateKeyPair defines the status.
|
||||
properties:
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
resourceVersion:
|
||||
type: string
|
||||
secretName:
|
||||
type: string
|
||||
type: object
|
||||
clusterrolebinding:
|
||||
properties:
|
||||
lastUpdate:
|
||||
description: Last time when k8s object was updated
|
||||
format: date-time
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
resourceVersion:
|
||||
description: Resource version of k8s object
|
||||
type: string
|
||||
type: object
|
||||
egressSelectorConfiguration:
|
||||
type: string
|
||||
enabled:
|
||||
type: boolean
|
||||
kubeconfig:
|
||||
description: TenantControlPlaneKubeconfigsStatus contains information about a the generated kubeconfig.
|
||||
properties:
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
secretName:
|
||||
type: string
|
||||
type: object
|
||||
sa:
|
||||
properties:
|
||||
lastUpdate:
|
||||
description: Last time when k8s object was updated
|
||||
format: date-time
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
resourceVersion:
|
||||
description: Resource version of k8s object
|
||||
type: string
|
||||
type: object
|
||||
service:
|
||||
description: KubernetesServiceStatus defines the status for the Tenant Control Plane Service in the management cluster.
|
||||
properties:
|
||||
conditions:
|
||||
description: Current service state
|
||||
items:
|
||||
description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: message is a human readable message indicating details about the transition. This may be an empty string.
|
||||
maxLength: 32768
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
|
||||
format: int64
|
||||
minimum: 0
|
||||
type: integer
|
||||
reason:
|
||||
description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
|
||||
maxLength: 1024
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||
type: string
|
||||
status:
|
||||
description: status of the condition, one of True, False, Unknown.
|
||||
enum:
|
||||
- "True"
|
||||
- "False"
|
||||
- Unknown
|
||||
type: string
|
||||
type:
|
||||
description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
required:
|
||||
- lastTransitionTime
|
||||
- message
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-map-keys:
|
||||
- type
|
||||
x-kubernetes-list-type: map
|
||||
loadBalancer:
|
||||
description: LoadBalancer contains the current status of the load-balancer, if one is present.
|
||||
properties:
|
||||
ingress:
|
||||
description: Ingress is a list containing ingress points for the load-balancer. Traffic intended for the service should be sent to these ingress points.
|
||||
items:
|
||||
description: 'LoadBalancerIngress represents the status of a load-balancer ingress point: traffic intended for the service should be sent to an ingress point.'
|
||||
properties:
|
||||
hostname:
|
||||
description: Hostname is set for load-balancer ingress points that are DNS based (typically AWS load-balancers)
|
||||
type: string
|
||||
ip:
|
||||
description: IP is set for load-balancer ingress points that are IP based (typically GCE or OpenStack load-balancers)
|
||||
type: string
|
||||
ports:
|
||||
description: Ports is a list of records of service ports If used, every port defined in the service should have an entry in it
|
||||
items:
|
||||
properties:
|
||||
error:
|
||||
description: 'Error is to record the problem with the service port The format of the error shall comply with the following rules: - built-in error values shall be specified in this file and those shall use CamelCase names - cloud provider specific error values must have names that comply with the format foo.example.com/CamelCase. --- The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)'
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
port:
|
||||
description: Port is the port number of the service port of which status is recorded here
|
||||
format: int32
|
||||
type: integer
|
||||
protocol:
|
||||
default: TCP
|
||||
description: 'Protocol is the protocol of the service port of which status is recorded here The supported values are: "TCP", "UDP", "SCTP"'
|
||||
type: string
|
||||
required:
|
||||
- port
|
||||
- protocol
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-type: atomic
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
name:
|
||||
description: The name of the Service for the given cluster.
|
||||
type: string
|
||||
namespace:
|
||||
description: The namespace which the Service for the given cluster is deployed.
|
||||
type: string
|
||||
port:
|
||||
description: The port where the service is running
|
||||
format: int32
|
||||
type: integer
|
||||
required:
|
||||
- name
|
||||
- namespace
|
||||
- port
|
||||
type: object
|
||||
required:
|
||||
- enabled
|
||||
type: object
|
||||
kubeProxy:
|
||||
description: AddonStatus defines the observed state of an Addon.
|
||||
@@ -338,6 +518,8 @@ spec:
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
resourceVersion:
|
||||
type: string
|
||||
secretName:
|
||||
type: string
|
||||
type: object
|
||||
@@ -347,6 +529,8 @@ spec:
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
resourceVersion:
|
||||
type: string
|
||||
secretName:
|
||||
type: string
|
||||
type: object
|
||||
@@ -356,6 +540,8 @@ spec:
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
resourceVersion:
|
||||
type: string
|
||||
secretName:
|
||||
type: string
|
||||
type: object
|
||||
@@ -387,6 +573,8 @@ spec:
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
resourceVersion:
|
||||
type: string
|
||||
secretName:
|
||||
type: string
|
||||
type: object
|
||||
@@ -396,6 +584,8 @@ spec:
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
resourceVersion:
|
||||
type: string
|
||||
secretName:
|
||||
type: string
|
||||
type: object
|
||||
@@ -535,6 +725,10 @@ spec:
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
lastUpdate:
|
||||
description: Last time when deployment was updated
|
||||
format: date-time
|
||||
type: string
|
||||
name:
|
||||
description: The name of the Deployment for the given cluster.
|
||||
type: string
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: TenantControlPlane
|
||||
metadata:
|
||||
name: tenantkind
|
||||
spec:
|
||||
controlPlane:
|
||||
deployment:
|
||||
replicas: 2
|
||||
additionalMetadata:
|
||||
annotations:
|
||||
environment.clastix.io: test
|
||||
tier.clastix.io: "0"
|
||||
labels:
|
||||
tenant.clastix.io: test
|
||||
kind.clastix.io: deployment
|
||||
service:
|
||||
additionalMetadata:
|
||||
annotations:
|
||||
environment.clastix.io: test
|
||||
tier.clastix.io: "0"
|
||||
labels:
|
||||
tenant.clastix.io: test
|
||||
kind.clastix.io: service
|
||||
serviceType: ClusterIP
|
||||
ingress:
|
||||
enabled: true
|
||||
hostname: kamaji.local
|
||||
ingressClassName: nginx
|
||||
additionalMetadata:
|
||||
annotations:
|
||||
kubernetes.io/ingress.allow-http: "false"
|
||||
nginx.ingress.kubernetes.io/secure-backends: "true"
|
||||
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
|
||||
kubernetes:
|
||||
version: "v1.23.4"
|
||||
kubelet:
|
||||
cgroupfs: systemd
|
||||
admissionControllers:
|
||||
- LimitRanger
|
||||
- ResourceQuota
|
||||
networkProfile:
|
||||
address: "172.18.0.2"
|
||||
port: 6443
|
||||
domain: "clastix.labs"
|
||||
serviceCidr: "10.96.0.0/16"
|
||||
podCidr: "10.244.0.0/16"
|
||||
dnsServiceIPs:
|
||||
- "10.96.0.10"
|
||||
# addons:
|
||||
# coreDNS:
|
||||
# # enabled: true
|
||||
# kubeProxy:
|
||||
# # enabled: false
|
||||
@@ -1,48 +0,0 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: TenantControlPlane
|
||||
metadata:
|
||||
name: tenant1
|
||||
spec:
|
||||
controlPlane:
|
||||
deployment:
|
||||
replicas: 2
|
||||
additionalMetadata:
|
||||
annotations:
|
||||
environment.clastix.io: test
|
||||
tier.clastix.io: "0"
|
||||
labels:
|
||||
tenant.clastix.io: test
|
||||
kind.clastix.io: deployment
|
||||
service:
|
||||
additionalMetadata:
|
||||
annotations:
|
||||
environment.clastix.io: test
|
||||
tier.clastix.io: "0"
|
||||
labels:
|
||||
tenant.clastix.io: test
|
||||
kind.clastix.io: service
|
||||
serviceType: NodePort
|
||||
ingress:
|
||||
enabled: false
|
||||
kubernetes:
|
||||
version: "v1.23.4"
|
||||
kubelet:
|
||||
cgroupfs: cgroupfs
|
||||
admissionControllers:
|
||||
- LimitRanger
|
||||
- ResourceQuota
|
||||
networkProfile:
|
||||
address: "172.18.0.2"
|
||||
port: 31443
|
||||
domain: "clastix.labs"
|
||||
serviceCidr: "10.96.0.0/16"
|
||||
podCidr: "10.244.0.0/16"
|
||||
dnsServiceIPs:
|
||||
- "10.96.0.10"
|
||||
addons:
|
||||
konnectivity:
|
||||
proxyPort: 31132
|
||||
proxyHost: "172.18.0.2"
|
||||
version: v0.0.31
|
||||
coreDNS: {}
|
||||
kubeProxy:
|
||||
@@ -1,53 +0,0 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: TenantControlPlane
|
||||
metadata:
|
||||
name: tenantkind
|
||||
spec:
|
||||
controlPlane:
|
||||
deployment:
|
||||
replicas: 2
|
||||
additionalMetadata:
|
||||
annotations:
|
||||
environment.clastix.io: test
|
||||
tier.clastix.io: "0"
|
||||
labels:
|
||||
tenant.clastix.io: test
|
||||
kind.clastix.io: deployment
|
||||
service:
|
||||
additionalMetadata:
|
||||
annotations:
|
||||
environment.clastix.io: test
|
||||
tier.clastix.io: "0"
|
||||
labels:
|
||||
tenant.clastix.io: test
|
||||
kind.clastix.io: service
|
||||
serviceType: ClusterIP
|
||||
ingress:
|
||||
enabled: true
|
||||
hostname: kamaji.local
|
||||
ingressClassName: nginx
|
||||
additionalMetadata:
|
||||
annotations:
|
||||
kubernetes.io/ingress.allow-http: "false"
|
||||
nginx.ingress.kubernetes.io/secure-backends: "true"
|
||||
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
|
||||
kubernetes:
|
||||
version: "v1.23.4"
|
||||
kubelet:
|
||||
cgroupfs: systemd
|
||||
# admissionControllers:
|
||||
# - LimitRanger
|
||||
# - ResourceQuota
|
||||
networkProfile:
|
||||
address: "172.18.0.2"
|
||||
port: 6443
|
||||
domain: "clastix.labs"
|
||||
serviceCidr: "10.96.0.0/16"
|
||||
podCidr: "10.244.0.0/16"
|
||||
dnsServiceIPs:
|
||||
- "10.96.0.10"
|
||||
addons:
|
||||
coreDNS:
|
||||
enabled: false
|
||||
# kubeProxy:
|
||||
# enabled: false
|
||||
@@ -1,40 +0,0 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: TenantControlPlane
|
||||
metadata:
|
||||
name: tenant-00
|
||||
namespace: tenants
|
||||
spec:
|
||||
controlPlane:
|
||||
deployment:
|
||||
replicas: 2
|
||||
additionalMetadata:
|
||||
annotations:
|
||||
environment.clastix.io: tenant-00
|
||||
labels:
|
||||
tenant.clastix.io: tenant-00
|
||||
kind.clastix.io: deployment
|
||||
service:
|
||||
additionalMetadata:
|
||||
annotations:
|
||||
environment.clastix.io: tenant-00
|
||||
labels:
|
||||
tenant.clastix.io: tenant-00
|
||||
kind.clastix.io: service
|
||||
serviceType: LoadBalancer
|
||||
ingress:
|
||||
enabled: false
|
||||
kubernetes:
|
||||
version: v1.23.1
|
||||
kubelet:
|
||||
cgroupfs: systemd
|
||||
admissionControllers:
|
||||
- ResourceQuota
|
||||
- LimitRanger
|
||||
networkProfile:
|
||||
address: 192.168.32.150
|
||||
port: 6443
|
||||
domain: clastix.labs
|
||||
serviceCidr: 10.96.0.0/16
|
||||
podCidr: 10.36.0.0/16
|
||||
dnsServiceIPs:
|
||||
- 10.96.0.10
|
||||
@@ -1,49 +0,0 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: TenantControlPlane
|
||||
metadata:
|
||||
name: test
|
||||
namespace: default
|
||||
spec:
|
||||
controlPlane:
|
||||
deployment:
|
||||
replicas: 2
|
||||
additionalMetadata:
|
||||
annotations:
|
||||
environment.clastix.io: test
|
||||
tier.clastix.io: "0"
|
||||
labels:
|
||||
tenant.clastix.io: test
|
||||
kind.clastix.io: deployment
|
||||
service:
|
||||
additionalMetadata:
|
||||
annotations:
|
||||
environment.clastix.io: test
|
||||
tier.clastix.io: "0"
|
||||
labels:
|
||||
tenant.clastix.io: test
|
||||
kind.clastix.io: service
|
||||
serviceType: ClusterIP
|
||||
ingress:
|
||||
enabled: false
|
||||
hostname: kamaji.local
|
||||
ingressClassName: nginx
|
||||
additionalMetadata:
|
||||
annotations:
|
||||
kubernetes.io/ingress.allow-http: "false"
|
||||
nginx.ingress.kubernetes.io/secure-backends: "true"
|
||||
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
|
||||
kubernetes:
|
||||
version: "v1.23.1"
|
||||
kubelet:
|
||||
cgroupfs: systemd
|
||||
admissionControllers:
|
||||
- ResourceQuota
|
||||
- LimitRanger
|
||||
networkProfile:
|
||||
address: "192.168.1.47"
|
||||
port: 6443
|
||||
domain: "clastix.labs"
|
||||
serviceCidr: "10.152.0.0/16"
|
||||
podCidr: "10.1.0.0/16"
|
||||
dnsServiceIPs:
|
||||
- "10.152.183.10"
|
||||
@@ -1,41 +0,0 @@
|
||||
apiVersion: kamaji.clastix.io/v1alpha1
|
||||
kind: TenantControlPlane
|
||||
metadata:
|
||||
name: tenant1
|
||||
spec:
|
||||
controlPlane:
|
||||
deployment:
|
||||
replicas: 2
|
||||
additionalMetadata:
|
||||
annotations:
|
||||
environment.clastix.io: test
|
||||
tier.clastix.io: "0"
|
||||
labels:
|
||||
tenant.clastix.io: test
|
||||
kind.clastix.io: deployment
|
||||
service:
|
||||
additionalMetadata:
|
||||
annotations:
|
||||
environment.clastix.io: test
|
||||
tier.clastix.io: "0"
|
||||
labels:
|
||||
tenant.clastix.io: test
|
||||
kind.clastix.io: service
|
||||
serviceType: NodePort
|
||||
ingress:
|
||||
enabled: false
|
||||
kubernetes:
|
||||
version: "v1.23.4"
|
||||
kubelet:
|
||||
cgroupfs: cgroupfs
|
||||
admissionControllers:
|
||||
- LimitRanger
|
||||
- ResourceQuota
|
||||
networkProfile:
|
||||
address: "192.168.1.47"
|
||||
port: 31443
|
||||
domain: "clastix.labs"
|
||||
serviceCidr: "10.96.0.0/16"
|
||||
podCidr: "10.244.0.0/16"
|
||||
dnsServiceIPs:
|
||||
- "10.96.0.10"
|
||||
@@ -1,3 +1,5 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
package controllers
|
||||
|
||||
import (
|
||||
@@ -41,7 +43,7 @@ func GetResources(config GroupResourceBuilderConfiguration) []resources.Resource
|
||||
|
||||
// GetDeleteableResources returns a list of resources that have to be deleted when tenant control planes are deleted
|
||||
// Currently there is only a default approach
|
||||
// TODO: the idea of this function is to become a factory to return the group of deleteable resources according to the given configuration
|
||||
// TODO: the idea of this function is to become a factory to return the group of deleteable resources according to the given configuration.
|
||||
func GetDeleteableResources(config GroupDeleteableResourceBuilderConfiguration) []resources.DeleteableResource {
|
||||
return getDefaultDeleteableResources(config)
|
||||
}
|
||||
@@ -52,11 +54,12 @@ func getDefaultResources(config GroupResourceBuilderConfiguration) []resources.R
|
||||
resources = append(resources, getKubernetesCertificatesResources(config.client, config.log, config.tcpReconcilerConfig, config.tenantControlPlane)...)
|
||||
resources = append(resources, getKubeconfigResources(config.client, config.log, config.tcpReconcilerConfig, config.tenantControlPlane)...)
|
||||
resources = append(resources, getKubernetesStorageResources(config.client, config.log, config.tcpReconcilerConfig, config.tenantControlPlane)...)
|
||||
resources = append(resources, getKonnectivityResources(config.client, config.tenantControlPlane)...)
|
||||
resources = append(resources, getInternalKonnectivityResources(config.client, config.log, config.tcpReconcilerConfig, config.tenantControlPlane)...)
|
||||
resources = append(resources, getKubernetesDeploymentResources(config.client, config.tcpReconcilerConfig, config.tenantControlPlane)...)
|
||||
resources = append(resources, getKubernetesIngressResources(config.client, config.tenantControlPlane)...)
|
||||
resources = append(resources, getKubeadmPhaseResources(config.client, config.log, config.tenantControlPlane)...)
|
||||
resources = append(resources, getKubeadmAddonResources(config.client, config.log, config.tenantControlPlane)...)
|
||||
resources = append(resources, getExternalKonnectivityResources(config.client, config.log, config.tcpReconcilerConfig, config.tenantControlPlane)...)
|
||||
|
||||
return resources
|
||||
}
|
||||
@@ -258,12 +261,42 @@ func getKubeadmAddonResources(c client.Client, log logr.Logger, tenantControlPla
|
||||
}
|
||||
}
|
||||
|
||||
func getKonnectivityResources(c client.Client, tenantControlPlane kamajiv1alpha1.TenantControlPlane) []resources.Resource {
|
||||
func getExternalKonnectivityResources(c client.Client, log logr.Logger, tcpReconcilerConfig TenantControlPlaneReconcilerConfig, tenantControlPlane kamajiv1alpha1.TenantControlPlane) []resources.Resource {
|
||||
return []resources.Resource{
|
||||
&konnectivity.EgressSelectorConfiguration{
|
||||
&konnectivity.ServiceAccountResource{
|
||||
Client: c,
|
||||
Name: "konnectivity-sa",
|
||||
},
|
||||
&konnectivity.ClusterRoleBindingResource{
|
||||
Client: c,
|
||||
Name: "konnectivity-clusterrolebinding",
|
||||
},
|
||||
&konnectivity.ServiceResource{
|
||||
Client: c,
|
||||
Name: "konnectivity-service",
|
||||
},
|
||||
&konnectivity.Agent{
|
||||
Client: c,
|
||||
Name: "konnectivity-agent",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func getInternalKonnectivityResources(c client.Client, log logr.Logger, tcpReconcilerConfig TenantControlPlaneReconcilerConfig, tenantControlPlane kamajiv1alpha1.TenantControlPlane) []resources.Resource {
|
||||
return []resources.Resource{
|
||||
&konnectivity.EgressSelectorConfigurationResource{
|
||||
Client: c,
|
||||
Name: "konnectivity-egress-selector-configuration",
|
||||
},
|
||||
&konnectivity.CertificateResource{
|
||||
Client: c,
|
||||
Log: log,
|
||||
Name: "konnectivity-certificate",
|
||||
},
|
||||
&konnectivity.KubeconfigResource{
|
||||
Client: c,
|
||||
Name: "konnectivity-kubeconfig",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,3 +37,6 @@ kamaji-kind-worker-push: kamaji-kind-worker-build
|
||||
|
||||
kamaji-kind-worker-join:
|
||||
$(kind_path)/join-node.bash
|
||||
|
||||
kamaji-kind-worker-join-through-konnectivity:
|
||||
$(kind_path)/join-node-konnectivity.bash
|
||||
|
||||
34
deploy/kind/join-node-konnectivity.bash
Executable file
34
deploy/kind/join-node-konnectivity.bash
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Constants
|
||||
export DOCKER_IMAGE_NAME="clastix/kamaji-kind-worker"
|
||||
|
||||
# Variables
|
||||
export KUBERNETES_VERSION=${1:-latest}
|
||||
|
||||
if [ -z $2 ]
|
||||
then
|
||||
MAPPING_PORT=""
|
||||
else
|
||||
MAPPING_PORT="-p ${2}:80"
|
||||
fi
|
||||
|
||||
export KONNECTIVITY_PROXY_HOST=${3:-konnectiviy.local}
|
||||
|
||||
clear
|
||||
echo "Welcome to join a new node through Konnectivity"
|
||||
|
||||
echo -ne "\nChecking right kubeconfig\n"
|
||||
kubectl cluster-info
|
||||
echo "Are you pointing to the right tenant control plane? (Type return to continue)"
|
||||
read
|
||||
|
||||
JOIN_CMD="$(kubeadm --kubeconfig=/tmp/kubeconfig token create --print-join-command) --ignore-preflight-errors=SystemVerification"
|
||||
echo "Deploying new node..."
|
||||
KIND_IP=$(docker inspect kamaji-control-plane --format='{{.NetworkSettings.Networks.kind.IPAddress}}')
|
||||
NODE=$(docker run -d --add-host $KONNECTIVITY_PROXY_HOST:$KIND_IP --privileged -v /lib/modules:/lib/modules:ro -v /var --net host $MAPPING_PORT $DOCKER_IMAGE_NAME:$KUBERNETES_VERSION)
|
||||
sleep 10
|
||||
echo "Joining new node..."
|
||||
docker exec -e JOIN_CMD="$JOIN_CMD" $NODE /bin/bash -c "$JOIN_CMD"
|
||||
@@ -23,10 +23,14 @@ nodes:
|
||||
- containerPort: 443
|
||||
hostPort: 443
|
||||
protocol: TCP
|
||||
## expose port 31132 of the node to port 31132 on the host for konnectivity
|
||||
- containerPort: 31132
|
||||
hostPort: 31132
|
||||
protocol: TCP
|
||||
## expose port 31443 of the node to port 31443 on the host
|
||||
- containerPort: 31443
|
||||
hostPort: 31443
|
||||
protocol: TCP
|
||||
protocol: TCP
|
||||
## expose port 6443 of the node to port 8443 on the host
|
||||
- containerPort: 6443
|
||||
hostPort: 8443
|
||||
|
||||
@@ -73,6 +73,23 @@ spec:
|
||||
EOF
|
||||
```
|
||||
|
||||
If workers are not reachable from tenant control plane, konnectivity can be enabled (it is by default):
|
||||
|
||||
```yaml
|
||||
...
|
||||
addons:
|
||||
konnectivity:
|
||||
enabled: true
|
||||
proxyHost: "172.18.0.2"
|
||||
proxyPort: 31132
|
||||
...
|
||||
```
|
||||
|
||||
`proxyHost` is the address where konnectivity proxy server will be running. Konnectivity works as sidecar container into the tenant control plane pod. If no value is specified, it will take tenant IP.
|
||||
|
||||
`proxyPort` is the port where konnectivity proxy server will be running. (default `8132`)
|
||||
|
||||
|
||||
```bash
|
||||
kubectl create namespace ${TENANT_NAMESPACE}
|
||||
kubectl apply -f ${TENANT_NAMESPACE}-${TENANT_NAME}-tcp.yaml
|
||||
|
||||
@@ -102,3 +102,16 @@ addons:
|
||||
addons:
|
||||
kubeProxy: {}
|
||||
```
|
||||
|
||||
### Konnectivity
|
||||
|
||||
```yaml
|
||||
addons:
|
||||
konnectivity:
|
||||
proxyPort: 31132 # mandatory
|
||||
proxyHost: "172.18.0.2"
|
||||
allowAddressAsExternalIP: false
|
||||
serviceType: NodePort # mandatory
|
||||
version: v0.0.31
|
||||
serverImage: us.gcr.io/k8s-artifacts-prod/kas-network-proxy/proxy-server
|
||||
agentImage: us.gcr.io/k8s-artifacts-prod/kas-network-proxy/proxy-agent
|
||||
|
||||
1
go.mod
1
go.mod
@@ -16,6 +16,7 @@ require (
|
||||
google.golang.org/grpc v1.43.0
|
||||
k8s.io/api v0.23.5
|
||||
k8s.io/apimachinery v0.23.5
|
||||
k8s.io/apiserver v0.23.5
|
||||
k8s.io/client-go v0.23.5
|
||||
k8s.io/cluster-bootstrap v0.0.0
|
||||
k8s.io/component-base v0.23.5
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,7 +29,8 @@ type CACertificate struct {
|
||||
}
|
||||
|
||||
func (r *CACertificate) ShouldStatusBeUpdated(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
return tenantControlPlane.Status.Certificates.CA.SecretName != r.resource.GetName()
|
||||
return tenantControlPlane.Status.Certificates.CA.SecretName != r.resource.GetName() ||
|
||||
tenantControlPlane.Status.Certificates.CA.ResourceVersion != r.resource.ResourceVersion
|
||||
}
|
||||
|
||||
func (r *CACertificate) ShouldCleanup(plane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
@@ -74,6 +75,7 @@ func (r *CACertificate) GetName() string {
|
||||
func (r *CACertificate) UpdateTenantControlPlaneStatus(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
tenantControlPlane.Status.Certificates.CA.LastUpdate = metav1.Now()
|
||||
tenantControlPlane.Status.Certificates.CA.SecretName = r.resource.GetName()
|
||||
tenantControlPlane.Status.Certificates.CA.ResourceVersion = r.resource.ResourceVersion
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -25,9 +25,17 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/resources/konnectivity"
|
||||
"github.com/clastix/kamaji/internal/utilities"
|
||||
)
|
||||
|
||||
const (
|
||||
konnectivityEgressSelectorConfigurationPath = "/etc/kubernetes/konnectivity/configurations/egress-selector-configuration.yaml"
|
||||
konnectivityServerName = "konnectivity-server"
|
||||
konnectivityServerPath = "/run/konnectivity"
|
||||
konnectivityUDSName = "konnectivity-uds"
|
||||
)
|
||||
|
||||
type KubernetesDeploymentResource struct {
|
||||
resource *appsv1.Deployment
|
||||
Client client.Client
|
||||
@@ -49,7 +57,7 @@ func (r *KubernetesDeploymentResource) ShouldCleanup(plane *kamajiv1alpha1.Tenan
|
||||
}
|
||||
|
||||
func (r *KubernetesDeploymentResource) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity != nil, nil
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity == nil, nil
|
||||
}
|
||||
|
||||
func (r *KubernetesDeploymentResource) Define(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
@@ -548,6 +556,10 @@ func (r *KubernetesDeploymentResource) CreateOrUpdate(ctx context.Context, tenan
|
||||
},
|
||||
}
|
||||
|
||||
if err := r.reconcileKonnectivity(&r.resource.Spec.Template.Spec, *tenantControlPlane); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return controllerutil.SetControllerReference(tenantControlPlane, r.resource, r.Client.Scheme())
|
||||
})
|
||||
}
|
||||
@@ -573,6 +585,7 @@ func (r *KubernetesDeploymentResource) UpdateTenantControlPlaneStatus(ctx contex
|
||||
DeploymentStatus: r.resource.Status,
|
||||
Name: r.resource.GetName(),
|
||||
Namespace: r.resource.GetNamespace(),
|
||||
LastUpdate: metav1.Now(),
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -605,7 +618,7 @@ func (r *KubernetesDeploymentResource) isNotReady() bool {
|
||||
}
|
||||
|
||||
func (r *KubernetesDeploymentResource) reconcileKonnectivity(podSpec *corev1.PodSpec, tenantControlPlane kamajiv1alpha1.TenantControlPlane) error {
|
||||
if tenantControlPlane.Spec.Addons.Konnectivity != nil {
|
||||
if tenantControlPlane.Spec.Addons.Konnectivity == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ func (r *Agent) ShouldStatusBeUpdated(ctx context.Context, tenantControlPlane *k
|
||||
}
|
||||
|
||||
func (r *Agent) ShouldCleanup(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity != nil
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity == nil
|
||||
}
|
||||
|
||||
func (r *Agent) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
|
||||
@@ -42,7 +42,7 @@ func (r *CertificateResource) ShouldStatusBeUpdated(ctx context.Context, tenantC
|
||||
}
|
||||
|
||||
func (r *CertificateResource) ShouldCleanup(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity != nil
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity == nil
|
||||
}
|
||||
|
||||
func (r *CertificateResource) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
|
||||
@@ -29,7 +29,7 @@ func (r *ClusterRoleBindingResource) ShouldStatusBeUpdated(ctx context.Context,
|
||||
}
|
||||
|
||||
func (r *ClusterRoleBindingResource) ShouldCleanup(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity != nil
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity == nil
|
||||
}
|
||||
|
||||
func (r *ClusterRoleBindingResource) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
|
||||
19
internal/resources/konnectivity/constants.go
Normal file
19
internal/resources/konnectivity/constants.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package konnectivity
|
||||
|
||||
const (
|
||||
AgentName = "konnectivity-agent"
|
||||
CertCommonName = "system:konnectivity-server"
|
||||
|
||||
agentTokenName = "konnectivity-agent-token"
|
||||
apiServerAPIVersion = "apiserver.k8s.io/v1beta1"
|
||||
certExpirationDelayYears = 10
|
||||
certOrganization = "system:master"
|
||||
defaultClusterName = "kubernetes"
|
||||
defaultUDSName = "/run/konnectivity/konnectivity-server.socket"
|
||||
egressSelectorConfigurationKind = "EgressSelectorConfiguration"
|
||||
egressSelectorConfigurationName = "cluster"
|
||||
konnectivityCertAndKeyBaseName = "konnectivity"
|
||||
konnectivityKubeconfigFileName = "konnectivity-server.conf"
|
||||
kubeconfigAPIVersion = "v1"
|
||||
roleAuthDelegator = "system:auth-delegator"
|
||||
)
|
||||
@@ -35,7 +35,7 @@ func (r *EgressSelectorConfigurationResource) Define(ctx context.Context, tenant
|
||||
}
|
||||
|
||||
func (r *EgressSelectorConfigurationResource) ShouldCleanup(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity != nil
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity == nil
|
||||
}
|
||||
|
||||
func (r *EgressSelectorConfigurationResource) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
|
||||
@@ -32,7 +32,7 @@ func (r *KubeconfigResource) ShouldStatusBeUpdated(ctx context.Context, tenantCo
|
||||
}
|
||||
|
||||
func (r *KubeconfigResource) ShouldCleanup(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity != nil
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity == nil
|
||||
}
|
||||
|
||||
func (r *KubeconfigResource) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
|
||||
@@ -30,7 +30,7 @@ func (r *ServiceAccountResource) ShouldStatusBeUpdated(ctx context.Context, tena
|
||||
}
|
||||
|
||||
func (r *ServiceAccountResource) ShouldCleanup(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity != nil
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity == nil
|
||||
}
|
||||
|
||||
func (r *ServiceAccountResource) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
k8stypes "k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
@@ -28,6 +27,18 @@ type ServiceResource struct {
|
||||
}
|
||||
|
||||
func (r *ServiceResource) ShouldStatusBeUpdated(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
if tenantControlPlane.Status.Addons.Konnectivity.Service.Name != r.resource.GetName() {
|
||||
return true
|
||||
}
|
||||
|
||||
if tenantControlPlane.Status.Addons.Konnectivity.Service.Namespace != r.resource.GetNamespace() {
|
||||
return true
|
||||
}
|
||||
|
||||
if tenantControlPlane.Status.Addons.Konnectivity.Service.Port != r.resource.Spec.Ports[0].Port {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(r.resource.Status.Conditions) != len(tenantControlPlane.Status.Addons.Konnectivity.Service.Conditions) {
|
||||
return true
|
||||
}
|
||||
@@ -60,7 +71,7 @@ func (r *ServiceResource) ShouldStatusBeUpdated(ctx context.Context, tenantContr
|
||||
}
|
||||
|
||||
func (r *ServiceResource) ShouldCleanup(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity != nil
|
||||
return tenantControlPlane.Spec.Addons.Konnectivity == nil
|
||||
}
|
||||
|
||||
func (r *ServiceResource) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
@@ -86,7 +97,7 @@ func (r *ServiceResource) UpdateTenantControlPlaneStatus(ctx context.Context, te
|
||||
return nil
|
||||
}
|
||||
|
||||
tenantControlPlane.Status.Addons.Konnectivity.Service = corev1.ServiceStatus{}
|
||||
tenantControlPlane.Status.Addons.Konnectivity.Service = kamajiv1alpha1.KubernetesServiceStatus{}
|
||||
tenantControlPlane.Status.Addons.Konnectivity.Enabled = false
|
||||
|
||||
return nil
|
||||
@@ -108,8 +119,7 @@ func (r *ServiceResource) CreateOrUpdate(ctx context.Context, tenantControlPlane
|
||||
}
|
||||
|
||||
func (r *ServiceResource) mutate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) func() error {
|
||||
namespacedName := k8stypes.NamespacedName{Namespace: r.resource.GetNamespace(), Name: r.resource.GetName()}
|
||||
address, _ := tenantControlPlane.GetAddress(ctx, r.Client, namespacedName, tenantControlPlane.Spec.Addons.Konnectivity.ProxyHost)
|
||||
address, _ := tenantControlPlane.GetKonnectivityServerAddress(ctx, r.Client)
|
||||
if address == "" {
|
||||
address = tenantControlPlane.Spec.NetworkProfile.Address
|
||||
}
|
||||
@@ -140,10 +150,10 @@ func (r *ServiceResource) mutate(ctx context.Context, tenantControlPlane *kamaji
|
||||
case utilities.IsValidIP(address):
|
||||
isIP = true
|
||||
case !utilities.IsValidHostname(address):
|
||||
return fmt.Errorf("%s is not a valid address for Konnectivity proxy server.", address)
|
||||
return fmt.Errorf("%s is not a valid address for konnectivity proxy server", address)
|
||||
}
|
||||
|
||||
switch tenantControlPlane.Spec.ControlPlane.Service.ServiceType {
|
||||
switch tenantControlPlane.Spec.Addons.Konnectivity.ServiceType {
|
||||
case kamajiv1alpha1.ServiceTypeLoadBalancer:
|
||||
r.resource.Spec.Type = corev1.ServiceTypeLoadBalancer
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ package utilities
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer/json"
|
||||
@@ -56,3 +58,24 @@ func EncondeToYaml(o runtime.Object) ([]byte, error) {
|
||||
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
// IsValidIP checks if the given argument is an IP.
|
||||
func IsValidIP(ip string) bool {
|
||||
return net.ParseIP(ip) != nil
|
||||
}
|
||||
|
||||
// IsValidHostname checks if the given argument is a valid hostname.
|
||||
func IsValidHostname(hostname string) bool {
|
||||
pattern := "^([a-z0-9]|[a-z0-9][a-z0-9-]{0,61}[a-z0-9])(\\.([a-z0-9]|[a-z0-9][a-z0-9-]{0,61}[a-z0-9]))*$"
|
||||
|
||||
return validateRegex(pattern, hostname)
|
||||
}
|
||||
|
||||
func validateRegex(pattern string, value string) bool {
|
||||
isFound, err := regexp.MatchString(pattern, value)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return isFound
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user