Skip to content

Install K3s on Oracle Cloud - Step by Step Guide

flowchart LR
    subgraph Step1["1. Provision"]
        TF[terraform apply]
    end

    subgraph Step2["2. Push"]
        Git[git push]
    end

    subgraph Step3["3. Wait"]
        Boot[Cloud-init<br/>Bootstrap]
    end

    subgraph Step4["4. Verify"]
        Check[kubectl get nodes]
    end

    TF --> Git --> Boot --> Check

After creating terraform.tfvars, run Terraform to provision the infrastructure:

Terminal window
cd tf-k3s
terraform init
terraform apply
sequenceDiagram
    participant You as Developer
    participant TF as Terraform
    participant OCI as OCI API
    participant Nodes as Compute Instances

    You->>TF: terraform apply
    TF->>OCI: Create VCN
    TF->>OCI: Create Subnets
    TF->>OCI: Create Security Lists
    TF->>OCI: Create Instances
    OCI->>Nodes: Launch with cloud-init
    TF->>You: Output IPs
    Note over Nodes: Bootstrapping begins...

Terraform creates the OCI networking and compute instances, then generates Kubernetes manifests in the argocd/ directory.

The generated manifests must be committed to your repository for Argo CD to sync them:

Terminal window
cd ..
git add argocd/
git commit -m "Configure cluster manifests"
git push
flowchart LR
    TF[Terraform] -->|generates| Manifests[argocd/]
    Manifests -->|git push| GH[GitHub]
    GH -->|syncs| Argo[Argo CD]
    Argo -->|deploys| Cluster[K3s Cluster]

Cloud-init scripts automatically configure each node:

gantt
    title Node Bootstrap Timeline
    dateFormat X
    axisFormat %s

    section Ingress
    Enable IP forwarding    :0, 30
    Configure iptables NAT  :30, 60
    Install K3s agent       :60, 120
    Join cluster            :120, 150

    section Server
    Install K3s server      :0, 90
    Deploy Argo CD          :90, 150
    Create secrets          :150, 180
    Sync applications       :180, 300

    section Worker
    Install K3s agent       :0, 90
    Join cluster            :90, 120
  • Ingress node enables IP forwarding and NAT
  • Server node installs K3s and Argo CD
  • Worker node joins the cluster

Allow approximately five minutes for all nodes to initialize and Argo CD to begin syncing.

Terminal window
terraform output
ssh -J ubuntu@<ingress-public-ip> ubuntu@10.0.2.10 "sudo kubectl get nodes"

Expected output:

NAME STATUS ROLES AGE VERSION
ingress Ready <none> 5m v1.34.3+k3s1
server Ready control-plane 5m v1.34.3+k3s1
worker-1 Ready <none> 5m v1.34.3+k3s1
Terminal window
ssh -J ubuntu@<ingress-public-ip> ubuntu@10.0.2.10 "sudo kubectl get applications -n argocd"

Expected output:

NAME SYNC STATUS HEALTH STATUS
argocd-ingress Synced Healthy
argocd-self-managed Synced Healthy
cert-manager Synced Healthy
docs-app Synced Healthy
envoy-gateway Synced Healthy
external-dns Synced Healthy
external-secrets Synced Healthy
gateway-api-crds Synced Healthy
managed-secrets Synced Healthy
root-app Synced Healthy
Terminal window
ssh -J ubuntu@<ingress-public-ip> ubuntu@10.0.2.10 "sudo kubectl get pods -A"

All pods should be Running except for completed Job pods.

After a few minutes, test the deployed application:

Terminal window
dig +short k3s.yourdomain.com
curl -I https://k3s.yourdomain.com

If ArgoCD applications remain in Unknown status after initial deploy:

Check if kustomize.buildOptions is set:

Terminal window
kubectl -n argocd get cm argocd-cm -o jsonpath='{.data.kustomize\.buildOptions}'

If empty, patch it and restart the repo server:

Terminal window
kubectl -n argocd patch cm argocd-cm --type=merge -p '{"data":{"kustomize.buildOptions":"--enable-helm"}}'
kubectl -n argocd rollout restart deploy argocd-repo-server

Sync applications in dependency order:

Terminal window
for app in gateway-api-crds external-dns cert-manager external-secrets envoy-gateway managed-secrets argocd-self-managed argocd-ingress docs-app; do
kubectl -n argocd patch application $app --type=merge -p '{"operation":{"sync":{}}}'
sleep 10
done

If a node fails to join with label validation errors, SSH to the node and check:

Terminal window
sudo journalctl -u k3s-agent -n 50

If you see unknown 'kubernetes.io' labels, the cloud-init used a restricted label. Fix by reinstalling:

Terminal window
sudo /usr/local/bin/k3s-agent-uninstall.sh
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC='agent --node-label role=ingress' K3S_URL=https://10.0.2.10:6443 K3S_TOKEN='<token>' sh -

After all applications are synced, verify HTTPS works:

Terminal window
curl -I https://k3s.yourdomain.com
curl -I https://cd.k3s.yourdomain.com

Both should return HTTP/2 200. HTTP requests should redirect with 301:

Terminal window
curl -I http://k3s.yourdomain.com

See Common Issues for more solutions.