[Infrastructure as Code (IaC)] Get Started with Kubernetes (K8S) - Use Pulumi Go SDK to manage Kubernetes (K8S)

Pulumi

Pulumi is a Modern Infrastructure as Code (IaC) to create, deploy, and manage infrastructure on any cloud using familiar programming languages and tools.

Pulumi’s Cloud Native SDK makes it easy to target any Kubernetes environment to provision a cluster, configure and deploy applications, and update them as required.

This article is about how to use Pulumi and Go SDK to manager Namespace and Deployment within Kubernetes (K8S).

Prerequisites

Install Pulumi and Go

Pulumi

Install the Pulumi - https://www.pulumi.com/ CLI.

1
2
# Mac OS X
$ brew install pulumi

Go Language Runtime

Install Go - https://golang.org/ .

1
2
# Mac OS X
$ brew install go

Configure Kubernetes

By default, Pulumi will look for a kubeconfig file in the following locations, just like kubectl:

  • The environment variable: $KUBECONFIG,

  • Or in current user’s default kubeconfig directory: ~/.kube/config

If the kubeconfig file is not in either of these locations, Pulumi will not find it, and it will fail to authenticate against the cluster. Set one of these locations to a valid kubeconfig file, if you have not done so already.

Run Pulumi

Create the workspace directory.

1
2
3
$ mkdir -p cloudolife-pulumi-go-alicloud-k8s

$ cd cloudolife-pulumi-go-alicloud-k8s

Pulumi login into local file system.

1
2
3
$ pulumi login file://.
Logged in to cloudolife as cloudolife (file://.)
or visit https://pulumi.com/docs/reference/install/ for manual instructions and release notes.

Pulumi new a project with go SDK.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ pulumi new kubernetes-go
This command will walk you through creating a new Pulumi project.

Enter a value or leave blank to accept the (default), and press <ENTER>.
Press ^C at any time to quit.

project name: (cloudolife-pulumi-go-alicloud-k8s)
project description: (A minimal Kubernetes Go Pulumi program)
Created project 'cloudolife-pulumi-go-alicloud-k8s'

stack name: (dev)
Created stack 'dev'
Enter your passphrase to protect config/secrets:
Re-enter your passphrase to confirm:

Enter your passphrase to unlock config/secrets
(set PULUMI_CONFIG_PASSPHRASE or PULUMI_CONFIG_PASSPHRASE_FILE to remember):
Installing dependencies...

Finished installing dependencies

Your new project is ready to go! ✨

To perform an initial deployment, run 'pulumi up'

The above command will create some files within the current directory.

1
2
3
4
5
6
7
tree .
.
├── Pulumi.dev.yaml
├── Pulumi.yaml
├── go.mod
├── go.sum
└── main.go

See and modify main.go file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# main.go

package main

import (
appsv1 "github.com/pulumi/pulumi-kubernetes/sdk/v2/go/kubernetes/apps/v1"
corev1 "github.com/pulumi/pulumi-kubernetes/sdk/v2/go/kubernetes/core/v1"
metav1 "github.com/pulumi/pulumi-kubernetes/sdk/v2/go/kubernetes/meta/v1"
"github.com/pulumi/pulumi/sdk/v2/go/pulumi"
)

func main() {
pulumi.Run(func(ctx *pulumi.Context) error {

// Apply a namespace.
namespace, err := corev1.NewNamespace(ctx, "pulumi-go-alicloud-k8s", &corev1.NamespaceArgs{
Metadata: &metav1.ObjectMetaArgs{
Name: pulumi.String("pulumi-go-alicloud-k8s"),
},
})

appLabels := pulumi.StringMap{
"app": pulumi.String("nginx"),
}

// Apply a Deployment.
deployment, err := appsv1.NewDeployment(ctx, "app-dep", &appsv1.DeploymentArgs{
Metadata: &metav1.ObjectMetaArgs{
Namespace: namespace.Metadata.Elem().Name(),
},
Spec: appsv1.DeploymentSpecArgs{
Selector: &metav1.LabelSelectorArgs{
MatchLabels: appLabels,
},
Replicas: pulumi.Int(1),
Template: &corev1.PodTemplateSpecArgs{
Metadata: &metav1.ObjectMetaArgs{
Labels:
appLabels,
},
Spec: &corev1.PodSpecArgs{
Containers: corev1.ContainerArray{
corev1.ContainerArgs{
Name: pulumi.String("nginx"),
Image: pulumi.String("nginx"),
}},
},
},
},
})
if err != nil {
return err
}

ctx.Export("name", deployment.Metadata.Elem().Name())

return nil
})
}

Run pulumi up to create the namespace and pods.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
$ pulumi up
Enter your passphrase to unlock config/secrets
(set PULUMI_CONFIG_PASSPHRASE or PULUMI_CONFIG_PASSPHRASE_FILE to remember):
Previewing update (dev):
Type Name Plan
pulumi:pulumi:Stack cloudolife-pulumi-go-alicloud-k8s-dev
+ ├─ kubernetes:core/v1:Namespace pulumi-go-alicloud-k8s create
+ └─ kubernetes:apps/v1:Deployment app-dep create

Outputs:
+ name: "app-dep-rx8h9grh"

Resources:
+ 2 to create
1 unchanged

Permalink: file:///Users/cloudolife/WorkSpaces/cloudolife/cloudolife-devops/cloudolife-pulumi/cloudolife-pulumi-go-alicloud-k8s/.pulumi/stacks/dev.json
Do you want to perform this update? details
pulumi:pulumi:Stack: (same)
[urn=urn:pulumi:dev::cloudolife-pulumi-go-alicloud-k8s::pulumi:pulumi:Stack::cloudolife-pulumi-go-alicloud-k8s-dev]
+ kubernetes:core/v1:Namespace: (create)
[urn=urn:pulumi:dev::cloudolife-pulumi-go-alicloud-k8s::kubernetes:core/v1:Namespace::pulumi-go-alicloud-k8s]
apiVersion: "v1"
kind : "Namespace"
metadata : {
labels: {
app.kubernetes.io/managed-by: "pulumi"
}
name : "pulumi-go-alicloud-k8s"
}
+ kubernetes:apps/v1:Deployment: (create)
[urn=urn:pulumi:dev::cloudolife-pulumi-go-alicloud-k8s::kubernetes:apps/v1:Deployment::app-dep]
apiVersion: "apps/v1"
kind : "Deployment"
metadata : {
annotations: {
pulumi.com/autonamed: "true"
}
labels : {
app.kubernetes.io/managed-by: "pulumi"
}
name : "app-dep-rx8h9grh"
namespace : "pulumi-go-alicloud-k8s"
}
spec : {
replicas: 1
selector: {
matchLabels: {
app: "nginx"
}
}
template: {
metadata: {
labels: {
app: "nginx"
}
}
spec : {
containers: [
[0]: {
image: "nginx"
name : "nginx"
}
]
}
}
}
--outputs:--
+ name: "app-dep-rx8h9grh"

Do you want to perform this update? yes
Updating (dev):
Type Name Status
pulumi:pulumi:Stack cloudolife-pulumi-go-alicloud-k8s-dev
+ ├─ kubernetes:core/v1:Namespace pulumi-go-alicloud-k8s created
+ └─ kubernetes:apps/v1:Deployment app-dep created

Outputs:
+ name: "app-dep-rx8h9grh"

Resources:
+ 2 created
1 unchanged

Permalink: file:///Users/cloudolife/WorkSpaces/cloudolife/cloudolife-devops/cloudolife-pulumi/cloudolife-pulumi-go-alicloud-k8s/.pulumi/stacks/dev.json

See namespaces abount pulumi-go-alicloud-k8s

1
2
3
kubectl get namespace
NAME STATUS AGE
pulumi-go-alicloud-k8s Active 3m29s

See pods about pulumi-go-alicloud-k8s.

1
2
3
$ kubectl get pods -n pulumi-go-alicloud-k8s
NAMESPACE NAME READY STATUS RESTARTS AGE
pulumi-go-alicloud-k8s app-dep-rx8h9grh-f89759699-2hn27 1/1 Running 0 14s

Destroy all resources created by Pulumi.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
$ pulumi destroy
Enter your passphrase to unlock config/secrets
(set PULUMI_CONFIG_PASSPHRASE or PULUMI_CONFIG_PASSPHRASE_FILE to remember):
Previewing destroy (dev):
Type Name Plan
- pulumi:pulumi:Stack cloudolife-pulumi-go-alicloud-k8s-dev delete
- ├─ kubernetes:core/v1:Namespace pulumi-go-alicloud-k8s delete
- └─ kubernetes:apps/v1:Deployment app-dep delete

Outputs:
- name: "app-dep-rx8h9grh"

Resources:
- 3 to delete

Permalink: file:///Users/cloudolife/WorkSpaces/cloudolife/cloudolife-devops/cloudolife-pulumi/cloudolife-pulumi-go-alicloud-k8s/.pulumi/stacks/dev.jsonn
Do you want to perform this destroy? details
- kubernetes:core/v1:Namespace: (delete)
[id=pulumi-go-alicloud-k8s]
[urn=urn:pulumi:dev::cloudolife-pulumi-go-alicloud-k8s::kubernetes:core/v1:Namespace::pulumi-go-alicloud-k8s]
- kubernetes:apps/v1:Deployment: (delete)
[id=pulumi-go-alicloud-k8s/app-dep-rx8h9grh]
[urn=urn:pulumi:dev::cloudolife-pulumi-go-alicloud-k8s::kubernetes:apps/v1:Deployment::app-dep]
- pulumi:pulumi:Stack: (delete)
[urn=urn:pulumi:dev::cloudolife-pulumi-go-alicloud-k8s::pulumi:pulumi:Stack::cloudolife-pulumi-go-alicloud-k8s-dev]
--outputs:--
- name: "app-dep-rx8h9grh"

Do you want to perform this destroy? yes
Destroying (dev):
Type Name Status
- pulumi:pulumi:Stack cloudolife-pulumi-go-alicloud-k8s-dev deleted
- ├─ kubernetes:core/v1:Namespace pulumi-go-alicloud-k8s deleted
- └─ kubernetes:apps/v1:Deployment app-dep deleted

Outputs:
- name: "app-dep-rx8h9grh"

Resources:
- 3 deleted

Duration: 30s

Permalink: file:///Users/cloudolife/WorkSpaces/cloudolife/cloudolife-devops/cloudolife-pulumi/cloudolife-pulumi-go-alicloud-k8s/.pulumi/stacks/dev.jsonn
The resources in the stack have been deleted, but the history and configuration associated with the stack are still maintained.
If you want to remove the stack completely, run 'pulumi stack rm dev'.

References

[1] Kubernetes Getting Started | Pulumi - https://www.pulumi.com/docs/get-started/kubernetes/

[2] Deploy Kubernetes and Applications with Go | Pulumi - https://www.pulumi.com/blog/deploy-kubernetes-and-apps-with-go/

[3] Pulumi - Modern Infrastructure as Code - https://www.pulumi.com/

[4] The Go Programming Language - https://golang.org/

[5] Kubernetes - https://kubernetes.io/