diff --git a/README.md b/README.md index 14c52ee..4f149e7 100644 --- a/README.md +++ b/README.md @@ -18,18 +18,18 @@ # Downloads a .tgz file to the working directory or --destination path helm pull \ oci://ghcr.io/whylabs/langkit \ - --version "0.10.0" + --version "0.17.0" helm diff upgrade \ --allow-unreleased \ --namespace langkit \ `# Specify the .tgz file as the chart` \ - langkit langkit-0.10.0.tgz + langkit langkit-0.17.0.tgz helm upgrade --install \ --create-namespace \ --namespace langkit \ - langkit langkit-0.10.0.tgz + langkit langkit-0.17.0.tgz ``` #### Extended Example @@ -37,7 +37,7 @@ helm upgrade --install \ # Configure local variables for clarity and simplicity helm_repo="ghcr.io/whylabs" chart_name="langkit" -chart_version="0.10.0" +chart_version="0.17.0" chart="${chart_name}-${chart_version}.tgz" # Release and namespace values mirror other variables for simplicity. diff --git a/charts/langkit/.helmignore b/charts/langkit/.helmignore index 0e8a0eb..c247b41 100644 --- a/charts/langkit/.helmignore +++ b/charts/langkit/.helmignore @@ -21,3 +21,5 @@ .idea/ *.tmproj .vscode/ +# Documentation +docs/ diff --git a/charts/langkit/CHANGELOG.md b/charts/langkit/CHANGELOG.md index bf6058d..2ff44dd 100644 --- a/charts/langkit/CHANGELOG.md +++ b/charts/langkit/CHANGELOG.md @@ -6,13 +6,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning] (https://semver.org/spec/v2.0.0.html). +## [0.17.0] - 2024-04-10 + +### Changed + +- Updated image from `1.0.13` to `1.0.14` + ## [0.16.0] - 2024-03-28 ### Changed - Updated image from `1.0.11` to `1.0.13` - ## [0.15.0] - 2024-03-22 ### Added diff --git a/charts/langkit/Chart.yaml b/charts/langkit/Chart.yaml index d19cf3c..139e070 100644 --- a/charts/langkit/Chart.yaml +++ b/charts/langkit/Chart.yaml @@ -2,5 +2,5 @@ apiVersion: v2 name: langkit description: A Helm chart for LangKit container deployment type: application -version: 0.16.0 -appVersion: "1.0.13" +version: 0.17.0 +appVersion: "1.0.14" diff --git a/charts/langkit/README.md b/charts/langkit/README.md index 203a994..95d2a96 100644 --- a/charts/langkit/README.md +++ b/charts/langkit/README.md @@ -6,6 +6,11 @@ > :warning: Review the [documentation on using WhyLab's Helm charts](../../README.md#how-to-use-whylabs-helm-repository) +## Quickstart + +View our [quickstart guide](docs/quickstart/README.md) that sets up a Kubernetes +cluster and deploys Langkit via this chart. + ## Prerequisites NOTE: Change the `--namespace` value if you will be deploying into a namespace other @@ -69,7 +74,7 @@ View the difference between the current state and desired state. # helm plugin install https://github.com/databus23/helm-diff helm diff upgrade \ --allow-unreleased \ - langkit langkit-0.12.0.tgz + langkit langkit-0.17.0.tgz ``` ### Install/Update @@ -77,14 +82,14 @@ helm diff upgrade \ helm upgrade --install \ --create-namespace \ --namespace langkit \ - langkit langkit-0.12.0.tgz + langkit langkit-0.17.0.tgz ``` ### Uninstall ```shell helm uninstall \ --namespace langkit \ - langkit langkit-0.12.0.tgz + langkit langkit-0.17.0.tgz ``` ## Development @@ -109,7 +114,7 @@ helm-docs --dry-run | image.containerPort | int | `8000` | | | image.pullPolicy | string | `"Always"` | | | image.repository | string | `"registry.gitlab.com/whylabs/langkit-container"` | | -| image.tag | string | `"1.0.13"` | | +| image.tag | string | `"1.0.14"` | | | imagePullSecrets[0].name | string | `"langkit-gitlab-registry-secret"` | | | ingress.annotations | object | `{}` | | | ingress.className | string | `""` | | diff --git a/charts/langkit/docs/README.md b/charts/langkit/docs/README.md new file mode 100644 index 0000000..814c969 --- /dev/null +++ b/charts/langkit/docs/README.md @@ -0,0 +1,3 @@ +# Langkit Helm Chart Documentation + +[Quickstart Guide](./quickstart/) diff --git a/charts/langkit/docs/quickstart/README.md b/charts/langkit/docs/quickstart/README.md new file mode 100644 index 0000000..4582af0 --- /dev/null +++ b/charts/langkit/docs/quickstart/README.md @@ -0,0 +1,146 @@ +# Quickstart + +This guide describes how to set up an EKS cluster for deploying Langkit. The +process involves three separate scripts for better organization and +maintainability. + +> :warning: This is not intended to be used in a production environment. + +## Prerequisites + +- An AWS account with appropriate permissions for creating resources. +- Git installed on your local machine. +- WhyLabs and Langkit credentials. + +## Clone This Repository + +Clone this repository. The following tutorial will be working with the shell +script files within the directory of this `README`. + +```shell +git clone https://github.com/whylabs/charts.git +``` + +## Environment Setup + +- [Recommended] [AWS CloudShell](https://aws.amazon.com/cloudshell/) +- Local terminal + +If you're a seasoned pro with AWS and the AWS CLI you can skip ahead to +[using the local terminal](#using-local-terminal). + +If you don't already have AWS credentials configured locally, the fastest way to +deploy the Langkit demo cluster is using +[AWS CloudShell](https://aws.amazon.com/cloudshell/), which is a browser-based +shell that already has your credentials configured. + +### Using Remote Terminal via [AWS CloudShell](https://aws.amazon.com/cloudshell/) + +1. **Login to your AWS Account** + + Be sure to login with a role that has sufficient permissions to create + Networking, EC2, EKS, and IAM resources. + +1. **Verify that you're in the desired region** + + The region can be selected at the top right corner of the AWS console + adjacent to your username/email address. + +1. **Search for and select/open the `CloudShell` service** + +1. **[Upload the provisioning scripts to the `CloudShell` environment](https://docs.aws.amazon.com/cloudshell/latest/userguide/getting-started.html#folder-upload)** + + 1. Click the `Actions` drop down menu and choose `Upload File` + 1. Select and upload the `prepare.sh`, `deploy-kubernetes.sh`, and + `deploy-langkit.sh` files (one at a time). + +### Using Local Terminal + +Ensure the AWS enviornment is configured correctly. See the official +[getting started with the AWS CLI documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html) + +### Setting Variables + +Set the following variables in your shell environment (local or CloudShell). +Variables with default values may be overridden as desired. Variables without +values **must** be configured. + +```shell +# AWS and EKS configuration +cluster_name="whylabs" +aws_region="us-west-2" +namespace="default" + +# Langkit configuration +chart_version="0.17.0" +whylabs_api_key="" +langkit_password="" +registry_username="" +registry_token="" +``` + +## Execute Provisioning Scripts + +1. **Ensure scripts have execution permissions set** + + ```shell + chmod 755 prepare.sh deploy-kubernetes.sh deploy-langkit.sh + ``` + +1. **Install dependencies** + + Navigate to the cloned directory and run the following command to install + `eksctl` and `helm` for managing EKS clusters and Helm charts: + + ```shell + ./prepare.sh + ``` + +1. **Create EKS Cluster** + + This script creates an EKS cluster. By default, it creates a cluster named + `whylabs` in the `us-west-2` region. Change the values to suit your needs. + + > :warning: This process takes ~20 minutes + + ```shell + ./deploy-kubernetes.sh \ + --cluster-name "${cluster_name}" \ + --aws-region "${aws_region}" + ``` + +1. **Deploy Langkit** + + ```shell + ./deploy-langkit.sh \ + --chart-version "${chart_version}" \ + --whylabs-api_key "${whylabs_api_key}" \ + --langkit-password "${langkit_password}" \ + --registry-username "${registry_username}" \ + --registry-token "${registry_token}" + ``` + +1. **Retrieve Langkit URL** + + > :warning: A Network Load Balancer is created by the Langkit service. You + > can reach the service at the DNS address of the load balancer. It may take + > a few moments for the load balancer to be provisioned. The following + > command will return the hostname once it's available. + + ```shell + hostname=$(kubectl get service langkit \ + --namespace "${namespace}" \ + -o json | \ + jq -r '.status.loadBalancer.ingress[0].hostname') + + printf "\nLangkit Hostname: http://${hostname}\n\n" + ``` + +1. **Verify Deployment** + + You can confirm that the deployment was successful by executing the + following command. You should see `HTTP/1.1 200 OK` within the response. + + ```shell + curl -v "http://${hostname}/health" + ``` diff --git a/charts/langkit/docs/quickstart/deploy-kubernetes.sh b/charts/langkit/docs/quickstart/deploy-kubernetes.sh new file mode 100755 index 0000000..e86ef8d --- /dev/null +++ b/charts/langkit/docs/quickstart/deploy-kubernetes.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash + +# Setting common bash options +set -o errexit # Exit on error +set -o nounset # Treat unset variables as an error +set -o pipefail # Consider errors in a pipeline + +# Default values for configuration variables +cluster_name="whylabs" +aws_region="us-west-2" + +# Function to print usage +usage() { + echo "Usage: $0 [--cluster-name ] [--aws-region ]" + exit 1 +} + +# Parse command line arguments +while [[ "$#" -gt 0 ]]; do + case $1 in + --cluster-name) cluster_name="$2"; shift ;; + --aws-region) aws_region="$2"; shift ;; + *) echo "Unknown parameter passed: $1"; exit 1 ;; + esac + shift +done + +export AWS_REGION="${aws_region}" + +# Create a configuration file for eksctl +cat < cluster.yaml +apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig + +metadata: + name: "${cluster_name}" + region: "${aws_region}" + +iam: + withOIDC: true + +addons: + - name: vpc-cni + version: latest + attachPolicyARNs: + - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy + - name: coredns + version: latest + - name: kube-proxy + version: latest + +managedNodeGroups: + - name: default + amiFamily: Bottlerocket + spot: true + instanceTypes: ["c7i.2xlarge", "c6i.2xlarge", "c5.2xlarge"] + desiredCapacity: 1 + minSize: 1 + maxSize: 4 +EOF + +# Check if the configuration file exists +if [ ! -f cluster.yaml ]; then + echo "Configuration file not found; exiting" + exit 1 +fi + +# Create the cluster from the configuration file +eksctl create cluster -f cluster.yaml + +# Configure and install the AWS Load Balancer Controller +curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.7.1/docs/install/iam_policy.json + +policyName="AWSLoadBalancerControllerIAMPolicy" +existingPolicyArn=$(aws iam list-policies --query 'Policies[?PolicyName==`'"${policyName}"'`].Arn' --output text) + +if [ -z "$existingPolicyArn" ]; then + echo "Policy does not exist. Creating new IAM policy: $policyName" + albPolicyArn=$(aws iam create-policy \ + --policy-name "${policyName}" \ + --policy-document file://iam_policy.json | jq -r '.Policy.Arn') +else + echo "Policy already exists. Using existing IAM policy ARN: $existingPolicyArn" + albPolicyArn=$existingPolicyArn +fi + +# Create the IAM service account with the policy +eksctl create iamserviceaccount \ + --cluster="${cluster_name}" \ + --namespace=kube-system \ + --name=aws-load-balancer-controller \ + --role-name AmazonEKSLoadBalancerControllerRole \ + --attach-policy-arn="${albPolicyArn}" \ + --approve + +helm repo add eks https://aws.github.io/eks-charts +helm repo update eks +helm install aws-load-balancer-controller eks/aws-load-balancer-controller \ + --namespace kube-system \ + --set clusterName="${cluster_name}" \ + --set serviceAccount.create=false \ + --set serviceAccount.name=aws-load-balancer-controller diff --git a/charts/langkit/docs/quickstart/deploy-langkit.sh b/charts/langkit/docs/quickstart/deploy-langkit.sh new file mode 100755 index 0000000..2bf01e7 --- /dev/null +++ b/charts/langkit/docs/quickstart/deploy-langkit.sh @@ -0,0 +1,142 @@ +#!/usr/bin/env bash + +# Setting common bash options +set -o errexit # Exit on error +set -o nounset # Treat unset variables as an error +set -o pipefail # Consider errors in a pipeline + +# Default values for configuration variables +whylabs_api_key="" +langkit_password="" +registry_username="" +registry_email="" +registry_token="" +chart_version="" +namespace="default" + +# Function to print usage +usage() { + echo "Usage: $0 [--whylabs-api-key ] [--langkit-password ] [--registry-username ]" + echo " [--chart-version ] [--registry-token ]" + exit 1 +} + +# Parse command line arguments +while [[ "$#" -gt 0 ]]; do + case $1 in + --whylabs-api-key) whylabs_api_key="$2"; shift ;; + --langkit-password) langkit_password="$2"; shift ;; + --registry-username) registry_username="$2"; shift ;; + --registry-email) registry_email="$2"; shift ;; + --registry-token) registry_token="$2"; shift ;; + --chart-version) chart_version="$2"; shift ;; + *) echo "Unknown parameter passed: $1"; exit 1 ;; + esac + shift +done + +# Check mandatory parameters +if [ -z "$whylabs_api_key" ] || [ -z "$langkit_password" ] || [ -z "$registry_username" ] || [ -z "$registry_token" ] || [ -z "$chart_version" ]; then + echo "Error: Missing required parameters." + usage +fi + +# Set the current Kubernetes context namespace +kubectl config set-context --current --namespace="${namespace}" + +if ! kubectl get secret whylabs-api-key &> /dev/null; then + kubectl create secret generic whylabs-api-key \ + --from-literal=WHYLABS_API_KEY="${whylabs_api_key}" + echo "whylabs-api-key secret created." +else + echo "whylabs-api-key secret already exists; skipping creation." +fi + +# Verify the secret was created successfully +if [ $? -ne 0 ]; then + echo "whylabs-api-key secret creation failed; exiting" + exit 1 +fi + +if ! kubectl get secret langkit-api-secret &> /dev/null; then + kubectl create secret generic langkit-api-secret \ + --from-literal=CONTAINER_PASSWORD="${langkit_password}" + echo "langkit-api-secret created." +else + echo "langkit-api-secret already exists; skipping creation." +fi + +# Verify the secret was created successfully +if [ $? -ne 0 ]; then + echo "langkit-api-secret secret creation failed; exiting" + exit 1 +fi + +# Use --registry-email if provided, otherwise default to @noreply.gitlab.com +if [ -z "$registry_email" ]; then + registry_email="${registry_username}@noreply.gitlab.com" +fi + +if ! kubectl get secret langkit-gitlab-registry-secret &> /dev/null; then + kubectl create secret docker-registry langkit-gitlab-registry-secret \ + --docker-server="registry.gitlab.com" \ + --docker-username="${registry_username}" \ + --docker-password="${registry_token}" \ + --docker-email="${registry_email}" + echo "langkit-gitlab-registry-secret created." +else + echo "langkit-gitlab-registry-secret already exists; skipping creation." +fi + +# Verify the secret was created successfully +if [ $? -ne 0 ]; then + echo "langkit-gitlab-registry-secret secret creation failed; exiting" + exit 1 +fi + +# Download the langkit Helm chart +helm pull \ + oci://ghcr.io/whylabs/langkit \ + --version "${chart_version}" + +# Check if helm pull was successful +if [ $? -ne 0 ]; then + echo "Helm chart download failed; exiting" + exit 1 +fi + +# Verify the Helm chart file exists at the expected path +if [ ! -f "langkit-${chart_version}.tgz" ]; then + echo "Helm chart not found; exiting" + exit 1 +fi + +# Install the langkit Helm chart +helm upgrade --install \ + --set "service.type=LoadBalancer" \ + --set "service.annotations.service\.beta\.kubernetes\.io/aws-load-balancer-type=external" \ + --set "service.annotations.service\.beta\.kubernetes\.io/aws-load-balancer-type=nlb" \ + --set "service.annotations.service\.beta\.kubernetes\.io/aws-load-balancer-scheme=internet-facing" \ + langkit "langkit-${chart_version}.tgz" + +# Check if Helm chart installation was successful +if [ $? -ne 0 ]; then + echo "Helm chart installation failed; exiting" + exit 1 +fi + +for (( i=1; i<=15; i++ )); do + echo "Attempt $i of 15: Checking for load balancer hostname..." + HOSTNAME=$(kubectl get svc langkit -o json | jq -r '.status.loadBalancer.ingress[0].hostname') + + if [ -n "$HOSTNAME" ]; then + echo "Langkit deployed successfully. Access the service at: http://${hostname}" + exit 0 + else + echo "Load balancer hostname not available yet. Retrying in 10 seconds..." + sleep 10 + fi +done + +echo "Max attempts reached. Load balancer hostname not found." +exit 1 diff --git a/charts/langkit/docs/quickstart/prepare.sh b/charts/langkit/docs/quickstart/prepare.sh new file mode 100755 index 0000000..9e1772d --- /dev/null +++ b/charts/langkit/docs/quickstart/prepare.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +# Setting common bash options +set -o errexit # Exit on error +set -o nounset # Treat unset variables as an error +set -o pipefail # Consider errors in a pipeline + +# Determine the architecture +ARCH=$(uname -m) +case $ARCH in + x86_64) + ARCH=amd64 + ;; + aarch64 | arm64) + ARCH=arm64 + ;; + *) + echo "Unsupported architecture: $ARCH" + exit 1 + ;; +esac +PLATFORM=$(uname -s)_$ARCH + +# Install eksctl +curl -sLO "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_${PLATFORM}.tar.gz" +tar -xzf eksctl_${PLATFORM}.tar.gz -C /tmp && rm eksctl_${PLATFORM}.tar.gz +sudo mv /tmp/eksctl /usr/local/bin + +# Validate eksctl installation +if ! command -v eksctl &> /dev/null; then + echo "eksctl could not be installed" + exit 1 +fi + +# Install helm +curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 +chmod 700 get_helm.sh +./get_helm.sh + +# Validate Helm installation +if ! command -v helm &> /dev/null; then + echo "Helm could not be installed" + exit 1 +fi + +echo "eksctl and helm installation complete" diff --git a/charts/langkit/values.yaml b/charts/langkit/values.yaml index f85e8ce..5c39d45 100644 --- a/charts/langkit/values.yaml +++ b/charts/langkit/values.yaml @@ -31,7 +31,7 @@ ingress: image: repository: registry.gitlab.com/whylabs/langkit-container pullPolicy: Always - tag: "1.0.13" + tag: "1.0.14" containerPort: 8000 imagePullSecrets: