2022-03-22 11:03:15 -04:00
package core
import (
"context"
2022-05-04 08:32:34 -04:00
"time"
2022-03-22 11:03:15 -04:00
2022-06-13 10:23:19 -04:00
"github.com/edgelesssys/constellation/coordinator/pubapi/pubproto"
2022-03-22 11:03:15 -04:00
"github.com/edgelesssys/constellation/coordinator/role"
2022-06-15 10:00:48 -04:00
attestationtypes "github.com/edgelesssys/constellation/internal/attestation/types"
2022-05-04 08:32:34 -04:00
"github.com/edgelesssys/constellation/internal/constants"
2022-03-22 11:03:15 -04:00
"go.uber.org/zap"
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
)
// GetK8sJoinArgs returns the args needed by a Node to join the cluster.
2022-05-24 04:04:42 -04:00
func ( c * Core ) GetK8sJoinArgs ( ctx context . Context ) ( * kubeadm . BootstrapTokenDiscovery , error ) {
return c . kube . GetJoinToken ( ctx , constants . KubernetesJoinTokenTTL )
2022-03-22 11:03:15 -04:00
}
2022-04-25 11:24:48 -04:00
// GetK8SCertificateKey returns the key needed by a Coordinator to join the cluster.
2022-05-24 04:04:42 -04:00
func ( c * Core ) GetK8SCertificateKey ( ctx context . Context ) ( string , error ) {
return c . kube . GetKubeadmCertificateKey ( ctx )
2022-04-25 11:24:48 -04:00
}
2022-03-22 11:03:15 -04:00
// InitCluster initializes the cluster, stores the join args, and returns the kubeconfig.
2022-06-15 10:00:48 -04:00
func ( c * Core ) InitCluster (
ctx context . Context , autoscalingNodeGroups [ ] string , cloudServiceAccountURI string , id attestationtypes . ID , masterSecret [ ] byte , sshUsers [ ] * pubproto . SSHUserKey ,
) ( [ ] byte , error ) {
2022-03-22 11:03:15 -04:00
c . zaplogger . Info ( "Initializing cluster" )
2022-05-24 04:04:42 -04:00
vpnIP , err := c . GetVPNIP ( )
if err != nil {
c . zaplogger . Error ( "Retrieving vpn ip failed" , zap . Error ( err ) )
return nil , err
}
2022-06-13 10:23:19 -04:00
// Convert SSH users map from protobuffer to map
sshUsersMap := make ( map [ string ] string )
if len ( sshUsers ) > 0 {
for _ , value := range sshUsers {
sshUsersMap [ value . Username ] = value . PublicKey
}
}
2022-06-15 10:00:48 -04:00
if err := c . kube . InitCluster ( ctx , autoscalingNodeGroups , cloudServiceAccountURI , vpnIP , id , masterSecret , sshUsersMap ) ; err != nil {
2022-03-22 11:03:15 -04:00
c . zaplogger . Error ( "Initializing cluster failed" , zap . Error ( err ) )
return nil , err
}
kubeconfig , err := c . kube . GetKubeconfig ( )
if err != nil {
return nil , err
}
if err := c . data ( ) . PutKubernetesConfig ( kubeconfig ) ; err != nil {
return nil , err
}
// set role in cloud provider metadata for autoconfiguration
if c . metadata . Supported ( ) {
if err := c . metadata . SignalRole ( context . TODO ( ) , role . Coordinator ) ; err != nil {
c . zaplogger . Info ( "unable to update role in cloud provider metadata" , zap . Error ( err ) )
}
}
return kubeconfig , nil
}
// JoinCluster lets a Node join the cluster.
2022-05-24 04:04:42 -04:00
func ( c * Core ) JoinCluster ( ctx context . Context , args * kubeadm . BootstrapTokenDiscovery , certKey string , peerRole role . Role ) error {
2022-04-26 05:22:21 -04:00
c . zaplogger . Info ( "Joining Kubernetes cluster" )
2022-03-22 11:03:15 -04:00
nodeVPNIP , err := c . vpn . GetInterfaceIP ( )
if err != nil {
c . zaplogger . Error ( "Retrieving vpn ip failed" , zap . Error ( err ) )
return err
}
2022-04-25 11:24:48 -04:00
// we need to pass the VPNIP for another control-plane, otherwise etcd will bind itself to the wrong IP address and fails
2022-05-24 04:04:42 -04:00
if err := c . kube . JoinCluster ( ctx , args , nodeVPNIP , certKey , peerRole ) ; err != nil {
2022-04-26 05:22:21 -04:00
c . zaplogger . Error ( "Joining Kubernetes cluster failed" , zap . Error ( err ) )
2022-03-22 11:03:15 -04:00
return err
}
2022-04-26 05:22:21 -04:00
c . zaplogger . Info ( "Joined Kubernetes cluster" )
2022-03-22 11:03:15 -04:00
// set role in cloud provider metadata for autoconfiguration
if c . metadata . Supported ( ) {
2022-04-25 11:24:48 -04:00
if err := c . metadata . SignalRole ( context . TODO ( ) , peerRole ) ; err != nil {
2022-03-22 11:03:15 -04:00
c . zaplogger . Info ( "unable to update role in cloud provider metadata" , zap . Error ( err ) )
}
}
return nil
}
// Cluster manages the overall cluster lifecycle (init, join).
type Cluster interface {
// InitCluster bootstraps a new cluster with the current node being the master, returning the arguments required to join the cluster.
2022-06-15 10:00:48 -04:00
InitCluster (
ctx context . Context , autoscalingNodeGroups [ ] string , cloudServiceAccountURI , vpnIP string , id attestationtypes . ID , masterSecret [ ] byte , sshUsers map [ string ] string ,
) error
2022-03-22 11:03:15 -04:00
// JoinCluster will join the current node to an existing cluster.
2022-05-24 04:04:42 -04:00
JoinCluster ( ctx context . Context , args * kubeadm . BootstrapTokenDiscovery , nodeVPNIP , certKey string , peerRole role . Role ) error
2022-03-22 11:03:15 -04:00
// GetKubeconfig reads the kubeconfig from the filesystem. Only succeeds after cluster is initialized.
GetKubeconfig ( ) ( [ ] byte , error )
2022-04-25 11:24:48 -04:00
// GetKubeadmCertificateKey returns the 64-byte hex string key needed to join the cluster as control-plane. This function must be executed on a control-plane.
2022-05-24 04:04:42 -04:00
GetKubeadmCertificateKey ( ctx context . Context ) ( string , error )
2022-05-04 08:32:34 -04:00
// GetJoinToken returns a bootstrap (join) token.
2022-05-24 04:04:42 -04:00
GetJoinToken ( ctx context . Context , ttl time . Duration ) ( * kubeadm . BootstrapTokenDiscovery , error )
2022-05-19 11:18:22 -04:00
// StartKubelet starts the kubelet service.
StartKubelet ( ) error
2022-03-22 11:03:15 -04:00
}
2022-04-26 05:22:21 -04:00
// ClusterFake behaves like a real cluster, but does not actually initialize or join Kubernetes.
2022-03-22 11:03:15 -04:00
type ClusterFake struct { }
// InitCluster fakes bootstrapping a new cluster with the current node being the master, returning the arguments required to join the cluster.
2022-06-15 10:00:48 -04:00
func ( c * ClusterFake ) InitCluster (
ctx context . Context , autoscalingNodeGroups [ ] string , cloudServiceAccountURI , vpnIP string , id attestationtypes . ID , masterSecret [ ] byte , sshUsers map [ string ] string ,
) error {
2022-05-04 08:32:34 -04:00
return nil
2022-03-22 11:03:15 -04:00
}
// JoinCluster will fake joining the current node to an existing cluster.
2022-05-24 04:04:42 -04:00
func ( c * ClusterFake ) JoinCluster ( ctx context . Context , args * kubeadm . BootstrapTokenDiscovery , nodeVPNIP , certKey string , peerRole role . Role ) error {
2022-03-22 11:03:15 -04:00
return nil
}
// GetKubeconfig fakes reading the kubeconfig from the filesystem. Only succeeds after cluster is initialized.
func ( c * ClusterFake ) GetKubeconfig ( ) ( [ ] byte , error ) {
return [ ] byte ( "kubeconfig" ) , nil
}
2022-04-25 11:24:48 -04:00
// GetKubeadmCertificateKey fakes generating a certificateKey.
2022-05-24 04:04:42 -04:00
func ( c * ClusterFake ) GetKubeadmCertificateKey ( context . Context ) ( string , error ) {
2022-04-25 11:24:48 -04:00
return "controlPlaneCertficateKey" , nil
}
2022-05-04 08:32:34 -04:00
// GetJoinToken returns a bootstrap (join) token.
2022-05-24 04:04:42 -04:00
func ( c * ClusterFake ) GetJoinToken ( ctx context . Context , _ time . Duration ) ( * kubeadm . BootstrapTokenDiscovery , error ) {
2022-05-04 08:32:34 -04:00
return & kubeadm . BootstrapTokenDiscovery {
APIServerEndpoint : "0.0.0.0" ,
Token : "kube-fake-token" ,
CACertHashes : [ ] string { "sha256:a60ebe9b0879090edd83b40a4df4bebb20506bac1e51d518ff8f4505a721930f" } ,
} , nil
}
2022-05-19 11:18:22 -04:00
// StartKubelet starts the kubelet service.
func ( c * ClusterFake ) StartKubelet ( ) error {
return nil
}