1 // Copyright 2021 Chaos Mesh Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 16 package v1alpha1 17 18 import ( 19 "fmt" 20 21 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 ) 23 24 // Stress chaos is a chaos to generate plenty of stresses over a collection of pods. 25 26 // +kubebuilder:object:root=true 27 // +kubebuilder:printcolumn:name="duration",type=string,JSONPath=`.spec.duration` 28 // +chaos-mesh:experiment 29 30 // StressChaos is the Schema for the stresschaos API 31 type StressChaos struct { 32 metav1.TypeMeta `json:",inline"` 33 metav1.ObjectMeta `json:"metadata,omitempty"` 34 35 // Spec defines the behavior of a time chaos experiment 36 Spec StressChaosSpec `json:"spec"` 37 38 // +optional 39 // Most recently observed status of the time chaos experiment 40 Status StressChaosStatus `json:"status,omitempty"` 41 } 42 43 var _ InnerObjectWithCustomStatus = (*StressChaos)(nil) 44 var _ InnerObjectWithSelector = (*StressChaos)(nil) 45 var _ InnerObject = (*StressChaos)(nil) 46 47 // StressChaosSpec defines the desired state of StressChaos 48 type StressChaosSpec struct { 49 ContainerSelector `json:",inline"` 50 51 // Stressors defines plenty of stressors supported to stress system components out. 52 // You can use one or more of them to make up various kinds of stresses. At least 53 // one of the stressors should be specified. 54 // +optional 55 Stressors *Stressors `json:"stressors,omitempty"` 56 57 // StressngStressors defines plenty of stressors just like `Stressors` except that it's an experimental 58 // feature and more powerful. You can define stressors in `stress-ng` (see also `man stress-ng`) dialect, 59 // however not all of the supported stressors are well tested. It maybe retired in later releases. You 60 // should always use `Stressors` to define the stressors and use this only when you want more stressors 61 // unsupported by `Stressors`. When both `StressngStressors` and `Stressors` are defined, `StressngStressors` 62 // wins. 63 // +optional 64 StressngStressors string `json:"stressngStressors,omitempty"` 65 66 // Duration represents the duration of the chaos action 67 // +optional 68 Duration *string `json:"duration,omitempty" webhook:"Duration"` 69 70 // RemoteCluster represents the remote cluster where the chaos will be deployed 71 // +optional 72 RemoteCluster string `json:"remoteCluster,omitempty"` 73 } 74 75 // StressChaosStatus defines the observed state of StressChaos 76 type StressChaosStatus struct { 77 ChaosStatus `json:",inline"` 78 // Instances always specifies stressing instances 79 // +optional 80 Instances map[string]StressInstance `json:"instances,omitempty"` 81 } 82 83 // StressInstance is an instance generates stresses 84 type StressInstance struct { 85 // UID is the stress-ng identifier 86 // +optional 87 UID string `json:"uid,omitempty"` 88 // MemoryUID is the memStress identifier 89 // +optional 90 MemoryUID string `json:"memoryUid,omitempty"` 91 // StartTime specifies when the stress-ng starts 92 // +optional 93 StartTime *metav1.Time `json:"startTime,omitempty"` 94 // MemoryStartTime specifies when the memStress starts 95 // +optional 96 MemoryStartTime *metav1.Time `json:"memoryStartTime,omitempty"` 97 } 98 99 // Stressors defines plenty of stressors supported to stress system components out. 100 // You can use one or more of them to make up various kinds of stresses 101 type Stressors struct { 102 // MemoryStressor stresses virtual memory out 103 // +optional 104 MemoryStressor *MemoryStressor `json:"memory,omitempty"` 105 // CPUStressor stresses CPU out 106 // +optional 107 CPUStressor *CPUStressor `json:"cpu,omitempty"` 108 } 109 110 // Normalize the stressors to comply with stress-ng 111 func (in *Stressors) Normalize() (cpuStressors string, memoryStressors string, err error) { 112 cpuStressors = "" 113 memoryStressors = "" 114 err = nil 115 116 if in.MemoryStressor != nil && in.MemoryStressor.Workers != 0 { 117 memoryStressors += fmt.Sprintf(" --workers %d", in.MemoryStressor.Workers) 118 119 if len(in.MemoryStressor.Size) != 0 { 120 memoryStressors += fmt.Sprintf(" --size %s", in.MemoryStressor.Size) 121 } 122 123 if in.MemoryStressor.Options != nil { 124 for _, v := range in.MemoryStressor.Options { 125 memoryStressors += fmt.Sprintf(" %v ", v) 126 } 127 } 128 } 129 if in.CPUStressor != nil && in.CPUStressor.Workers != 0 { 130 // Without these two args, we may not reach the resource limit of pod, 131 // especially when we set cpu workers > 1 132 // More details see: https://github.com/chaos-mesh/chaos-mesh/issues/3100 133 cpuStressors += " --cpu-load-slice 10 --cpu-method sqrt" 134 cpuStressors += fmt.Sprintf(" --cpu %d", in.CPUStressor.Workers) 135 136 if in.CPUStressor.Load != nil { 137 cpuStressors += fmt.Sprintf(" --cpu-load %d", 138 *in.CPUStressor.Load) 139 } 140 141 if in.CPUStressor.Options != nil { 142 for _, v := range in.CPUStressor.Options { 143 cpuStressors += fmt.Sprintf(" %v ", v) 144 } 145 } 146 } 147 148 return 149 } 150 151 // Stressor defines common configurations of a stressor 152 type Stressor struct { 153 // Workers specifies N workers to apply the stressor. 154 // Maximum 8192 workers can run by stress-ng 155 // +kubebuilder:validation:Maximum=8192 156 Workers int `json:"workers"` 157 } 158 159 // MemoryStressor defines how to stress memory out 160 type MemoryStressor struct { 161 Stressor `json:",inline"` 162 163 // Size specifies N bytes consumed per vm worker, default is the total available memory. 164 // One can specify the size as % of total available memory or in units of B, KB/KiB, 165 // MB/MiB, GB/GiB, TB/TiB. 166 // +optional 167 Size string `json:"size,omitempty" webhook:"Bytes"` 168 169 // OOMScoreAdj sets the oom_score_adj of the stress process. See `man 5 proc` to know more 170 // about this option. 171 // +kubebuilder:validation:Minimum=-1000 172 // +kubebuilder:validation:Maximum=1000 173 // +kubebuilder:default=0 174 // +optional 175 OOMScoreAdj int `json:"oomScoreAdj,omitempty"` 176 177 // extend stress-ng options 178 // +optional 179 Options []string `json:"options,omitempty"` 180 } 181 182 // CPUStressor defines how to stress CPU out 183 type CPUStressor struct { 184 Stressor `json:",inline"` 185 // Load specifies P percent loading per CPU worker. 0 is effectively a sleep (no load) and 100 186 // is full loading. 187 // +kubebuilder:validation:Minimum=0 188 // +kubebuilder:validation:Maximum=100 189 // +optional 190 Load *int `json:"load,omitempty"` 191 192 // extend stress-ng options 193 // +optional 194 Options []string `json:"options,omitempty"` 195 } 196 197 func (obj *StressChaos) GetSelectorSpecs() map[string]interface{} { 198 return map[string]interface{}{ 199 ".": &obj.Spec.ContainerSelector, 200 } 201 } 202 203 func (obj *StressChaos) GetCustomStatus() interface{} { 204 return &obj.Status.Instances 205 } 206