mirror of
https://github.com/rancher/rke.git
synced 2025-07-07 12:28:46 +00:00
Merge pull request #15 from moelsayed/cluster_upgrade
Add cluster upgrade
This commit is contained in:
commit
9e28d35656
@ -11,13 +11,13 @@ network:
|
|||||||
foo: bar
|
foo: bar
|
||||||
|
|
||||||
hosts:
|
hosts:
|
||||||
- hostname: server1
|
- advertised_hostname: server1
|
||||||
ip: 1.1.1.1
|
ip: 1.1.1.1
|
||||||
user: ubuntu
|
user: ubuntu
|
||||||
role: [controlplane, etcd]
|
role: [controlplane, etcd]
|
||||||
docker_socket: /var/run/docker.sock
|
docker_socket: /var/run/docker.sock
|
||||||
advertise_address: 10.1.1.1
|
advertise_address: 10.1.1.1
|
||||||
- hostname: server2
|
- advertised_hostname: server2
|
||||||
ip: 2.2.2.2
|
ip: 2.2.2.2
|
||||||
user: ubuntu
|
user: ubuntu
|
||||||
role: [worker]
|
role: [worker]
|
||||||
|
@ -16,10 +16,7 @@ func SetUpAuthentication(kubeCluster, currentCluster *Cluster) error {
|
|||||||
if kubeCluster.Authentication.Strategy == X509AuthenticationProvider {
|
if kubeCluster.Authentication.Strategy == X509AuthenticationProvider {
|
||||||
var err error
|
var err error
|
||||||
if currentCluster != nil {
|
if currentCluster != nil {
|
||||||
kubeCluster.Certificates, err = getClusterCerts(kubeCluster.KubeClient)
|
kubeCluster.Certificates = currentCluster.Certificates
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Failed to Get Kubernetes certificates: %v", err)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
kubeCluster.Certificates, err = pki.StartCertificatesGeneration(
|
kubeCluster.Certificates, err = pki.StartCertificatesGeneration(
|
||||||
kubeCluster.ControlPlaneHosts,
|
kubeCluster.ControlPlaneHosts,
|
||||||
|
@ -41,6 +41,10 @@ func (c *Cluster) GetClusterState() (*Cluster, error) {
|
|||||||
// Handle pervious kubernetes state and certificate generation
|
// Handle pervious kubernetes state and certificate generation
|
||||||
currentCluster = getStateFromKubernetes(c.KubeClient, pki.KubeAdminConfigPath)
|
currentCluster = getStateFromKubernetes(c.KubeClient, pki.KubeAdminConfigPath)
|
||||||
if currentCluster != nil {
|
if currentCluster != nil {
|
||||||
|
currentCluster.Certificates, err = getClusterCerts(c.KubeClient)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to Get Kubernetes certificates: %v", err)
|
||||||
|
}
|
||||||
err = currentCluster.InvertIndexHosts()
|
err = currentCluster.InvertIndexHosts()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Failed to classify hosts from fetched cluster: %v", err)
|
return nil, fmt.Errorf("Failed to classify hosts from fetched cluster: %v", err)
|
||||||
|
51
cluster/upgrade.go
Normal file
51
cluster/upgrade.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package cluster
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/rancher/rke/k8s"
|
||||||
|
"github.com/rancher/rke/pki"
|
||||||
|
"github.com/rancher/rke/services"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *Cluster) ClusterUpgrade() error {
|
||||||
|
// make sure all nodes are Ready
|
||||||
|
logrus.Debugf("[upgrade] Checking node status")
|
||||||
|
if err := checkK8sNodesState(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// upgrade Contol Plane
|
||||||
|
logrus.Infof("[upgrade] Upgrading Control Plane Services")
|
||||||
|
if err := services.UpgradeControlPlane(c.ControlPlaneHosts, c.EtcdHosts, c.Services); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logrus.Infof("[upgrade] Control Plane Services updgraded successfully")
|
||||||
|
|
||||||
|
// upgrade Worker Plane
|
||||||
|
logrus.Infof("[upgrade] Upgrading Worker Plane Services")
|
||||||
|
if err := services.UpgradeWorkerPlane(c.ControlPlaneHosts, c.WorkerHosts, c.Services); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logrus.Infof("[upgrade] Worker Plane Services updgraded successfully")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkK8sNodesState() error {
|
||||||
|
k8sClient, err := k8s.NewClient(pki.KubeAdminConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
nodeList, err := k8s.GetNodeList(k8sClient)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, node := range nodeList.Items {
|
||||||
|
ready := k8s.IsNodeReady(node)
|
||||||
|
if !ready {
|
||||||
|
return fmt.Errorf("[upgrade] Node: %s is NotReady", node.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logrus.Infof("[upgrade] All nodes are Ready")
|
||||||
|
return nil
|
||||||
|
}
|
@ -22,6 +22,14 @@ func ClusterCommand() cli.Command {
|
|||||||
EnvVar: "CLUSTER_FILE",
|
EnvVar: "CLUSTER_FILE",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
clusterUpgradeFlags := []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "cluster-file",
|
||||||
|
Usage: "Specify an upgraded cluster YAML file",
|
||||||
|
Value: "cluster.yml",
|
||||||
|
EnvVar: "CLUSTER_FILE",
|
||||||
|
},
|
||||||
|
}
|
||||||
return cli.Command{
|
return cli.Command{
|
||||||
Name: "cluster",
|
Name: "cluster",
|
||||||
ShortName: "cluster",
|
ShortName: "cluster",
|
||||||
@ -40,6 +48,12 @@ func ClusterCommand() cli.Command {
|
|||||||
Action: getClusterVersion,
|
Action: getClusterVersion,
|
||||||
Flags: []cli.Flag{},
|
Flags: []cli.Flag{},
|
||||||
},
|
},
|
||||||
|
cli.Command{
|
||||||
|
Name: "upgrade",
|
||||||
|
Usage: "Upgrade Cluster Kubernetes version",
|
||||||
|
Action: clusterUpgradeFromCli,
|
||||||
|
Flags: clusterUpgradeFlags,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,7 +80,6 @@ func ClusterUp(clusterFile string) (string, string, string, string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return APIURL, caCrt, clientCert, clientKey, err
|
return APIURL, caCrt, clientCert, clientKey, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = kubeCluster.SetUpHosts()
|
err = kubeCluster.SetUpHosts()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return APIURL, caCrt, clientCert, clientKey, err
|
return APIURL, caCrt, clientCert, clientKey, err
|
||||||
@ -136,3 +149,51 @@ func getClusterVersion(ctx *cli.Context) error {
|
|||||||
fmt.Printf("Server Version: %s\n", serverVersion)
|
fmt.Printf("Server Version: %s\n", serverVersion)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func clusterUpgradeFromCli(ctx *cli.Context) error {
|
||||||
|
clusterFile, err := resolveClusterFile(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to resolve cluster file: %v", err)
|
||||||
|
}
|
||||||
|
_, _, _, _, err = ClusterUpgrade(clusterFile)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func ClusterUpgrade(clusterFile string) (string, string, string, string, error) {
|
||||||
|
logrus.Infof("Upgrading Kubernetes cluster")
|
||||||
|
var APIURL, caCrt, clientCert, clientKey string
|
||||||
|
kubeCluster, err := cluster.ParseConfig(clusterFile)
|
||||||
|
if err != nil {
|
||||||
|
return APIURL, caCrt, clientCert, clientKey, err
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Debugf("Getting current cluster")
|
||||||
|
currentCluster, err := kubeCluster.GetClusterState()
|
||||||
|
if err != nil {
|
||||||
|
return APIURL, caCrt, clientCert, clientKey, err
|
||||||
|
}
|
||||||
|
logrus.Debugf("Setting up upgrade tunnels")
|
||||||
|
/*
|
||||||
|
kubeCluster is the cluster.yaml definition. It should have updated configuration
|
||||||
|
currentCluster is the current state fetched from kubernetes
|
||||||
|
we add currentCluster certs to kubeCluster, kubeCluster would have the latest configuration from cluster.yaml and the certs to connect to k8s and apply the upgrade
|
||||||
|
*/
|
||||||
|
kubeCluster.Certificates = currentCluster.Certificates
|
||||||
|
err = kubeCluster.TunnelHosts()
|
||||||
|
if err != nil {
|
||||||
|
return APIURL, caCrt, clientCert, clientKey, err
|
||||||
|
}
|
||||||
|
logrus.Debugf("Starting cluster upgrade")
|
||||||
|
err = kubeCluster.ClusterUpgrade()
|
||||||
|
if err != nil {
|
||||||
|
return APIURL, caCrt, clientCert, clientKey, err
|
||||||
|
}
|
||||||
|
logrus.Infof("Cluster upgraded successfully")
|
||||||
|
|
||||||
|
APIURL = fmt.Sprintf("https://" + kubeCluster.ControlPlaneHosts[0].IP + ":6443")
|
||||||
|
caCrt = string(cert.EncodeCertPEM(kubeCluster.Certificates[pki.CACertName].Certificate))
|
||||||
|
clientCert = string(cert.EncodeCertPEM(kubeCluster.Certificates[pki.KubeAdminCommonName].Certificate))
|
||||||
|
clientKey = string(cert.EncodePrivateKeyPEM(kubeCluster.Certificates[pki.KubeAdminCommonName].Key))
|
||||||
|
return APIURL, caCrt, clientCert, clientKey, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -77,3 +77,65 @@ func RemoveContainer(dClient *client.Client, hostname string, containerName stri
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func StopContainer(dClient *client.Client, hostname string, containerName string) error {
|
||||||
|
err := dClient.ContainerStop(context.Background(), containerName, nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Can't stop Docker container %s for host [%s]: %v", containerName, hostname, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RenameContainer(dClient *client.Client, hostname string, oldContainerName string, newContainerName string) error {
|
||||||
|
err := dClient.ContainerRename(context.Background(), oldContainerName, newContainerName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Can't rename Docker container %s for host [%s]: %v", oldContainerName, hostname, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartContainer(dClient *client.Client, hostname string, containerName string) error {
|
||||||
|
if err := dClient.ContainerStart(context.Background(), containerName, types.ContainerStartOptions{}); err != nil {
|
||||||
|
return fmt.Errorf("Failed to start %s container on host [%s]: %v", containerName, hostname, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateContiner(dClient *client.Client, hostname string, containerName string, imageCfg *container.Config, hostCfg *container.HostConfig) (container.ContainerCreateCreatedBody, error) {
|
||||||
|
created, err := dClient.ContainerCreate(context.Background(), imageCfg, hostCfg, nil, containerName)
|
||||||
|
if err != nil {
|
||||||
|
return container.ContainerCreateCreatedBody{}, fmt.Errorf("Failed to create %s container on host [%s]: %v", containerName, hostname, err)
|
||||||
|
}
|
||||||
|
return created, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func InspectContainer(dClient *client.Client, hostname string, containerName string) (types.ContainerJSON, error) {
|
||||||
|
inspection, err := dClient.ContainerInspect(context.Background(), containerName)
|
||||||
|
if err != nil {
|
||||||
|
return types.ContainerJSON{}, fmt.Errorf("Failed to inspect %s container on host [%s]: %v", containerName, hostname, err)
|
||||||
|
}
|
||||||
|
return inspection, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func StopRenameContainer(dClient *client.Client, hostname string, oldContainerName string, newContainerName string) error {
|
||||||
|
if err := StopContainer(dClient, hostname, oldContainerName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := WaitForContainer(dClient, oldContainerName); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := RenameContainer(dClient, hostname, oldContainerName, newContainerName)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func WaitForContainer(dClient *client.Client, containerName string) error {
|
||||||
|
statusCh, errCh := dClient.ContainerWait(context.Background(), containerName, container.WaitConditionNotRunning)
|
||||||
|
select {
|
||||||
|
case err := <-errCh:
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error wating for container [%s]: %v", containerName, err)
|
||||||
|
}
|
||||||
|
case <-statusCh:
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
34
k8s/configmap.go
Normal file
34
k8s/configmap.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package k8s
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
)
|
||||||
|
|
||||||
|
func UpdateConfigMap(k8sClient *kubernetes.Clientset, configYaml []byte, configMapName string) error {
|
||||||
|
cfgMap := &v1.ConfigMap{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: configMapName,
|
||||||
|
Namespace: metav1.NamespaceSystem,
|
||||||
|
},
|
||||||
|
Data: map[string]string{
|
||||||
|
configMapName: string(configYaml),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := k8sClient.CoreV1().ConfigMaps(metav1.NamespaceSystem).Create(cfgMap); err != nil {
|
||||||
|
if !apierrors.IsAlreadyExists(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := k8sClient.CoreV1().ConfigMaps(metav1.NamespaceSystem).Update(cfgMap); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetConfigMap(k8sClient *kubernetes.Clientset, configMapName string) (*v1.ConfigMap, error) {
|
||||||
|
return k8sClient.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(configMapName, metav1.GetOptions{})
|
||||||
|
}
|
72
k8s/k8s.go
72
k8s/k8s.go
@ -1,9 +1,6 @@
|
|||||||
package k8s
|
package k8s
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/api/core/v1"
|
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
)
|
)
|
||||||
@ -20,72 +17,3 @@ func NewClient(kubeConfigPath string) (*kubernetes.Clientset, error) {
|
|||||||
}
|
}
|
||||||
return K8sClientSet, nil
|
return K8sClientSet, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateConfigMap(k8sClient *kubernetes.Clientset, configYaml []byte, configMapName string) error {
|
|
||||||
cfgMap := &v1.ConfigMap{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: configMapName,
|
|
||||||
Namespace: metav1.NamespaceSystem,
|
|
||||||
},
|
|
||||||
Data: map[string]string{
|
|
||||||
configMapName: string(configYaml),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := k8sClient.CoreV1().ConfigMaps(metav1.NamespaceSystem).Create(cfgMap); err != nil {
|
|
||||||
if !apierrors.IsAlreadyExists(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := k8sClient.CoreV1().ConfigMaps(metav1.NamespaceSystem).Update(cfgMap); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetConfigMap(k8sClient *kubernetes.Clientset, configMapName string) (*v1.ConfigMap, error) {
|
|
||||||
return k8sClient.CoreV1().ConfigMaps(metav1.NamespaceSystem).Get(configMapName, metav1.GetOptions{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func UpdateSecret(k8sClient *kubernetes.Clientset, fieldName string, secretData []byte, secretName string) error {
|
|
||||||
secret := &v1.Secret{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: secretName,
|
|
||||||
Namespace: metav1.NamespaceSystem,
|
|
||||||
},
|
|
||||||
Data: map[string][]byte{
|
|
||||||
fieldName: secretData,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if _, err := k8sClient.CoreV1().Secrets(metav1.NamespaceSystem).Create(secret); err != nil {
|
|
||||||
if !apierrors.IsAlreadyExists(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// update secret if its already exist
|
|
||||||
oldSecret, err := k8sClient.CoreV1().Secrets(metav1.NamespaceSystem).Get(secretName, metav1.GetOptions{})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
newData := oldSecret.Data
|
|
||||||
newData[fieldName] = secretData
|
|
||||||
secret := &v1.Secret{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: secretName,
|
|
||||||
Namespace: metav1.NamespaceSystem,
|
|
||||||
},
|
|
||||||
Data: newData,
|
|
||||||
}
|
|
||||||
if _, err := k8sClient.CoreV1().Secrets(metav1.NamespaceSystem).Update(secret); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetSecret(k8sClient *kubernetes.Clientset, secretName string) (*v1.Secret, error) {
|
|
||||||
return k8sClient.CoreV1().Secrets(metav1.NamespaceSystem).Get(secretName, metav1.GetOptions{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteNode(k8sClient *kubernetes.Clientset, nodeName string) error {
|
|
||||||
return k8sClient.CoreV1().Nodes().Delete(nodeName, &metav1.DeleteOptions{})
|
|
||||||
}
|
|
||||||
|
54
k8s/node.go
Normal file
54
k8s/node.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package k8s
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DeleteNode(k8sClient *kubernetes.Clientset, nodeName string) error {
|
||||||
|
return k8sClient.CoreV1().Nodes().Delete(nodeName, &metav1.DeleteOptions{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetNodeList(k8sClient *kubernetes.Clientset) (*v1.NodeList, error) {
|
||||||
|
return k8sClient.CoreV1().Nodes().List(metav1.ListOptions{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func CordonUncordon(k8sClient *kubernetes.Clientset, nodeName string, cordoned bool) error {
|
||||||
|
updated := false
|
||||||
|
for retries := 0; retries <= 5; retries++ {
|
||||||
|
node, err := k8sClient.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
logrus.Debugf("Error getting node %s: %v", nodeName, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if node.Spec.Unschedulable == cordoned {
|
||||||
|
logrus.Debugf("Node %s is already cordoned: %v", nodeName, cordoned)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
node.Spec.Unschedulable = cordoned
|
||||||
|
_, err = k8sClient.CoreV1().Nodes().Update(node)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Debugf("Error setting cordoned state for node %s: %v", nodeName, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
if !updated {
|
||||||
|
return fmt.Errorf("Failed to set cordonded state for node: %s", nodeName)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsNodeReady(node v1.Node) bool {
|
||||||
|
nodeConditions := node.Status.Conditions
|
||||||
|
for _, condition := range nodeConditions {
|
||||||
|
if condition.Type == "Ready" && condition.Status == v1.ConditionTrue {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
47
k8s/secret.go
Normal file
47
k8s/secret.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package k8s
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetSecret(k8sClient *kubernetes.Clientset, secretName string) (*v1.Secret, error) {
|
||||||
|
return k8sClient.CoreV1().Secrets(metav1.NamespaceSystem).Get(secretName, metav1.GetOptions{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdateSecret(k8sClient *kubernetes.Clientset, fieldName string, secretData []byte, secretName string) error {
|
||||||
|
secret := &v1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: secretName,
|
||||||
|
Namespace: metav1.NamespaceSystem,
|
||||||
|
},
|
||||||
|
Data: map[string][]byte{
|
||||||
|
fieldName: secretData,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if _, err := k8sClient.CoreV1().Secrets(metav1.NamespaceSystem).Create(secret); err != nil {
|
||||||
|
if !apierrors.IsAlreadyExists(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// update secret if its already exist
|
||||||
|
oldSecret, err := k8sClient.CoreV1().Secrets(metav1.NamespaceSystem).Get(secretName, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
newData := oldSecret.Data
|
||||||
|
newData[fieldName] = secretData
|
||||||
|
secret := &v1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: secretName,
|
||||||
|
Namespace: metav1.NamespaceSystem,
|
||||||
|
},
|
||||||
|
Data: newData,
|
||||||
|
}
|
||||||
|
if _, err := k8sClient.CoreV1().Secrets(metav1.NamespaceSystem).Update(secret); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -28,3 +28,26 @@ func RunControlPlane(controlHosts []hosts.Host, etcdHosts []hosts.Host, controlS
|
|||||||
logrus.Infof("[%s] Successfully started Controller Plane..", ControlRole)
|
logrus.Infof("[%s] Successfully started Controller Plane..", ControlRole)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func UpgradeControlPlane(controlHosts []hosts.Host, etcdHosts []hosts.Host, controlServices v1.RKEConfigServices) error {
|
||||||
|
logrus.Infof("[%s] Upgrading the Controller Plane..", ControlRole)
|
||||||
|
for _, host := range controlHosts {
|
||||||
|
// upgrade KubeAPI
|
||||||
|
if err := upgradeKubeAPI(host, etcdHosts, controlServices.KubeAPI); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// upgrade KubeController
|
||||||
|
if err := upgradeKubeController(host, controlServices.KubeController); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// upgrade scheduler
|
||||||
|
err := upgradeScheduler(host, controlServices.Scheduler)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logrus.Infof("[%s] Successfully upgraded Controller Plane..", ControlRole)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/rancher/rke/hosts"
|
"github.com/rancher/rke/hosts"
|
||||||
"github.com/rancher/rke/pki"
|
"github.com/rancher/rke/pki"
|
||||||
"github.com/rancher/types/apis/cluster.cattle.io/v1"
|
"github.com/rancher/types/apis/cluster.cattle.io/v1"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func runKubeAPI(host hosts.Host, etcdHosts []hosts.Host, kubeAPIService v1.KubeAPIService) error {
|
func runKubeAPI(host hosts.Host, etcdHosts []hosts.Host, kubeAPIService v1.KubeAPIService) error {
|
||||||
@ -17,6 +18,31 @@ func runKubeAPI(host hosts.Host, etcdHosts []hosts.Host, kubeAPIService v1.KubeA
|
|||||||
return docker.DoRunContainer(host.DClient, imageCfg, hostCfg, KubeAPIContainerName, host.AdvertisedHostname, ControlRole)
|
return docker.DoRunContainer(host.DClient, imageCfg, hostCfg, KubeAPIContainerName, host.AdvertisedHostname, ControlRole)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func upgradeKubeAPI(host hosts.Host, etcdHosts []hosts.Host, kubeAPIService v1.KubeAPIService) error {
|
||||||
|
logrus.Debugf("[upgrade/KubeAPI] Checking for deployed version")
|
||||||
|
containerInspect, err := docker.InspectContainer(host.DClient, host.AdvertisedHostname, KubeAPIContainerName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if containerInspect.Config.Image == kubeAPIService.Image {
|
||||||
|
logrus.Infof("[upgrade/KubeAPI] KubeAPI is already up to date")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
logrus.Debugf("[upgrade/KubeAPI] Stopping old container")
|
||||||
|
oldContainerName := "old-" + KubeAPIContainerName
|
||||||
|
if err := docker.StopRenameContainer(host.DClient, host.AdvertisedHostname, KubeAPIContainerName, oldContainerName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Container doesn't exist now!, lets deploy it!
|
||||||
|
logrus.Debugf("[upgrade/KubeAPI] Deploying new container")
|
||||||
|
if err := runKubeAPI(host, etcdHosts, kubeAPIService); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logrus.Debugf("[upgrade/KubeAPI] Removing old container")
|
||||||
|
err = docker.RemoveContainer(host.DClient, host.AdvertisedHostname, oldContainerName)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func buildKubeAPIConfig(host hosts.Host, kubeAPIService v1.KubeAPIService, etcdConnString string) (*container.Config, *container.HostConfig) {
|
func buildKubeAPIConfig(host hosts.Host, kubeAPIService v1.KubeAPIService, etcdConnString string) (*container.Config, *container.HostConfig) {
|
||||||
imageCfg := &container.Config{
|
imageCfg := &container.Config{
|
||||||
Image: kubeAPIService.Image,
|
Image: kubeAPIService.Image,
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/rancher/rke/hosts"
|
"github.com/rancher/rke/hosts"
|
||||||
"github.com/rancher/rke/pki"
|
"github.com/rancher/rke/pki"
|
||||||
"github.com/rancher/types/apis/cluster.cattle.io/v1"
|
"github.com/rancher/types/apis/cluster.cattle.io/v1"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func runKubeController(host hosts.Host, kubeControllerService v1.KubeControllerService) error {
|
func runKubeController(host hosts.Host, kubeControllerService v1.KubeControllerService) error {
|
||||||
@ -15,6 +16,32 @@ func runKubeController(host hosts.Host, kubeControllerService v1.KubeControllerS
|
|||||||
return docker.DoRunContainer(host.DClient, imageCfg, hostCfg, KubeControllerContainerName, host.AdvertisedHostname, ControlRole)
|
return docker.DoRunContainer(host.DClient, imageCfg, hostCfg, KubeControllerContainerName, host.AdvertisedHostname, ControlRole)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func upgradeKubeController(host hosts.Host, kubeControllerService v1.KubeControllerService) error {
|
||||||
|
logrus.Debugf("[upgrade/KubeController] Checking for deployed version")
|
||||||
|
containerInspect, err := docker.InspectContainer(host.DClient, host.AdvertisedHostname, KubeControllerContainerName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if containerInspect.Config.Image == kubeControllerService.Image {
|
||||||
|
logrus.Infof("[upgrade/KubeController] KubeController is already up to date")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
logrus.Debugf("[upgrade/KubeController] Stopping old container")
|
||||||
|
oldContainerName := "old-" + KubeControllerContainerName
|
||||||
|
if err := docker.StopRenameContainer(host.DClient, host.AdvertisedHostname, KubeControllerContainerName, oldContainerName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Container doesn't exist now!, lets deploy it!
|
||||||
|
logrus.Debugf("[upgrade/KubeController] Deploying new container")
|
||||||
|
if err := runKubeController(host, kubeControllerService); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logrus.Debugf("[upgrade/KubeController] Removing old container")
|
||||||
|
err = docker.RemoveContainer(host.DClient, host.AdvertisedHostname, oldContainerName)
|
||||||
|
return err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func buildKubeControllerConfig(kubeControllerService v1.KubeControllerService) (*container.Config, *container.HostConfig) {
|
func buildKubeControllerConfig(kubeControllerService v1.KubeControllerService) (*container.Config, *container.HostConfig) {
|
||||||
imageCfg := &container.Config{
|
imageCfg := &container.Config{
|
||||||
Image: kubeControllerService.Image,
|
Image: kubeControllerService.Image,
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/rancher/rke/hosts"
|
"github.com/rancher/rke/hosts"
|
||||||
"github.com/rancher/rke/pki"
|
"github.com/rancher/rke/pki"
|
||||||
"github.com/rancher/types/apis/cluster.cattle.io/v1"
|
"github.com/rancher/types/apis/cluster.cattle.io/v1"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func runKubelet(host hosts.Host, kubeletService v1.KubeletService, isMaster bool) error {
|
func runKubelet(host hosts.Host, kubeletService v1.KubeletService, isMaster bool) error {
|
||||||
@ -16,6 +17,31 @@ func runKubelet(host hosts.Host, kubeletService v1.KubeletService, isMaster bool
|
|||||||
return docker.DoRunContainer(host.DClient, imageCfg, hostCfg, KubeletContainerName, host.AdvertisedHostname, WorkerRole)
|
return docker.DoRunContainer(host.DClient, imageCfg, hostCfg, KubeletContainerName, host.AdvertisedHostname, WorkerRole)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func upgradeKubelet(host hosts.Host, kubeletService v1.KubeletService, isMaster bool) error {
|
||||||
|
logrus.Debugf("[upgrade/Kubelet] Checking for deployed version")
|
||||||
|
containerInspect, err := docker.InspectContainer(host.DClient, host.AdvertisedHostname, KubeletContainerName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if containerInspect.Config.Image == kubeletService.Image {
|
||||||
|
logrus.Infof("[upgrade/Kubelet] Kubelet is already up to date")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
logrus.Debugf("[upgrade/Kubelet] Stopping old container")
|
||||||
|
oldContainerName := "old-" + KubeletContainerName
|
||||||
|
if err := docker.StopRenameContainer(host.DClient, host.AdvertisedHostname, KubeletContainerName, oldContainerName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Container doesn't exist now!, lets deploy it!
|
||||||
|
logrus.Debugf("[upgrade/Kubelet] Deploying new container")
|
||||||
|
if err := runKubelet(host, kubeletService, isMaster); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logrus.Debugf("[upgrade/Kubelet] Removing old container")
|
||||||
|
err = docker.RemoveContainer(host.DClient, host.AdvertisedHostname, oldContainerName)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func buildKubeletConfig(host hosts.Host, kubeletService v1.KubeletService, isMaster bool) (*container.Config, *container.HostConfig) {
|
func buildKubeletConfig(host hosts.Host, kubeletService v1.KubeletService, isMaster bool) (*container.Config, *container.HostConfig) {
|
||||||
imageCfg := &container.Config{
|
imageCfg := &container.Config{
|
||||||
Image: kubeletService.Image,
|
Image: kubeletService.Image,
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/rancher/rke/hosts"
|
"github.com/rancher/rke/hosts"
|
||||||
"github.com/rancher/rke/pki"
|
"github.com/rancher/rke/pki"
|
||||||
"github.com/rancher/types/apis/cluster.cattle.io/v1"
|
"github.com/rancher/types/apis/cluster.cattle.io/v1"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func runKubeproxy(host hosts.Host, kubeproxyService v1.KubeproxyService) error {
|
func runKubeproxy(host hosts.Host, kubeproxyService v1.KubeproxyService) error {
|
||||||
@ -15,6 +16,30 @@ func runKubeproxy(host hosts.Host, kubeproxyService v1.KubeproxyService) error {
|
|||||||
return docker.DoRunContainer(host.DClient, imageCfg, hostCfg, KubeproxyContainerName, host.AdvertisedHostname, WorkerRole)
|
return docker.DoRunContainer(host.DClient, imageCfg, hostCfg, KubeproxyContainerName, host.AdvertisedHostname, WorkerRole)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func upgradeKubeproxy(host hosts.Host, kubeproxyService v1.KubeproxyService) error {
|
||||||
|
logrus.Debugf("[upgrade/Kubeproxy] Checking for deployed version")
|
||||||
|
containerInspect, err := docker.InspectContainer(host.DClient, host.AdvertisedHostname, KubeproxyContainerName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if containerInspect.Config.Image == kubeproxyService.Image {
|
||||||
|
logrus.Infof("[upgrade/Kubeproxy] Kubeproxy is already up to date")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
logrus.Debugf("[upgrade/Kubeproxy] Stopping old container")
|
||||||
|
oldContainerName := "old-" + KubeproxyContainerName
|
||||||
|
if err := docker.StopRenameContainer(host.DClient, host.AdvertisedHostname, KubeproxyContainerName, oldContainerName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Container doesn't exist now!, lets deploy it!
|
||||||
|
logrus.Debugf("[upgrade/Kubeproxy] Deploying new container")
|
||||||
|
if err := runKubeproxy(host, kubeproxyService); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logrus.Debugf("[upgrade/Kubeproxy] Removing old container")
|
||||||
|
err = docker.RemoveContainer(host.DClient, host.AdvertisedHostname, oldContainerName)
|
||||||
|
return err
|
||||||
|
}
|
||||||
func buildKubeproxyConfig(host hosts.Host, kubeproxyService v1.KubeproxyService) (*container.Config, *container.HostConfig) {
|
func buildKubeproxyConfig(host hosts.Host, kubeproxyService v1.KubeproxyService) (*container.Config, *container.HostConfig) {
|
||||||
imageCfg := &container.Config{
|
imageCfg := &container.Config{
|
||||||
Image: kubeproxyService.Image,
|
Image: kubeproxyService.Image,
|
||||||
|
@ -8,12 +8,37 @@ import (
|
|||||||
"github.com/rancher/rke/hosts"
|
"github.com/rancher/rke/hosts"
|
||||||
"github.com/rancher/rke/pki"
|
"github.com/rancher/rke/pki"
|
||||||
"github.com/rancher/types/apis/cluster.cattle.io/v1"
|
"github.com/rancher/types/apis/cluster.cattle.io/v1"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func runScheduler(host hosts.Host, schedulerService v1.SchedulerService) error {
|
func runScheduler(host hosts.Host, schedulerService v1.SchedulerService) error {
|
||||||
imageCfg, hostCfg := buildSchedulerConfig(host, schedulerService)
|
imageCfg, hostCfg := buildSchedulerConfig(host, schedulerService)
|
||||||
return docker.DoRunContainer(host.DClient, imageCfg, hostCfg, SchedulerContainerName, host.AdvertisedHostname, ControlRole)
|
return docker.DoRunContainer(host.DClient, imageCfg, hostCfg, SchedulerContainerName, host.AdvertisedHostname, ControlRole)
|
||||||
}
|
}
|
||||||
|
func upgradeScheduler(host hosts.Host, schedulerService v1.SchedulerService) error {
|
||||||
|
logrus.Debugf("[upgrade/Scheduler] Checking for deployed version")
|
||||||
|
containerInspect, err := docker.InspectContainer(host.DClient, host.AdvertisedHostname, SchedulerContainerName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if containerInspect.Config.Image == schedulerService.Image {
|
||||||
|
logrus.Infof("[upgrade/Scheduler] Scheduler is already up to date")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
logrus.Debugf("[upgrade/Scheduler] Stopping old container")
|
||||||
|
oldContainerName := "old-" + SchedulerContainerName
|
||||||
|
if err := docker.StopRenameContainer(host.DClient, host.AdvertisedHostname, SchedulerContainerName, oldContainerName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Container doesn't exist now!, lets deploy it!
|
||||||
|
logrus.Debugf("[upgrade/Scheduler] Deploying new container")
|
||||||
|
if err := runScheduler(host, schedulerService); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logrus.Debugf("[upgrade/Scheduler] Removing old container")
|
||||||
|
err = docker.RemoveContainer(host.DClient, host.AdvertisedHostname, oldContainerName)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func buildSchedulerConfig(host hosts.Host, schedulerService v1.SchedulerService) (*container.Config, *container.HostConfig) {
|
func buildSchedulerConfig(host hosts.Host, schedulerService v1.SchedulerService) (*container.Config, *container.HostConfig) {
|
||||||
imageCfg := &container.Config{
|
imageCfg := &container.Config{
|
||||||
|
@ -2,6 +2,8 @@ package services
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/rancher/rke/hosts"
|
"github.com/rancher/rke/hosts"
|
||||||
|
"github.com/rancher/rke/k8s"
|
||||||
|
"github.com/rancher/rke/pki"
|
||||||
"github.com/rancher/types/apis/cluster.cattle.io/v1"
|
"github.com/rancher/types/apis/cluster.cattle.io/v1"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@ -34,3 +36,55 @@ func RunWorkerPlane(controlHosts []hosts.Host, workerHosts []hosts.Host, workerS
|
|||||||
logrus.Infof("[%s] Successfully started Worker Plane..", WorkerRole)
|
logrus.Infof("[%s] Successfully started Worker Plane..", WorkerRole)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func UpgradeWorkerPlane(controlHosts []hosts.Host, workerHosts []hosts.Host, workerServices v1.RKEConfigServices) error {
|
||||||
|
logrus.Infof("[%s] Upgrading Worker Plane..", WorkerRole)
|
||||||
|
k8sClient, err := k8s.NewClient(pki.KubeAdminConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, host := range controlHosts {
|
||||||
|
// cordone the node
|
||||||
|
logrus.Debugf("[upgrade] Cordoning node: %s", host.AdvertisedHostname)
|
||||||
|
if err = k8s.CordonUncordon(k8sClient, host.AdvertisedHostname, true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = upgradeKubelet(host, workerServices.Kubelet, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = upgradeKubeproxy(host, workerServices.Kubeproxy)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Debugf("[upgrade] Uncordoning node: %s", host.AdvertisedHostname)
|
||||||
|
if err = k8s.CordonUncordon(k8sClient, host.AdvertisedHostname, false); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, host := range workerHosts {
|
||||||
|
// cordone the node
|
||||||
|
logrus.Debugf("[upgrade] Cordoning node: %s", host.AdvertisedHostname)
|
||||||
|
if err = k8s.CordonUncordon(k8sClient, host.AdvertisedHostname, true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// upgrade kubelet
|
||||||
|
err := upgradeKubelet(host, workerServices.Kubelet, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// upgrade kubeproxy
|
||||||
|
err = upgradeKubeproxy(host, workerServices.Kubeproxy)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Debugf("[upgrade] Uncordoning node: %s", host.AdvertisedHostname)
|
||||||
|
if err = k8s.CordonUncordon(k8sClient, host.AdvertisedHostname, false); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logrus.Infof("[%s] Successfully upgraded Worker Plane..", WorkerRole)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user