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"] --> LB["Hetzner Load Balancer"] --> S["Service<br/>hello"] --> P["Pods<br/>your app replicas"]
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:
- Run a production-ready workload. 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. Run a production-ready workload 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. Next steps covers the security checklist to work through 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 Argo CD .
Next step#
You have a running app and a working deploy loop. Continue with Next steps to see where to go from here: understanding the platform, upgrades, security, and running real services.
Related#
Explore your cluster
Run essential kubectl commands to inspect your Syself Autopilot cluster. Learn what healthy nodes, system pods, and events look like on a fresh cluster.
Next steps
Where to go after deploying your first app on Syself Autopilot: understand the platform, plan for upgrades, work through the security checklist, and run real services.