On this page, you can find essential steps and code for starting with Pulumi and Cloud, from installation to advanced deployment scenarios, highlighting the benefits of infrastructure as code (IaC) for simplifying and automating cloud infrastructure management.
The Pulumi CLI never transmits your cloud credentials to Pulumi Cloud.
Before proceeding with the examples, it’s necessary to execute the following Pulumi CLI commands to securely store credentials locally. You can obtain all the credential data from the “rc” file that was downloaded after creating the OpenStack CLI user.
pulumi config set authUrl $OS_AUTH_URL
pulumi config set --secret userName $OS_USERNAME
pulumi config set --secret passWord $OS_PASSWORD
pulumi config set tenantId $OS_PROJECT_DOMAIN_ID
pulumi config set domainName $OS_USER_DOMAIN_NAME
Create project and run Pulumi stack:
mkdir ventus && cd ventus
pulumi new ventus-dev
“If you’re using pulumi new or any other pulumi command for the first time, you might need to log in to Pulumi Cloud. Pulumi CLI and Pulumi Cloud work together to provide a reliable experience. It’s free for personal use, offers features for teams, and there are also self-managed options available. Pressing Enter at the prompt will open a browser for you to sign in or sign up.”
Place the code example within the “ventus” directory and run:
pulumi up
The Go code snippet provided below defines an infrastructure deployment using Pulumi for managing resources on the Cloud. Here’s a breakdown of what it does:
This code can be used to provision resources on the cloud, including creating VM instances with SSH access configured via key pairs and security groups. Adjustments can be made to customize the deployment according to specific requirements.
package main
import (
"github.com/pulumi/pulumi-openstack/sdk/v3/go/openstack"
"github.com/pulumi/pulumi-openstack/sdk/v3/go/openstack/compute"
"github.com/pulumi/pulumi-openstack/sdk/v3/go/openstack/networking"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
cfg := config.New(ctx, "")
openstackProvider, err := openstack.NewProvider(ctx, "openstack", &openstack.ProviderArgs{
AuthUrl: pulumi.String(cfg.Require("authUrl")),
UserName: pulumi.String(cfg.Require("userName")),
Password: pulumi.String(cfg.Require("passWord")),
TenantId: pulumi.String(cfg.Require("tenantId")),
DomainName: pulumi.String(cfg.Require("domainName")),
})
if err != nil {
return err
}
// Create a new key pair for SSH access
keyPair, err := compute.NewKeypair(ctx, "keyPair", &compute.KeypairArgs{
Name: pulumi.String("my-keypair"),
// Public key would be string contents of your public key for SSH access
PublicKey: pulumi.String("PUBLIC KEY"),
}, pulumi.Provider(openstackProvider))
if err != nil {
return err
}
// Define the security group to allow SSH access
secGroup, err := networking.NewSecGroup(ctx, "secGroup", &networking.SecGroupArgs{
Name: pulumi.String("ssh"),
Description: pulumi.String("Allow SSH"),
}, pulumi.Provider(openstackProvider))
if err != nil {
return err
}
// Add a security group rule to allow inbound SSH connections
_, err = networking.NewSecGroupRule(ctx, "ssh", &networking.SecGroupRuleArgs{
Direction: pulumi.String("ingress"),
Ethertype: pulumi.String("IPv4"),
PortRangeMin: pulumi.Int(22),
PortRangeMax: pulumi.Int(22),
Protocol: pulumi.String("tcp"),
SecurityGroupId: secGroup.ID(),
RemoteIpPrefix: pulumi.String("0.0.0.0/0"),
}, pulumi.Provider(openstackProvider))
if err != nil {
return err
}
// Create a new OpenStack VM
vm, err := compute.NewInstance(ctx, "vm", &compute.InstanceArgs{
FlavorName: pulumi.String("VC-2"),
ImageName: pulumi.String("ubuntu-server-22.04-LTS-20240110"),
Name: pulumi.String("example-vm"),
Networks: compute.InstanceNetworkArray{
&compute.InstanceNetworkArgs{Name: pulumi.String("public")},
},
KeyPair: keyPair.Name,
SecurityGroups: pulumi.StringArray{secGroup.Name},
}, pulumi.Provider(openstackProvider))
if err != nil {
return err
}
// Export the IP address of the VM
ctx.Export("ip", vm.AccessIpV4)
return nil
})
}
The Go code snippet provided below defines an infrastructure deployment using Pulumi for managing resources on the Cloud. Here’s a breakdown of what it does:
The userDataScript variable contains a shell script that is executed as UserData to configure the VM. It installs nginx and starts the service.
This code can be used to provision resources on the Cloud, including creating VM instances with SSH and Web access configured via key pairs and security groups. Adjustments can be made to customize the deployment according to specific requirements.
package main
import (
"github.com/pulumi/pulumi-openstack/sdk/v3/go/openstack"
"github.com/pulumi/pulumi-openstack/sdk/v3/go/openstack/compute"
"github.com/pulumi/pulumi-openstack/sdk/v3/go/openstack/networking"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
cfg := config.New(ctx, "")
openstackProvider, err := openstack.NewProvider(ctx, "openstack", &openstack.ProviderArgs{
AuthUrl: pulumi.String(cfg.Require("authUrl")),
UserName: pulumi.String(cfg.Require("userName")),
Password: pulumi.String(cfg.Require("passWord")),
TenantId: pulumi.String(cfg.Require("tenantId")),
DomainName: pulumi.String(cfg.Require("domainName")),
})
if err != nil {
return err
}
// Create a new key pair for SSH access
keyPair, err := compute.NewKeypair(ctx, "keyPair", &compute.KeypairArgs{
Name: pulumi.String("my-keypair"),
// Public key would be string contents of your public key for SSH access
PublicKey: pulumi.String("PUBLIC KEY"),
}, pulumi.Provider(openstackProvider))
if err != nil {
return err
}
// Define the security group to allow SSH access
secGroup, err := networking.NewSecGroup(ctx, "secGroup", &networking.SecGroupArgs{
Name: pulumi.String("sshandweb"),
Description: pulumi.String("Allow SSH access and Web access"),
}, pulumi.Provider(openstackProvider))
if err != nil {
return err
}
// Add a security group rule to allow inbound SSH connections
_, err = networking.NewSecGroupRule(ctx, "ssh-access-80", &networking.SecGroupRuleArgs{
Direction: pulumi.String("ingress"),
Ethertype: pulumi.String("IPv4"),
PortRangeMin: pulumi.Int(22),
PortRangeMax: pulumi.Int(22),
Protocol: pulumi.String("tcp"),
SecurityGroupId: secGroup.ID(),
RemoteIpPrefix: pulumi.String("0.0.0.0/0"),
}, pulumi.Provider(openstackProvider))
if err != nil {
return err
}
// Add a security group rule to allow inbound WEB connections
_, err = networking.NewSecGroupRule(ctx, "web-access-443", &networking.SecGroupRuleArgs{
Direction: pulumi.String("ingress"),
Ethertype: pulumi.String("IPv4"),
PortRangeMin: pulumi.Int(80),
PortRangeMax: pulumi.Int(80),
Protocol: pulumi.String("tcp"),
SecurityGroupId: secGroup.ID(),
RemoteIpPrefix: pulumi.String("0.0.0.0/0"),
}, pulumi.Provider(openstackProvider))
if err != nil {
return err
}
// Add a security group rule to allow inbound WEB connections
_, err = networking.NewSecGroupRule(ctx, "web-access", &networking.SecGroupRuleArgs{
Direction: pulumi.String("ingress"),
Ethertype: pulumi.String("IPv4"),
PortRangeMin: pulumi.Int(443),
PortRangeMax: pulumi.Int(443),
Protocol: pulumi.String("tcp"),
SecurityGroupId: secGroup.ID(),
RemoteIpPrefix: pulumi.String("0.0.0.0/0"),
}, pulumi.Provider(openstackProvider))
if err != nil {
return err
}
// Create a new OpenStack VM
vm, err := compute.NewInstance(ctx, "vm", &compute.InstanceArgs{
FlavorName: pulumi.String("VC-2"),
ImageName: pulumi.String("ubuntu-server-22.04-LTS-20240110"),
Name: pulumi.String("example-vm"),
Networks: compute.InstanceNetworkArray{
&compute.InstanceNetworkArgs{Name: pulumi.String("public")},
},
KeyPair: keyPair.Name,
SecurityGroups: pulumi.StringArray{secGroup.Name},
UserData: pulumi.String(userDataScript),
}, pulumi.Provider(openstackProvider))
if err != nil {
return err
}
// Export the IP address of the VM
ctx.Export("ip", vm.AccessIpV4)
return nil
})
}
// userDataScript contains the shell script to be executed as UserData.
var userDataScript = `
#cloud-config
apt:
preserve_sources_list: true
sources:
- sourceline: "deb http://archive.ubuntu.com/ubuntu focal main universe"
package_upgrade: true
packages:
- nginx
runcmd:
- systemctl start nginx
`
The Go code snippet provided below sets up an kubernetes cluster scenario using Pulumi to manage resources on the Cloud. Here’s a breakdown of its functionality:
The cluster configuration includes parameters such as the cluster template ID, key pair for authentication, master and node counts, and flavor of the VM instances.
The kubeconfig for the provisioned Kubernetes cluster is exported to Pulumi config as a secret.
package main
import (
"github.com/pulumi/pulumi-openstack/sdk/v3/go/openstack"
"github.com/pulumi/pulumi-openstack/sdk/v3/go/openstack/compute"
"github.com/pulumi/pulumi-openstack/sdk/v3/go/openstack/containerinfra"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
cfg := config.New(ctx, "")
openstackProvider, err := openstack.NewProvider(ctx, "openstack", &openstack.ProviderArgs{
AuthUrl: pulumi.String(cfg.Require("authUrl")),
UserName: pulumi.String(cfg.Require("userName")),
Password: pulumi.String(cfg.Require("passWord")),
TenantId: pulumi.String(cfg.Require("tenantId")),
DomainName: pulumi.String(cfg.Require("domainName")),
})
if err != nil {
return err
}
// Create a new key pair for SSH access
_, err = compute.NewKeypair(ctx, "keyPair", &compute.KeypairArgs{
Name: pulumi.String("my-keypair"),
// Public key would be string contents of your public key for SSH access
PublicKey: pulumi.String("PUBLIC KEY"),
}, pulumi.Provider(openstackProvider))
if err != nil {
return err
}
//create k8s cluster
k8s, err := containerinfra.NewCluster(ctx, "k8s1", &containerinfra.ClusterArgs{
ClusterTemplateId: pulumi.String("ID"), //openstack coe cluster template list
Keypair: pulumi.String("my-keypair"),
MasterCount: pulumi.Int(1),
NodeCount: pulumi.Int(1),
Flavor: pulumi.String("VC-2"),
MasterFlavor: pulumi.String("VC-2"),
}, pulumi.Provider(openstackProvider))
if err != nil {
return err
}
// Export the kubeconfig to pulumi config in secret
ctx.Export("kubeconfig", k8s.Kubeconfig)
return nil
})
}