Skip to content

Getting Started#

In this guide, you will complete the following objectives:

  1. Deploy an application on the platform, complete with an HTTPS endpoint.
  2. Use Headlamp to view logs and pod details.

Deploying a Simple Application#

There are several steps to deploy an application and have it be accessible via HTTPS:

  1. Define the application.
  2. Request a TLS certificate.
  3. Define HTTP routing rules.
  4. Expose the application on the cluster network.

Defining the Application#

In your tenant repo, create a file named deployment.yaml with the following YAML. This will define a simple application named hello-world, which will use a standard nginx container. Noteable features include:

  1. Resource requests and limits ensure that your app resource requirements are met and your app resources aren't conflicting with other app resources. For more information, see right-sizing pods.
  2. Liveness probe informs that the application is healthy.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-world
spec:
  selector:
    matchLabels:
      app: hello-world
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
        - name: hello-world
          image: nginx:latest
          ports:
            - name: http
              containerPort: 80
          resources:
            requests:
              memory: 32Mi
              cpu: 50m
            limits:
              memory: 128Mi
              cpu: 500m
          livenessProbe:
            httpGet:
              path: /
              port: 80

After committing this file, the manifest will be applied and a pod will spin up. You should see your Workloads -> Deployments and its pod in Headlamp.

Important: Headlamp Access Requirement

If you log into Headlamp and cannot see your resources or namespace, it is highly likely that your Enterprise Directory (ED) Group is missing a critical configuration. To ensure your group is included in your authentication token (JWT), you must add mw-gateway as a Service Viewer to your ED Group. If this step is skipped, you will be unable to view your tenant resources.

Requesting a TLS Certificate#

Now that we have a containerized application, let's start the process to expose it by requesting a TLS certificate. For a domain name, all tenants are authorized to use *.<tenant-id>.tenants.prod.aws.itcp.cloud.vt.edu. For this guide, we'll simply use the root of your tenant domain, but you may create a subdomain if you'd like.

In your tenant repo, create a file named certificate.yaml with the following YAML. Be sure to replace my-tenant-name in both commonName and dnsNames with your tenant identifier. This will request a TLS certificate for the specified names and store the private key and certificate in the Kubernetes secret named hello-world-tls-cert.

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: hello-world
spec:
  commonName: my-tenant-name.tenants.prod.aws.itcp.cloud.vt.edu
  dnsNames:
    - my-tenant-name.tenants.prod.aws.itcp.cloud.vt.edu
  secretName: hello-world-tls-cert
  issuerRef:
    kind: ClusterIssuer
    name: letsencrypt
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: hello-world
spec:
  commonName: my-tenant-name.tenants.pprd.aws.itcp.cloud.vt.edu
  dnsNames:
    - my-tenant-name.tenants.pprd.aws.itcp.cloud.vt.edu
  secretName: hello-world-tls-cert
  issuerRef:
    kind: ClusterIssuer
    name: letsencrypt

After defining the manifest, should now see your certificate-manage -> Certificate listed in Headlamp. Since we are using LetsEncrypt to issue certificates, you may also notice a temporary pod and domain/ingress defined in your namespace to complete the HTTP challenge. Once the challenge is completed and the certificate is issued, you'll see it all disappear and you'll be left with a Certificate in the Ready state.

Defining the HTTP Routing Config#

Now that we have a certificate defined, let's define our HTTP routing configuration. To keep it simple, we're going to send all requests for our domain to our application. The cluster routing components don't search for pods directly, but use a Service to discover the application.

Create a file named ingress.yaml with the following YAML. This will define a routing rule that will send all requests to our tenant domain to a Service named hello-world, which we'll define in the next step. Be sure to replace my-tenant-name in both the host and tls.hosts fields with your tenant identifier. This also provides config to routing components to use the TLS key/cert stored in hello-world-tls-cert.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-world
spec:
  rules:
    - host: my-tenant-name.tenants.prod.aws.itcp.cloud.vt.edu
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: hello-world
              port: 
                number: 80
  tls:
  - hosts:
      - my-tenant-name.tenants.prod.aws.itcp.cloud.vt.edu
    secretName: hello-world-tls-cert  
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-world
spec:
  rules:
    - host: my-tenant-name.tenants.pprd.aws.itcp.cloud.vt.edu
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: hello-world
              port: 
                number: 80
  tls:
  - hosts:
      - my-tenant-name.tenants.pprd.aws.itcp.cloud.vt.edu
    secretName: hello-world-tls-cert  

Once this is defined, you should now see your Network -> Ingress listed in Headlamp.

Exposing the Application on the Cluster Network#

Now, all we need to do is define a Service, which exposes the container on the cluster network. This will finally allow the pod to be discovered by the HTTP routing components.

In a file named service.yaml, place the following YAML to define the Service. This will expose all pods that have a label with key app and value hello-world.

apiVersion: v1
kind: Service
metadata:
  name: hello-world
spec:
  selector:
    app: hello-world
  ports:
    - port: 80

Once the manifest is applied, you should see your Network -> Service listed in Headlamp. You will now see a "Welcome to nginx!" page at your tenant URL. Congrats! 🎉

Using Headlamp#

Although we've used Headlamp a few times already, there are a few other neat capabilities that you might find useful.

Viewing Pod Details and Logs#

If you click on the link for a specific pod, you will see quite a few details about the pod, including environment variables, volume information, and resource utilization.

Using kubectl#

While Headlamp provides a lot of insights, it doesn't expose everything. Kubectl is a Kubernetes command-line tool that can be configured to query resources, read logs, and more.

  1. If you don't already have kubectl, follow these instructions to install kubectl.

  2. After logging into Headlamp, click on Get Token in the sidebar. Follow the one-time setup instructions.

  3. Try to query the running pods and see if our hello world app is up and running:

    kubectl get pods -n <my-tenant-name>
    

Third-Party Integration and Support

The config is stored in ~/.kube/config and is typically referred to as a "kubeconfig" file. Many other third-party tools can use this file to visualize and inspect resources you have permissions to see. You are welcome to explore them, but be mindful of procurement practices and who might have access to your config, as your credential is stored there.

Next Steps#

Now that you have a simple app up and running, it's time to replace it with your own app! To remove this sample app, simply remove the manifests.

For more advanced CI/CD needs, consider setting up a pipeline to validate your manifests before deployment. We provide a default pipeline that's perfect for simple tasks and basic Kubernetes manifest validation.