Skip to main content

Add a Custom Pack

Custom packs are built by users and deployed to custom registries using the Spectro Cloud CLI tool. To get started with Spectro Cloud CLI, review the Spectro Cloud CLI installation instructions.

Prerequsites

The following items are required to create a custom pack.

JSON Schema

Each pack contains a metadata file named pack.json. The table below explains in greater detail the JSON schema attributes.

Property NameData typeRequiredDescription
nameStringTrueName of the pack
displayNameStringTrueName of the pack as it is to be displayed on the Palette management console.
layerStringTrueRelevant layer that this pack should be part of; such as os, k8s, cni, csi, addon
addonTypeStringFalseAddon-type must be set for packs that have the layer set to Addon. The value must be one of the following: logging, monitoring, load balancer, authentication, ingress, security. Setting a relevant correct addon type ensures packs are organized correctly on the management console making it easy for profile authors to find packs.
versionStringTrueA Semantic version for the pack. It is recommended that the pack version be the same as the underlying integration it is being created for. For example, the version for the pack that will install Prometheus 2.3.4, should set to 2.3.4.
cloudTypesArrayTrueYou can provide one or more types for a pack. Supported values are as follows:

all, aws, azure, gcp, tencent, vsphere, openstack, baremetal, maas, aks, eks, tke, edge, edge-native, coxedge, and libvirt (virtualized edge).
groupStringFalseOptional categorization of packs. For example, LTS can be set for Ubuntu OS packs.
annotationsArrayFalseOptional key-value pairs required during pack installation. Typically, custom packs do not need to set annotations. Some packs like the ones for OS require annotations that need to be set with an image id.
eolStringFalseEnd of life date for integration.
KubeManifestsArrayFalseRelative path to Kubernetes manifest yaml files.
ansibleRolesArrayFalseRelative part to the Ansible role folders. These folders should contain all the artifacts required by Ansible. Please refer to the Ansible documentation for more details on how Ansible roles are constructed.
In Palette, Ansible roles are used to customize the OS image used for cluster nodes. Typically, these are roles that perform tasks like hardening the OS, installing monitoring agents, etc.
chartsArrayFalseRelative path to the helm chart archives.

The following is the JSON schema for packs. Review the schema to ensure your JSON configuration is defined correctly.


{
"type": "object",
"required": ["name", "displayName", "version", "layer"],
"properties": {
"name": {
"$ref": "#/definitions/nonEmptyString"
},
"displayName": {
"$ref": "#/definitions/nonEmptyString"
},
"version": {
"$ref": "#/definitions/nonEmptyString"
},
"layer": {
"$ref": "#/definitions/layer"
},
"group": {
"type": "string"
},
"cloudTypes": {
"type": "array",
"items": {
"type": "string",
"enum": [
"all",
"aws",
"azure",
"gcp",
"vsphere",
"openstack",
"baremetal",
"maas",
"aks",
"eks",
"tencent",
"tke",
"edge",
"libvirt",
"edge-native",
"coxedge"
]
}
},
"cloudType": {
"type": "string",
"enum": [
"all",
"aws",
"azure",
"gcp",
"vsphere",
"openstack",
"baremetal",
"maas",
"aks",
"eks",
"tencent",
"tke",
"edge",
"libvirt",
"edge-native",
"coxedge"
]
},
"eol": {
"type": "string"
},
"addonType": {
"type": "string"
},
"addonSubType": {
"type": "string"
},
"ansibleRoles": {
"type": "array",
"items": {
"type": "string"
}
},
"charts": {
"type": "array",
"items": {
"type": "string"
}
},
"kubeManifests": {
"type": "array",
"items": {
"type": "string"
}
},
"annotations": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"constraints": {
"$ref": "#/definitions/constraints"
}
},
"definitions": {
"nonEmptyString": {
"type": "string",
"minLength": 1
},
"layer": {
"type": "string",
"enum": ["kernel", "os", "k8s", "cni", "csi", "addon"]
},
"constraints": {
"type": "object",
"properties": {
"dependencies": {
"type": "array",
"items": {
"$ref": "#/definitions/dependency"
}
},
"resources": {
"type": "array",
"items": {
"$ref": "#/definitions/resource"
}
}
}
},
"dependency": {
"type": "object",
"required": ["packName", "layer", "type"],
"properties": {
"packName": {
"$ref": "#/definitions/nonEmptyString"
},
"layer": {
"$ref": "#/definitions/layer"
},
"minVersion": {
"type": "string"
},
"maxVersion": {
"type": "string"
},
"type": {
"type": "string",
"enum": ["required", "optional", "notSupported", "upgrade"]
}
}
},
"resource": {
"type": "object",
"required": ["type"],
"properties": {
"type": {
"type": "string",
"enum": ["cpu", "memory", "diskSize"]
},
"minLimit": {
"type": "number"
},
"components": {
"type": "array",
"items": {
"$ref": "#/definitions/component"
}
}
}
},
"component": {
"type": "object",
"required": ["scheduleType"],
"properties": {
"scheduleType": {
"type": "string",
"enum": ["all", "control-plane", "worker"]
},
"resourceRequestParamRef": {
"type": "string"
},
"replicaCountParamRef": {
"type": "string"
}
}
}
}
}

Create a Custom Pack

Follow the steps below to create a custom pack.

  1. Create a directory with a suitable name for all the pack contents.

    Example: prometheus_1_0

  2. Create a metadata file named pack.json to describe the pack.

    Example:

    {
    "annotations": {
    "name": "value"
    },
    "ansibleRoles": [],
    "displayName": "<PACK_DISPLAY_NAME>",
    "eol": "2028-04-30",
    "group": "<PACK_GROUP>",
    "kubeManifests": ["manifests/deployment.yaml"],
    "layer": "<LAYER>",
    "name": "<PACK_NAME>",
    "version": "<PACK_VERSION>"
    }
  3. Create a file named values.yaml. This file consists of configurable parameters that need to be exposed to the end-users during the creation of a cluster profile.

info

A values.yaml file is mandatory for every pack. For an OS pack, there are typically no configurable parameters, but an empty file still needs to be added to the OS pack.

Parameters for all charts, manifests, and Ansible roles defined in the pack are defined in the values.yaml file. Helm charts natively support values override. Any values defined are merged with those defined within a chart. Manifests and Ansible roles need to be explicitly templatized if parameter configuration is desired.

    pack:
namespace : <default namespace for charts and manifests>
charts:
chart1:
<configurable chart1 parameters>
chart2:
<configurable chart2 parameters>
manifests:
manifest1:
<templatized manifest1 parameters>
manifest2:
<templatized manifest2 parameters>
ansibleRoles:
role1:
<templatized role1 parameters>
role2:
<templatized role2 parameters>
  1. A pack must have the logo file named logo.png and must be copied into the pack directory.

  2. Login to the pack registry using the following command:

     spectro registry login [REGISTRY_SERVER]
  3. Push the newly defined pack to the pack registry using the following command:

     spectro pack push [PACK_DIR_LOCATION] --registry-server [REGISTRY_SERVER]
  4. To overwrite contents of a previously deployed pack, use the force option as follows:

     spectro pack push [PACK_DIR_LOCATION] -f --registry-server [REGISTRY_SERVER]

Adding an OS Pack

The OS is one of the Core Layers in a cluster profile. An OS pack can be built to use a custom OS image for cluster nodes. This might be desirable if an organization wants to use an approved hardened OS image for their infrastructure. There are typically the following two scenarios for the OS image:


  1. Pre-Installed Kubernetes - The OS image has the desired version of Kubernetes components like kubelet, kubectl, etc installed.

  2. Vanilla OS Image - Kubernetes components are not installed.

Additionally, for both scenarios additional components or packages may need to be installed at runtime to prepare the final OS image. This can be done by specifying one or more Ansible roles in the pack. The following are a few examples of building custom OS pack to cover the some of these scenarios.

A few sample pack manifests for building a custom OS pack are shown in the following examples. These are examples for images that do not have Kubernetes components pre-installed. Palette installs these components at the time of provisioning. The version of Kubernetes that gets installed depends on the Kubernetes pack configuration in the cluster profile. If Kubernetes is pre-installed in the image, set the flag skipK8sInstall to true.

Examples

AWS Custom-OS Pack

{
"annotations":
{
"cloudRegion": "us-east-1",
"imageId": "ami-071f6fc516c53fca1",
"imageOwner": "421085264799",
"osName": "centos",
"os_spectro_version": "0",
"sshUsername": "centos",
"skipK8sInstall": "false",
},
"ansibleRoles": ["harden_os"],
"cloudTypes": ["aws"],
"displayName": "CentOS",
"eol": "2024-06-30",
"group": "",
"kubeManifests": [],
"layer": "os",
"name": "golden-centos-aws",
"version": "7.7.1908",
}

Ansible Roles

In all the previous examples, additional customization in the form of an Ansible role called harden_os is specified in the pack manifest. The tasks and other files for the implementation of this role need to be included in the pack. The final directory structure of for the pack would be as follows:

./pack.json
./logo.png
./values.yaml
./harden_os
./harden_os/tasks
./harden_os/tasks/main.yml
./harden_os/files
./harden_os/files/sec_harden.sh

Ansible roles are optional and only required if additional runtime customization is required. Once an OS pack is constructed, push it to the pack registry using the Spectro CLI tool.

warning

During the image customization phase of a cluster deployment, failures related to missing packages or package version mismatch could occur when using a custom OS pack. These errors are presented on the console. The image needs to be updated to resolve any such issues.