npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@npm-wharf/kubeform

v1.6.3

Published

a module for programatically provisioning kubernetes clusters via cloud provider APIs

Downloads

3

Readme

kubeform

A module for initializing new Kubernetes clusters via available 3rd party providers (GKE is the only implementation atm).

Build Status Coverage Status Version npm npm Downloads Dependencies

Approach

GKE

At present, the approach is to make use of a service account that has the IAM roles:

  • roles/billing.projectManager
  • roles/container.clusterAdmin
  • roles/editor
  • roles/iam.roleAdmin
  • roles/iam.roleViewer
  • roles/resourcemanager.organizationAdmin
  • roles/resourcemanager.projectCreator
  • roles/resourcemanager.projectIamAdmin

So that it can create a project per cluster and create a specialized service account for the cluster and assign it the roles required for it to do the job needed. This bypasses several security concerns that would exist if all clusters were to exist within a single project and used the top-level, default security account.

You can grant the necessary roles to a service account with the following gcloud CLI command:

gcloud organizations add-iam-policy-binding [organization id] --member serviceAccount:[full service account id] --role [role]

Environment

Certain options can be set via environment variables:

| Variable | Description | Default | |:-:|---|---| | KUBERNETES_PROVIDER | The backing service to use for the request | 'GKE' | | GOOGLE_APPLICATION_CREDENTIALS | Path to Google API credentials file | '' | | GOOGLE_ORGANIZATION_ID | Google Organization Id to create projects under | '' | | GOOGLE_BILLING_ID | Google Billing Account Id to associate with project | '' | | SERVICE_ACCOUNT_CREDENTIALS | Path to existing Service Account credentials file | '' |

Events Emitted

After calling create the instance will emit events to provide some indication of progress and metadata being fed back from the creation process:

prerequisites-created

GKE provider:

{
  provider: 'gke',
  prerequisites: [
    'project-created',
    'service-apis-enabled',
    'billing-associated',
    'service-account-created',
    'account-credentials-acquired',
    'iam-roles-assigned'
  ]
}

bucket-permissions-set

{
  readAccess: [ ],
  writeAccess: [ ]
}

cluster-initialized

{
  kubernetesCluster: {
    projectId: '',
    zone: [],
    cluster: {
      name: '',
      description: '',
      nodePools: [
        {
          ...
        }
      ],
      network: ,
      clusterIpv4Cidr: ,
      initialClusterVersion: '',
      locations: [],
      addonsConfig: {
        ...
      },
      masterAuth: {
        user: '',
        password: ''
      }
    }
  }
}

API

constructor (config)

The constructor takes an optional set of properties in the hash to provide required settings directly instead of requiring environment variables:

  • authFile: the location of the file containing credentials to use for authentication when creating projects and clusters
  • applicationCredentials: the same as above, except the literal credentials object
  • credFile: the location of the file containing credentials to use for within the cluster's project for basic operations. If omitted, new credentials will be created for the project
  • credentials: the same as above, except the literal credentials object
  • billingAccount: the id of the billing account to associate with the project & cluster
  • organizationId: the organization identity
  • provider: the name of the Kubernetes provider currently gke or none
const Kubeform = require('@npm-wharf/kubeform')
const kube = new Kubeform({
  authFile: '/path/to/auth.json',
  billingAccount: '11223344',
  organizationId: '123-4567-890',
  provider: 'gke'
})

create (options)

Send a creation request to the underlying Kubernetes service with desired options. Returns a promise that resolves when the cluster is created or rejects if an error occurs during the initial API call or during creation.

Options is a (somewhat) sanitized hash of characteristics you want for the cluster.

// defaults values for each option shown in options hash,
// omitted options will fall back to default value
// defaults are not assumed to work for general purposes,
// they exist to get you *something* but you should provide
// values that make sense for your cluster
kube.create(
  {
    name: '',
    description: '',
    locations: [], // the regions or zones to provision the master and workers in
    serviceAccount: '',
    readableBuckets: [], // existing buckets to grant the service account read access to
    writeableBuckets: [], // existing buckets to grant the service account write access to
    version: '1.10.11-gke.1', // a valid Kubernetes cluster version for the cloud provider
    basicAuth: true,
    user: 'admin', // basic auth user name
    password: '', // basic auth password - UUID generated by default
    managers: 1, //
    manager: {
      distributed: false, // spread manager nodes across region (multi-zone)
    },
    credentials: { // optional way to re-use previously acquired service account credentials
      type: "service_account",
      project_id: "project-name",
      private_key_id: "000000000000000000000000000001",
      private_key: "-----BEGIN PRIVATE  KEY-----\n-----END PRIVATE KEY-----\n", // required
      client_email: "[email protected]", // required
      client_id: "000000000000000000001",
      auth_uri: "https://accounts.google.com/o/oauth2/auth",
      token_uri: "https://oauth2.googleapis.com/token",
      auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs",
      client_x509_cert_url: "https://www.googleapis.com/robot/v1/metadata/x509/project-name-k8s-sa%40project-name.iam.gserviceaccount.com"
    },
    worker: { // desired resourcing per worker
      cores: 2, // cores per VM/machine
      memory: '13GB', // memory followed by units in GB or MB
      count: 3, // default worker count,
      min: 3, // if autoscaling is on, a minimum and max are required
      max: 6, // if autoscaling is on, a minimum and max are required
      maxPerInstance: 4, // matches 3 x the # of workers by default, instances (or pools) are how most providers span a cluster across AZs
      reserved: true, // whether the service should assign nodes that can provide availability guarantees or not (and cost less)
      maintenanceWindow: '08:00', // time in UTC for when automated maint should begin
      storage: {
        ephemeral: '0GB', // unreliable but usually cheaper/free storage :grimacing:
        persistent: '100GB', // how much reliable storage to attach to the instance - usually costs extra
      },
      network: {
        range: '', // give containers a CIDR range to be assigned within
        vpc: '' // set the id/name for a preset network or VPC
      }
    },
    flags: {
      alphaFeatures: false, // allow alpha features
      authedNetworksOnly: false, // only allow authorized networks to communicate with master nodes
      autoRepair: true, // service should auto-repair down/unresponsive nodes
      autoScale: false, // allow the service to detect load and scale workers up and down
      autoUpgrade: false, // allow the service to auto-upgrade kubernetes
      basicAuth: true, // allow basic auth
      clientCert: true, // generate a client cert automatically
      includeDashboard: false, // include a default installation of the kubernetes dashboard
      legacyAuthorization: false, // must be false for full RBAC
      loadBalancedHTTP: true, // required for use with Google's Cloud LB
      networkPolicy: true, // turn on network policies (calico)
      privateCluster: false, // nodes do not receive public IPs and the master is inaccessible by default
      serviceMonitoring: false, // should the service perform additonal monitoring
      serviceLogging: false // should the service perform additional logging
    }
  }
)

About Service Credentials

In many cases, cloud providers will issue a new set of credentials for the service account every time you run kubeform. The idempotent nature of kubeform will prevent new clusters from being created, but will not prevent new keys from being acquired to ensure that the credentials block gets populated in the resulting data about your cluster.

To prevent this, you can pre-populate the options with a credentials hash that will require certain fields based on the chosen cloud provider. Kubeform will re-use these credentials and bypass the credentials acquisition step when it detects this.

getRegions ()

Returns a list of available regions.

getVersions (projectId, zoneId)

Returns the list of valid Kubernetes versions for the project and zone given the chosen cloud provider.

getZones (region)

Given a region, list the zones available.

init (options)

The init command was created to help create a valid kubeform cluster specification from a ~/.kubeform file that provides defaults.

The options hash can have 3 of the following properties:

  • defaults - the file to use for defaults, ~/.kubeform
  • data - a hash or file path to supply overrides/missing values

When called without a data property (that must either be a hash containing missing values, or a string pointing to a file that can supply missing values), this function will throw an error that has a .required property containing an array of values necessary to create a minimal cluster specification.

If all required data is present, the full specification will be the result of the function.

CLI

kubeform provision ./path/to/config -a ./path/to/authFile.json -p gke -c ./path/to/service-credentials.json

Will attempt to provision a Kuberenetes cluster using the provider specified. Provider defaults to GKE. Auth file is required.

  • -a, --auth : the path to the authorization file.

Additional options:

  • -c, --credentials : service account credentials to re-use for your cluster
  • -o, --organization : the organization id that owns the cluster
  • -b, --billing : the billing id that the cluster should be associated with
  • -f, --file : the file to write all cluster details to

Both of these options may be provided via the configuration file and are likely to vary between providers.

kubeform init -f ./data.toml -a ./path/to/authFile -p gke

Creates a new Kubernetes cluster specification. Auth file is required.

  • -a, --auth : the path to the authorization file.

Additional options:

  • -f, --data : the file used to satisfy missing fields from the default
  • -d, --defaults : the file to use for supplying default values
  • -o, --output : the file to write the cluster specification to
  • --verbose : output verbose logging

Long-term Goals

  • add an API to price options hash before creation
  • add support for EKS
  • add support for AKS
  • add support for kops?

Full kubeform Specification in TOML format

The only properties shown here that are not required by kubeform are the network properties as these are optional settings.

name = "my-cluster"
description = "this is my cluster"
projectId = "my-project"
billingId = "123-456-789"
organizationId = "1234567890"
version = "1.10.11-gke.1"
zones = [ "us-central1-a" ]
basicAuth = true
user = "admin"
password = "thisisapasswordformanagingk8s"
serviceAccount = "my-k8s-sa"
readableBuckets = []
writeableBuclets = []

managers = 1
[manager]
  distributed = false

[worker]
  cores = 2
  memory = "13GB"
  count = 3
  min = 3
  max = 6
  maxPerInstance = 4
  reserved = true
  maintenanceWindow = "08:00"

[worker.storage]
  ephemeral = "0GB"
  persistent = "100GB"

[worker.network]
  range = "10.0.0.0/32"
  vpc = "my-vpc"

[flags]
  alphaFeatures = false
  authedNetworksOnly = false
  autoRepair = true
  autoScale = true
  autoUpgrade = true
  basicAuth = true
  clientCert = true
  includeDashboard = false
  legacyAuthorization = false
  loadBalancedHTTP = true
  networkPolicy = true
  privateCluster = false
  serviceMonitoring = false
  serviceLogging = false

Example ~/.kubeform file

basicAuth = true
user = "admin"
managers = 1

[manager]
  distributed = false

[worker]
  cores = 2
  memory = "13GB"
  maxPerInstance = 4
  reserved = true
  maintenanceWindow = "08:00"

[worker.storage]
  ephemeral = "0GB"
  persistent = "160GB"

[flags]
  alphaFeatures = false
  authedNetworksOnly = false
  autoRepair = true
  autoScale = true
  autoUpgrade = true
  basicAuth = true
  clientCert = true
  includeDashboard = false
  legacyAuthorization = false
  loadBalancedHTTP = true
  networkPolicy = true
  privateCluster = false
  serviceMonitoring = false
  serviceLogging = false