Skip to content

Commit

Permalink
reuse node-servant upgrade logic
Browse files Browse the repository at this point in the history
Signed-off-by: hxcGit <houxc_mail@163.com>
  • Loading branch information
xavier-hou committed Apr 14, 2023
1 parent c5433b3 commit f5a0bad
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 93 deletions.
85 changes: 45 additions & 40 deletions pkg/node-servant/static-pod-upgrade/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,10 @@ import (

"k8s.io/klog/v2"

appsv1alpha1 "github.com/openyurtio/openyurt/pkg/apis/apps/v1alpha1"
"github.com/openyurtio/openyurt/pkg/node-servant/static-pod-upgrade/util"
)

const (
// TODO: use constant value of static-pod controller
OTA = "ota"
Auto = "auto"
)

var (
DefaultConfigmapPath = "/data"
DefaultManifestPath = "/etc/kubernetes/manifests"
Expand Down Expand Up @@ -64,59 +59,64 @@ type Controller struct {
}

func NewWithOptions(o *Options) (*Controller, error) {
ctrl := New(o.name, o.namespace, o.manifest, o.mode)
ctrl.hash = o.hash
ctrl.timeout = o.timeout
return ctrl, nil
}

func New(name, namespace, manifest, mode string) *Controller {
ctrl := &Controller{
name: o.name,
namespace: o.namespace,
manifest: o.manifest,
hash: o.hash,
upgradeMode: o.mode,
timeout: o.timeout,
name: name,
namespace: namespace,
manifest: manifest,
upgradeMode: mode,
}

ctrl.manifestPath = filepath.Join(DefaultManifestPath, util.WithYamlSuffix(ctrl.manifest))
ctrl.bakManifestPath = filepath.Join(DefaultUpgradePath, util.WithBackupSuffix(ctrl.manifest))
ctrl.configMapDataPath = filepath.Join(DefaultConfigmapPath, ctrl.manifest)
ctrl.upgradeManifestPath = filepath.Join(DefaultUpgradePath, util.WithUpgradeSuffix(ctrl.manifest))

return ctrl, nil
return ctrl
}

func (ctrl *Controller) Upgrade() error {
// 1. Check old manifest and the latest manifest exist
if err := ctrl.checkManifestFileExist(); err != nil {
return err
}
klog.Info("Check old manifest and new manifest files existence success")

// 2. prepare the latest manifest
if err := ctrl.prepareManifest(); err != nil {
if err := ctrl.createUpgradeSpace(); err != nil {
return err
}
klog.Info("Prepare upgrade manifest success")
klog.Info("Create upgrade space success")

// 3. execute upgrade operations
// execute upgrade operations
switch ctrl.upgradeMode {
case Auto:
case string(appsv1alpha1.AutoStaticPodUpgradeStrategyType):
return ctrl.AutoUpgrade()
case string(appsv1alpha1.OTAStaticPodUpgradeStrategyType):
return ctrl.OTAUpgrade()
}

return nil
}

func (ctrl *Controller) AutoUpgrade() error {
// (1) Back up the old manifest in case of upgrade failure
// (1) Prepare the latest manifest
if err := ctrl.prepareManifest(); err != nil {
return err
}
klog.Info("Auto prepare upgrade manifest success")

// (2) Back up the old manifest in case of upgrade failure
if err := ctrl.backupManifest(); err != nil {
return err
}
klog.Info("Auto upgrade backupManifest success")

// (2) Replace manifest and kubelet will upgrade the static pod automatically
// (3) Replace manifest and kubelet will upgrade the static pod automatically
if err := ctrl.replaceManifest(); err != nil {
return err
}
klog.Info("Auto upgrade replaceManifest success")

// (3) Verify the new static pod is running
// (4) Verify the new static pod is running
ok, err := ctrl.verify()
if err != nil {
if err := ctrl.rollbackManifest(); err != nil {
Expand All @@ -135,30 +135,35 @@ func (ctrl *Controller) AutoUpgrade() error {
return nil
}

// checkManifestFileExist check if the specified files exist
func (ctrl *Controller) checkManifestFileExist() error {
check := []string{ctrl.manifestPath, ctrl.configMapDataPath}
for _, c := range check {
_, err := os.Stat(c)
if os.IsNotExist(err) {
return fmt.Errorf("manifest %s does not exist", c)
}
func (ctrl *Controller) OTAUpgrade() error {
// (1) Back up the old manifest in case of upgrade failure
if err := ctrl.backupManifest(); err != nil {
return err
}
klog.Info("OTA upgrade backupManifest success")

// (2) Replace manifest and kubelet will upgrade the static pod automatically
if err := ctrl.replaceManifest(); err != nil {
return err
}
klog.Info("OTA upgrade replaceManifest success")

return nil
}

// prepareManifest move the latest manifest to DefaultUpgradePath and set `.upgrade` suffix
// TODO: In kubernetes when mount configmap file to the sub path of hostpath mount, it will not be persistent
// TODO: Init configmap(latest manifest) to a default place and move it to `DefaultUpgradePath` to save it persistent
func (ctrl *Controller) prepareManifest() error {
// createUpgradeSpace creates DefaultUpgradePath if it doesn't exist
func (ctrl *Controller) createUpgradeSpace() error {
// Make sure upgrade dir exist
if _, err := os.Stat(DefaultUpgradePath); os.IsNotExist(err) {
if err = os.Mkdir(DefaultUpgradePath, 0755); err != nil {
return err
}
}
return nil
}

// prepareManifest move the latest manifest to DefaultUpgradePath and set `.upgrade` suffix
func (ctrl *Controller) prepareManifest() error {
return util.CopyFile(ctrl.configMapDataPath, ctrl.upgradeManifestPath)
}

Expand Down
22 changes: 4 additions & 18 deletions pkg/node-servant/static-pod-upgrade/upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"path/filepath"
"strings"
"testing"
"time"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -56,7 +57,7 @@ func Test(t *testing.T) {
},
}

modes := []string{"ota", "auto"}
modes := []string{"auto"}

for _, mode := range modes {
/*
Expand All @@ -79,15 +80,15 @@ func Test(t *testing.T) {
manifest: TestManifest,
hash: TestHashValue,
mode: mode,
timeout: DefaultStaticPodRunningCheckTimeout,
timeout: time.Second,
}
ctrl, err := NewWithOptions(o)
if err != nil {
t.Errorf("Fail to get upgrade controller, %v", err)
}

if err := ctrl.Upgrade(); err != nil {
if strings.Contains(err.Error(), "fail to access yurthub pods API") {
if !strings.Contains(err.Error(), "timeout waiting for static pod") {
t.Errorf("Fail to upgrade, %v", err)
}
}
Expand All @@ -104,20 +105,5 @@ func Test(t *testing.T) {
t.Errorf("Manifest for ota upgrade does not exist")
}
}
/*
4. Verify Auto upgrade mode
*/
if mode == "auto" {
checkFiles := []string{ctrl.upgradeManifestPath, ctrl.bakManifestPath}
for _, file := range checkFiles {
ok, err := util.FileExists(file)
if err != nil {
t.Errorf("Fail to check %s manifest existence for auto upgrade, %v", file, err)
}
if !ok {
t.Errorf("Manifest %s for auto upgrade does not exist", file)
}
}
}
}
}
17 changes: 13 additions & 4 deletions pkg/yurthub/otaupdate/ota.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ import (
"github.com/openyurtio/openyurt/pkg/controller/daemonpodupdater"
"github.com/openyurtio/openyurt/pkg/yurthub/cachemanager"
"github.com/openyurtio/openyurt/pkg/yurthub/kubernetes/rest"
"github.com/openyurtio/openyurt/pkg/yurthub/otaupdate/daemon"
"github.com/openyurtio/openyurt/pkg/yurthub/otaupdate/static"
upgrade "github.com/openyurtio/openyurt/pkg/yurthub/otaupdate/upgrader"
"github.com/openyurtio/openyurt/pkg/yurthub/otaupdate/util"
"github.com/openyurtio/openyurt/pkg/yurthub/storage"
)
Expand Down Expand Up @@ -108,10 +107,20 @@ func UpdatePod(clientset kubernetes.Interface, nodeName string) http.Handler {
kind := pod.GetOwnerReferences()[0].Kind
switch kind {
case StaticPod:
upgrader = &static.StaticPodUpgrader{Interface: clientset,
ok, err := upgrade.PreCheck(podName, namespace, clientset)
if err != nil {
util.WriteErr(w, "Static pod pre-check failed", http.StatusInternalServerError)
return
}
if !ok {
util.WriteErr(w, "Configmap for static pod does not exist", http.StatusForbidden)
return
}
upgrader = &upgrade.StaticPodUpgrader{Interface: clientset,
NamespacedName: types.NamespacedName{Namespace: namespace, Name: podName}}

case DaemonPod:
upgrader = &daemon.DaemonPodUpgrader{Interface: clientset,
upgrader = &upgrade.DaemonPodUpgrader{Interface: clientset,
NamespacedName: types.NamespacedName{Namespace: namespace, Name: podName}}
default:
util.WriteErr(w, fmt.Sprintf("Not support ota upgrade pod type %v", kind), http.StatusBadRequest)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package daemon
package upgrader

import (
"context"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package daemon
package upgrader

import (
"testing"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package static
package upgrader

import (
"context"
Expand All @@ -23,18 +23,21 @@ import (
"os"
"path/filepath"

apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
"k8s.io/klog/v2"

spctrlutil "github.com/openyurtio/openyurt/pkg/controller/staticpod/util"
upgrade "github.com/openyurtio/openyurt/pkg/node-servant/static-pod-upgrade"
upgradeutil "github.com/openyurtio/openyurt/pkg/node-servant/static-pod-upgrade/util"
)

const OTA = "ota"

var (
DefaultManifestPath = "/etc/kubernetes/manifests"
DefaultUpgradePath = "/tmp/manifests"
DefaultUpgradePath = "/tmp/manifests"
)

type StaticPodUpgrader struct {
Expand All @@ -43,19 +46,7 @@ type StaticPodUpgrader struct {
}

func (s *StaticPodUpgrader) Apply() error {
manifestPath := filepath.Join(DefaultManifestPath, upgradeutil.WithYamlSuffix(s.Name))
upgradeManifestPath := filepath.Join(DefaultUpgradePath, upgradeutil.WithUpgradeSuffix(s.Name))
backupManifestPath := filepath.Join(DefaultUpgradePath, upgradeutil.WithBackupSuffix(s.Name))

// 1. Make sure upgrade dir exist
if _, err := os.Stat(DefaultUpgradePath); os.IsNotExist(err) {
if err = os.Mkdir(DefaultUpgradePath, 0755); err != nil {
return err
}
klog.V(5).Infof("Create upgrade dir %v", DefaultUpgradePath)
}

// 2. Get upgrade manifest from api-serv
cm, err := s.CoreV1().ConfigMaps(s.Namespace).Get(context.TODO(),
spctrlutil.WithConfigMapPrefix(spctrlutil.Hyphen(s.Namespace, s.Name)), metav1.GetOptions{})
if err != nil {
Expand All @@ -71,19 +62,20 @@ func (s *StaticPodUpgrader) Apply() error {
}
klog.V(5).Info("Generate upgrade manifest")

// 3. Backup manifest
if err := upgradeutil.CopyFile(manifestPath, backupManifestPath); err != nil {
return err
}
klog.V(5).Info("Backup upgrade manifest success")
ctrl := upgrade.New(s.Name, s.Namespace, s.Name, OTA)
return ctrl.Upgrade()
}

// 4. Execute upgrade
if err := upgradeutil.CopyFile(upgradeManifestPath, manifestPath); err != nil {
return err
func PreCheck(name, namespace string, c kubernetes.Interface) (bool, error) {
_, err := c.CoreV1().ConfigMaps(namespace).Get(context.TODO(),
spctrlutil.WithConfigMapPrefix(spctrlutil.Hyphen(namespace, name)), metav1.GetOptions{})
if err != nil {
if apierrors.IsNotFound(err) {
return false, nil
}
return false, err
}
klog.V(5).Info("Replace upgrade manifest success")

return nil
return true, nil
}

func genUpgradeManifest(path, data string) error {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package static
package upgrader

import (
"os"
Expand All @@ -28,14 +28,17 @@ import (
"k8s.io/client-go/kubernetes/fake"

spctrlutil "github.com/openyurtio/openyurt/pkg/controller/staticpod/util"
upgrade "github.com/openyurtio/openyurt/pkg/node-servant/static-pod-upgrade"
upgradeutil "github.com/openyurtio/openyurt/pkg/node-servant/static-pod-upgrade/util"
"github.com/openyurtio/openyurt/pkg/yurthub/otaupdate/util"
)

func TestStaticPodUpgrader_ApplyManifestNotExist(t *testing.T) {
// Temporarily modify the manifest path in order to test
DefaultManifestPath = t.TempDir()
_, _ = os.Create(filepath.Join(DefaultManifestPath, upgradeutil.WithYamlSuffix("nginx")))
upgrade.DefaultUpgradePath = t.TempDir()
upgrade.DefaultManifestPath = t.TempDir()
DefaultUpgradePath = upgrade.DefaultUpgradePath
_, _ = os.Create(filepath.Join(upgrade.DefaultManifestPath, upgradeutil.WithYamlSuffix("nginx")))

cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Expand Down

0 comments on commit f5a0bad

Please sign in to comment.