diff --git a/pkg/webhooks/machine_webhook.go b/pkg/webhooks/machine_webhook.go
index ae7eaf0f9df6dc9cf3eb5c47ee8dee2d689ad0bb..f60bf86736e53e4032cb298a859b64149652fca2 100644
--- a/pkg/webhooks/machine_webhook.go
+++ b/pkg/webhooks/machine_webhook.go
@@ -3,6 +3,7 @@ package webhooks
 import (
 	"context"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"regexp"
 	goruntime "runtime"
@@ -729,6 +730,12 @@ func validateAWS(m *machinev1beta1.Machine, config *admissionConfig) (bool, []st
 		warnings = append(warnings, "providerSpec.iamInstanceProfile: no IAM instance profile provided: nodes may be unable to join the cluster")
 	}
 
+	if providerSpec.CapacityReservationID != "" {
+		if err := validateAwsCapacityReservationId(providerSpec.CapacityReservationID); err != nil {
+			errs = append(errs, field.Invalid(field.NewPath("providerSpec", "capacityReservationId"), providerSpec.CapacityReservationID, err.Error()))
+		}
+	}
+
 	// TODO(alberto): Validate providerSpec.BlockDevices.
 	// https://github.com/openshift/cluster-api-provider-aws/pull/299#discussion_r433920532
 
@@ -2269,3 +2276,16 @@ func appendNextAzureResourceIDValidation(parts []string, id string) error {
 	}
 	return fmt.Errorf("invalid resource ID: %s", id)
 }
+
+// validateAWScapacityReservationId validate capacity reservation group ID.
+func validateAwsCapacityReservationId(capacityReservationId string) error {
+	if len(capacityReservationId) == 0 {
+		return errors.New("invalid capacityReservationId: capacityReservationId cannot be empty")
+	}
+	// It must starts with cr-xxxxxxxxxxxxxxxxx with length of 17 characters excluding cr-
+	re := regexp.MustCompile(`^cr-[0-9a-f]{17}$`)
+	if !re.MatchString(capacityReservationId) {
+		return fmt.Errorf("invalid value for capacityReservationId: %q, it must start with 'cr-' and be exactly 20 characters long with 17 hexadecimal characters", capacityReservationId)
+	}
+	return nil
+}
diff --git a/pkg/webhooks/machine_webhook_test.go b/pkg/webhooks/machine_webhook_test.go
index 72d17602c06a695db17b73b7c684b6a0a8cba7ff..b946e9f2b12f7ccad831db2e7505e041675254b1 100644
--- a/pkg/webhooks/machine_webhook_test.go
+++ b/pkg/webhooks/machine_webhook_test.go
@@ -152,6 +152,48 @@ func TestMachineCreation(t *testing.T) {
 			},
 			expectedError: "",
 		},
+		{
+			name:         "with AWS and CapacityReservationID is empty",
+			platformType: osconfigv1.AWSPlatformType,
+			clusterID:    "aws-cluster",
+			providerSpecValue: &kruntime.RawExtension{
+				Object: &machinev1beta1.AWSMachineProviderConfig{
+					AMI: machinev1beta1.AWSResourceReference{
+						ID: ptr.To[string]("ami"),
+					},
+					CapacityReservationID: "",
+				},
+			},
+			expectedError: "",
+		},
+		{
+			name:         "with AWS and CapacityReservationID is valid",
+			platformType: osconfigv1.AWSPlatformType,
+			clusterID:    "aws-cluster",
+			providerSpecValue: &kruntime.RawExtension{
+				Object: &machinev1beta1.AWSMachineProviderConfig{
+					AMI: machinev1beta1.AWSResourceReference{
+						ID: ptr.To[string]("ami"),
+					},
+					CapacityReservationID: "cr-12345678901234567",
+				},
+			},
+			expectedError: "",
+		},
+		{
+			name:         "with AWS and CapacityReservationID is not valid",
+			platformType: osconfigv1.AWSPlatformType,
+			clusterID:    "aws-cluster",
+			providerSpecValue: &kruntime.RawExtension{
+				Object: &machinev1beta1.AWSMachineProviderConfig{
+					AMI: machinev1beta1.AWSResourceReference{
+						ID: ptr.To[string]("ami"),
+					},
+					CapacityReservationID: "cr-123",
+				},
+			},
+			expectedError: "admission webhook \"validation.machine.machine.openshift.io\" denied the request: providerSpec.capacityReservationId: Invalid value: \"cr-123\": invalid value for capacityReservationId: \"cr-123\", it must start with 'cr-' and be exactly 20 characters long with 17 hexadecimal characters",
+		},
 		{
 			name:              "with Azure and a nil provider spec value",
 			platformType:      osconfigv1.AzurePlatformType,