or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-resources.mdhelm-integration.mdindex.mdkustomize-integration.mdnetworking-resources.mdprovider-configuration.mdrbac-resources.mdstorage-resources.mdworkload-resources.mdyaml-deployment.md

yaml-deployment.mddocs/

0

# YAML Deployment

1

2

The YAML deployment capabilities enable you to deploy Kubernetes resources from existing YAML manifests while gaining full Pulumi integration, resource management, and transformation capabilities.

3

4

## Package Import

5

6

```typescript { .api }

7

import { yaml } from "@pulumi/kubernetes";

8

import * as k8s from "@pulumi/kubernetes";

9

10

// Direct YAML imports

11

import { ConfigFile, ConfigGroup } from "@pulumi/kubernetes/yaml/v2";

12

```

13

14

## CollectionComponentResource Base Class

15

16

Base class that provides strongly-typed resource lookup for YAML-based collections.

17

18

```typescript { .api }

19

abstract class CollectionComponentResource extends pulumi.ComponentResource {

20

// Strongly-typed resource lookup method

21

public getResource<T extends pulumi.CustomResource>(

22

group: string,

23

version: string,

24

kind: string,

25

name: string,

26

namespace?: string

27

): T

28

29

// Get resource by GroupVersionKind string

30

public getResource(groupVersionKind: string, name: string, namespace?: string): pulumi.CustomResource

31

32

// Get specific property from resource

33

public getResourceProperty(groupVersionKind: string, name: string, property: string, namespace?: string): pulumi.Output<any>

34

}

35

```

36

37

## ConfigFile (yaml/v2)

38

39

ConfigFile deploys resources from a single YAML manifest file with full Pulumi lifecycle management.

40

41

```typescript { .api }

42

class ConfigFile extends CollectionComponentResource {

43

constructor(name: string, args: ConfigFileArgs, opts?: pulumi.ComponentResourceOptions)

44

45

// Resource access methods inherited from CollectionComponentResource

46

}

47

48

interface ConfigFileArgs {

49

// File specification

50

file: pulumi.Input<string>; // Path to YAML file (required)

51

52

// Resource configuration

53

resourcePrefix?: pulumi.Input<string>; // Prefix for resource names

54

55

// Deployment options

56

skipAwait?: pulumi.Input<boolean>; // Skip waiting for resource readiness

57

}

58

```

59

60

### ConfigFile Usage Examples

61

62

```typescript { .api }

63

// Deploy from single YAML file

64

const nginxManifest = new k8s.yaml.v2.ConfigFile("nginx-manifest", {

65

file: "./manifests/nginx-deployment.yaml",

66

});

67

68

// Deploy from multiple YAML files

69

const appManifests = new k8s.yaml.v2.ConfigFile("app-manifests", {

70

files: [

71

"./manifests/deployment.yaml",

72

"./manifests/service.yaml",

73

"./manifests/ingress.yaml",

74

],

75

});

76

77

// Deploy with namespace override

78

const devApp = new k8s.yaml.v2.ConfigFile("dev-app", {

79

file: "./manifests/app.yaml",

80

namespace: "development", // Override namespace in YAML

81

});

82

83

// Deploy with resource name prefix

84

const prefixedApp = new k8s.yaml.v2.ConfigFile("prefixed-app", {

85

file: "./manifests/app.yaml",

86

resourcePrefix: "staging-", // Prefix all resource names

87

});

88

89

// Deploy with await disabled for faster deployment

90

const fastApp = new k8s.yaml.v2.ConfigFile("fast-app", {

91

file: "./manifests/app.yaml",

92

skipAwait: true, // Don't wait for resources to become ready

93

});

94

```

95

96

### Accessing Resources from ConfigFile

97

98

```typescript { .api }

99

// Get specific resources from the deployed manifest

100

const deployment = appManifests.getResource("apps/v1", "Deployment", "nginx-deployment");

101

const service = appManifests.getResource("v1", "Service", "nginx-service");

102

103

// Using generic method with type assertion

104

const ingress = appManifests.getResource("networking.k8s.io/v1/Ingress", "nginx-ingress");

105

106

// Get resource properties

107

const serviceIP = appManifests.getResourceProperty("v1/Service", "nginx-service", "status");

108

const deploymentReplicas = appManifests.getResourceProperty("apps/v1/Deployment", "nginx-deployment", "spec.replicas");

109

110

// Export important values

111

export const loadBalancerIP = service.status.loadBalancer.ingress[0].ip;

112

export const ingressHostname = ingress.status.loadBalancer.ingress[0].hostname;

113

```

114

115

## ConfigGroup (yaml/v2)

116

117

ConfigGroup deploys resources from multiple YAML files or directories with pattern matching capabilities.

118

119

```typescript { .api }

120

class ConfigGroup extends CollectionComponentResource {

121

constructor(name: string, args: ConfigGroupArgs, opts?: pulumi.ComponentResourceOptions)

122

123

// Resource access methods inherited from CollectionComponentResource

124

}

125

126

interface ConfigGroupArgs {

127

// File specification

128

files?: pulumi.Input<pulumi.Input<string>[]>; // Array of file paths (supports glob patterns)

129

130

// Content specification

131

yaml?: pulumi.Input<string>; // YAML content string

132

objs?: pulumi.Input<any[]>; // Array of Kubernetes objects

133

134

// Resource configuration

135

resourcePrefix?: pulumi.Input<string>; // Prefix for resource names

136

137

// Deployment options

138

skipAwait?: pulumi.Input<boolean>; // Skip waiting for resource readiness

139

}

140

```

141

142

### ConfigGroup Usage Examples

143

144

```typescript { .api }

145

// Deploy all YAML files from directory using glob pattern

146

const allManifests = new k8s.yaml.v2.ConfigGroup("all-manifests", {

147

files: ["./manifests/**/*.yaml"],

148

namespace: "applications",

149

});

150

151

// Deploy specific files

152

const coreServices = new k8s.yaml.v2.ConfigGroup("core-services", {

153

files: [

154

"./manifests/database/*.yaml",

155

"./manifests/cache/redis.yaml",

156

"./manifests/monitoring/prometheus.yaml",

157

],

158

namespace: "infrastructure",

159

});

160

161

// Deploy from YAML content strings

162

const inlineManifests = new k8s.yaml.v2.ConfigGroup("inline-manifests", {

163

yaml: [

164

`

165

apiVersion: v1

166

kind: ConfigMap

167

metadata:

168

name: app-config

169

data:

170

database.url: "postgresql://db:5432/app"

171

redis.host: "redis:6379"

172

`,

173

`

174

apiVersion: apps/v1

175

kind: Deployment

176

metadata:

177

name: app

178

spec:

179

replicas: 3

180

selector:

181

matchLabels:

182

app: myapp

183

template:

184

metadata:

185

labels:

186

app: myapp

187

spec:

188

containers:

189

- name: app

190

image: myapp:v1.0

191

ports:

192

- containerPort: 8080

193

`,

194

],

195

});

196

197

// Deploy from Kubernetes objects

198

const objectManifests = new k8s.yaml.v2.ConfigGroup("object-manifests", {

199

objs: [

200

{

201

apiVersion: "v1",

202

kind: "Namespace",

203

metadata: {

204

name: "my-application",

205

labels: {

206

environment: "production",

207

},

208

},

209

},

210

{

211

apiVersion: "v1",

212

kind: "Secret",

213

metadata: {

214

name: "app-secrets",

215

namespace: "my-application",

216

},

217

type: "Opaque",

218

stringData: {

219

username: "admin",

220

password: "secret-password",

221

},

222

},

223

],

224

});

225

226

// Environment-specific deployment

227

const envManifests = new k8s.yaml.v2.ConfigGroup("env-manifests", {

228

files: [

229

"./manifests/base/*.yaml",

230

`./manifests/overlays/${pulumi.getStack()}/*.yaml`,

231

],

232

namespace: `app-${pulumi.getStack()}`,

233

resourcePrefix: `${pulumi.getStack()}-`,

234

});

235

```

236

237

### Advanced ConfigGroup Patterns

238

239

```typescript { .api }

240

// Multi-environment deployment with transformations

241

const createEnvironmentDeployment = (environment: string) => {

242

return new k8s.yaml.v2.ConfigGroup(`app-${environment}`, {

243

files: [

244

"./manifests/base/*.yaml",

245

`./manifests/overlays/${environment}/*.yaml`,

246

],

247

namespace: `app-${environment}`,

248

transformations: [

249

// Environment-specific labels

250

(args: any) => {

251

if (args.type.startsWith("kubernetes:")) {

252

args.props = pulumi.output(args.props).apply((props: any) => ({

253

...props,

254

metadata: {

255

...props.metadata,

256

labels: {

257

...props.metadata?.labels,

258

environment: environment,

259

"deployment.kubernetes.io/revision": "1",

260

},

261

},

262

}));

263

}

264

return { props: args.props, opts: args.opts };

265

},

266

// Environment-specific resource scaling

267

(args: any) => {

268

if (args.type === "kubernetes:apps/v1:Deployment") {

269

const replicas = environment === "production" ? 3 : 1;

270

args.props = pulumi.output(args.props).apply((props: any) => ({

271

...props,

272

spec: {

273

...props.spec,

274

replicas: replicas,

275

},

276

}));

277

}

278

return { props: args.props, opts: args.opts };

279

},

280

],

281

});

282

};

283

284

// Deploy to multiple environments

285

const devDeployment = createEnvironmentDeployment("development");

286

const stagingDeployment = createEnvironmentDeployment("staging");

287

const prodDeployment = createEnvironmentDeployment("production");

288

```

289

290

## Complete Application Examples

291

292

### Microservices Application

293

294

```typescript { .api }

295

// Deploy database layer

296

const databaseLayer = new k8s.yaml.v2.ConfigGroup("database", {

297

files: ["./manifests/database/*.yaml"],

298

namespace: "data",

299

transformations: [

300

(args: any) => {

301

// Add persistence annotations

302

if (args.type === "kubernetes:apps/v1:StatefulSet") {

303

args.props = pulumi.output(args.props).apply((props: any) => ({

304

...props,

305

metadata: {

306

...props.metadata,

307

annotations: {

308

...props.metadata?.annotations,

309

"backup.kubernetes.io/enabled": "true",

310

},

311

},

312

}));

313

}

314

return { props: args.props, opts: args.opts };

315

},

316

],

317

});

318

319

// Deploy application services

320

const appServices = new k8s.yaml.v2.ConfigGroup("app-services", {

321

files: [

322

"./manifests/services/user-service/*.yaml",

323

"./manifests/services/order-service/*.yaml",

324

"./manifests/services/payment-service/*.yaml",

325

],

326

namespace: "applications",

327

transformations: [

328

(args: any) => {

329

// Add service mesh annotations

330

if (args.type === "kubernetes:apps/v1:Deployment") {

331

args.props = pulumi.output(args.props).apply((props: any) => ({

332

...props,

333

spec: {

334

...props.spec,

335

template: {

336

...props.spec.template,

337

metadata: {

338

...props.spec.template.metadata,

339

annotations: {

340

...props.spec.template.metadata?.annotations,

341

"sidecar.istio.io/inject": "true",

342

"prometheus.io/scrape": "true",

343

"prometheus.io/port": "9090",

344

},

345

},

346

},

347

},

348

}));

349

}

350

return { props: args.props, opts: args.opts };

351

},

352

],

353

}, {

354

dependsOn: [databaseLayer],

355

});

356

357

// Deploy gateway and ingress

358

const gateway = new k8s.yaml.v2.ConfigFile("api-gateway", {

359

files: [

360

"./manifests/gateway/gateway.yaml",

361

"./manifests/gateway/virtualservice.yaml",

362

],

363

namespace: "istio-system",

364

}, {

365

dependsOn: [appServices],

366

});

367

368

// Access deployed resources

369

const userService = appServices.getResource("v1", "Service", "user-service", "applications");

370

const orderDeployment = appServices.getResource("apps/v1", "Deployment", "order-service", "applications");

371

372

// Export service endpoints

373

export const userServiceEndpoint = userService.spec.clusterIP;

374

export const gatewayURL = gateway.getResourceProperty("networking.istio.io/v1beta1/Gateway", "api-gateway", "status");

375

```

376

377

### CI/CD Pipeline Integration

378

379

```typescript { .api }

380

// Deploy from CI/CD generated manifests

381

const cicdDeployment = new k8s.yaml.v2.ConfigGroup("cicd-deployment", {

382

files: [`./build/manifests/${pulumi.getStack()}/*.yaml`],

383

namespace: `app-${pulumi.getStack()}`,

384

transformations: [

385

// Add CI/CD metadata

386

(args: any) => {

387

if (args.type.startsWith("kubernetes:")) {

388

args.props = pulumi.output(args.props).apply((props: any) => ({

389

...props,

390

metadata: {

391

...props.metadata,

392

annotations: {

393

...props.metadata?.annotations,

394

"deployment.kubernetes.io/revision": process.env.BUILD_NUMBER || "unknown",

395

"git.commit": process.env.GIT_COMMIT || "unknown",

396

"ci.pipeline": process.env.CI_PIPELINE_ID || "unknown",

397

},

398

labels: {

399

...props.metadata?.labels,

400

"app.kubernetes.io/version": process.env.APP_VERSION || "latest",

401

},

402

},

403

}));

404

}

405

return { props: args.props, opts: args.opts };

406

},

407

// Environment-specific resource adjustments

408

(args: any) => {

409

const stack = pulumi.getStack();

410

if (args.type === "kubernetes:apps/v1:Deployment") {

411

args.props = pulumi.output(args.props).apply((props: any) => ({

412

...props,

413

spec: {

414

...props.spec,

415

replicas: stack === "production" ? 5 : 2,

416

template: {

417

...props.spec.template,

418

spec: {

419

...props.spec.template.spec,

420

containers: props.spec.template.spec.containers?.map((container: any) => ({

421

...container,

422

resources: {

423

requests: {

424

cpu: stack === "production" ? "200m" : "100m",

425

memory: stack === "production" ? "256Mi" : "128Mi",

426

},

427

limits: {

428

cpu: stack === "production" ? "1" : "500m",

429

memory: stack === "production" ? "1Gi" : "512Mi",

430

},

431

},

432

})),

433

},

434

},

435

},

436

}));

437

}

438

return { props: args.props, opts: args.opts };

439

},

440

],

441

});

442

```

443

444

### Multi-Cluster Deployment

445

446

```typescript { .api }

447

// Deploy to multiple clusters with different configurations

448

const deployToCluster = (clusterName: string, region: string) => {

449

return new k8s.yaml.v2.ConfigGroup(`app-${clusterName}`, {

450

files: ["./manifests/app/*.yaml"],

451

namespace: "applications",

452

transformations: [

453

// Cluster-specific labels and annotations

454

(args: any) => {

455

if (args.type.startsWith("kubernetes:")) {

456

args.props = pulumi.output(args.props).apply((props: any) => ({

457

...props,

458

metadata: {

459

...props.metadata,

460

labels: {

461

...props.metadata?.labels,

462

"cluster": clusterName,

463

"region": region,

464

},

465

annotations: {

466

...props.metadata?.annotations,

467

"deployment.cluster": clusterName,

468

},

469

},

470

}));

471

}

472

return { props: args.props, opts: args.opts };

473

},

474

// Regional configuration

475

(args: any) => {

476

if (args.type === "v1/Service" && args.props.spec?.type === "LoadBalancer") {

477

args.props = pulumi.output(args.props).apply((props: any) => ({

478

...props,

479

metadata: {

480

...props.metadata,

481

annotations: {

482

...props.metadata?.annotations,

483

"service.beta.kubernetes.io/aws-load-balancer-type":

484

region.startsWith("us-") ? "nlb" : "classic",

485

},

486

},

487

}));

488

}

489

return { props: args.props, opts: args.opts };

490

},

491

],

492

});

493

};

494

495

// Deploy to multiple clusters

496

const usEast1Deployment = deployToCluster("us-east-1", "us-east-1");

497

const usWest2Deployment = deployToCluster("us-west-2", "us-west-2");

498

const euWest1Deployment = deployToCluster("eu-west-1", "eu-west-1");

499

```

500

501

## Best Practices

502

503

### YAML Management Best Practices

504

505

1. **File Organization**: Organize YAML files by component, environment, or namespace

506

2. **Glob Patterns**: Use glob patterns for flexible file selection

507

3. **Resource Naming**: Use consistent naming conventions across manifests

508

4. **Namespace Management**: Use namespace overrides rather than hardcoding namespaces

509

5. **Transformations**: Use transformations for cross-cutting concerns

510

511

### Deployment Best Practices

512

513

1. **Environment Separation**: Use different directories or overlays for different environments

514

2. **Resource Dependencies**: Use Pulumi dependencies to ensure proper deployment order

515

3. **Resource Access**: Use the resource access methods for inter-resource references

516

4. **Error Handling**: Implement proper error handling and rollback strategies

517

5. **Monitoring**: Monitor deployed resources and implement health checks

518

519

### Security Best Practices

520

521

1. **Secret Management**: Use Pulumi secrets for sensitive data rather than plain YAML

522

2. **RBAC Integration**: Apply appropriate RBAC configurations

523

3. **Network Policies**: Include network policies in your manifests

524

4. **Resource Limits**: Always specify resource requests and limits

525

5. **Image Security**: Use specific image tags and trusted registries

526

527

The YAML deployment capabilities provide a bridge between traditional Kubernetes manifests and modern infrastructure-as-code practices, enabling gradual migration while gaining the benefits of Pulumi's resource management and transformation capabilities.