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.