Deploy your first app
With a healthy cluster confirmed, deploy a sample application to it and open it in your browser through a Hetzner Load Balancer. Most of the wait is the load balancer coming up.
Prerequisites
- A healthy workload cluster with
KUBECONFIGstill pointed at it. Complete Explore your cluster to confirm it is ready.
Deploy the application
You create two Kubernetes objects. A Deployment keeps a set of identical pods running and replaces any that fail. A Service gives those pods one stable address; with type: LoadBalancer, that address is a public IP on a Hetzner Load Balancer.
Create a file named app.yaml:
# app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello
spec:
replicas: 2
selector:
matchLabels:
app: hello
template:
metadata:
labels:
app: hello
spec:
containers:
- name: hello
image: nginx:stable-alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: hello
spec:
type: LoadBalancer
selector:
app: hello
ports:
- port: 80
targetPort: 80
Apply it:
$ kubectl apply -f app.yaml
deployment.apps/hello created
service/hello created
Both pods start within a few seconds. Confirm they are running:
$ kubectl get pods -l app=hello
NAME READY STATUS RESTARTS AGE
hello-6d4b9c8f7d-8kx2p 1/1 Running 0 20s
hello-6d4b9c8f7d-v5qtm 1/1 Running 0 20s
Both pods show 1/1 Running. The random suffixes in your pod names differ.
Watch the load balancer appear
A Service with type: LoadBalancer tells Syself Autopilot to create a Hetzner Load Balancer in the Hetzner Cloud project that holds your cluster. This takes about a minute. Once it exists, every request follows the same path:
flowchart LR I["Internet<br/>the external IP"]:::external --> LB["Hetzner Load Balancer"]:::external --> S["Service<br/>hello"]:::app --> P["Pods<br/>your app replicas"]:::app
Watch the Service until an external IP appears:
$ kubectl get service hello --watch
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello LoadBalancer 100.96.45.12 <pending> 80:31820/TCP 15s
hello LoadBalancer 100.96.45.12 167.235.10.20 80:31820/TCP 70s
When the EXTERNAL-IP column changes from <pending> to an IP address, the load balancer is ready. Press Ctrl+ C to stop watching. Your IP and ports differ from the example.
You can also see the new load balancer in the Hetzner Cloud Console under Load Balancers.
Access the application
Open http://<EXTERNAL-IP> in your browser, or test it with curl:
$ curl http://<EXTERNAL-IP>
You should see the nginx welcome page, an HTML response starting with <title>Welcome to nginx!</title>. Your app is live on the internet. Both pods serve traffic through the same load balancer, so if one fails, the other keeps answering.
Clean up
Delete the Deployment and Service when you are done:
$ kubectl delete -f app.yaml
deployment.apps "hello" deleted
service "hello" deleted
The Hetzner Load Balancer is deleted automatically when the Service is removed, so it stops billing right away.
Beyond a single load balancer
This example uses a plain LoadBalancer Service, one load balancer per application. For production workloads you typically want:
- An ingress controller. This is a component that routes requests for several applications through one load balancer, based on the hostname or URL path. Syself Autopilot does not include a built-in ingress controller; choose one that fits your needs.
- TLS termination at the ingress level.
See Expose an application for a complete guide covering ingress and TLS options.
Get the most out of Syself
You now have a running cluster and a working deploy loop. That is the demo. The platform's depth shows up in what comes next:
- Survive node drains. Syself Autopilot drains and replaces nodes during upgrades and self-healing. A bare Deployment like the one above takes a traffic hit on every such event. Survive node drains adds the probes, disruption budgets, and resource requests that keep an app serving through all of it.
- Harden your workloads. The node this app ran on is hardened by default. The pod you deployed is not. Work through the security checklist and enforce Pod Security Standards before production.
- Set up observability. Every component in the cluster exports Prometheus metrics, but nothing collects them yet. Set up Prometheus and Grafana turns them into dashboards and alerts.
- Bring in your team. So far you have used a single kubeconfig file. Configure OIDC connects your identity provider so teammates log in with short-lived tokens instead of shared credentials.
Tip
GitOps is a natural next step. You can keep every manifest in a Git repository and use Argo CD or Flux to apply changes automatically. See GitOps with Syself Autopilot .
Next step
You have a running app and a working deploy loop. Before you put real traffic on it, go through the Production readiness checklist .
Just evaluating? The cluster keeps billing until you remove it. When you are done, delete the cluster to stop the meter.
Related
Overview
A map of what you can run on Syself Autopilot and where each task lives, framed by the one rule that shapes it all: node replacement is routine, so no pod stays put.
Production readiness checklist
What to check before a workload or component runs in production, from replicas and pod security to backups and GitOps, with a link to the page that covers each practice in depth.