Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,6 @@ WORKDIR /go/src/github.com/openshift/machine-config-operator
COPY . .
RUN make install DESTDIR=./instroot-rhel9

# Add a RHEL 8 builder to compile the RHEL 8 compatible binaries
FROM registry.ci.openshift.org/ocp/builder:rhel-8-golang-1.25-openshift-4.22 AS rhel8-builder
ARG TAGS=""
WORKDIR /go/src/github.com/openshift/machine-config-operator
# Copy the RHEL 8 machine-config-daemon binary and rename
COPY . .
RUN make install DESTDIR=./instroot-rhel8

FROM registry.ci.openshift.org/ocp/4.22:base-rhel9
ARG TAGS=""
COPY install /manifests
Expand Down Expand Up @@ -45,8 +37,6 @@ RUN if [ "${TAGS}" = "fcos" ]; then \
# Do this after package installation to avoid invalidating state for faster
# local builds.
COPY --from=rhel9-builder /go/src/github.com/openshift/machine-config-operator/instroot-rhel9/usr/bin/* /usr/bin/
# Copy the RHEL 8 machine-config-daemon binary and rename
COPY --from=rhel8-builder /go/src/github.com/openshift/machine-config-operator/instroot-rhel8/usr/bin/machine-config-daemon /usr/bin/machine-config-daemon.rhel8
COPY templates /etc/mcc/templates
ENTRYPOINT ["/usr/bin/machine-config-operator"]
LABEL io.openshift.release.operator true
10 changes: 0 additions & 10 deletions Dockerfile.rhel7
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,6 @@ WORKDIR /go/src/github.com/openshift/machine-config-operator
COPY . .
RUN make install DESTDIR=./instroot-rhel9

# Add a RHEL 8 builder to compile the RHEL 8 compatible binaries
FROM registry.ci.openshift.org/ocp/builder:rhel-8-golang-1.25-openshift-4.22 AS rhel8-builder
ARG TAGS=""
WORKDIR /go/src/github.com/openshift/machine-config-operator
# Copy the RHEL 8 machine-config-daemon binary and rename
COPY . .
RUN make install DESTDIR=./instroot-rhel8

FROM registry.ci.openshift.org/ocp/4.22:base-rhel9
ARG TAGS=""
COPY install /manifests
Expand Down Expand Up @@ -46,8 +38,6 @@ RUN if [ "${TAGS}" = "fcos" ]; then \
# Do this after package installation to avoid invalidating state for faster
# local builds.
COPY --from=rhel9-builder /go/src/github.com/openshift/machine-config-operator/instroot-rhel9/usr/bin/* /usr/bin/
# Copy the RHEL 8 machine-config-daemon binary and rename
COPY --from=rhel8-builder /go/src/github.com/openshift/machine-config-operator/instroot-rhel8/usr/bin/machine-config-daemon /usr/bin/machine-config-daemon.rhel8
COPY templates /etc/mcc/templates
ENTRYPOINT ["/usr/bin/machine-config-operator"]
LABEL io.openshift.release.operator true
5 changes: 1 addition & 4 deletions pkg/daemon/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,8 @@ const (
// SSH Keys for user "core" will only be written at /home/core/.ssh
CoreUserSSHPath = "/home/" + CoreUserName + "/.ssh"

// SSH keys in RHCOS 8 will be written to /home/core/.ssh/authorized_keys
RHCOS8SSHKeyPath = CoreUserSSHPath + "/authorized_keys"

// SSH keys in RHCOS 9 / FCOS / SCOS will be written to /home/core/.ssh/authorized_keys.d/ignition
RHCOS9SSHKeyPath = CoreUserSSHPath + "/authorized_keys.d/ignition"
RHCOSDefaultSSHKeyPath = CoreUserSSHPath + "/authorized_keys.d/ignition"

// CRIOServiceName is used to specify reloads and restarts of the CRI-O service
CRIOServiceName = "crio"
Expand Down
102 changes: 11 additions & 91 deletions pkg/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,7 @@ const (
onceFromRemoteConfig
)

var (
defaultRebootTimeout = 24 * time.Hour
)
var defaultRebootTimeout = 24 * time.Hour

// rebootCommand creates a new transient systemd unit to reboot the system.
// With the upstream implementation of kubelet graceful shutdown feature,
Expand All @@ -267,8 +265,10 @@ var (
// kubelet uses systemd inhibitor locks to delay node shutdown to terminate pods.
// https://kubernetes.io/docs/concepts/architecture/nodes/#graceful-node-shutdown
func rebootCommand(rationale string, workaroundOCPBUGS51150 bool) *exec.Cmd {
systemdRunArgs := []string{"--unit", "machine-config-daemon-reboot",
"--description", fmt.Sprintf("machine-config-daemon: %s", rationale)}
systemdRunArgs := []string{
"--unit", "machine-config-daemon-reboot",
"--description", fmt.Sprintf("machine-config-daemon: %s", rationale),
}
// we need this until we have https://github.com/ostreedev/ostree/pull/3389
if workaroundOCPBUGS51150 {
systemdRunArgs = append(systemdRunArgs, "-p", "Requires=ostree-finalize-staged.service", "-p", "After=ostree-finalize-staged.service")
Expand Down Expand Up @@ -384,7 +384,8 @@ func (dn *Daemon) ClusterConnect(
// we don't need to react in milliseconds. See also updateDelay above.
dn.queue = workqueue.NewTypedRateLimitingQueueWithConfig[string](workqueue.NewTypedMaxOfRateLimiter[string](
&workqueue.TypedBucketRateLimiter[string]{Limiter: rate.NewLimiter(rate.Limit(updateDelay), 1)},
workqueue.NewTypedItemExponentialFailureRateLimiter[string](1*time.Second, maxUpdateBackoff)),
workqueue.NewTypedItemExponentialFailureRateLimiter[string](1*time.Second, maxUpdateBackoff),
),
workqueue.TypedRateLimitingQueueConfig[string]{Name: "machineconfigdaemon"})

nodeInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
Expand Down Expand Up @@ -457,7 +458,8 @@ func (dn *Daemon) HypershiftConnect(

dn.queue = workqueue.NewTypedRateLimitingQueueWithConfig[string](workqueue.NewTypedMaxOfRateLimiter[string](
&workqueue.TypedBucketRateLimiter[string]{Limiter: rate.NewLimiter(rate.Limit(updateDelay), 1)},
workqueue.NewTypedItemExponentialFailureRateLimiter[string](1*time.Second, maxUpdateBackoff)),
workqueue.NewTypedItemExponentialFailureRateLimiter[string](1*time.Second, maxUpdateBackoff),
),
workqueue.TypedRateLimitingQueueConfig[string]{Name: "machineconfigdaemon"})

dn.enqueueNode = dn.enqueueDefault
Expand Down Expand Up @@ -540,12 +542,6 @@ func ReexecuteForTargetRoot(target string) error {
case sourceMajor == "10" && targetMajor == "9":
sourceBinarySuffix = ".rhel9"
klog.Info("container is rhel10, target is rhel9")
case sourceMajor == "10" && targetMajor == "8":
sourceBinarySuffix = ".rhel8"
klog.Info("container is rhel10, target is rhel8")
case sourceMajor == "9" && targetMajor == "8":
sourceBinarySuffix = ".rhel8"
klog.Info("container is rhel9, target is rhel8")
default:
klog.Infof("using appropriate binary for source=rhel-%s target=rhel-%s", sourceMajor, targetMajor)
}
Expand Down Expand Up @@ -1931,7 +1927,6 @@ func (dn *Daemon) generateBootstrappingMCMismatchError(currentConfigOnDisk *onDi
}

func (dn *Daemon) createBootstrapMachineConfigDiffFile(oldConfig, newConfig *mcfgv1.MachineConfig) {

if _, err := os.Stat(bootstrapConfigDiffPath); err == nil {
// If the file already exists, we don't need to write it again
return
Expand Down Expand Up @@ -2004,7 +1999,6 @@ func removeIgnitionArtifacts() error {
// when scaling up older bootimages and targeting newer RHEL versions. In this case,
// we may want to pin NIC interface names that reference static IP addresses.
// More information:
// - RHEL 8→9 transition: https://issues.redhat.com/browse/OCPBUGS-10787
// - RHEL 9→10 transition: https://issues.redhat.com/browse/OCPBUGS-63593
func PersistNetworkInterfaces(osRoot string) error {
hostos, err := osrelease.GetHostRunningOSFromRoot(osRoot)
Expand All @@ -2024,7 +2018,7 @@ func PersistNetworkInterfaces(osRoot string) error {
// likely this NIC pinning should actually be driven automatically by
// host updates. If you change this, you'll need to change the conditions
// below too.
persisting := hostos.IsEL8() || hostos.IsEL9()
persisting := hostos.IsEL9()
cleanup := hostos.IsEL10()
if !(persisting || cleanup) {
return nil
Expand All @@ -2040,9 +2034,7 @@ func PersistNetworkInterfaces(osRoot string) error {

switch {
case persisting:
if hostos.IsEL8() {
klog.Info("Persisting NIC names for RHEL8 host system (RHEL8→9 transition)")
} else if hostos.IsEL9() {
if hostos.IsEL9() {
klog.Info("Persisting NIC names for RHEL9 host system (RHEL9→10 transition)")
}
case cleanup:
Expand Down Expand Up @@ -2107,71 +2099,6 @@ func PersistNetworkInterfaces(osRoot string) error {
return nil
}

// When we move from RHCOS 8 -> RHCOS 9, the SSH keys do not get written to the
// new location before the node reboots into RHCOS 9 because:
//
// 1. When the upgrade configs are written to the node, it is still running
// RHCOS 8, so the keys are not being written to the new location since the
// location is inferred from the currently booted OS.
// 2. The node reboots into RHCOS 9 to complete the upgrade.
// 3. The "are we on the latest config" functions detect that we are indeed on
// the latest config and so it does not attempt to perform an update.
//
// To work around that check on bootup if the we should use the new SSH key
// path and if the old SSH key path exists, we know that we need to migrate tot
// he new key path by calling dn.updateSSHKeyLocation().
func (dn *Daemon) isSSHKeyLocationUpdateRequired() (bool, error) {
if !dn.useNewSSHKeyPath() {
// Return early because we're not using the new SSH key path.
return false, nil
}

oldKeyExists, err := fileExists(constants.RHCOS8SSHKeyPath)
if err != nil {
return false, err
}

newKeyExists, err := fileExists(constants.RHCOS9SSHKeyPath)
if err != nil {
return false, err
}

// If the old key exists and the new key does not, we need to update.
return oldKeyExists && !newKeyExists, nil
}

// Decode the Ignition config and perform the SSH key update.
func (dn *Daemon) updateSSHKeyLocation(cfg *mcfgv1.MachineConfig) error {
klog.Infof("SSH key location update required. Moving SSH keys from %q to %q.", constants.RHCOS8SSHKeyPath, constants.RHCOS9SSHKeyPath)

ignConfig, err := ctrlcommon.ParseAndConvertConfig(cfg.Spec.Config.Raw)
if err != nil {
return fmt.Errorf("ignition failure when updating SSH key location: %w", err)
}

if err := dn.updateSSHKeys(ignConfig.Passwd.Users, ignConfig.Passwd.Users); err != nil {
return fmt.Errorf("could not write SSH keys to new location: %w", err)
}

return nil
}

// Determines if we need to update the SSH key location and performs the
// necessary update if so.
func (dn *Daemon) updateSSHKeyLocationIfNeeded(cfg *mcfgv1.MachineConfig) error {
sshKeyLocationUpdateRequired, err := dn.isSSHKeyLocationUpdateRequired()
if err != nil {
return fmt.Errorf("unable to determine if SSH key location update is required: %w", err)
}

if !sshKeyLocationUpdateRequired {
klog.Infof("SSH key location (%q) up-to-date!", constants.RHCOS9SSHKeyPath)
return nil
}

return dn.updateSSHKeyLocation(cfg)
}

// checkStateOnFirstRun is a core entrypoint for our state machine.
// It determines whether we're in our desired state, or if we're
// transitioning between states, and whether or not we need to update
Expand Down Expand Up @@ -2266,13 +2193,6 @@ func (dn *Daemon) checkStateOnFirstRun() error {

}

// When upgrading the OS, it is possible that the SSH key location will
// change. We should detect whether that is the case and update before we
// check for any config drift.
if err := dn.updateSSHKeyLocationIfNeeded(state.currentConfig); err != nil {
return err
}

if err := dn.validateOnDiskStateOrImage(state.currentConfig, state.currentImage); err != nil {
dn.nodeWriter.Eventf(corev1.EventTypeWarning, "OnDiskStateValidationFailed", err.Error())
// Start the config drift monitor even when there's pre-existing drift
Expand Down
14 changes: 0 additions & 14 deletions pkg/daemon/osrelease/osrelease.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,6 @@ func (os OperatingSystem) IsEL() bool {
return os.id == rhcos || os.id == scos || (os.id == rhel && os.variantID == coreos)
}

// IsEL8 is true if the OS is RHCOS 8 or SCOS 8
func (os OperatingSystem) IsEL8() bool {
return os.IsEL() && strings.HasPrefix(os.version, "8.") || os.version == "8"
}

// IsEL9 is true if the OS is RHCOS 9 or SCOS 9
func (os OperatingSystem) IsEL9() bool {
return os.IsEL() && strings.HasPrefix(os.version, "9.") || os.version == "9"
Expand Down Expand Up @@ -199,15 +194,6 @@ func getOSVersion(or osrelease.OSRelease) string {
return strings.ReplaceAll(or.VERSION, openshiftVersion, "")
}
}
// 4.1 and 4.2 bootimages doesn't ship RHEL_VERSION and OPENSHIFT_VERSION
// into /etc/os-release and hence we need to interpret ourself RHEL Version
// from VERSION_ID . See https://issues.redhat.com/browse/OCPBUGS-28974
if or.VERSION_ID == "4.1" {
return "8.1"
}
if or.VERSION_ID == "4.2" {
return "8.2"
}

// Fallback to the VERSION_ID field
return or.VERSION_ID
Expand Down
88 changes: 3 additions & 85 deletions pkg/daemon/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -2488,20 +2488,8 @@ func createSSHKeyDir(authKeyDir string) error {
return exec.Command("runuser", "-u", constants.CoreUserName, "--", "mkdir", "-m", "0700", "-p", dir).Run()
}

// Create the root SSH key directory (/home/core/.ssh) first (if there does not exist one).
if _, err := os.Stat(constants.CoreUserSSHPath); os.IsNotExist(err) {
if err := mkdir(filepath.Dir(constants.RHCOS8SSHKeyPath)); err != nil {
return err
}
}

// For RHCOS 8, creating /home/core/.ssh is all that is needed.
if authKeyDir == constants.RHCOS8SSHKeyPath {
return nil
}

// Create the next level of the SSH key directory (/home/core/.ssh/authorized_keys.d) for RHCOS 9 cases.
return mkdir(filepath.Dir(constants.RHCOS9SSHKeyPath))
// Create the SSH key directory (/home/core/.ssh/authorized_keys.d).
return mkdir(filepath.Dir(constants.RHCOSDefaultSSHKeyPath))
}

func (dn *Daemon) atomicallyWriteSSHKey(authKeyPath, keys string) error {
Expand Down Expand Up @@ -2630,13 +2618,6 @@ func (dn *Daemon) updateKubeConfigPermission() error {
return nil
}

// Determines if we should use the new SSH key path
// (/home/core/.ssh/authorized_keys.d/ignition) or the old SSH key path
// (/home/core/.ssh/authorized_keys)
func (dn *Daemon) useNewSSHKeyPath() bool {
return dn.os.IsEL9() || dn.os.IsEL10() || dn.os.IsFCOS() || dn.os.IsSCOS()
}

// Update a given PasswdUser's SSHKey
func (dn *Daemon) updateSSHKeys(newUsers, oldUsers []ign3types.PasswdUser) error {
klog.Info("updating SSH keys")
Expand Down Expand Up @@ -2664,28 +2645,9 @@ func (dn *Daemon) updateSSHKeys(newUsers, oldUsers []ign3types.PasswdUser) error
}
}

authKeyPath := constants.RHCOS8SSHKeyPath

if !dn.mock {
// In RHCOS 8.6 or lower, the keys were written to `/home/core/.ssh/authorized_keys`.
// RHCOS 9.0+, FCOS, and SCOS will however expect the keys at `/home/core/.ssh/authorized_keys.d/ignition`.
// Check if the authorized_keys file at the legacy path exists. If it does, remove it.
// It will be recreated at the new fragment path by the atomicallyWriteSSHKey function
// that is called right after.
if dn.useNewSSHKeyPath() {
authKeyPath = constants.RHCOS9SSHKeyPath

if err := cleanSSHKeyPaths(); err != nil {
return err
}

if err := removeNonIgnitionKeyPathFragments(); err != nil {
return err
}
}

// Note we write keys only for the core user and so this ignores the user list
return dn.atomicallyWriteSSHKey(authKeyPath, concatSSHKeys)
return dn.atomicallyWriteSSHKey(constants.RHCOSDefaultSSHKeyPath, concatSSHKeys)
}

return nil
Expand Down Expand Up @@ -2738,50 +2700,6 @@ func fileExists(path string) (bool, error) {
return false, fmt.Errorf("cannot stat file: %w", err)
}

// Removes the old SSH key path (/home/core/.ssh/authorized_keys), if found.
func cleanSSHKeyPaths() error {
oldKeyExists, err := fileExists(constants.RHCOS8SSHKeyPath)
if err != nil {
return err
}

if !oldKeyExists {
return nil
}

if err := os.RemoveAll(constants.RHCOS8SSHKeyPath); err != nil {
return fmt.Errorf("failed to remove path '%s': %w", constants.RHCOS8SSHKeyPath, err)
}

return nil
}

// Ensures authorized_keys.d/ignition is the only fragment that exists within the /home/core/.ssh dir.
func removeNonIgnitionKeyPathFragments() error {
// /home/core/.ssh/authorized_keys.d
authKeyFragmentDirPath := filepath.Dir(constants.RHCOS9SSHKeyPath)
// ignition
authKeyFragmentBasename := filepath.Base(constants.RHCOS9SSHKeyPath)

keyFragmentsDir, err := ctrlcommon.ReadDir(authKeyFragmentDirPath)
if err == nil {
for _, fragment := range keyFragmentsDir {
if fragment.Name() != authKeyFragmentBasename {
keyPath := filepath.Join(authKeyFragmentDirPath, fragment.Name())
err := os.RemoveAll(keyPath)
if err != nil {
return fmt.Errorf("failed to remove path '%s': %w", keyPath, err)
}
}
}
} else if !errors.Is(err, fs.ErrNotExist) {
// This shouldn't ever happen
return fmt.Errorf("unexpectedly failed to get info for path '%s': %w", constants.RHCOS9SSHKeyPath, err)
}

return nil
}

// InplaceUpdateViaNewContainer runs rpm-ostree ex deploy-via-self
// via a privileged container. This is needed on firstboot of old
// nodes as well as temporarily for 4.11 -> 4.12 upgrades.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ contents:
export IP4_DOMAINS IP6_DOMAINS
export -f resolv_prepender

# For RHEL8 with NetworkManager >= 1.36 and RHEL9 with NetworkManager >=1.42 we can use simplified logic
# For RHEL9 with NetworkManager >=1.42 we can use simplified logic
# of observing only a single "dns-change" event. Older version of NetworkManager require however that we
# react on a set of multiple events. Once dns-change event is detected we create a flag file to ignore
# subsequent up&co. events as undesired.
Expand Down
Loading