This tutorial guides you through the process of deploying a simple service onto k8s using a hspec (HyScale Service Spec) and the hyscale command line tool.


To deploy your container image to K8s using hyscale, first prepare a short declarative spec file (hspec) as shown below.


If you do not already have an image or if you want hyscale to build the image for you, there are 2 other possible starting points described later in this document:


  • You have either the source code (eg. php files) or binaries (eg. war file) for your service.
  • You have a Docker file for your service.

The hyscale tool reads the supplied hspec and performs the necessary actions needed for deployment to k8s such as preparing a dockerfile, building the docker image and generating the various k8s manifests needed to satisfy the items declared in the hspec.

For the complete hspec reference, see here.


Preparing your first (and basic) service spec ("hspec")

Lets assume you have an image to deploy. Here is a basic service spec for deploying a tomcat image. This spec specifies some volumes needed, a port to be exposed outside the cluster and a http healthcheck.


myservice.hspec

name: myservice  # any identifier for your service

image:
    registry: registry.hub.docker.com
    name: library/tomcat
    tag: 8.5.0-jre8
 
volumes:
    - name: tomcat-logs-dir  # any identifier for your volume
       path: /usr/local/tomcat/logs
       size: 1Gi
       # for using a non-default storage-class, specify as follows:
       # storageClass: <storage-class-name>

external: true  # this will make the service accessible outside the cluster (via a LoadBalancer type IP). Default is "false"

ports:
    - port: 8080/tcp
       healthCheck:
             httpPath: /docs/images/tomcat.gif

Additional things you can specify in your service spec

Config Properties

props:
    JAVA_HOME: /usr/local/java
    TOMCAT_HOME: /usr/local/tomcat

propsVolumePath: /usr/local/data/config/tomcat.props  # This is default path if this directive is not specified

On deploy, these props go into a K8s ConfigMap and get injected as environment variables into the container. If propsVolumePath is specified, the ConfigMap is also mounted as a volume attached to the pod and the service code can then read these props from the file path specified.


Secrets

secrets:
    MYSQL_PASSWORD:XXXXXX

This works similar to the config properties above except that these go into K8s Secrets. If secretsVolumePath is specified, the secrets will be mounted as a volume and available at the path location inside the container.


If you already have secrets in K8s that you manage separately, you could specify just the name as follows. HyScale expects these to be present within a secret name "-" which should have been pre-created within the cluster.

secrets:
    - MYSQL_PASSWORD

Auto-Scale (HPA)

replicas:
    min: 1
    max: 4
    cpuThreshold: 30%

Logging & other Agents (sidecars)

agents:
    - name: fluentd  # any identified for your agent/sidecar
       image: quay.io/fluentd_elasticsearch/fluentd
       props:
            FLUENTD_ARGS: --no-supervisor -vv
       volumes:
            - mountPath: /mnt/log
               attach: tomcat-logs  # this is the name of the main service's volume to be mounted into this agent/sidecar

This will deploy the specified image as a sidecar alongside your main service container. The attach directive above specifies the identifier of the main service volume to be mounted into the sidecar.


Miscellaneous

replicas: 3  # specify fixed number of replica pods needed, if you haven't specified auto-scaling as above
memory: 2G   # minimum memory to be requested for your service
cpu: 3

startCommands: <start-command with args>    # command+args in k8s yaml, overrides ENTRYPOINT+CMD

Using HyScale to build your image (optional)

Building from source / binaries

To start from source, or binaries for compiled languages, place this buildSpec snippet under the image directive:

image:
    # target registry, image name & tag go here as previously shown
    # images built by hyscale using the buildSpec below will be pushed to this target registry
    # hyscale relies on docker daemon to build images

    buildSpec:
    stackImage: tomcat:8.5.0-jre8
    artifacts:
        - name: myservice  # any identifier for your artifact
           source: target/myservice.war
           destination: /usr/local/tomcat/webapps/

Where:
stackImage is the base stack image that your code depends on and can be specified in the format registry-url/name:tag
source is the relative path to the artifacts including the filename, relative to your hspec file. This can be a zip file but not a folder.

destination specifies the absolute path inside the container where the artifacts should be placed.


Building from a Dockerfile

image:
    # target registry, image name & tag go here as previously shown
    # images built by hyscale using the buildSpec below will be pushed to this target registry
    # hyscale relies on docker daemon to build images

    dockerfile: {}

Hyscale will look for a “Dockerfile” in the same directory as the hspec file. If your Dockerfile is in a different path or if you need to specify a target stage (in a multi-stage Dockerfile) or some build arguments, use the directives dockerfilePath, target and buildArgs respectively.


Specifying over-rides for different environments

Managing configuration differences across environments is necessary, so a hspec alone may not be sufficient across all environments. Environment specific configurations can be achieved through profiles as shown in the example below.


Stage profile for myservice can be like


stage-myservice.hprof

environment: stage
overrides: myservice
 
volumes:
    - name: tomcat-logs-dir
       size: 2Gi

replicas:
    min: 1
    max: 4
    cpuThreshold: 30%
 

Deploy the service to K8s

To deploy, invoke the hyscale deploy command:

hyscale deploy service -f `<myservice.hspec>` -n `<my-namespace>` -a `<my-app-name>`

where my-app-name is any identifier for your app and my-namespace is the namespace within the cluster. HyScale will attempt to create this namespace for you if it doesn't already exist.


To deploy with a profile override, invoke the following deploy command:

hyscale deploy service -f `<myservice.hspec>` -n `<my-namespace>` -a `<my-app-name>` -p `<stage-myservice.hprof>`

To view the status of your deployment:

hyscale get service status -s `<myservice>` -n `<my-namespace>` -a `<my-app-name>`

where myservice is the name of your service (same as your hspec file name without the .hspec extension)


To view logs:

hyscale get service logs -s `<myservice>` -n `<my-namespace>` -a `<my-app-name>`

For all possible commands, see App-Centric Ops & Commands