Nine Ways To Fail at Cloud Native

A presentation at FlowCon in November 2020 in by Holly Cummins

Slide 1

Slide 1

nine ways to fail at cloud native Holly Cummins IBM Garage @holly_cummins

Slide 2

Slide 2

I’m a consultant with the IBM Garage. These are my scary stories #IBMGarage @holly_cummins

Slide 3

Slide 3

fail the magic morphing meaning

Slide 4

Slide 4

what is cloud native? #IBMGarage @holly_cummins

Slide 5

Slide 5

#IBMGarage @holly_cummins

Slide 6

Slide 6

Credit to @bibryam #IBMGarage @holly_cummins

Slide 7

Slide 7

(a great article, btw) #IBMGarage @holly_cummins

Slide 8

Slide 8

(a great article, btw) #IBMGarage @holly_cummins

Slide 9

Slide 9

2019 #IBMGarage @holly_cummins

Slide 10

Slide 10

microservices containers dynamically orchestrated 2019 #IBMGarage @holly_cummins

Slide 11

Slide 11

e v i t a n d u o l c “the n o i t a d n u o f g n i co mput is wrong … .” e v i t a n d u o l c t abo u #IBMGarage Dr Holly @holly_cummins

Slide 12

Slide 12

e v i t a n d u o l c “the n o i t a d n u o f g n i co mput is wrong … .” e v i t a n d u o l c t abo u #IBMGarage Dr Holly @holly_cummins

Slide 13

Slide 13

Dr Holly #IBMGarage @holly_cummins

Slide 14

Slide 14

#IBMGarage @holly_cummins

Slide 15

Slide 15

2020 IBM Garage @holly_cummins

Slide 16

Slide 16

2020 IBM Garage @holly_cummins

Slide 17

Slide 17

IBM Garage @holly_cummins

Slide 18

Slide 18

IBM Garage @holly_cummins

Slide 19

Slide 19

IBM Garage @holly_cummins

Slide 20

Slide 20

IBM Garage @holly_cummins

Slide 21

Slide 21

IBM Garage @holly_cummins

Slide 22

Slide 22

IBM Garage @holly_cummins

Slide 23

Slide 23

born on the cloud IBM Garage @holly_cummins

Slide 24

Slide 24

born on the cloud IBM Garage @holly_cummins

Slide 25

Slide 25

microservices born on the cloud IBM Garage @holly_cummins

Slide 26

Slide 26

born on the cloud IBM Garage microservices @holly_cummins

Slide 27

Slide 27

kubernetes born on the cloud IBM Garage microservices @holly_cummins

Slide 28

Slide 28

born on the cloud IBM Garage microservices kubernetes @holly_cummins

Slide 29

Slide 29

devops born on the cloud IBM Garage microservices kubernetes @holly_cummins

Slide 30

Slide 30

born on the cloud IBM Garage microservices kubernetes devops @holly_cummins

Slide 31

Slide 31

born on the cloud IBM Garage microservices kubernetes devops modern and nice @holly_cummins

Slide 32

Slide 32

born on the cloud microservices kubernetes devops modern and nice IBM Garage @holly_cummins

Slide 33

Slide 33

synonym for ‘cloud’ born on the cloud microservices kubernetes devops modern and nice IBM Garage @holly_cummins

Slide 34

Slide 34

born on the cloud microservices kubernetes devops synonym for ‘cloud’ modern and nice IBM Garage @holly_cummins

Slide 35

Slide 35

?? IBM Garage ?? ?? ?? idempotent ?? ?? @holly_cummins

Slide 36

Slide 36

rerunnable IBM Garage @holly_cummins

Slide 37

Slide 37

born on the cloud kubernetes microservices IBM Garage 12-factor just ‘cloud’ modern and nice rerunnable @holly_cummins

Slide 38

Slide 38

© 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 39

Slide 39

© 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 40

Slide 40

cloud native is not © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 41

Slide 41

cloud native is not a synonym for ‘microservices’ © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 42

Slide 42

© 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 43

Slide 43

if ‘cloud native’ has to be a synonym for anything, it would be ‘idempotent’ © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 44

Slide 44

if ‘cloud native’ has to be a synonym for anything, it would be ‘idempotent’ which definitely needs a synonym © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 45

Slide 45

2019 #IBMGarage @holly_cummins

Slide 46

Slide 46

microservices stack containers 2019 #IBMGarage @holly_cummins

Slide 47

Slide 47

2020 IBM Garage @holly_cummins

Slide 48

Slide 48

immutable infrastructure microservices exemplify 2020 IBM Garage @holly_cummins

Slide 49

Slide 49

why? #IBMGarage @holly_cummins

Slide 50

Slide 50

© 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 51

Slide 51

build great products faster © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 52

Slide 52

2020 IBM Garage @holly_cummins

Slide 53

Slide 53

make high-impact changes frequently and predictably with minimal toil 2020 IBM Garage @holly_cummins

Slide 54

Slide 54

what problem are we trying to solve? © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 55

Slide 55

fail the muddy goal

Slide 56

Slide 56

what problem are we trying to solve? © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 57

Slide 57

“everyone else is doing it?” #IBMGarage @holly_cummins

Slide 58

Slide 58

wishful mimicry #IBMGarage @holly_cummins

Slide 59

Slide 59

why cloud? #IBMGarage @holly_cummins

Slide 60

Slide 60

cost © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 61

Slide 61

cost el a s t i c i t y © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 62

Slide 62

s cost pee d © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 63

Slide 63

exotic capabilities © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 64

Slide 64

why cloud native? © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 65

Slide 65

© 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 66

Slide 66

2011 12 factors © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 67

Slide 67

2011 12 factors how to write a cloud application so you don’t get electrocuted © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 68

Slide 68

2010 the dawn of cloud native © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 69

Slide 69

#IBMGarage @holly_cummins

Slide 70

Slide 70

born on the cloud kubernetes microservices IBM Garage 12-factor just ‘cloud’ modern and nice rerunnable @holly_cummins

Slide 71

Slide 71

are we all agreed on the goal? © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 72

Slide 72

why are there no microservices in this cloud native app Alice? #IBMGarage @holly_cummins

Slide 73

Slide 73

why is the cloud only saving us money, Alice? #IBMGarage @holly_cummins

Slide 74

Slide 74

fail microservices envy

Slide 75

Slide 75

microservices are not the goal #IBMGarage @holly_cummins

Slide 76

Slide 76

microservices are not the goal they are the means #IBMGarage @holly_cummins

Slide 77

Slide 77

“we’re going too slowly. we need to get rid of COBOL and make microservices!” #IBMGarage @holly_cummins

Slide 78

Slide 78

“we’re going too slowly. we need to get rid of COBOL and make microservices!” “… but our release board only meets twice a year.” #IBMGarage @holly_cummins

Slide 79

Slide 79

se a b od o g a e r a s r e n i a t con © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 80

Slide 80

it’s not a competition to see how many you can have © 2019 IBM Corporation se a b od o g a e r a s r e n i a t con #IBMGarage @holly_cummins

Slide 81

Slide 81

distributed monolith #IBMGarage @holly_cummins

Slide 82

Slide 82

distributed monolith but without compile-time checking … or guaranteed function execution #IBMGarage @holly_cummins

Slide 83

Slide 83

reasons not to do microservices small team not planning to release independently don’t want complexity of a service mesh - or worse yet, rolling your own domain model doesn’t split nicely #IBMGarage @holly_cummins

Slide 84

Slide 84

fail cloud-native spaghetti

Slide 85

Slide 85

“every time we change one microservice, another breaks” #IBMGarage @holly_cummins

Slide 86

Slide 86

cloud-native spaghetti is still spaghetti (Image: Cloudy with a Chance of Meatballs.) © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 87

Slide 87

distributed != decoupled © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 88

Slide 88

“each of our microservices has duplicated the same object model … with twenty classes and seventy fields” © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 89

Slide 89

Microservice © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 90

Slide 90

Microservice Domain © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 91

Slide 91

Microservice Domain © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 92

Slide 92

© 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 93

Slide 93

Courtesy NASA/ JPL-Caltech © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 94

Slide 94

© 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 95

Slide 95

© 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 96

Slide 96

Slide 97

Slide 97

metric units

Slide 98

Slide 98

metric units imperial units

Slide 99

Slide 99

metric units imperial units distributing did not help

Slide 100

Slide 100

microservices need consumer-driven contract tests © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 101

Slide 101

fail the not-actually-continuous continuous integration and continuous deployment

Slide 102

Slide 102

“we have a CI/CD” #IBMGarage @holly_cummins

Slide 103

Slide 103

CI/CD is something you do not a tool you buy #IBMGarage @holly_cummins

Slide 104

Slide 104

“i’ll merge my branch into our CI next week” #IBMGarage @holly_cummins

Slide 105

Slide 105

“CI/CD … CI/CD … CI/CD … we release every six months … CI/CD …. ” #IBMGarage @holly_cummins

Slide 106

Slide 106

continuous. I don’t think that word means what you think it means. #IBMGarage @holly_cummins

Slide 107

Slide 107

how often should you push to master? #IBMGarage @holly_cummins

Slide 108

Slide 108

how often should you push to master? integrate? #IBMGarage @holly_cummins

Slide 109

Slide 109

how often should you push to master? integrate? every character #IBMGarage @holly_cummins

Slide 110

Slide 110

how often should you push to master? integrate? every character actually continuous … but stupid #IBMGarage @holly_cummins

Slide 111

Slide 111

how often should you push to master? integrate? every character every commit (several times an hour) actually continuous … but stupid #IBMGarage @holly_cummins

Slide 112

Slide 112

how often should you push to master? integrate? every character every commit (several times an hour) every few commits (several times a day) actually continuous … but stupid #IBMGarage @holly_cummins

Slide 113

Slide 113

how often should you push to master? integrate? every character every commit (several times an hour) every few commits (several times a day) once a day actually continuous … but stupid #IBMGarage @holly_cummins

Slide 114

Slide 114

how often should you push to master? integrate? every character every commit (several times an hour) every few commits (several times a day) once a day once a week actually continuous … but stupid #IBMGarage @holly_cummins

Slide 115

Slide 115

how often should you push to master? integrate? every character every commit (several times an hour) every few commits (several times a day) once a day once a week once a month actually continuous … but stupid #IBMGarage @holly_cummins

Slide 116

Slide 116

how often should you push to master? integrate? every character every commit (several times an hour) every few commits (several times a day) once a day once a week once a month once every six months actually continuous … but stupid #IBMGarage @holly_cummins

Slide 117

Slide 117

how often should you push to master? integrate? every character every commit (several times an hour) every few commits (several times a day) once a day once a week once a month once every six months actually continuous … but stupid #IBMGarage trunk-based development @holly_cummins

Slide 118

Slide 118

how often should you push to master? integrate? every character every commit (several times an hour) every few commits (several times a day) once a day ok actually continuous … but stupid #IBMGarage once a week once a month once every six months trunk-based development @holly_cummins

Slide 119

Slide 119

how often should you push to master? integrate? every character every commit (several times an hour) every few commits (several times a day) once a day ok actually continuous … but stupid #IBMGarage bad once a week once a month once every six months trunk-based development @holly_cummins

Slide 120

Slide 120

how often should you push to master? integrate? every character every commit (several times an hour) every few commits (several times a day) once a day ok once a week once a month once every six months bad bad actually continuous … but stupid #IBMGarage trunk-based development @holly_cummins

Slide 121

Slide 121

how often should you push to master? integrate? every character every commit (several times an hour) every few commits (several times a day) once a day ok once a week once a month once every six months bad bad seriously? actually continuous … but stupid #IBMGarage trunk-based development @holly_cummins

Slide 122

Slide 122

how often should you push to master? integrate? every character every commit (several times an hour) every few commits (several times a day) once a day ok once a week once a month once every six months bad bad my favourite actually continuous … but stupid #IBMGarage seriously? trunk-based development @holly_cummins

Slide 123

Slide 123

how often should you release? every push (many times a day) every user story every epic once a sprint once a quarter #IBMGarage once every two years @holly_cummins

Slide 124

Slide 124

deploy? how often should you release? every push (many times a day) every user story every epic once a sprint once a quarter #IBMGarage once every two years @holly_cummins

Slide 125

Slide 125

deploy? how often should you release? every push (many times a day) every user story every epic once a sprint once a quarter once every two years (need a good handle on feature flags) #IBMGarage @holly_cummins

Slide 126

Slide 126

deploy? how often should you release? every push (many times a day) every user story every epic once a sprint once a quarter ok once every two years (need a good handle on feature flags) #IBMGarage @holly_cummins

Slide 127

Slide 127

deploy? how often should you release? every push (many times a day) every user story every epic once a sprint once a quarter ok (need a good handle on feature flags) #IBMGarage once every two years oldschool @holly_cummins

Slide 128

Slide 128

deploy? how often should you release? every push (many times a day) every user story every epic once a sprint once a quarter ok once every two years sigh (need a good handle on feature flags) #IBMGarage oldschool @holly_cummins

Slide 129

Slide 129

deploy? how often should you release? every push (many times a day) every user story every epic once a sprint once a quarter ok ok once every two years sigh (need a good handle on feature flags) #IBMGarage oldschool @holly_cummins

Slide 130

Slide 130

deploy? how often should you release? every push (many times a day) every user story every epic once a sprint once a quarter ok ok once every two years sigh hardcore (need a good handle on feature flags) #IBMGarage oldschool @holly_cummins

Slide 131

Slide 131

deploy? how often should you release? every push (many times a day) every user story every epic once a sprint once a quarter ok ok once every two years sigh hardcore (need a good handle on feature flags) #IBMGarage my favourite oldschool @holly_cummins

Slide 132

Slide 132

how often should you test in staging? #IBMGarage @holly_cummins

Slide 133

Slide 133

how often should you test in staging? deliver? #IBMGarage @holly_cummins

Slide 134

Slide 134

how often should you test in staging? deliver? every push my favourite #IBMGarage @holly_cummins

Slide 135

Slide 135

“we can’t actually release this.” #IBMGarage @holly_cummins

Slide 136

Slide 136

why? #IBMGarage @holly_cummins

Slide 137

Slide 137

what’s stopping more frequent deploys? #IBMGarage @holly_cummins

Slide 138

Slide 138

“we can’t release this microservice… we deploy all our microservices at the same time.” #IBMGarage @holly_cummins

Slide 139

Slide 139

“we can’t ship until every feature is complete” © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 140

Slide 140

if you’re not embarrassed by your first release it was too late - Reid Hoffman #IBMGarage @holly_cummins

Slide 141

Slide 141

speed © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 142

Slide 142

speed © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 143

Slide 143

what’s the point of architecture that can go faster, if you don’t go faster? © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 144

Slide 144

what’s the point of architecture that can go faster, if you don’t go faster? © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 145

Slide 145

how not to drive a car © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 146

Slide 146

feedback is good engineering © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 147

Slide 147

feedback is good business © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 148

Slide 148

deferred wiring #IBMGarage @holly_cummins

Slide 149

Slide 149

feature flags #IBMGarage @holly_cummins

Slide 150

Slide 150

A/B testing canary deploys #IBMGarage @holly_cummins

Slide 151

Slide 151

fail the ‘someday’ automation

Slide 152

Slide 152

“our tests aren’t automated” © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 153

Slide 153

“we don’t know if our code works” © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 154

Slide 154

“we don’t know if our code works” © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 155

Slide 155

systems will behave in unexpected ways © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 156

Slide 156

dependency updates can change behaviour © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 157

Slide 157

“we can’t ship until we have more confidence in the quality” © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 158

Slide 158

microservices need automated integration tests © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 159

Slide 159

not a good CI/CD indicator a good CI/CD indicator “we don’t know when the build is broken” © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 160

Slide 160

a good build radiator © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 161

Slide 161

© 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 162

Slide 162

“oh yes, that build has been broken for a few weeks…” © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 163

Slide 163

fail the lockeddown totally rigid inflexible un-cloudy cloud

Slide 164

Slide 164

#IBMGarage @holly_cummins

Slide 165

Slide 165

“we’ve configured our network! #IBMGarage @holly_cummins

Slide 166

Slide 166

“we’ve configured our network! you can either access the cloud servers … or access jira. #IBMGarage @holly_cummins

Slide 167

Slide 167

“we’ve configured our network! you can either access the cloud servers … or access jira. to access both you’d need two machines.” #IBMGarage @holly_cummins

Slide 168

Slide 168

“it takes us a week to start coding.” #IBMGarage @holly_cummins

Slide 169

Slide 169

“it takes us a week to start coding.” “two days to get a repo … two days to get a pipeline …” #IBMGarage @holly_cummins

Slide 170

Slide 170

“we’ve scheduled the architecture board review for a month after the project is ready to ship” © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 171

Slide 171

“this provisioning software is broken” #IBMGarage @holly_cummins

Slide 172

Slide 172

10 minute provision-time what we sold “this provisioning software is broken” #IBMGarage @holly_cummins

Slide 173

Slide 173

what the client thought they’d got 10 minute provision-time what we sold 3 month provisiontime “this provisioning software is broken” #IBMGarage @holly_cummins

Slide 174

Slide 174

what the client thought they’d got 10 minute provision-time the reason 3 month provisiontime 84-step pre-approval process what we sold “this provisioning software is broken” #IBMGarage @holly_cummins

Slide 175

Slide 175

#IBMGarage @holly_cummins

Slide 176

Slide 176

#IBMGarage @holly_cummins

Slide 177

Slide 177

old-style governance isn’t going to work #IBMGarage @holly_cummins

Slide 178

Slide 178

Provider A #IBMGarage @holly_cummins

Slide 179

Slide 179

Provider A Provider B “we’re going to change cloud provider to fix our procurement process!” #IBMGarage @holly_cummins

Slide 180

Slide 180

Provider A Provider B “we’re going to change cloud provider to fix our procurement process!” #IBMGarage @holly_cummins

Slide 181

Slide 181

if the developers are the only ones changing, cloud native is not going to work #IBMGarage @holly_cummins

Slide 182

Slide 182

there is a cost: developers leave #IBMGarage @holly_cummins

Slide 183

Slide 183

fail the mystery money pit

Slide 184

Slide 184

the cloud makes it so easy to provision hardware. IBM Garage @holly_cummins

Slide 185

Slide 185

that doesn’t mean the hardware is free. IBM Garage @holly_cummins

Slide 186

Slide 186

or useful. IBM Garage @holly_cummins

Slide 187

Slide 187

Hey boss, I created a Kubernetes cluster. IBM Garage @holly_cummins

Slide 188

Slide 188

Hey boss, I created a Kubernetes cluster. I forgot it for 2 months. IBM Garage @holly_cummins

Slide 189

Slide 189

Hey boss, I created a Kubernetes cluster. I forgot it for 2 months. … and it’s £1000 a month. IBM Garage @holly_cummins

Slide 190

Slide 190

Slide 191

Slide 191

Slide 192

Slide 192

2017 survey 25% of 16,000 servers doing no useful work #IBMGarage @holly_cummins

Slide 193

Slide 193

2017 survey 25% of 16,000 servers doing no useful work “perhaps someone forgot to turn them off” #IBMGarage @holly_cummins

Slide 194

Slide 194

ouch IBM Garage @holly_cummins

Slide 195

Slide 195

There is surely nothing quite so useless as doing with great efficiency what should not be done at all. — Peter Drucker IBM Garage @holly_cummins

Slide 196

Slide 196

“we have no idea how much we’re spending on cloud.” IBM Garage @holly_cummins

Slide 197

Slide 197

cloud to manage your clouds IBM Garage @holly_cummins

Slide 198

Slide 198

IBM Garage @holly_cummins

Slide 199

Slide 199

FinOps IBM Garage @holly_cummins

Slide 200

Slide 200

fail microservices ops mayhem

Slide 201

Slide 201

SRE #IBMGarage @holly_cummins

Slide 202

Slide 202

site reliability engineering #IBMGarage @holly_cummins

Slide 203

Slide 203

@holly_cummins

Slide 204

Slide 204

make releases deeply boring @holly_cummins

Slide 205

Slide 205

how to brick a spaceprobe Phobos 1 © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 206

Slide 206

“we couldn’t get the automated checks to work, so we bypassed them” © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 207

Slide 207

recoverability © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 208

Slide 208

unrecoverable © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 209

Slide 209

back in ms no data loss manual intervention bricked fast, but data lost handoffs © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 210

Slide 210

handoffs bad automation good © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 211

Slide 211

ways to succeed at cloud native © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 212

Slide 212

be clear on what you’re trying to achieve © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 213

Slide 213

optimise for feedback © 2019 IBM Corporation #IBMGarage @holly_cummins

Slide 214

Slide 214

if you automate something, change the processes around that assume that the previously manual process is expensive or error prone. #IBMGarage @holly_cummins

Slide 215

Slide 215

#IBMGarage @holly_cummins

Slide 216

Slide 216

#IBMGarage @holly_cummins

Slide 217

Slide 217

® @holly_cummins 134